main.bundle.js 1.9 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284
  1. /******/ (function(modules) { // webpackBootstrap
  2. /******/ // The module cache
  3. /******/ var installedModules = {};
  4. /******/
  5. /******/ // The require function
  6. /******/ function __webpack_require__(moduleId) {
  7. /******/
  8. /******/ // Check if module is in cache
  9. /******/ if(installedModules[moduleId]) {
  10. /******/ return installedModules[moduleId].exports;
  11. /******/ }
  12. /******/ // Create a new module (and put it into the cache)
  13. /******/ var module = installedModules[moduleId] = {
  14. /******/ i: moduleId,
  15. /******/ l: false,
  16. /******/ exports: {}
  17. /******/ };
  18. /******/
  19. /******/ // Execute the module function
  20. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  21. /******/
  22. /******/ // Flag the module as loaded
  23. /******/ module.l = true;
  24. /******/
  25. /******/ // Return the exports of the module
  26. /******/ return module.exports;
  27. /******/ }
  28. /******/
  29. /******/
  30. /******/ // expose the modules object (__webpack_modules__)
  31. /******/ __webpack_require__.m = modules;
  32. /******/
  33. /******/ // expose the module cache
  34. /******/ __webpack_require__.c = installedModules;
  35. /******/
  36. /******/ // define getter function for harmony exports
  37. /******/ __webpack_require__.d = function(exports, name, getter) {
  38. /******/ if(!__webpack_require__.o(exports, name)) {
  39. /******/ Object.defineProperty(exports, name, {
  40. /******/ configurable: false,
  41. /******/ enumerable: true,
  42. /******/ get: getter
  43. /******/ });
  44. /******/ }
  45. /******/ };
  46. /******/
  47. /******/ // getDefaultExport function for compatibility with non-harmony modules
  48. /******/ __webpack_require__.n = function(module) {
  49. /******/ var getter = module && module.__esModule ?
  50. /******/ function getDefault() { return module['default']; } :
  51. /******/ function getModuleExports() { return module; };
  52. /******/ __webpack_require__.d(getter, 'a', getter);
  53. /******/ return getter;
  54. /******/ };
  55. /******/
  56. /******/ // Object.prototype.hasOwnProperty.call
  57. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  58. /******/
  59. /******/ // __webpack_public_path__
  60. /******/ __webpack_require__.p = "";
  61. /******/
  62. /******/ // Load entry module and return exports
  63. /******/ return __webpack_require__(__webpack_require__.s = 1);
  64. /******/ })
  65. /************************************************************************/
  66. /******/ ([
  67. /* 0 */
  68. /***/ (function(module, exports, __webpack_require__) {
  69. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  70. * jQuery JavaScript Library v3.2.1
  71. * https://jquery.com/
  72. *
  73. * Includes Sizzle.js
  74. * https://sizzlejs.com/
  75. *
  76. * Copyright JS Foundation and other contributors
  77. * Released under the MIT license
  78. * https://jquery.org/license
  79. *
  80. * Date: 2017-03-20T18:59Z
  81. */
  82. ( function( global, factory ) {
  83. "use strict";
  84. if ( typeof module === "object" && typeof module.exports === "object" ) {
  85. // For CommonJS and CommonJS-like environments where a proper `window`
  86. // is present, execute the factory and get jQuery.
  87. // For environments that do not have a `window` with a `document`
  88. // (such as Node.js), expose a factory as module.exports.
  89. // This accentuates the need for the creation of a real `window`.
  90. // e.g. var jQuery = require("jquery")(window);
  91. // See ticket #14549 for more info.
  92. module.exports = global.document ?
  93. factory( global, true ) :
  94. function( w ) {
  95. if ( !w.document ) {
  96. throw new Error( "jQuery requires a window with a document" );
  97. }
  98. return factory( w );
  99. };
  100. } else {
  101. factory( global );
  102. }
  103. // Pass this if window is not defined yet
  104. } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
  105. // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
  106. // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
  107. // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
  108. // enough that all such attempts are guarded in a try block.
  109. "use strict";
  110. var arr = [];
  111. var document = window.document;
  112. var getProto = Object.getPrototypeOf;
  113. var slice = arr.slice;
  114. var concat = arr.concat;
  115. var push = arr.push;
  116. var indexOf = arr.indexOf;
  117. var class2type = {};
  118. var toString = class2type.toString;
  119. var hasOwn = class2type.hasOwnProperty;
  120. var fnToString = hasOwn.toString;
  121. var ObjectFunctionString = fnToString.call( Object );
  122. var support = {};
  123. function DOMEval( code, doc ) {
  124. doc = doc || document;
  125. var script = doc.createElement( "script" );
  126. script.text = code;
  127. doc.head.appendChild( script ).parentNode.removeChild( script );
  128. }
  129. /* global Symbol */
  130. // Defining this global in .eslintrc.json would create a danger of using the global
  131. // unguarded in another place, it seems safer to define global only for this module
  132. var
  133. version = "3.2.1",
  134. // Define a local copy of jQuery
  135. jQuery = function( selector, context ) {
  136. // The jQuery object is actually just the init constructor 'enhanced'
  137. // Need init if jQuery is called (just allow error to be thrown if not included)
  138. return new jQuery.fn.init( selector, context );
  139. },
  140. // Support: Android <=4.0 only
  141. // Make sure we trim BOM and NBSP
  142. rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
  143. // Matches dashed string for camelizing
  144. rmsPrefix = /^-ms-/,
  145. rdashAlpha = /-([a-z])/g,
  146. // Used by jQuery.camelCase as callback to replace()
  147. fcamelCase = function( all, letter ) {
  148. return letter.toUpperCase();
  149. };
  150. jQuery.fn = jQuery.prototype = {
  151. // The current version of jQuery being used
  152. jquery: version,
  153. constructor: jQuery,
  154. // The default length of a jQuery object is 0
  155. length: 0,
  156. toArray: function() {
  157. return slice.call( this );
  158. },
  159. // Get the Nth element in the matched element set OR
  160. // Get the whole matched element set as a clean array
  161. get: function( num ) {
  162. // Return all the elements in a clean array
  163. if ( num == null ) {
  164. return slice.call( this );
  165. }
  166. // Return just the one element from the set
  167. return num < 0 ? this[ num + this.length ] : this[ num ];
  168. },
  169. // Take an array of elements and push it onto the stack
  170. // (returning the new matched element set)
  171. pushStack: function( elems ) {
  172. // Build a new jQuery matched element set
  173. var ret = jQuery.merge( this.constructor(), elems );
  174. // Add the old object onto the stack (as a reference)
  175. ret.prevObject = this;
  176. // Return the newly-formed element set
  177. return ret;
  178. },
  179. // Execute a callback for every element in the matched set.
  180. each: function( callback ) {
  181. return jQuery.each( this, callback );
  182. },
  183. map: function( callback ) {
  184. return this.pushStack( jQuery.map( this, function( elem, i ) {
  185. return callback.call( elem, i, elem );
  186. } ) );
  187. },
  188. slice: function() {
  189. return this.pushStack( slice.apply( this, arguments ) );
  190. },
  191. first: function() {
  192. return this.eq( 0 );
  193. },
  194. last: function() {
  195. return this.eq( -1 );
  196. },
  197. eq: function( i ) {
  198. var len = this.length,
  199. j = +i + ( i < 0 ? len : 0 );
  200. return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
  201. },
  202. end: function() {
  203. return this.prevObject || this.constructor();
  204. },
  205. // For internal use only.
  206. // Behaves like an Array's method, not like a jQuery method.
  207. push: push,
  208. sort: arr.sort,
  209. splice: arr.splice
  210. };
  211. jQuery.extend = jQuery.fn.extend = function() {
  212. var options, name, src, copy, copyIsArray, clone,
  213. target = arguments[ 0 ] || {},
  214. i = 1,
  215. length = arguments.length,
  216. deep = false;
  217. // Handle a deep copy situation
  218. if ( typeof target === "boolean" ) {
  219. deep = target;
  220. // Skip the boolean and the target
  221. target = arguments[ i ] || {};
  222. i++;
  223. }
  224. // Handle case when target is a string or something (possible in deep copy)
  225. if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
  226. target = {};
  227. }
  228. // Extend jQuery itself if only one argument is passed
  229. if ( i === length ) {
  230. target = this;
  231. i--;
  232. }
  233. for ( ; i < length; i++ ) {
  234. // Only deal with non-null/undefined values
  235. if ( ( options = arguments[ i ] ) != null ) {
  236. // Extend the base object
  237. for ( name in options ) {
  238. src = target[ name ];
  239. copy = options[ name ];
  240. // Prevent never-ending loop
  241. if ( target === copy ) {
  242. continue;
  243. }
  244. // Recurse if we're merging plain objects or arrays
  245. if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
  246. ( copyIsArray = Array.isArray( copy ) ) ) ) {
  247. if ( copyIsArray ) {
  248. copyIsArray = false;
  249. clone = src && Array.isArray( src ) ? src : [];
  250. } else {
  251. clone = src && jQuery.isPlainObject( src ) ? src : {};
  252. }
  253. // Never move original objects, clone them
  254. target[ name ] = jQuery.extend( deep, clone, copy );
  255. // Don't bring in undefined values
  256. } else if ( copy !== undefined ) {
  257. target[ name ] = copy;
  258. }
  259. }
  260. }
  261. }
  262. // Return the modified object
  263. return target;
  264. };
  265. jQuery.extend( {
  266. // Unique for each copy of jQuery on the page
  267. expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
  268. // Assume jQuery is ready without the ready module
  269. isReady: true,
  270. error: function( msg ) {
  271. throw new Error( msg );
  272. },
  273. noop: function() {},
  274. isFunction: function( obj ) {
  275. return jQuery.type( obj ) === "function";
  276. },
  277. isWindow: function( obj ) {
  278. return obj != null && obj === obj.window;
  279. },
  280. isNumeric: function( obj ) {
  281. // As of jQuery 3.0, isNumeric is limited to
  282. // strings and numbers (primitives or objects)
  283. // that can be coerced to finite numbers (gh-2662)
  284. var type = jQuery.type( obj );
  285. return ( type === "number" || type === "string" ) &&
  286. // parseFloat NaNs numeric-cast false positives ("")
  287. // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  288. // subtraction forces infinities to NaN
  289. !isNaN( obj - parseFloat( obj ) );
  290. },
  291. isPlainObject: function( obj ) {
  292. var proto, Ctor;
  293. // Detect obvious negatives
  294. // Use toString instead of jQuery.type to catch host objects
  295. if ( !obj || toString.call( obj ) !== "[object Object]" ) {
  296. return false;
  297. }
  298. proto = getProto( obj );
  299. // Objects with no prototype (e.g., `Object.create( null )`) are plain
  300. if ( !proto ) {
  301. return true;
  302. }
  303. // Objects with prototype are plain iff they were constructed by a global Object function
  304. Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
  305. return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
  306. },
  307. isEmptyObject: function( obj ) {
  308. /* eslint-disable no-unused-vars */
  309. // See https://github.com/eslint/eslint/issues/6125
  310. var name;
  311. for ( name in obj ) {
  312. return false;
  313. }
  314. return true;
  315. },
  316. type: function( obj ) {
  317. if ( obj == null ) {
  318. return obj + "";
  319. }
  320. // Support: Android <=2.3 only (functionish RegExp)
  321. return typeof obj === "object" || typeof obj === "function" ?
  322. class2type[ toString.call( obj ) ] || "object" :
  323. typeof obj;
  324. },
  325. // Evaluates a script in a global context
  326. globalEval: function( code ) {
  327. DOMEval( code );
  328. },
  329. // Convert dashed to camelCase; used by the css and data modules
  330. // Support: IE <=9 - 11, Edge 12 - 13
  331. // Microsoft forgot to hump their vendor prefix (#9572)
  332. camelCase: function( string ) {
  333. return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
  334. },
  335. each: function( obj, callback ) {
  336. var length, i = 0;
  337. if ( isArrayLike( obj ) ) {
  338. length = obj.length;
  339. for ( ; i < length; i++ ) {
  340. if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
  341. break;
  342. }
  343. }
  344. } else {
  345. for ( i in obj ) {
  346. if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
  347. break;
  348. }
  349. }
  350. }
  351. return obj;
  352. },
  353. // Support: Android <=4.0 only
  354. trim: function( text ) {
  355. return text == null ?
  356. "" :
  357. ( text + "" ).replace( rtrim, "" );
  358. },
  359. // results is for internal usage only
  360. makeArray: function( arr, results ) {
  361. var ret = results || [];
  362. if ( arr != null ) {
  363. if ( isArrayLike( Object( arr ) ) ) {
  364. jQuery.merge( ret,
  365. typeof arr === "string" ?
  366. [ arr ] : arr
  367. );
  368. } else {
  369. push.call( ret, arr );
  370. }
  371. }
  372. return ret;
  373. },
  374. inArray: function( elem, arr, i ) {
  375. return arr == null ? -1 : indexOf.call( arr, elem, i );
  376. },
  377. // Support: Android <=4.0 only, PhantomJS 1 only
  378. // push.apply(_, arraylike) throws on ancient WebKit
  379. merge: function( first, second ) {
  380. var len = +second.length,
  381. j = 0,
  382. i = first.length;
  383. for ( ; j < len; j++ ) {
  384. first[ i++ ] = second[ j ];
  385. }
  386. first.length = i;
  387. return first;
  388. },
  389. grep: function( elems, callback, invert ) {
  390. var callbackInverse,
  391. matches = [],
  392. i = 0,
  393. length = elems.length,
  394. callbackExpect = !invert;
  395. // Go through the array, only saving the items
  396. // that pass the validator function
  397. for ( ; i < length; i++ ) {
  398. callbackInverse = !callback( elems[ i ], i );
  399. if ( callbackInverse !== callbackExpect ) {
  400. matches.push( elems[ i ] );
  401. }
  402. }
  403. return matches;
  404. },
  405. // arg is for internal usage only
  406. map: function( elems, callback, arg ) {
  407. var length, value,
  408. i = 0,
  409. ret = [];
  410. // Go through the array, translating each of the items to their new values
  411. if ( isArrayLike( elems ) ) {
  412. length = elems.length;
  413. for ( ; i < length; i++ ) {
  414. value = callback( elems[ i ], i, arg );
  415. if ( value != null ) {
  416. ret.push( value );
  417. }
  418. }
  419. // Go through every key on the object,
  420. } else {
  421. for ( i in elems ) {
  422. value = callback( elems[ i ], i, arg );
  423. if ( value != null ) {
  424. ret.push( value );
  425. }
  426. }
  427. }
  428. // Flatten any nested arrays
  429. return concat.apply( [], ret );
  430. },
  431. // A global GUID counter for objects
  432. guid: 1,
  433. // Bind a function to a context, optionally partially applying any
  434. // arguments.
  435. proxy: function( fn, context ) {
  436. var tmp, args, proxy;
  437. if ( typeof context === "string" ) {
  438. tmp = fn[ context ];
  439. context = fn;
  440. fn = tmp;
  441. }
  442. // Quick check to determine if target is callable, in the spec
  443. // this throws a TypeError, but we will just return undefined.
  444. if ( !jQuery.isFunction( fn ) ) {
  445. return undefined;
  446. }
  447. // Simulated bind
  448. args = slice.call( arguments, 2 );
  449. proxy = function() {
  450. return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
  451. };
  452. // Set the guid of unique handler to the same of original handler, so it can be removed
  453. proxy.guid = fn.guid = fn.guid || jQuery.guid++;
  454. return proxy;
  455. },
  456. now: Date.now,
  457. // jQuery.support is not used in Core but other projects attach their
  458. // properties to it so it needs to exist.
  459. support: support
  460. } );
  461. if ( typeof Symbol === "function" ) {
  462. jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
  463. }
  464. // Populate the class2type map
  465. jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
  466. function( i, name ) {
  467. class2type[ "[object " + name + "]" ] = name.toLowerCase();
  468. } );
  469. function isArrayLike( obj ) {
  470. // Support: real iOS 8.2 only (not reproducible in simulator)
  471. // `in` check used to prevent JIT error (gh-2145)
  472. // hasOwn isn't used here due to false negatives
  473. // regarding Nodelist length in IE
  474. var length = !!obj && "length" in obj && obj.length,
  475. type = jQuery.type( obj );
  476. if ( type === "function" || jQuery.isWindow( obj ) ) {
  477. return false;
  478. }
  479. return type === "array" || length === 0 ||
  480. typeof length === "number" && length > 0 && ( length - 1 ) in obj;
  481. }
  482. var Sizzle =
  483. /*!
  484. * Sizzle CSS Selector Engine v2.3.3
  485. * https://sizzlejs.com/
  486. *
  487. * Copyright jQuery Foundation and other contributors
  488. * Released under the MIT license
  489. * http://jquery.org/license
  490. *
  491. * Date: 2016-08-08
  492. */
  493. (function( window ) {
  494. var i,
  495. support,
  496. Expr,
  497. getText,
  498. isXML,
  499. tokenize,
  500. compile,
  501. select,
  502. outermostContext,
  503. sortInput,
  504. hasDuplicate,
  505. // Local document vars
  506. setDocument,
  507. document,
  508. docElem,
  509. documentIsHTML,
  510. rbuggyQSA,
  511. rbuggyMatches,
  512. matches,
  513. contains,
  514. // Instance-specific data
  515. expando = "sizzle" + 1 * new Date(),
  516. preferredDoc = window.document,
  517. dirruns = 0,
  518. done = 0,
  519. classCache = createCache(),
  520. tokenCache = createCache(),
  521. compilerCache = createCache(),
  522. sortOrder = function( a, b ) {
  523. if ( a === b ) {
  524. hasDuplicate = true;
  525. }
  526. return 0;
  527. },
  528. // Instance methods
  529. hasOwn = ({}).hasOwnProperty,
  530. arr = [],
  531. pop = arr.pop,
  532. push_native = arr.push,
  533. push = arr.push,
  534. slice = arr.slice,
  535. // Use a stripped-down indexOf as it's faster than native
  536. // https://jsperf.com/thor-indexof-vs-for/5
  537. indexOf = function( list, elem ) {
  538. var i = 0,
  539. len = list.length;
  540. for ( ; i < len; i++ ) {
  541. if ( list[i] === elem ) {
  542. return i;
  543. }
  544. }
  545. return -1;
  546. },
  547. booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  548. // Regular expressions
  549. // http://www.w3.org/TR/css3-selectors/#whitespace
  550. whitespace = "[\\x20\\t\\r\\n\\f]",
  551. // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  552. identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
  553. // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  554. attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
  555. // Operator (capture 2)
  556. "*([*^$|!~]?=)" + whitespace +
  557. // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  558. "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  559. "*\\]",
  560. pseudos = ":(" + identifier + ")(?:\\((" +
  561. // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  562. // 1. quoted (capture 3; capture 4 or capture 5)
  563. "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  564. // 2. simple (capture 6)
  565. "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  566. // 3. anything else (capture 2)
  567. ".*" +
  568. ")\\)|)",
  569. // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  570. rwhitespace = new RegExp( whitespace + "+", "g" ),
  571. rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  572. rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  573. rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  574. rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
  575. rpseudo = new RegExp( pseudos ),
  576. ridentifier = new RegExp( "^" + identifier + "$" ),
  577. matchExpr = {
  578. "ID": new RegExp( "^#(" + identifier + ")" ),
  579. "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
  580. "TAG": new RegExp( "^(" + identifier + "|[*])" ),
  581. "ATTR": new RegExp( "^" + attributes ),
  582. "PSEUDO": new RegExp( "^" + pseudos ),
  583. "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  584. "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  585. "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  586. "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  587. // For use in libraries implementing .is()
  588. // We use this for POS matching in `select`
  589. "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  590. whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  591. },
  592. rinputs = /^(?:input|select|textarea|button)$/i,
  593. rheader = /^h\d$/i,
  594. rnative = /^[^{]+\{\s*\[native \w/,
  595. // Easily-parseable/retrievable ID or TAG or CLASS selectors
  596. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  597. rsibling = /[+~]/,
  598. // CSS escapes
  599. // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  600. runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  601. funescape = function( _, escaped, escapedWhitespace ) {
  602. var high = "0x" + escaped - 0x10000;
  603. // NaN means non-codepoint
  604. // Support: Firefox<24
  605. // Workaround erroneous numeric interpretation of +"0x"
  606. return high !== high || escapedWhitespace ?
  607. escaped :
  608. high < 0 ?
  609. // BMP codepoint
  610. String.fromCharCode( high + 0x10000 ) :
  611. // Supplemental Plane codepoint (surrogate pair)
  612. String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  613. },
  614. // CSS string/identifier serialization
  615. // https://drafts.csswg.org/cssom/#common-serializing-idioms
  616. rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
  617. fcssescape = function( ch, asCodePoint ) {
  618. if ( asCodePoint ) {
  619. // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
  620. if ( ch === "\0" ) {
  621. return "\uFFFD";
  622. }
  623. // Control characters and (dependent upon position) numbers get escaped as code points
  624. return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
  625. }
  626. // Other potentially-special ASCII characters get backslash-escaped
  627. return "\\" + ch;
  628. },
  629. // Used for iframes
  630. // See setDocument()
  631. // Removing the function wrapper causes a "Permission Denied"
  632. // error in IE
  633. unloadHandler = function() {
  634. setDocument();
  635. },
  636. disabledAncestor = addCombinator(
  637. function( elem ) {
  638. return elem.disabled === true && ("form" in elem || "label" in elem);
  639. },
  640. { dir: "parentNode", next: "legend" }
  641. );
  642. // Optimize for push.apply( _, NodeList )
  643. try {
  644. push.apply(
  645. (arr = slice.call( preferredDoc.childNodes )),
  646. preferredDoc.childNodes
  647. );
  648. // Support: Android<4.0
  649. // Detect silently failing push.apply
  650. arr[ preferredDoc.childNodes.length ].nodeType;
  651. } catch ( e ) {
  652. push = { apply: arr.length ?
  653. // Leverage slice if possible
  654. function( target, els ) {
  655. push_native.apply( target, slice.call(els) );
  656. } :
  657. // Support: IE<9
  658. // Otherwise append directly
  659. function( target, els ) {
  660. var j = target.length,
  661. i = 0;
  662. // Can't trust NodeList.length
  663. while ( (target[j++] = els[i++]) ) {}
  664. target.length = j - 1;
  665. }
  666. };
  667. }
  668. function Sizzle( selector, context, results, seed ) {
  669. var m, i, elem, nid, match, groups, newSelector,
  670. newContext = context && context.ownerDocument,
  671. // nodeType defaults to 9, since context defaults to document
  672. nodeType = context ? context.nodeType : 9;
  673. results = results || [];
  674. // Return early from calls with invalid selector or context
  675. if ( typeof selector !== "string" || !selector ||
  676. nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
  677. return results;
  678. }
  679. // Try to shortcut find operations (as opposed to filters) in HTML documents
  680. if ( !seed ) {
  681. if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  682. setDocument( context );
  683. }
  684. context = context || document;
  685. if ( documentIsHTML ) {
  686. // If the selector is sufficiently simple, try using a "get*By*" DOM method
  687. // (excepting DocumentFragment context, where the methods don't exist)
  688. if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
  689. // ID selector
  690. if ( (m = match[1]) ) {
  691. // Document context
  692. if ( nodeType === 9 ) {
  693. if ( (elem = context.getElementById( m )) ) {
  694. // Support: IE, Opera, Webkit
  695. // TODO: identify versions
  696. // getElementById can match elements by name instead of ID
  697. if ( elem.id === m ) {
  698. results.push( elem );
  699. return results;
  700. }
  701. } else {
  702. return results;
  703. }
  704. // Element context
  705. } else {
  706. // Support: IE, Opera, Webkit
  707. // TODO: identify versions
  708. // getElementById can match elements by name instead of ID
  709. if ( newContext && (elem = newContext.getElementById( m )) &&
  710. contains( context, elem ) &&
  711. elem.id === m ) {
  712. results.push( elem );
  713. return results;
  714. }
  715. }
  716. // Type selector
  717. } else if ( match[2] ) {
  718. push.apply( results, context.getElementsByTagName( selector ) );
  719. return results;
  720. // Class selector
  721. } else if ( (m = match[3]) && support.getElementsByClassName &&
  722. context.getElementsByClassName ) {
  723. push.apply( results, context.getElementsByClassName( m ) );
  724. return results;
  725. }
  726. }
  727. // Take advantage of querySelectorAll
  728. if ( support.qsa &&
  729. !compilerCache[ selector + " " ] &&
  730. (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  731. if ( nodeType !== 1 ) {
  732. newContext = context;
  733. newSelector = selector;
  734. // qSA looks outside Element context, which is not what we want
  735. // Thanks to Andrew Dupont for this workaround technique
  736. // Support: IE <=8
  737. // Exclude object elements
  738. } else if ( context.nodeName.toLowerCase() !== "object" ) {
  739. // Capture the context ID, setting it first if necessary
  740. if ( (nid = context.getAttribute( "id" )) ) {
  741. nid = nid.replace( rcssescape, fcssescape );
  742. } else {
  743. context.setAttribute( "id", (nid = expando) );
  744. }
  745. // Prefix every selector in the list
  746. groups = tokenize( selector );
  747. i = groups.length;
  748. while ( i-- ) {
  749. groups[i] = "#" + nid + " " + toSelector( groups[i] );
  750. }
  751. newSelector = groups.join( "," );
  752. // Expand context for sibling selectors
  753. newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
  754. context;
  755. }
  756. if ( newSelector ) {
  757. try {
  758. push.apply( results,
  759. newContext.querySelectorAll( newSelector )
  760. );
  761. return results;
  762. } catch ( qsaError ) {
  763. } finally {
  764. if ( nid === expando ) {
  765. context.removeAttribute( "id" );
  766. }
  767. }
  768. }
  769. }
  770. }
  771. }
  772. // All others
  773. return select( selector.replace( rtrim, "$1" ), context, results, seed );
  774. }
  775. /**
  776. * Create key-value caches of limited size
  777. * @returns {function(string, object)} Returns the Object data after storing it on itself with
  778. * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  779. * deleting the oldest entry
  780. */
  781. function createCache() {
  782. var keys = [];
  783. function cache( key, value ) {
  784. // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  785. if ( keys.push( key + " " ) > Expr.cacheLength ) {
  786. // Only keep the most recent entries
  787. delete cache[ keys.shift() ];
  788. }
  789. return (cache[ key + " " ] = value);
  790. }
  791. return cache;
  792. }
  793. /**
  794. * Mark a function for special use by Sizzle
  795. * @param {Function} fn The function to mark
  796. */
  797. function markFunction( fn ) {
  798. fn[ expando ] = true;
  799. return fn;
  800. }
  801. /**
  802. * Support testing using an element
  803. * @param {Function} fn Passed the created element and returns a boolean result
  804. */
  805. function assert( fn ) {
  806. var el = document.createElement("fieldset");
  807. try {
  808. return !!fn( el );
  809. } catch (e) {
  810. return false;
  811. } finally {
  812. // Remove from its parent by default
  813. if ( el.parentNode ) {
  814. el.parentNode.removeChild( el );
  815. }
  816. // release memory in IE
  817. el = null;
  818. }
  819. }
  820. /**
  821. * Adds the same handler for all of the specified attrs
  822. * @param {String} attrs Pipe-separated list of attributes
  823. * @param {Function} handler The method that will be applied
  824. */
  825. function addHandle( attrs, handler ) {
  826. var arr = attrs.split("|"),
  827. i = arr.length;
  828. while ( i-- ) {
  829. Expr.attrHandle[ arr[i] ] = handler;
  830. }
  831. }
  832. /**
  833. * Checks document order of two siblings
  834. * @param {Element} a
  835. * @param {Element} b
  836. * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  837. */
  838. function siblingCheck( a, b ) {
  839. var cur = b && a,
  840. diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  841. a.sourceIndex - b.sourceIndex;
  842. // Use IE sourceIndex if available on both nodes
  843. if ( diff ) {
  844. return diff;
  845. }
  846. // Check if b follows a
  847. if ( cur ) {
  848. while ( (cur = cur.nextSibling) ) {
  849. if ( cur === b ) {
  850. return -1;
  851. }
  852. }
  853. }
  854. return a ? 1 : -1;
  855. }
  856. /**
  857. * Returns a function to use in pseudos for input types
  858. * @param {String} type
  859. */
  860. function createInputPseudo( type ) {
  861. return function( elem ) {
  862. var name = elem.nodeName.toLowerCase();
  863. return name === "input" && elem.type === type;
  864. };
  865. }
  866. /**
  867. * Returns a function to use in pseudos for buttons
  868. * @param {String} type
  869. */
  870. function createButtonPseudo( type ) {
  871. return function( elem ) {
  872. var name = elem.nodeName.toLowerCase();
  873. return (name === "input" || name === "button") && elem.type === type;
  874. };
  875. }
  876. /**
  877. * Returns a function to use in pseudos for :enabled/:disabled
  878. * @param {Boolean} disabled true for :disabled; false for :enabled
  879. */
  880. function createDisabledPseudo( disabled ) {
  881. // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
  882. return function( elem ) {
  883. // Only certain elements can match :enabled or :disabled
  884. // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
  885. // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
  886. if ( "form" in elem ) {
  887. // Check for inherited disabledness on relevant non-disabled elements:
  888. // * listed form-associated elements in a disabled fieldset
  889. // https://html.spec.whatwg.org/multipage/forms.html#category-listed
  890. // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
  891. // * option elements in a disabled optgroup
  892. // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
  893. // All such elements have a "form" property.
  894. if ( elem.parentNode && elem.disabled === false ) {
  895. // Option elements defer to a parent optgroup if present
  896. if ( "label" in elem ) {
  897. if ( "label" in elem.parentNode ) {
  898. return elem.parentNode.disabled === disabled;
  899. } else {
  900. return elem.disabled === disabled;
  901. }
  902. }
  903. // Support: IE 6 - 11
  904. // Use the isDisabled shortcut property to check for disabled fieldset ancestors
  905. return elem.isDisabled === disabled ||
  906. // Where there is no isDisabled, check manually
  907. /* jshint -W018 */
  908. elem.isDisabled !== !disabled &&
  909. disabledAncestor( elem ) === disabled;
  910. }
  911. return elem.disabled === disabled;
  912. // Try to winnow out elements that can't be disabled before trusting the disabled property.
  913. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
  914. // even exist on them, let alone have a boolean value.
  915. } else if ( "label" in elem ) {
  916. return elem.disabled === disabled;
  917. }
  918. // Remaining elements are neither :enabled nor :disabled
  919. return false;
  920. };
  921. }
  922. /**
  923. * Returns a function to use in pseudos for positionals
  924. * @param {Function} fn
  925. */
  926. function createPositionalPseudo( fn ) {
  927. return markFunction(function( argument ) {
  928. argument = +argument;
  929. return markFunction(function( seed, matches ) {
  930. var j,
  931. matchIndexes = fn( [], seed.length, argument ),
  932. i = matchIndexes.length;
  933. // Match elements found at the specified indexes
  934. while ( i-- ) {
  935. if ( seed[ (j = matchIndexes[i]) ] ) {
  936. seed[j] = !(matches[j] = seed[j]);
  937. }
  938. }
  939. });
  940. });
  941. }
  942. /**
  943. * Checks a node for validity as a Sizzle context
  944. * @param {Element|Object=} context
  945. * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  946. */
  947. function testContext( context ) {
  948. return context && typeof context.getElementsByTagName !== "undefined" && context;
  949. }
  950. // Expose support vars for convenience
  951. support = Sizzle.support = {};
  952. /**
  953. * Detects XML nodes
  954. * @param {Element|Object} elem An element or a document
  955. * @returns {Boolean} True iff elem is a non-HTML XML node
  956. */
  957. isXML = Sizzle.isXML = function( elem ) {
  958. // documentElement is verified for cases where it doesn't yet exist
  959. // (such as loading iframes in IE - #4833)
  960. var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  961. return documentElement ? documentElement.nodeName !== "HTML" : false;
  962. };
  963. /**
  964. * Sets document-related variables once based on the current document
  965. * @param {Element|Object} [doc] An element or document object to use to set the document
  966. * @returns {Object} Returns the current document
  967. */
  968. setDocument = Sizzle.setDocument = function( node ) {
  969. var hasCompare, subWindow,
  970. doc = node ? node.ownerDocument || node : preferredDoc;
  971. // Return early if doc is invalid or already selected
  972. if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  973. return document;
  974. }
  975. // Update global variables
  976. document = doc;
  977. docElem = document.documentElement;
  978. documentIsHTML = !isXML( document );
  979. // Support: IE 9-11, Edge
  980. // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
  981. if ( preferredDoc !== document &&
  982. (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
  983. // Support: IE 11, Edge
  984. if ( subWindow.addEventListener ) {
  985. subWindow.addEventListener( "unload", unloadHandler, false );
  986. // Support: IE 9 - 10 only
  987. } else if ( subWindow.attachEvent ) {
  988. subWindow.attachEvent( "onunload", unloadHandler );
  989. }
  990. }
  991. /* Attributes
  992. ---------------------------------------------------------------------- */
  993. // Support: IE<8
  994. // Verify that getAttribute really returns attributes and not properties
  995. // (excepting IE8 booleans)
  996. support.attributes = assert(function( el ) {
  997. el.className = "i";
  998. return !el.getAttribute("className");
  999. });
  1000. /* getElement(s)By*
  1001. ---------------------------------------------------------------------- */
  1002. // Check if getElementsByTagName("*") returns only elements
  1003. support.getElementsByTagName = assert(function( el ) {
  1004. el.appendChild( document.createComment("") );
  1005. return !el.getElementsByTagName("*").length;
  1006. });
  1007. // Support: IE<9
  1008. support.getElementsByClassName = rnative.test( document.getElementsByClassName );
  1009. // Support: IE<10
  1010. // Check if getElementById returns elements by name
  1011. // The broken getElementById methods don't pick up programmatically-set names,
  1012. // so use a roundabout getElementsByName test
  1013. support.getById = assert(function( el ) {
  1014. docElem.appendChild( el ).id = expando;
  1015. return !document.getElementsByName || !document.getElementsByName( expando ).length;
  1016. });
  1017. // ID filter and find
  1018. if ( support.getById ) {
  1019. Expr.filter["ID"] = function( id ) {
  1020. var attrId = id.replace( runescape, funescape );
  1021. return function( elem ) {
  1022. return elem.getAttribute("id") === attrId;
  1023. };
  1024. };
  1025. Expr.find["ID"] = function( id, context ) {
  1026. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  1027. var elem = context.getElementById( id );
  1028. return elem ? [ elem ] : [];
  1029. }
  1030. };
  1031. } else {
  1032. Expr.filter["ID"] = function( id ) {
  1033. var attrId = id.replace( runescape, funescape );
  1034. return function( elem ) {
  1035. var node = typeof elem.getAttributeNode !== "undefined" &&
  1036. elem.getAttributeNode("id");
  1037. return node && node.value === attrId;
  1038. };
  1039. };
  1040. // Support: IE 6 - 7 only
  1041. // getElementById is not reliable as a find shortcut
  1042. Expr.find["ID"] = function( id, context ) {
  1043. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  1044. var node, i, elems,
  1045. elem = context.getElementById( id );
  1046. if ( elem ) {
  1047. // Verify the id attribute
  1048. node = elem.getAttributeNode("id");
  1049. if ( node && node.value === id ) {
  1050. return [ elem ];
  1051. }
  1052. // Fall back on getElementsByName
  1053. elems = context.getElementsByName( id );
  1054. i = 0;
  1055. while ( (elem = elems[i++]) ) {
  1056. node = elem.getAttributeNode("id");
  1057. if ( node && node.value === id ) {
  1058. return [ elem ];
  1059. }
  1060. }
  1061. }
  1062. return [];
  1063. }
  1064. };
  1065. }
  1066. // Tag
  1067. Expr.find["TAG"] = support.getElementsByTagName ?
  1068. function( tag, context ) {
  1069. if ( typeof context.getElementsByTagName !== "undefined" ) {
  1070. return context.getElementsByTagName( tag );
  1071. // DocumentFragment nodes don't have gEBTN
  1072. } else if ( support.qsa ) {
  1073. return context.querySelectorAll( tag );
  1074. }
  1075. } :
  1076. function( tag, context ) {
  1077. var elem,
  1078. tmp = [],
  1079. i = 0,
  1080. // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  1081. results = context.getElementsByTagName( tag );
  1082. // Filter out possible comments
  1083. if ( tag === "*" ) {
  1084. while ( (elem = results[i++]) ) {
  1085. if ( elem.nodeType === 1 ) {
  1086. tmp.push( elem );
  1087. }
  1088. }
  1089. return tmp;
  1090. }
  1091. return results;
  1092. };
  1093. // Class
  1094. Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  1095. if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
  1096. return context.getElementsByClassName( className );
  1097. }
  1098. };
  1099. /* QSA/matchesSelector
  1100. ---------------------------------------------------------------------- */
  1101. // QSA and matchesSelector support
  1102. // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  1103. rbuggyMatches = [];
  1104. // qSa(:focus) reports false when true (Chrome 21)
  1105. // We allow this because of a bug in IE8/9 that throws an error
  1106. // whenever `document.activeElement` is accessed on an iframe
  1107. // So, we allow :focus to pass through QSA all the time to avoid the IE error
  1108. // See https://bugs.jquery.com/ticket/13378
  1109. rbuggyQSA = [];
  1110. if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
  1111. // Build QSA regex
  1112. // Regex strategy adopted from Diego Perini
  1113. assert(function( el ) {
  1114. // Select is set to empty string on purpose
  1115. // This is to test IE's treatment of not explicitly
  1116. // setting a boolean content attribute,
  1117. // since its presence should be enough
  1118. // https://bugs.jquery.com/ticket/12359
  1119. docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
  1120. "<select id='" + expando + "-\r\\' msallowcapture=''>" +
  1121. "<option selected=''></option></select>";
  1122. // Support: IE8, Opera 11-12.16
  1123. // Nothing should be selected when empty strings follow ^= or $= or *=
  1124. // The test attribute must be unknown in Opera but "safe" for WinRT
  1125. // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  1126. if ( el.querySelectorAll("[msallowcapture^='']").length ) {
  1127. rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  1128. }
  1129. // Support: IE8
  1130. // Boolean attributes and "value" are not treated correctly
  1131. if ( !el.querySelectorAll("[selected]").length ) {
  1132. rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  1133. }
  1134. // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
  1135. if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
  1136. rbuggyQSA.push("~=");
  1137. }
  1138. // Webkit/Opera - :checked should return selected option elements
  1139. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1140. // IE8 throws error here and will not see later tests
  1141. if ( !el.querySelectorAll(":checked").length ) {
  1142. rbuggyQSA.push(":checked");
  1143. }
  1144. // Support: Safari 8+, iOS 8+
  1145. // https://bugs.webkit.org/show_bug.cgi?id=136851
  1146. // In-page `selector#id sibling-combinator selector` fails
  1147. if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
  1148. rbuggyQSA.push(".#.+[+~]");
  1149. }
  1150. });
  1151. assert(function( el ) {
  1152. el.innerHTML = "<a href='' disabled='disabled'></a>" +
  1153. "<select disabled='disabled'><option/></select>";
  1154. // Support: Windows 8 Native Apps
  1155. // The type and name attributes are restricted during .innerHTML assignment
  1156. var input = document.createElement("input");
  1157. input.setAttribute( "type", "hidden" );
  1158. el.appendChild( input ).setAttribute( "name", "D" );
  1159. // Support: IE8
  1160. // Enforce case-sensitivity of name attribute
  1161. if ( el.querySelectorAll("[name=d]").length ) {
  1162. rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
  1163. }
  1164. // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  1165. // IE8 throws error here and will not see later tests
  1166. if ( el.querySelectorAll(":enabled").length !== 2 ) {
  1167. rbuggyQSA.push( ":enabled", ":disabled" );
  1168. }
  1169. // Support: IE9-11+
  1170. // IE's :disabled selector does not pick up the children of disabled fieldsets
  1171. docElem.appendChild( el ).disabled = true;
  1172. if ( el.querySelectorAll(":disabled").length !== 2 ) {
  1173. rbuggyQSA.push( ":enabled", ":disabled" );
  1174. }
  1175. // Opera 10-11 does not throw on post-comma invalid pseudos
  1176. el.querySelectorAll("*,:x");
  1177. rbuggyQSA.push(",.*:");
  1178. });
  1179. }
  1180. if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
  1181. docElem.webkitMatchesSelector ||
  1182. docElem.mozMatchesSelector ||
  1183. docElem.oMatchesSelector ||
  1184. docElem.msMatchesSelector) )) ) {
  1185. assert(function( el ) {
  1186. // Check to see if it's possible to do matchesSelector
  1187. // on a disconnected node (IE 9)
  1188. support.disconnectedMatch = matches.call( el, "*" );
  1189. // This should fail with an exception
  1190. // Gecko does not error, returns false instead
  1191. matches.call( el, "[s!='']:x" );
  1192. rbuggyMatches.push( "!=", pseudos );
  1193. });
  1194. }
  1195. rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  1196. rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  1197. /* Contains
  1198. ---------------------------------------------------------------------- */
  1199. hasCompare = rnative.test( docElem.compareDocumentPosition );
  1200. // Element contains another
  1201. // Purposefully self-exclusive
  1202. // As in, an element does not contain itself
  1203. contains = hasCompare || rnative.test( docElem.contains ) ?
  1204. function( a, b ) {
  1205. var adown = a.nodeType === 9 ? a.documentElement : a,
  1206. bup = b && b.parentNode;
  1207. return a === bup || !!( bup && bup.nodeType === 1 && (
  1208. adown.contains ?
  1209. adown.contains( bup ) :
  1210. a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  1211. ));
  1212. } :
  1213. function( a, b ) {
  1214. if ( b ) {
  1215. while ( (b = b.parentNode) ) {
  1216. if ( b === a ) {
  1217. return true;
  1218. }
  1219. }
  1220. }
  1221. return false;
  1222. };
  1223. /* Sorting
  1224. ---------------------------------------------------------------------- */
  1225. // Document order sorting
  1226. sortOrder = hasCompare ?
  1227. function( a, b ) {
  1228. // Flag for duplicate removal
  1229. if ( a === b ) {
  1230. hasDuplicate = true;
  1231. return 0;
  1232. }
  1233. // Sort on method existence if only one input has compareDocumentPosition
  1234. var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  1235. if ( compare ) {
  1236. return compare;
  1237. }
  1238. // Calculate position if both inputs belong to the same document
  1239. compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
  1240. a.compareDocumentPosition( b ) :
  1241. // Otherwise we know they are disconnected
  1242. 1;
  1243. // Disconnected nodes
  1244. if ( compare & 1 ||
  1245. (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  1246. // Choose the first element that is related to our preferred document
  1247. if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
  1248. return -1;
  1249. }
  1250. if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
  1251. return 1;
  1252. }
  1253. // Maintain original order
  1254. return sortInput ?
  1255. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1256. 0;
  1257. }
  1258. return compare & 4 ? -1 : 1;
  1259. } :
  1260. function( a, b ) {
  1261. // Exit early if the nodes are identical
  1262. if ( a === b ) {
  1263. hasDuplicate = true;
  1264. return 0;
  1265. }
  1266. var cur,
  1267. i = 0,
  1268. aup = a.parentNode,
  1269. bup = b.parentNode,
  1270. ap = [ a ],
  1271. bp = [ b ];
  1272. // Parentless nodes are either documents or disconnected
  1273. if ( !aup || !bup ) {
  1274. return a === document ? -1 :
  1275. b === document ? 1 :
  1276. aup ? -1 :
  1277. bup ? 1 :
  1278. sortInput ?
  1279. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1280. 0;
  1281. // If the nodes are siblings, we can do a quick check
  1282. } else if ( aup === bup ) {
  1283. return siblingCheck( a, b );
  1284. }
  1285. // Otherwise we need full lists of their ancestors for comparison
  1286. cur = a;
  1287. while ( (cur = cur.parentNode) ) {
  1288. ap.unshift( cur );
  1289. }
  1290. cur = b;
  1291. while ( (cur = cur.parentNode) ) {
  1292. bp.unshift( cur );
  1293. }
  1294. // Walk down the tree looking for a discrepancy
  1295. while ( ap[i] === bp[i] ) {
  1296. i++;
  1297. }
  1298. return i ?
  1299. // Do a sibling check if the nodes have a common ancestor
  1300. siblingCheck( ap[i], bp[i] ) :
  1301. // Otherwise nodes in our document sort first
  1302. ap[i] === preferredDoc ? -1 :
  1303. bp[i] === preferredDoc ? 1 :
  1304. 0;
  1305. };
  1306. return document;
  1307. };
  1308. Sizzle.matches = function( expr, elements ) {
  1309. return Sizzle( expr, null, null, elements );
  1310. };
  1311. Sizzle.matchesSelector = function( elem, expr ) {
  1312. // Set document vars if needed
  1313. if ( ( elem.ownerDocument || elem ) !== document ) {
  1314. setDocument( elem );
  1315. }
  1316. // Make sure that attribute selectors are quoted
  1317. expr = expr.replace( rattributeQuotes, "='$1']" );
  1318. if ( support.matchesSelector && documentIsHTML &&
  1319. !compilerCache[ expr + " " ] &&
  1320. ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  1321. ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
  1322. try {
  1323. var ret = matches.call( elem, expr );
  1324. // IE 9's matchesSelector returns false on disconnected nodes
  1325. if ( ret || support.disconnectedMatch ||
  1326. // As well, disconnected nodes are said to be in a document
  1327. // fragment in IE 9
  1328. elem.document && elem.document.nodeType !== 11 ) {
  1329. return ret;
  1330. }
  1331. } catch (e) {}
  1332. }
  1333. return Sizzle( expr, document, null, [ elem ] ).length > 0;
  1334. };
  1335. Sizzle.contains = function( context, elem ) {
  1336. // Set document vars if needed
  1337. if ( ( context.ownerDocument || context ) !== document ) {
  1338. setDocument( context );
  1339. }
  1340. return contains( context, elem );
  1341. };
  1342. Sizzle.attr = function( elem, name ) {
  1343. // Set document vars if needed
  1344. if ( ( elem.ownerDocument || elem ) !== document ) {
  1345. setDocument( elem );
  1346. }
  1347. var fn = Expr.attrHandle[ name.toLowerCase() ],
  1348. // Don't get fooled by Object.prototype properties (jQuery #13807)
  1349. val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  1350. fn( elem, name, !documentIsHTML ) :
  1351. undefined;
  1352. return val !== undefined ?
  1353. val :
  1354. support.attributes || !documentIsHTML ?
  1355. elem.getAttribute( name ) :
  1356. (val = elem.getAttributeNode(name)) && val.specified ?
  1357. val.value :
  1358. null;
  1359. };
  1360. Sizzle.escape = function( sel ) {
  1361. return (sel + "").replace( rcssescape, fcssescape );
  1362. };
  1363. Sizzle.error = function( msg ) {
  1364. throw new Error( "Syntax error, unrecognized expression: " + msg );
  1365. };
  1366. /**
  1367. * Document sorting and removing duplicates
  1368. * @param {ArrayLike} results
  1369. */
  1370. Sizzle.uniqueSort = function( results ) {
  1371. var elem,
  1372. duplicates = [],
  1373. j = 0,
  1374. i = 0;
  1375. // Unless we *know* we can detect duplicates, assume their presence
  1376. hasDuplicate = !support.detectDuplicates;
  1377. sortInput = !support.sortStable && results.slice( 0 );
  1378. results.sort( sortOrder );
  1379. if ( hasDuplicate ) {
  1380. while ( (elem = results[i++]) ) {
  1381. if ( elem === results[ i ] ) {
  1382. j = duplicates.push( i );
  1383. }
  1384. }
  1385. while ( j-- ) {
  1386. results.splice( duplicates[ j ], 1 );
  1387. }
  1388. }
  1389. // Clear input after sorting to release objects
  1390. // See https://github.com/jquery/sizzle/pull/225
  1391. sortInput = null;
  1392. return results;
  1393. };
  1394. /**
  1395. * Utility function for retrieving the text value of an array of DOM nodes
  1396. * @param {Array|Element} elem
  1397. */
  1398. getText = Sizzle.getText = function( elem ) {
  1399. var node,
  1400. ret = "",
  1401. i = 0,
  1402. nodeType = elem.nodeType;
  1403. if ( !nodeType ) {
  1404. // If no nodeType, this is expected to be an array
  1405. while ( (node = elem[i++]) ) {
  1406. // Do not traverse comment nodes
  1407. ret += getText( node );
  1408. }
  1409. } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  1410. // Use textContent for elements
  1411. // innerText usage removed for consistency of new lines (jQuery #11153)
  1412. if ( typeof elem.textContent === "string" ) {
  1413. return elem.textContent;
  1414. } else {
  1415. // Traverse its children
  1416. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1417. ret += getText( elem );
  1418. }
  1419. }
  1420. } else if ( nodeType === 3 || nodeType === 4 ) {
  1421. return elem.nodeValue;
  1422. }
  1423. // Do not include comment or processing instruction nodes
  1424. return ret;
  1425. };
  1426. Expr = Sizzle.selectors = {
  1427. // Can be adjusted by the user
  1428. cacheLength: 50,
  1429. createPseudo: markFunction,
  1430. match: matchExpr,
  1431. attrHandle: {},
  1432. find: {},
  1433. relative: {
  1434. ">": { dir: "parentNode", first: true },
  1435. " ": { dir: "parentNode" },
  1436. "+": { dir: "previousSibling", first: true },
  1437. "~": { dir: "previousSibling" }
  1438. },
  1439. preFilter: {
  1440. "ATTR": function( match ) {
  1441. match[1] = match[1].replace( runescape, funescape );
  1442. // Move the given value to match[3] whether quoted or unquoted
  1443. match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
  1444. if ( match[2] === "~=" ) {
  1445. match[3] = " " + match[3] + " ";
  1446. }
  1447. return match.slice( 0, 4 );
  1448. },
  1449. "CHILD": function( match ) {
  1450. /* matches from matchExpr["CHILD"]
  1451. 1 type (only|nth|...)
  1452. 2 what (child|of-type)
  1453. 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  1454. 4 xn-component of xn+y argument ([+-]?\d*n|)
  1455. 5 sign of xn-component
  1456. 6 x of xn-component
  1457. 7 sign of y-component
  1458. 8 y of y-component
  1459. */
  1460. match[1] = match[1].toLowerCase();
  1461. if ( match[1].slice( 0, 3 ) === "nth" ) {
  1462. // nth-* requires argument
  1463. if ( !match[3] ) {
  1464. Sizzle.error( match[0] );
  1465. }
  1466. // numeric x and y parameters for Expr.filter.CHILD
  1467. // remember that false/true cast respectively to 0/1
  1468. match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  1469. match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  1470. // other types prohibit arguments
  1471. } else if ( match[3] ) {
  1472. Sizzle.error( match[0] );
  1473. }
  1474. return match;
  1475. },
  1476. "PSEUDO": function( match ) {
  1477. var excess,
  1478. unquoted = !match[6] && match[2];
  1479. if ( matchExpr["CHILD"].test( match[0] ) ) {
  1480. return null;
  1481. }
  1482. // Accept quoted arguments as-is
  1483. if ( match[3] ) {
  1484. match[2] = match[4] || match[5] || "";
  1485. // Strip excess characters from unquoted arguments
  1486. } else if ( unquoted && rpseudo.test( unquoted ) &&
  1487. // Get excess from tokenize (recursively)
  1488. (excess = tokenize( unquoted, true )) &&
  1489. // advance to the next closing parenthesis
  1490. (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  1491. // excess is a negative index
  1492. match[0] = match[0].slice( 0, excess );
  1493. match[2] = unquoted.slice( 0, excess );
  1494. }
  1495. // Return only captures needed by the pseudo filter method (type and argument)
  1496. return match.slice( 0, 3 );
  1497. }
  1498. },
  1499. filter: {
  1500. "TAG": function( nodeNameSelector ) {
  1501. var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  1502. return nodeNameSelector === "*" ?
  1503. function() { return true; } :
  1504. function( elem ) {
  1505. return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  1506. };
  1507. },
  1508. "CLASS": function( className ) {
  1509. var pattern = classCache[ className + " " ];
  1510. return pattern ||
  1511. (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  1512. classCache( className, function( elem ) {
  1513. return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  1514. });
  1515. },
  1516. "ATTR": function( name, operator, check ) {
  1517. return function( elem ) {
  1518. var result = Sizzle.attr( elem, name );
  1519. if ( result == null ) {
  1520. return operator === "!=";
  1521. }
  1522. if ( !operator ) {
  1523. return true;
  1524. }
  1525. result += "";
  1526. return operator === "=" ? result === check :
  1527. operator === "!=" ? result !== check :
  1528. operator === "^=" ? check && result.indexOf( check ) === 0 :
  1529. operator === "*=" ? check && result.indexOf( check ) > -1 :
  1530. operator === "$=" ? check && result.slice( -check.length ) === check :
  1531. operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  1532. operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  1533. false;
  1534. };
  1535. },
  1536. "CHILD": function( type, what, argument, first, last ) {
  1537. var simple = type.slice( 0, 3 ) !== "nth",
  1538. forward = type.slice( -4 ) !== "last",
  1539. ofType = what === "of-type";
  1540. return first === 1 && last === 0 ?
  1541. // Shortcut for :nth-*(n)
  1542. function( elem ) {
  1543. return !!elem.parentNode;
  1544. } :
  1545. function( elem, context, xml ) {
  1546. var cache, uniqueCache, outerCache, node, nodeIndex, start,
  1547. dir = simple !== forward ? "nextSibling" : "previousSibling",
  1548. parent = elem.parentNode,
  1549. name = ofType && elem.nodeName.toLowerCase(),
  1550. useCache = !xml && !ofType,
  1551. diff = false;
  1552. if ( parent ) {
  1553. // :(first|last|only)-(child|of-type)
  1554. if ( simple ) {
  1555. while ( dir ) {
  1556. node = elem;
  1557. while ( (node = node[ dir ]) ) {
  1558. if ( ofType ?
  1559. node.nodeName.toLowerCase() === name :
  1560. node.nodeType === 1 ) {
  1561. return false;
  1562. }
  1563. }
  1564. // Reverse direction for :only-* (if we haven't yet done so)
  1565. start = dir = type === "only" && !start && "nextSibling";
  1566. }
  1567. return true;
  1568. }
  1569. start = [ forward ? parent.firstChild : parent.lastChild ];
  1570. // non-xml :nth-child(...) stores cache data on `parent`
  1571. if ( forward && useCache ) {
  1572. // Seek `elem` from a previously-cached index
  1573. // ...in a gzip-friendly way
  1574. node = parent;
  1575. outerCache = node[ expando ] || (node[ expando ] = {});
  1576. // Support: IE <9 only
  1577. // Defend against cloned attroperties (jQuery gh-1709)
  1578. uniqueCache = outerCache[ node.uniqueID ] ||
  1579. (outerCache[ node.uniqueID ] = {});
  1580. cache = uniqueCache[ type ] || [];
  1581. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1582. diff = nodeIndex && cache[ 2 ];
  1583. node = nodeIndex && parent.childNodes[ nodeIndex ];
  1584. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1585. // Fallback to seeking `elem` from the start
  1586. (diff = nodeIndex = 0) || start.pop()) ) {
  1587. // When found, cache indexes on `parent` and break
  1588. if ( node.nodeType === 1 && ++diff && node === elem ) {
  1589. uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
  1590. break;
  1591. }
  1592. }
  1593. } else {
  1594. // Use previously-cached element index if available
  1595. if ( useCache ) {
  1596. // ...in a gzip-friendly way
  1597. node = elem;
  1598. outerCache = node[ expando ] || (node[ expando ] = {});
  1599. // Support: IE <9 only
  1600. // Defend against cloned attroperties (jQuery gh-1709)
  1601. uniqueCache = outerCache[ node.uniqueID ] ||
  1602. (outerCache[ node.uniqueID ] = {});
  1603. cache = uniqueCache[ type ] || [];
  1604. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1605. diff = nodeIndex;
  1606. }
  1607. // xml :nth-child(...)
  1608. // or :nth-last-child(...) or :nth(-last)?-of-type(...)
  1609. if ( diff === false ) {
  1610. // Use the same loop as above to seek `elem` from the start
  1611. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1612. (diff = nodeIndex = 0) || start.pop()) ) {
  1613. if ( ( ofType ?
  1614. node.nodeName.toLowerCase() === name :
  1615. node.nodeType === 1 ) &&
  1616. ++diff ) {
  1617. // Cache the index of each encountered element
  1618. if ( useCache ) {
  1619. outerCache = node[ expando ] || (node[ expando ] = {});
  1620. // Support: IE <9 only
  1621. // Defend against cloned attroperties (jQuery gh-1709)
  1622. uniqueCache = outerCache[ node.uniqueID ] ||
  1623. (outerCache[ node.uniqueID ] = {});
  1624. uniqueCache[ type ] = [ dirruns, diff ];
  1625. }
  1626. if ( node === elem ) {
  1627. break;
  1628. }
  1629. }
  1630. }
  1631. }
  1632. }
  1633. // Incorporate the offset, then check against cycle size
  1634. diff -= last;
  1635. return diff === first || ( diff % first === 0 && diff / first >= 0 );
  1636. }
  1637. };
  1638. },
  1639. "PSEUDO": function( pseudo, argument ) {
  1640. // pseudo-class names are case-insensitive
  1641. // http://www.w3.org/TR/selectors/#pseudo-classes
  1642. // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  1643. // Remember that setFilters inherits from pseudos
  1644. var args,
  1645. fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  1646. Sizzle.error( "unsupported pseudo: " + pseudo );
  1647. // The user may use createPseudo to indicate that
  1648. // arguments are needed to create the filter function
  1649. // just as Sizzle does
  1650. if ( fn[ expando ] ) {
  1651. return fn( argument );
  1652. }
  1653. // But maintain support for old signatures
  1654. if ( fn.length > 1 ) {
  1655. args = [ pseudo, pseudo, "", argument ];
  1656. return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  1657. markFunction(function( seed, matches ) {
  1658. var idx,
  1659. matched = fn( seed, argument ),
  1660. i = matched.length;
  1661. while ( i-- ) {
  1662. idx = indexOf( seed, matched[i] );
  1663. seed[ idx ] = !( matches[ idx ] = matched[i] );
  1664. }
  1665. }) :
  1666. function( elem ) {
  1667. return fn( elem, 0, args );
  1668. };
  1669. }
  1670. return fn;
  1671. }
  1672. },
  1673. pseudos: {
  1674. // Potentially complex pseudos
  1675. "not": markFunction(function( selector ) {
  1676. // Trim the selector passed to compile
  1677. // to avoid treating leading and trailing
  1678. // spaces as combinators
  1679. var input = [],
  1680. results = [],
  1681. matcher = compile( selector.replace( rtrim, "$1" ) );
  1682. return matcher[ expando ] ?
  1683. markFunction(function( seed, matches, context, xml ) {
  1684. var elem,
  1685. unmatched = matcher( seed, null, xml, [] ),
  1686. i = seed.length;
  1687. // Match elements unmatched by `matcher`
  1688. while ( i-- ) {
  1689. if ( (elem = unmatched[i]) ) {
  1690. seed[i] = !(matches[i] = elem);
  1691. }
  1692. }
  1693. }) :
  1694. function( elem, context, xml ) {
  1695. input[0] = elem;
  1696. matcher( input, null, xml, results );
  1697. // Don't keep the element (issue #299)
  1698. input[0] = null;
  1699. return !results.pop();
  1700. };
  1701. }),
  1702. "has": markFunction(function( selector ) {
  1703. return function( elem ) {
  1704. return Sizzle( selector, elem ).length > 0;
  1705. };
  1706. }),
  1707. "contains": markFunction(function( text ) {
  1708. text = text.replace( runescape, funescape );
  1709. return function( elem ) {
  1710. return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  1711. };
  1712. }),
  1713. // "Whether an element is represented by a :lang() selector
  1714. // is based solely on the element's language value
  1715. // being equal to the identifier C,
  1716. // or beginning with the identifier C immediately followed by "-".
  1717. // The matching of C against the element's language value is performed case-insensitively.
  1718. // The identifier C does not have to be a valid language name."
  1719. // http://www.w3.org/TR/selectors/#lang-pseudo
  1720. "lang": markFunction( function( lang ) {
  1721. // lang value must be a valid identifier
  1722. if ( !ridentifier.test(lang || "") ) {
  1723. Sizzle.error( "unsupported lang: " + lang );
  1724. }
  1725. lang = lang.replace( runescape, funescape ).toLowerCase();
  1726. return function( elem ) {
  1727. var elemLang;
  1728. do {
  1729. if ( (elemLang = documentIsHTML ?
  1730. elem.lang :
  1731. elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  1732. elemLang = elemLang.toLowerCase();
  1733. return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  1734. }
  1735. } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  1736. return false;
  1737. };
  1738. }),
  1739. // Miscellaneous
  1740. "target": function( elem ) {
  1741. var hash = window.location && window.location.hash;
  1742. return hash && hash.slice( 1 ) === elem.id;
  1743. },
  1744. "root": function( elem ) {
  1745. return elem === docElem;
  1746. },
  1747. "focus": function( elem ) {
  1748. return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  1749. },
  1750. // Boolean properties
  1751. "enabled": createDisabledPseudo( false ),
  1752. "disabled": createDisabledPseudo( true ),
  1753. "checked": function( elem ) {
  1754. // In CSS3, :checked should return both checked and selected elements
  1755. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1756. var nodeName = elem.nodeName.toLowerCase();
  1757. return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  1758. },
  1759. "selected": function( elem ) {
  1760. // Accessing this property makes selected-by-default
  1761. // options in Safari work properly
  1762. if ( elem.parentNode ) {
  1763. elem.parentNode.selectedIndex;
  1764. }
  1765. return elem.selected === true;
  1766. },
  1767. // Contents
  1768. "empty": function( elem ) {
  1769. // http://www.w3.org/TR/selectors/#empty-pseudo
  1770. // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  1771. // but not by others (comment: 8; processing instruction: 7; etc.)
  1772. // nodeType < 6 works because attributes (2) do not appear as children
  1773. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1774. if ( elem.nodeType < 6 ) {
  1775. return false;
  1776. }
  1777. }
  1778. return true;
  1779. },
  1780. "parent": function( elem ) {
  1781. return !Expr.pseudos["empty"]( elem );
  1782. },
  1783. // Element/input types
  1784. "header": function( elem ) {
  1785. return rheader.test( elem.nodeName );
  1786. },
  1787. "input": function( elem ) {
  1788. return rinputs.test( elem.nodeName );
  1789. },
  1790. "button": function( elem ) {
  1791. var name = elem.nodeName.toLowerCase();
  1792. return name === "input" && elem.type === "button" || name === "button";
  1793. },
  1794. "text": function( elem ) {
  1795. var attr;
  1796. return elem.nodeName.toLowerCase() === "input" &&
  1797. elem.type === "text" &&
  1798. // Support: IE<8
  1799. // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  1800. ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
  1801. },
  1802. // Position-in-collection
  1803. "first": createPositionalPseudo(function() {
  1804. return [ 0 ];
  1805. }),
  1806. "last": createPositionalPseudo(function( matchIndexes, length ) {
  1807. return [ length - 1 ];
  1808. }),
  1809. "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1810. return [ argument < 0 ? argument + length : argument ];
  1811. }),
  1812. "even": createPositionalPseudo(function( matchIndexes, length ) {
  1813. var i = 0;
  1814. for ( ; i < length; i += 2 ) {
  1815. matchIndexes.push( i );
  1816. }
  1817. return matchIndexes;
  1818. }),
  1819. "odd": createPositionalPseudo(function( matchIndexes, length ) {
  1820. var i = 1;
  1821. for ( ; i < length; i += 2 ) {
  1822. matchIndexes.push( i );
  1823. }
  1824. return matchIndexes;
  1825. }),
  1826. "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1827. var i = argument < 0 ? argument + length : argument;
  1828. for ( ; --i >= 0; ) {
  1829. matchIndexes.push( i );
  1830. }
  1831. return matchIndexes;
  1832. }),
  1833. "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1834. var i = argument < 0 ? argument + length : argument;
  1835. for ( ; ++i < length; ) {
  1836. matchIndexes.push( i );
  1837. }
  1838. return matchIndexes;
  1839. })
  1840. }
  1841. };
  1842. Expr.pseudos["nth"] = Expr.pseudos["eq"];
  1843. // Add button/input type pseudos
  1844. for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  1845. Expr.pseudos[ i ] = createInputPseudo( i );
  1846. }
  1847. for ( i in { submit: true, reset: true } ) {
  1848. Expr.pseudos[ i ] = createButtonPseudo( i );
  1849. }
  1850. // Easy API for creating new setFilters
  1851. function setFilters() {}
  1852. setFilters.prototype = Expr.filters = Expr.pseudos;
  1853. Expr.setFilters = new setFilters();
  1854. tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
  1855. var matched, match, tokens, type,
  1856. soFar, groups, preFilters,
  1857. cached = tokenCache[ selector + " " ];
  1858. if ( cached ) {
  1859. return parseOnly ? 0 : cached.slice( 0 );
  1860. }
  1861. soFar = selector;
  1862. groups = [];
  1863. preFilters = Expr.preFilter;
  1864. while ( soFar ) {
  1865. // Comma and first run
  1866. if ( !matched || (match = rcomma.exec( soFar )) ) {
  1867. if ( match ) {
  1868. // Don't consume trailing commas as valid
  1869. soFar = soFar.slice( match[0].length ) || soFar;
  1870. }
  1871. groups.push( (tokens = []) );
  1872. }
  1873. matched = false;
  1874. // Combinators
  1875. if ( (match = rcombinators.exec( soFar )) ) {
  1876. matched = match.shift();
  1877. tokens.push({
  1878. value: matched,
  1879. // Cast descendant combinators to space
  1880. type: match[0].replace( rtrim, " " )
  1881. });
  1882. soFar = soFar.slice( matched.length );
  1883. }
  1884. // Filters
  1885. for ( type in Expr.filter ) {
  1886. if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  1887. (match = preFilters[ type ]( match ))) ) {
  1888. matched = match.shift();
  1889. tokens.push({
  1890. value: matched,
  1891. type: type,
  1892. matches: match
  1893. });
  1894. soFar = soFar.slice( matched.length );
  1895. }
  1896. }
  1897. if ( !matched ) {
  1898. break;
  1899. }
  1900. }
  1901. // Return the length of the invalid excess
  1902. // if we're just parsing
  1903. // Otherwise, throw an error or return tokens
  1904. return parseOnly ?
  1905. soFar.length :
  1906. soFar ?
  1907. Sizzle.error( selector ) :
  1908. // Cache the tokens
  1909. tokenCache( selector, groups ).slice( 0 );
  1910. };
  1911. function toSelector( tokens ) {
  1912. var i = 0,
  1913. len = tokens.length,
  1914. selector = "";
  1915. for ( ; i < len; i++ ) {
  1916. selector += tokens[i].value;
  1917. }
  1918. return selector;
  1919. }
  1920. function addCombinator( matcher, combinator, base ) {
  1921. var dir = combinator.dir,
  1922. skip = combinator.next,
  1923. key = skip || dir,
  1924. checkNonElements = base && key === "parentNode",
  1925. doneName = done++;
  1926. return combinator.first ?
  1927. // Check against closest ancestor/preceding element
  1928. function( elem, context, xml ) {
  1929. while ( (elem = elem[ dir ]) ) {
  1930. if ( elem.nodeType === 1 || checkNonElements ) {
  1931. return matcher( elem, context, xml );
  1932. }
  1933. }
  1934. return false;
  1935. } :
  1936. // Check against all ancestor/preceding elements
  1937. function( elem, context, xml ) {
  1938. var oldCache, uniqueCache, outerCache,
  1939. newCache = [ dirruns, doneName ];
  1940. // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
  1941. if ( xml ) {
  1942. while ( (elem = elem[ dir ]) ) {
  1943. if ( elem.nodeType === 1 || checkNonElements ) {
  1944. if ( matcher( elem, context, xml ) ) {
  1945. return true;
  1946. }
  1947. }
  1948. }
  1949. } else {
  1950. while ( (elem = elem[ dir ]) ) {
  1951. if ( elem.nodeType === 1 || checkNonElements ) {
  1952. outerCache = elem[ expando ] || (elem[ expando ] = {});
  1953. // Support: IE <9 only
  1954. // Defend against cloned attroperties (jQuery gh-1709)
  1955. uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
  1956. if ( skip && skip === elem.nodeName.toLowerCase() ) {
  1957. elem = elem[ dir ] || elem;
  1958. } else if ( (oldCache = uniqueCache[ key ]) &&
  1959. oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
  1960. // Assign to newCache so results back-propagate to previous elements
  1961. return (newCache[ 2 ] = oldCache[ 2 ]);
  1962. } else {
  1963. // Reuse newcache so results back-propagate to previous elements
  1964. uniqueCache[ key ] = newCache;
  1965. // A match means we're done; a fail means we have to keep checking
  1966. if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
  1967. return true;
  1968. }
  1969. }
  1970. }
  1971. }
  1972. }
  1973. return false;
  1974. };
  1975. }
  1976. function elementMatcher( matchers ) {
  1977. return matchers.length > 1 ?
  1978. function( elem, context, xml ) {
  1979. var i = matchers.length;
  1980. while ( i-- ) {
  1981. if ( !matchers[i]( elem, context, xml ) ) {
  1982. return false;
  1983. }
  1984. }
  1985. return true;
  1986. } :
  1987. matchers[0];
  1988. }
  1989. function multipleContexts( selector, contexts, results ) {
  1990. var i = 0,
  1991. len = contexts.length;
  1992. for ( ; i < len; i++ ) {
  1993. Sizzle( selector, contexts[i], results );
  1994. }
  1995. return results;
  1996. }
  1997. function condense( unmatched, map, filter, context, xml ) {
  1998. var elem,
  1999. newUnmatched = [],
  2000. i = 0,
  2001. len = unmatched.length,
  2002. mapped = map != null;
  2003. for ( ; i < len; i++ ) {
  2004. if ( (elem = unmatched[i]) ) {
  2005. if ( !filter || filter( elem, context, xml ) ) {
  2006. newUnmatched.push( elem );
  2007. if ( mapped ) {
  2008. map.push( i );
  2009. }
  2010. }
  2011. }
  2012. }
  2013. return newUnmatched;
  2014. }
  2015. function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  2016. if ( postFilter && !postFilter[ expando ] ) {
  2017. postFilter = setMatcher( postFilter );
  2018. }
  2019. if ( postFinder && !postFinder[ expando ] ) {
  2020. postFinder = setMatcher( postFinder, postSelector );
  2021. }
  2022. return markFunction(function( seed, results, context, xml ) {
  2023. var temp, i, elem,
  2024. preMap = [],
  2025. postMap = [],
  2026. preexisting = results.length,
  2027. // Get initial elements from seed or context
  2028. elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  2029. // Prefilter to get matcher input, preserving a map for seed-results synchronization
  2030. matcherIn = preFilter && ( seed || !selector ) ?
  2031. condense( elems, preMap, preFilter, context, xml ) :
  2032. elems,
  2033. matcherOut = matcher ?
  2034. // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  2035. postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  2036. // ...intermediate processing is necessary
  2037. [] :
  2038. // ...otherwise use results directly
  2039. results :
  2040. matcherIn;
  2041. // Find primary matches
  2042. if ( matcher ) {
  2043. matcher( matcherIn, matcherOut, context, xml );
  2044. }
  2045. // Apply postFilter
  2046. if ( postFilter ) {
  2047. temp = condense( matcherOut, postMap );
  2048. postFilter( temp, [], context, xml );
  2049. // Un-match failing elements by moving them back to matcherIn
  2050. i = temp.length;
  2051. while ( i-- ) {
  2052. if ( (elem = temp[i]) ) {
  2053. matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  2054. }
  2055. }
  2056. }
  2057. if ( seed ) {
  2058. if ( postFinder || preFilter ) {
  2059. if ( postFinder ) {
  2060. // Get the final matcherOut by condensing this intermediate into postFinder contexts
  2061. temp = [];
  2062. i = matcherOut.length;
  2063. while ( i-- ) {
  2064. if ( (elem = matcherOut[i]) ) {
  2065. // Restore matcherIn since elem is not yet a final match
  2066. temp.push( (matcherIn[i] = elem) );
  2067. }
  2068. }
  2069. postFinder( null, (matcherOut = []), temp, xml );
  2070. }
  2071. // Move matched elements from seed to results to keep them synchronized
  2072. i = matcherOut.length;
  2073. while ( i-- ) {
  2074. if ( (elem = matcherOut[i]) &&
  2075. (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  2076. seed[temp] = !(results[temp] = elem);
  2077. }
  2078. }
  2079. }
  2080. // Add elements to results, through postFinder if defined
  2081. } else {
  2082. matcherOut = condense(
  2083. matcherOut === results ?
  2084. matcherOut.splice( preexisting, matcherOut.length ) :
  2085. matcherOut
  2086. );
  2087. if ( postFinder ) {
  2088. postFinder( null, results, matcherOut, xml );
  2089. } else {
  2090. push.apply( results, matcherOut );
  2091. }
  2092. }
  2093. });
  2094. }
  2095. function matcherFromTokens( tokens ) {
  2096. var checkContext, matcher, j,
  2097. len = tokens.length,
  2098. leadingRelative = Expr.relative[ tokens[0].type ],
  2099. implicitRelative = leadingRelative || Expr.relative[" "],
  2100. i = leadingRelative ? 1 : 0,
  2101. // The foundational matcher ensures that elements are reachable from top-level context(s)
  2102. matchContext = addCombinator( function( elem ) {
  2103. return elem === checkContext;
  2104. }, implicitRelative, true ),
  2105. matchAnyContext = addCombinator( function( elem ) {
  2106. return indexOf( checkContext, elem ) > -1;
  2107. }, implicitRelative, true ),
  2108. matchers = [ function( elem, context, xml ) {
  2109. var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  2110. (checkContext = context).nodeType ?
  2111. matchContext( elem, context, xml ) :
  2112. matchAnyContext( elem, context, xml ) );
  2113. // Avoid hanging onto element (issue #299)
  2114. checkContext = null;
  2115. return ret;
  2116. } ];
  2117. for ( ; i < len; i++ ) {
  2118. if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  2119. matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  2120. } else {
  2121. matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  2122. // Return special upon seeing a positional matcher
  2123. if ( matcher[ expando ] ) {
  2124. // Find the next relative operator (if any) for proper handling
  2125. j = ++i;
  2126. for ( ; j < len; j++ ) {
  2127. if ( Expr.relative[ tokens[j].type ] ) {
  2128. break;
  2129. }
  2130. }
  2131. return setMatcher(
  2132. i > 1 && elementMatcher( matchers ),
  2133. i > 1 && toSelector(
  2134. // If the preceding token was a descendant combinator, insert an implicit any-element `*`
  2135. tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  2136. ).replace( rtrim, "$1" ),
  2137. matcher,
  2138. i < j && matcherFromTokens( tokens.slice( i, j ) ),
  2139. j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  2140. j < len && toSelector( tokens )
  2141. );
  2142. }
  2143. matchers.push( matcher );
  2144. }
  2145. }
  2146. return elementMatcher( matchers );
  2147. }
  2148. function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  2149. var bySet = setMatchers.length > 0,
  2150. byElement = elementMatchers.length > 0,
  2151. superMatcher = function( seed, context, xml, results, outermost ) {
  2152. var elem, j, matcher,
  2153. matchedCount = 0,
  2154. i = "0",
  2155. unmatched = seed && [],
  2156. setMatched = [],
  2157. contextBackup = outermostContext,
  2158. // We must always have either seed elements or outermost context
  2159. elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
  2160. // Use integer dirruns iff this is the outermost matcher
  2161. dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  2162. len = elems.length;
  2163. if ( outermost ) {
  2164. outermostContext = context === document || context || outermost;
  2165. }
  2166. // Add elements passing elementMatchers directly to results
  2167. // Support: IE<9, Safari
  2168. // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  2169. for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
  2170. if ( byElement && elem ) {
  2171. j = 0;
  2172. if ( !context && elem.ownerDocument !== document ) {
  2173. setDocument( elem );
  2174. xml = !documentIsHTML;
  2175. }
  2176. while ( (matcher = elementMatchers[j++]) ) {
  2177. if ( matcher( elem, context || document, xml) ) {
  2178. results.push( elem );
  2179. break;
  2180. }
  2181. }
  2182. if ( outermost ) {
  2183. dirruns = dirrunsUnique;
  2184. }
  2185. }
  2186. // Track unmatched elements for set filters
  2187. if ( bySet ) {
  2188. // They will have gone through all possible matchers
  2189. if ( (elem = !matcher && elem) ) {
  2190. matchedCount--;
  2191. }
  2192. // Lengthen the array for every element, matched or not
  2193. if ( seed ) {
  2194. unmatched.push( elem );
  2195. }
  2196. }
  2197. }
  2198. // `i` is now the count of elements visited above, and adding it to `matchedCount`
  2199. // makes the latter nonnegative.
  2200. matchedCount += i;
  2201. // Apply set filters to unmatched elements
  2202. // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
  2203. // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
  2204. // no element matchers and no seed.
  2205. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
  2206. // case, which will result in a "00" `matchedCount` that differs from `i` but is also
  2207. // numerically zero.
  2208. if ( bySet && i !== matchedCount ) {
  2209. j = 0;
  2210. while ( (matcher = setMatchers[j++]) ) {
  2211. matcher( unmatched, setMatched, context, xml );
  2212. }
  2213. if ( seed ) {
  2214. // Reintegrate element matches to eliminate the need for sorting
  2215. if ( matchedCount > 0 ) {
  2216. while ( i-- ) {
  2217. if ( !(unmatched[i] || setMatched[i]) ) {
  2218. setMatched[i] = pop.call( results );
  2219. }
  2220. }
  2221. }
  2222. // Discard index placeholder values to get only actual matches
  2223. setMatched = condense( setMatched );
  2224. }
  2225. // Add matches to results
  2226. push.apply( results, setMatched );
  2227. // Seedless set matches succeeding multiple successful matchers stipulate sorting
  2228. if ( outermost && !seed && setMatched.length > 0 &&
  2229. ( matchedCount + setMatchers.length ) > 1 ) {
  2230. Sizzle.uniqueSort( results );
  2231. }
  2232. }
  2233. // Override manipulation of globals by nested matchers
  2234. if ( outermost ) {
  2235. dirruns = dirrunsUnique;
  2236. outermostContext = contextBackup;
  2237. }
  2238. return unmatched;
  2239. };
  2240. return bySet ?
  2241. markFunction( superMatcher ) :
  2242. superMatcher;
  2243. }
  2244. compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
  2245. var i,
  2246. setMatchers = [],
  2247. elementMatchers = [],
  2248. cached = compilerCache[ selector + " " ];
  2249. if ( !cached ) {
  2250. // Generate a function of recursive functions that can be used to check each element
  2251. if ( !match ) {
  2252. match = tokenize( selector );
  2253. }
  2254. i = match.length;
  2255. while ( i-- ) {
  2256. cached = matcherFromTokens( match[i] );
  2257. if ( cached[ expando ] ) {
  2258. setMatchers.push( cached );
  2259. } else {
  2260. elementMatchers.push( cached );
  2261. }
  2262. }
  2263. // Cache the compiled function
  2264. cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  2265. // Save selector and tokenization
  2266. cached.selector = selector;
  2267. }
  2268. return cached;
  2269. };
  2270. /**
  2271. * A low-level selection function that works with Sizzle's compiled
  2272. * selector functions
  2273. * @param {String|Function} selector A selector or a pre-compiled
  2274. * selector function built with Sizzle.compile
  2275. * @param {Element} context
  2276. * @param {Array} [results]
  2277. * @param {Array} [seed] A set of elements to match against
  2278. */
  2279. select = Sizzle.select = function( selector, context, results, seed ) {
  2280. var i, tokens, token, type, find,
  2281. compiled = typeof selector === "function" && selector,
  2282. match = !seed && tokenize( (selector = compiled.selector || selector) );
  2283. results = results || [];
  2284. // Try to minimize operations if there is only one selector in the list and no seed
  2285. // (the latter of which guarantees us context)
  2286. if ( match.length === 1 ) {
  2287. // Reduce context if the leading compound selector is an ID
  2288. tokens = match[0] = match[0].slice( 0 );
  2289. if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  2290. context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
  2291. context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  2292. if ( !context ) {
  2293. return results;
  2294. // Precompiled matchers will still verify ancestry, so step up a level
  2295. } else if ( compiled ) {
  2296. context = context.parentNode;
  2297. }
  2298. selector = selector.slice( tokens.shift().value.length );
  2299. }
  2300. // Fetch a seed set for right-to-left matching
  2301. i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  2302. while ( i-- ) {
  2303. token = tokens[i];
  2304. // Abort if we hit a combinator
  2305. if ( Expr.relative[ (type = token.type) ] ) {
  2306. break;
  2307. }
  2308. if ( (find = Expr.find[ type ]) ) {
  2309. // Search, expanding context for leading sibling combinators
  2310. if ( (seed = find(
  2311. token.matches[0].replace( runescape, funescape ),
  2312. rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
  2313. )) ) {
  2314. // If seed is empty or no tokens remain, we can return early
  2315. tokens.splice( i, 1 );
  2316. selector = seed.length && toSelector( tokens );
  2317. if ( !selector ) {
  2318. push.apply( results, seed );
  2319. return results;
  2320. }
  2321. break;
  2322. }
  2323. }
  2324. }
  2325. }
  2326. // Compile and execute a filtering function if one is not provided
  2327. // Provide `match` to avoid retokenization if we modified the selector above
  2328. ( compiled || compile( selector, match ) )(
  2329. seed,
  2330. context,
  2331. !documentIsHTML,
  2332. results,
  2333. !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
  2334. );
  2335. return results;
  2336. };
  2337. // One-time assignments
  2338. // Sort stability
  2339. support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  2340. // Support: Chrome 14-35+
  2341. // Always assume duplicates if they aren't passed to the comparison function
  2342. support.detectDuplicates = !!hasDuplicate;
  2343. // Initialize against the default document
  2344. setDocument();
  2345. // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  2346. // Detached nodes confoundingly follow *each other*
  2347. support.sortDetached = assert(function( el ) {
  2348. // Should return 1, but returns 4 (following)
  2349. return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
  2350. });
  2351. // Support: IE<8
  2352. // Prevent attribute/property "interpolation"
  2353. // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  2354. if ( !assert(function( el ) {
  2355. el.innerHTML = "<a href='#'></a>";
  2356. return el.firstChild.getAttribute("href") === "#" ;
  2357. }) ) {
  2358. addHandle( "type|href|height|width", function( elem, name, isXML ) {
  2359. if ( !isXML ) {
  2360. return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  2361. }
  2362. });
  2363. }
  2364. // Support: IE<9
  2365. // Use defaultValue in place of getAttribute("value")
  2366. if ( !support.attributes || !assert(function( el ) {
  2367. el.innerHTML = "<input/>";
  2368. el.firstChild.setAttribute( "value", "" );
  2369. return el.firstChild.getAttribute( "value" ) === "";
  2370. }) ) {
  2371. addHandle( "value", function( elem, name, isXML ) {
  2372. if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  2373. return elem.defaultValue;
  2374. }
  2375. });
  2376. }
  2377. // Support: IE<9
  2378. // Use getAttributeNode to fetch booleans when getAttribute lies
  2379. if ( !assert(function( el ) {
  2380. return el.getAttribute("disabled") == null;
  2381. }) ) {
  2382. addHandle( booleans, function( elem, name, isXML ) {
  2383. var val;
  2384. if ( !isXML ) {
  2385. return elem[ name ] === true ? name.toLowerCase() :
  2386. (val = elem.getAttributeNode( name )) && val.specified ?
  2387. val.value :
  2388. null;
  2389. }
  2390. });
  2391. }
  2392. return Sizzle;
  2393. })( window );
  2394. jQuery.find = Sizzle;
  2395. jQuery.expr = Sizzle.selectors;
  2396. // Deprecated
  2397. jQuery.expr[ ":" ] = jQuery.expr.pseudos;
  2398. jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
  2399. jQuery.text = Sizzle.getText;
  2400. jQuery.isXMLDoc = Sizzle.isXML;
  2401. jQuery.contains = Sizzle.contains;
  2402. jQuery.escapeSelector = Sizzle.escape;
  2403. var dir = function( elem, dir, until ) {
  2404. var matched = [],
  2405. truncate = until !== undefined;
  2406. while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
  2407. if ( elem.nodeType === 1 ) {
  2408. if ( truncate && jQuery( elem ).is( until ) ) {
  2409. break;
  2410. }
  2411. matched.push( elem );
  2412. }
  2413. }
  2414. return matched;
  2415. };
  2416. var siblings = function( n, elem ) {
  2417. var matched = [];
  2418. for ( ; n; n = n.nextSibling ) {
  2419. if ( n.nodeType === 1 && n !== elem ) {
  2420. matched.push( n );
  2421. }
  2422. }
  2423. return matched;
  2424. };
  2425. var rneedsContext = jQuery.expr.match.needsContext;
  2426. function nodeName( elem, name ) {
  2427. return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
  2428. };
  2429. var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
  2430. var risSimple = /^.[^:#\[\.,]*$/;
  2431. // Implement the identical functionality for filter and not
  2432. function winnow( elements, qualifier, not ) {
  2433. if ( jQuery.isFunction( qualifier ) ) {
  2434. return jQuery.grep( elements, function( elem, i ) {
  2435. return !!qualifier.call( elem, i, elem ) !== not;
  2436. } );
  2437. }
  2438. // Single element
  2439. if ( qualifier.nodeType ) {
  2440. return jQuery.grep( elements, function( elem ) {
  2441. return ( elem === qualifier ) !== not;
  2442. } );
  2443. }
  2444. // Arraylike of elements (jQuery, arguments, Array)
  2445. if ( typeof qualifier !== "string" ) {
  2446. return jQuery.grep( elements, function( elem ) {
  2447. return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
  2448. } );
  2449. }
  2450. // Simple selector that can be filtered directly, removing non-Elements
  2451. if ( risSimple.test( qualifier ) ) {
  2452. return jQuery.filter( qualifier, elements, not );
  2453. }
  2454. // Complex selector, compare the two sets, removing non-Elements
  2455. qualifier = jQuery.filter( qualifier, elements );
  2456. return jQuery.grep( elements, function( elem ) {
  2457. return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
  2458. } );
  2459. }
  2460. jQuery.filter = function( expr, elems, not ) {
  2461. var elem = elems[ 0 ];
  2462. if ( not ) {
  2463. expr = ":not(" + expr + ")";
  2464. }
  2465. if ( elems.length === 1 && elem.nodeType === 1 ) {
  2466. return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
  2467. }
  2468. return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
  2469. return elem.nodeType === 1;
  2470. } ) );
  2471. };
  2472. jQuery.fn.extend( {
  2473. find: function( selector ) {
  2474. var i, ret,
  2475. len = this.length,
  2476. self = this;
  2477. if ( typeof selector !== "string" ) {
  2478. return this.pushStack( jQuery( selector ).filter( function() {
  2479. for ( i = 0; i < len; i++ ) {
  2480. if ( jQuery.contains( self[ i ], this ) ) {
  2481. return true;
  2482. }
  2483. }
  2484. } ) );
  2485. }
  2486. ret = this.pushStack( [] );
  2487. for ( i = 0; i < len; i++ ) {
  2488. jQuery.find( selector, self[ i ], ret );
  2489. }
  2490. return len > 1 ? jQuery.uniqueSort( ret ) : ret;
  2491. },
  2492. filter: function( selector ) {
  2493. return this.pushStack( winnow( this, selector || [], false ) );
  2494. },
  2495. not: function( selector ) {
  2496. return this.pushStack( winnow( this, selector || [], true ) );
  2497. },
  2498. is: function( selector ) {
  2499. return !!winnow(
  2500. this,
  2501. // If this is a positional/relative selector, check membership in the returned set
  2502. // so $("p:first").is("p:last") won't return true for a doc with two "p".
  2503. typeof selector === "string" && rneedsContext.test( selector ) ?
  2504. jQuery( selector ) :
  2505. selector || [],
  2506. false
  2507. ).length;
  2508. }
  2509. } );
  2510. // Initialize a jQuery object
  2511. // A central reference to the root jQuery(document)
  2512. var rootjQuery,
  2513. // A simple way to check for HTML strings
  2514. // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  2515. // Strict HTML recognition (#11290: must start with <)
  2516. // Shortcut simple #id case for speed
  2517. rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
  2518. init = jQuery.fn.init = function( selector, context, root ) {
  2519. var match, elem;
  2520. // HANDLE: $(""), $(null), $(undefined), $(false)
  2521. if ( !selector ) {
  2522. return this;
  2523. }
  2524. // Method init() accepts an alternate rootjQuery
  2525. // so migrate can support jQuery.sub (gh-2101)
  2526. root = root || rootjQuery;
  2527. // Handle HTML strings
  2528. if ( typeof selector === "string" ) {
  2529. if ( selector[ 0 ] === "<" &&
  2530. selector[ selector.length - 1 ] === ">" &&
  2531. selector.length >= 3 ) {
  2532. // Assume that strings that start and end with <> are HTML and skip the regex check
  2533. match = [ null, selector, null ];
  2534. } else {
  2535. match = rquickExpr.exec( selector );
  2536. }
  2537. // Match html or make sure no context is specified for #id
  2538. if ( match && ( match[ 1 ] || !context ) ) {
  2539. // HANDLE: $(html) -> $(array)
  2540. if ( match[ 1 ] ) {
  2541. context = context instanceof jQuery ? context[ 0 ] : context;
  2542. // Option to run scripts is true for back-compat
  2543. // Intentionally let the error be thrown if parseHTML is not present
  2544. jQuery.merge( this, jQuery.parseHTML(
  2545. match[ 1 ],
  2546. context && context.nodeType ? context.ownerDocument || context : document,
  2547. true
  2548. ) );
  2549. // HANDLE: $(html, props)
  2550. if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
  2551. for ( match in context ) {
  2552. // Properties of context are called as methods if possible
  2553. if ( jQuery.isFunction( this[ match ] ) ) {
  2554. this[ match ]( context[ match ] );
  2555. // ...and otherwise set as attributes
  2556. } else {
  2557. this.attr( match, context[ match ] );
  2558. }
  2559. }
  2560. }
  2561. return this;
  2562. // HANDLE: $(#id)
  2563. } else {
  2564. elem = document.getElementById( match[ 2 ] );
  2565. if ( elem ) {
  2566. // Inject the element directly into the jQuery object
  2567. this[ 0 ] = elem;
  2568. this.length = 1;
  2569. }
  2570. return this;
  2571. }
  2572. // HANDLE: $(expr, $(...))
  2573. } else if ( !context || context.jquery ) {
  2574. return ( context || root ).find( selector );
  2575. // HANDLE: $(expr, context)
  2576. // (which is just equivalent to: $(context).find(expr)
  2577. } else {
  2578. return this.constructor( context ).find( selector );
  2579. }
  2580. // HANDLE: $(DOMElement)
  2581. } else if ( selector.nodeType ) {
  2582. this[ 0 ] = selector;
  2583. this.length = 1;
  2584. return this;
  2585. // HANDLE: $(function)
  2586. // Shortcut for document ready
  2587. } else if ( jQuery.isFunction( selector ) ) {
  2588. return root.ready !== undefined ?
  2589. root.ready( selector ) :
  2590. // Execute immediately if ready is not present
  2591. selector( jQuery );
  2592. }
  2593. return jQuery.makeArray( selector, this );
  2594. };
  2595. // Give the init function the jQuery prototype for later instantiation
  2596. init.prototype = jQuery.fn;
  2597. // Initialize central reference
  2598. rootjQuery = jQuery( document );
  2599. var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  2600. // Methods guaranteed to produce a unique set when starting from a unique set
  2601. guaranteedUnique = {
  2602. children: true,
  2603. contents: true,
  2604. next: true,
  2605. prev: true
  2606. };
  2607. jQuery.fn.extend( {
  2608. has: function( target ) {
  2609. var targets = jQuery( target, this ),
  2610. l = targets.length;
  2611. return this.filter( function() {
  2612. var i = 0;
  2613. for ( ; i < l; i++ ) {
  2614. if ( jQuery.contains( this, targets[ i ] ) ) {
  2615. return true;
  2616. }
  2617. }
  2618. } );
  2619. },
  2620. closest: function( selectors, context ) {
  2621. var cur,
  2622. i = 0,
  2623. l = this.length,
  2624. matched = [],
  2625. targets = typeof selectors !== "string" && jQuery( selectors );
  2626. // Positional selectors never match, since there's no _selection_ context
  2627. if ( !rneedsContext.test( selectors ) ) {
  2628. for ( ; i < l; i++ ) {
  2629. for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
  2630. // Always skip document fragments
  2631. if ( cur.nodeType < 11 && ( targets ?
  2632. targets.index( cur ) > -1 :
  2633. // Don't pass non-elements to Sizzle
  2634. cur.nodeType === 1 &&
  2635. jQuery.find.matchesSelector( cur, selectors ) ) ) {
  2636. matched.push( cur );
  2637. break;
  2638. }
  2639. }
  2640. }
  2641. }
  2642. return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
  2643. },
  2644. // Determine the position of an element within the set
  2645. index: function( elem ) {
  2646. // No argument, return index in parent
  2647. if ( !elem ) {
  2648. return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  2649. }
  2650. // Index in selector
  2651. if ( typeof elem === "string" ) {
  2652. return indexOf.call( jQuery( elem ), this[ 0 ] );
  2653. }
  2654. // Locate the position of the desired element
  2655. return indexOf.call( this,
  2656. // If it receives a jQuery object, the first element is used
  2657. elem.jquery ? elem[ 0 ] : elem
  2658. );
  2659. },
  2660. add: function( selector, context ) {
  2661. return this.pushStack(
  2662. jQuery.uniqueSort(
  2663. jQuery.merge( this.get(), jQuery( selector, context ) )
  2664. )
  2665. );
  2666. },
  2667. addBack: function( selector ) {
  2668. return this.add( selector == null ?
  2669. this.prevObject : this.prevObject.filter( selector )
  2670. );
  2671. }
  2672. } );
  2673. function sibling( cur, dir ) {
  2674. while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
  2675. return cur;
  2676. }
  2677. jQuery.each( {
  2678. parent: function( elem ) {
  2679. var parent = elem.parentNode;
  2680. return parent && parent.nodeType !== 11 ? parent : null;
  2681. },
  2682. parents: function( elem ) {
  2683. return dir( elem, "parentNode" );
  2684. },
  2685. parentsUntil: function( elem, i, until ) {
  2686. return dir( elem, "parentNode", until );
  2687. },
  2688. next: function( elem ) {
  2689. return sibling( elem, "nextSibling" );
  2690. },
  2691. prev: function( elem ) {
  2692. return sibling( elem, "previousSibling" );
  2693. },
  2694. nextAll: function( elem ) {
  2695. return dir( elem, "nextSibling" );
  2696. },
  2697. prevAll: function( elem ) {
  2698. return dir( elem, "previousSibling" );
  2699. },
  2700. nextUntil: function( elem, i, until ) {
  2701. return dir( elem, "nextSibling", until );
  2702. },
  2703. prevUntil: function( elem, i, until ) {
  2704. return dir( elem, "previousSibling", until );
  2705. },
  2706. siblings: function( elem ) {
  2707. return siblings( ( elem.parentNode || {} ).firstChild, elem );
  2708. },
  2709. children: function( elem ) {
  2710. return siblings( elem.firstChild );
  2711. },
  2712. contents: function( elem ) {
  2713. if ( nodeName( elem, "iframe" ) ) {
  2714. return elem.contentDocument;
  2715. }
  2716. // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
  2717. // Treat the template element as a regular one in browsers that
  2718. // don't support it.
  2719. if ( nodeName( elem, "template" ) ) {
  2720. elem = elem.content || elem;
  2721. }
  2722. return jQuery.merge( [], elem.childNodes );
  2723. }
  2724. }, function( name, fn ) {
  2725. jQuery.fn[ name ] = function( until, selector ) {
  2726. var matched = jQuery.map( this, fn, until );
  2727. if ( name.slice( -5 ) !== "Until" ) {
  2728. selector = until;
  2729. }
  2730. if ( selector && typeof selector === "string" ) {
  2731. matched = jQuery.filter( selector, matched );
  2732. }
  2733. if ( this.length > 1 ) {
  2734. // Remove duplicates
  2735. if ( !guaranteedUnique[ name ] ) {
  2736. jQuery.uniqueSort( matched );
  2737. }
  2738. // Reverse order for parents* and prev-derivatives
  2739. if ( rparentsprev.test( name ) ) {
  2740. matched.reverse();
  2741. }
  2742. }
  2743. return this.pushStack( matched );
  2744. };
  2745. } );
  2746. var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
  2747. // Convert String-formatted options into Object-formatted ones
  2748. function createOptions( options ) {
  2749. var object = {};
  2750. jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
  2751. object[ flag ] = true;
  2752. } );
  2753. return object;
  2754. }
  2755. /*
  2756. * Create a callback list using the following parameters:
  2757. *
  2758. * options: an optional list of space-separated options that will change how
  2759. * the callback list behaves or a more traditional option object
  2760. *
  2761. * By default a callback list will act like an event callback list and can be
  2762. * "fired" multiple times.
  2763. *
  2764. * Possible options:
  2765. *
  2766. * once: will ensure the callback list can only be fired once (like a Deferred)
  2767. *
  2768. * memory: will keep track of previous values and will call any callback added
  2769. * after the list has been fired right away with the latest "memorized"
  2770. * values (like a Deferred)
  2771. *
  2772. * unique: will ensure a callback can only be added once (no duplicate in the list)
  2773. *
  2774. * stopOnFalse: interrupt callings when a callback returns false
  2775. *
  2776. */
  2777. jQuery.Callbacks = function( options ) {
  2778. // Convert options from String-formatted to Object-formatted if needed
  2779. // (we check in cache first)
  2780. options = typeof options === "string" ?
  2781. createOptions( options ) :
  2782. jQuery.extend( {}, options );
  2783. var // Flag to know if list is currently firing
  2784. firing,
  2785. // Last fire value for non-forgettable lists
  2786. memory,
  2787. // Flag to know if list was already fired
  2788. fired,
  2789. // Flag to prevent firing
  2790. locked,
  2791. // Actual callback list
  2792. list = [],
  2793. // Queue of execution data for repeatable lists
  2794. queue = [],
  2795. // Index of currently firing callback (modified by add/remove as needed)
  2796. firingIndex = -1,
  2797. // Fire callbacks
  2798. fire = function() {
  2799. // Enforce single-firing
  2800. locked = locked || options.once;
  2801. // Execute callbacks for all pending executions,
  2802. // respecting firingIndex overrides and runtime changes
  2803. fired = firing = true;
  2804. for ( ; queue.length; firingIndex = -1 ) {
  2805. memory = queue.shift();
  2806. while ( ++firingIndex < list.length ) {
  2807. // Run callback and check for early termination
  2808. if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
  2809. options.stopOnFalse ) {
  2810. // Jump to end and forget the data so .add doesn't re-fire
  2811. firingIndex = list.length;
  2812. memory = false;
  2813. }
  2814. }
  2815. }
  2816. // Forget the data if we're done with it
  2817. if ( !options.memory ) {
  2818. memory = false;
  2819. }
  2820. firing = false;
  2821. // Clean up if we're done firing for good
  2822. if ( locked ) {
  2823. // Keep an empty list if we have data for future add calls
  2824. if ( memory ) {
  2825. list = [];
  2826. // Otherwise, this object is spent
  2827. } else {
  2828. list = "";
  2829. }
  2830. }
  2831. },
  2832. // Actual Callbacks object
  2833. self = {
  2834. // Add a callback or a collection of callbacks to the list
  2835. add: function() {
  2836. if ( list ) {
  2837. // If we have memory from a past run, we should fire after adding
  2838. if ( memory && !firing ) {
  2839. firingIndex = list.length - 1;
  2840. queue.push( memory );
  2841. }
  2842. ( function add( args ) {
  2843. jQuery.each( args, function( _, arg ) {
  2844. if ( jQuery.isFunction( arg ) ) {
  2845. if ( !options.unique || !self.has( arg ) ) {
  2846. list.push( arg );
  2847. }
  2848. } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
  2849. // Inspect recursively
  2850. add( arg );
  2851. }
  2852. } );
  2853. } )( arguments );
  2854. if ( memory && !firing ) {
  2855. fire();
  2856. }
  2857. }
  2858. return this;
  2859. },
  2860. // Remove a callback from the list
  2861. remove: function() {
  2862. jQuery.each( arguments, function( _, arg ) {
  2863. var index;
  2864. while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
  2865. list.splice( index, 1 );
  2866. // Handle firing indexes
  2867. if ( index <= firingIndex ) {
  2868. firingIndex--;
  2869. }
  2870. }
  2871. } );
  2872. return this;
  2873. },
  2874. // Check if a given callback is in the list.
  2875. // If no argument is given, return whether or not list has callbacks attached.
  2876. has: function( fn ) {
  2877. return fn ?
  2878. jQuery.inArray( fn, list ) > -1 :
  2879. list.length > 0;
  2880. },
  2881. // Remove all callbacks from the list
  2882. empty: function() {
  2883. if ( list ) {
  2884. list = [];
  2885. }
  2886. return this;
  2887. },
  2888. // Disable .fire and .add
  2889. // Abort any current/pending executions
  2890. // Clear all callbacks and values
  2891. disable: function() {
  2892. locked = queue = [];
  2893. list = memory = "";
  2894. return this;
  2895. },
  2896. disabled: function() {
  2897. return !list;
  2898. },
  2899. // Disable .fire
  2900. // Also disable .add unless we have memory (since it would have no effect)
  2901. // Abort any pending executions
  2902. lock: function() {
  2903. locked = queue = [];
  2904. if ( !memory && !firing ) {
  2905. list = memory = "";
  2906. }
  2907. return this;
  2908. },
  2909. locked: function() {
  2910. return !!locked;
  2911. },
  2912. // Call all callbacks with the given context and arguments
  2913. fireWith: function( context, args ) {
  2914. if ( !locked ) {
  2915. args = args || [];
  2916. args = [ context, args.slice ? args.slice() : args ];
  2917. queue.push( args );
  2918. if ( !firing ) {
  2919. fire();
  2920. }
  2921. }
  2922. return this;
  2923. },
  2924. // Call all the callbacks with the given arguments
  2925. fire: function() {
  2926. self.fireWith( this, arguments );
  2927. return this;
  2928. },
  2929. // To know if the callbacks have already been called at least once
  2930. fired: function() {
  2931. return !!fired;
  2932. }
  2933. };
  2934. return self;
  2935. };
  2936. function Identity( v ) {
  2937. return v;
  2938. }
  2939. function Thrower( ex ) {
  2940. throw ex;
  2941. }
  2942. function adoptValue( value, resolve, reject, noValue ) {
  2943. var method;
  2944. try {
  2945. // Check for promise aspect first to privilege synchronous behavior
  2946. if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
  2947. method.call( value ).done( resolve ).fail( reject );
  2948. // Other thenables
  2949. } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
  2950. method.call( value, resolve, reject );
  2951. // Other non-thenables
  2952. } else {
  2953. // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
  2954. // * false: [ value ].slice( 0 ) => resolve( value )
  2955. // * true: [ value ].slice( 1 ) => resolve()
  2956. resolve.apply( undefined, [ value ].slice( noValue ) );
  2957. }
  2958. // For Promises/A+, convert exceptions into rejections
  2959. // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
  2960. // Deferred#then to conditionally suppress rejection.
  2961. } catch ( value ) {
  2962. // Support: Android 4.0 only
  2963. // Strict mode functions invoked without .call/.apply get global-object context
  2964. reject.apply( undefined, [ value ] );
  2965. }
  2966. }
  2967. jQuery.extend( {
  2968. Deferred: function( func ) {
  2969. var tuples = [
  2970. // action, add listener, callbacks,
  2971. // ... .then handlers, argument index, [final state]
  2972. [ "notify", "progress", jQuery.Callbacks( "memory" ),
  2973. jQuery.Callbacks( "memory" ), 2 ],
  2974. [ "resolve", "done", jQuery.Callbacks( "once memory" ),
  2975. jQuery.Callbacks( "once memory" ), 0, "resolved" ],
  2976. [ "reject", "fail", jQuery.Callbacks( "once memory" ),
  2977. jQuery.Callbacks( "once memory" ), 1, "rejected" ]
  2978. ],
  2979. state = "pending",
  2980. promise = {
  2981. state: function() {
  2982. return state;
  2983. },
  2984. always: function() {
  2985. deferred.done( arguments ).fail( arguments );
  2986. return this;
  2987. },
  2988. "catch": function( fn ) {
  2989. return promise.then( null, fn );
  2990. },
  2991. // Keep pipe for back-compat
  2992. pipe: function( /* fnDone, fnFail, fnProgress */ ) {
  2993. var fns = arguments;
  2994. return jQuery.Deferred( function( newDefer ) {
  2995. jQuery.each( tuples, function( i, tuple ) {
  2996. // Map tuples (progress, done, fail) to arguments (done, fail, progress)
  2997. var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
  2998. // deferred.progress(function() { bind to newDefer or newDefer.notify })
  2999. // deferred.done(function() { bind to newDefer or newDefer.resolve })
  3000. // deferred.fail(function() { bind to newDefer or newDefer.reject })
  3001. deferred[ tuple[ 1 ] ]( function() {
  3002. var returned = fn && fn.apply( this, arguments );
  3003. if ( returned && jQuery.isFunction( returned.promise ) ) {
  3004. returned.promise()
  3005. .progress( newDefer.notify )
  3006. .done( newDefer.resolve )
  3007. .fail( newDefer.reject );
  3008. } else {
  3009. newDefer[ tuple[ 0 ] + "With" ](
  3010. this,
  3011. fn ? [ returned ] : arguments
  3012. );
  3013. }
  3014. } );
  3015. } );
  3016. fns = null;
  3017. } ).promise();
  3018. },
  3019. then: function( onFulfilled, onRejected, onProgress ) {
  3020. var maxDepth = 0;
  3021. function resolve( depth, deferred, handler, special ) {
  3022. return function() {
  3023. var that = this,
  3024. args = arguments,
  3025. mightThrow = function() {
  3026. var returned, then;
  3027. // Support: Promises/A+ section 2.3.3.3.3
  3028. // https://promisesaplus.com/#point-59
  3029. // Ignore double-resolution attempts
  3030. if ( depth < maxDepth ) {
  3031. return;
  3032. }
  3033. returned = handler.apply( that, args );
  3034. // Support: Promises/A+ section 2.3.1
  3035. // https://promisesaplus.com/#point-48
  3036. if ( returned === deferred.promise() ) {
  3037. throw new TypeError( "Thenable self-resolution" );
  3038. }
  3039. // Support: Promises/A+ sections 2.3.3.1, 3.5
  3040. // https://promisesaplus.com/#point-54
  3041. // https://promisesaplus.com/#point-75
  3042. // Retrieve `then` only once
  3043. then = returned &&
  3044. // Support: Promises/A+ section 2.3.4
  3045. // https://promisesaplus.com/#point-64
  3046. // Only check objects and functions for thenability
  3047. ( typeof returned === "object" ||
  3048. typeof returned === "function" ) &&
  3049. returned.then;
  3050. // Handle a returned thenable
  3051. if ( jQuery.isFunction( then ) ) {
  3052. // Special processors (notify) just wait for resolution
  3053. if ( special ) {
  3054. then.call(
  3055. returned,
  3056. resolve( maxDepth, deferred, Identity, special ),
  3057. resolve( maxDepth, deferred, Thrower, special )
  3058. );
  3059. // Normal processors (resolve) also hook into progress
  3060. } else {
  3061. // ...and disregard older resolution values
  3062. maxDepth++;
  3063. then.call(
  3064. returned,
  3065. resolve( maxDepth, deferred, Identity, special ),
  3066. resolve( maxDepth, deferred, Thrower, special ),
  3067. resolve( maxDepth, deferred, Identity,
  3068. deferred.notifyWith )
  3069. );
  3070. }
  3071. // Handle all other returned values
  3072. } else {
  3073. // Only substitute handlers pass on context
  3074. // and multiple values (non-spec behavior)
  3075. if ( handler !== Identity ) {
  3076. that = undefined;
  3077. args = [ returned ];
  3078. }
  3079. // Process the value(s)
  3080. // Default process is resolve
  3081. ( special || deferred.resolveWith )( that, args );
  3082. }
  3083. },
  3084. // Only normal processors (resolve) catch and reject exceptions
  3085. process = special ?
  3086. mightThrow :
  3087. function() {
  3088. try {
  3089. mightThrow();
  3090. } catch ( e ) {
  3091. if ( jQuery.Deferred.exceptionHook ) {
  3092. jQuery.Deferred.exceptionHook( e,
  3093. process.stackTrace );
  3094. }
  3095. // Support: Promises/A+ section 2.3.3.3.4.1
  3096. // https://promisesaplus.com/#point-61
  3097. // Ignore post-resolution exceptions
  3098. if ( depth + 1 >= maxDepth ) {
  3099. // Only substitute handlers pass on context
  3100. // and multiple values (non-spec behavior)
  3101. if ( handler !== Thrower ) {
  3102. that = undefined;
  3103. args = [ e ];
  3104. }
  3105. deferred.rejectWith( that, args );
  3106. }
  3107. }
  3108. };
  3109. // Support: Promises/A+ section 2.3.3.3.1
  3110. // https://promisesaplus.com/#point-57
  3111. // Re-resolve promises immediately to dodge false rejection from
  3112. // subsequent errors
  3113. if ( depth ) {
  3114. process();
  3115. } else {
  3116. // Call an optional hook to record the stack, in case of exception
  3117. // since it's otherwise lost when execution goes async
  3118. if ( jQuery.Deferred.getStackHook ) {
  3119. process.stackTrace = jQuery.Deferred.getStackHook();
  3120. }
  3121. window.setTimeout( process );
  3122. }
  3123. };
  3124. }
  3125. return jQuery.Deferred( function( newDefer ) {
  3126. // progress_handlers.add( ... )
  3127. tuples[ 0 ][ 3 ].add(
  3128. resolve(
  3129. 0,
  3130. newDefer,
  3131. jQuery.isFunction( onProgress ) ?
  3132. onProgress :
  3133. Identity,
  3134. newDefer.notifyWith
  3135. )
  3136. );
  3137. // fulfilled_handlers.add( ... )
  3138. tuples[ 1 ][ 3 ].add(
  3139. resolve(
  3140. 0,
  3141. newDefer,
  3142. jQuery.isFunction( onFulfilled ) ?
  3143. onFulfilled :
  3144. Identity
  3145. )
  3146. );
  3147. // rejected_handlers.add( ... )
  3148. tuples[ 2 ][ 3 ].add(
  3149. resolve(
  3150. 0,
  3151. newDefer,
  3152. jQuery.isFunction( onRejected ) ?
  3153. onRejected :
  3154. Thrower
  3155. )
  3156. );
  3157. } ).promise();
  3158. },
  3159. // Get a promise for this deferred
  3160. // If obj is provided, the promise aspect is added to the object
  3161. promise: function( obj ) {
  3162. return obj != null ? jQuery.extend( obj, promise ) : promise;
  3163. }
  3164. },
  3165. deferred = {};
  3166. // Add list-specific methods
  3167. jQuery.each( tuples, function( i, tuple ) {
  3168. var list = tuple[ 2 ],
  3169. stateString = tuple[ 5 ];
  3170. // promise.progress = list.add
  3171. // promise.done = list.add
  3172. // promise.fail = list.add
  3173. promise[ tuple[ 1 ] ] = list.add;
  3174. // Handle state
  3175. if ( stateString ) {
  3176. list.add(
  3177. function() {
  3178. // state = "resolved" (i.e., fulfilled)
  3179. // state = "rejected"
  3180. state = stateString;
  3181. },
  3182. // rejected_callbacks.disable
  3183. // fulfilled_callbacks.disable
  3184. tuples[ 3 - i ][ 2 ].disable,
  3185. // progress_callbacks.lock
  3186. tuples[ 0 ][ 2 ].lock
  3187. );
  3188. }
  3189. // progress_handlers.fire
  3190. // fulfilled_handlers.fire
  3191. // rejected_handlers.fire
  3192. list.add( tuple[ 3 ].fire );
  3193. // deferred.notify = function() { deferred.notifyWith(...) }
  3194. // deferred.resolve = function() { deferred.resolveWith(...) }
  3195. // deferred.reject = function() { deferred.rejectWith(...) }
  3196. deferred[ tuple[ 0 ] ] = function() {
  3197. deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
  3198. return this;
  3199. };
  3200. // deferred.notifyWith = list.fireWith
  3201. // deferred.resolveWith = list.fireWith
  3202. // deferred.rejectWith = list.fireWith
  3203. deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
  3204. } );
  3205. // Make the deferred a promise
  3206. promise.promise( deferred );
  3207. // Call given func if any
  3208. if ( func ) {
  3209. func.call( deferred, deferred );
  3210. }
  3211. // All done!
  3212. return deferred;
  3213. },
  3214. // Deferred helper
  3215. when: function( singleValue ) {
  3216. var
  3217. // count of uncompleted subordinates
  3218. remaining = arguments.length,
  3219. // count of unprocessed arguments
  3220. i = remaining,
  3221. // subordinate fulfillment data
  3222. resolveContexts = Array( i ),
  3223. resolveValues = slice.call( arguments ),
  3224. // the master Deferred
  3225. master = jQuery.Deferred(),
  3226. // subordinate callback factory
  3227. updateFunc = function( i ) {
  3228. return function( value ) {
  3229. resolveContexts[ i ] = this;
  3230. resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
  3231. if ( !( --remaining ) ) {
  3232. master.resolveWith( resolveContexts, resolveValues );
  3233. }
  3234. };
  3235. };
  3236. // Single- and empty arguments are adopted like Promise.resolve
  3237. if ( remaining <= 1 ) {
  3238. adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
  3239. !remaining );
  3240. // Use .then() to unwrap secondary thenables (cf. gh-3000)
  3241. if ( master.state() === "pending" ||
  3242. jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
  3243. return master.then();
  3244. }
  3245. }
  3246. // Multiple arguments are aggregated like Promise.all array elements
  3247. while ( i-- ) {
  3248. adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
  3249. }
  3250. return master.promise();
  3251. }
  3252. } );
  3253. // These usually indicate a programmer mistake during development,
  3254. // warn about them ASAP rather than swallowing them by default.
  3255. var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
  3256. jQuery.Deferred.exceptionHook = function( error, stack ) {
  3257. // Support: IE 8 - 9 only
  3258. // Console exists when dev tools are open, which can happen at any time
  3259. if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
  3260. window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
  3261. }
  3262. };
  3263. jQuery.readyException = function( error ) {
  3264. window.setTimeout( function() {
  3265. throw error;
  3266. } );
  3267. };
  3268. // The deferred used on DOM ready
  3269. var readyList = jQuery.Deferred();
  3270. jQuery.fn.ready = function( fn ) {
  3271. readyList
  3272. .then( fn )
  3273. // Wrap jQuery.readyException in a function so that the lookup
  3274. // happens at the time of error handling instead of callback
  3275. // registration.
  3276. .catch( function( error ) {
  3277. jQuery.readyException( error );
  3278. } );
  3279. return this;
  3280. };
  3281. jQuery.extend( {
  3282. // Is the DOM ready to be used? Set to true once it occurs.
  3283. isReady: false,
  3284. // A counter to track how many items to wait for before
  3285. // the ready event fires. See #6781
  3286. readyWait: 1,
  3287. // Handle when the DOM is ready
  3288. ready: function( wait ) {
  3289. // Abort if there are pending holds or we're already ready
  3290. if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
  3291. return;
  3292. }
  3293. // Remember that the DOM is ready
  3294. jQuery.isReady = true;
  3295. // If a normal DOM Ready event fired, decrement, and wait if need be
  3296. if ( wait !== true && --jQuery.readyWait > 0 ) {
  3297. return;
  3298. }
  3299. // If there are functions bound, to execute
  3300. readyList.resolveWith( document, [ jQuery ] );
  3301. }
  3302. } );
  3303. jQuery.ready.then = readyList.then;
  3304. // The ready event handler and self cleanup method
  3305. function completed() {
  3306. document.removeEventListener( "DOMContentLoaded", completed );
  3307. window.removeEventListener( "load", completed );
  3308. jQuery.ready();
  3309. }
  3310. // Catch cases where $(document).ready() is called
  3311. // after the browser event has already occurred.
  3312. // Support: IE <=9 - 10 only
  3313. // Older IE sometimes signals "interactive" too soon
  3314. if ( document.readyState === "complete" ||
  3315. ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
  3316. // Handle it asynchronously to allow scripts the opportunity to delay ready
  3317. window.setTimeout( jQuery.ready );
  3318. } else {
  3319. // Use the handy event callback
  3320. document.addEventListener( "DOMContentLoaded", completed );
  3321. // A fallback to window.onload, that will always work
  3322. window.addEventListener( "load", completed );
  3323. }
  3324. // Multifunctional method to get and set values of a collection
  3325. // The value/s can optionally be executed if it's a function
  3326. var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
  3327. var i = 0,
  3328. len = elems.length,
  3329. bulk = key == null;
  3330. // Sets many values
  3331. if ( jQuery.type( key ) === "object" ) {
  3332. chainable = true;
  3333. for ( i in key ) {
  3334. access( elems, fn, i, key[ i ], true, emptyGet, raw );
  3335. }
  3336. // Sets one value
  3337. } else if ( value !== undefined ) {
  3338. chainable = true;
  3339. if ( !jQuery.isFunction( value ) ) {
  3340. raw = true;
  3341. }
  3342. if ( bulk ) {
  3343. // Bulk operations run against the entire set
  3344. if ( raw ) {
  3345. fn.call( elems, value );
  3346. fn = null;
  3347. // ...except when executing function values
  3348. } else {
  3349. bulk = fn;
  3350. fn = function( elem, key, value ) {
  3351. return bulk.call( jQuery( elem ), value );
  3352. };
  3353. }
  3354. }
  3355. if ( fn ) {
  3356. for ( ; i < len; i++ ) {
  3357. fn(
  3358. elems[ i ], key, raw ?
  3359. value :
  3360. value.call( elems[ i ], i, fn( elems[ i ], key ) )
  3361. );
  3362. }
  3363. }
  3364. }
  3365. if ( chainable ) {
  3366. return elems;
  3367. }
  3368. // Gets
  3369. if ( bulk ) {
  3370. return fn.call( elems );
  3371. }
  3372. return len ? fn( elems[ 0 ], key ) : emptyGet;
  3373. };
  3374. var acceptData = function( owner ) {
  3375. // Accepts only:
  3376. // - Node
  3377. // - Node.ELEMENT_NODE
  3378. // - Node.DOCUMENT_NODE
  3379. // - Object
  3380. // - Any
  3381. return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
  3382. };
  3383. function Data() {
  3384. this.expando = jQuery.expando + Data.uid++;
  3385. }
  3386. Data.uid = 1;
  3387. Data.prototype = {
  3388. cache: function( owner ) {
  3389. // Check if the owner object already has a cache
  3390. var value = owner[ this.expando ];
  3391. // If not, create one
  3392. if ( !value ) {
  3393. value = {};
  3394. // We can accept data for non-element nodes in modern browsers,
  3395. // but we should not, see #8335.
  3396. // Always return an empty object.
  3397. if ( acceptData( owner ) ) {
  3398. // If it is a node unlikely to be stringify-ed or looped over
  3399. // use plain assignment
  3400. if ( owner.nodeType ) {
  3401. owner[ this.expando ] = value;
  3402. // Otherwise secure it in a non-enumerable property
  3403. // configurable must be true to allow the property to be
  3404. // deleted when data is removed
  3405. } else {
  3406. Object.defineProperty( owner, this.expando, {
  3407. value: value,
  3408. configurable: true
  3409. } );
  3410. }
  3411. }
  3412. }
  3413. return value;
  3414. },
  3415. set: function( owner, data, value ) {
  3416. var prop,
  3417. cache = this.cache( owner );
  3418. // Handle: [ owner, key, value ] args
  3419. // Always use camelCase key (gh-2257)
  3420. if ( typeof data === "string" ) {
  3421. cache[ jQuery.camelCase( data ) ] = value;
  3422. // Handle: [ owner, { properties } ] args
  3423. } else {
  3424. // Copy the properties one-by-one to the cache object
  3425. for ( prop in data ) {
  3426. cache[ jQuery.camelCase( prop ) ] = data[ prop ];
  3427. }
  3428. }
  3429. return cache;
  3430. },
  3431. get: function( owner, key ) {
  3432. return key === undefined ?
  3433. this.cache( owner ) :
  3434. // Always use camelCase key (gh-2257)
  3435. owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
  3436. },
  3437. access: function( owner, key, value ) {
  3438. // In cases where either:
  3439. //
  3440. // 1. No key was specified
  3441. // 2. A string key was specified, but no value provided
  3442. //
  3443. // Take the "read" path and allow the get method to determine
  3444. // which value to return, respectively either:
  3445. //
  3446. // 1. The entire cache object
  3447. // 2. The data stored at the key
  3448. //
  3449. if ( key === undefined ||
  3450. ( ( key && typeof key === "string" ) && value === undefined ) ) {
  3451. return this.get( owner, key );
  3452. }
  3453. // When the key is not a string, or both a key and value
  3454. // are specified, set or extend (existing objects) with either:
  3455. //
  3456. // 1. An object of properties
  3457. // 2. A key and value
  3458. //
  3459. this.set( owner, key, value );
  3460. // Since the "set" path can have two possible entry points
  3461. // return the expected data based on which path was taken[*]
  3462. return value !== undefined ? value : key;
  3463. },
  3464. remove: function( owner, key ) {
  3465. var i,
  3466. cache = owner[ this.expando ];
  3467. if ( cache === undefined ) {
  3468. return;
  3469. }
  3470. if ( key !== undefined ) {
  3471. // Support array or space separated string of keys
  3472. if ( Array.isArray( key ) ) {
  3473. // If key is an array of keys...
  3474. // We always set camelCase keys, so remove that.
  3475. key = key.map( jQuery.camelCase );
  3476. } else {
  3477. key = jQuery.camelCase( key );
  3478. // If a key with the spaces exists, use it.
  3479. // Otherwise, create an array by matching non-whitespace
  3480. key = key in cache ?
  3481. [ key ] :
  3482. ( key.match( rnothtmlwhite ) || [] );
  3483. }
  3484. i = key.length;
  3485. while ( i-- ) {
  3486. delete cache[ key[ i ] ];
  3487. }
  3488. }
  3489. // Remove the expando if there's no more data
  3490. if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
  3491. // Support: Chrome <=35 - 45
  3492. // Webkit & Blink performance suffers when deleting properties
  3493. // from DOM nodes, so set to undefined instead
  3494. // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
  3495. if ( owner.nodeType ) {
  3496. owner[ this.expando ] = undefined;
  3497. } else {
  3498. delete owner[ this.expando ];
  3499. }
  3500. }
  3501. },
  3502. hasData: function( owner ) {
  3503. var cache = owner[ this.expando ];
  3504. return cache !== undefined && !jQuery.isEmptyObject( cache );
  3505. }
  3506. };
  3507. var dataPriv = new Data();
  3508. var dataUser = new Data();
  3509. // Implementation Summary
  3510. //
  3511. // 1. Enforce API surface and semantic compatibility with 1.9.x branch
  3512. // 2. Improve the module's maintainability by reducing the storage
  3513. // paths to a single mechanism.
  3514. // 3. Use the same single mechanism to support "private" and "user" data.
  3515. // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  3516. // 5. Avoid exposing implementation details on user objects (eg. expando properties)
  3517. // 6. Provide a clear path for implementation upgrade to WeakMap in 2014
  3518. var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  3519. rmultiDash = /[A-Z]/g;
  3520. function getData( data ) {
  3521. if ( data === "true" ) {
  3522. return true;
  3523. }
  3524. if ( data === "false" ) {
  3525. return false;
  3526. }
  3527. if ( data === "null" ) {
  3528. return null;
  3529. }
  3530. // Only convert to a number if it doesn't change the string
  3531. if ( data === +data + "" ) {
  3532. return +data;
  3533. }
  3534. if ( rbrace.test( data ) ) {
  3535. return JSON.parse( data );
  3536. }
  3537. return data;
  3538. }
  3539. function dataAttr( elem, key, data ) {
  3540. var name;
  3541. // If nothing was found internally, try to fetch any
  3542. // data from the HTML5 data-* attribute
  3543. if ( data === undefined && elem.nodeType === 1 ) {
  3544. name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
  3545. data = elem.getAttribute( name );
  3546. if ( typeof data === "string" ) {
  3547. try {
  3548. data = getData( data );
  3549. } catch ( e ) {}
  3550. // Make sure we set the data so it isn't changed later
  3551. dataUser.set( elem, key, data );
  3552. } else {
  3553. data = undefined;
  3554. }
  3555. }
  3556. return data;
  3557. }
  3558. jQuery.extend( {
  3559. hasData: function( elem ) {
  3560. return dataUser.hasData( elem ) || dataPriv.hasData( elem );
  3561. },
  3562. data: function( elem, name, data ) {
  3563. return dataUser.access( elem, name, data );
  3564. },
  3565. removeData: function( elem, name ) {
  3566. dataUser.remove( elem, name );
  3567. },
  3568. // TODO: Now that all calls to _data and _removeData have been replaced
  3569. // with direct calls to dataPriv methods, these can be deprecated.
  3570. _data: function( elem, name, data ) {
  3571. return dataPriv.access( elem, name, data );
  3572. },
  3573. _removeData: function( elem, name ) {
  3574. dataPriv.remove( elem, name );
  3575. }
  3576. } );
  3577. jQuery.fn.extend( {
  3578. data: function( key, value ) {
  3579. var i, name, data,
  3580. elem = this[ 0 ],
  3581. attrs = elem && elem.attributes;
  3582. // Gets all values
  3583. if ( key === undefined ) {
  3584. if ( this.length ) {
  3585. data = dataUser.get( elem );
  3586. if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
  3587. i = attrs.length;
  3588. while ( i-- ) {
  3589. // Support: IE 11 only
  3590. // The attrs elements can be null (#14894)
  3591. if ( attrs[ i ] ) {
  3592. name = attrs[ i ].name;
  3593. if ( name.indexOf( "data-" ) === 0 ) {
  3594. name = jQuery.camelCase( name.slice( 5 ) );
  3595. dataAttr( elem, name, data[ name ] );
  3596. }
  3597. }
  3598. }
  3599. dataPriv.set( elem, "hasDataAttrs", true );
  3600. }
  3601. }
  3602. return data;
  3603. }
  3604. // Sets multiple values
  3605. if ( typeof key === "object" ) {
  3606. return this.each( function() {
  3607. dataUser.set( this, key );
  3608. } );
  3609. }
  3610. return access( this, function( value ) {
  3611. var data;
  3612. // The calling jQuery object (element matches) is not empty
  3613. // (and therefore has an element appears at this[ 0 ]) and the
  3614. // `value` parameter was not undefined. An empty jQuery object
  3615. // will result in `undefined` for elem = this[ 0 ] which will
  3616. // throw an exception if an attempt to read a data cache is made.
  3617. if ( elem && value === undefined ) {
  3618. // Attempt to get data from the cache
  3619. // The key will always be camelCased in Data
  3620. data = dataUser.get( elem, key );
  3621. if ( data !== undefined ) {
  3622. return data;
  3623. }
  3624. // Attempt to "discover" the data in
  3625. // HTML5 custom data-* attrs
  3626. data = dataAttr( elem, key );
  3627. if ( data !== undefined ) {
  3628. return data;
  3629. }
  3630. // We tried really hard, but the data doesn't exist.
  3631. return;
  3632. }
  3633. // Set the data...
  3634. this.each( function() {
  3635. // We always store the camelCased key
  3636. dataUser.set( this, key, value );
  3637. } );
  3638. }, null, value, arguments.length > 1, null, true );
  3639. },
  3640. removeData: function( key ) {
  3641. return this.each( function() {
  3642. dataUser.remove( this, key );
  3643. } );
  3644. }
  3645. } );
  3646. jQuery.extend( {
  3647. queue: function( elem, type, data ) {
  3648. var queue;
  3649. if ( elem ) {
  3650. type = ( type || "fx" ) + "queue";
  3651. queue = dataPriv.get( elem, type );
  3652. // Speed up dequeue by getting out quickly if this is just a lookup
  3653. if ( data ) {
  3654. if ( !queue || Array.isArray( data ) ) {
  3655. queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
  3656. } else {
  3657. queue.push( data );
  3658. }
  3659. }
  3660. return queue || [];
  3661. }
  3662. },
  3663. dequeue: function( elem, type ) {
  3664. type = type || "fx";
  3665. var queue = jQuery.queue( elem, type ),
  3666. startLength = queue.length,
  3667. fn = queue.shift(),
  3668. hooks = jQuery._queueHooks( elem, type ),
  3669. next = function() {
  3670. jQuery.dequeue( elem, type );
  3671. };
  3672. // If the fx queue is dequeued, always remove the progress sentinel
  3673. if ( fn === "inprogress" ) {
  3674. fn = queue.shift();
  3675. startLength--;
  3676. }
  3677. if ( fn ) {
  3678. // Add a progress sentinel to prevent the fx queue from being
  3679. // automatically dequeued
  3680. if ( type === "fx" ) {
  3681. queue.unshift( "inprogress" );
  3682. }
  3683. // Clear up the last queue stop function
  3684. delete hooks.stop;
  3685. fn.call( elem, next, hooks );
  3686. }
  3687. if ( !startLength && hooks ) {
  3688. hooks.empty.fire();
  3689. }
  3690. },
  3691. // Not public - generate a queueHooks object, or return the current one
  3692. _queueHooks: function( elem, type ) {
  3693. var key = type + "queueHooks";
  3694. return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
  3695. empty: jQuery.Callbacks( "once memory" ).add( function() {
  3696. dataPriv.remove( elem, [ type + "queue", key ] );
  3697. } )
  3698. } );
  3699. }
  3700. } );
  3701. jQuery.fn.extend( {
  3702. queue: function( type, data ) {
  3703. var setter = 2;
  3704. if ( typeof type !== "string" ) {
  3705. data = type;
  3706. type = "fx";
  3707. setter--;
  3708. }
  3709. if ( arguments.length < setter ) {
  3710. return jQuery.queue( this[ 0 ], type );
  3711. }
  3712. return data === undefined ?
  3713. this :
  3714. this.each( function() {
  3715. var queue = jQuery.queue( this, type, data );
  3716. // Ensure a hooks for this queue
  3717. jQuery._queueHooks( this, type );
  3718. if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
  3719. jQuery.dequeue( this, type );
  3720. }
  3721. } );
  3722. },
  3723. dequeue: function( type ) {
  3724. return this.each( function() {
  3725. jQuery.dequeue( this, type );
  3726. } );
  3727. },
  3728. clearQueue: function( type ) {
  3729. return this.queue( type || "fx", [] );
  3730. },
  3731. // Get a promise resolved when queues of a certain type
  3732. // are emptied (fx is the type by default)
  3733. promise: function( type, obj ) {
  3734. var tmp,
  3735. count = 1,
  3736. defer = jQuery.Deferred(),
  3737. elements = this,
  3738. i = this.length,
  3739. resolve = function() {
  3740. if ( !( --count ) ) {
  3741. defer.resolveWith( elements, [ elements ] );
  3742. }
  3743. };
  3744. if ( typeof type !== "string" ) {
  3745. obj = type;
  3746. type = undefined;
  3747. }
  3748. type = type || "fx";
  3749. while ( i-- ) {
  3750. tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
  3751. if ( tmp && tmp.empty ) {
  3752. count++;
  3753. tmp.empty.add( resolve );
  3754. }
  3755. }
  3756. resolve();
  3757. return defer.promise( obj );
  3758. }
  3759. } );
  3760. var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
  3761. var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
  3762. var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
  3763. var isHiddenWithinTree = function( elem, el ) {
  3764. // isHiddenWithinTree might be called from jQuery#filter function;
  3765. // in that case, element will be second argument
  3766. elem = el || elem;
  3767. // Inline style trumps all
  3768. return elem.style.display === "none" ||
  3769. elem.style.display === "" &&
  3770. // Otherwise, check computed style
  3771. // Support: Firefox <=43 - 45
  3772. // Disconnected elements can have computed display: none, so first confirm that elem is
  3773. // in the document.
  3774. jQuery.contains( elem.ownerDocument, elem ) &&
  3775. jQuery.css( elem, "display" ) === "none";
  3776. };
  3777. var swap = function( elem, options, callback, args ) {
  3778. var ret, name,
  3779. old = {};
  3780. // Remember the old values, and insert the new ones
  3781. for ( name in options ) {
  3782. old[ name ] = elem.style[ name ];
  3783. elem.style[ name ] = options[ name ];
  3784. }
  3785. ret = callback.apply( elem, args || [] );
  3786. // Revert the old values
  3787. for ( name in options ) {
  3788. elem.style[ name ] = old[ name ];
  3789. }
  3790. return ret;
  3791. };
  3792. function adjustCSS( elem, prop, valueParts, tween ) {
  3793. var adjusted,
  3794. scale = 1,
  3795. maxIterations = 20,
  3796. currentValue = tween ?
  3797. function() {
  3798. return tween.cur();
  3799. } :
  3800. function() {
  3801. return jQuery.css( elem, prop, "" );
  3802. },
  3803. initial = currentValue(),
  3804. unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
  3805. // Starting value computation is required for potential unit mismatches
  3806. initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
  3807. rcssNum.exec( jQuery.css( elem, prop ) );
  3808. if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
  3809. // Trust units reported by jQuery.css
  3810. unit = unit || initialInUnit[ 3 ];
  3811. // Make sure we update the tween properties later on
  3812. valueParts = valueParts || [];
  3813. // Iteratively approximate from a nonzero starting point
  3814. initialInUnit = +initial || 1;
  3815. do {
  3816. // If previous iteration zeroed out, double until we get *something*.
  3817. // Use string for doubling so we don't accidentally see scale as unchanged below
  3818. scale = scale || ".5";
  3819. // Adjust and apply
  3820. initialInUnit = initialInUnit / scale;
  3821. jQuery.style( elem, prop, initialInUnit + unit );
  3822. // Update scale, tolerating zero or NaN from tween.cur()
  3823. // Break the loop if scale is unchanged or perfect, or if we've just had enough.
  3824. } while (
  3825. scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
  3826. );
  3827. }
  3828. if ( valueParts ) {
  3829. initialInUnit = +initialInUnit || +initial || 0;
  3830. // Apply relative offset (+=/-=) if specified
  3831. adjusted = valueParts[ 1 ] ?
  3832. initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
  3833. +valueParts[ 2 ];
  3834. if ( tween ) {
  3835. tween.unit = unit;
  3836. tween.start = initialInUnit;
  3837. tween.end = adjusted;
  3838. }
  3839. }
  3840. return adjusted;
  3841. }
  3842. var defaultDisplayMap = {};
  3843. function getDefaultDisplay( elem ) {
  3844. var temp,
  3845. doc = elem.ownerDocument,
  3846. nodeName = elem.nodeName,
  3847. display = defaultDisplayMap[ nodeName ];
  3848. if ( display ) {
  3849. return display;
  3850. }
  3851. temp = doc.body.appendChild( doc.createElement( nodeName ) );
  3852. display = jQuery.css( temp, "display" );
  3853. temp.parentNode.removeChild( temp );
  3854. if ( display === "none" ) {
  3855. display = "block";
  3856. }
  3857. defaultDisplayMap[ nodeName ] = display;
  3858. return display;
  3859. }
  3860. function showHide( elements, show ) {
  3861. var display, elem,
  3862. values = [],
  3863. index = 0,
  3864. length = elements.length;
  3865. // Determine new display value for elements that need to change
  3866. for ( ; index < length; index++ ) {
  3867. elem = elements[ index ];
  3868. if ( !elem.style ) {
  3869. continue;
  3870. }
  3871. display = elem.style.display;
  3872. if ( show ) {
  3873. // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
  3874. // check is required in this first loop unless we have a nonempty display value (either
  3875. // inline or about-to-be-restored)
  3876. if ( display === "none" ) {
  3877. values[ index ] = dataPriv.get( elem, "display" ) || null;
  3878. if ( !values[ index ] ) {
  3879. elem.style.display = "";
  3880. }
  3881. }
  3882. if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
  3883. values[ index ] = getDefaultDisplay( elem );
  3884. }
  3885. } else {
  3886. if ( display !== "none" ) {
  3887. values[ index ] = "none";
  3888. // Remember what we're overwriting
  3889. dataPriv.set( elem, "display", display );
  3890. }
  3891. }
  3892. }
  3893. // Set the display of the elements in a second loop to avoid constant reflow
  3894. for ( index = 0; index < length; index++ ) {
  3895. if ( values[ index ] != null ) {
  3896. elements[ index ].style.display = values[ index ];
  3897. }
  3898. }
  3899. return elements;
  3900. }
  3901. jQuery.fn.extend( {
  3902. show: function() {
  3903. return showHide( this, true );
  3904. },
  3905. hide: function() {
  3906. return showHide( this );
  3907. },
  3908. toggle: function( state ) {
  3909. if ( typeof state === "boolean" ) {
  3910. return state ? this.show() : this.hide();
  3911. }
  3912. return this.each( function() {
  3913. if ( isHiddenWithinTree( this ) ) {
  3914. jQuery( this ).show();
  3915. } else {
  3916. jQuery( this ).hide();
  3917. }
  3918. } );
  3919. }
  3920. } );
  3921. var rcheckableType = ( /^(?:checkbox|radio)$/i );
  3922. var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
  3923. var rscriptType = ( /^$|\/(?:java|ecma)script/i );
  3924. // We have to close these tags to support XHTML (#13200)
  3925. var wrapMap = {
  3926. // Support: IE <=9 only
  3927. option: [ 1, "<select multiple='multiple'>", "</select>" ],
  3928. // XHTML parsers do not magically insert elements in the
  3929. // same way that tag soup parsers do. So we cannot shorten
  3930. // this by omitting <tbody> or other required elements.
  3931. thead: [ 1, "<table>", "</table>" ],
  3932. col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  3933. tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  3934. td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  3935. _default: [ 0, "", "" ]
  3936. };
  3937. // Support: IE <=9 only
  3938. wrapMap.optgroup = wrapMap.option;
  3939. wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  3940. wrapMap.th = wrapMap.td;
  3941. function getAll( context, tag ) {
  3942. // Support: IE <=9 - 11 only
  3943. // Use typeof to avoid zero-argument method invocation on host objects (#15151)
  3944. var ret;
  3945. if ( typeof context.getElementsByTagName !== "undefined" ) {
  3946. ret = context.getElementsByTagName( tag || "*" );
  3947. } else if ( typeof context.querySelectorAll !== "undefined" ) {
  3948. ret = context.querySelectorAll( tag || "*" );
  3949. } else {
  3950. ret = [];
  3951. }
  3952. if ( tag === undefined || tag && nodeName( context, tag ) ) {
  3953. return jQuery.merge( [ context ], ret );
  3954. }
  3955. return ret;
  3956. }
  3957. // Mark scripts as having already been evaluated
  3958. function setGlobalEval( elems, refElements ) {
  3959. var i = 0,
  3960. l = elems.length;
  3961. for ( ; i < l; i++ ) {
  3962. dataPriv.set(
  3963. elems[ i ],
  3964. "globalEval",
  3965. !refElements || dataPriv.get( refElements[ i ], "globalEval" )
  3966. );
  3967. }
  3968. }
  3969. var rhtml = /<|&#?\w+;/;
  3970. function buildFragment( elems, context, scripts, selection, ignored ) {
  3971. var elem, tmp, tag, wrap, contains, j,
  3972. fragment = context.createDocumentFragment(),
  3973. nodes = [],
  3974. i = 0,
  3975. l = elems.length;
  3976. for ( ; i < l; i++ ) {
  3977. elem = elems[ i ];
  3978. if ( elem || elem === 0 ) {
  3979. // Add nodes directly
  3980. if ( jQuery.type( elem ) === "object" ) {
  3981. // Support: Android <=4.0 only, PhantomJS 1 only
  3982. // push.apply(_, arraylike) throws on ancient WebKit
  3983. jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  3984. // Convert non-html into a text node
  3985. } else if ( !rhtml.test( elem ) ) {
  3986. nodes.push( context.createTextNode( elem ) );
  3987. // Convert html into DOM nodes
  3988. } else {
  3989. tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
  3990. // Deserialize a standard representation
  3991. tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
  3992. wrap = wrapMap[ tag ] || wrapMap._default;
  3993. tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
  3994. // Descend through wrappers to the right content
  3995. j = wrap[ 0 ];
  3996. while ( j-- ) {
  3997. tmp = tmp.lastChild;
  3998. }
  3999. // Support: Android <=4.0 only, PhantomJS 1 only
  4000. // push.apply(_, arraylike) throws on ancient WebKit
  4001. jQuery.merge( nodes, tmp.childNodes );
  4002. // Remember the top-level container
  4003. tmp = fragment.firstChild;
  4004. // Ensure the created nodes are orphaned (#12392)
  4005. tmp.textContent = "";
  4006. }
  4007. }
  4008. }
  4009. // Remove wrapper from fragment
  4010. fragment.textContent = "";
  4011. i = 0;
  4012. while ( ( elem = nodes[ i++ ] ) ) {
  4013. // Skip elements already in the context collection (trac-4087)
  4014. if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
  4015. if ( ignored ) {
  4016. ignored.push( elem );
  4017. }
  4018. continue;
  4019. }
  4020. contains = jQuery.contains( elem.ownerDocument, elem );
  4021. // Append to fragment
  4022. tmp = getAll( fragment.appendChild( elem ), "script" );
  4023. // Preserve script evaluation history
  4024. if ( contains ) {
  4025. setGlobalEval( tmp );
  4026. }
  4027. // Capture executables
  4028. if ( scripts ) {
  4029. j = 0;
  4030. while ( ( elem = tmp[ j++ ] ) ) {
  4031. if ( rscriptType.test( elem.type || "" ) ) {
  4032. scripts.push( elem );
  4033. }
  4034. }
  4035. }
  4036. }
  4037. return fragment;
  4038. }
  4039. ( function() {
  4040. var fragment = document.createDocumentFragment(),
  4041. div = fragment.appendChild( document.createElement( "div" ) ),
  4042. input = document.createElement( "input" );
  4043. // Support: Android 4.0 - 4.3 only
  4044. // Check state lost if the name is set (#11217)
  4045. // Support: Windows Web Apps (WWA)
  4046. // `name` and `type` must use .setAttribute for WWA (#14901)
  4047. input.setAttribute( "type", "radio" );
  4048. input.setAttribute( "checked", "checked" );
  4049. input.setAttribute( "name", "t" );
  4050. div.appendChild( input );
  4051. // Support: Android <=4.1 only
  4052. // Older WebKit doesn't clone checked state correctly in fragments
  4053. support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
  4054. // Support: IE <=11 only
  4055. // Make sure textarea (and checkbox) defaultValue is properly cloned
  4056. div.innerHTML = "<textarea>x</textarea>";
  4057. support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
  4058. } )();
  4059. var documentElement = document.documentElement;
  4060. var
  4061. rkeyEvent = /^key/,
  4062. rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
  4063. rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
  4064. function returnTrue() {
  4065. return true;
  4066. }
  4067. function returnFalse() {
  4068. return false;
  4069. }
  4070. // Support: IE <=9 only
  4071. // See #13393 for more info
  4072. function safeActiveElement() {
  4073. try {
  4074. return document.activeElement;
  4075. } catch ( err ) { }
  4076. }
  4077. function on( elem, types, selector, data, fn, one ) {
  4078. var origFn, type;
  4079. // Types can be a map of types/handlers
  4080. if ( typeof types === "object" ) {
  4081. // ( types-Object, selector, data )
  4082. if ( typeof selector !== "string" ) {
  4083. // ( types-Object, data )
  4084. data = data || selector;
  4085. selector = undefined;
  4086. }
  4087. for ( type in types ) {
  4088. on( elem, type, selector, data, types[ type ], one );
  4089. }
  4090. return elem;
  4091. }
  4092. if ( data == null && fn == null ) {
  4093. // ( types, fn )
  4094. fn = selector;
  4095. data = selector = undefined;
  4096. } else if ( fn == null ) {
  4097. if ( typeof selector === "string" ) {
  4098. // ( types, selector, fn )
  4099. fn = data;
  4100. data = undefined;
  4101. } else {
  4102. // ( types, data, fn )
  4103. fn = data;
  4104. data = selector;
  4105. selector = undefined;
  4106. }
  4107. }
  4108. if ( fn === false ) {
  4109. fn = returnFalse;
  4110. } else if ( !fn ) {
  4111. return elem;
  4112. }
  4113. if ( one === 1 ) {
  4114. origFn = fn;
  4115. fn = function( event ) {
  4116. // Can use an empty set, since event contains the info
  4117. jQuery().off( event );
  4118. return origFn.apply( this, arguments );
  4119. };
  4120. // Use same guid so caller can remove using origFn
  4121. fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  4122. }
  4123. return elem.each( function() {
  4124. jQuery.event.add( this, types, fn, data, selector );
  4125. } );
  4126. }
  4127. /*
  4128. * Helper functions for managing events -- not part of the public interface.
  4129. * Props to Dean Edwards' addEvent library for many of the ideas.
  4130. */
  4131. jQuery.event = {
  4132. global: {},
  4133. add: function( elem, types, handler, data, selector ) {
  4134. var handleObjIn, eventHandle, tmp,
  4135. events, t, handleObj,
  4136. special, handlers, type, namespaces, origType,
  4137. elemData = dataPriv.get( elem );
  4138. // Don't attach events to noData or text/comment nodes (but allow plain objects)
  4139. if ( !elemData ) {
  4140. return;
  4141. }
  4142. // Caller can pass in an object of custom data in lieu of the handler
  4143. if ( handler.handler ) {
  4144. handleObjIn = handler;
  4145. handler = handleObjIn.handler;
  4146. selector = handleObjIn.selector;
  4147. }
  4148. // Ensure that invalid selectors throw exceptions at attach time
  4149. // Evaluate against documentElement in case elem is a non-element node (e.g., document)
  4150. if ( selector ) {
  4151. jQuery.find.matchesSelector( documentElement, selector );
  4152. }
  4153. // Make sure that the handler has a unique ID, used to find/remove it later
  4154. if ( !handler.guid ) {
  4155. handler.guid = jQuery.guid++;
  4156. }
  4157. // Init the element's event structure and main handler, if this is the first
  4158. if ( !( events = elemData.events ) ) {
  4159. events = elemData.events = {};
  4160. }
  4161. if ( !( eventHandle = elemData.handle ) ) {
  4162. eventHandle = elemData.handle = function( e ) {
  4163. // Discard the second event of a jQuery.event.trigger() and
  4164. // when an event is called after a page has unloaded
  4165. return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
  4166. jQuery.event.dispatch.apply( elem, arguments ) : undefined;
  4167. };
  4168. }
  4169. // Handle multiple events separated by a space
  4170. types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
  4171. t = types.length;
  4172. while ( t-- ) {
  4173. tmp = rtypenamespace.exec( types[ t ] ) || [];
  4174. type = origType = tmp[ 1 ];
  4175. namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
  4176. // There *must* be a type, no attaching namespace-only handlers
  4177. if ( !type ) {
  4178. continue;
  4179. }
  4180. // If event changes its type, use the special event handlers for the changed type
  4181. special = jQuery.event.special[ type ] || {};
  4182. // If selector defined, determine special event api type, otherwise given type
  4183. type = ( selector ? special.delegateType : special.bindType ) || type;
  4184. // Update special based on newly reset type
  4185. special = jQuery.event.special[ type ] || {};
  4186. // handleObj is passed to all event handlers
  4187. handleObj = jQuery.extend( {
  4188. type: type,
  4189. origType: origType,
  4190. data: data,
  4191. handler: handler,
  4192. guid: handler.guid,
  4193. selector: selector,
  4194. needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  4195. namespace: namespaces.join( "." )
  4196. }, handleObjIn );
  4197. // Init the event handler queue if we're the first
  4198. if ( !( handlers = events[ type ] ) ) {
  4199. handlers = events[ type ] = [];
  4200. handlers.delegateCount = 0;
  4201. // Only use addEventListener if the special events handler returns false
  4202. if ( !special.setup ||
  4203. special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  4204. if ( elem.addEventListener ) {
  4205. elem.addEventListener( type, eventHandle );
  4206. }
  4207. }
  4208. }
  4209. if ( special.add ) {
  4210. special.add.call( elem, handleObj );
  4211. if ( !handleObj.handler.guid ) {
  4212. handleObj.handler.guid = handler.guid;
  4213. }
  4214. }
  4215. // Add to the element's handler list, delegates in front
  4216. if ( selector ) {
  4217. handlers.splice( handlers.delegateCount++, 0, handleObj );
  4218. } else {
  4219. handlers.push( handleObj );
  4220. }
  4221. // Keep track of which events have ever been used, for event optimization
  4222. jQuery.event.global[ type ] = true;
  4223. }
  4224. },
  4225. // Detach an event or set of events from an element
  4226. remove: function( elem, types, handler, selector, mappedTypes ) {
  4227. var j, origCount, tmp,
  4228. events, t, handleObj,
  4229. special, handlers, type, namespaces, origType,
  4230. elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
  4231. if ( !elemData || !( events = elemData.events ) ) {
  4232. return;
  4233. }
  4234. // Once for each type.namespace in types; type may be omitted
  4235. types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
  4236. t = types.length;
  4237. while ( t-- ) {
  4238. tmp = rtypenamespace.exec( types[ t ] ) || [];
  4239. type = origType = tmp[ 1 ];
  4240. namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
  4241. // Unbind all events (on this namespace, if provided) for the element
  4242. if ( !type ) {
  4243. for ( type in events ) {
  4244. jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  4245. }
  4246. continue;
  4247. }
  4248. special = jQuery.event.special[ type ] || {};
  4249. type = ( selector ? special.delegateType : special.bindType ) || type;
  4250. handlers = events[ type ] || [];
  4251. tmp = tmp[ 2 ] &&
  4252. new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
  4253. // Remove matching events
  4254. origCount = j = handlers.length;
  4255. while ( j-- ) {
  4256. handleObj = handlers[ j ];
  4257. if ( ( mappedTypes || origType === handleObj.origType ) &&
  4258. ( !handler || handler.guid === handleObj.guid ) &&
  4259. ( !tmp || tmp.test( handleObj.namespace ) ) &&
  4260. ( !selector || selector === handleObj.selector ||
  4261. selector === "**" && handleObj.selector ) ) {
  4262. handlers.splice( j, 1 );
  4263. if ( handleObj.selector ) {
  4264. handlers.delegateCount--;
  4265. }
  4266. if ( special.remove ) {
  4267. special.remove.call( elem, handleObj );
  4268. }
  4269. }
  4270. }
  4271. // Remove generic event handler if we removed something and no more handlers exist
  4272. // (avoids potential for endless recursion during removal of special event handlers)
  4273. if ( origCount && !handlers.length ) {
  4274. if ( !special.teardown ||
  4275. special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  4276. jQuery.removeEvent( elem, type, elemData.handle );
  4277. }
  4278. delete events[ type ];
  4279. }
  4280. }
  4281. // Remove data and the expando if it's no longer used
  4282. if ( jQuery.isEmptyObject( events ) ) {
  4283. dataPriv.remove( elem, "handle events" );
  4284. }
  4285. },
  4286. dispatch: function( nativeEvent ) {
  4287. // Make a writable jQuery.Event from the native event object
  4288. var event = jQuery.event.fix( nativeEvent );
  4289. var i, j, ret, matched, handleObj, handlerQueue,
  4290. args = new Array( arguments.length ),
  4291. handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
  4292. special = jQuery.event.special[ event.type ] || {};
  4293. // Use the fix-ed jQuery.Event rather than the (read-only) native event
  4294. args[ 0 ] = event;
  4295. for ( i = 1; i < arguments.length; i++ ) {
  4296. args[ i ] = arguments[ i ];
  4297. }
  4298. event.delegateTarget = this;
  4299. // Call the preDispatch hook for the mapped type, and let it bail if desired
  4300. if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  4301. return;
  4302. }
  4303. // Determine handlers
  4304. handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  4305. // Run delegates first; they may want to stop propagation beneath us
  4306. i = 0;
  4307. while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
  4308. event.currentTarget = matched.elem;
  4309. j = 0;
  4310. while ( ( handleObj = matched.handlers[ j++ ] ) &&
  4311. !event.isImmediatePropagationStopped() ) {
  4312. // Triggered event must either 1) have no namespace, or 2) have namespace(s)
  4313. // a subset or equal to those in the bound event (both can have no namespace).
  4314. if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
  4315. event.handleObj = handleObj;
  4316. event.data = handleObj.data;
  4317. ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
  4318. handleObj.handler ).apply( matched.elem, args );
  4319. if ( ret !== undefined ) {
  4320. if ( ( event.result = ret ) === false ) {
  4321. event.preventDefault();
  4322. event.stopPropagation();
  4323. }
  4324. }
  4325. }
  4326. }
  4327. }
  4328. // Call the postDispatch hook for the mapped type
  4329. if ( special.postDispatch ) {
  4330. special.postDispatch.call( this, event );
  4331. }
  4332. return event.result;
  4333. },
  4334. handlers: function( event, handlers ) {
  4335. var i, handleObj, sel, matchedHandlers, matchedSelectors,
  4336. handlerQueue = [],
  4337. delegateCount = handlers.delegateCount,
  4338. cur = event.target;
  4339. // Find delegate handlers
  4340. if ( delegateCount &&
  4341. // Support: IE <=9
  4342. // Black-hole SVG <use> instance trees (trac-13180)
  4343. cur.nodeType &&
  4344. // Support: Firefox <=42
  4345. // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
  4346. // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
  4347. // Support: IE 11 only
  4348. // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
  4349. !( event.type === "click" && event.button >= 1 ) ) {
  4350. for ( ; cur !== this; cur = cur.parentNode || this ) {
  4351. // Don't check non-elements (#13208)
  4352. // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  4353. if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
  4354. matchedHandlers = [];
  4355. matchedSelectors = {};
  4356. for ( i = 0; i < delegateCount; i++ ) {
  4357. handleObj = handlers[ i ];
  4358. // Don't conflict with Object.prototype properties (#13203)
  4359. sel = handleObj.selector + " ";
  4360. if ( matchedSelectors[ sel ] === undefined ) {
  4361. matchedSelectors[ sel ] = handleObj.needsContext ?
  4362. jQuery( sel, this ).index( cur ) > -1 :
  4363. jQuery.find( sel, this, null, [ cur ] ).length;
  4364. }
  4365. if ( matchedSelectors[ sel ] ) {
  4366. matchedHandlers.push( handleObj );
  4367. }
  4368. }
  4369. if ( matchedHandlers.length ) {
  4370. handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
  4371. }
  4372. }
  4373. }
  4374. }
  4375. // Add the remaining (directly-bound) handlers
  4376. cur = this;
  4377. if ( delegateCount < handlers.length ) {
  4378. handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
  4379. }
  4380. return handlerQueue;
  4381. },
  4382. addProp: function( name, hook ) {
  4383. Object.defineProperty( jQuery.Event.prototype, name, {
  4384. enumerable: true,
  4385. configurable: true,
  4386. get: jQuery.isFunction( hook ) ?
  4387. function() {
  4388. if ( this.originalEvent ) {
  4389. return hook( this.originalEvent );
  4390. }
  4391. } :
  4392. function() {
  4393. if ( this.originalEvent ) {
  4394. return this.originalEvent[ name ];
  4395. }
  4396. },
  4397. set: function( value ) {
  4398. Object.defineProperty( this, name, {
  4399. enumerable: true,
  4400. configurable: true,
  4401. writable: true,
  4402. value: value
  4403. } );
  4404. }
  4405. } );
  4406. },
  4407. fix: function( originalEvent ) {
  4408. return originalEvent[ jQuery.expando ] ?
  4409. originalEvent :
  4410. new jQuery.Event( originalEvent );
  4411. },
  4412. special: {
  4413. load: {
  4414. // Prevent triggered image.load events from bubbling to window.load
  4415. noBubble: true
  4416. },
  4417. focus: {
  4418. // Fire native event if possible so blur/focus sequence is correct
  4419. trigger: function() {
  4420. if ( this !== safeActiveElement() && this.focus ) {
  4421. this.focus();
  4422. return false;
  4423. }
  4424. },
  4425. delegateType: "focusin"
  4426. },
  4427. blur: {
  4428. trigger: function() {
  4429. if ( this === safeActiveElement() && this.blur ) {
  4430. this.blur();
  4431. return false;
  4432. }
  4433. },
  4434. delegateType: "focusout"
  4435. },
  4436. click: {
  4437. // For checkbox, fire native event so checked state will be right
  4438. trigger: function() {
  4439. if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
  4440. this.click();
  4441. return false;
  4442. }
  4443. },
  4444. // For cross-browser consistency, don't fire native .click() on links
  4445. _default: function( event ) {
  4446. return nodeName( event.target, "a" );
  4447. }
  4448. },
  4449. beforeunload: {
  4450. postDispatch: function( event ) {
  4451. // Support: Firefox 20+
  4452. // Firefox doesn't alert if the returnValue field is not set.
  4453. if ( event.result !== undefined && event.originalEvent ) {
  4454. event.originalEvent.returnValue = event.result;
  4455. }
  4456. }
  4457. }
  4458. }
  4459. };
  4460. jQuery.removeEvent = function( elem, type, handle ) {
  4461. // This "if" is needed for plain objects
  4462. if ( elem.removeEventListener ) {
  4463. elem.removeEventListener( type, handle );
  4464. }
  4465. };
  4466. jQuery.Event = function( src, props ) {
  4467. // Allow instantiation without the 'new' keyword
  4468. if ( !( this instanceof jQuery.Event ) ) {
  4469. return new jQuery.Event( src, props );
  4470. }
  4471. // Event object
  4472. if ( src && src.type ) {
  4473. this.originalEvent = src;
  4474. this.type = src.type;
  4475. // Events bubbling up the document may have been marked as prevented
  4476. // by a handler lower down the tree; reflect the correct value.
  4477. this.isDefaultPrevented = src.defaultPrevented ||
  4478. src.defaultPrevented === undefined &&
  4479. // Support: Android <=2.3 only
  4480. src.returnValue === false ?
  4481. returnTrue :
  4482. returnFalse;
  4483. // Create target properties
  4484. // Support: Safari <=6 - 7 only
  4485. // Target should not be a text node (#504, #13143)
  4486. this.target = ( src.target && src.target.nodeType === 3 ) ?
  4487. src.target.parentNode :
  4488. src.target;
  4489. this.currentTarget = src.currentTarget;
  4490. this.relatedTarget = src.relatedTarget;
  4491. // Event type
  4492. } else {
  4493. this.type = src;
  4494. }
  4495. // Put explicitly provided properties onto the event object
  4496. if ( props ) {
  4497. jQuery.extend( this, props );
  4498. }
  4499. // Create a timestamp if incoming event doesn't have one
  4500. this.timeStamp = src && src.timeStamp || jQuery.now();
  4501. // Mark it as fixed
  4502. this[ jQuery.expando ] = true;
  4503. };
  4504. // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  4505. // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  4506. jQuery.Event.prototype = {
  4507. constructor: jQuery.Event,
  4508. isDefaultPrevented: returnFalse,
  4509. isPropagationStopped: returnFalse,
  4510. isImmediatePropagationStopped: returnFalse,
  4511. isSimulated: false,
  4512. preventDefault: function() {
  4513. var e = this.originalEvent;
  4514. this.isDefaultPrevented = returnTrue;
  4515. if ( e && !this.isSimulated ) {
  4516. e.preventDefault();
  4517. }
  4518. },
  4519. stopPropagation: function() {
  4520. var e = this.originalEvent;
  4521. this.isPropagationStopped = returnTrue;
  4522. if ( e && !this.isSimulated ) {
  4523. e.stopPropagation();
  4524. }
  4525. },
  4526. stopImmediatePropagation: function() {
  4527. var e = this.originalEvent;
  4528. this.isImmediatePropagationStopped = returnTrue;
  4529. if ( e && !this.isSimulated ) {
  4530. e.stopImmediatePropagation();
  4531. }
  4532. this.stopPropagation();
  4533. }
  4534. };
  4535. // Includes all common event props including KeyEvent and MouseEvent specific props
  4536. jQuery.each( {
  4537. altKey: true,
  4538. bubbles: true,
  4539. cancelable: true,
  4540. changedTouches: true,
  4541. ctrlKey: true,
  4542. detail: true,
  4543. eventPhase: true,
  4544. metaKey: true,
  4545. pageX: true,
  4546. pageY: true,
  4547. shiftKey: true,
  4548. view: true,
  4549. "char": true,
  4550. charCode: true,
  4551. key: true,
  4552. keyCode: true,
  4553. button: true,
  4554. buttons: true,
  4555. clientX: true,
  4556. clientY: true,
  4557. offsetX: true,
  4558. offsetY: true,
  4559. pointerId: true,
  4560. pointerType: true,
  4561. screenX: true,
  4562. screenY: true,
  4563. targetTouches: true,
  4564. toElement: true,
  4565. touches: true,
  4566. which: function( event ) {
  4567. var button = event.button;
  4568. // Add which for key events
  4569. if ( event.which == null && rkeyEvent.test( event.type ) ) {
  4570. return event.charCode != null ? event.charCode : event.keyCode;
  4571. }
  4572. // Add which for click: 1 === left; 2 === middle; 3 === right
  4573. if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
  4574. if ( button & 1 ) {
  4575. return 1;
  4576. }
  4577. if ( button & 2 ) {
  4578. return 3;
  4579. }
  4580. if ( button & 4 ) {
  4581. return 2;
  4582. }
  4583. return 0;
  4584. }
  4585. return event.which;
  4586. }
  4587. }, jQuery.event.addProp );
  4588. // Create mouseenter/leave events using mouseover/out and event-time checks
  4589. // so that event delegation works in jQuery.
  4590. // Do the same for pointerenter/pointerleave and pointerover/pointerout
  4591. //
  4592. // Support: Safari 7 only
  4593. // Safari sends mouseenter too often; see:
  4594. // https://bugs.chromium.org/p/chromium/issues/detail?id=470258
  4595. // for the description of the bug (it existed in older Chrome versions as well).
  4596. jQuery.each( {
  4597. mouseenter: "mouseover",
  4598. mouseleave: "mouseout",
  4599. pointerenter: "pointerover",
  4600. pointerleave: "pointerout"
  4601. }, function( orig, fix ) {
  4602. jQuery.event.special[ orig ] = {
  4603. delegateType: fix,
  4604. bindType: fix,
  4605. handle: function( event ) {
  4606. var ret,
  4607. target = this,
  4608. related = event.relatedTarget,
  4609. handleObj = event.handleObj;
  4610. // For mouseenter/leave call the handler if related is outside the target.
  4611. // NB: No relatedTarget if the mouse left/entered the browser window
  4612. if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
  4613. event.type = handleObj.origType;
  4614. ret = handleObj.handler.apply( this, arguments );
  4615. event.type = fix;
  4616. }
  4617. return ret;
  4618. }
  4619. };
  4620. } );
  4621. jQuery.fn.extend( {
  4622. on: function( types, selector, data, fn ) {
  4623. return on( this, types, selector, data, fn );
  4624. },
  4625. one: function( types, selector, data, fn ) {
  4626. return on( this, types, selector, data, fn, 1 );
  4627. },
  4628. off: function( types, selector, fn ) {
  4629. var handleObj, type;
  4630. if ( types && types.preventDefault && types.handleObj ) {
  4631. // ( event ) dispatched jQuery.Event
  4632. handleObj = types.handleObj;
  4633. jQuery( types.delegateTarget ).off(
  4634. handleObj.namespace ?
  4635. handleObj.origType + "." + handleObj.namespace :
  4636. handleObj.origType,
  4637. handleObj.selector,
  4638. handleObj.handler
  4639. );
  4640. return this;
  4641. }
  4642. if ( typeof types === "object" ) {
  4643. // ( types-object [, selector] )
  4644. for ( type in types ) {
  4645. this.off( type, selector, types[ type ] );
  4646. }
  4647. return this;
  4648. }
  4649. if ( selector === false || typeof selector === "function" ) {
  4650. // ( types [, fn] )
  4651. fn = selector;
  4652. selector = undefined;
  4653. }
  4654. if ( fn === false ) {
  4655. fn = returnFalse;
  4656. }
  4657. return this.each( function() {
  4658. jQuery.event.remove( this, types, fn, selector );
  4659. } );
  4660. }
  4661. } );
  4662. var
  4663. /* eslint-disable max-len */
  4664. // See https://github.com/eslint/eslint/issues/3229
  4665. rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
  4666. /* eslint-enable */
  4667. // Support: IE <=10 - 11, Edge 12 - 13
  4668. // In IE/Edge using regex groups here causes severe slowdowns.
  4669. // See https://connect.microsoft.com/IE/feedback/details/1736512/
  4670. rnoInnerhtml = /<script|<style|<link/i,
  4671. // checked="checked" or checked
  4672. rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
  4673. rscriptTypeMasked = /^true\/(.*)/,
  4674. rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
  4675. // Prefer a tbody over its parent table for containing new rows
  4676. function manipulationTarget( elem, content ) {
  4677. if ( nodeName( elem, "table" ) &&
  4678. nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
  4679. return jQuery( ">tbody", elem )[ 0 ] || elem;
  4680. }
  4681. return elem;
  4682. }
  4683. // Replace/restore the type attribute of script elements for safe DOM manipulation
  4684. function disableScript( elem ) {
  4685. elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
  4686. return elem;
  4687. }
  4688. function restoreScript( elem ) {
  4689. var match = rscriptTypeMasked.exec( elem.type );
  4690. if ( match ) {
  4691. elem.type = match[ 1 ];
  4692. } else {
  4693. elem.removeAttribute( "type" );
  4694. }
  4695. return elem;
  4696. }
  4697. function cloneCopyEvent( src, dest ) {
  4698. var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
  4699. if ( dest.nodeType !== 1 ) {
  4700. return;
  4701. }
  4702. // 1. Copy private data: events, handlers, etc.
  4703. if ( dataPriv.hasData( src ) ) {
  4704. pdataOld = dataPriv.access( src );
  4705. pdataCur = dataPriv.set( dest, pdataOld );
  4706. events = pdataOld.events;
  4707. if ( events ) {
  4708. delete pdataCur.handle;
  4709. pdataCur.events = {};
  4710. for ( type in events ) {
  4711. for ( i = 0, l = events[ type ].length; i < l; i++ ) {
  4712. jQuery.event.add( dest, type, events[ type ][ i ] );
  4713. }
  4714. }
  4715. }
  4716. }
  4717. // 2. Copy user data
  4718. if ( dataUser.hasData( src ) ) {
  4719. udataOld = dataUser.access( src );
  4720. udataCur = jQuery.extend( {}, udataOld );
  4721. dataUser.set( dest, udataCur );
  4722. }
  4723. }
  4724. // Fix IE bugs, see support tests
  4725. function fixInput( src, dest ) {
  4726. var nodeName = dest.nodeName.toLowerCase();
  4727. // Fails to persist the checked state of a cloned checkbox or radio button.
  4728. if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
  4729. dest.checked = src.checked;
  4730. // Fails to return the selected option to the default selected state when cloning options
  4731. } else if ( nodeName === "input" || nodeName === "textarea" ) {
  4732. dest.defaultValue = src.defaultValue;
  4733. }
  4734. }
  4735. function domManip( collection, args, callback, ignored ) {
  4736. // Flatten any nested arrays
  4737. args = concat.apply( [], args );
  4738. var fragment, first, scripts, hasScripts, node, doc,
  4739. i = 0,
  4740. l = collection.length,
  4741. iNoClone = l - 1,
  4742. value = args[ 0 ],
  4743. isFunction = jQuery.isFunction( value );
  4744. // We can't cloneNode fragments that contain checked, in WebKit
  4745. if ( isFunction ||
  4746. ( l > 1 && typeof value === "string" &&
  4747. !support.checkClone && rchecked.test( value ) ) ) {
  4748. return collection.each( function( index ) {
  4749. var self = collection.eq( index );
  4750. if ( isFunction ) {
  4751. args[ 0 ] = value.call( this, index, self.html() );
  4752. }
  4753. domManip( self, args, callback, ignored );
  4754. } );
  4755. }
  4756. if ( l ) {
  4757. fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
  4758. first = fragment.firstChild;
  4759. if ( fragment.childNodes.length === 1 ) {
  4760. fragment = first;
  4761. }
  4762. // Require either new content or an interest in ignored elements to invoke the callback
  4763. if ( first || ignored ) {
  4764. scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
  4765. hasScripts = scripts.length;
  4766. // Use the original fragment for the last item
  4767. // instead of the first because it can end up
  4768. // being emptied incorrectly in certain situations (#8070).
  4769. for ( ; i < l; i++ ) {
  4770. node = fragment;
  4771. if ( i !== iNoClone ) {
  4772. node = jQuery.clone( node, true, true );
  4773. // Keep references to cloned scripts for later restoration
  4774. if ( hasScripts ) {
  4775. // Support: Android <=4.0 only, PhantomJS 1 only
  4776. // push.apply(_, arraylike) throws on ancient WebKit
  4777. jQuery.merge( scripts, getAll( node, "script" ) );
  4778. }
  4779. }
  4780. callback.call( collection[ i ], node, i );
  4781. }
  4782. if ( hasScripts ) {
  4783. doc = scripts[ scripts.length - 1 ].ownerDocument;
  4784. // Reenable scripts
  4785. jQuery.map( scripts, restoreScript );
  4786. // Evaluate executable scripts on first document insertion
  4787. for ( i = 0; i < hasScripts; i++ ) {
  4788. node = scripts[ i ];
  4789. if ( rscriptType.test( node.type || "" ) &&
  4790. !dataPriv.access( node, "globalEval" ) &&
  4791. jQuery.contains( doc, node ) ) {
  4792. if ( node.src ) {
  4793. // Optional AJAX dependency, but won't run scripts if not present
  4794. if ( jQuery._evalUrl ) {
  4795. jQuery._evalUrl( node.src );
  4796. }
  4797. } else {
  4798. DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
  4799. }
  4800. }
  4801. }
  4802. }
  4803. }
  4804. }
  4805. return collection;
  4806. }
  4807. function remove( elem, selector, keepData ) {
  4808. var node,
  4809. nodes = selector ? jQuery.filter( selector, elem ) : elem,
  4810. i = 0;
  4811. for ( ; ( node = nodes[ i ] ) != null; i++ ) {
  4812. if ( !keepData && node.nodeType === 1 ) {
  4813. jQuery.cleanData( getAll( node ) );
  4814. }
  4815. if ( node.parentNode ) {
  4816. if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
  4817. setGlobalEval( getAll( node, "script" ) );
  4818. }
  4819. node.parentNode.removeChild( node );
  4820. }
  4821. }
  4822. return elem;
  4823. }
  4824. jQuery.extend( {
  4825. htmlPrefilter: function( html ) {
  4826. return html.replace( rxhtmlTag, "<$1></$2>" );
  4827. },
  4828. clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  4829. var i, l, srcElements, destElements,
  4830. clone = elem.cloneNode( true ),
  4831. inPage = jQuery.contains( elem.ownerDocument, elem );
  4832. // Fix IE cloning issues
  4833. if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
  4834. !jQuery.isXMLDoc( elem ) ) {
  4835. // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
  4836. destElements = getAll( clone );
  4837. srcElements = getAll( elem );
  4838. for ( i = 0, l = srcElements.length; i < l; i++ ) {
  4839. fixInput( srcElements[ i ], destElements[ i ] );
  4840. }
  4841. }
  4842. // Copy the events from the original to the clone
  4843. if ( dataAndEvents ) {
  4844. if ( deepDataAndEvents ) {
  4845. srcElements = srcElements || getAll( elem );
  4846. destElements = destElements || getAll( clone );
  4847. for ( i = 0, l = srcElements.length; i < l; i++ ) {
  4848. cloneCopyEvent( srcElements[ i ], destElements[ i ] );
  4849. }
  4850. } else {
  4851. cloneCopyEvent( elem, clone );
  4852. }
  4853. }
  4854. // Preserve script evaluation history
  4855. destElements = getAll( clone, "script" );
  4856. if ( destElements.length > 0 ) {
  4857. setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
  4858. }
  4859. // Return the cloned set
  4860. return clone;
  4861. },
  4862. cleanData: function( elems ) {
  4863. var data, elem, type,
  4864. special = jQuery.event.special,
  4865. i = 0;
  4866. for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
  4867. if ( acceptData( elem ) ) {
  4868. if ( ( data = elem[ dataPriv.expando ] ) ) {
  4869. if ( data.events ) {
  4870. for ( type in data.events ) {
  4871. if ( special[ type ] ) {
  4872. jQuery.event.remove( elem, type );
  4873. // This is a shortcut to avoid jQuery.event.remove's overhead
  4874. } else {
  4875. jQuery.removeEvent( elem, type, data.handle );
  4876. }
  4877. }
  4878. }
  4879. // Support: Chrome <=35 - 45+
  4880. // Assign undefined instead of using delete, see Data#remove
  4881. elem[ dataPriv.expando ] = undefined;
  4882. }
  4883. if ( elem[ dataUser.expando ] ) {
  4884. // Support: Chrome <=35 - 45+
  4885. // Assign undefined instead of using delete, see Data#remove
  4886. elem[ dataUser.expando ] = undefined;
  4887. }
  4888. }
  4889. }
  4890. }
  4891. } );
  4892. jQuery.fn.extend( {
  4893. detach: function( selector ) {
  4894. return remove( this, selector, true );
  4895. },
  4896. remove: function( selector ) {
  4897. return remove( this, selector );
  4898. },
  4899. text: function( value ) {
  4900. return access( this, function( value ) {
  4901. return value === undefined ?
  4902. jQuery.text( this ) :
  4903. this.empty().each( function() {
  4904. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  4905. this.textContent = value;
  4906. }
  4907. } );
  4908. }, null, value, arguments.length );
  4909. },
  4910. append: function() {
  4911. return domManip( this, arguments, function( elem ) {
  4912. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  4913. var target = manipulationTarget( this, elem );
  4914. target.appendChild( elem );
  4915. }
  4916. } );
  4917. },
  4918. prepend: function() {
  4919. return domManip( this, arguments, function( elem ) {
  4920. if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  4921. var target = manipulationTarget( this, elem );
  4922. target.insertBefore( elem, target.firstChild );
  4923. }
  4924. } );
  4925. },
  4926. before: function() {
  4927. return domManip( this, arguments, function( elem ) {
  4928. if ( this.parentNode ) {
  4929. this.parentNode.insertBefore( elem, this );
  4930. }
  4931. } );
  4932. },
  4933. after: function() {
  4934. return domManip( this, arguments, function( elem ) {
  4935. if ( this.parentNode ) {
  4936. this.parentNode.insertBefore( elem, this.nextSibling );
  4937. }
  4938. } );
  4939. },
  4940. empty: function() {
  4941. var elem,
  4942. i = 0;
  4943. for ( ; ( elem = this[ i ] ) != null; i++ ) {
  4944. if ( elem.nodeType === 1 ) {
  4945. // Prevent memory leaks
  4946. jQuery.cleanData( getAll( elem, false ) );
  4947. // Remove any remaining nodes
  4948. elem.textContent = "";
  4949. }
  4950. }
  4951. return this;
  4952. },
  4953. clone: function( dataAndEvents, deepDataAndEvents ) {
  4954. dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
  4955. deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
  4956. return this.map( function() {
  4957. return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
  4958. } );
  4959. },
  4960. html: function( value ) {
  4961. return access( this, function( value ) {
  4962. var elem = this[ 0 ] || {},
  4963. i = 0,
  4964. l = this.length;
  4965. if ( value === undefined && elem.nodeType === 1 ) {
  4966. return elem.innerHTML;
  4967. }
  4968. // See if we can take a shortcut and just use innerHTML
  4969. if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
  4970. !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
  4971. value = jQuery.htmlPrefilter( value );
  4972. try {
  4973. for ( ; i < l; i++ ) {
  4974. elem = this[ i ] || {};
  4975. // Remove element nodes and prevent memory leaks
  4976. if ( elem.nodeType === 1 ) {
  4977. jQuery.cleanData( getAll( elem, false ) );
  4978. elem.innerHTML = value;
  4979. }
  4980. }
  4981. elem = 0;
  4982. // If using innerHTML throws an exception, use the fallback method
  4983. } catch ( e ) {}
  4984. }
  4985. if ( elem ) {
  4986. this.empty().append( value );
  4987. }
  4988. }, null, value, arguments.length );
  4989. },
  4990. replaceWith: function() {
  4991. var ignored = [];
  4992. // Make the changes, replacing each non-ignored context element with the new content
  4993. return domManip( this, arguments, function( elem ) {
  4994. var parent = this.parentNode;
  4995. if ( jQuery.inArray( this, ignored ) < 0 ) {
  4996. jQuery.cleanData( getAll( this ) );
  4997. if ( parent ) {
  4998. parent.replaceChild( elem, this );
  4999. }
  5000. }
  5001. // Force callback invocation
  5002. }, ignored );
  5003. }
  5004. } );
  5005. jQuery.each( {
  5006. appendTo: "append",
  5007. prependTo: "prepend",
  5008. insertBefore: "before",
  5009. insertAfter: "after",
  5010. replaceAll: "replaceWith"
  5011. }, function( name, original ) {
  5012. jQuery.fn[ name ] = function( selector ) {
  5013. var elems,
  5014. ret = [],
  5015. insert = jQuery( selector ),
  5016. last = insert.length - 1,
  5017. i = 0;
  5018. for ( ; i <= last; i++ ) {
  5019. elems = i === last ? this : this.clone( true );
  5020. jQuery( insert[ i ] )[ original ]( elems );
  5021. // Support: Android <=4.0 only, PhantomJS 1 only
  5022. // .get() because push.apply(_, arraylike) throws on ancient WebKit
  5023. push.apply( ret, elems.get() );
  5024. }
  5025. return this.pushStack( ret );
  5026. };
  5027. } );
  5028. var rmargin = ( /^margin/ );
  5029. var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
  5030. var getStyles = function( elem ) {
  5031. // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
  5032. // IE throws on elements created in popups
  5033. // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
  5034. var view = elem.ownerDocument.defaultView;
  5035. if ( !view || !view.opener ) {
  5036. view = window;
  5037. }
  5038. return view.getComputedStyle( elem );
  5039. };
  5040. ( function() {
  5041. // Executing both pixelPosition & boxSizingReliable tests require only one layout
  5042. // so they're executed at the same time to save the second computation.
  5043. function computeStyleTests() {
  5044. // This is a singleton, we need to execute it only once
  5045. if ( !div ) {
  5046. return;
  5047. }
  5048. div.style.cssText =
  5049. "box-sizing:border-box;" +
  5050. "position:relative;display:block;" +
  5051. "margin:auto;border:1px;padding:1px;" +
  5052. "top:1%;width:50%";
  5053. div.innerHTML = "";
  5054. documentElement.appendChild( container );
  5055. var divStyle = window.getComputedStyle( div );
  5056. pixelPositionVal = divStyle.top !== "1%";
  5057. // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
  5058. reliableMarginLeftVal = divStyle.marginLeft === "2px";
  5059. boxSizingReliableVal = divStyle.width === "4px";
  5060. // Support: Android 4.0 - 4.3 only
  5061. // Some styles come back with percentage values, even though they shouldn't
  5062. div.style.marginRight = "50%";
  5063. pixelMarginRightVal = divStyle.marginRight === "4px";
  5064. documentElement.removeChild( container );
  5065. // Nullify the div so it wouldn't be stored in the memory and
  5066. // it will also be a sign that checks already performed
  5067. div = null;
  5068. }
  5069. var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
  5070. container = document.createElement( "div" ),
  5071. div = document.createElement( "div" );
  5072. // Finish early in limited (non-browser) environments
  5073. if ( !div.style ) {
  5074. return;
  5075. }
  5076. // Support: IE <=9 - 11 only
  5077. // Style of cloned element affects source element cloned (#8908)
  5078. div.style.backgroundClip = "content-box";
  5079. div.cloneNode( true ).style.backgroundClip = "";
  5080. support.clearCloneStyle = div.style.backgroundClip === "content-box";
  5081. container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
  5082. "padding:0;margin-top:1px;position:absolute";
  5083. container.appendChild( div );
  5084. jQuery.extend( support, {
  5085. pixelPosition: function() {
  5086. computeStyleTests();
  5087. return pixelPositionVal;
  5088. },
  5089. boxSizingReliable: function() {
  5090. computeStyleTests();
  5091. return boxSizingReliableVal;
  5092. },
  5093. pixelMarginRight: function() {
  5094. computeStyleTests();
  5095. return pixelMarginRightVal;
  5096. },
  5097. reliableMarginLeft: function() {
  5098. computeStyleTests();
  5099. return reliableMarginLeftVal;
  5100. }
  5101. } );
  5102. } )();
  5103. function curCSS( elem, name, computed ) {
  5104. var width, minWidth, maxWidth, ret,
  5105. // Support: Firefox 51+
  5106. // Retrieving style before computed somehow
  5107. // fixes an issue with getting wrong values
  5108. // on detached elements
  5109. style = elem.style;
  5110. computed = computed || getStyles( elem );
  5111. // getPropertyValue is needed for:
  5112. // .css('filter') (IE 9 only, #12537)
  5113. // .css('--customProperty) (#3144)
  5114. if ( computed ) {
  5115. ret = computed.getPropertyValue( name ) || computed[ name ];
  5116. if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
  5117. ret = jQuery.style( elem, name );
  5118. }
  5119. // A tribute to the "awesome hack by Dean Edwards"
  5120. // Android Browser returns percentage for some values,
  5121. // but width seems to be reliably pixels.
  5122. // This is against the CSSOM draft spec:
  5123. // https://drafts.csswg.org/cssom/#resolved-values
  5124. if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
  5125. // Remember the original values
  5126. width = style.width;
  5127. minWidth = style.minWidth;
  5128. maxWidth = style.maxWidth;
  5129. // Put in the new values to get a computed value out
  5130. style.minWidth = style.maxWidth = style.width = ret;
  5131. ret = computed.width;
  5132. // Revert the changed values
  5133. style.width = width;
  5134. style.minWidth = minWidth;
  5135. style.maxWidth = maxWidth;
  5136. }
  5137. }
  5138. return ret !== undefined ?
  5139. // Support: IE <=9 - 11 only
  5140. // IE returns zIndex value as an integer.
  5141. ret + "" :
  5142. ret;
  5143. }
  5144. function addGetHookIf( conditionFn, hookFn ) {
  5145. // Define the hook, we'll check on the first run if it's really needed.
  5146. return {
  5147. get: function() {
  5148. if ( conditionFn() ) {
  5149. // Hook not needed (or it's not possible to use it due
  5150. // to missing dependency), remove it.
  5151. delete this.get;
  5152. return;
  5153. }
  5154. // Hook needed; redefine it so that the support test is not executed again.
  5155. return ( this.get = hookFn ).apply( this, arguments );
  5156. }
  5157. };
  5158. }
  5159. var
  5160. // Swappable if display is none or starts with table
  5161. // except "table", "table-cell", or "table-caption"
  5162. // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  5163. rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  5164. rcustomProp = /^--/,
  5165. cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  5166. cssNormalTransform = {
  5167. letterSpacing: "0",
  5168. fontWeight: "400"
  5169. },
  5170. cssPrefixes = [ "Webkit", "Moz", "ms" ],
  5171. emptyStyle = document.createElement( "div" ).style;
  5172. // Return a css property mapped to a potentially vendor prefixed property
  5173. function vendorPropName( name ) {
  5174. // Shortcut for names that are not vendor prefixed
  5175. if ( name in emptyStyle ) {
  5176. return name;
  5177. }
  5178. // Check for vendor prefixed names
  5179. var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
  5180. i = cssPrefixes.length;
  5181. while ( i-- ) {
  5182. name = cssPrefixes[ i ] + capName;
  5183. if ( name in emptyStyle ) {
  5184. return name;
  5185. }
  5186. }
  5187. }
  5188. // Return a property mapped along what jQuery.cssProps suggests or to
  5189. // a vendor prefixed property.
  5190. function finalPropName( name ) {
  5191. var ret = jQuery.cssProps[ name ];
  5192. if ( !ret ) {
  5193. ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
  5194. }
  5195. return ret;
  5196. }
  5197. function setPositiveNumber( elem, value, subtract ) {
  5198. // Any relative (+/-) values have already been
  5199. // normalized at this point
  5200. var matches = rcssNum.exec( value );
  5201. return matches ?
  5202. // Guard against undefined "subtract", e.g., when used as in cssHooks
  5203. Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
  5204. value;
  5205. }
  5206. function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  5207. var i,
  5208. val = 0;
  5209. // If we already have the right measurement, avoid augmentation
  5210. if ( extra === ( isBorderBox ? "border" : "content" ) ) {
  5211. i = 4;
  5212. // Otherwise initialize for horizontal or vertical properties
  5213. } else {
  5214. i = name === "width" ? 1 : 0;
  5215. }
  5216. for ( ; i < 4; i += 2 ) {
  5217. // Both box models exclude margin, so add it if we want it
  5218. if ( extra === "margin" ) {
  5219. val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  5220. }
  5221. if ( isBorderBox ) {
  5222. // border-box includes padding, so remove it if we want content
  5223. if ( extra === "content" ) {
  5224. val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5225. }
  5226. // At this point, extra isn't border nor margin, so remove border
  5227. if ( extra !== "margin" ) {
  5228. val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5229. }
  5230. } else {
  5231. // At this point, extra isn't content, so add padding
  5232. val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5233. // At this point, extra isn't content nor padding, so add border
  5234. if ( extra !== "padding" ) {
  5235. val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5236. }
  5237. }
  5238. }
  5239. return val;
  5240. }
  5241. function getWidthOrHeight( elem, name, extra ) {
  5242. // Start with computed style
  5243. var valueIsBorderBox,
  5244. styles = getStyles( elem ),
  5245. val = curCSS( elem, name, styles ),
  5246. isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  5247. // Computed unit is not pixels. Stop here and return.
  5248. if ( rnumnonpx.test( val ) ) {
  5249. return val;
  5250. }
  5251. // Check for style in case a browser which returns unreliable values
  5252. // for getComputedStyle silently falls back to the reliable elem.style
  5253. valueIsBorderBox = isBorderBox &&
  5254. ( support.boxSizingReliable() || val === elem.style[ name ] );
  5255. // Fall back to offsetWidth/Height when value is "auto"
  5256. // This happens for inline elements with no explicit setting (gh-3571)
  5257. if ( val === "auto" ) {
  5258. val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
  5259. }
  5260. // Normalize "", auto, and prepare for extra
  5261. val = parseFloat( val ) || 0;
  5262. // Use the active box-sizing model to add/subtract irrelevant styles
  5263. return ( val +
  5264. augmentWidthOrHeight(
  5265. elem,
  5266. name,
  5267. extra || ( isBorderBox ? "border" : "content" ),
  5268. valueIsBorderBox,
  5269. styles
  5270. )
  5271. ) + "px";
  5272. }
  5273. jQuery.extend( {
  5274. // Add in style property hooks for overriding the default
  5275. // behavior of getting and setting a style property
  5276. cssHooks: {
  5277. opacity: {
  5278. get: function( elem, computed ) {
  5279. if ( computed ) {
  5280. // We should always get a number back from opacity
  5281. var ret = curCSS( elem, "opacity" );
  5282. return ret === "" ? "1" : ret;
  5283. }
  5284. }
  5285. }
  5286. },
  5287. // Don't automatically add "px" to these possibly-unitless properties
  5288. cssNumber: {
  5289. "animationIterationCount": true,
  5290. "columnCount": true,
  5291. "fillOpacity": true,
  5292. "flexGrow": true,
  5293. "flexShrink": true,
  5294. "fontWeight": true,
  5295. "lineHeight": true,
  5296. "opacity": true,
  5297. "order": true,
  5298. "orphans": true,
  5299. "widows": true,
  5300. "zIndex": true,
  5301. "zoom": true
  5302. },
  5303. // Add in properties whose names you wish to fix before
  5304. // setting or getting the value
  5305. cssProps: {
  5306. "float": "cssFloat"
  5307. },
  5308. // Get and set the style property on a DOM Node
  5309. style: function( elem, name, value, extra ) {
  5310. // Don't set styles on text and comment nodes
  5311. if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  5312. return;
  5313. }
  5314. // Make sure that we're working with the right name
  5315. var ret, type, hooks,
  5316. origName = jQuery.camelCase( name ),
  5317. isCustomProp = rcustomProp.test( name ),
  5318. style = elem.style;
  5319. // Make sure that we're working with the right name. We don't
  5320. // want to query the value if it is a CSS custom property
  5321. // since they are user-defined.
  5322. if ( !isCustomProp ) {
  5323. name = finalPropName( origName );
  5324. }
  5325. // Gets hook for the prefixed version, then unprefixed version
  5326. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  5327. // Check if we're setting a value
  5328. if ( value !== undefined ) {
  5329. type = typeof value;
  5330. // Convert "+=" or "-=" to relative numbers (#7345)
  5331. if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
  5332. value = adjustCSS( elem, name, ret );
  5333. // Fixes bug #9237
  5334. type = "number";
  5335. }
  5336. // Make sure that null and NaN values aren't set (#7116)
  5337. if ( value == null || value !== value ) {
  5338. return;
  5339. }
  5340. // If a number was passed in, add the unit (except for certain CSS properties)
  5341. if ( type === "number" ) {
  5342. value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
  5343. }
  5344. // background-* props affect original clone's values
  5345. if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  5346. style[ name ] = "inherit";
  5347. }
  5348. // If a hook was provided, use that value, otherwise just set the specified value
  5349. if ( !hooks || !( "set" in hooks ) ||
  5350. ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
  5351. if ( isCustomProp ) {
  5352. style.setProperty( name, value );
  5353. } else {
  5354. style[ name ] = value;
  5355. }
  5356. }
  5357. } else {
  5358. // If a hook was provided get the non-computed value from there
  5359. if ( hooks && "get" in hooks &&
  5360. ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
  5361. return ret;
  5362. }
  5363. // Otherwise just get the value from the style object
  5364. return style[ name ];
  5365. }
  5366. },
  5367. css: function( elem, name, extra, styles ) {
  5368. var val, num, hooks,
  5369. origName = jQuery.camelCase( name ),
  5370. isCustomProp = rcustomProp.test( name );
  5371. // Make sure that we're working with the right name. We don't
  5372. // want to modify the value if it is a CSS custom property
  5373. // since they are user-defined.
  5374. if ( !isCustomProp ) {
  5375. name = finalPropName( origName );
  5376. }
  5377. // Try prefixed name followed by the unprefixed name
  5378. hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  5379. // If a hook was provided get the computed value from there
  5380. if ( hooks && "get" in hooks ) {
  5381. val = hooks.get( elem, true, extra );
  5382. }
  5383. // Otherwise, if a way to get the computed value exists, use that
  5384. if ( val === undefined ) {
  5385. val = curCSS( elem, name, styles );
  5386. }
  5387. // Convert "normal" to computed value
  5388. if ( val === "normal" && name in cssNormalTransform ) {
  5389. val = cssNormalTransform[ name ];
  5390. }
  5391. // Make numeric if forced or a qualifier was provided and val looks numeric
  5392. if ( extra === "" || extra ) {
  5393. num = parseFloat( val );
  5394. return extra === true || isFinite( num ) ? num || 0 : val;
  5395. }
  5396. return val;
  5397. }
  5398. } );
  5399. jQuery.each( [ "height", "width" ], function( i, name ) {
  5400. jQuery.cssHooks[ name ] = {
  5401. get: function( elem, computed, extra ) {
  5402. if ( computed ) {
  5403. // Certain elements can have dimension info if we invisibly show them
  5404. // but it must have a current display style that would benefit
  5405. return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
  5406. // Support: Safari 8+
  5407. // Table columns in Safari have non-zero offsetWidth & zero
  5408. // getBoundingClientRect().width unless display is changed.
  5409. // Support: IE <=11 only
  5410. // Running getBoundingClientRect on a disconnected node
  5411. // in IE throws an error.
  5412. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
  5413. swap( elem, cssShow, function() {
  5414. return getWidthOrHeight( elem, name, extra );
  5415. } ) :
  5416. getWidthOrHeight( elem, name, extra );
  5417. }
  5418. },
  5419. set: function( elem, value, extra ) {
  5420. var matches,
  5421. styles = extra && getStyles( elem ),
  5422. subtract = extra && augmentWidthOrHeight(
  5423. elem,
  5424. name,
  5425. extra,
  5426. jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
  5427. styles
  5428. );
  5429. // Convert to pixels if value adjustment is needed
  5430. if ( subtract && ( matches = rcssNum.exec( value ) ) &&
  5431. ( matches[ 3 ] || "px" ) !== "px" ) {
  5432. elem.style[ name ] = value;
  5433. value = jQuery.css( elem, name );
  5434. }
  5435. return setPositiveNumber( elem, value, subtract );
  5436. }
  5437. };
  5438. } );
  5439. jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
  5440. function( elem, computed ) {
  5441. if ( computed ) {
  5442. return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
  5443. elem.getBoundingClientRect().left -
  5444. swap( elem, { marginLeft: 0 }, function() {
  5445. return elem.getBoundingClientRect().left;
  5446. } )
  5447. ) + "px";
  5448. }
  5449. }
  5450. );
  5451. // These hooks are used by animate to expand properties
  5452. jQuery.each( {
  5453. margin: "",
  5454. padding: "",
  5455. border: "Width"
  5456. }, function( prefix, suffix ) {
  5457. jQuery.cssHooks[ prefix + suffix ] = {
  5458. expand: function( value ) {
  5459. var i = 0,
  5460. expanded = {},
  5461. // Assumes a single number if not a string
  5462. parts = typeof value === "string" ? value.split( " " ) : [ value ];
  5463. for ( ; i < 4; i++ ) {
  5464. expanded[ prefix + cssExpand[ i ] + suffix ] =
  5465. parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  5466. }
  5467. return expanded;
  5468. }
  5469. };
  5470. if ( !rmargin.test( prefix ) ) {
  5471. jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
  5472. }
  5473. } );
  5474. jQuery.fn.extend( {
  5475. css: function( name, value ) {
  5476. return access( this, function( elem, name, value ) {
  5477. var styles, len,
  5478. map = {},
  5479. i = 0;
  5480. if ( Array.isArray( name ) ) {
  5481. styles = getStyles( elem );
  5482. len = name.length;
  5483. for ( ; i < len; i++ ) {
  5484. map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
  5485. }
  5486. return map;
  5487. }
  5488. return value !== undefined ?
  5489. jQuery.style( elem, name, value ) :
  5490. jQuery.css( elem, name );
  5491. }, name, value, arguments.length > 1 );
  5492. }
  5493. } );
  5494. function Tween( elem, options, prop, end, easing ) {
  5495. return new Tween.prototype.init( elem, options, prop, end, easing );
  5496. }
  5497. jQuery.Tween = Tween;
  5498. Tween.prototype = {
  5499. constructor: Tween,
  5500. init: function( elem, options, prop, end, easing, unit ) {
  5501. this.elem = elem;
  5502. this.prop = prop;
  5503. this.easing = easing || jQuery.easing._default;
  5504. this.options = options;
  5505. this.start = this.now = this.cur();
  5506. this.end = end;
  5507. this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
  5508. },
  5509. cur: function() {
  5510. var hooks = Tween.propHooks[ this.prop ];
  5511. return hooks && hooks.get ?
  5512. hooks.get( this ) :
  5513. Tween.propHooks._default.get( this );
  5514. },
  5515. run: function( percent ) {
  5516. var eased,
  5517. hooks = Tween.propHooks[ this.prop ];
  5518. if ( this.options.duration ) {
  5519. this.pos = eased = jQuery.easing[ this.easing ](
  5520. percent, this.options.duration * percent, 0, 1, this.options.duration
  5521. );
  5522. } else {
  5523. this.pos = eased = percent;
  5524. }
  5525. this.now = ( this.end - this.start ) * eased + this.start;
  5526. if ( this.options.step ) {
  5527. this.options.step.call( this.elem, this.now, this );
  5528. }
  5529. if ( hooks && hooks.set ) {
  5530. hooks.set( this );
  5531. } else {
  5532. Tween.propHooks._default.set( this );
  5533. }
  5534. return this;
  5535. }
  5536. };
  5537. Tween.prototype.init.prototype = Tween.prototype;
  5538. Tween.propHooks = {
  5539. _default: {
  5540. get: function( tween ) {
  5541. var result;
  5542. // Use a property on the element directly when it is not a DOM element,
  5543. // or when there is no matching style property that exists.
  5544. if ( tween.elem.nodeType !== 1 ||
  5545. tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
  5546. return tween.elem[ tween.prop ];
  5547. }
  5548. // Passing an empty string as a 3rd parameter to .css will automatically
  5549. // attempt a parseFloat and fallback to a string if the parse fails.
  5550. // Simple values such as "10px" are parsed to Float;
  5551. // complex values such as "rotate(1rad)" are returned as-is.
  5552. result = jQuery.css( tween.elem, tween.prop, "" );
  5553. // Empty strings, null, undefined and "auto" are converted to 0.
  5554. return !result || result === "auto" ? 0 : result;
  5555. },
  5556. set: function( tween ) {
  5557. // Use step hook for back compat.
  5558. // Use cssHook if its there.
  5559. // Use .style if available and use plain properties where available.
  5560. if ( jQuery.fx.step[ tween.prop ] ) {
  5561. jQuery.fx.step[ tween.prop ]( tween );
  5562. } else if ( tween.elem.nodeType === 1 &&
  5563. ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
  5564. jQuery.cssHooks[ tween.prop ] ) ) {
  5565. jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  5566. } else {
  5567. tween.elem[ tween.prop ] = tween.now;
  5568. }
  5569. }
  5570. }
  5571. };
  5572. // Support: IE <=9 only
  5573. // Panic based approach to setting things on disconnected nodes
  5574. Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  5575. set: function( tween ) {
  5576. if ( tween.elem.nodeType && tween.elem.parentNode ) {
  5577. tween.elem[ tween.prop ] = tween.now;
  5578. }
  5579. }
  5580. };
  5581. jQuery.easing = {
  5582. linear: function( p ) {
  5583. return p;
  5584. },
  5585. swing: function( p ) {
  5586. return 0.5 - Math.cos( p * Math.PI ) / 2;
  5587. },
  5588. _default: "swing"
  5589. };
  5590. jQuery.fx = Tween.prototype.init;
  5591. // Back compat <1.8 extension point
  5592. jQuery.fx.step = {};
  5593. var
  5594. fxNow, inProgress,
  5595. rfxtypes = /^(?:toggle|show|hide)$/,
  5596. rrun = /queueHooks$/;
  5597. function schedule() {
  5598. if ( inProgress ) {
  5599. if ( document.hidden === false && window.requestAnimationFrame ) {
  5600. window.requestAnimationFrame( schedule );
  5601. } else {
  5602. window.setTimeout( schedule, jQuery.fx.interval );
  5603. }
  5604. jQuery.fx.tick();
  5605. }
  5606. }
  5607. // Animations created synchronously will run synchronously
  5608. function createFxNow() {
  5609. window.setTimeout( function() {
  5610. fxNow = undefined;
  5611. } );
  5612. return ( fxNow = jQuery.now() );
  5613. }
  5614. // Generate parameters to create a standard animation
  5615. function genFx( type, includeWidth ) {
  5616. var which,
  5617. i = 0,
  5618. attrs = { height: type };
  5619. // If we include width, step value is 1 to do all cssExpand values,
  5620. // otherwise step value is 2 to skip over Left and Right
  5621. includeWidth = includeWidth ? 1 : 0;
  5622. for ( ; i < 4; i += 2 - includeWidth ) {
  5623. which = cssExpand[ i ];
  5624. attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  5625. }
  5626. if ( includeWidth ) {
  5627. attrs.opacity = attrs.width = type;
  5628. }
  5629. return attrs;
  5630. }
  5631. function createTween( value, prop, animation ) {
  5632. var tween,
  5633. collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
  5634. index = 0,
  5635. length = collection.length;
  5636. for ( ; index < length; index++ ) {
  5637. if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
  5638. // We're done with this property
  5639. return tween;
  5640. }
  5641. }
  5642. }
  5643. function defaultPrefilter( elem, props, opts ) {
  5644. var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
  5645. isBox = "width" in props || "height" in props,
  5646. anim = this,
  5647. orig = {},
  5648. style = elem.style,
  5649. hidden = elem.nodeType && isHiddenWithinTree( elem ),
  5650. dataShow = dataPriv.get( elem, "fxshow" );
  5651. // Queue-skipping animations hijack the fx hooks
  5652. if ( !opts.queue ) {
  5653. hooks = jQuery._queueHooks( elem, "fx" );
  5654. if ( hooks.unqueued == null ) {
  5655. hooks.unqueued = 0;
  5656. oldfire = hooks.empty.fire;
  5657. hooks.empty.fire = function() {
  5658. if ( !hooks.unqueued ) {
  5659. oldfire();
  5660. }
  5661. };
  5662. }
  5663. hooks.unqueued++;
  5664. anim.always( function() {
  5665. // Ensure the complete handler is called before this completes
  5666. anim.always( function() {
  5667. hooks.unqueued--;
  5668. if ( !jQuery.queue( elem, "fx" ).length ) {
  5669. hooks.empty.fire();
  5670. }
  5671. } );
  5672. } );
  5673. }
  5674. // Detect show/hide animations
  5675. for ( prop in props ) {
  5676. value = props[ prop ];
  5677. if ( rfxtypes.test( value ) ) {
  5678. delete props[ prop ];
  5679. toggle = toggle || value === "toggle";
  5680. if ( value === ( hidden ? "hide" : "show" ) ) {
  5681. // Pretend to be hidden if this is a "show" and
  5682. // there is still data from a stopped show/hide
  5683. if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
  5684. hidden = true;
  5685. // Ignore all other no-op show/hide data
  5686. } else {
  5687. continue;
  5688. }
  5689. }
  5690. orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
  5691. }
  5692. }
  5693. // Bail out if this is a no-op like .hide().hide()
  5694. propTween = !jQuery.isEmptyObject( props );
  5695. if ( !propTween && jQuery.isEmptyObject( orig ) ) {
  5696. return;
  5697. }
  5698. // Restrict "overflow" and "display" styles during box animations
  5699. if ( isBox && elem.nodeType === 1 ) {
  5700. // Support: IE <=9 - 11, Edge 12 - 13
  5701. // Record all 3 overflow attributes because IE does not infer the shorthand
  5702. // from identically-valued overflowX and overflowY
  5703. opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
  5704. // Identify a display type, preferring old show/hide data over the CSS cascade
  5705. restoreDisplay = dataShow && dataShow.display;
  5706. if ( restoreDisplay == null ) {
  5707. restoreDisplay = dataPriv.get( elem, "display" );
  5708. }
  5709. display = jQuery.css( elem, "display" );
  5710. if ( display === "none" ) {
  5711. if ( restoreDisplay ) {
  5712. display = restoreDisplay;
  5713. } else {
  5714. // Get nonempty value(s) by temporarily forcing visibility
  5715. showHide( [ elem ], true );
  5716. restoreDisplay = elem.style.display || restoreDisplay;
  5717. display = jQuery.css( elem, "display" );
  5718. showHide( [ elem ] );
  5719. }
  5720. }
  5721. // Animate inline elements as inline-block
  5722. if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
  5723. if ( jQuery.css( elem, "float" ) === "none" ) {
  5724. // Restore the original display value at the end of pure show/hide animations
  5725. if ( !propTween ) {
  5726. anim.done( function() {
  5727. style.display = restoreDisplay;
  5728. } );
  5729. if ( restoreDisplay == null ) {
  5730. display = style.display;
  5731. restoreDisplay = display === "none" ? "" : display;
  5732. }
  5733. }
  5734. style.display = "inline-block";
  5735. }
  5736. }
  5737. }
  5738. if ( opts.overflow ) {
  5739. style.overflow = "hidden";
  5740. anim.always( function() {
  5741. style.overflow = opts.overflow[ 0 ];
  5742. style.overflowX = opts.overflow[ 1 ];
  5743. style.overflowY = opts.overflow[ 2 ];
  5744. } );
  5745. }
  5746. // Implement show/hide animations
  5747. propTween = false;
  5748. for ( prop in orig ) {
  5749. // General show/hide setup for this element animation
  5750. if ( !propTween ) {
  5751. if ( dataShow ) {
  5752. if ( "hidden" in dataShow ) {
  5753. hidden = dataShow.hidden;
  5754. }
  5755. } else {
  5756. dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
  5757. }
  5758. // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
  5759. if ( toggle ) {
  5760. dataShow.hidden = !hidden;
  5761. }
  5762. // Show elements before animating them
  5763. if ( hidden ) {
  5764. showHide( [ elem ], true );
  5765. }
  5766. /* eslint-disable no-loop-func */
  5767. anim.done( function() {
  5768. /* eslint-enable no-loop-func */
  5769. // The final step of a "hide" animation is actually hiding the element
  5770. if ( !hidden ) {
  5771. showHide( [ elem ] );
  5772. }
  5773. dataPriv.remove( elem, "fxshow" );
  5774. for ( prop in orig ) {
  5775. jQuery.style( elem, prop, orig[ prop ] );
  5776. }
  5777. } );
  5778. }
  5779. // Per-property setup
  5780. propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
  5781. if ( !( prop in dataShow ) ) {
  5782. dataShow[ prop ] = propTween.start;
  5783. if ( hidden ) {
  5784. propTween.end = propTween.start;
  5785. propTween.start = 0;
  5786. }
  5787. }
  5788. }
  5789. }
  5790. function propFilter( props, specialEasing ) {
  5791. var index, name, easing, value, hooks;
  5792. // camelCase, specialEasing and expand cssHook pass
  5793. for ( index in props ) {
  5794. name = jQuery.camelCase( index );
  5795. easing = specialEasing[ name ];
  5796. value = props[ index ];
  5797. if ( Array.isArray( value ) ) {
  5798. easing = value[ 1 ];
  5799. value = props[ index ] = value[ 0 ];
  5800. }
  5801. if ( index !== name ) {
  5802. props[ name ] = value;
  5803. delete props[ index ];
  5804. }
  5805. hooks = jQuery.cssHooks[ name ];
  5806. if ( hooks && "expand" in hooks ) {
  5807. value = hooks.expand( value );
  5808. delete props[ name ];
  5809. // Not quite $.extend, this won't overwrite existing keys.
  5810. // Reusing 'index' because we have the correct "name"
  5811. for ( index in value ) {
  5812. if ( !( index in props ) ) {
  5813. props[ index ] = value[ index ];
  5814. specialEasing[ index ] = easing;
  5815. }
  5816. }
  5817. } else {
  5818. specialEasing[ name ] = easing;
  5819. }
  5820. }
  5821. }
  5822. function Animation( elem, properties, options ) {
  5823. var result,
  5824. stopped,
  5825. index = 0,
  5826. length = Animation.prefilters.length,
  5827. deferred = jQuery.Deferred().always( function() {
  5828. // Don't match elem in the :animated selector
  5829. delete tick.elem;
  5830. } ),
  5831. tick = function() {
  5832. if ( stopped ) {
  5833. return false;
  5834. }
  5835. var currentTime = fxNow || createFxNow(),
  5836. remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  5837. // Support: Android 2.3 only
  5838. // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
  5839. temp = remaining / animation.duration || 0,
  5840. percent = 1 - temp,
  5841. index = 0,
  5842. length = animation.tweens.length;
  5843. for ( ; index < length; index++ ) {
  5844. animation.tweens[ index ].run( percent );
  5845. }
  5846. deferred.notifyWith( elem, [ animation, percent, remaining ] );
  5847. // If there's more to do, yield
  5848. if ( percent < 1 && length ) {
  5849. return remaining;
  5850. }
  5851. // If this was an empty animation, synthesize a final progress notification
  5852. if ( !length ) {
  5853. deferred.notifyWith( elem, [ animation, 1, 0 ] );
  5854. }
  5855. // Resolve the animation and report its conclusion
  5856. deferred.resolveWith( elem, [ animation ] );
  5857. return false;
  5858. },
  5859. animation = deferred.promise( {
  5860. elem: elem,
  5861. props: jQuery.extend( {}, properties ),
  5862. opts: jQuery.extend( true, {
  5863. specialEasing: {},
  5864. easing: jQuery.easing._default
  5865. }, options ),
  5866. originalProperties: properties,
  5867. originalOptions: options,
  5868. startTime: fxNow || createFxNow(),
  5869. duration: options.duration,
  5870. tweens: [],
  5871. createTween: function( prop, end ) {
  5872. var tween = jQuery.Tween( elem, animation.opts, prop, end,
  5873. animation.opts.specialEasing[ prop ] || animation.opts.easing );
  5874. animation.tweens.push( tween );
  5875. return tween;
  5876. },
  5877. stop: function( gotoEnd ) {
  5878. var index = 0,
  5879. // If we are going to the end, we want to run all the tweens
  5880. // otherwise we skip this part
  5881. length = gotoEnd ? animation.tweens.length : 0;
  5882. if ( stopped ) {
  5883. return this;
  5884. }
  5885. stopped = true;
  5886. for ( ; index < length; index++ ) {
  5887. animation.tweens[ index ].run( 1 );
  5888. }
  5889. // Resolve when we played the last frame; otherwise, reject
  5890. if ( gotoEnd ) {
  5891. deferred.notifyWith( elem, [ animation, 1, 0 ] );
  5892. deferred.resolveWith( elem, [ animation, gotoEnd ] );
  5893. } else {
  5894. deferred.rejectWith( elem, [ animation, gotoEnd ] );
  5895. }
  5896. return this;
  5897. }
  5898. } ),
  5899. props = animation.props;
  5900. propFilter( props, animation.opts.specialEasing );
  5901. for ( ; index < length; index++ ) {
  5902. result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
  5903. if ( result ) {
  5904. if ( jQuery.isFunction( result.stop ) ) {
  5905. jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
  5906. jQuery.proxy( result.stop, result );
  5907. }
  5908. return result;
  5909. }
  5910. }
  5911. jQuery.map( props, createTween, animation );
  5912. if ( jQuery.isFunction( animation.opts.start ) ) {
  5913. animation.opts.start.call( elem, animation );
  5914. }
  5915. // Attach callbacks from options
  5916. animation
  5917. .progress( animation.opts.progress )
  5918. .done( animation.opts.done, animation.opts.complete )
  5919. .fail( animation.opts.fail )
  5920. .always( animation.opts.always );
  5921. jQuery.fx.timer(
  5922. jQuery.extend( tick, {
  5923. elem: elem,
  5924. anim: animation,
  5925. queue: animation.opts.queue
  5926. } )
  5927. );
  5928. return animation;
  5929. }
  5930. jQuery.Animation = jQuery.extend( Animation, {
  5931. tweeners: {
  5932. "*": [ function( prop, value ) {
  5933. var tween = this.createTween( prop, value );
  5934. adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
  5935. return tween;
  5936. } ]
  5937. },
  5938. tweener: function( props, callback ) {
  5939. if ( jQuery.isFunction( props ) ) {
  5940. callback = props;
  5941. props = [ "*" ];
  5942. } else {
  5943. props = props.match( rnothtmlwhite );
  5944. }
  5945. var prop,
  5946. index = 0,
  5947. length = props.length;
  5948. for ( ; index < length; index++ ) {
  5949. prop = props[ index ];
  5950. Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
  5951. Animation.tweeners[ prop ].unshift( callback );
  5952. }
  5953. },
  5954. prefilters: [ defaultPrefilter ],
  5955. prefilter: function( callback, prepend ) {
  5956. if ( prepend ) {
  5957. Animation.prefilters.unshift( callback );
  5958. } else {
  5959. Animation.prefilters.push( callback );
  5960. }
  5961. }
  5962. } );
  5963. jQuery.speed = function( speed, easing, fn ) {
  5964. var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
  5965. complete: fn || !fn && easing ||
  5966. jQuery.isFunction( speed ) && speed,
  5967. duration: speed,
  5968. easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
  5969. };
  5970. // Go to the end state if fx are off
  5971. if ( jQuery.fx.off ) {
  5972. opt.duration = 0;
  5973. } else {
  5974. if ( typeof opt.duration !== "number" ) {
  5975. if ( opt.duration in jQuery.fx.speeds ) {
  5976. opt.duration = jQuery.fx.speeds[ opt.duration ];
  5977. } else {
  5978. opt.duration = jQuery.fx.speeds._default;
  5979. }
  5980. }
  5981. }
  5982. // Normalize opt.queue - true/undefined/null -> "fx"
  5983. if ( opt.queue == null || opt.queue === true ) {
  5984. opt.queue = "fx";
  5985. }
  5986. // Queueing
  5987. opt.old = opt.complete;
  5988. opt.complete = function() {
  5989. if ( jQuery.isFunction( opt.old ) ) {
  5990. opt.old.call( this );
  5991. }
  5992. if ( opt.queue ) {
  5993. jQuery.dequeue( this, opt.queue );
  5994. }
  5995. };
  5996. return opt;
  5997. };
  5998. jQuery.fn.extend( {
  5999. fadeTo: function( speed, to, easing, callback ) {
  6000. // Show any hidden elements after setting opacity to 0
  6001. return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
  6002. // Animate to the value specified
  6003. .end().animate( { opacity: to }, speed, easing, callback );
  6004. },
  6005. animate: function( prop, speed, easing, callback ) {
  6006. var empty = jQuery.isEmptyObject( prop ),
  6007. optall = jQuery.speed( speed, easing, callback ),
  6008. doAnimation = function() {
  6009. // Operate on a copy of prop so per-property easing won't be lost
  6010. var anim = Animation( this, jQuery.extend( {}, prop ), optall );
  6011. // Empty animations, or finishing resolves immediately
  6012. if ( empty || dataPriv.get( this, "finish" ) ) {
  6013. anim.stop( true );
  6014. }
  6015. };
  6016. doAnimation.finish = doAnimation;
  6017. return empty || optall.queue === false ?
  6018. this.each( doAnimation ) :
  6019. this.queue( optall.queue, doAnimation );
  6020. },
  6021. stop: function( type, clearQueue, gotoEnd ) {
  6022. var stopQueue = function( hooks ) {
  6023. var stop = hooks.stop;
  6024. delete hooks.stop;
  6025. stop( gotoEnd );
  6026. };
  6027. if ( typeof type !== "string" ) {
  6028. gotoEnd = clearQueue;
  6029. clearQueue = type;
  6030. type = undefined;
  6031. }
  6032. if ( clearQueue && type !== false ) {
  6033. this.queue( type || "fx", [] );
  6034. }
  6035. return this.each( function() {
  6036. var dequeue = true,
  6037. index = type != null && type + "queueHooks",
  6038. timers = jQuery.timers,
  6039. data = dataPriv.get( this );
  6040. if ( index ) {
  6041. if ( data[ index ] && data[ index ].stop ) {
  6042. stopQueue( data[ index ] );
  6043. }
  6044. } else {
  6045. for ( index in data ) {
  6046. if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
  6047. stopQueue( data[ index ] );
  6048. }
  6049. }
  6050. }
  6051. for ( index = timers.length; index--; ) {
  6052. if ( timers[ index ].elem === this &&
  6053. ( type == null || timers[ index ].queue === type ) ) {
  6054. timers[ index ].anim.stop( gotoEnd );
  6055. dequeue = false;
  6056. timers.splice( index, 1 );
  6057. }
  6058. }
  6059. // Start the next in the queue if the last step wasn't forced.
  6060. // Timers currently will call their complete callbacks, which
  6061. // will dequeue but only if they were gotoEnd.
  6062. if ( dequeue || !gotoEnd ) {
  6063. jQuery.dequeue( this, type );
  6064. }
  6065. } );
  6066. },
  6067. finish: function( type ) {
  6068. if ( type !== false ) {
  6069. type = type || "fx";
  6070. }
  6071. return this.each( function() {
  6072. var index,
  6073. data = dataPriv.get( this ),
  6074. queue = data[ type + "queue" ],
  6075. hooks = data[ type + "queueHooks" ],
  6076. timers = jQuery.timers,
  6077. length = queue ? queue.length : 0;
  6078. // Enable finishing flag on private data
  6079. data.finish = true;
  6080. // Empty the queue first
  6081. jQuery.queue( this, type, [] );
  6082. if ( hooks && hooks.stop ) {
  6083. hooks.stop.call( this, true );
  6084. }
  6085. // Look for any active animations, and finish them
  6086. for ( index = timers.length; index--; ) {
  6087. if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  6088. timers[ index ].anim.stop( true );
  6089. timers.splice( index, 1 );
  6090. }
  6091. }
  6092. // Look for any animations in the old queue and finish them
  6093. for ( index = 0; index < length; index++ ) {
  6094. if ( queue[ index ] && queue[ index ].finish ) {
  6095. queue[ index ].finish.call( this );
  6096. }
  6097. }
  6098. // Turn off finishing flag
  6099. delete data.finish;
  6100. } );
  6101. }
  6102. } );
  6103. jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
  6104. var cssFn = jQuery.fn[ name ];
  6105. jQuery.fn[ name ] = function( speed, easing, callback ) {
  6106. return speed == null || typeof speed === "boolean" ?
  6107. cssFn.apply( this, arguments ) :
  6108. this.animate( genFx( name, true ), speed, easing, callback );
  6109. };
  6110. } );
  6111. // Generate shortcuts for custom animations
  6112. jQuery.each( {
  6113. slideDown: genFx( "show" ),
  6114. slideUp: genFx( "hide" ),
  6115. slideToggle: genFx( "toggle" ),
  6116. fadeIn: { opacity: "show" },
  6117. fadeOut: { opacity: "hide" },
  6118. fadeToggle: { opacity: "toggle" }
  6119. }, function( name, props ) {
  6120. jQuery.fn[ name ] = function( speed, easing, callback ) {
  6121. return this.animate( props, speed, easing, callback );
  6122. };
  6123. } );
  6124. jQuery.timers = [];
  6125. jQuery.fx.tick = function() {
  6126. var timer,
  6127. i = 0,
  6128. timers = jQuery.timers;
  6129. fxNow = jQuery.now();
  6130. for ( ; i < timers.length; i++ ) {
  6131. timer = timers[ i ];
  6132. // Run the timer and safely remove it when done (allowing for external removal)
  6133. if ( !timer() && timers[ i ] === timer ) {
  6134. timers.splice( i--, 1 );
  6135. }
  6136. }
  6137. if ( !timers.length ) {
  6138. jQuery.fx.stop();
  6139. }
  6140. fxNow = undefined;
  6141. };
  6142. jQuery.fx.timer = function( timer ) {
  6143. jQuery.timers.push( timer );
  6144. jQuery.fx.start();
  6145. };
  6146. jQuery.fx.interval = 13;
  6147. jQuery.fx.start = function() {
  6148. if ( inProgress ) {
  6149. return;
  6150. }
  6151. inProgress = true;
  6152. schedule();
  6153. };
  6154. jQuery.fx.stop = function() {
  6155. inProgress = null;
  6156. };
  6157. jQuery.fx.speeds = {
  6158. slow: 600,
  6159. fast: 200,
  6160. // Default speed
  6161. _default: 400
  6162. };
  6163. // Based off of the plugin by Clint Helfers, with permission.
  6164. // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
  6165. jQuery.fn.delay = function( time, type ) {
  6166. time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
  6167. type = type || "fx";
  6168. return this.queue( type, function( next, hooks ) {
  6169. var timeout = window.setTimeout( next, time );
  6170. hooks.stop = function() {
  6171. window.clearTimeout( timeout );
  6172. };
  6173. } );
  6174. };
  6175. ( function() {
  6176. var input = document.createElement( "input" ),
  6177. select = document.createElement( "select" ),
  6178. opt = select.appendChild( document.createElement( "option" ) );
  6179. input.type = "checkbox";
  6180. // Support: Android <=4.3 only
  6181. // Default value for a checkbox should be "on"
  6182. support.checkOn = input.value !== "";
  6183. // Support: IE <=11 only
  6184. // Must access selectedIndex to make default options select
  6185. support.optSelected = opt.selected;
  6186. // Support: IE <=11 only
  6187. // An input loses its value after becoming a radio
  6188. input = document.createElement( "input" );
  6189. input.value = "t";
  6190. input.type = "radio";
  6191. support.radioValue = input.value === "t";
  6192. } )();
  6193. var boolHook,
  6194. attrHandle = jQuery.expr.attrHandle;
  6195. jQuery.fn.extend( {
  6196. attr: function( name, value ) {
  6197. return access( this, jQuery.attr, name, value, arguments.length > 1 );
  6198. },
  6199. removeAttr: function( name ) {
  6200. return this.each( function() {
  6201. jQuery.removeAttr( this, name );
  6202. } );
  6203. }
  6204. } );
  6205. jQuery.extend( {
  6206. attr: function( elem, name, value ) {
  6207. var ret, hooks,
  6208. nType = elem.nodeType;
  6209. // Don't get/set attributes on text, comment and attribute nodes
  6210. if ( nType === 3 || nType === 8 || nType === 2 ) {
  6211. return;
  6212. }
  6213. // Fallback to prop when attributes are not supported
  6214. if ( typeof elem.getAttribute === "undefined" ) {
  6215. return jQuery.prop( elem, name, value );
  6216. }
  6217. // Attribute hooks are determined by the lowercase version
  6218. // Grab necessary hook if one is defined
  6219. if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
  6220. hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
  6221. ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
  6222. }
  6223. if ( value !== undefined ) {
  6224. if ( value === null ) {
  6225. jQuery.removeAttr( elem, name );
  6226. return;
  6227. }
  6228. if ( hooks && "set" in hooks &&
  6229. ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
  6230. return ret;
  6231. }
  6232. elem.setAttribute( name, value + "" );
  6233. return value;
  6234. }
  6235. if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
  6236. return ret;
  6237. }
  6238. ret = jQuery.find.attr( elem, name );
  6239. // Non-existent attributes return null, we normalize to undefined
  6240. return ret == null ? undefined : ret;
  6241. },
  6242. attrHooks: {
  6243. type: {
  6244. set: function( elem, value ) {
  6245. if ( !support.radioValue && value === "radio" &&
  6246. nodeName( elem, "input" ) ) {
  6247. var val = elem.value;
  6248. elem.setAttribute( "type", value );
  6249. if ( val ) {
  6250. elem.value = val;
  6251. }
  6252. return value;
  6253. }
  6254. }
  6255. }
  6256. },
  6257. removeAttr: function( elem, value ) {
  6258. var name,
  6259. i = 0,
  6260. // Attribute names can contain non-HTML whitespace characters
  6261. // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
  6262. attrNames = value && value.match( rnothtmlwhite );
  6263. if ( attrNames && elem.nodeType === 1 ) {
  6264. while ( ( name = attrNames[ i++ ] ) ) {
  6265. elem.removeAttribute( name );
  6266. }
  6267. }
  6268. }
  6269. } );
  6270. // Hooks for boolean attributes
  6271. boolHook = {
  6272. set: function( elem, value, name ) {
  6273. if ( value === false ) {
  6274. // Remove boolean attributes when set to false
  6275. jQuery.removeAttr( elem, name );
  6276. } else {
  6277. elem.setAttribute( name, name );
  6278. }
  6279. return name;
  6280. }
  6281. };
  6282. jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
  6283. var getter = attrHandle[ name ] || jQuery.find.attr;
  6284. attrHandle[ name ] = function( elem, name, isXML ) {
  6285. var ret, handle,
  6286. lowercaseName = name.toLowerCase();
  6287. if ( !isXML ) {
  6288. // Avoid an infinite loop by temporarily removing this function from the getter
  6289. handle = attrHandle[ lowercaseName ];
  6290. attrHandle[ lowercaseName ] = ret;
  6291. ret = getter( elem, name, isXML ) != null ?
  6292. lowercaseName :
  6293. null;
  6294. attrHandle[ lowercaseName ] = handle;
  6295. }
  6296. return ret;
  6297. };
  6298. } );
  6299. var rfocusable = /^(?:input|select|textarea|button)$/i,
  6300. rclickable = /^(?:a|area)$/i;
  6301. jQuery.fn.extend( {
  6302. prop: function( name, value ) {
  6303. return access( this, jQuery.prop, name, value, arguments.length > 1 );
  6304. },
  6305. removeProp: function( name ) {
  6306. return this.each( function() {
  6307. delete this[ jQuery.propFix[ name ] || name ];
  6308. } );
  6309. }
  6310. } );
  6311. jQuery.extend( {
  6312. prop: function( elem, name, value ) {
  6313. var ret, hooks,
  6314. nType = elem.nodeType;
  6315. // Don't get/set properties on text, comment and attribute nodes
  6316. if ( nType === 3 || nType === 8 || nType === 2 ) {
  6317. return;
  6318. }
  6319. if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
  6320. // Fix name and attach hooks
  6321. name = jQuery.propFix[ name ] || name;
  6322. hooks = jQuery.propHooks[ name ];
  6323. }
  6324. if ( value !== undefined ) {
  6325. if ( hooks && "set" in hooks &&
  6326. ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
  6327. return ret;
  6328. }
  6329. return ( elem[ name ] = value );
  6330. }
  6331. if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
  6332. return ret;
  6333. }
  6334. return elem[ name ];
  6335. },
  6336. propHooks: {
  6337. tabIndex: {
  6338. get: function( elem ) {
  6339. // Support: IE <=9 - 11 only
  6340. // elem.tabIndex doesn't always return the
  6341. // correct value when it hasn't been explicitly set
  6342. // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
  6343. // Use proper attribute retrieval(#12072)
  6344. var tabindex = jQuery.find.attr( elem, "tabindex" );
  6345. if ( tabindex ) {
  6346. return parseInt( tabindex, 10 );
  6347. }
  6348. if (
  6349. rfocusable.test( elem.nodeName ) ||
  6350. rclickable.test( elem.nodeName ) &&
  6351. elem.href
  6352. ) {
  6353. return 0;
  6354. }
  6355. return -1;
  6356. }
  6357. }
  6358. },
  6359. propFix: {
  6360. "for": "htmlFor",
  6361. "class": "className"
  6362. }
  6363. } );
  6364. // Support: IE <=11 only
  6365. // Accessing the selectedIndex property
  6366. // forces the browser to respect setting selected
  6367. // on the option
  6368. // The getter ensures a default option is selected
  6369. // when in an optgroup
  6370. // eslint rule "no-unused-expressions" is disabled for this code
  6371. // since it considers such accessions noop
  6372. if ( !support.optSelected ) {
  6373. jQuery.propHooks.selected = {
  6374. get: function( elem ) {
  6375. /* eslint no-unused-expressions: "off" */
  6376. var parent = elem.parentNode;
  6377. if ( parent && parent.parentNode ) {
  6378. parent.parentNode.selectedIndex;
  6379. }
  6380. return null;
  6381. },
  6382. set: function( elem ) {
  6383. /* eslint no-unused-expressions: "off" */
  6384. var parent = elem.parentNode;
  6385. if ( parent ) {
  6386. parent.selectedIndex;
  6387. if ( parent.parentNode ) {
  6388. parent.parentNode.selectedIndex;
  6389. }
  6390. }
  6391. }
  6392. };
  6393. }
  6394. jQuery.each( [
  6395. "tabIndex",
  6396. "readOnly",
  6397. "maxLength",
  6398. "cellSpacing",
  6399. "cellPadding",
  6400. "rowSpan",
  6401. "colSpan",
  6402. "useMap",
  6403. "frameBorder",
  6404. "contentEditable"
  6405. ], function() {
  6406. jQuery.propFix[ this.toLowerCase() ] = this;
  6407. } );
  6408. // Strip and collapse whitespace according to HTML spec
  6409. // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
  6410. function stripAndCollapse( value ) {
  6411. var tokens = value.match( rnothtmlwhite ) || [];
  6412. return tokens.join( " " );
  6413. }
  6414. function getClass( elem ) {
  6415. return elem.getAttribute && elem.getAttribute( "class" ) || "";
  6416. }
  6417. jQuery.fn.extend( {
  6418. addClass: function( value ) {
  6419. var classes, elem, cur, curValue, clazz, j, finalValue,
  6420. i = 0;
  6421. if ( jQuery.isFunction( value ) ) {
  6422. return this.each( function( j ) {
  6423. jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
  6424. } );
  6425. }
  6426. if ( typeof value === "string" && value ) {
  6427. classes = value.match( rnothtmlwhite ) || [];
  6428. while ( ( elem = this[ i++ ] ) ) {
  6429. curValue = getClass( elem );
  6430. cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
  6431. if ( cur ) {
  6432. j = 0;
  6433. while ( ( clazz = classes[ j++ ] ) ) {
  6434. if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
  6435. cur += clazz + " ";
  6436. }
  6437. }
  6438. // Only assign if different to avoid unneeded rendering.
  6439. finalValue = stripAndCollapse( cur );
  6440. if ( curValue !== finalValue ) {
  6441. elem.setAttribute( "class", finalValue );
  6442. }
  6443. }
  6444. }
  6445. }
  6446. return this;
  6447. },
  6448. removeClass: function( value ) {
  6449. var classes, elem, cur, curValue, clazz, j, finalValue,
  6450. i = 0;
  6451. if ( jQuery.isFunction( value ) ) {
  6452. return this.each( function( j ) {
  6453. jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
  6454. } );
  6455. }
  6456. if ( !arguments.length ) {
  6457. return this.attr( "class", "" );
  6458. }
  6459. if ( typeof value === "string" && value ) {
  6460. classes = value.match( rnothtmlwhite ) || [];
  6461. while ( ( elem = this[ i++ ] ) ) {
  6462. curValue = getClass( elem );
  6463. // This expression is here for better compressibility (see addClass)
  6464. cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
  6465. if ( cur ) {
  6466. j = 0;
  6467. while ( ( clazz = classes[ j++ ] ) ) {
  6468. // Remove *all* instances
  6469. while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
  6470. cur = cur.replace( " " + clazz + " ", " " );
  6471. }
  6472. }
  6473. // Only assign if different to avoid unneeded rendering.
  6474. finalValue = stripAndCollapse( cur );
  6475. if ( curValue !== finalValue ) {
  6476. elem.setAttribute( "class", finalValue );
  6477. }
  6478. }
  6479. }
  6480. }
  6481. return this;
  6482. },
  6483. toggleClass: function( value, stateVal ) {
  6484. var type = typeof value;
  6485. if ( typeof stateVal === "boolean" && type === "string" ) {
  6486. return stateVal ? this.addClass( value ) : this.removeClass( value );
  6487. }
  6488. if ( jQuery.isFunction( value ) ) {
  6489. return this.each( function( i ) {
  6490. jQuery( this ).toggleClass(
  6491. value.call( this, i, getClass( this ), stateVal ),
  6492. stateVal
  6493. );
  6494. } );
  6495. }
  6496. return this.each( function() {
  6497. var className, i, self, classNames;
  6498. if ( type === "string" ) {
  6499. // Toggle individual class names
  6500. i = 0;
  6501. self = jQuery( this );
  6502. classNames = value.match( rnothtmlwhite ) || [];
  6503. while ( ( className = classNames[ i++ ] ) ) {
  6504. // Check each className given, space separated list
  6505. if ( self.hasClass( className ) ) {
  6506. self.removeClass( className );
  6507. } else {
  6508. self.addClass( className );
  6509. }
  6510. }
  6511. // Toggle whole class name
  6512. } else if ( value === undefined || type === "boolean" ) {
  6513. className = getClass( this );
  6514. if ( className ) {
  6515. // Store className if set
  6516. dataPriv.set( this, "__className__", className );
  6517. }
  6518. // If the element has a class name or if we're passed `false`,
  6519. // then remove the whole classname (if there was one, the above saved it).
  6520. // Otherwise bring back whatever was previously saved (if anything),
  6521. // falling back to the empty string if nothing was stored.
  6522. if ( this.setAttribute ) {
  6523. this.setAttribute( "class",
  6524. className || value === false ?
  6525. "" :
  6526. dataPriv.get( this, "__className__" ) || ""
  6527. );
  6528. }
  6529. }
  6530. } );
  6531. },
  6532. hasClass: function( selector ) {
  6533. var className, elem,
  6534. i = 0;
  6535. className = " " + selector + " ";
  6536. while ( ( elem = this[ i++ ] ) ) {
  6537. if ( elem.nodeType === 1 &&
  6538. ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
  6539. return true;
  6540. }
  6541. }
  6542. return false;
  6543. }
  6544. } );
  6545. var rreturn = /\r/g;
  6546. jQuery.fn.extend( {
  6547. val: function( value ) {
  6548. var hooks, ret, isFunction,
  6549. elem = this[ 0 ];
  6550. if ( !arguments.length ) {
  6551. if ( elem ) {
  6552. hooks = jQuery.valHooks[ elem.type ] ||
  6553. jQuery.valHooks[ elem.nodeName.toLowerCase() ];
  6554. if ( hooks &&
  6555. "get" in hooks &&
  6556. ( ret = hooks.get( elem, "value" ) ) !== undefined
  6557. ) {
  6558. return ret;
  6559. }
  6560. ret = elem.value;
  6561. // Handle most common string cases
  6562. if ( typeof ret === "string" ) {
  6563. return ret.replace( rreturn, "" );
  6564. }
  6565. // Handle cases where value is null/undef or number
  6566. return ret == null ? "" : ret;
  6567. }
  6568. return;
  6569. }
  6570. isFunction = jQuery.isFunction( value );
  6571. return this.each( function( i ) {
  6572. var val;
  6573. if ( this.nodeType !== 1 ) {
  6574. return;
  6575. }
  6576. if ( isFunction ) {
  6577. val = value.call( this, i, jQuery( this ).val() );
  6578. } else {
  6579. val = value;
  6580. }
  6581. // Treat null/undefined as ""; convert numbers to string
  6582. if ( val == null ) {
  6583. val = "";
  6584. } else if ( typeof val === "number" ) {
  6585. val += "";
  6586. } else if ( Array.isArray( val ) ) {
  6587. val = jQuery.map( val, function( value ) {
  6588. return value == null ? "" : value + "";
  6589. } );
  6590. }
  6591. hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
  6592. // If set returns undefined, fall back to normal setting
  6593. if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
  6594. this.value = val;
  6595. }
  6596. } );
  6597. }
  6598. } );
  6599. jQuery.extend( {
  6600. valHooks: {
  6601. option: {
  6602. get: function( elem ) {
  6603. var val = jQuery.find.attr( elem, "value" );
  6604. return val != null ?
  6605. val :
  6606. // Support: IE <=10 - 11 only
  6607. // option.text throws exceptions (#14686, #14858)
  6608. // Strip and collapse whitespace
  6609. // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
  6610. stripAndCollapse( jQuery.text( elem ) );
  6611. }
  6612. },
  6613. select: {
  6614. get: function( elem ) {
  6615. var value, option, i,
  6616. options = elem.options,
  6617. index = elem.selectedIndex,
  6618. one = elem.type === "select-one",
  6619. values = one ? null : [],
  6620. max = one ? index + 1 : options.length;
  6621. if ( index < 0 ) {
  6622. i = max;
  6623. } else {
  6624. i = one ? index : 0;
  6625. }
  6626. // Loop through all the selected options
  6627. for ( ; i < max; i++ ) {
  6628. option = options[ i ];
  6629. // Support: IE <=9 only
  6630. // IE8-9 doesn't update selected after form reset (#2551)
  6631. if ( ( option.selected || i === index ) &&
  6632. // Don't return options that are disabled or in a disabled optgroup
  6633. !option.disabled &&
  6634. ( !option.parentNode.disabled ||
  6635. !nodeName( option.parentNode, "optgroup" ) ) ) {
  6636. // Get the specific value for the option
  6637. value = jQuery( option ).val();
  6638. // We don't need an array for one selects
  6639. if ( one ) {
  6640. return value;
  6641. }
  6642. // Multi-Selects return an array
  6643. values.push( value );
  6644. }
  6645. }
  6646. return values;
  6647. },
  6648. set: function( elem, value ) {
  6649. var optionSet, option,
  6650. options = elem.options,
  6651. values = jQuery.makeArray( value ),
  6652. i = options.length;
  6653. while ( i-- ) {
  6654. option = options[ i ];
  6655. /* eslint-disable no-cond-assign */
  6656. if ( option.selected =
  6657. jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
  6658. ) {
  6659. optionSet = true;
  6660. }
  6661. /* eslint-enable no-cond-assign */
  6662. }
  6663. // Force browsers to behave consistently when non-matching value is set
  6664. if ( !optionSet ) {
  6665. elem.selectedIndex = -1;
  6666. }
  6667. return values;
  6668. }
  6669. }
  6670. }
  6671. } );
  6672. // Radios and checkboxes getter/setter
  6673. jQuery.each( [ "radio", "checkbox" ], function() {
  6674. jQuery.valHooks[ this ] = {
  6675. set: function( elem, value ) {
  6676. if ( Array.isArray( value ) ) {
  6677. return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
  6678. }
  6679. }
  6680. };
  6681. if ( !support.checkOn ) {
  6682. jQuery.valHooks[ this ].get = function( elem ) {
  6683. return elem.getAttribute( "value" ) === null ? "on" : elem.value;
  6684. };
  6685. }
  6686. } );
  6687. // Return jQuery for attributes-only inclusion
  6688. var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
  6689. jQuery.extend( jQuery.event, {
  6690. trigger: function( event, data, elem, onlyHandlers ) {
  6691. var i, cur, tmp, bubbleType, ontype, handle, special,
  6692. eventPath = [ elem || document ],
  6693. type = hasOwn.call( event, "type" ) ? event.type : event,
  6694. namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
  6695. cur = tmp = elem = elem || document;
  6696. // Don't do events on text and comment nodes
  6697. if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  6698. return;
  6699. }
  6700. // focus/blur morphs to focusin/out; ensure we're not firing them right now
  6701. if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  6702. return;
  6703. }
  6704. if ( type.indexOf( "." ) > -1 ) {
  6705. // Namespaced trigger; create a regexp to match event type in handle()
  6706. namespaces = type.split( "." );
  6707. type = namespaces.shift();
  6708. namespaces.sort();
  6709. }
  6710. ontype = type.indexOf( ":" ) < 0 && "on" + type;
  6711. // Caller can pass in a jQuery.Event object, Object, or just an event type string
  6712. event = event[ jQuery.expando ] ?
  6713. event :
  6714. new jQuery.Event( type, typeof event === "object" && event );
  6715. // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  6716. event.isTrigger = onlyHandlers ? 2 : 3;
  6717. event.namespace = namespaces.join( "." );
  6718. event.rnamespace = event.namespace ?
  6719. new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
  6720. null;
  6721. // Clean up the event in case it is being reused
  6722. event.result = undefined;
  6723. if ( !event.target ) {
  6724. event.target = elem;
  6725. }
  6726. // Clone any incoming data and prepend the event, creating the handler arg list
  6727. data = data == null ?
  6728. [ event ] :
  6729. jQuery.makeArray( data, [ event ] );
  6730. // Allow special events to draw outside the lines
  6731. special = jQuery.event.special[ type ] || {};
  6732. if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  6733. return;
  6734. }
  6735. // Determine event propagation path in advance, per W3C events spec (#9951)
  6736. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  6737. if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  6738. bubbleType = special.delegateType || type;
  6739. if ( !rfocusMorph.test( bubbleType + type ) ) {
  6740. cur = cur.parentNode;
  6741. }
  6742. for ( ; cur; cur = cur.parentNode ) {
  6743. eventPath.push( cur );
  6744. tmp = cur;
  6745. }
  6746. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  6747. if ( tmp === ( elem.ownerDocument || document ) ) {
  6748. eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  6749. }
  6750. }
  6751. // Fire handlers on the event path
  6752. i = 0;
  6753. while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
  6754. event.type = i > 1 ?
  6755. bubbleType :
  6756. special.bindType || type;
  6757. // jQuery handler
  6758. handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
  6759. dataPriv.get( cur, "handle" );
  6760. if ( handle ) {
  6761. handle.apply( cur, data );
  6762. }
  6763. // Native handler
  6764. handle = ontype && cur[ ontype ];
  6765. if ( handle && handle.apply && acceptData( cur ) ) {
  6766. event.result = handle.apply( cur, data );
  6767. if ( event.result === false ) {
  6768. event.preventDefault();
  6769. }
  6770. }
  6771. }
  6772. event.type = type;
  6773. // If nobody prevented the default action, do it now
  6774. if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  6775. if ( ( !special._default ||
  6776. special._default.apply( eventPath.pop(), data ) === false ) &&
  6777. acceptData( elem ) ) {
  6778. // Call a native DOM method on the target with the same name as the event.
  6779. // Don't do default actions on window, that's where global variables be (#6170)
  6780. if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  6781. // Don't re-trigger an onFOO event when we call its FOO() method
  6782. tmp = elem[ ontype ];
  6783. if ( tmp ) {
  6784. elem[ ontype ] = null;
  6785. }
  6786. // Prevent re-triggering of the same event, since we already bubbled it above
  6787. jQuery.event.triggered = type;
  6788. elem[ type ]();
  6789. jQuery.event.triggered = undefined;
  6790. if ( tmp ) {
  6791. elem[ ontype ] = tmp;
  6792. }
  6793. }
  6794. }
  6795. }
  6796. return event.result;
  6797. },
  6798. // Piggyback on a donor event to simulate a different one
  6799. // Used only for `focus(in | out)` events
  6800. simulate: function( type, elem, event ) {
  6801. var e = jQuery.extend(
  6802. new jQuery.Event(),
  6803. event,
  6804. {
  6805. type: type,
  6806. isSimulated: true
  6807. }
  6808. );
  6809. jQuery.event.trigger( e, null, elem );
  6810. }
  6811. } );
  6812. jQuery.fn.extend( {
  6813. trigger: function( type, data ) {
  6814. return this.each( function() {
  6815. jQuery.event.trigger( type, data, this );
  6816. } );
  6817. },
  6818. triggerHandler: function( type, data ) {
  6819. var elem = this[ 0 ];
  6820. if ( elem ) {
  6821. return jQuery.event.trigger( type, data, elem, true );
  6822. }
  6823. }
  6824. } );
  6825. jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
  6826. "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
  6827. "change select submit keydown keypress keyup contextmenu" ).split( " " ),
  6828. function( i, name ) {
  6829. // Handle event binding
  6830. jQuery.fn[ name ] = function( data, fn ) {
  6831. return arguments.length > 0 ?
  6832. this.on( name, null, data, fn ) :
  6833. this.trigger( name );
  6834. };
  6835. } );
  6836. jQuery.fn.extend( {
  6837. hover: function( fnOver, fnOut ) {
  6838. return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
  6839. }
  6840. } );
  6841. support.focusin = "onfocusin" in window;
  6842. // Support: Firefox <=44
  6843. // Firefox doesn't have focus(in | out) events
  6844. // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
  6845. //
  6846. // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
  6847. // focus(in | out) events fire after focus & blur events,
  6848. // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
  6849. // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
  6850. if ( !support.focusin ) {
  6851. jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  6852. // Attach a single capturing handler on the document while someone wants focusin/focusout
  6853. var handler = function( event ) {
  6854. jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
  6855. };
  6856. jQuery.event.special[ fix ] = {
  6857. setup: function() {
  6858. var doc = this.ownerDocument || this,
  6859. attaches = dataPriv.access( doc, fix );
  6860. if ( !attaches ) {
  6861. doc.addEventListener( orig, handler, true );
  6862. }
  6863. dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
  6864. },
  6865. teardown: function() {
  6866. var doc = this.ownerDocument || this,
  6867. attaches = dataPriv.access( doc, fix ) - 1;
  6868. if ( !attaches ) {
  6869. doc.removeEventListener( orig, handler, true );
  6870. dataPriv.remove( doc, fix );
  6871. } else {
  6872. dataPriv.access( doc, fix, attaches );
  6873. }
  6874. }
  6875. };
  6876. } );
  6877. }
  6878. var location = window.location;
  6879. var nonce = jQuery.now();
  6880. var rquery = ( /\?/ );
  6881. // Cross-browser xml parsing
  6882. jQuery.parseXML = function( data ) {
  6883. var xml;
  6884. if ( !data || typeof data !== "string" ) {
  6885. return null;
  6886. }
  6887. // Support: IE 9 - 11 only
  6888. // IE throws on parseFromString with invalid input.
  6889. try {
  6890. xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
  6891. } catch ( e ) {
  6892. xml = undefined;
  6893. }
  6894. if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
  6895. jQuery.error( "Invalid XML: " + data );
  6896. }
  6897. return xml;
  6898. };
  6899. var
  6900. rbracket = /\[\]$/,
  6901. rCRLF = /\r?\n/g,
  6902. rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
  6903. rsubmittable = /^(?:input|select|textarea|keygen)/i;
  6904. function buildParams( prefix, obj, traditional, add ) {
  6905. var name;
  6906. if ( Array.isArray( obj ) ) {
  6907. // Serialize array item.
  6908. jQuery.each( obj, function( i, v ) {
  6909. if ( traditional || rbracket.test( prefix ) ) {
  6910. // Treat each array item as a scalar.
  6911. add( prefix, v );
  6912. } else {
  6913. // Item is non-scalar (array or object), encode its numeric index.
  6914. buildParams(
  6915. prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
  6916. v,
  6917. traditional,
  6918. add
  6919. );
  6920. }
  6921. } );
  6922. } else if ( !traditional && jQuery.type( obj ) === "object" ) {
  6923. // Serialize object item.
  6924. for ( name in obj ) {
  6925. buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
  6926. }
  6927. } else {
  6928. // Serialize scalar item.
  6929. add( prefix, obj );
  6930. }
  6931. }
  6932. // Serialize an array of form elements or a set of
  6933. // key/values into a query string
  6934. jQuery.param = function( a, traditional ) {
  6935. var prefix,
  6936. s = [],
  6937. add = function( key, valueOrFunction ) {
  6938. // If value is a function, invoke it and use its return value
  6939. var value = jQuery.isFunction( valueOrFunction ) ?
  6940. valueOrFunction() :
  6941. valueOrFunction;
  6942. s[ s.length ] = encodeURIComponent( key ) + "=" +
  6943. encodeURIComponent( value == null ? "" : value );
  6944. };
  6945. // If an array was passed in, assume that it is an array of form elements.
  6946. if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
  6947. // Serialize the form elements
  6948. jQuery.each( a, function() {
  6949. add( this.name, this.value );
  6950. } );
  6951. } else {
  6952. // If traditional, encode the "old" way (the way 1.3.2 or older
  6953. // did it), otherwise encode params recursively.
  6954. for ( prefix in a ) {
  6955. buildParams( prefix, a[ prefix ], traditional, add );
  6956. }
  6957. }
  6958. // Return the resulting serialization
  6959. return s.join( "&" );
  6960. };
  6961. jQuery.fn.extend( {
  6962. serialize: function() {
  6963. return jQuery.param( this.serializeArray() );
  6964. },
  6965. serializeArray: function() {
  6966. return this.map( function() {
  6967. // Can add propHook for "elements" to filter or add form elements
  6968. var elements = jQuery.prop( this, "elements" );
  6969. return elements ? jQuery.makeArray( elements ) : this;
  6970. } )
  6971. .filter( function() {
  6972. var type = this.type;
  6973. // Use .is( ":disabled" ) so that fieldset[disabled] works
  6974. return this.name && !jQuery( this ).is( ":disabled" ) &&
  6975. rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
  6976. ( this.checked || !rcheckableType.test( type ) );
  6977. } )
  6978. .map( function( i, elem ) {
  6979. var val = jQuery( this ).val();
  6980. if ( val == null ) {
  6981. return null;
  6982. }
  6983. if ( Array.isArray( val ) ) {
  6984. return jQuery.map( val, function( val ) {
  6985. return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  6986. } );
  6987. }
  6988. return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  6989. } ).get();
  6990. }
  6991. } );
  6992. var
  6993. r20 = /%20/g,
  6994. rhash = /#.*$/,
  6995. rantiCache = /([?&])_=[^&]*/,
  6996. rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  6997. // #7653, #8125, #8152: local protocol detection
  6998. rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  6999. rnoContent = /^(?:GET|HEAD)$/,
  7000. rprotocol = /^\/\//,
  7001. /* Prefilters
  7002. * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  7003. * 2) These are called:
  7004. * - BEFORE asking for a transport
  7005. * - AFTER param serialization (s.data is a string if s.processData is true)
  7006. * 3) key is the dataType
  7007. * 4) the catchall symbol "*" can be used
  7008. * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  7009. */
  7010. prefilters = {},
  7011. /* Transports bindings
  7012. * 1) key is the dataType
  7013. * 2) the catchall symbol "*" can be used
  7014. * 3) selection will start with transport dataType and THEN go to "*" if needed
  7015. */
  7016. transports = {},
  7017. // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  7018. allTypes = "*/".concat( "*" ),
  7019. // Anchor tag for parsing the document origin
  7020. originAnchor = document.createElement( "a" );
  7021. originAnchor.href = location.href;
  7022. // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  7023. function addToPrefiltersOrTransports( structure ) {
  7024. // dataTypeExpression is optional and defaults to "*"
  7025. return function( dataTypeExpression, func ) {
  7026. if ( typeof dataTypeExpression !== "string" ) {
  7027. func = dataTypeExpression;
  7028. dataTypeExpression = "*";
  7029. }
  7030. var dataType,
  7031. i = 0,
  7032. dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
  7033. if ( jQuery.isFunction( func ) ) {
  7034. // For each dataType in the dataTypeExpression
  7035. while ( ( dataType = dataTypes[ i++ ] ) ) {
  7036. // Prepend if requested
  7037. if ( dataType[ 0 ] === "+" ) {
  7038. dataType = dataType.slice( 1 ) || "*";
  7039. ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
  7040. // Otherwise append
  7041. } else {
  7042. ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
  7043. }
  7044. }
  7045. }
  7046. };
  7047. }
  7048. // Base inspection function for prefilters and transports
  7049. function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
  7050. var inspected = {},
  7051. seekingTransport = ( structure === transports );
  7052. function inspect( dataType ) {
  7053. var selected;
  7054. inspected[ dataType ] = true;
  7055. jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
  7056. var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
  7057. if ( typeof dataTypeOrTransport === "string" &&
  7058. !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
  7059. options.dataTypes.unshift( dataTypeOrTransport );
  7060. inspect( dataTypeOrTransport );
  7061. return false;
  7062. } else if ( seekingTransport ) {
  7063. return !( selected = dataTypeOrTransport );
  7064. }
  7065. } );
  7066. return selected;
  7067. }
  7068. return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
  7069. }
  7070. // A special extend for ajax options
  7071. // that takes "flat" options (not to be deep extended)
  7072. // Fixes #9887
  7073. function ajaxExtend( target, src ) {
  7074. var key, deep,
  7075. flatOptions = jQuery.ajaxSettings.flatOptions || {};
  7076. for ( key in src ) {
  7077. if ( src[ key ] !== undefined ) {
  7078. ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
  7079. }
  7080. }
  7081. if ( deep ) {
  7082. jQuery.extend( true, target, deep );
  7083. }
  7084. return target;
  7085. }
  7086. /* Handles responses to an ajax request:
  7087. * - finds the right dataType (mediates between content-type and expected dataType)
  7088. * - returns the corresponding response
  7089. */
  7090. function ajaxHandleResponses( s, jqXHR, responses ) {
  7091. var ct, type, finalDataType, firstDataType,
  7092. contents = s.contents,
  7093. dataTypes = s.dataTypes;
  7094. // Remove auto dataType and get content-type in the process
  7095. while ( dataTypes[ 0 ] === "*" ) {
  7096. dataTypes.shift();
  7097. if ( ct === undefined ) {
  7098. ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
  7099. }
  7100. }
  7101. // Check if we're dealing with a known content-type
  7102. if ( ct ) {
  7103. for ( type in contents ) {
  7104. if ( contents[ type ] && contents[ type ].test( ct ) ) {
  7105. dataTypes.unshift( type );
  7106. break;
  7107. }
  7108. }
  7109. }
  7110. // Check to see if we have a response for the expected dataType
  7111. if ( dataTypes[ 0 ] in responses ) {
  7112. finalDataType = dataTypes[ 0 ];
  7113. } else {
  7114. // Try convertible dataTypes
  7115. for ( type in responses ) {
  7116. if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
  7117. finalDataType = type;
  7118. break;
  7119. }
  7120. if ( !firstDataType ) {
  7121. firstDataType = type;
  7122. }
  7123. }
  7124. // Or just use first one
  7125. finalDataType = finalDataType || firstDataType;
  7126. }
  7127. // If we found a dataType
  7128. // We add the dataType to the list if needed
  7129. // and return the corresponding response
  7130. if ( finalDataType ) {
  7131. if ( finalDataType !== dataTypes[ 0 ] ) {
  7132. dataTypes.unshift( finalDataType );
  7133. }
  7134. return responses[ finalDataType ];
  7135. }
  7136. }
  7137. /* Chain conversions given the request and the original response
  7138. * Also sets the responseXXX fields on the jqXHR instance
  7139. */
  7140. function ajaxConvert( s, response, jqXHR, isSuccess ) {
  7141. var conv2, current, conv, tmp, prev,
  7142. converters = {},
  7143. // Work with a copy of dataTypes in case we need to modify it for conversion
  7144. dataTypes = s.dataTypes.slice();
  7145. // Create converters map with lowercased keys
  7146. if ( dataTypes[ 1 ] ) {
  7147. for ( conv in s.converters ) {
  7148. converters[ conv.toLowerCase() ] = s.converters[ conv ];
  7149. }
  7150. }
  7151. current = dataTypes.shift();
  7152. // Convert to each sequential dataType
  7153. while ( current ) {
  7154. if ( s.responseFields[ current ] ) {
  7155. jqXHR[ s.responseFields[ current ] ] = response;
  7156. }
  7157. // Apply the dataFilter if provided
  7158. if ( !prev && isSuccess && s.dataFilter ) {
  7159. response = s.dataFilter( response, s.dataType );
  7160. }
  7161. prev = current;
  7162. current = dataTypes.shift();
  7163. if ( current ) {
  7164. // There's only work to do if current dataType is non-auto
  7165. if ( current === "*" ) {
  7166. current = prev;
  7167. // Convert response if prev dataType is non-auto and differs from current
  7168. } else if ( prev !== "*" && prev !== current ) {
  7169. // Seek a direct converter
  7170. conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  7171. // If none found, seek a pair
  7172. if ( !conv ) {
  7173. for ( conv2 in converters ) {
  7174. // If conv2 outputs current
  7175. tmp = conv2.split( " " );
  7176. if ( tmp[ 1 ] === current ) {
  7177. // If prev can be converted to accepted input
  7178. conv = converters[ prev + " " + tmp[ 0 ] ] ||
  7179. converters[ "* " + tmp[ 0 ] ];
  7180. if ( conv ) {
  7181. // Condense equivalence converters
  7182. if ( conv === true ) {
  7183. conv = converters[ conv2 ];
  7184. // Otherwise, insert the intermediate dataType
  7185. } else if ( converters[ conv2 ] !== true ) {
  7186. current = tmp[ 0 ];
  7187. dataTypes.unshift( tmp[ 1 ] );
  7188. }
  7189. break;
  7190. }
  7191. }
  7192. }
  7193. }
  7194. // Apply converter (if not an equivalence)
  7195. if ( conv !== true ) {
  7196. // Unless errors are allowed to bubble, catch and return them
  7197. if ( conv && s.throws ) {
  7198. response = conv( response );
  7199. } else {
  7200. try {
  7201. response = conv( response );
  7202. } catch ( e ) {
  7203. return {
  7204. state: "parsererror",
  7205. error: conv ? e : "No conversion from " + prev + " to " + current
  7206. };
  7207. }
  7208. }
  7209. }
  7210. }
  7211. }
  7212. }
  7213. return { state: "success", data: response };
  7214. }
  7215. jQuery.extend( {
  7216. // Counter for holding the number of active queries
  7217. active: 0,
  7218. // Last-Modified header cache for next request
  7219. lastModified: {},
  7220. etag: {},
  7221. ajaxSettings: {
  7222. url: location.href,
  7223. type: "GET",
  7224. isLocal: rlocalProtocol.test( location.protocol ),
  7225. global: true,
  7226. processData: true,
  7227. async: true,
  7228. contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  7229. /*
  7230. timeout: 0,
  7231. data: null,
  7232. dataType: null,
  7233. username: null,
  7234. password: null,
  7235. cache: null,
  7236. throws: false,
  7237. traditional: false,
  7238. headers: {},
  7239. */
  7240. accepts: {
  7241. "*": allTypes,
  7242. text: "text/plain",
  7243. html: "text/html",
  7244. xml: "application/xml, text/xml",
  7245. json: "application/json, text/javascript"
  7246. },
  7247. contents: {
  7248. xml: /\bxml\b/,
  7249. html: /\bhtml/,
  7250. json: /\bjson\b/
  7251. },
  7252. responseFields: {
  7253. xml: "responseXML",
  7254. text: "responseText",
  7255. json: "responseJSON"
  7256. },
  7257. // Data converters
  7258. // Keys separate source (or catchall "*") and destination types with a single space
  7259. converters: {
  7260. // Convert anything to text
  7261. "* text": String,
  7262. // Text to html (true = no transformation)
  7263. "text html": true,
  7264. // Evaluate text as a json expression
  7265. "text json": JSON.parse,
  7266. // Parse text as xml
  7267. "text xml": jQuery.parseXML
  7268. },
  7269. // For options that shouldn't be deep extended:
  7270. // you can add your own custom options here if
  7271. // and when you create one that shouldn't be
  7272. // deep extended (see ajaxExtend)
  7273. flatOptions: {
  7274. url: true,
  7275. context: true
  7276. }
  7277. },
  7278. // Creates a full fledged settings object into target
  7279. // with both ajaxSettings and settings fields.
  7280. // If target is omitted, writes into ajaxSettings.
  7281. ajaxSetup: function( target, settings ) {
  7282. return settings ?
  7283. // Building a settings object
  7284. ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
  7285. // Extending ajaxSettings
  7286. ajaxExtend( jQuery.ajaxSettings, target );
  7287. },
  7288. ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
  7289. ajaxTransport: addToPrefiltersOrTransports( transports ),
  7290. // Main method
  7291. ajax: function( url, options ) {
  7292. // If url is an object, simulate pre-1.5 signature
  7293. if ( typeof url === "object" ) {
  7294. options = url;
  7295. url = undefined;
  7296. }
  7297. // Force options to be an object
  7298. options = options || {};
  7299. var transport,
  7300. // URL without anti-cache param
  7301. cacheURL,
  7302. // Response headers
  7303. responseHeadersString,
  7304. responseHeaders,
  7305. // timeout handle
  7306. timeoutTimer,
  7307. // Url cleanup var
  7308. urlAnchor,
  7309. // Request state (becomes false upon send and true upon completion)
  7310. completed,
  7311. // To know if global events are to be dispatched
  7312. fireGlobals,
  7313. // Loop variable
  7314. i,
  7315. // uncached part of the url
  7316. uncached,
  7317. // Create the final options object
  7318. s = jQuery.ajaxSetup( {}, options ),
  7319. // Callbacks context
  7320. callbackContext = s.context || s,
  7321. // Context for global events is callbackContext if it is a DOM node or jQuery collection
  7322. globalEventContext = s.context &&
  7323. ( callbackContext.nodeType || callbackContext.jquery ) ?
  7324. jQuery( callbackContext ) :
  7325. jQuery.event,
  7326. // Deferreds
  7327. deferred = jQuery.Deferred(),
  7328. completeDeferred = jQuery.Callbacks( "once memory" ),
  7329. // Status-dependent callbacks
  7330. statusCode = s.statusCode || {},
  7331. // Headers (they are sent all at once)
  7332. requestHeaders = {},
  7333. requestHeadersNames = {},
  7334. // Default abort message
  7335. strAbort = "canceled",
  7336. // Fake xhr
  7337. jqXHR = {
  7338. readyState: 0,
  7339. // Builds headers hashtable if needed
  7340. getResponseHeader: function( key ) {
  7341. var match;
  7342. if ( completed ) {
  7343. if ( !responseHeaders ) {
  7344. responseHeaders = {};
  7345. while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
  7346. responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
  7347. }
  7348. }
  7349. match = responseHeaders[ key.toLowerCase() ];
  7350. }
  7351. return match == null ? null : match;
  7352. },
  7353. // Raw string
  7354. getAllResponseHeaders: function() {
  7355. return completed ? responseHeadersString : null;
  7356. },
  7357. // Caches the header
  7358. setRequestHeader: function( name, value ) {
  7359. if ( completed == null ) {
  7360. name = requestHeadersNames[ name.toLowerCase() ] =
  7361. requestHeadersNames[ name.toLowerCase() ] || name;
  7362. requestHeaders[ name ] = value;
  7363. }
  7364. return this;
  7365. },
  7366. // Overrides response content-type header
  7367. overrideMimeType: function( type ) {
  7368. if ( completed == null ) {
  7369. s.mimeType = type;
  7370. }
  7371. return this;
  7372. },
  7373. // Status-dependent callbacks
  7374. statusCode: function( map ) {
  7375. var code;
  7376. if ( map ) {
  7377. if ( completed ) {
  7378. // Execute the appropriate callbacks
  7379. jqXHR.always( map[ jqXHR.status ] );
  7380. } else {
  7381. // Lazy-add the new callbacks in a way that preserves old ones
  7382. for ( code in map ) {
  7383. statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
  7384. }
  7385. }
  7386. }
  7387. return this;
  7388. },
  7389. // Cancel the request
  7390. abort: function( statusText ) {
  7391. var finalText = statusText || strAbort;
  7392. if ( transport ) {
  7393. transport.abort( finalText );
  7394. }
  7395. done( 0, finalText );
  7396. return this;
  7397. }
  7398. };
  7399. // Attach deferreds
  7400. deferred.promise( jqXHR );
  7401. // Add protocol if not provided (prefilters might expect it)
  7402. // Handle falsy url in the settings object (#10093: consistency with old signature)
  7403. // We also use the url parameter if available
  7404. s.url = ( ( url || s.url || location.href ) + "" )
  7405. .replace( rprotocol, location.protocol + "//" );
  7406. // Alias method option to type as per ticket #12004
  7407. s.type = options.method || options.type || s.method || s.type;
  7408. // Extract dataTypes list
  7409. s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
  7410. // A cross-domain request is in order when the origin doesn't match the current origin.
  7411. if ( s.crossDomain == null ) {
  7412. urlAnchor = document.createElement( "a" );
  7413. // Support: IE <=8 - 11, Edge 12 - 13
  7414. // IE throws exception on accessing the href property if url is malformed,
  7415. // e.g. http://example.com:80x/
  7416. try {
  7417. urlAnchor.href = s.url;
  7418. // Support: IE <=8 - 11 only
  7419. // Anchor's host property isn't correctly set when s.url is relative
  7420. urlAnchor.href = urlAnchor.href;
  7421. s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
  7422. urlAnchor.protocol + "//" + urlAnchor.host;
  7423. } catch ( e ) {
  7424. // If there is an error parsing the URL, assume it is crossDomain,
  7425. // it can be rejected by the transport if it is invalid
  7426. s.crossDomain = true;
  7427. }
  7428. }
  7429. // Convert data if not already a string
  7430. if ( s.data && s.processData && typeof s.data !== "string" ) {
  7431. s.data = jQuery.param( s.data, s.traditional );
  7432. }
  7433. // Apply prefilters
  7434. inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
  7435. // If request was aborted inside a prefilter, stop there
  7436. if ( completed ) {
  7437. return jqXHR;
  7438. }
  7439. // We can fire global events as of now if asked to
  7440. // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
  7441. fireGlobals = jQuery.event && s.global;
  7442. // Watch for a new set of requests
  7443. if ( fireGlobals && jQuery.active++ === 0 ) {
  7444. jQuery.event.trigger( "ajaxStart" );
  7445. }
  7446. // Uppercase the type
  7447. s.type = s.type.toUpperCase();
  7448. // Determine if request has content
  7449. s.hasContent = !rnoContent.test( s.type );
  7450. // Save the URL in case we're toying with the If-Modified-Since
  7451. // and/or If-None-Match header later on
  7452. // Remove hash to simplify url manipulation
  7453. cacheURL = s.url.replace( rhash, "" );
  7454. // More options handling for requests with no content
  7455. if ( !s.hasContent ) {
  7456. // Remember the hash so we can put it back
  7457. uncached = s.url.slice( cacheURL.length );
  7458. // If data is available, append data to url
  7459. if ( s.data ) {
  7460. cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
  7461. // #9682: remove data so that it's not used in an eventual retry
  7462. delete s.data;
  7463. }
  7464. // Add or update anti-cache param if needed
  7465. if ( s.cache === false ) {
  7466. cacheURL = cacheURL.replace( rantiCache, "$1" );
  7467. uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
  7468. }
  7469. // Put hash and anti-cache on the URL that will be requested (gh-1732)
  7470. s.url = cacheURL + uncached;
  7471. // Change '%20' to '+' if this is encoded form body content (gh-2658)
  7472. } else if ( s.data && s.processData &&
  7473. ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
  7474. s.data = s.data.replace( r20, "+" );
  7475. }
  7476. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  7477. if ( s.ifModified ) {
  7478. if ( jQuery.lastModified[ cacheURL ] ) {
  7479. jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
  7480. }
  7481. if ( jQuery.etag[ cacheURL ] ) {
  7482. jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
  7483. }
  7484. }
  7485. // Set the correct header, if data is being sent
  7486. if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
  7487. jqXHR.setRequestHeader( "Content-Type", s.contentType );
  7488. }
  7489. // Set the Accepts header for the server, depending on the dataType
  7490. jqXHR.setRequestHeader(
  7491. "Accept",
  7492. s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
  7493. s.accepts[ s.dataTypes[ 0 ] ] +
  7494. ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
  7495. s.accepts[ "*" ]
  7496. );
  7497. // Check for headers option
  7498. for ( i in s.headers ) {
  7499. jqXHR.setRequestHeader( i, s.headers[ i ] );
  7500. }
  7501. // Allow custom headers/mimetypes and early abort
  7502. if ( s.beforeSend &&
  7503. ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
  7504. // Abort if not done already and return
  7505. return jqXHR.abort();
  7506. }
  7507. // Aborting is no longer a cancellation
  7508. strAbort = "abort";
  7509. // Install callbacks on deferreds
  7510. completeDeferred.add( s.complete );
  7511. jqXHR.done( s.success );
  7512. jqXHR.fail( s.error );
  7513. // Get transport
  7514. transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
  7515. // If no transport, we auto-abort
  7516. if ( !transport ) {
  7517. done( -1, "No Transport" );
  7518. } else {
  7519. jqXHR.readyState = 1;
  7520. // Send global event
  7521. if ( fireGlobals ) {
  7522. globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
  7523. }
  7524. // If request was aborted inside ajaxSend, stop there
  7525. if ( completed ) {
  7526. return jqXHR;
  7527. }
  7528. // Timeout
  7529. if ( s.async && s.timeout > 0 ) {
  7530. timeoutTimer = window.setTimeout( function() {
  7531. jqXHR.abort( "timeout" );
  7532. }, s.timeout );
  7533. }
  7534. try {
  7535. completed = false;
  7536. transport.send( requestHeaders, done );
  7537. } catch ( e ) {
  7538. // Rethrow post-completion exceptions
  7539. if ( completed ) {
  7540. throw e;
  7541. }
  7542. // Propagate others as results
  7543. done( -1, e );
  7544. }
  7545. }
  7546. // Callback for when everything is done
  7547. function done( status, nativeStatusText, responses, headers ) {
  7548. var isSuccess, success, error, response, modified,
  7549. statusText = nativeStatusText;
  7550. // Ignore repeat invocations
  7551. if ( completed ) {
  7552. return;
  7553. }
  7554. completed = true;
  7555. // Clear timeout if it exists
  7556. if ( timeoutTimer ) {
  7557. window.clearTimeout( timeoutTimer );
  7558. }
  7559. // Dereference transport for early garbage collection
  7560. // (no matter how long the jqXHR object will be used)
  7561. transport = undefined;
  7562. // Cache response headers
  7563. responseHeadersString = headers || "";
  7564. // Set readyState
  7565. jqXHR.readyState = status > 0 ? 4 : 0;
  7566. // Determine if successful
  7567. isSuccess = status >= 200 && status < 300 || status === 304;
  7568. // Get response data
  7569. if ( responses ) {
  7570. response = ajaxHandleResponses( s, jqXHR, responses );
  7571. }
  7572. // Convert no matter what (that way responseXXX fields are always set)
  7573. response = ajaxConvert( s, response, jqXHR, isSuccess );
  7574. // If successful, handle type chaining
  7575. if ( isSuccess ) {
  7576. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  7577. if ( s.ifModified ) {
  7578. modified = jqXHR.getResponseHeader( "Last-Modified" );
  7579. if ( modified ) {
  7580. jQuery.lastModified[ cacheURL ] = modified;
  7581. }
  7582. modified = jqXHR.getResponseHeader( "etag" );
  7583. if ( modified ) {
  7584. jQuery.etag[ cacheURL ] = modified;
  7585. }
  7586. }
  7587. // if no content
  7588. if ( status === 204 || s.type === "HEAD" ) {
  7589. statusText = "nocontent";
  7590. // if not modified
  7591. } else if ( status === 304 ) {
  7592. statusText = "notmodified";
  7593. // If we have data, let's convert it
  7594. } else {
  7595. statusText = response.state;
  7596. success = response.data;
  7597. error = response.error;
  7598. isSuccess = !error;
  7599. }
  7600. } else {
  7601. // Extract error from statusText and normalize for non-aborts
  7602. error = statusText;
  7603. if ( status || !statusText ) {
  7604. statusText = "error";
  7605. if ( status < 0 ) {
  7606. status = 0;
  7607. }
  7608. }
  7609. }
  7610. // Set data for the fake xhr object
  7611. jqXHR.status = status;
  7612. jqXHR.statusText = ( nativeStatusText || statusText ) + "";
  7613. // Success/Error
  7614. if ( isSuccess ) {
  7615. deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
  7616. } else {
  7617. deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
  7618. }
  7619. // Status-dependent callbacks
  7620. jqXHR.statusCode( statusCode );
  7621. statusCode = undefined;
  7622. if ( fireGlobals ) {
  7623. globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
  7624. [ jqXHR, s, isSuccess ? success : error ] );
  7625. }
  7626. // Complete
  7627. completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
  7628. if ( fireGlobals ) {
  7629. globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
  7630. // Handle the global AJAX counter
  7631. if ( !( --jQuery.active ) ) {
  7632. jQuery.event.trigger( "ajaxStop" );
  7633. }
  7634. }
  7635. }
  7636. return jqXHR;
  7637. },
  7638. getJSON: function( url, data, callback ) {
  7639. return jQuery.get( url, data, callback, "json" );
  7640. },
  7641. getScript: function( url, callback ) {
  7642. return jQuery.get( url, undefined, callback, "script" );
  7643. }
  7644. } );
  7645. jQuery.each( [ "get", "post" ], function( i, method ) {
  7646. jQuery[ method ] = function( url, data, callback, type ) {
  7647. // Shift arguments if data argument was omitted
  7648. if ( jQuery.isFunction( data ) ) {
  7649. type = type || callback;
  7650. callback = data;
  7651. data = undefined;
  7652. }
  7653. // The url can be an options object (which then must have .url)
  7654. return jQuery.ajax( jQuery.extend( {
  7655. url: url,
  7656. type: method,
  7657. dataType: type,
  7658. data: data,
  7659. success: callback
  7660. }, jQuery.isPlainObject( url ) && url ) );
  7661. };
  7662. } );
  7663. jQuery._evalUrl = function( url ) {
  7664. return jQuery.ajax( {
  7665. url: url,
  7666. // Make this explicit, since user can override this through ajaxSetup (#11264)
  7667. type: "GET",
  7668. dataType: "script",
  7669. cache: true,
  7670. async: false,
  7671. global: false,
  7672. "throws": true
  7673. } );
  7674. };
  7675. jQuery.fn.extend( {
  7676. wrapAll: function( html ) {
  7677. var wrap;
  7678. if ( this[ 0 ] ) {
  7679. if ( jQuery.isFunction( html ) ) {
  7680. html = html.call( this[ 0 ] );
  7681. }
  7682. // The elements to wrap the target around
  7683. wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
  7684. if ( this[ 0 ].parentNode ) {
  7685. wrap.insertBefore( this[ 0 ] );
  7686. }
  7687. wrap.map( function() {
  7688. var elem = this;
  7689. while ( elem.firstElementChild ) {
  7690. elem = elem.firstElementChild;
  7691. }
  7692. return elem;
  7693. } ).append( this );
  7694. }
  7695. return this;
  7696. },
  7697. wrapInner: function( html ) {
  7698. if ( jQuery.isFunction( html ) ) {
  7699. return this.each( function( i ) {
  7700. jQuery( this ).wrapInner( html.call( this, i ) );
  7701. } );
  7702. }
  7703. return this.each( function() {
  7704. var self = jQuery( this ),
  7705. contents = self.contents();
  7706. if ( contents.length ) {
  7707. contents.wrapAll( html );
  7708. } else {
  7709. self.append( html );
  7710. }
  7711. } );
  7712. },
  7713. wrap: function( html ) {
  7714. var isFunction = jQuery.isFunction( html );
  7715. return this.each( function( i ) {
  7716. jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
  7717. } );
  7718. },
  7719. unwrap: function( selector ) {
  7720. this.parent( selector ).not( "body" ).each( function() {
  7721. jQuery( this ).replaceWith( this.childNodes );
  7722. } );
  7723. return this;
  7724. }
  7725. } );
  7726. jQuery.expr.pseudos.hidden = function( elem ) {
  7727. return !jQuery.expr.pseudos.visible( elem );
  7728. };
  7729. jQuery.expr.pseudos.visible = function( elem ) {
  7730. return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
  7731. };
  7732. jQuery.ajaxSettings.xhr = function() {
  7733. try {
  7734. return new window.XMLHttpRequest();
  7735. } catch ( e ) {}
  7736. };
  7737. var xhrSuccessStatus = {
  7738. // File protocol always yields status code 0, assume 200
  7739. 0: 200,
  7740. // Support: IE <=9 only
  7741. // #1450: sometimes IE returns 1223 when it should be 204
  7742. 1223: 204
  7743. },
  7744. xhrSupported = jQuery.ajaxSettings.xhr();
  7745. support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  7746. support.ajax = xhrSupported = !!xhrSupported;
  7747. jQuery.ajaxTransport( function( options ) {
  7748. var callback, errorCallback;
  7749. // Cross domain only allowed if supported through XMLHttpRequest
  7750. if ( support.cors || xhrSupported && !options.crossDomain ) {
  7751. return {
  7752. send: function( headers, complete ) {
  7753. var i,
  7754. xhr = options.xhr();
  7755. xhr.open(
  7756. options.type,
  7757. options.url,
  7758. options.async,
  7759. options.username,
  7760. options.password
  7761. );
  7762. // Apply custom fields if provided
  7763. if ( options.xhrFields ) {
  7764. for ( i in options.xhrFields ) {
  7765. xhr[ i ] = options.xhrFields[ i ];
  7766. }
  7767. }
  7768. // Override mime type if needed
  7769. if ( options.mimeType && xhr.overrideMimeType ) {
  7770. xhr.overrideMimeType( options.mimeType );
  7771. }
  7772. // X-Requested-With header
  7773. // For cross-domain requests, seeing as conditions for a preflight are
  7774. // akin to a jigsaw puzzle, we simply never set it to be sure.
  7775. // (it can always be set on a per-request basis or even using ajaxSetup)
  7776. // For same-domain requests, won't change header if already provided.
  7777. if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
  7778. headers[ "X-Requested-With" ] = "XMLHttpRequest";
  7779. }
  7780. // Set headers
  7781. for ( i in headers ) {
  7782. xhr.setRequestHeader( i, headers[ i ] );
  7783. }
  7784. // Callback
  7785. callback = function( type ) {
  7786. return function() {
  7787. if ( callback ) {
  7788. callback = errorCallback = xhr.onload =
  7789. xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
  7790. if ( type === "abort" ) {
  7791. xhr.abort();
  7792. } else if ( type === "error" ) {
  7793. // Support: IE <=9 only
  7794. // On a manual native abort, IE9 throws
  7795. // errors on any property access that is not readyState
  7796. if ( typeof xhr.status !== "number" ) {
  7797. complete( 0, "error" );
  7798. } else {
  7799. complete(
  7800. // File: protocol always yields status 0; see #8605, #14207
  7801. xhr.status,
  7802. xhr.statusText
  7803. );
  7804. }
  7805. } else {
  7806. complete(
  7807. xhrSuccessStatus[ xhr.status ] || xhr.status,
  7808. xhr.statusText,
  7809. // Support: IE <=9 only
  7810. // IE9 has no XHR2 but throws on binary (trac-11426)
  7811. // For XHR2 non-text, let the caller handle it (gh-2498)
  7812. ( xhr.responseType || "text" ) !== "text" ||
  7813. typeof xhr.responseText !== "string" ?
  7814. { binary: xhr.response } :
  7815. { text: xhr.responseText },
  7816. xhr.getAllResponseHeaders()
  7817. );
  7818. }
  7819. }
  7820. };
  7821. };
  7822. // Listen to events
  7823. xhr.onload = callback();
  7824. errorCallback = xhr.onerror = callback( "error" );
  7825. // Support: IE 9 only
  7826. // Use onreadystatechange to replace onabort
  7827. // to handle uncaught aborts
  7828. if ( xhr.onabort !== undefined ) {
  7829. xhr.onabort = errorCallback;
  7830. } else {
  7831. xhr.onreadystatechange = function() {
  7832. // Check readyState before timeout as it changes
  7833. if ( xhr.readyState === 4 ) {
  7834. // Allow onerror to be called first,
  7835. // but that will not handle a native abort
  7836. // Also, save errorCallback to a variable
  7837. // as xhr.onerror cannot be accessed
  7838. window.setTimeout( function() {
  7839. if ( callback ) {
  7840. errorCallback();
  7841. }
  7842. } );
  7843. }
  7844. };
  7845. }
  7846. // Create the abort callback
  7847. callback = callback( "abort" );
  7848. try {
  7849. // Do send the request (this may raise an exception)
  7850. xhr.send( options.hasContent && options.data || null );
  7851. } catch ( e ) {
  7852. // #14683: Only rethrow if this hasn't been notified as an error yet
  7853. if ( callback ) {
  7854. throw e;
  7855. }
  7856. }
  7857. },
  7858. abort: function() {
  7859. if ( callback ) {
  7860. callback();
  7861. }
  7862. }
  7863. };
  7864. }
  7865. } );
  7866. // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
  7867. jQuery.ajaxPrefilter( function( s ) {
  7868. if ( s.crossDomain ) {
  7869. s.contents.script = false;
  7870. }
  7871. } );
  7872. // Install script dataType
  7873. jQuery.ajaxSetup( {
  7874. accepts: {
  7875. script: "text/javascript, application/javascript, " +
  7876. "application/ecmascript, application/x-ecmascript"
  7877. },
  7878. contents: {
  7879. script: /\b(?:java|ecma)script\b/
  7880. },
  7881. converters: {
  7882. "text script": function( text ) {
  7883. jQuery.globalEval( text );
  7884. return text;
  7885. }
  7886. }
  7887. } );
  7888. // Handle cache's special case and crossDomain
  7889. jQuery.ajaxPrefilter( "script", function( s ) {
  7890. if ( s.cache === undefined ) {
  7891. s.cache = false;
  7892. }
  7893. if ( s.crossDomain ) {
  7894. s.type = "GET";
  7895. }
  7896. } );
  7897. // Bind script tag hack transport
  7898. jQuery.ajaxTransport( "script", function( s ) {
  7899. // This transport only deals with cross domain requests
  7900. if ( s.crossDomain ) {
  7901. var script, callback;
  7902. return {
  7903. send: function( _, complete ) {
  7904. script = jQuery( "<script>" ).prop( {
  7905. charset: s.scriptCharset,
  7906. src: s.url
  7907. } ).on(
  7908. "load error",
  7909. callback = function( evt ) {
  7910. script.remove();
  7911. callback = null;
  7912. if ( evt ) {
  7913. complete( evt.type === "error" ? 404 : 200, evt.type );
  7914. }
  7915. }
  7916. );
  7917. // Use native DOM manipulation to avoid our domManip AJAX trickery
  7918. document.head.appendChild( script[ 0 ] );
  7919. },
  7920. abort: function() {
  7921. if ( callback ) {
  7922. callback();
  7923. }
  7924. }
  7925. };
  7926. }
  7927. } );
  7928. var oldCallbacks = [],
  7929. rjsonp = /(=)\?(?=&|$)|\?\?/;
  7930. // Default jsonp settings
  7931. jQuery.ajaxSetup( {
  7932. jsonp: "callback",
  7933. jsonpCallback: function() {
  7934. var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
  7935. this[ callback ] = true;
  7936. return callback;
  7937. }
  7938. } );
  7939. // Detect, normalize options and install callbacks for jsonp requests
  7940. jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
  7941. var callbackName, overwritten, responseContainer,
  7942. jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
  7943. "url" :
  7944. typeof s.data === "string" &&
  7945. ( s.contentType || "" )
  7946. .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
  7947. rjsonp.test( s.data ) && "data"
  7948. );
  7949. // Handle iff the expected data type is "jsonp" or we have a parameter to set
  7950. if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
  7951. // Get callback name, remembering preexisting value associated with it
  7952. callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
  7953. s.jsonpCallback() :
  7954. s.jsonpCallback;
  7955. // Insert callback into url or form data
  7956. if ( jsonProp ) {
  7957. s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
  7958. } else if ( s.jsonp !== false ) {
  7959. s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
  7960. }
  7961. // Use data converter to retrieve json after script execution
  7962. s.converters[ "script json" ] = function() {
  7963. if ( !responseContainer ) {
  7964. jQuery.error( callbackName + " was not called" );
  7965. }
  7966. return responseContainer[ 0 ];
  7967. };
  7968. // Force json dataType
  7969. s.dataTypes[ 0 ] = "json";
  7970. // Install callback
  7971. overwritten = window[ callbackName ];
  7972. window[ callbackName ] = function() {
  7973. responseContainer = arguments;
  7974. };
  7975. // Clean-up function (fires after converters)
  7976. jqXHR.always( function() {
  7977. // If previous value didn't exist - remove it
  7978. if ( overwritten === undefined ) {
  7979. jQuery( window ).removeProp( callbackName );
  7980. // Otherwise restore preexisting value
  7981. } else {
  7982. window[ callbackName ] = overwritten;
  7983. }
  7984. // Save back as free
  7985. if ( s[ callbackName ] ) {
  7986. // Make sure that re-using the options doesn't screw things around
  7987. s.jsonpCallback = originalSettings.jsonpCallback;
  7988. // Save the callback name for future use
  7989. oldCallbacks.push( callbackName );
  7990. }
  7991. // Call if it was a function and we have a response
  7992. if ( responseContainer && jQuery.isFunction( overwritten ) ) {
  7993. overwritten( responseContainer[ 0 ] );
  7994. }
  7995. responseContainer = overwritten = undefined;
  7996. } );
  7997. // Delegate to script
  7998. return "script";
  7999. }
  8000. } );
  8001. // Support: Safari 8 only
  8002. // In Safari 8 documents created via document.implementation.createHTMLDocument
  8003. // collapse sibling forms: the second one becomes a child of the first one.
  8004. // Because of that, this security measure has to be disabled in Safari 8.
  8005. // https://bugs.webkit.org/show_bug.cgi?id=137337
  8006. support.createHTMLDocument = ( function() {
  8007. var body = document.implementation.createHTMLDocument( "" ).body;
  8008. body.innerHTML = "<form></form><form></form>";
  8009. return body.childNodes.length === 2;
  8010. } )();
  8011. // Argument "data" should be string of html
  8012. // context (optional): If specified, the fragment will be created in this context,
  8013. // defaults to document
  8014. // keepScripts (optional): If true, will include scripts passed in the html string
  8015. jQuery.parseHTML = function( data, context, keepScripts ) {
  8016. if ( typeof data !== "string" ) {
  8017. return [];
  8018. }
  8019. if ( typeof context === "boolean" ) {
  8020. keepScripts = context;
  8021. context = false;
  8022. }
  8023. var base, parsed, scripts;
  8024. if ( !context ) {
  8025. // Stop scripts or inline event handlers from being executed immediately
  8026. // by using document.implementation
  8027. if ( support.createHTMLDocument ) {
  8028. context = document.implementation.createHTMLDocument( "" );
  8029. // Set the base href for the created document
  8030. // so any parsed elements with URLs
  8031. // are based on the document's URL (gh-2965)
  8032. base = context.createElement( "base" );
  8033. base.href = document.location.href;
  8034. context.head.appendChild( base );
  8035. } else {
  8036. context = document;
  8037. }
  8038. }
  8039. parsed = rsingleTag.exec( data );
  8040. scripts = !keepScripts && [];
  8041. // Single tag
  8042. if ( parsed ) {
  8043. return [ context.createElement( parsed[ 1 ] ) ];
  8044. }
  8045. parsed = buildFragment( [ data ], context, scripts );
  8046. if ( scripts && scripts.length ) {
  8047. jQuery( scripts ).remove();
  8048. }
  8049. return jQuery.merge( [], parsed.childNodes );
  8050. };
  8051. /**
  8052. * Load a url into a page
  8053. */
  8054. jQuery.fn.load = function( url, params, callback ) {
  8055. var selector, type, response,
  8056. self = this,
  8057. off = url.indexOf( " " );
  8058. if ( off > -1 ) {
  8059. selector = stripAndCollapse( url.slice( off ) );
  8060. url = url.slice( 0, off );
  8061. }
  8062. // If it's a function
  8063. if ( jQuery.isFunction( params ) ) {
  8064. // We assume that it's the callback
  8065. callback = params;
  8066. params = undefined;
  8067. // Otherwise, build a param string
  8068. } else if ( params && typeof params === "object" ) {
  8069. type = "POST";
  8070. }
  8071. // If we have elements to modify, make the request
  8072. if ( self.length > 0 ) {
  8073. jQuery.ajax( {
  8074. url: url,
  8075. // If "type" variable is undefined, then "GET" method will be used.
  8076. // Make value of this field explicit since
  8077. // user can override it through ajaxSetup method
  8078. type: type || "GET",
  8079. dataType: "html",
  8080. data: params
  8081. } ).done( function( responseText ) {
  8082. // Save response for use in complete callback
  8083. response = arguments;
  8084. self.html( selector ?
  8085. // If a selector was specified, locate the right elements in a dummy div
  8086. // Exclude scripts to avoid IE 'Permission Denied' errors
  8087. jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
  8088. // Otherwise use the full result
  8089. responseText );
  8090. // If the request succeeds, this function gets "data", "status", "jqXHR"
  8091. // but they are ignored because response was set above.
  8092. // If it fails, this function gets "jqXHR", "status", "error"
  8093. } ).always( callback && function( jqXHR, status ) {
  8094. self.each( function() {
  8095. callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
  8096. } );
  8097. } );
  8098. }
  8099. return this;
  8100. };
  8101. // Attach a bunch of functions for handling common AJAX events
  8102. jQuery.each( [
  8103. "ajaxStart",
  8104. "ajaxStop",
  8105. "ajaxComplete",
  8106. "ajaxError",
  8107. "ajaxSuccess",
  8108. "ajaxSend"
  8109. ], function( i, type ) {
  8110. jQuery.fn[ type ] = function( fn ) {
  8111. return this.on( type, fn );
  8112. };
  8113. } );
  8114. jQuery.expr.pseudos.animated = function( elem ) {
  8115. return jQuery.grep( jQuery.timers, function( fn ) {
  8116. return elem === fn.elem;
  8117. } ).length;
  8118. };
  8119. jQuery.offset = {
  8120. setOffset: function( elem, options, i ) {
  8121. var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
  8122. position = jQuery.css( elem, "position" ),
  8123. curElem = jQuery( elem ),
  8124. props = {};
  8125. // Set position first, in-case top/left are set even on static elem
  8126. if ( position === "static" ) {
  8127. elem.style.position = "relative";
  8128. }
  8129. curOffset = curElem.offset();
  8130. curCSSTop = jQuery.css( elem, "top" );
  8131. curCSSLeft = jQuery.css( elem, "left" );
  8132. calculatePosition = ( position === "absolute" || position === "fixed" ) &&
  8133. ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
  8134. // Need to be able to calculate position if either
  8135. // top or left is auto and position is either absolute or fixed
  8136. if ( calculatePosition ) {
  8137. curPosition = curElem.position();
  8138. curTop = curPosition.top;
  8139. curLeft = curPosition.left;
  8140. } else {
  8141. curTop = parseFloat( curCSSTop ) || 0;
  8142. curLeft = parseFloat( curCSSLeft ) || 0;
  8143. }
  8144. if ( jQuery.isFunction( options ) ) {
  8145. // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
  8146. options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
  8147. }
  8148. if ( options.top != null ) {
  8149. props.top = ( options.top - curOffset.top ) + curTop;
  8150. }
  8151. if ( options.left != null ) {
  8152. props.left = ( options.left - curOffset.left ) + curLeft;
  8153. }
  8154. if ( "using" in options ) {
  8155. options.using.call( elem, props );
  8156. } else {
  8157. curElem.css( props );
  8158. }
  8159. }
  8160. };
  8161. jQuery.fn.extend( {
  8162. offset: function( options ) {
  8163. // Preserve chaining for setter
  8164. if ( arguments.length ) {
  8165. return options === undefined ?
  8166. this :
  8167. this.each( function( i ) {
  8168. jQuery.offset.setOffset( this, options, i );
  8169. } );
  8170. }
  8171. var doc, docElem, rect, win,
  8172. elem = this[ 0 ];
  8173. if ( !elem ) {
  8174. return;
  8175. }
  8176. // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
  8177. // Support: IE <=11 only
  8178. // Running getBoundingClientRect on a
  8179. // disconnected node in IE throws an error
  8180. if ( !elem.getClientRects().length ) {
  8181. return { top: 0, left: 0 };
  8182. }
  8183. rect = elem.getBoundingClientRect();
  8184. doc = elem.ownerDocument;
  8185. docElem = doc.documentElement;
  8186. win = doc.defaultView;
  8187. return {
  8188. top: rect.top + win.pageYOffset - docElem.clientTop,
  8189. left: rect.left + win.pageXOffset - docElem.clientLeft
  8190. };
  8191. },
  8192. position: function() {
  8193. if ( !this[ 0 ] ) {
  8194. return;
  8195. }
  8196. var offsetParent, offset,
  8197. elem = this[ 0 ],
  8198. parentOffset = { top: 0, left: 0 };
  8199. // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
  8200. // because it is its only offset parent
  8201. if ( jQuery.css( elem, "position" ) === "fixed" ) {
  8202. // Assume getBoundingClientRect is there when computed position is fixed
  8203. offset = elem.getBoundingClientRect();
  8204. } else {
  8205. // Get *real* offsetParent
  8206. offsetParent = this.offsetParent();
  8207. // Get correct offsets
  8208. offset = this.offset();
  8209. if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
  8210. parentOffset = offsetParent.offset();
  8211. }
  8212. // Add offsetParent borders
  8213. parentOffset = {
  8214. top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
  8215. left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
  8216. };
  8217. }
  8218. // Subtract parent offsets and element margins
  8219. return {
  8220. top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
  8221. left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
  8222. };
  8223. },
  8224. // This method will return documentElement in the following cases:
  8225. // 1) For the element inside the iframe without offsetParent, this method will return
  8226. // documentElement of the parent window
  8227. // 2) For the hidden or detached element
  8228. // 3) For body or html element, i.e. in case of the html node - it will return itself
  8229. //
  8230. // but those exceptions were never presented as a real life use-cases
  8231. // and might be considered as more preferable results.
  8232. //
  8233. // This logic, however, is not guaranteed and can change at any point in the future
  8234. offsetParent: function() {
  8235. return this.map( function() {
  8236. var offsetParent = this.offsetParent;
  8237. while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
  8238. offsetParent = offsetParent.offsetParent;
  8239. }
  8240. return offsetParent || documentElement;
  8241. } );
  8242. }
  8243. } );
  8244. // Create scrollLeft and scrollTop methods
  8245. jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
  8246. var top = "pageYOffset" === prop;
  8247. jQuery.fn[ method ] = function( val ) {
  8248. return access( this, function( elem, method, val ) {
  8249. // Coalesce documents and windows
  8250. var win;
  8251. if ( jQuery.isWindow( elem ) ) {
  8252. win = elem;
  8253. } else if ( elem.nodeType === 9 ) {
  8254. win = elem.defaultView;
  8255. }
  8256. if ( val === undefined ) {
  8257. return win ? win[ prop ] : elem[ method ];
  8258. }
  8259. if ( win ) {
  8260. win.scrollTo(
  8261. !top ? val : win.pageXOffset,
  8262. top ? val : win.pageYOffset
  8263. );
  8264. } else {
  8265. elem[ method ] = val;
  8266. }
  8267. }, method, val, arguments.length );
  8268. };
  8269. } );
  8270. // Support: Safari <=7 - 9.1, Chrome <=37 - 49
  8271. // Add the top/left cssHooks using jQuery.fn.position
  8272. // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  8273. // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
  8274. // getComputedStyle returns percent when specified for top/left/bottom/right;
  8275. // rather than make the css module depend on the offset module, just check for it here
  8276. jQuery.each( [ "top", "left" ], function( i, prop ) {
  8277. jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
  8278. function( elem, computed ) {
  8279. if ( computed ) {
  8280. computed = curCSS( elem, prop );
  8281. // If curCSS returns percentage, fallback to offset
  8282. return rnumnonpx.test( computed ) ?
  8283. jQuery( elem ).position()[ prop ] + "px" :
  8284. computed;
  8285. }
  8286. }
  8287. );
  8288. } );
  8289. // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  8290. jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  8291. jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
  8292. function( defaultExtra, funcName ) {
  8293. // Margin is only for outerHeight, outerWidth
  8294. jQuery.fn[ funcName ] = function( margin, value ) {
  8295. var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  8296. extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  8297. return access( this, function( elem, type, value ) {
  8298. var doc;
  8299. if ( jQuery.isWindow( elem ) ) {
  8300. // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
  8301. return funcName.indexOf( "outer" ) === 0 ?
  8302. elem[ "inner" + name ] :
  8303. elem.document.documentElement[ "client" + name ];
  8304. }
  8305. // Get document width or height
  8306. if ( elem.nodeType === 9 ) {
  8307. doc = elem.documentElement;
  8308. // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
  8309. // whichever is greatest
  8310. return Math.max(
  8311. elem.body[ "scroll" + name ], doc[ "scroll" + name ],
  8312. elem.body[ "offset" + name ], doc[ "offset" + name ],
  8313. doc[ "client" + name ]
  8314. );
  8315. }
  8316. return value === undefined ?
  8317. // Get width or height on the element, requesting but not forcing parseFloat
  8318. jQuery.css( elem, type, extra ) :
  8319. // Set width or height on the element
  8320. jQuery.style( elem, type, value, extra );
  8321. }, type, chainable ? margin : undefined, chainable );
  8322. };
  8323. } );
  8324. } );
  8325. jQuery.fn.extend( {
  8326. bind: function( types, data, fn ) {
  8327. return this.on( types, null, data, fn );
  8328. },
  8329. unbind: function( types, fn ) {
  8330. return this.off( types, null, fn );
  8331. },
  8332. delegate: function( selector, types, data, fn ) {
  8333. return this.on( types, selector, data, fn );
  8334. },
  8335. undelegate: function( selector, types, fn ) {
  8336. // ( namespace ) or ( selector, types [, fn] )
  8337. return arguments.length === 1 ?
  8338. this.off( selector, "**" ) :
  8339. this.off( types, selector || "**", fn );
  8340. }
  8341. } );
  8342. jQuery.holdReady = function( hold ) {
  8343. if ( hold ) {
  8344. jQuery.readyWait++;
  8345. } else {
  8346. jQuery.ready( true );
  8347. }
  8348. };
  8349. jQuery.isArray = Array.isArray;
  8350. jQuery.parseJSON = JSON.parse;
  8351. jQuery.nodeName = nodeName;
  8352. // Register as a named AMD module, since jQuery can be concatenated with other
  8353. // files that may use define, but not via a proper concatenation script that
  8354. // understands anonymous AMD modules. A named AMD is safest and most robust
  8355. // way to register. Lowercase jquery is used because AMD module names are
  8356. // derived from file names, and jQuery is normally delivered in a lowercase
  8357. // file name. Do this after creating the global so that if an AMD module wants
  8358. // to call noConflict to hide this version of jQuery, it will work.
  8359. // Note that for maximum portability, libraries that are not jQuery should
  8360. // declare themselves as anonymous modules, and avoid setting a global if an
  8361. // AMD loader is present. jQuery is a special case. For more information, see
  8362. // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
  8363. if ( true ) {
  8364. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
  8365. return jQuery;
  8366. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  8367. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  8368. }
  8369. var
  8370. // Map over jQuery in case of overwrite
  8371. _jQuery = window.jQuery,
  8372. // Map over the $ in case of overwrite
  8373. _$ = window.$;
  8374. jQuery.noConflict = function( deep ) {
  8375. if ( window.$ === jQuery ) {
  8376. window.$ = _$;
  8377. }
  8378. if ( deep && window.jQuery === jQuery ) {
  8379. window.jQuery = _jQuery;
  8380. }
  8381. return jQuery;
  8382. };
  8383. // Expose jQuery and $ identifiers, even in AMD
  8384. // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
  8385. // and CommonJS for browser emulators (#13566)
  8386. if ( !noGlobal ) {
  8387. window.jQuery = window.$ = jQuery;
  8388. }
  8389. return jQuery;
  8390. } );
  8391. /***/ }),
  8392. /* 1 */
  8393. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  8394. "use strict";
  8395. Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
  8396. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery__ = __webpack_require__(0);
  8397. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_jquery__);
  8398. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_bootstrap__ = __webpack_require__(2);
  8399. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_bootstrap___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_bootstrap__);
  8400. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap_select__ = __webpack_require__(5);
  8401. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap_select___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_bootstrap_select__);
  8402. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_bootstrap_validator__ = __webpack_require__(6);
  8403. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_bootstrap_validator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_bootstrap_validator__);
  8404. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput__ = __webpack_require__(7);
  8405. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput__);
  8406. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css__ = __webpack_require__(8);
  8407. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css__);
  8408. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css__ = __webpack_require__(9);
  8409. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css__);
  8410. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css__ = __webpack_require__(10);
  8411. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css__);
  8412. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css__ = __webpack_require__(11);
  8413. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8__style_css__);
  8414. // Javascript
  8415. // CSS
  8416. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(function () {
  8417. __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#myInput").on("keyup", function(eventObject) {
  8418. var input, filter, ul, li, a, i;
  8419. input = eventObject.currentTarget;
  8420. filter = input.value.toUpperCase();
  8421. ul = document.getElementById("myUL");
  8422. li = ul.getElementsByTagName('a');
  8423. // Loop through all list items, and hide those who don't match the search query
  8424. for (i = 0; i < li.length; i++) {
  8425. a = li[i]; //li[i].getElementsByTagName("a")[0];
  8426. if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
  8427. li[i].style.display = "";
  8428. } else {
  8429. li[i].style.display = "none";
  8430. }
  8431. }
  8432. });
  8433. function checkUsernameInputHandler(eventObject) {
  8434. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8435. var data = JSON.stringify({"username": input_el.val()});
  8436. var url = `/teachers/check_username/${input_el.val()}`
  8437. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8438. url,
  8439. data,
  8440. function(result) {
  8441. if (result.exists) {
  8442. console.log("Username exists");
  8443. }
  8444. },
  8445. "json"
  8446. );
  8447. }
  8448. function usernameGenerator(eventObject, firstname, surname) {
  8449. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8450. input_el.val(firstname+"."+surname);
  8451. }
  8452. function deleteRelationHandler(eventObject) {
  8453. var url = this.dataset.url;
  8454. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8455. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8456. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8457. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8458. url: url,
  8459. type: 'DELETE',
  8460. success: function(result) {
  8461. el.closest(".list-group-item").remove();
  8462. modalEl.modal('hide');
  8463. }
  8464. });
  8465. });
  8466. return false;
  8467. };
  8468. function deleteHandler(eventObject) {
  8469. var url = this.dataset.url;
  8470. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8471. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8472. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8473. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8474. url: url,
  8475. type: 'DELETE',
  8476. success: function(result) {
  8477. modalEl.modal('hide');
  8478. window.location.replace(result.redirect_url);
  8479. }
  8480. });
  8481. });
  8482. return false;
  8483. };
  8484. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".ajax-post").on("click", function(eventObject) {
  8485. var select_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.select).first();
  8486. var listgroup_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.listgroup).first();
  8487. var url = this.dataset.url;
  8488. var data = JSON.stringify({"ids": select_el.val()});
  8489. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8490. url,
  8491. data,
  8492. function(result) {
  8493. var i;
  8494. if (result.elements != null) {
  8495. for (i = 0; i < result.elements.length; i++) {
  8496. var newItem = `
  8497. <a href="#" class="list-group-item clearfix">
  8498. <span class="glyphicon glyphicon-book"></span>
  8499. ${result.elements[i].Name}
  8500. <span class="pull-right">
  8501. <button data-url="/${result.name1}/${result.id1}/${result.name2}/${result.id2[i]}/delete" class="btn btn-xs btn-warning karmen-ajax-delete">
  8502. <span class="glyphicon glyphicon-trash"></span>
  8503. </button>
  8504. </span>
  8505. `;
  8506. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(listgroup_el).append(newItem);
  8507. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8508. }
  8509. }
  8510. },
  8511. "json"
  8512. );
  8513. select_el.val('default');
  8514. select_el.selectpicker("refresh");
  8515. return false;
  8516. });
  8517. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete-relation").on("click", deleteRelationHandler);
  8518. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8519. });
  8520. /***/ }),
  8521. /* 2 */
  8522. /***/ (function(module, exports, __webpack_require__) {
  8523. /*!
  8524. * Bootstrap v4.1.3 (https://getbootstrap.com/)
  8525. * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  8526. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8527. */
  8528. (function (global, factory) {
  8529. true ? factory(exports, __webpack_require__(0), __webpack_require__(3)) :
  8530. typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :
  8531. (factory((global.bootstrap = {}),global.jQuery,global.Popper));
  8532. }(this, (function (exports,$,Popper) { 'use strict';
  8533. $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
  8534. Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;
  8535. function _defineProperties(target, props) {
  8536. for (var i = 0; i < props.length; i++) {
  8537. var descriptor = props[i];
  8538. descriptor.enumerable = descriptor.enumerable || false;
  8539. descriptor.configurable = true;
  8540. if ("value" in descriptor) descriptor.writable = true;
  8541. Object.defineProperty(target, descriptor.key, descriptor);
  8542. }
  8543. }
  8544. function _createClass(Constructor, protoProps, staticProps) {
  8545. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  8546. if (staticProps) _defineProperties(Constructor, staticProps);
  8547. return Constructor;
  8548. }
  8549. function _defineProperty(obj, key, value) {
  8550. if (key in obj) {
  8551. Object.defineProperty(obj, key, {
  8552. value: value,
  8553. enumerable: true,
  8554. configurable: true,
  8555. writable: true
  8556. });
  8557. } else {
  8558. obj[key] = value;
  8559. }
  8560. return obj;
  8561. }
  8562. function _objectSpread(target) {
  8563. for (var i = 1; i < arguments.length; i++) {
  8564. var source = arguments[i] != null ? arguments[i] : {};
  8565. var ownKeys = Object.keys(source);
  8566. if (typeof Object.getOwnPropertySymbols === 'function') {
  8567. ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
  8568. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  8569. }));
  8570. }
  8571. ownKeys.forEach(function (key) {
  8572. _defineProperty(target, key, source[key]);
  8573. });
  8574. }
  8575. return target;
  8576. }
  8577. function _inheritsLoose(subClass, superClass) {
  8578. subClass.prototype = Object.create(superClass.prototype);
  8579. subClass.prototype.constructor = subClass;
  8580. subClass.__proto__ = superClass;
  8581. }
  8582. /**
  8583. * --------------------------------------------------------------------------
  8584. * Bootstrap (v4.1.3): util.js
  8585. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8586. * --------------------------------------------------------------------------
  8587. */
  8588. var Util = function ($$$1) {
  8589. /**
  8590. * ------------------------------------------------------------------------
  8591. * Private TransitionEnd Helpers
  8592. * ------------------------------------------------------------------------
  8593. */
  8594. var TRANSITION_END = 'transitionend';
  8595. var MAX_UID = 1000000;
  8596. var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
  8597. function toType(obj) {
  8598. return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
  8599. }
  8600. function getSpecialTransitionEndEvent() {
  8601. return {
  8602. bindType: TRANSITION_END,
  8603. delegateType: TRANSITION_END,
  8604. handle: function handle(event) {
  8605. if ($$$1(event.target).is(this)) {
  8606. return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
  8607. }
  8608. return undefined; // eslint-disable-line no-undefined
  8609. }
  8610. };
  8611. }
  8612. function transitionEndEmulator(duration) {
  8613. var _this = this;
  8614. var called = false;
  8615. $$$1(this).one(Util.TRANSITION_END, function () {
  8616. called = true;
  8617. });
  8618. setTimeout(function () {
  8619. if (!called) {
  8620. Util.triggerTransitionEnd(_this);
  8621. }
  8622. }, duration);
  8623. return this;
  8624. }
  8625. function setTransitionEndSupport() {
  8626. $$$1.fn.emulateTransitionEnd = transitionEndEmulator;
  8627. $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
  8628. }
  8629. /**
  8630. * --------------------------------------------------------------------------
  8631. * Public Util Api
  8632. * --------------------------------------------------------------------------
  8633. */
  8634. var Util = {
  8635. TRANSITION_END: 'bsTransitionEnd',
  8636. getUID: function getUID(prefix) {
  8637. do {
  8638. // eslint-disable-next-line no-bitwise
  8639. prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
  8640. } while (document.getElementById(prefix));
  8641. return prefix;
  8642. },
  8643. getSelectorFromElement: function getSelectorFromElement(element) {
  8644. var selector = element.getAttribute('data-target');
  8645. if (!selector || selector === '#') {
  8646. selector = element.getAttribute('href') || '';
  8647. }
  8648. try {
  8649. return document.querySelector(selector) ? selector : null;
  8650. } catch (err) {
  8651. return null;
  8652. }
  8653. },
  8654. getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {
  8655. if (!element) {
  8656. return 0;
  8657. } // Get transition-duration of the element
  8658. var transitionDuration = $$$1(element).css('transition-duration');
  8659. var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found
  8660. if (!floatTransitionDuration) {
  8661. return 0;
  8662. } // If multiple durations are defined, take the first
  8663. transitionDuration = transitionDuration.split(',')[0];
  8664. return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER;
  8665. },
  8666. reflow: function reflow(element) {
  8667. return element.offsetHeight;
  8668. },
  8669. triggerTransitionEnd: function triggerTransitionEnd(element) {
  8670. $$$1(element).trigger(TRANSITION_END);
  8671. },
  8672. // TODO: Remove in v5
  8673. supportsTransitionEnd: function supportsTransitionEnd() {
  8674. return Boolean(TRANSITION_END);
  8675. },
  8676. isElement: function isElement(obj) {
  8677. return (obj[0] || obj).nodeType;
  8678. },
  8679. typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
  8680. for (var property in configTypes) {
  8681. if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
  8682. var expectedTypes = configTypes[property];
  8683. var value = config[property];
  8684. var valueType = value && Util.isElement(value) ? 'element' : toType(value);
  8685. if (!new RegExp(expectedTypes).test(valueType)) {
  8686. throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
  8687. }
  8688. }
  8689. }
  8690. }
  8691. };
  8692. setTransitionEndSupport();
  8693. return Util;
  8694. }($);
  8695. /**
  8696. * --------------------------------------------------------------------------
  8697. * Bootstrap (v4.1.3): alert.js
  8698. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8699. * --------------------------------------------------------------------------
  8700. */
  8701. var Alert = function ($$$1) {
  8702. /**
  8703. * ------------------------------------------------------------------------
  8704. * Constants
  8705. * ------------------------------------------------------------------------
  8706. */
  8707. var NAME = 'alert';
  8708. var VERSION = '4.1.3';
  8709. var DATA_KEY = 'bs.alert';
  8710. var EVENT_KEY = "." + DATA_KEY;
  8711. var DATA_API_KEY = '.data-api';
  8712. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8713. var Selector = {
  8714. DISMISS: '[data-dismiss="alert"]'
  8715. };
  8716. var Event = {
  8717. CLOSE: "close" + EVENT_KEY,
  8718. CLOSED: "closed" + EVENT_KEY,
  8719. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  8720. };
  8721. var ClassName = {
  8722. ALERT: 'alert',
  8723. FADE: 'fade',
  8724. SHOW: 'show'
  8725. /**
  8726. * ------------------------------------------------------------------------
  8727. * Class Definition
  8728. * ------------------------------------------------------------------------
  8729. */
  8730. };
  8731. var Alert =
  8732. /*#__PURE__*/
  8733. function () {
  8734. function Alert(element) {
  8735. this._element = element;
  8736. } // Getters
  8737. var _proto = Alert.prototype;
  8738. // Public
  8739. _proto.close = function close(element) {
  8740. var rootElement = this._element;
  8741. if (element) {
  8742. rootElement = this._getRootElement(element);
  8743. }
  8744. var customEvent = this._triggerCloseEvent(rootElement);
  8745. if (customEvent.isDefaultPrevented()) {
  8746. return;
  8747. }
  8748. this._removeElement(rootElement);
  8749. };
  8750. _proto.dispose = function dispose() {
  8751. $$$1.removeData(this._element, DATA_KEY);
  8752. this._element = null;
  8753. }; // Private
  8754. _proto._getRootElement = function _getRootElement(element) {
  8755. var selector = Util.getSelectorFromElement(element);
  8756. var parent = false;
  8757. if (selector) {
  8758. parent = document.querySelector(selector);
  8759. }
  8760. if (!parent) {
  8761. parent = $$$1(element).closest("." + ClassName.ALERT)[0];
  8762. }
  8763. return parent;
  8764. };
  8765. _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
  8766. var closeEvent = $$$1.Event(Event.CLOSE);
  8767. $$$1(element).trigger(closeEvent);
  8768. return closeEvent;
  8769. };
  8770. _proto._removeElement = function _removeElement(element) {
  8771. var _this = this;
  8772. $$$1(element).removeClass(ClassName.SHOW);
  8773. if (!$$$1(element).hasClass(ClassName.FADE)) {
  8774. this._destroyElement(element);
  8775. return;
  8776. }
  8777. var transitionDuration = Util.getTransitionDurationFromElement(element);
  8778. $$$1(element).one(Util.TRANSITION_END, function (event) {
  8779. return _this._destroyElement(element, event);
  8780. }).emulateTransitionEnd(transitionDuration);
  8781. };
  8782. _proto._destroyElement = function _destroyElement(element) {
  8783. $$$1(element).detach().trigger(Event.CLOSED).remove();
  8784. }; // Static
  8785. Alert._jQueryInterface = function _jQueryInterface(config) {
  8786. return this.each(function () {
  8787. var $element = $$$1(this);
  8788. var data = $element.data(DATA_KEY);
  8789. if (!data) {
  8790. data = new Alert(this);
  8791. $element.data(DATA_KEY, data);
  8792. }
  8793. if (config === 'close') {
  8794. data[config](this);
  8795. }
  8796. });
  8797. };
  8798. Alert._handleDismiss = function _handleDismiss(alertInstance) {
  8799. return function (event) {
  8800. if (event) {
  8801. event.preventDefault();
  8802. }
  8803. alertInstance.close(this);
  8804. };
  8805. };
  8806. _createClass(Alert, null, [{
  8807. key: "VERSION",
  8808. get: function get() {
  8809. return VERSION;
  8810. }
  8811. }]);
  8812. return Alert;
  8813. }();
  8814. /**
  8815. * ------------------------------------------------------------------------
  8816. * Data Api implementation
  8817. * ------------------------------------------------------------------------
  8818. */
  8819. $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
  8820. /**
  8821. * ------------------------------------------------------------------------
  8822. * jQuery
  8823. * ------------------------------------------------------------------------
  8824. */
  8825. $$$1.fn[NAME] = Alert._jQueryInterface;
  8826. $$$1.fn[NAME].Constructor = Alert;
  8827. $$$1.fn[NAME].noConflict = function () {
  8828. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  8829. return Alert._jQueryInterface;
  8830. };
  8831. return Alert;
  8832. }($);
  8833. /**
  8834. * --------------------------------------------------------------------------
  8835. * Bootstrap (v4.1.3): button.js
  8836. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8837. * --------------------------------------------------------------------------
  8838. */
  8839. var Button = function ($$$1) {
  8840. /**
  8841. * ------------------------------------------------------------------------
  8842. * Constants
  8843. * ------------------------------------------------------------------------
  8844. */
  8845. var NAME = 'button';
  8846. var VERSION = '4.1.3';
  8847. var DATA_KEY = 'bs.button';
  8848. var EVENT_KEY = "." + DATA_KEY;
  8849. var DATA_API_KEY = '.data-api';
  8850. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8851. var ClassName = {
  8852. ACTIVE: 'active',
  8853. BUTTON: 'btn',
  8854. FOCUS: 'focus'
  8855. };
  8856. var Selector = {
  8857. DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
  8858. DATA_TOGGLE: '[data-toggle="buttons"]',
  8859. INPUT: 'input',
  8860. ACTIVE: '.active',
  8861. BUTTON: '.btn'
  8862. };
  8863. var Event = {
  8864. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
  8865. FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY)
  8866. /**
  8867. * ------------------------------------------------------------------------
  8868. * Class Definition
  8869. * ------------------------------------------------------------------------
  8870. */
  8871. };
  8872. var Button =
  8873. /*#__PURE__*/
  8874. function () {
  8875. function Button(element) {
  8876. this._element = element;
  8877. } // Getters
  8878. var _proto = Button.prototype;
  8879. // Public
  8880. _proto.toggle = function toggle() {
  8881. var triggerChangeEvent = true;
  8882. var addAriaPressed = true;
  8883. var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0];
  8884. if (rootElement) {
  8885. var input = this._element.querySelector(Selector.INPUT);
  8886. if (input) {
  8887. if (input.type === 'radio') {
  8888. if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) {
  8889. triggerChangeEvent = false;
  8890. } else {
  8891. var activeElement = rootElement.querySelector(Selector.ACTIVE);
  8892. if (activeElement) {
  8893. $$$1(activeElement).removeClass(ClassName.ACTIVE);
  8894. }
  8895. }
  8896. }
  8897. if (triggerChangeEvent) {
  8898. if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {
  8899. return;
  8900. }
  8901. input.checked = !this._element.classList.contains(ClassName.ACTIVE);
  8902. $$$1(input).trigger('change');
  8903. }
  8904. input.focus();
  8905. addAriaPressed = false;
  8906. }
  8907. }
  8908. if (addAriaPressed) {
  8909. this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE));
  8910. }
  8911. if (triggerChangeEvent) {
  8912. $$$1(this._element).toggleClass(ClassName.ACTIVE);
  8913. }
  8914. };
  8915. _proto.dispose = function dispose() {
  8916. $$$1.removeData(this._element, DATA_KEY);
  8917. this._element = null;
  8918. }; // Static
  8919. Button._jQueryInterface = function _jQueryInterface(config) {
  8920. return this.each(function () {
  8921. var data = $$$1(this).data(DATA_KEY);
  8922. if (!data) {
  8923. data = new Button(this);
  8924. $$$1(this).data(DATA_KEY, data);
  8925. }
  8926. if (config === 'toggle') {
  8927. data[config]();
  8928. }
  8929. });
  8930. };
  8931. _createClass(Button, null, [{
  8932. key: "VERSION",
  8933. get: function get() {
  8934. return VERSION;
  8935. }
  8936. }]);
  8937. return Button;
  8938. }();
  8939. /**
  8940. * ------------------------------------------------------------------------
  8941. * Data Api implementation
  8942. * ------------------------------------------------------------------------
  8943. */
  8944. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
  8945. event.preventDefault();
  8946. var button = event.target;
  8947. if (!$$$1(button).hasClass(ClassName.BUTTON)) {
  8948. button = $$$1(button).closest(Selector.BUTTON);
  8949. }
  8950. Button._jQueryInterface.call($$$1(button), 'toggle');
  8951. }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
  8952. var button = $$$1(event.target).closest(Selector.BUTTON)[0];
  8953. $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
  8954. });
  8955. /**
  8956. * ------------------------------------------------------------------------
  8957. * jQuery
  8958. * ------------------------------------------------------------------------
  8959. */
  8960. $$$1.fn[NAME] = Button._jQueryInterface;
  8961. $$$1.fn[NAME].Constructor = Button;
  8962. $$$1.fn[NAME].noConflict = function () {
  8963. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  8964. return Button._jQueryInterface;
  8965. };
  8966. return Button;
  8967. }($);
  8968. /**
  8969. * --------------------------------------------------------------------------
  8970. * Bootstrap (v4.1.3): carousel.js
  8971. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8972. * --------------------------------------------------------------------------
  8973. */
  8974. var Carousel = function ($$$1) {
  8975. /**
  8976. * ------------------------------------------------------------------------
  8977. * Constants
  8978. * ------------------------------------------------------------------------
  8979. */
  8980. var NAME = 'carousel';
  8981. var VERSION = '4.1.3';
  8982. var DATA_KEY = 'bs.carousel';
  8983. var EVENT_KEY = "." + DATA_KEY;
  8984. var DATA_API_KEY = '.data-api';
  8985. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8986. var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
  8987. var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
  8988. var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
  8989. var Default = {
  8990. interval: 5000,
  8991. keyboard: true,
  8992. slide: false,
  8993. pause: 'hover',
  8994. wrap: true
  8995. };
  8996. var DefaultType = {
  8997. interval: '(number|boolean)',
  8998. keyboard: 'boolean',
  8999. slide: '(boolean|string)',
  9000. pause: '(string|boolean)',
  9001. wrap: 'boolean'
  9002. };
  9003. var Direction = {
  9004. NEXT: 'next',
  9005. PREV: 'prev',
  9006. LEFT: 'left',
  9007. RIGHT: 'right'
  9008. };
  9009. var Event = {
  9010. SLIDE: "slide" + EVENT_KEY,
  9011. SLID: "slid" + EVENT_KEY,
  9012. KEYDOWN: "keydown" + EVENT_KEY,
  9013. MOUSEENTER: "mouseenter" + EVENT_KEY,
  9014. MOUSELEAVE: "mouseleave" + EVENT_KEY,
  9015. TOUCHEND: "touchend" + EVENT_KEY,
  9016. LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY,
  9017. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  9018. };
  9019. var ClassName = {
  9020. CAROUSEL: 'carousel',
  9021. ACTIVE: 'active',
  9022. SLIDE: 'slide',
  9023. RIGHT: 'carousel-item-right',
  9024. LEFT: 'carousel-item-left',
  9025. NEXT: 'carousel-item-next',
  9026. PREV: 'carousel-item-prev',
  9027. ITEM: 'carousel-item'
  9028. };
  9029. var Selector = {
  9030. ACTIVE: '.active',
  9031. ACTIVE_ITEM: '.active.carousel-item',
  9032. ITEM: '.carousel-item',
  9033. NEXT_PREV: '.carousel-item-next, .carousel-item-prev',
  9034. INDICATORS: '.carousel-indicators',
  9035. DATA_SLIDE: '[data-slide], [data-slide-to]',
  9036. DATA_RIDE: '[data-ride="carousel"]'
  9037. /**
  9038. * ------------------------------------------------------------------------
  9039. * Class Definition
  9040. * ------------------------------------------------------------------------
  9041. */
  9042. };
  9043. var Carousel =
  9044. /*#__PURE__*/
  9045. function () {
  9046. function Carousel(element, config) {
  9047. this._items = null;
  9048. this._interval = null;
  9049. this._activeElement = null;
  9050. this._isPaused = false;
  9051. this._isSliding = false;
  9052. this.touchTimeout = null;
  9053. this._config = this._getConfig(config);
  9054. this._element = $$$1(element)[0];
  9055. this._indicatorsElement = this._element.querySelector(Selector.INDICATORS);
  9056. this._addEventListeners();
  9057. } // Getters
  9058. var _proto = Carousel.prototype;
  9059. // Public
  9060. _proto.next = function next() {
  9061. if (!this._isSliding) {
  9062. this._slide(Direction.NEXT);
  9063. }
  9064. };
  9065. _proto.nextWhenVisible = function nextWhenVisible() {
  9066. // Don't call next when the page isn't visible
  9067. // or the carousel or its parent isn't visible
  9068. if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') {
  9069. this.next();
  9070. }
  9071. };
  9072. _proto.prev = function prev() {
  9073. if (!this._isSliding) {
  9074. this._slide(Direction.PREV);
  9075. }
  9076. };
  9077. _proto.pause = function pause(event) {
  9078. if (!event) {
  9079. this._isPaused = true;
  9080. }
  9081. if (this._element.querySelector(Selector.NEXT_PREV)) {
  9082. Util.triggerTransitionEnd(this._element);
  9083. this.cycle(true);
  9084. }
  9085. clearInterval(this._interval);
  9086. this._interval = null;
  9087. };
  9088. _proto.cycle = function cycle(event) {
  9089. if (!event) {
  9090. this._isPaused = false;
  9091. }
  9092. if (this._interval) {
  9093. clearInterval(this._interval);
  9094. this._interval = null;
  9095. }
  9096. if (this._config.interval && !this._isPaused) {
  9097. this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
  9098. }
  9099. };
  9100. _proto.to = function to(index) {
  9101. var _this = this;
  9102. this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);
  9103. var activeIndex = this._getItemIndex(this._activeElement);
  9104. if (index > this._items.length - 1 || index < 0) {
  9105. return;
  9106. }
  9107. if (this._isSliding) {
  9108. $$$1(this._element).one(Event.SLID, function () {
  9109. return _this.to(index);
  9110. });
  9111. return;
  9112. }
  9113. if (activeIndex === index) {
  9114. this.pause();
  9115. this.cycle();
  9116. return;
  9117. }
  9118. var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;
  9119. this._slide(direction, this._items[index]);
  9120. };
  9121. _proto.dispose = function dispose() {
  9122. $$$1(this._element).off(EVENT_KEY);
  9123. $$$1.removeData(this._element, DATA_KEY);
  9124. this._items = null;
  9125. this._config = null;
  9126. this._element = null;
  9127. this._interval = null;
  9128. this._isPaused = null;
  9129. this._isSliding = null;
  9130. this._activeElement = null;
  9131. this._indicatorsElement = null;
  9132. }; // Private
  9133. _proto._getConfig = function _getConfig(config) {
  9134. config = _objectSpread({}, Default, config);
  9135. Util.typeCheckConfig(NAME, config, DefaultType);
  9136. return config;
  9137. };
  9138. _proto._addEventListeners = function _addEventListeners() {
  9139. var _this2 = this;
  9140. if (this._config.keyboard) {
  9141. $$$1(this._element).on(Event.KEYDOWN, function (event) {
  9142. return _this2._keydown(event);
  9143. });
  9144. }
  9145. if (this._config.pause === 'hover') {
  9146. $$$1(this._element).on(Event.MOUSEENTER, function (event) {
  9147. return _this2.pause(event);
  9148. }).on(Event.MOUSELEAVE, function (event) {
  9149. return _this2.cycle(event);
  9150. });
  9151. if ('ontouchstart' in document.documentElement) {
  9152. // If it's a touch-enabled device, mouseenter/leave are fired as
  9153. // part of the mouse compatibility events on first tap - the carousel
  9154. // would stop cycling until user tapped out of it;
  9155. // here, we listen for touchend, explicitly pause the carousel
  9156. // (as if it's the second time we tap on it, mouseenter compat event
  9157. // is NOT fired) and after a timeout (to allow for mouse compatibility
  9158. // events to fire) we explicitly restart cycling
  9159. $$$1(this._element).on(Event.TOUCHEND, function () {
  9160. _this2.pause();
  9161. if (_this2.touchTimeout) {
  9162. clearTimeout(_this2.touchTimeout);
  9163. }
  9164. _this2.touchTimeout = setTimeout(function (event) {
  9165. return _this2.cycle(event);
  9166. }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);
  9167. });
  9168. }
  9169. }
  9170. };
  9171. _proto._keydown = function _keydown(event) {
  9172. if (/input|textarea/i.test(event.target.tagName)) {
  9173. return;
  9174. }
  9175. switch (event.which) {
  9176. case ARROW_LEFT_KEYCODE:
  9177. event.preventDefault();
  9178. this.prev();
  9179. break;
  9180. case ARROW_RIGHT_KEYCODE:
  9181. event.preventDefault();
  9182. this.next();
  9183. break;
  9184. default:
  9185. }
  9186. };
  9187. _proto._getItemIndex = function _getItemIndex(element) {
  9188. this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : [];
  9189. return this._items.indexOf(element);
  9190. };
  9191. _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
  9192. var isNextDirection = direction === Direction.NEXT;
  9193. var isPrevDirection = direction === Direction.PREV;
  9194. var activeIndex = this._getItemIndex(activeElement);
  9195. var lastItemIndex = this._items.length - 1;
  9196. var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
  9197. if (isGoingToWrap && !this._config.wrap) {
  9198. return activeElement;
  9199. }
  9200. var delta = direction === Direction.PREV ? -1 : 1;
  9201. var itemIndex = (activeIndex + delta) % this._items.length;
  9202. return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
  9203. };
  9204. _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
  9205. var targetIndex = this._getItemIndex(relatedTarget);
  9206. var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM));
  9207. var slideEvent = $$$1.Event(Event.SLIDE, {
  9208. relatedTarget: relatedTarget,
  9209. direction: eventDirectionName,
  9210. from: fromIndex,
  9211. to: targetIndex
  9212. });
  9213. $$$1(this._element).trigger(slideEvent);
  9214. return slideEvent;
  9215. };
  9216. _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
  9217. if (this._indicatorsElement) {
  9218. var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE));
  9219. $$$1(indicators).removeClass(ClassName.ACTIVE);
  9220. var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
  9221. if (nextIndicator) {
  9222. $$$1(nextIndicator).addClass(ClassName.ACTIVE);
  9223. }
  9224. }
  9225. };
  9226. _proto._slide = function _slide(direction, element) {
  9227. var _this3 = this;
  9228. var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);
  9229. var activeElementIndex = this._getItemIndex(activeElement);
  9230. var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
  9231. var nextElementIndex = this._getItemIndex(nextElement);
  9232. var isCycling = Boolean(this._interval);
  9233. var directionalClassName;
  9234. var orderClassName;
  9235. var eventDirectionName;
  9236. if (direction === Direction.NEXT) {
  9237. directionalClassName = ClassName.LEFT;
  9238. orderClassName = ClassName.NEXT;
  9239. eventDirectionName = Direction.LEFT;
  9240. } else {
  9241. directionalClassName = ClassName.RIGHT;
  9242. orderClassName = ClassName.PREV;
  9243. eventDirectionName = Direction.RIGHT;
  9244. }
  9245. if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) {
  9246. this._isSliding = false;
  9247. return;
  9248. }
  9249. var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
  9250. if (slideEvent.isDefaultPrevented()) {
  9251. return;
  9252. }
  9253. if (!activeElement || !nextElement) {
  9254. // Some weirdness is happening, so we bail
  9255. return;
  9256. }
  9257. this._isSliding = true;
  9258. if (isCycling) {
  9259. this.pause();
  9260. }
  9261. this._setActiveIndicatorElement(nextElement);
  9262. var slidEvent = $$$1.Event(Event.SLID, {
  9263. relatedTarget: nextElement,
  9264. direction: eventDirectionName,
  9265. from: activeElementIndex,
  9266. to: nextElementIndex
  9267. });
  9268. if ($$$1(this._element).hasClass(ClassName.SLIDE)) {
  9269. $$$1(nextElement).addClass(orderClassName);
  9270. Util.reflow(nextElement);
  9271. $$$1(activeElement).addClass(directionalClassName);
  9272. $$$1(nextElement).addClass(directionalClassName);
  9273. var transitionDuration = Util.getTransitionDurationFromElement(activeElement);
  9274. $$$1(activeElement).one(Util.TRANSITION_END, function () {
  9275. $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE);
  9276. $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName);
  9277. _this3._isSliding = false;
  9278. setTimeout(function () {
  9279. return $$$1(_this3._element).trigger(slidEvent);
  9280. }, 0);
  9281. }).emulateTransitionEnd(transitionDuration);
  9282. } else {
  9283. $$$1(activeElement).removeClass(ClassName.ACTIVE);
  9284. $$$1(nextElement).addClass(ClassName.ACTIVE);
  9285. this._isSliding = false;
  9286. $$$1(this._element).trigger(slidEvent);
  9287. }
  9288. if (isCycling) {
  9289. this.cycle();
  9290. }
  9291. }; // Static
  9292. Carousel._jQueryInterface = function _jQueryInterface(config) {
  9293. return this.each(function () {
  9294. var data = $$$1(this).data(DATA_KEY);
  9295. var _config = _objectSpread({}, Default, $$$1(this).data());
  9296. if (typeof config === 'object') {
  9297. _config = _objectSpread({}, _config, config);
  9298. }
  9299. var action = typeof config === 'string' ? config : _config.slide;
  9300. if (!data) {
  9301. data = new Carousel(this, _config);
  9302. $$$1(this).data(DATA_KEY, data);
  9303. }
  9304. if (typeof config === 'number') {
  9305. data.to(config);
  9306. } else if (typeof action === 'string') {
  9307. if (typeof data[action] === 'undefined') {
  9308. throw new TypeError("No method named \"" + action + "\"");
  9309. }
  9310. data[action]();
  9311. } else if (_config.interval) {
  9312. data.pause();
  9313. data.cycle();
  9314. }
  9315. });
  9316. };
  9317. Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
  9318. var selector = Util.getSelectorFromElement(this);
  9319. if (!selector) {
  9320. return;
  9321. }
  9322. var target = $$$1(selector)[0];
  9323. if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) {
  9324. return;
  9325. }
  9326. var config = _objectSpread({}, $$$1(target).data(), $$$1(this).data());
  9327. var slideIndex = this.getAttribute('data-slide-to');
  9328. if (slideIndex) {
  9329. config.interval = false;
  9330. }
  9331. Carousel._jQueryInterface.call($$$1(target), config);
  9332. if (slideIndex) {
  9333. $$$1(target).data(DATA_KEY).to(slideIndex);
  9334. }
  9335. event.preventDefault();
  9336. };
  9337. _createClass(Carousel, null, [{
  9338. key: "VERSION",
  9339. get: function get() {
  9340. return VERSION;
  9341. }
  9342. }, {
  9343. key: "Default",
  9344. get: function get() {
  9345. return Default;
  9346. }
  9347. }]);
  9348. return Carousel;
  9349. }();
  9350. /**
  9351. * ------------------------------------------------------------------------
  9352. * Data Api implementation
  9353. * ------------------------------------------------------------------------
  9354. */
  9355. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
  9356. $$$1(window).on(Event.LOAD_DATA_API, function () {
  9357. var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE));
  9358. for (var i = 0, len = carousels.length; i < len; i++) {
  9359. var $carousel = $$$1(carousels[i]);
  9360. Carousel._jQueryInterface.call($carousel, $carousel.data());
  9361. }
  9362. });
  9363. /**
  9364. * ------------------------------------------------------------------------
  9365. * jQuery
  9366. * ------------------------------------------------------------------------
  9367. */
  9368. $$$1.fn[NAME] = Carousel._jQueryInterface;
  9369. $$$1.fn[NAME].Constructor = Carousel;
  9370. $$$1.fn[NAME].noConflict = function () {
  9371. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  9372. return Carousel._jQueryInterface;
  9373. };
  9374. return Carousel;
  9375. }($);
  9376. /**
  9377. * --------------------------------------------------------------------------
  9378. * Bootstrap (v4.1.3): collapse.js
  9379. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9380. * --------------------------------------------------------------------------
  9381. */
  9382. var Collapse = function ($$$1) {
  9383. /**
  9384. * ------------------------------------------------------------------------
  9385. * Constants
  9386. * ------------------------------------------------------------------------
  9387. */
  9388. var NAME = 'collapse';
  9389. var VERSION = '4.1.3';
  9390. var DATA_KEY = 'bs.collapse';
  9391. var EVENT_KEY = "." + DATA_KEY;
  9392. var DATA_API_KEY = '.data-api';
  9393. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  9394. var Default = {
  9395. toggle: true,
  9396. parent: ''
  9397. };
  9398. var DefaultType = {
  9399. toggle: 'boolean',
  9400. parent: '(string|element)'
  9401. };
  9402. var Event = {
  9403. SHOW: "show" + EVENT_KEY,
  9404. SHOWN: "shown" + EVENT_KEY,
  9405. HIDE: "hide" + EVENT_KEY,
  9406. HIDDEN: "hidden" + EVENT_KEY,
  9407. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  9408. };
  9409. var ClassName = {
  9410. SHOW: 'show',
  9411. COLLAPSE: 'collapse',
  9412. COLLAPSING: 'collapsing',
  9413. COLLAPSED: 'collapsed'
  9414. };
  9415. var Dimension = {
  9416. WIDTH: 'width',
  9417. HEIGHT: 'height'
  9418. };
  9419. var Selector = {
  9420. ACTIVES: '.show, .collapsing',
  9421. DATA_TOGGLE: '[data-toggle="collapse"]'
  9422. /**
  9423. * ------------------------------------------------------------------------
  9424. * Class Definition
  9425. * ------------------------------------------------------------------------
  9426. */
  9427. };
  9428. var Collapse =
  9429. /*#__PURE__*/
  9430. function () {
  9431. function Collapse(element, config) {
  9432. this._isTransitioning = false;
  9433. this._element = element;
  9434. this._config = this._getConfig(config);
  9435. this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
  9436. var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));
  9437. for (var i = 0, len = toggleList.length; i < len; i++) {
  9438. var elem = toggleList[i];
  9439. var selector = Util.getSelectorFromElement(elem);
  9440. var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {
  9441. return foundElem === element;
  9442. });
  9443. if (selector !== null && filterElement.length > 0) {
  9444. this._selector = selector;
  9445. this._triggerArray.push(elem);
  9446. }
  9447. }
  9448. this._parent = this._config.parent ? this._getParent() : null;
  9449. if (!this._config.parent) {
  9450. this._addAriaAndCollapsedClass(this._element, this._triggerArray);
  9451. }
  9452. if (this._config.toggle) {
  9453. this.toggle();
  9454. }
  9455. } // Getters
  9456. var _proto = Collapse.prototype;
  9457. // Public
  9458. _proto.toggle = function toggle() {
  9459. if ($$$1(this._element).hasClass(ClassName.SHOW)) {
  9460. this.hide();
  9461. } else {
  9462. this.show();
  9463. }
  9464. };
  9465. _proto.show = function show() {
  9466. var _this = this;
  9467. if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) {
  9468. return;
  9469. }
  9470. var actives;
  9471. var activesData;
  9472. if (this._parent) {
  9473. actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) {
  9474. return elem.getAttribute('data-parent') === _this._config.parent;
  9475. });
  9476. if (actives.length === 0) {
  9477. actives = null;
  9478. }
  9479. }
  9480. if (actives) {
  9481. activesData = $$$1(actives).not(this._selector).data(DATA_KEY);
  9482. if (activesData && activesData._isTransitioning) {
  9483. return;
  9484. }
  9485. }
  9486. var startEvent = $$$1.Event(Event.SHOW);
  9487. $$$1(this._element).trigger(startEvent);
  9488. if (startEvent.isDefaultPrevented()) {
  9489. return;
  9490. }
  9491. if (actives) {
  9492. Collapse._jQueryInterface.call($$$1(actives).not(this._selector), 'hide');
  9493. if (!activesData) {
  9494. $$$1(actives).data(DATA_KEY, null);
  9495. }
  9496. }
  9497. var dimension = this._getDimension();
  9498. $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
  9499. this._element.style[dimension] = 0;
  9500. if (this._triggerArray.length) {
  9501. $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
  9502. }
  9503. this.setTransitioning(true);
  9504. var complete = function complete() {
  9505. $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);
  9506. _this._element.style[dimension] = '';
  9507. _this.setTransitioning(false);
  9508. $$$1(_this._element).trigger(Event.SHOWN);
  9509. };
  9510. var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
  9511. var scrollSize = "scroll" + capitalizedDimension;
  9512. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  9513. $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  9514. this._element.style[dimension] = this._element[scrollSize] + "px";
  9515. };
  9516. _proto.hide = function hide() {
  9517. var _this2 = this;
  9518. if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) {
  9519. return;
  9520. }
  9521. var startEvent = $$$1.Event(Event.HIDE);
  9522. $$$1(this._element).trigger(startEvent);
  9523. if (startEvent.isDefaultPrevented()) {
  9524. return;
  9525. }
  9526. var dimension = this._getDimension();
  9527. this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
  9528. Util.reflow(this._element);
  9529. $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
  9530. var triggerArrayLength = this._triggerArray.length;
  9531. if (triggerArrayLength > 0) {
  9532. for (var i = 0; i < triggerArrayLength; i++) {
  9533. var trigger = this._triggerArray[i];
  9534. var selector = Util.getSelectorFromElement(trigger);
  9535. if (selector !== null) {
  9536. var $elem = $$$1([].slice.call(document.querySelectorAll(selector)));
  9537. if (!$elem.hasClass(ClassName.SHOW)) {
  9538. $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
  9539. }
  9540. }
  9541. }
  9542. }
  9543. this.setTransitioning(true);
  9544. var complete = function complete() {
  9545. _this2.setTransitioning(false);
  9546. $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
  9547. };
  9548. this._element.style[dimension] = '';
  9549. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  9550. $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  9551. };
  9552. _proto.setTransitioning = function setTransitioning(isTransitioning) {
  9553. this._isTransitioning = isTransitioning;
  9554. };
  9555. _proto.dispose = function dispose() {
  9556. $$$1.removeData(this._element, DATA_KEY);
  9557. this._config = null;
  9558. this._parent = null;
  9559. this._element = null;
  9560. this._triggerArray = null;
  9561. this._isTransitioning = null;
  9562. }; // Private
  9563. _proto._getConfig = function _getConfig(config) {
  9564. config = _objectSpread({}, Default, config);
  9565. config.toggle = Boolean(config.toggle); // Coerce string values
  9566. Util.typeCheckConfig(NAME, config, DefaultType);
  9567. return config;
  9568. };
  9569. _proto._getDimension = function _getDimension() {
  9570. var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH);
  9571. return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
  9572. };
  9573. _proto._getParent = function _getParent() {
  9574. var _this3 = this;
  9575. var parent = null;
  9576. if (Util.isElement(this._config.parent)) {
  9577. parent = this._config.parent; // It's a jQuery object
  9578. if (typeof this._config.parent.jquery !== 'undefined') {
  9579. parent = this._config.parent[0];
  9580. }
  9581. } else {
  9582. parent = document.querySelector(this._config.parent);
  9583. }
  9584. var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
  9585. var children = [].slice.call(parent.querySelectorAll(selector));
  9586. $$$1(children).each(function (i, element) {
  9587. _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
  9588. });
  9589. return parent;
  9590. };
  9591. _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
  9592. if (element) {
  9593. var isOpen = $$$1(element).hasClass(ClassName.SHOW);
  9594. if (triggerArray.length) {
  9595. $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
  9596. }
  9597. }
  9598. }; // Static
  9599. Collapse._getTargetFromElement = function _getTargetFromElement(element) {
  9600. var selector = Util.getSelectorFromElement(element);
  9601. return selector ? document.querySelector(selector) : null;
  9602. };
  9603. Collapse._jQueryInterface = function _jQueryInterface(config) {
  9604. return this.each(function () {
  9605. var $this = $$$1(this);
  9606. var data = $this.data(DATA_KEY);
  9607. var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {});
  9608. if (!data && _config.toggle && /show|hide/.test(config)) {
  9609. _config.toggle = false;
  9610. }
  9611. if (!data) {
  9612. data = new Collapse(this, _config);
  9613. $this.data(DATA_KEY, data);
  9614. }
  9615. if (typeof config === 'string') {
  9616. if (typeof data[config] === 'undefined') {
  9617. throw new TypeError("No method named \"" + config + "\"");
  9618. }
  9619. data[config]();
  9620. }
  9621. });
  9622. };
  9623. _createClass(Collapse, null, [{
  9624. key: "VERSION",
  9625. get: function get() {
  9626. return VERSION;
  9627. }
  9628. }, {
  9629. key: "Default",
  9630. get: function get() {
  9631. return Default;
  9632. }
  9633. }]);
  9634. return Collapse;
  9635. }();
  9636. /**
  9637. * ------------------------------------------------------------------------
  9638. * Data Api implementation
  9639. * ------------------------------------------------------------------------
  9640. */
  9641. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  9642. // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
  9643. if (event.currentTarget.tagName === 'A') {
  9644. event.preventDefault();
  9645. }
  9646. var $trigger = $$$1(this);
  9647. var selector = Util.getSelectorFromElement(this);
  9648. var selectors = [].slice.call(document.querySelectorAll(selector));
  9649. $$$1(selectors).each(function () {
  9650. var $target = $$$1(this);
  9651. var data = $target.data(DATA_KEY);
  9652. var config = data ? 'toggle' : $trigger.data();
  9653. Collapse._jQueryInterface.call($target, config);
  9654. });
  9655. });
  9656. /**
  9657. * ------------------------------------------------------------------------
  9658. * jQuery
  9659. * ------------------------------------------------------------------------
  9660. */
  9661. $$$1.fn[NAME] = Collapse._jQueryInterface;
  9662. $$$1.fn[NAME].Constructor = Collapse;
  9663. $$$1.fn[NAME].noConflict = function () {
  9664. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  9665. return Collapse._jQueryInterface;
  9666. };
  9667. return Collapse;
  9668. }($);
  9669. /**
  9670. * --------------------------------------------------------------------------
  9671. * Bootstrap (v4.1.3): dropdown.js
  9672. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9673. * --------------------------------------------------------------------------
  9674. */
  9675. var Dropdown = function ($$$1) {
  9676. /**
  9677. * ------------------------------------------------------------------------
  9678. * Constants
  9679. * ------------------------------------------------------------------------
  9680. */
  9681. var NAME = 'dropdown';
  9682. var VERSION = '4.1.3';
  9683. var DATA_KEY = 'bs.dropdown';
  9684. var EVENT_KEY = "." + DATA_KEY;
  9685. var DATA_API_KEY = '.data-api';
  9686. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  9687. var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  9688. var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
  9689. var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
  9690. var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
  9691. var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
  9692. var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
  9693. var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE);
  9694. var Event = {
  9695. HIDE: "hide" + EVENT_KEY,
  9696. HIDDEN: "hidden" + EVENT_KEY,
  9697. SHOW: "show" + EVENT_KEY,
  9698. SHOWN: "shown" + EVENT_KEY,
  9699. CLICK: "click" + EVENT_KEY,
  9700. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
  9701. KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY,
  9702. KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY
  9703. };
  9704. var ClassName = {
  9705. DISABLED: 'disabled',
  9706. SHOW: 'show',
  9707. DROPUP: 'dropup',
  9708. DROPRIGHT: 'dropright',
  9709. DROPLEFT: 'dropleft',
  9710. MENURIGHT: 'dropdown-menu-right',
  9711. MENULEFT: 'dropdown-menu-left',
  9712. POSITION_STATIC: 'position-static'
  9713. };
  9714. var Selector = {
  9715. DATA_TOGGLE: '[data-toggle="dropdown"]',
  9716. FORM_CHILD: '.dropdown form',
  9717. MENU: '.dropdown-menu',
  9718. NAVBAR_NAV: '.navbar-nav',
  9719. VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
  9720. };
  9721. var AttachmentMap = {
  9722. TOP: 'top-start',
  9723. TOPEND: 'top-end',
  9724. BOTTOM: 'bottom-start',
  9725. BOTTOMEND: 'bottom-end',
  9726. RIGHT: 'right-start',
  9727. RIGHTEND: 'right-end',
  9728. LEFT: 'left-start',
  9729. LEFTEND: 'left-end'
  9730. };
  9731. var Default = {
  9732. offset: 0,
  9733. flip: true,
  9734. boundary: 'scrollParent',
  9735. reference: 'toggle',
  9736. display: 'dynamic'
  9737. };
  9738. var DefaultType = {
  9739. offset: '(number|string|function)',
  9740. flip: 'boolean',
  9741. boundary: '(string|element)',
  9742. reference: '(string|element)',
  9743. display: 'string'
  9744. /**
  9745. * ------------------------------------------------------------------------
  9746. * Class Definition
  9747. * ------------------------------------------------------------------------
  9748. */
  9749. };
  9750. var Dropdown =
  9751. /*#__PURE__*/
  9752. function () {
  9753. function Dropdown(element, config) {
  9754. this._element = element;
  9755. this._popper = null;
  9756. this._config = this._getConfig(config);
  9757. this._menu = this._getMenuElement();
  9758. this._inNavbar = this._detectNavbar();
  9759. this._addEventListeners();
  9760. } // Getters
  9761. var _proto = Dropdown.prototype;
  9762. // Public
  9763. _proto.toggle = function toggle() {
  9764. if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) {
  9765. return;
  9766. }
  9767. var parent = Dropdown._getParentFromElement(this._element);
  9768. var isActive = $$$1(this._menu).hasClass(ClassName.SHOW);
  9769. Dropdown._clearMenus();
  9770. if (isActive) {
  9771. return;
  9772. }
  9773. var relatedTarget = {
  9774. relatedTarget: this._element
  9775. };
  9776. var showEvent = $$$1.Event(Event.SHOW, relatedTarget);
  9777. $$$1(parent).trigger(showEvent);
  9778. if (showEvent.isDefaultPrevented()) {
  9779. return;
  9780. } // Disable totally Popper.js for Dropdown in Navbar
  9781. if (!this._inNavbar) {
  9782. /**
  9783. * Check for Popper dependency
  9784. * Popper - https://popper.js.org
  9785. */
  9786. if (typeof Popper === 'undefined') {
  9787. throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)');
  9788. }
  9789. var referenceElement = this._element;
  9790. if (this._config.reference === 'parent') {
  9791. referenceElement = parent;
  9792. } else if (Util.isElement(this._config.reference)) {
  9793. referenceElement = this._config.reference; // Check if it's jQuery element
  9794. if (typeof this._config.reference.jquery !== 'undefined') {
  9795. referenceElement = this._config.reference[0];
  9796. }
  9797. } // If boundary is not `scrollParent`, then set position to `static`
  9798. // to allow the menu to "escape" the scroll parent's boundaries
  9799. // https://github.com/twbs/bootstrap/issues/24251
  9800. if (this._config.boundary !== 'scrollParent') {
  9801. $$$1(parent).addClass(ClassName.POSITION_STATIC);
  9802. }
  9803. this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig());
  9804. } // If this is a touch-enabled device we add extra
  9805. // empty mouseover listeners to the body's immediate children;
  9806. // only needed because of broken event delegation on iOS
  9807. // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
  9808. if ('ontouchstart' in document.documentElement && $$$1(parent).closest(Selector.NAVBAR_NAV).length === 0) {
  9809. $$$1(document.body).children().on('mouseover', null, $$$1.noop);
  9810. }
  9811. this._element.focus();
  9812. this._element.setAttribute('aria-expanded', true);
  9813. $$$1(this._menu).toggleClass(ClassName.SHOW);
  9814. $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget));
  9815. };
  9816. _proto.dispose = function dispose() {
  9817. $$$1.removeData(this._element, DATA_KEY);
  9818. $$$1(this._element).off(EVENT_KEY);
  9819. this._element = null;
  9820. this._menu = null;
  9821. if (this._popper !== null) {
  9822. this._popper.destroy();
  9823. this._popper = null;
  9824. }
  9825. };
  9826. _proto.update = function update() {
  9827. this._inNavbar = this._detectNavbar();
  9828. if (this._popper !== null) {
  9829. this._popper.scheduleUpdate();
  9830. }
  9831. }; // Private
  9832. _proto._addEventListeners = function _addEventListeners() {
  9833. var _this = this;
  9834. $$$1(this._element).on(Event.CLICK, function (event) {
  9835. event.preventDefault();
  9836. event.stopPropagation();
  9837. _this.toggle();
  9838. });
  9839. };
  9840. _proto._getConfig = function _getConfig(config) {
  9841. config = _objectSpread({}, this.constructor.Default, $$$1(this._element).data(), config);
  9842. Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
  9843. return config;
  9844. };
  9845. _proto._getMenuElement = function _getMenuElement() {
  9846. if (!this._menu) {
  9847. var parent = Dropdown._getParentFromElement(this._element);
  9848. if (parent) {
  9849. this._menu = parent.querySelector(Selector.MENU);
  9850. }
  9851. }
  9852. return this._menu;
  9853. };
  9854. _proto._getPlacement = function _getPlacement() {
  9855. var $parentDropdown = $$$1(this._element.parentNode);
  9856. var placement = AttachmentMap.BOTTOM; // Handle dropup
  9857. if ($parentDropdown.hasClass(ClassName.DROPUP)) {
  9858. placement = AttachmentMap.TOP;
  9859. if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
  9860. placement = AttachmentMap.TOPEND;
  9861. }
  9862. } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {
  9863. placement = AttachmentMap.RIGHT;
  9864. } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {
  9865. placement = AttachmentMap.LEFT;
  9866. } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
  9867. placement = AttachmentMap.BOTTOMEND;
  9868. }
  9869. return placement;
  9870. };
  9871. _proto._detectNavbar = function _detectNavbar() {
  9872. return $$$1(this._element).closest('.navbar').length > 0;
  9873. };
  9874. _proto._getPopperConfig = function _getPopperConfig() {
  9875. var _this2 = this;
  9876. var offsetConf = {};
  9877. if (typeof this._config.offset === 'function') {
  9878. offsetConf.fn = function (data) {
  9879. data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets) || {});
  9880. return data;
  9881. };
  9882. } else {
  9883. offsetConf.offset = this._config.offset;
  9884. }
  9885. var popperConfig = {
  9886. placement: this._getPlacement(),
  9887. modifiers: {
  9888. offset: offsetConf,
  9889. flip: {
  9890. enabled: this._config.flip
  9891. },
  9892. preventOverflow: {
  9893. boundariesElement: this._config.boundary
  9894. }
  9895. } // Disable Popper.js if we have a static display
  9896. };
  9897. if (this._config.display === 'static') {
  9898. popperConfig.modifiers.applyStyle = {
  9899. enabled: false
  9900. };
  9901. }
  9902. return popperConfig;
  9903. }; // Static
  9904. Dropdown._jQueryInterface = function _jQueryInterface(config) {
  9905. return this.each(function () {
  9906. var data = $$$1(this).data(DATA_KEY);
  9907. var _config = typeof config === 'object' ? config : null;
  9908. if (!data) {
  9909. data = new Dropdown(this, _config);
  9910. $$$1(this).data(DATA_KEY, data);
  9911. }
  9912. if (typeof config === 'string') {
  9913. if (typeof data[config] === 'undefined') {
  9914. throw new TypeError("No method named \"" + config + "\"");
  9915. }
  9916. data[config]();
  9917. }
  9918. });
  9919. };
  9920. Dropdown._clearMenus = function _clearMenus(event) {
  9921. if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
  9922. return;
  9923. }
  9924. var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));
  9925. for (var i = 0, len = toggles.length; i < len; i++) {
  9926. var parent = Dropdown._getParentFromElement(toggles[i]);
  9927. var context = $$$1(toggles[i]).data(DATA_KEY);
  9928. var relatedTarget = {
  9929. relatedTarget: toggles[i]
  9930. };
  9931. if (event && event.type === 'click') {
  9932. relatedTarget.clickEvent = event;
  9933. }
  9934. if (!context) {
  9935. continue;
  9936. }
  9937. var dropdownMenu = context._menu;
  9938. if (!$$$1(parent).hasClass(ClassName.SHOW)) {
  9939. continue;
  9940. }
  9941. if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) {
  9942. continue;
  9943. }
  9944. var hideEvent = $$$1.Event(Event.HIDE, relatedTarget);
  9945. $$$1(parent).trigger(hideEvent);
  9946. if (hideEvent.isDefaultPrevented()) {
  9947. continue;
  9948. } // If this is a touch-enabled device we remove the extra
  9949. // empty mouseover listeners we added for iOS support
  9950. if ('ontouchstart' in document.documentElement) {
  9951. $$$1(document.body).children().off('mouseover', null, $$$1.noop);
  9952. }
  9953. toggles[i].setAttribute('aria-expanded', 'false');
  9954. $$$1(dropdownMenu).removeClass(ClassName.SHOW);
  9955. $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget));
  9956. }
  9957. };
  9958. Dropdown._getParentFromElement = function _getParentFromElement(element) {
  9959. var parent;
  9960. var selector = Util.getSelectorFromElement(element);
  9961. if (selector) {
  9962. parent = document.querySelector(selector);
  9963. }
  9964. return parent || element.parentNode;
  9965. }; // eslint-disable-next-line complexity
  9966. Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
  9967. // If not input/textarea:
  9968. // - And not a key in REGEXP_KEYDOWN => not a dropdown command
  9969. // If input/textarea:
  9970. // - If space key => not a dropdown command
  9971. // - If key is other than escape
  9972. // - If key is not up or down => not a dropdown command
  9973. // - If trigger inside the menu => not a dropdown command
  9974. if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
  9975. return;
  9976. }
  9977. event.preventDefault();
  9978. event.stopPropagation();
  9979. if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) {
  9980. return;
  9981. }
  9982. var parent = Dropdown._getParentFromElement(this);
  9983. var isActive = $$$1(parent).hasClass(ClassName.SHOW);
  9984. if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
  9985. if (event.which === ESCAPE_KEYCODE) {
  9986. var toggle = parent.querySelector(Selector.DATA_TOGGLE);
  9987. $$$1(toggle).trigger('focus');
  9988. }
  9989. $$$1(this).trigger('click');
  9990. return;
  9991. }
  9992. var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS));
  9993. if (items.length === 0) {
  9994. return;
  9995. }
  9996. var index = items.indexOf(event.target);
  9997. if (event.which === ARROW_UP_KEYCODE && index > 0) {
  9998. // Up
  9999. index--;
  10000. }
  10001. if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
  10002. // Down
  10003. index++;
  10004. }
  10005. if (index < 0) {
  10006. index = 0;
  10007. }
  10008. items[index].focus();
  10009. };
  10010. _createClass(Dropdown, null, [{
  10011. key: "VERSION",
  10012. get: function get() {
  10013. return VERSION;
  10014. }
  10015. }, {
  10016. key: "Default",
  10017. get: function get() {
  10018. return Default;
  10019. }
  10020. }, {
  10021. key: "DefaultType",
  10022. get: function get() {
  10023. return DefaultType;
  10024. }
  10025. }]);
  10026. return Dropdown;
  10027. }();
  10028. /**
  10029. * ------------------------------------------------------------------------
  10030. * Data Api implementation
  10031. * ------------------------------------------------------------------------
  10032. */
  10033. $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  10034. event.preventDefault();
  10035. event.stopPropagation();
  10036. Dropdown._jQueryInterface.call($$$1(this), 'toggle');
  10037. }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
  10038. e.stopPropagation();
  10039. });
  10040. /**
  10041. * ------------------------------------------------------------------------
  10042. * jQuery
  10043. * ------------------------------------------------------------------------
  10044. */
  10045. $$$1.fn[NAME] = Dropdown._jQueryInterface;
  10046. $$$1.fn[NAME].Constructor = Dropdown;
  10047. $$$1.fn[NAME].noConflict = function () {
  10048. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  10049. return Dropdown._jQueryInterface;
  10050. };
  10051. return Dropdown;
  10052. }($, Popper);
  10053. /**
  10054. * --------------------------------------------------------------------------
  10055. * Bootstrap (v4.1.3): modal.js
  10056. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10057. * --------------------------------------------------------------------------
  10058. */
  10059. var Modal = function ($$$1) {
  10060. /**
  10061. * ------------------------------------------------------------------------
  10062. * Constants
  10063. * ------------------------------------------------------------------------
  10064. */
  10065. var NAME = 'modal';
  10066. var VERSION = '4.1.3';
  10067. var DATA_KEY = 'bs.modal';
  10068. var EVENT_KEY = "." + DATA_KEY;
  10069. var DATA_API_KEY = '.data-api';
  10070. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  10071. var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  10072. var Default = {
  10073. backdrop: true,
  10074. keyboard: true,
  10075. focus: true,
  10076. show: true
  10077. };
  10078. var DefaultType = {
  10079. backdrop: '(boolean|string)',
  10080. keyboard: 'boolean',
  10081. focus: 'boolean',
  10082. show: 'boolean'
  10083. };
  10084. var Event = {
  10085. HIDE: "hide" + EVENT_KEY,
  10086. HIDDEN: "hidden" + EVENT_KEY,
  10087. SHOW: "show" + EVENT_KEY,
  10088. SHOWN: "shown" + EVENT_KEY,
  10089. FOCUSIN: "focusin" + EVENT_KEY,
  10090. RESIZE: "resize" + EVENT_KEY,
  10091. CLICK_DISMISS: "click.dismiss" + EVENT_KEY,
  10092. KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY,
  10093. MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY,
  10094. MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY,
  10095. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  10096. };
  10097. var ClassName = {
  10098. SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
  10099. BACKDROP: 'modal-backdrop',
  10100. OPEN: 'modal-open',
  10101. FADE: 'fade',
  10102. SHOW: 'show'
  10103. };
  10104. var Selector = {
  10105. DIALOG: '.modal-dialog',
  10106. DATA_TOGGLE: '[data-toggle="modal"]',
  10107. DATA_DISMISS: '[data-dismiss="modal"]',
  10108. FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
  10109. STICKY_CONTENT: '.sticky-top'
  10110. /**
  10111. * ------------------------------------------------------------------------
  10112. * Class Definition
  10113. * ------------------------------------------------------------------------
  10114. */
  10115. };
  10116. var Modal =
  10117. /*#__PURE__*/
  10118. function () {
  10119. function Modal(element, config) {
  10120. this._config = this._getConfig(config);
  10121. this._element = element;
  10122. this._dialog = element.querySelector(Selector.DIALOG);
  10123. this._backdrop = null;
  10124. this._isShown = false;
  10125. this._isBodyOverflowing = false;
  10126. this._ignoreBackdropClick = false;
  10127. this._scrollbarWidth = 0;
  10128. } // Getters
  10129. var _proto = Modal.prototype;
  10130. // Public
  10131. _proto.toggle = function toggle(relatedTarget) {
  10132. return this._isShown ? this.hide() : this.show(relatedTarget);
  10133. };
  10134. _proto.show = function show(relatedTarget) {
  10135. var _this = this;
  10136. if (this._isTransitioning || this._isShown) {
  10137. return;
  10138. }
  10139. if ($$$1(this._element).hasClass(ClassName.FADE)) {
  10140. this._isTransitioning = true;
  10141. }
  10142. var showEvent = $$$1.Event(Event.SHOW, {
  10143. relatedTarget: relatedTarget
  10144. });
  10145. $$$1(this._element).trigger(showEvent);
  10146. if (this._isShown || showEvent.isDefaultPrevented()) {
  10147. return;
  10148. }
  10149. this._isShown = true;
  10150. this._checkScrollbar();
  10151. this._setScrollbar();
  10152. this._adjustDialog();
  10153. $$$1(document.body).addClass(ClassName.OPEN);
  10154. this._setEscapeEvent();
  10155. this._setResizeEvent();
  10156. $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {
  10157. return _this.hide(event);
  10158. });
  10159. $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
  10160. $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {
  10161. if ($$$1(event.target).is(_this._element)) {
  10162. _this._ignoreBackdropClick = true;
  10163. }
  10164. });
  10165. });
  10166. this._showBackdrop(function () {
  10167. return _this._showElement(relatedTarget);
  10168. });
  10169. };
  10170. _proto.hide = function hide(event) {
  10171. var _this2 = this;
  10172. if (event) {
  10173. event.preventDefault();
  10174. }
  10175. if (this._isTransitioning || !this._isShown) {
  10176. return;
  10177. }
  10178. var hideEvent = $$$1.Event(Event.HIDE);
  10179. $$$1(this._element).trigger(hideEvent);
  10180. if (!this._isShown || hideEvent.isDefaultPrevented()) {
  10181. return;
  10182. }
  10183. this._isShown = false;
  10184. var transition = $$$1(this._element).hasClass(ClassName.FADE);
  10185. if (transition) {
  10186. this._isTransitioning = true;
  10187. }
  10188. this._setEscapeEvent();
  10189. this._setResizeEvent();
  10190. $$$1(document).off(Event.FOCUSIN);
  10191. $$$1(this._element).removeClass(ClassName.SHOW);
  10192. $$$1(this._element).off(Event.CLICK_DISMISS);
  10193. $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS);
  10194. if (transition) {
  10195. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  10196. $$$1(this._element).one(Util.TRANSITION_END, function (event) {
  10197. return _this2._hideModal(event);
  10198. }).emulateTransitionEnd(transitionDuration);
  10199. } else {
  10200. this._hideModal();
  10201. }
  10202. };
  10203. _proto.dispose = function dispose() {
  10204. $$$1.removeData(this._element, DATA_KEY);
  10205. $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY);
  10206. this._config = null;
  10207. this._element = null;
  10208. this._dialog = null;
  10209. this._backdrop = null;
  10210. this._isShown = null;
  10211. this._isBodyOverflowing = null;
  10212. this._ignoreBackdropClick = null;
  10213. this._scrollbarWidth = null;
  10214. };
  10215. _proto.handleUpdate = function handleUpdate() {
  10216. this._adjustDialog();
  10217. }; // Private
  10218. _proto._getConfig = function _getConfig(config) {
  10219. config = _objectSpread({}, Default, config);
  10220. Util.typeCheckConfig(NAME, config, DefaultType);
  10221. return config;
  10222. };
  10223. _proto._showElement = function _showElement(relatedTarget) {
  10224. var _this3 = this;
  10225. var transition = $$$1(this._element).hasClass(ClassName.FADE);
  10226. if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
  10227. // Don't move modal's DOM position
  10228. document.body.appendChild(this._element);
  10229. }
  10230. this._element.style.display = 'block';
  10231. this._element.removeAttribute('aria-hidden');
  10232. this._element.scrollTop = 0;
  10233. if (transition) {
  10234. Util.reflow(this._element);
  10235. }
  10236. $$$1(this._element).addClass(ClassName.SHOW);
  10237. if (this._config.focus) {
  10238. this._enforceFocus();
  10239. }
  10240. var shownEvent = $$$1.Event(Event.SHOWN, {
  10241. relatedTarget: relatedTarget
  10242. });
  10243. var transitionComplete = function transitionComplete() {
  10244. if (_this3._config.focus) {
  10245. _this3._element.focus();
  10246. }
  10247. _this3._isTransitioning = false;
  10248. $$$1(_this3._element).trigger(shownEvent);
  10249. };
  10250. if (transition) {
  10251. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  10252. $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);
  10253. } else {
  10254. transitionComplete();
  10255. }
  10256. };
  10257. _proto._enforceFocus = function _enforceFocus() {
  10258. var _this4 = this;
  10259. $$$1(document).off(Event.FOCUSIN) // Guard against infinite focus loop
  10260. .on(Event.FOCUSIN, function (event) {
  10261. if (document !== event.target && _this4._element !== event.target && $$$1(_this4._element).has(event.target).length === 0) {
  10262. _this4._element.focus();
  10263. }
  10264. });
  10265. };
  10266. _proto._setEscapeEvent = function _setEscapeEvent() {
  10267. var _this5 = this;
  10268. if (this._isShown && this._config.keyboard) {
  10269. $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
  10270. if (event.which === ESCAPE_KEYCODE) {
  10271. event.preventDefault();
  10272. _this5.hide();
  10273. }
  10274. });
  10275. } else if (!this._isShown) {
  10276. $$$1(this._element).off(Event.KEYDOWN_DISMISS);
  10277. }
  10278. };
  10279. _proto._setResizeEvent = function _setResizeEvent() {
  10280. var _this6 = this;
  10281. if (this._isShown) {
  10282. $$$1(window).on(Event.RESIZE, function (event) {
  10283. return _this6.handleUpdate(event);
  10284. });
  10285. } else {
  10286. $$$1(window).off(Event.RESIZE);
  10287. }
  10288. };
  10289. _proto._hideModal = function _hideModal() {
  10290. var _this7 = this;
  10291. this._element.style.display = 'none';
  10292. this._element.setAttribute('aria-hidden', true);
  10293. this._isTransitioning = false;
  10294. this._showBackdrop(function () {
  10295. $$$1(document.body).removeClass(ClassName.OPEN);
  10296. _this7._resetAdjustments();
  10297. _this7._resetScrollbar();
  10298. $$$1(_this7._element).trigger(Event.HIDDEN);
  10299. });
  10300. };
  10301. _proto._removeBackdrop = function _removeBackdrop() {
  10302. if (this._backdrop) {
  10303. $$$1(this._backdrop).remove();
  10304. this._backdrop = null;
  10305. }
  10306. };
  10307. _proto._showBackdrop = function _showBackdrop(callback) {
  10308. var _this8 = this;
  10309. var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
  10310. if (this._isShown && this._config.backdrop) {
  10311. this._backdrop = document.createElement('div');
  10312. this._backdrop.className = ClassName.BACKDROP;
  10313. if (animate) {
  10314. this._backdrop.classList.add(animate);
  10315. }
  10316. $$$1(this._backdrop).appendTo(document.body);
  10317. $$$1(this._element).on(Event.CLICK_DISMISS, function (event) {
  10318. if (_this8._ignoreBackdropClick) {
  10319. _this8._ignoreBackdropClick = false;
  10320. return;
  10321. }
  10322. if (event.target !== event.currentTarget) {
  10323. return;
  10324. }
  10325. if (_this8._config.backdrop === 'static') {
  10326. _this8._element.focus();
  10327. } else {
  10328. _this8.hide();
  10329. }
  10330. });
  10331. if (animate) {
  10332. Util.reflow(this._backdrop);
  10333. }
  10334. $$$1(this._backdrop).addClass(ClassName.SHOW);
  10335. if (!callback) {
  10336. return;
  10337. }
  10338. if (!animate) {
  10339. callback();
  10340. return;
  10341. }
  10342. var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
  10343. $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);
  10344. } else if (!this._isShown && this._backdrop) {
  10345. $$$1(this._backdrop).removeClass(ClassName.SHOW);
  10346. var callbackRemove = function callbackRemove() {
  10347. _this8._removeBackdrop();
  10348. if (callback) {
  10349. callback();
  10350. }
  10351. };
  10352. if ($$$1(this._element).hasClass(ClassName.FADE)) {
  10353. var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
  10354. $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);
  10355. } else {
  10356. callbackRemove();
  10357. }
  10358. } else if (callback) {
  10359. callback();
  10360. }
  10361. }; // ----------------------------------------------------------------------
  10362. // the following methods are used to handle overflowing modals
  10363. // todo (fat): these should probably be refactored out of modal.js
  10364. // ----------------------------------------------------------------------
  10365. _proto._adjustDialog = function _adjustDialog() {
  10366. var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
  10367. if (!this._isBodyOverflowing && isModalOverflowing) {
  10368. this._element.style.paddingLeft = this._scrollbarWidth + "px";
  10369. }
  10370. if (this._isBodyOverflowing && !isModalOverflowing) {
  10371. this._element.style.paddingRight = this._scrollbarWidth + "px";
  10372. }
  10373. };
  10374. _proto._resetAdjustments = function _resetAdjustments() {
  10375. this._element.style.paddingLeft = '';
  10376. this._element.style.paddingRight = '';
  10377. };
  10378. _proto._checkScrollbar = function _checkScrollbar() {
  10379. var rect = document.body.getBoundingClientRect();
  10380. this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;
  10381. this._scrollbarWidth = this._getScrollbarWidth();
  10382. };
  10383. _proto._setScrollbar = function _setScrollbar() {
  10384. var _this9 = this;
  10385. if (this._isBodyOverflowing) {
  10386. // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
  10387. // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
  10388. var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
  10389. var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding
  10390. $$$1(fixedContent).each(function (index, element) {
  10391. var actualPadding = element.style.paddingRight;
  10392. var calculatedPadding = $$$1(element).css('padding-right');
  10393. $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px");
  10394. }); // Adjust sticky content margin
  10395. $$$1(stickyContent).each(function (index, element) {
  10396. var actualMargin = element.style.marginRight;
  10397. var calculatedMargin = $$$1(element).css('margin-right');
  10398. $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px");
  10399. }); // Adjust body padding
  10400. var actualPadding = document.body.style.paddingRight;
  10401. var calculatedPadding = $$$1(document.body).css('padding-right');
  10402. $$$1(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
  10403. }
  10404. };
  10405. _proto._resetScrollbar = function _resetScrollbar() {
  10406. // Restore fixed content padding
  10407. var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
  10408. $$$1(fixedContent).each(function (index, element) {
  10409. var padding = $$$1(element).data('padding-right');
  10410. $$$1(element).removeData('padding-right');
  10411. element.style.paddingRight = padding ? padding : '';
  10412. }); // Restore sticky content
  10413. var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT));
  10414. $$$1(elements).each(function (index, element) {
  10415. var margin = $$$1(element).data('margin-right');
  10416. if (typeof margin !== 'undefined') {
  10417. $$$1(element).css('margin-right', margin).removeData('margin-right');
  10418. }
  10419. }); // Restore body padding
  10420. var padding = $$$1(document.body).data('padding-right');
  10421. $$$1(document.body).removeData('padding-right');
  10422. document.body.style.paddingRight = padding ? padding : '';
  10423. };
  10424. _proto._getScrollbarWidth = function _getScrollbarWidth() {
  10425. // thx d.walsh
  10426. var scrollDiv = document.createElement('div');
  10427. scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
  10428. document.body.appendChild(scrollDiv);
  10429. var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
  10430. document.body.removeChild(scrollDiv);
  10431. return scrollbarWidth;
  10432. }; // Static
  10433. Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
  10434. return this.each(function () {
  10435. var data = $$$1(this).data(DATA_KEY);
  10436. var _config = _objectSpread({}, Default, $$$1(this).data(), typeof config === 'object' && config ? config : {});
  10437. if (!data) {
  10438. data = new Modal(this, _config);
  10439. $$$1(this).data(DATA_KEY, data);
  10440. }
  10441. if (typeof config === 'string') {
  10442. if (typeof data[config] === 'undefined') {
  10443. throw new TypeError("No method named \"" + config + "\"");
  10444. }
  10445. data[config](relatedTarget);
  10446. } else if (_config.show) {
  10447. data.show(relatedTarget);
  10448. }
  10449. });
  10450. };
  10451. _createClass(Modal, null, [{
  10452. key: "VERSION",
  10453. get: function get() {
  10454. return VERSION;
  10455. }
  10456. }, {
  10457. key: "Default",
  10458. get: function get() {
  10459. return Default;
  10460. }
  10461. }]);
  10462. return Modal;
  10463. }();
  10464. /**
  10465. * ------------------------------------------------------------------------
  10466. * Data Api implementation
  10467. * ------------------------------------------------------------------------
  10468. */
  10469. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  10470. var _this10 = this;
  10471. var target;
  10472. var selector = Util.getSelectorFromElement(this);
  10473. if (selector) {
  10474. target = document.querySelector(selector);
  10475. }
  10476. var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data());
  10477. if (this.tagName === 'A' || this.tagName === 'AREA') {
  10478. event.preventDefault();
  10479. }
  10480. var $target = $$$1(target).one(Event.SHOW, function (showEvent) {
  10481. if (showEvent.isDefaultPrevented()) {
  10482. // Only register focus restorer if modal will actually get shown
  10483. return;
  10484. }
  10485. $target.one(Event.HIDDEN, function () {
  10486. if ($$$1(_this10).is(':visible')) {
  10487. _this10.focus();
  10488. }
  10489. });
  10490. });
  10491. Modal._jQueryInterface.call($$$1(target), config, this);
  10492. });
  10493. /**
  10494. * ------------------------------------------------------------------------
  10495. * jQuery
  10496. * ------------------------------------------------------------------------
  10497. */
  10498. $$$1.fn[NAME] = Modal._jQueryInterface;
  10499. $$$1.fn[NAME].Constructor = Modal;
  10500. $$$1.fn[NAME].noConflict = function () {
  10501. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  10502. return Modal._jQueryInterface;
  10503. };
  10504. return Modal;
  10505. }($);
  10506. /**
  10507. * --------------------------------------------------------------------------
  10508. * Bootstrap (v4.1.3): tooltip.js
  10509. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10510. * --------------------------------------------------------------------------
  10511. */
  10512. var Tooltip = function ($$$1) {
  10513. /**
  10514. * ------------------------------------------------------------------------
  10515. * Constants
  10516. * ------------------------------------------------------------------------
  10517. */
  10518. var NAME = 'tooltip';
  10519. var VERSION = '4.1.3';
  10520. var DATA_KEY = 'bs.tooltip';
  10521. var EVENT_KEY = "." + DATA_KEY;
  10522. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  10523. var CLASS_PREFIX = 'bs-tooltip';
  10524. var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
  10525. var DefaultType = {
  10526. animation: 'boolean',
  10527. template: 'string',
  10528. title: '(string|element|function)',
  10529. trigger: 'string',
  10530. delay: '(number|object)',
  10531. html: 'boolean',
  10532. selector: '(string|boolean)',
  10533. placement: '(string|function)',
  10534. offset: '(number|string)',
  10535. container: '(string|element|boolean)',
  10536. fallbackPlacement: '(string|array)',
  10537. boundary: '(string|element)'
  10538. };
  10539. var AttachmentMap = {
  10540. AUTO: 'auto',
  10541. TOP: 'top',
  10542. RIGHT: 'right',
  10543. BOTTOM: 'bottom',
  10544. LEFT: 'left'
  10545. };
  10546. var Default = {
  10547. animation: true,
  10548. template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
  10549. trigger: 'hover focus',
  10550. title: '',
  10551. delay: 0,
  10552. html: false,
  10553. selector: false,
  10554. placement: 'top',
  10555. offset: 0,
  10556. container: false,
  10557. fallbackPlacement: 'flip',
  10558. boundary: 'scrollParent'
  10559. };
  10560. var HoverState = {
  10561. SHOW: 'show',
  10562. OUT: 'out'
  10563. };
  10564. var Event = {
  10565. HIDE: "hide" + EVENT_KEY,
  10566. HIDDEN: "hidden" + EVENT_KEY,
  10567. SHOW: "show" + EVENT_KEY,
  10568. SHOWN: "shown" + EVENT_KEY,
  10569. INSERTED: "inserted" + EVENT_KEY,
  10570. CLICK: "click" + EVENT_KEY,
  10571. FOCUSIN: "focusin" + EVENT_KEY,
  10572. FOCUSOUT: "focusout" + EVENT_KEY,
  10573. MOUSEENTER: "mouseenter" + EVENT_KEY,
  10574. MOUSELEAVE: "mouseleave" + EVENT_KEY
  10575. };
  10576. var ClassName = {
  10577. FADE: 'fade',
  10578. SHOW: 'show'
  10579. };
  10580. var Selector = {
  10581. TOOLTIP: '.tooltip',
  10582. TOOLTIP_INNER: '.tooltip-inner',
  10583. ARROW: '.arrow'
  10584. };
  10585. var Trigger = {
  10586. HOVER: 'hover',
  10587. FOCUS: 'focus',
  10588. CLICK: 'click',
  10589. MANUAL: 'manual'
  10590. /**
  10591. * ------------------------------------------------------------------------
  10592. * Class Definition
  10593. * ------------------------------------------------------------------------
  10594. */
  10595. };
  10596. var Tooltip =
  10597. /*#__PURE__*/
  10598. function () {
  10599. function Tooltip(element, config) {
  10600. /**
  10601. * Check for Popper dependency
  10602. * Popper - https://popper.js.org
  10603. */
  10604. if (typeof Popper === 'undefined') {
  10605. throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)');
  10606. } // private
  10607. this._isEnabled = true;
  10608. this._timeout = 0;
  10609. this._hoverState = '';
  10610. this._activeTrigger = {};
  10611. this._popper = null; // Protected
  10612. this.element = element;
  10613. this.config = this._getConfig(config);
  10614. this.tip = null;
  10615. this._setListeners();
  10616. } // Getters
  10617. var _proto = Tooltip.prototype;
  10618. // Public
  10619. _proto.enable = function enable() {
  10620. this._isEnabled = true;
  10621. };
  10622. _proto.disable = function disable() {
  10623. this._isEnabled = false;
  10624. };
  10625. _proto.toggleEnabled = function toggleEnabled() {
  10626. this._isEnabled = !this._isEnabled;
  10627. };
  10628. _proto.toggle = function toggle(event) {
  10629. if (!this._isEnabled) {
  10630. return;
  10631. }
  10632. if (event) {
  10633. var dataKey = this.constructor.DATA_KEY;
  10634. var context = $$$1(event.currentTarget).data(dataKey);
  10635. if (!context) {
  10636. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10637. $$$1(event.currentTarget).data(dataKey, context);
  10638. }
  10639. context._activeTrigger.click = !context._activeTrigger.click;
  10640. if (context._isWithActiveTrigger()) {
  10641. context._enter(null, context);
  10642. } else {
  10643. context._leave(null, context);
  10644. }
  10645. } else {
  10646. if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) {
  10647. this._leave(null, this);
  10648. return;
  10649. }
  10650. this._enter(null, this);
  10651. }
  10652. };
  10653. _proto.dispose = function dispose() {
  10654. clearTimeout(this._timeout);
  10655. $$$1.removeData(this.element, this.constructor.DATA_KEY);
  10656. $$$1(this.element).off(this.constructor.EVENT_KEY);
  10657. $$$1(this.element).closest('.modal').off('hide.bs.modal');
  10658. if (this.tip) {
  10659. $$$1(this.tip).remove();
  10660. }
  10661. this._isEnabled = null;
  10662. this._timeout = null;
  10663. this._hoverState = null;
  10664. this._activeTrigger = null;
  10665. if (this._popper !== null) {
  10666. this._popper.destroy();
  10667. }
  10668. this._popper = null;
  10669. this.element = null;
  10670. this.config = null;
  10671. this.tip = null;
  10672. };
  10673. _proto.show = function show() {
  10674. var _this = this;
  10675. if ($$$1(this.element).css('display') === 'none') {
  10676. throw new Error('Please use show on visible elements');
  10677. }
  10678. var showEvent = $$$1.Event(this.constructor.Event.SHOW);
  10679. if (this.isWithContent() && this._isEnabled) {
  10680. $$$1(this.element).trigger(showEvent);
  10681. var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element);
  10682. if (showEvent.isDefaultPrevented() || !isInTheDom) {
  10683. return;
  10684. }
  10685. var tip = this.getTipElement();
  10686. var tipId = Util.getUID(this.constructor.NAME);
  10687. tip.setAttribute('id', tipId);
  10688. this.element.setAttribute('aria-describedby', tipId);
  10689. this.setContent();
  10690. if (this.config.animation) {
  10691. $$$1(tip).addClass(ClassName.FADE);
  10692. }
  10693. var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
  10694. var attachment = this._getAttachment(placement);
  10695. this.addAttachmentClass(attachment);
  10696. var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container);
  10697. $$$1(tip).data(this.constructor.DATA_KEY, this);
  10698. if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) {
  10699. $$$1(tip).appendTo(container);
  10700. }
  10701. $$$1(this.element).trigger(this.constructor.Event.INSERTED);
  10702. this._popper = new Popper(this.element, tip, {
  10703. placement: attachment,
  10704. modifiers: {
  10705. offset: {
  10706. offset: this.config.offset
  10707. },
  10708. flip: {
  10709. behavior: this.config.fallbackPlacement
  10710. },
  10711. arrow: {
  10712. element: Selector.ARROW
  10713. },
  10714. preventOverflow: {
  10715. boundariesElement: this.config.boundary
  10716. }
  10717. },
  10718. onCreate: function onCreate(data) {
  10719. if (data.originalPlacement !== data.placement) {
  10720. _this._handlePopperPlacementChange(data);
  10721. }
  10722. },
  10723. onUpdate: function onUpdate(data) {
  10724. _this._handlePopperPlacementChange(data);
  10725. }
  10726. });
  10727. $$$1(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra
  10728. // empty mouseover listeners to the body's immediate children;
  10729. // only needed because of broken event delegation on iOS
  10730. // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
  10731. if ('ontouchstart' in document.documentElement) {
  10732. $$$1(document.body).children().on('mouseover', null, $$$1.noop);
  10733. }
  10734. var complete = function complete() {
  10735. if (_this.config.animation) {
  10736. _this._fixTransition();
  10737. }
  10738. var prevHoverState = _this._hoverState;
  10739. _this._hoverState = null;
  10740. $$$1(_this.element).trigger(_this.constructor.Event.SHOWN);
  10741. if (prevHoverState === HoverState.OUT) {
  10742. _this._leave(null, _this);
  10743. }
  10744. };
  10745. if ($$$1(this.tip).hasClass(ClassName.FADE)) {
  10746. var transitionDuration = Util.getTransitionDurationFromElement(this.tip);
  10747. $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  10748. } else {
  10749. complete();
  10750. }
  10751. }
  10752. };
  10753. _proto.hide = function hide(callback) {
  10754. var _this2 = this;
  10755. var tip = this.getTipElement();
  10756. var hideEvent = $$$1.Event(this.constructor.Event.HIDE);
  10757. var complete = function complete() {
  10758. if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {
  10759. tip.parentNode.removeChild(tip);
  10760. }
  10761. _this2._cleanTipClass();
  10762. _this2.element.removeAttribute('aria-describedby');
  10763. $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
  10764. if (_this2._popper !== null) {
  10765. _this2._popper.destroy();
  10766. }
  10767. if (callback) {
  10768. callback();
  10769. }
  10770. };
  10771. $$$1(this.element).trigger(hideEvent);
  10772. if (hideEvent.isDefaultPrevented()) {
  10773. return;
  10774. }
  10775. $$$1(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra
  10776. // empty mouseover listeners we added for iOS support
  10777. if ('ontouchstart' in document.documentElement) {
  10778. $$$1(document.body).children().off('mouseover', null, $$$1.noop);
  10779. }
  10780. this._activeTrigger[Trigger.CLICK] = false;
  10781. this._activeTrigger[Trigger.FOCUS] = false;
  10782. this._activeTrigger[Trigger.HOVER] = false;
  10783. if ($$$1(this.tip).hasClass(ClassName.FADE)) {
  10784. var transitionDuration = Util.getTransitionDurationFromElement(tip);
  10785. $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  10786. } else {
  10787. complete();
  10788. }
  10789. this._hoverState = '';
  10790. };
  10791. _proto.update = function update() {
  10792. if (this._popper !== null) {
  10793. this._popper.scheduleUpdate();
  10794. }
  10795. }; // Protected
  10796. _proto.isWithContent = function isWithContent() {
  10797. return Boolean(this.getTitle());
  10798. };
  10799. _proto.addAttachmentClass = function addAttachmentClass(attachment) {
  10800. $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
  10801. };
  10802. _proto.getTipElement = function getTipElement() {
  10803. this.tip = this.tip || $$$1(this.config.template)[0];
  10804. return this.tip;
  10805. };
  10806. _proto.setContent = function setContent() {
  10807. var tip = this.getTipElement();
  10808. this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle());
  10809. $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW);
  10810. };
  10811. _proto.setElementContent = function setElementContent($element, content) {
  10812. var html = this.config.html;
  10813. if (typeof content === 'object' && (content.nodeType || content.jquery)) {
  10814. // Content is a DOM node or a jQuery
  10815. if (html) {
  10816. if (!$$$1(content).parent().is($element)) {
  10817. $element.empty().append(content);
  10818. }
  10819. } else {
  10820. $element.text($$$1(content).text());
  10821. }
  10822. } else {
  10823. $element[html ? 'html' : 'text'](content);
  10824. }
  10825. };
  10826. _proto.getTitle = function getTitle() {
  10827. var title = this.element.getAttribute('data-original-title');
  10828. if (!title) {
  10829. title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
  10830. }
  10831. return title;
  10832. }; // Private
  10833. _proto._getAttachment = function _getAttachment(placement) {
  10834. return AttachmentMap[placement.toUpperCase()];
  10835. };
  10836. _proto._setListeners = function _setListeners() {
  10837. var _this3 = this;
  10838. var triggers = this.config.trigger.split(' ');
  10839. triggers.forEach(function (trigger) {
  10840. if (trigger === 'click') {
  10841. $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {
  10842. return _this3.toggle(event);
  10843. });
  10844. } else if (trigger !== Trigger.MANUAL) {
  10845. var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;
  10846. var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;
  10847. $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) {
  10848. return _this3._enter(event);
  10849. }).on(eventOut, _this3.config.selector, function (event) {
  10850. return _this3._leave(event);
  10851. });
  10852. }
  10853. $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () {
  10854. return _this3.hide();
  10855. });
  10856. });
  10857. if (this.config.selector) {
  10858. this.config = _objectSpread({}, this.config, {
  10859. trigger: 'manual',
  10860. selector: ''
  10861. });
  10862. } else {
  10863. this._fixTitle();
  10864. }
  10865. };
  10866. _proto._fixTitle = function _fixTitle() {
  10867. var titleType = typeof this.element.getAttribute('data-original-title');
  10868. if (this.element.getAttribute('title') || titleType !== 'string') {
  10869. this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
  10870. this.element.setAttribute('title', '');
  10871. }
  10872. };
  10873. _proto._enter = function _enter(event, context) {
  10874. var dataKey = this.constructor.DATA_KEY;
  10875. context = context || $$$1(event.currentTarget).data(dataKey);
  10876. if (!context) {
  10877. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10878. $$$1(event.currentTarget).data(dataKey, context);
  10879. }
  10880. if (event) {
  10881. context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
  10882. }
  10883. if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {
  10884. context._hoverState = HoverState.SHOW;
  10885. return;
  10886. }
  10887. clearTimeout(context._timeout);
  10888. context._hoverState = HoverState.SHOW;
  10889. if (!context.config.delay || !context.config.delay.show) {
  10890. context.show();
  10891. return;
  10892. }
  10893. context._timeout = setTimeout(function () {
  10894. if (context._hoverState === HoverState.SHOW) {
  10895. context.show();
  10896. }
  10897. }, context.config.delay.show);
  10898. };
  10899. _proto._leave = function _leave(event, context) {
  10900. var dataKey = this.constructor.DATA_KEY;
  10901. context = context || $$$1(event.currentTarget).data(dataKey);
  10902. if (!context) {
  10903. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10904. $$$1(event.currentTarget).data(dataKey, context);
  10905. }
  10906. if (event) {
  10907. context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
  10908. }
  10909. if (context._isWithActiveTrigger()) {
  10910. return;
  10911. }
  10912. clearTimeout(context._timeout);
  10913. context._hoverState = HoverState.OUT;
  10914. if (!context.config.delay || !context.config.delay.hide) {
  10915. context.hide();
  10916. return;
  10917. }
  10918. context._timeout = setTimeout(function () {
  10919. if (context._hoverState === HoverState.OUT) {
  10920. context.hide();
  10921. }
  10922. }, context.config.delay.hide);
  10923. };
  10924. _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
  10925. for (var trigger in this._activeTrigger) {
  10926. if (this._activeTrigger[trigger]) {
  10927. return true;
  10928. }
  10929. }
  10930. return false;
  10931. };
  10932. _proto._getConfig = function _getConfig(config) {
  10933. config = _objectSpread({}, this.constructor.Default, $$$1(this.element).data(), typeof config === 'object' && config ? config : {});
  10934. if (typeof config.delay === 'number') {
  10935. config.delay = {
  10936. show: config.delay,
  10937. hide: config.delay
  10938. };
  10939. }
  10940. if (typeof config.title === 'number') {
  10941. config.title = config.title.toString();
  10942. }
  10943. if (typeof config.content === 'number') {
  10944. config.content = config.content.toString();
  10945. }
  10946. Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
  10947. return config;
  10948. };
  10949. _proto._getDelegateConfig = function _getDelegateConfig() {
  10950. var config = {};
  10951. if (this.config) {
  10952. for (var key in this.config) {
  10953. if (this.constructor.Default[key] !== this.config[key]) {
  10954. config[key] = this.config[key];
  10955. }
  10956. }
  10957. }
  10958. return config;
  10959. };
  10960. _proto._cleanTipClass = function _cleanTipClass() {
  10961. var $tip = $$$1(this.getTipElement());
  10962. var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
  10963. if (tabClass !== null && tabClass.length) {
  10964. $tip.removeClass(tabClass.join(''));
  10965. }
  10966. };
  10967. _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {
  10968. var popperInstance = popperData.instance;
  10969. this.tip = popperInstance.popper;
  10970. this._cleanTipClass();
  10971. this.addAttachmentClass(this._getAttachment(popperData.placement));
  10972. };
  10973. _proto._fixTransition = function _fixTransition() {
  10974. var tip = this.getTipElement();
  10975. var initConfigAnimation = this.config.animation;
  10976. if (tip.getAttribute('x-placement') !== null) {
  10977. return;
  10978. }
  10979. $$$1(tip).removeClass(ClassName.FADE);
  10980. this.config.animation = false;
  10981. this.hide();
  10982. this.show();
  10983. this.config.animation = initConfigAnimation;
  10984. }; // Static
  10985. Tooltip._jQueryInterface = function _jQueryInterface(config) {
  10986. return this.each(function () {
  10987. var data = $$$1(this).data(DATA_KEY);
  10988. var _config = typeof config === 'object' && config;
  10989. if (!data && /dispose|hide/.test(config)) {
  10990. return;
  10991. }
  10992. if (!data) {
  10993. data = new Tooltip(this, _config);
  10994. $$$1(this).data(DATA_KEY, data);
  10995. }
  10996. if (typeof config === 'string') {
  10997. if (typeof data[config] === 'undefined') {
  10998. throw new TypeError("No method named \"" + config + "\"");
  10999. }
  11000. data[config]();
  11001. }
  11002. });
  11003. };
  11004. _createClass(Tooltip, null, [{
  11005. key: "VERSION",
  11006. get: function get() {
  11007. return VERSION;
  11008. }
  11009. }, {
  11010. key: "Default",
  11011. get: function get() {
  11012. return Default;
  11013. }
  11014. }, {
  11015. key: "NAME",
  11016. get: function get() {
  11017. return NAME;
  11018. }
  11019. }, {
  11020. key: "DATA_KEY",
  11021. get: function get() {
  11022. return DATA_KEY;
  11023. }
  11024. }, {
  11025. key: "Event",
  11026. get: function get() {
  11027. return Event;
  11028. }
  11029. }, {
  11030. key: "EVENT_KEY",
  11031. get: function get() {
  11032. return EVENT_KEY;
  11033. }
  11034. }, {
  11035. key: "DefaultType",
  11036. get: function get() {
  11037. return DefaultType;
  11038. }
  11039. }]);
  11040. return Tooltip;
  11041. }();
  11042. /**
  11043. * ------------------------------------------------------------------------
  11044. * jQuery
  11045. * ------------------------------------------------------------------------
  11046. */
  11047. $$$1.fn[NAME] = Tooltip._jQueryInterface;
  11048. $$$1.fn[NAME].Constructor = Tooltip;
  11049. $$$1.fn[NAME].noConflict = function () {
  11050. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11051. return Tooltip._jQueryInterface;
  11052. };
  11053. return Tooltip;
  11054. }($, Popper);
  11055. /**
  11056. * --------------------------------------------------------------------------
  11057. * Bootstrap (v4.1.3): popover.js
  11058. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11059. * --------------------------------------------------------------------------
  11060. */
  11061. var Popover = function ($$$1) {
  11062. /**
  11063. * ------------------------------------------------------------------------
  11064. * Constants
  11065. * ------------------------------------------------------------------------
  11066. */
  11067. var NAME = 'popover';
  11068. var VERSION = '4.1.3';
  11069. var DATA_KEY = 'bs.popover';
  11070. var EVENT_KEY = "." + DATA_KEY;
  11071. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11072. var CLASS_PREFIX = 'bs-popover';
  11073. var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
  11074. var Default = _objectSpread({}, Tooltip.Default, {
  11075. placement: 'right',
  11076. trigger: 'click',
  11077. content: '',
  11078. template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
  11079. });
  11080. var DefaultType = _objectSpread({}, Tooltip.DefaultType, {
  11081. content: '(string|element|function)'
  11082. });
  11083. var ClassName = {
  11084. FADE: 'fade',
  11085. SHOW: 'show'
  11086. };
  11087. var Selector = {
  11088. TITLE: '.popover-header',
  11089. CONTENT: '.popover-body'
  11090. };
  11091. var Event = {
  11092. HIDE: "hide" + EVENT_KEY,
  11093. HIDDEN: "hidden" + EVENT_KEY,
  11094. SHOW: "show" + EVENT_KEY,
  11095. SHOWN: "shown" + EVENT_KEY,
  11096. INSERTED: "inserted" + EVENT_KEY,
  11097. CLICK: "click" + EVENT_KEY,
  11098. FOCUSIN: "focusin" + EVENT_KEY,
  11099. FOCUSOUT: "focusout" + EVENT_KEY,
  11100. MOUSEENTER: "mouseenter" + EVENT_KEY,
  11101. MOUSELEAVE: "mouseleave" + EVENT_KEY
  11102. /**
  11103. * ------------------------------------------------------------------------
  11104. * Class Definition
  11105. * ------------------------------------------------------------------------
  11106. */
  11107. };
  11108. var Popover =
  11109. /*#__PURE__*/
  11110. function (_Tooltip) {
  11111. _inheritsLoose(Popover, _Tooltip);
  11112. function Popover() {
  11113. return _Tooltip.apply(this, arguments) || this;
  11114. }
  11115. var _proto = Popover.prototype;
  11116. // Overrides
  11117. _proto.isWithContent = function isWithContent() {
  11118. return this.getTitle() || this._getContent();
  11119. };
  11120. _proto.addAttachmentClass = function addAttachmentClass(attachment) {
  11121. $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
  11122. };
  11123. _proto.getTipElement = function getTipElement() {
  11124. this.tip = this.tip || $$$1(this.config.template)[0];
  11125. return this.tip;
  11126. };
  11127. _proto.setContent = function setContent() {
  11128. var $tip = $$$1(this.getTipElement()); // We use append for html objects to maintain js events
  11129. this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
  11130. var content = this._getContent();
  11131. if (typeof content === 'function') {
  11132. content = content.call(this.element);
  11133. }
  11134. this.setElementContent($tip.find(Selector.CONTENT), content);
  11135. $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW);
  11136. }; // Private
  11137. _proto._getContent = function _getContent() {
  11138. return this.element.getAttribute('data-content') || this.config.content;
  11139. };
  11140. _proto._cleanTipClass = function _cleanTipClass() {
  11141. var $tip = $$$1(this.getTipElement());
  11142. var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
  11143. if (tabClass !== null && tabClass.length > 0) {
  11144. $tip.removeClass(tabClass.join(''));
  11145. }
  11146. }; // Static
  11147. Popover._jQueryInterface = function _jQueryInterface(config) {
  11148. return this.each(function () {
  11149. var data = $$$1(this).data(DATA_KEY);
  11150. var _config = typeof config === 'object' ? config : null;
  11151. if (!data && /destroy|hide/.test(config)) {
  11152. return;
  11153. }
  11154. if (!data) {
  11155. data = new Popover(this, _config);
  11156. $$$1(this).data(DATA_KEY, data);
  11157. }
  11158. if (typeof config === 'string') {
  11159. if (typeof data[config] === 'undefined') {
  11160. throw new TypeError("No method named \"" + config + "\"");
  11161. }
  11162. data[config]();
  11163. }
  11164. });
  11165. };
  11166. _createClass(Popover, null, [{
  11167. key: "VERSION",
  11168. // Getters
  11169. get: function get() {
  11170. return VERSION;
  11171. }
  11172. }, {
  11173. key: "Default",
  11174. get: function get() {
  11175. return Default;
  11176. }
  11177. }, {
  11178. key: "NAME",
  11179. get: function get() {
  11180. return NAME;
  11181. }
  11182. }, {
  11183. key: "DATA_KEY",
  11184. get: function get() {
  11185. return DATA_KEY;
  11186. }
  11187. }, {
  11188. key: "Event",
  11189. get: function get() {
  11190. return Event;
  11191. }
  11192. }, {
  11193. key: "EVENT_KEY",
  11194. get: function get() {
  11195. return EVENT_KEY;
  11196. }
  11197. }, {
  11198. key: "DefaultType",
  11199. get: function get() {
  11200. return DefaultType;
  11201. }
  11202. }]);
  11203. return Popover;
  11204. }(Tooltip);
  11205. /**
  11206. * ------------------------------------------------------------------------
  11207. * jQuery
  11208. * ------------------------------------------------------------------------
  11209. */
  11210. $$$1.fn[NAME] = Popover._jQueryInterface;
  11211. $$$1.fn[NAME].Constructor = Popover;
  11212. $$$1.fn[NAME].noConflict = function () {
  11213. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11214. return Popover._jQueryInterface;
  11215. };
  11216. return Popover;
  11217. }($);
  11218. /**
  11219. * --------------------------------------------------------------------------
  11220. * Bootstrap (v4.1.3): scrollspy.js
  11221. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11222. * --------------------------------------------------------------------------
  11223. */
  11224. var ScrollSpy = function ($$$1) {
  11225. /**
  11226. * ------------------------------------------------------------------------
  11227. * Constants
  11228. * ------------------------------------------------------------------------
  11229. */
  11230. var NAME = 'scrollspy';
  11231. var VERSION = '4.1.3';
  11232. var DATA_KEY = 'bs.scrollspy';
  11233. var EVENT_KEY = "." + DATA_KEY;
  11234. var DATA_API_KEY = '.data-api';
  11235. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11236. var Default = {
  11237. offset: 10,
  11238. method: 'auto',
  11239. target: ''
  11240. };
  11241. var DefaultType = {
  11242. offset: 'number',
  11243. method: 'string',
  11244. target: '(string|element)'
  11245. };
  11246. var Event = {
  11247. ACTIVATE: "activate" + EVENT_KEY,
  11248. SCROLL: "scroll" + EVENT_KEY,
  11249. LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
  11250. };
  11251. var ClassName = {
  11252. DROPDOWN_ITEM: 'dropdown-item',
  11253. DROPDOWN_MENU: 'dropdown-menu',
  11254. ACTIVE: 'active'
  11255. };
  11256. var Selector = {
  11257. DATA_SPY: '[data-spy="scroll"]',
  11258. ACTIVE: '.active',
  11259. NAV_LIST_GROUP: '.nav, .list-group',
  11260. NAV_LINKS: '.nav-link',
  11261. NAV_ITEMS: '.nav-item',
  11262. LIST_ITEMS: '.list-group-item',
  11263. DROPDOWN: '.dropdown',
  11264. DROPDOWN_ITEMS: '.dropdown-item',
  11265. DROPDOWN_TOGGLE: '.dropdown-toggle'
  11266. };
  11267. var OffsetMethod = {
  11268. OFFSET: 'offset',
  11269. POSITION: 'position'
  11270. /**
  11271. * ------------------------------------------------------------------------
  11272. * Class Definition
  11273. * ------------------------------------------------------------------------
  11274. */
  11275. };
  11276. var ScrollSpy =
  11277. /*#__PURE__*/
  11278. function () {
  11279. function ScrollSpy(element, config) {
  11280. var _this = this;
  11281. this._element = element;
  11282. this._scrollElement = element.tagName === 'BODY' ? window : element;
  11283. this._config = this._getConfig(config);
  11284. this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
  11285. this._offsets = [];
  11286. this._targets = [];
  11287. this._activeTarget = null;
  11288. this._scrollHeight = 0;
  11289. $$$1(this._scrollElement).on(Event.SCROLL, function (event) {
  11290. return _this._process(event);
  11291. });
  11292. this.refresh();
  11293. this._process();
  11294. } // Getters
  11295. var _proto = ScrollSpy.prototype;
  11296. // Public
  11297. _proto.refresh = function refresh() {
  11298. var _this2 = this;
  11299. var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;
  11300. var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
  11301. var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
  11302. this._offsets = [];
  11303. this._targets = [];
  11304. this._scrollHeight = this._getScrollHeight();
  11305. var targets = [].slice.call(document.querySelectorAll(this._selector));
  11306. targets.map(function (element) {
  11307. var target;
  11308. var targetSelector = Util.getSelectorFromElement(element);
  11309. if (targetSelector) {
  11310. target = document.querySelector(targetSelector);
  11311. }
  11312. if (target) {
  11313. var targetBCR = target.getBoundingClientRect();
  11314. if (targetBCR.width || targetBCR.height) {
  11315. // TODO (fat): remove sketch reliance on jQuery position/offset
  11316. return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector];
  11317. }
  11318. }
  11319. return null;
  11320. }).filter(function (item) {
  11321. return item;
  11322. }).sort(function (a, b) {
  11323. return a[0] - b[0];
  11324. }).forEach(function (item) {
  11325. _this2._offsets.push(item[0]);
  11326. _this2._targets.push(item[1]);
  11327. });
  11328. };
  11329. _proto.dispose = function dispose() {
  11330. $$$1.removeData(this._element, DATA_KEY);
  11331. $$$1(this._scrollElement).off(EVENT_KEY);
  11332. this._element = null;
  11333. this._scrollElement = null;
  11334. this._config = null;
  11335. this._selector = null;
  11336. this._offsets = null;
  11337. this._targets = null;
  11338. this._activeTarget = null;
  11339. this._scrollHeight = null;
  11340. }; // Private
  11341. _proto._getConfig = function _getConfig(config) {
  11342. config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});
  11343. if (typeof config.target !== 'string') {
  11344. var id = $$$1(config.target).attr('id');
  11345. if (!id) {
  11346. id = Util.getUID(NAME);
  11347. $$$1(config.target).attr('id', id);
  11348. }
  11349. config.target = "#" + id;
  11350. }
  11351. Util.typeCheckConfig(NAME, config, DefaultType);
  11352. return config;
  11353. };
  11354. _proto._getScrollTop = function _getScrollTop() {
  11355. return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
  11356. };
  11357. _proto._getScrollHeight = function _getScrollHeight() {
  11358. return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
  11359. };
  11360. _proto._getOffsetHeight = function _getOffsetHeight() {
  11361. return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
  11362. };
  11363. _proto._process = function _process() {
  11364. var scrollTop = this._getScrollTop() + this._config.offset;
  11365. var scrollHeight = this._getScrollHeight();
  11366. var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
  11367. if (this._scrollHeight !== scrollHeight) {
  11368. this.refresh();
  11369. }
  11370. if (scrollTop >= maxScroll) {
  11371. var target = this._targets[this._targets.length - 1];
  11372. if (this._activeTarget !== target) {
  11373. this._activate(target);
  11374. }
  11375. return;
  11376. }
  11377. if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
  11378. this._activeTarget = null;
  11379. this._clear();
  11380. return;
  11381. }
  11382. var offsetLength = this._offsets.length;
  11383. for (var i = offsetLength; i--;) {
  11384. var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
  11385. if (isActiveTarget) {
  11386. this._activate(this._targets[i]);
  11387. }
  11388. }
  11389. };
  11390. _proto._activate = function _activate(target) {
  11391. this._activeTarget = target;
  11392. this._clear();
  11393. var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style
  11394. queries = queries.map(function (selector) {
  11395. return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]");
  11396. });
  11397. var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(','))));
  11398. if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
  11399. $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
  11400. $link.addClass(ClassName.ACTIVE);
  11401. } else {
  11402. // Set triggered link as active
  11403. $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
  11404. // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
  11405. $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item
  11406. $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
  11407. }
  11408. $$$1(this._scrollElement).trigger(Event.ACTIVATE, {
  11409. relatedTarget: target
  11410. });
  11411. };
  11412. _proto._clear = function _clear() {
  11413. var nodes = [].slice.call(document.querySelectorAll(this._selector));
  11414. $$$1(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
  11415. }; // Static
  11416. ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
  11417. return this.each(function () {
  11418. var data = $$$1(this).data(DATA_KEY);
  11419. var _config = typeof config === 'object' && config;
  11420. if (!data) {
  11421. data = new ScrollSpy(this, _config);
  11422. $$$1(this).data(DATA_KEY, data);
  11423. }
  11424. if (typeof config === 'string') {
  11425. if (typeof data[config] === 'undefined') {
  11426. throw new TypeError("No method named \"" + config + "\"");
  11427. }
  11428. data[config]();
  11429. }
  11430. });
  11431. };
  11432. _createClass(ScrollSpy, null, [{
  11433. key: "VERSION",
  11434. get: function get() {
  11435. return VERSION;
  11436. }
  11437. }, {
  11438. key: "Default",
  11439. get: function get() {
  11440. return Default;
  11441. }
  11442. }]);
  11443. return ScrollSpy;
  11444. }();
  11445. /**
  11446. * ------------------------------------------------------------------------
  11447. * Data Api implementation
  11448. * ------------------------------------------------------------------------
  11449. */
  11450. $$$1(window).on(Event.LOAD_DATA_API, function () {
  11451. var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));
  11452. var scrollSpysLength = scrollSpys.length;
  11453. for (var i = scrollSpysLength; i--;) {
  11454. var $spy = $$$1(scrollSpys[i]);
  11455. ScrollSpy._jQueryInterface.call($spy, $spy.data());
  11456. }
  11457. });
  11458. /**
  11459. * ------------------------------------------------------------------------
  11460. * jQuery
  11461. * ------------------------------------------------------------------------
  11462. */
  11463. $$$1.fn[NAME] = ScrollSpy._jQueryInterface;
  11464. $$$1.fn[NAME].Constructor = ScrollSpy;
  11465. $$$1.fn[NAME].noConflict = function () {
  11466. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11467. return ScrollSpy._jQueryInterface;
  11468. };
  11469. return ScrollSpy;
  11470. }($);
  11471. /**
  11472. * --------------------------------------------------------------------------
  11473. * Bootstrap (v4.1.3): tab.js
  11474. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11475. * --------------------------------------------------------------------------
  11476. */
  11477. var Tab = function ($$$1) {
  11478. /**
  11479. * ------------------------------------------------------------------------
  11480. * Constants
  11481. * ------------------------------------------------------------------------
  11482. */
  11483. var NAME = 'tab';
  11484. var VERSION = '4.1.3';
  11485. var DATA_KEY = 'bs.tab';
  11486. var EVENT_KEY = "." + DATA_KEY;
  11487. var DATA_API_KEY = '.data-api';
  11488. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11489. var Event = {
  11490. HIDE: "hide" + EVENT_KEY,
  11491. HIDDEN: "hidden" + EVENT_KEY,
  11492. SHOW: "show" + EVENT_KEY,
  11493. SHOWN: "shown" + EVENT_KEY,
  11494. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  11495. };
  11496. var ClassName = {
  11497. DROPDOWN_MENU: 'dropdown-menu',
  11498. ACTIVE: 'active',
  11499. DISABLED: 'disabled',
  11500. FADE: 'fade',
  11501. SHOW: 'show'
  11502. };
  11503. var Selector = {
  11504. DROPDOWN: '.dropdown',
  11505. NAV_LIST_GROUP: '.nav, .list-group',
  11506. ACTIVE: '.active',
  11507. ACTIVE_UL: '> li > .active',
  11508. DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
  11509. DROPDOWN_TOGGLE: '.dropdown-toggle',
  11510. DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
  11511. /**
  11512. * ------------------------------------------------------------------------
  11513. * Class Definition
  11514. * ------------------------------------------------------------------------
  11515. */
  11516. };
  11517. var Tab =
  11518. /*#__PURE__*/
  11519. function () {
  11520. function Tab(element) {
  11521. this._element = element;
  11522. } // Getters
  11523. var _proto = Tab.prototype;
  11524. // Public
  11525. _proto.show = function show() {
  11526. var _this = this;
  11527. if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $$$1(this._element).hasClass(ClassName.ACTIVE) || $$$1(this._element).hasClass(ClassName.DISABLED)) {
  11528. return;
  11529. }
  11530. var target;
  11531. var previous;
  11532. var listElement = $$$1(this._element).closest(Selector.NAV_LIST_GROUP)[0];
  11533. var selector = Util.getSelectorFromElement(this._element);
  11534. if (listElement) {
  11535. var itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE;
  11536. previous = $$$1.makeArray($$$1(listElement).find(itemSelector));
  11537. previous = previous[previous.length - 1];
  11538. }
  11539. var hideEvent = $$$1.Event(Event.HIDE, {
  11540. relatedTarget: this._element
  11541. });
  11542. var showEvent = $$$1.Event(Event.SHOW, {
  11543. relatedTarget: previous
  11544. });
  11545. if (previous) {
  11546. $$$1(previous).trigger(hideEvent);
  11547. }
  11548. $$$1(this._element).trigger(showEvent);
  11549. if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
  11550. return;
  11551. }
  11552. if (selector) {
  11553. target = document.querySelector(selector);
  11554. }
  11555. this._activate(this._element, listElement);
  11556. var complete = function complete() {
  11557. var hiddenEvent = $$$1.Event(Event.HIDDEN, {
  11558. relatedTarget: _this._element
  11559. });
  11560. var shownEvent = $$$1.Event(Event.SHOWN, {
  11561. relatedTarget: previous
  11562. });
  11563. $$$1(previous).trigger(hiddenEvent);
  11564. $$$1(_this._element).trigger(shownEvent);
  11565. };
  11566. if (target) {
  11567. this._activate(target, target.parentNode, complete);
  11568. } else {
  11569. complete();
  11570. }
  11571. };
  11572. _proto.dispose = function dispose() {
  11573. $$$1.removeData(this._element, DATA_KEY);
  11574. this._element = null;
  11575. }; // Private
  11576. _proto._activate = function _activate(element, container, callback) {
  11577. var _this2 = this;
  11578. var activeElements;
  11579. if (container.nodeName === 'UL') {
  11580. activeElements = $$$1(container).find(Selector.ACTIVE_UL);
  11581. } else {
  11582. activeElements = $$$1(container).children(Selector.ACTIVE);
  11583. }
  11584. var active = activeElements[0];
  11585. var isTransitioning = callback && active && $$$1(active).hasClass(ClassName.FADE);
  11586. var complete = function complete() {
  11587. return _this2._transitionComplete(element, active, callback);
  11588. };
  11589. if (active && isTransitioning) {
  11590. var transitionDuration = Util.getTransitionDurationFromElement(active);
  11591. $$$1(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  11592. } else {
  11593. complete();
  11594. }
  11595. };
  11596. _proto._transitionComplete = function _transitionComplete(element, active, callback) {
  11597. if (active) {
  11598. $$$1(active).removeClass(ClassName.SHOW + " " + ClassName.ACTIVE);
  11599. var dropdownChild = $$$1(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
  11600. if (dropdownChild) {
  11601. $$$1(dropdownChild).removeClass(ClassName.ACTIVE);
  11602. }
  11603. if (active.getAttribute('role') === 'tab') {
  11604. active.setAttribute('aria-selected', false);
  11605. }
  11606. }
  11607. $$$1(element).addClass(ClassName.ACTIVE);
  11608. if (element.getAttribute('role') === 'tab') {
  11609. element.setAttribute('aria-selected', true);
  11610. }
  11611. Util.reflow(element);
  11612. $$$1(element).addClass(ClassName.SHOW);
  11613. if (element.parentNode && $$$1(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
  11614. var dropdownElement = $$$1(element).closest(Selector.DROPDOWN)[0];
  11615. if (dropdownElement) {
  11616. var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE));
  11617. $$$1(dropdownToggleList).addClass(ClassName.ACTIVE);
  11618. }
  11619. element.setAttribute('aria-expanded', true);
  11620. }
  11621. if (callback) {
  11622. callback();
  11623. }
  11624. }; // Static
  11625. Tab._jQueryInterface = function _jQueryInterface(config) {
  11626. return this.each(function () {
  11627. var $this = $$$1(this);
  11628. var data = $this.data(DATA_KEY);
  11629. if (!data) {
  11630. data = new Tab(this);
  11631. $this.data(DATA_KEY, data);
  11632. }
  11633. if (typeof config === 'string') {
  11634. if (typeof data[config] === 'undefined') {
  11635. throw new TypeError("No method named \"" + config + "\"");
  11636. }
  11637. data[config]();
  11638. }
  11639. });
  11640. };
  11641. _createClass(Tab, null, [{
  11642. key: "VERSION",
  11643. get: function get() {
  11644. return VERSION;
  11645. }
  11646. }]);
  11647. return Tab;
  11648. }();
  11649. /**
  11650. * ------------------------------------------------------------------------
  11651. * Data Api implementation
  11652. * ------------------------------------------------------------------------
  11653. */
  11654. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  11655. event.preventDefault();
  11656. Tab._jQueryInterface.call($$$1(this), 'show');
  11657. });
  11658. /**
  11659. * ------------------------------------------------------------------------
  11660. * jQuery
  11661. * ------------------------------------------------------------------------
  11662. */
  11663. $$$1.fn[NAME] = Tab._jQueryInterface;
  11664. $$$1.fn[NAME].Constructor = Tab;
  11665. $$$1.fn[NAME].noConflict = function () {
  11666. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11667. return Tab._jQueryInterface;
  11668. };
  11669. return Tab;
  11670. }($);
  11671. /**
  11672. * --------------------------------------------------------------------------
  11673. * Bootstrap (v4.1.3): index.js
  11674. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11675. * --------------------------------------------------------------------------
  11676. */
  11677. (function ($$$1) {
  11678. if (typeof $$$1 === 'undefined') {
  11679. throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.');
  11680. }
  11681. var version = $$$1.fn.jquery.split(' ')[0].split('.');
  11682. var minMajor = 1;
  11683. var ltMajor = 2;
  11684. var minMinor = 9;
  11685. var minPatch = 1;
  11686. var maxMajor = 4;
  11687. if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
  11688. throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');
  11689. }
  11690. })($);
  11691. exports.Util = Util;
  11692. exports.Alert = Alert;
  11693. exports.Button = Button;
  11694. exports.Carousel = Carousel;
  11695. exports.Collapse = Collapse;
  11696. exports.Dropdown = Dropdown;
  11697. exports.Modal = Modal;
  11698. exports.Popover = Popover;
  11699. exports.Scrollspy = ScrollSpy;
  11700. exports.Tab = Tab;
  11701. exports.Tooltip = Tooltip;
  11702. Object.defineProperty(exports, '__esModule', { value: true });
  11703. })));
  11704. //# sourceMappingURL=bootstrap.js.map
  11705. /***/ }),
  11706. /* 3 */
  11707. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  11708. "use strict";
  11709. Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
  11710. /* WEBPACK VAR INJECTION */(function(global) {/**!
  11711. * @fileOverview Kickass library to create and place poppers near their reference elements.
  11712. * @version 1.14.4
  11713. * @license
  11714. * Copyright (c) 2016 Federico Zivolo and contributors
  11715. *
  11716. * Permission is hereby granted, free of charge, to any person obtaining a copy
  11717. * of this software and associated documentation files (the "Software"), to deal
  11718. * in the Software without restriction, including without limitation the rights
  11719. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11720. * copies of the Software, and to permit persons to whom the Software is
  11721. * furnished to do so, subject to the following conditions:
  11722. *
  11723. * The above copyright notice and this permission notice shall be included in all
  11724. * copies or substantial portions of the Software.
  11725. *
  11726. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11727. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11728. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11729. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11730. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  11731. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  11732. * SOFTWARE.
  11733. */
  11734. var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
  11735. var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
  11736. var timeoutDuration = 0;
  11737. for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
  11738. if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
  11739. timeoutDuration = 1;
  11740. break;
  11741. }
  11742. }
  11743. function microtaskDebounce(fn) {
  11744. var called = false;
  11745. return function () {
  11746. if (called) {
  11747. return;
  11748. }
  11749. called = true;
  11750. window.Promise.resolve().then(function () {
  11751. called = false;
  11752. fn();
  11753. });
  11754. };
  11755. }
  11756. function taskDebounce(fn) {
  11757. var scheduled = false;
  11758. return function () {
  11759. if (!scheduled) {
  11760. scheduled = true;
  11761. setTimeout(function () {
  11762. scheduled = false;
  11763. fn();
  11764. }, timeoutDuration);
  11765. }
  11766. };
  11767. }
  11768. var supportsMicroTasks = isBrowser && window.Promise;
  11769. /**
  11770. * Create a debounced version of a method, that's asynchronously deferred
  11771. * but called in the minimum time possible.
  11772. *
  11773. * @method
  11774. * @memberof Popper.Utils
  11775. * @argument {Function} fn
  11776. * @returns {Function}
  11777. */
  11778. var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
  11779. /**
  11780. * Check if the given variable is a function
  11781. * @method
  11782. * @memberof Popper.Utils
  11783. * @argument {Any} functionToCheck - variable to check
  11784. * @returns {Boolean} answer to: is a function?
  11785. */
  11786. function isFunction(functionToCheck) {
  11787. var getType = {};
  11788. return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
  11789. }
  11790. /**
  11791. * Get CSS computed property of the given element
  11792. * @method
  11793. * @memberof Popper.Utils
  11794. * @argument {Eement} element
  11795. * @argument {String} property
  11796. */
  11797. function getStyleComputedProperty(element, property) {
  11798. if (element.nodeType !== 1) {
  11799. return [];
  11800. }
  11801. // NOTE: 1 DOM access here
  11802. var css = getComputedStyle(element, null);
  11803. return property ? css[property] : css;
  11804. }
  11805. /**
  11806. * Returns the parentNode or the host of the element
  11807. * @method
  11808. * @memberof Popper.Utils
  11809. * @argument {Element} element
  11810. * @returns {Element} parent
  11811. */
  11812. function getParentNode(element) {
  11813. if (element.nodeName === 'HTML') {
  11814. return element;
  11815. }
  11816. return element.parentNode || element.host;
  11817. }
  11818. /**
  11819. * Returns the scrolling parent of the given element
  11820. * @method
  11821. * @memberof Popper.Utils
  11822. * @argument {Element} element
  11823. * @returns {Element} scroll parent
  11824. */
  11825. function getScrollParent(element) {
  11826. // Return body, `getScroll` will take care to get the correct `scrollTop` from it
  11827. if (!element) {
  11828. return document.body;
  11829. }
  11830. switch (element.nodeName) {
  11831. case 'HTML':
  11832. case 'BODY':
  11833. return element.ownerDocument.body;
  11834. case '#document':
  11835. return element.body;
  11836. }
  11837. // Firefox want us to check `-x` and `-y` variations as well
  11838. var _getStyleComputedProp = getStyleComputedProperty(element),
  11839. overflow = _getStyleComputedProp.overflow,
  11840. overflowX = _getStyleComputedProp.overflowX,
  11841. overflowY = _getStyleComputedProp.overflowY;
  11842. if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
  11843. return element;
  11844. }
  11845. return getScrollParent(getParentNode(element));
  11846. }
  11847. var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
  11848. var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
  11849. /**
  11850. * Determines if the browser is Internet Explorer
  11851. * @method
  11852. * @memberof Popper.Utils
  11853. * @param {Number} version to check
  11854. * @returns {Boolean} isIE
  11855. */
  11856. function isIE(version) {
  11857. if (version === 11) {
  11858. return isIE11;
  11859. }
  11860. if (version === 10) {
  11861. return isIE10;
  11862. }
  11863. return isIE11 || isIE10;
  11864. }
  11865. /**
  11866. * Returns the offset parent of the given element
  11867. * @method
  11868. * @memberof Popper.Utils
  11869. * @argument {Element} element
  11870. * @returns {Element} offset parent
  11871. */
  11872. function getOffsetParent(element) {
  11873. if (!element) {
  11874. return document.documentElement;
  11875. }
  11876. var noOffsetParent = isIE(10) ? document.body : null;
  11877. // NOTE: 1 DOM access here
  11878. var offsetParent = element.offsetParent;
  11879. // Skip hidden elements which don't have an offsetParent
  11880. while (offsetParent === noOffsetParent && element.nextElementSibling) {
  11881. offsetParent = (element = element.nextElementSibling).offsetParent;
  11882. }
  11883. var nodeName = offsetParent && offsetParent.nodeName;
  11884. if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
  11885. return element ? element.ownerDocument.documentElement : document.documentElement;
  11886. }
  11887. // .offsetParent will return the closest TD or TABLE in case
  11888. // no offsetParent is present, I hate this job...
  11889. if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
  11890. return getOffsetParent(offsetParent);
  11891. }
  11892. return offsetParent;
  11893. }
  11894. function isOffsetContainer(element) {
  11895. var nodeName = element.nodeName;
  11896. if (nodeName === 'BODY') {
  11897. return false;
  11898. }
  11899. return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
  11900. }
  11901. /**
  11902. * Finds the root node (document, shadowDOM root) of the given element
  11903. * @method
  11904. * @memberof Popper.Utils
  11905. * @argument {Element} node
  11906. * @returns {Element} root node
  11907. */
  11908. function getRoot(node) {
  11909. if (node.parentNode !== null) {
  11910. return getRoot(node.parentNode);
  11911. }
  11912. return node;
  11913. }
  11914. /**
  11915. * Finds the offset parent common to the two provided nodes
  11916. * @method
  11917. * @memberof Popper.Utils
  11918. * @argument {Element} element1
  11919. * @argument {Element} element2
  11920. * @returns {Element} common offset parent
  11921. */
  11922. function findCommonOffsetParent(element1, element2) {
  11923. // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  11924. if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
  11925. return document.documentElement;
  11926. }
  11927. // Here we make sure to give as "start" the element that comes first in the DOM
  11928. var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
  11929. var start = order ? element1 : element2;
  11930. var end = order ? element2 : element1;
  11931. // Get common ancestor container
  11932. var range = document.createRange();
  11933. range.setStart(start, 0);
  11934. range.setEnd(end, 0);
  11935. var commonAncestorContainer = range.commonAncestorContainer;
  11936. // Both nodes are inside #document
  11937. if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
  11938. if (isOffsetContainer(commonAncestorContainer)) {
  11939. return commonAncestorContainer;
  11940. }
  11941. return getOffsetParent(commonAncestorContainer);
  11942. }
  11943. // one of the nodes is inside shadowDOM, find which one
  11944. var element1root = getRoot(element1);
  11945. if (element1root.host) {
  11946. return findCommonOffsetParent(element1root.host, element2);
  11947. } else {
  11948. return findCommonOffsetParent(element1, getRoot(element2).host);
  11949. }
  11950. }
  11951. /**
  11952. * Gets the scroll value of the given element in the given side (top and left)
  11953. * @method
  11954. * @memberof Popper.Utils
  11955. * @argument {Element} element
  11956. * @argument {String} side `top` or `left`
  11957. * @returns {number} amount of scrolled pixels
  11958. */
  11959. function getScroll(element) {
  11960. var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
  11961. var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
  11962. var nodeName = element.nodeName;
  11963. if (nodeName === 'BODY' || nodeName === 'HTML') {
  11964. var html = element.ownerDocument.documentElement;
  11965. var scrollingElement = element.ownerDocument.scrollingElement || html;
  11966. return scrollingElement[upperSide];
  11967. }
  11968. return element[upperSide];
  11969. }
  11970. /*
  11971. * Sum or subtract the element scroll values (left and top) from a given rect object
  11972. * @method
  11973. * @memberof Popper.Utils
  11974. * @param {Object} rect - Rect object you want to change
  11975. * @param {HTMLElement} element - The element from the function reads the scroll values
  11976. * @param {Boolean} subtract - set to true if you want to subtract the scroll values
  11977. * @return {Object} rect - The modifier rect object
  11978. */
  11979. function includeScroll(rect, element) {
  11980. var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  11981. var scrollTop = getScroll(element, 'top');
  11982. var scrollLeft = getScroll(element, 'left');
  11983. var modifier = subtract ? -1 : 1;
  11984. rect.top += scrollTop * modifier;
  11985. rect.bottom += scrollTop * modifier;
  11986. rect.left += scrollLeft * modifier;
  11987. rect.right += scrollLeft * modifier;
  11988. return rect;
  11989. }
  11990. /*
  11991. * Helper to detect borders of a given element
  11992. * @method
  11993. * @memberof Popper.Utils
  11994. * @param {CSSStyleDeclaration} styles
  11995. * Result of `getStyleComputedProperty` on the given element
  11996. * @param {String} axis - `x` or `y`
  11997. * @return {number} borders - The borders size of the given axis
  11998. */
  11999. function getBordersSize(styles, axis) {
  12000. var sideA = axis === 'x' ? 'Left' : 'Top';
  12001. var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
  12002. return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
  12003. }
  12004. function getSize(axis, body, html, computedStyle) {
  12005. return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
  12006. }
  12007. function getWindowSizes(document) {
  12008. var body = document.body;
  12009. var html = document.documentElement;
  12010. var computedStyle = isIE(10) && getComputedStyle(html);
  12011. return {
  12012. height: getSize('Height', body, html, computedStyle),
  12013. width: getSize('Width', body, html, computedStyle)
  12014. };
  12015. }
  12016. var classCallCheck = function (instance, Constructor) {
  12017. if (!(instance instanceof Constructor)) {
  12018. throw new TypeError("Cannot call a class as a function");
  12019. }
  12020. };
  12021. var createClass = function () {
  12022. function defineProperties(target, props) {
  12023. for (var i = 0; i < props.length; i++) {
  12024. var descriptor = props[i];
  12025. descriptor.enumerable = descriptor.enumerable || false;
  12026. descriptor.configurable = true;
  12027. if ("value" in descriptor) descriptor.writable = true;
  12028. Object.defineProperty(target, descriptor.key, descriptor);
  12029. }
  12030. }
  12031. return function (Constructor, protoProps, staticProps) {
  12032. if (protoProps) defineProperties(Constructor.prototype, protoProps);
  12033. if (staticProps) defineProperties(Constructor, staticProps);
  12034. return Constructor;
  12035. };
  12036. }();
  12037. var defineProperty = function (obj, key, value) {
  12038. if (key in obj) {
  12039. Object.defineProperty(obj, key, {
  12040. value: value,
  12041. enumerable: true,
  12042. configurable: true,
  12043. writable: true
  12044. });
  12045. } else {
  12046. obj[key] = value;
  12047. }
  12048. return obj;
  12049. };
  12050. var _extends = Object.assign || function (target) {
  12051. for (var i = 1; i < arguments.length; i++) {
  12052. var source = arguments[i];
  12053. for (var key in source) {
  12054. if (Object.prototype.hasOwnProperty.call(source, key)) {
  12055. target[key] = source[key];
  12056. }
  12057. }
  12058. }
  12059. return target;
  12060. };
  12061. /**
  12062. * Given element offsets, generate an output similar to getBoundingClientRect
  12063. * @method
  12064. * @memberof Popper.Utils
  12065. * @argument {Object} offsets
  12066. * @returns {Object} ClientRect like output
  12067. */
  12068. function getClientRect(offsets) {
  12069. return _extends({}, offsets, {
  12070. right: offsets.left + offsets.width,
  12071. bottom: offsets.top + offsets.height
  12072. });
  12073. }
  12074. /**
  12075. * Get bounding client rect of given element
  12076. * @method
  12077. * @memberof Popper.Utils
  12078. * @param {HTMLElement} element
  12079. * @return {Object} client rect
  12080. */
  12081. function getBoundingClientRect(element) {
  12082. var rect = {};
  12083. // IE10 10 FIX: Please, don't ask, the element isn't
  12084. // considered in DOM in some circumstances...
  12085. // This isn't reproducible in IE10 compatibility mode of IE11
  12086. try {
  12087. if (isIE(10)) {
  12088. rect = element.getBoundingClientRect();
  12089. var scrollTop = getScroll(element, 'top');
  12090. var scrollLeft = getScroll(element, 'left');
  12091. rect.top += scrollTop;
  12092. rect.left += scrollLeft;
  12093. rect.bottom += scrollTop;
  12094. rect.right += scrollLeft;
  12095. } else {
  12096. rect = element.getBoundingClientRect();
  12097. }
  12098. } catch (e) {}
  12099. var result = {
  12100. left: rect.left,
  12101. top: rect.top,
  12102. width: rect.right - rect.left,
  12103. height: rect.bottom - rect.top
  12104. };
  12105. // subtract scrollbar size from sizes
  12106. var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
  12107. var width = sizes.width || element.clientWidth || result.right - result.left;
  12108. var height = sizes.height || element.clientHeight || result.bottom - result.top;
  12109. var horizScrollbar = element.offsetWidth - width;
  12110. var vertScrollbar = element.offsetHeight - height;
  12111. // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
  12112. // we make this check conditional for performance reasons
  12113. if (horizScrollbar || vertScrollbar) {
  12114. var styles = getStyleComputedProperty(element);
  12115. horizScrollbar -= getBordersSize(styles, 'x');
  12116. vertScrollbar -= getBordersSize(styles, 'y');
  12117. result.width -= horizScrollbar;
  12118. result.height -= vertScrollbar;
  12119. }
  12120. return getClientRect(result);
  12121. }
  12122. function getOffsetRectRelativeToArbitraryNode(children, parent) {
  12123. var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  12124. var isIE10 = isIE(10);
  12125. var isHTML = parent.nodeName === 'HTML';
  12126. var childrenRect = getBoundingClientRect(children);
  12127. var parentRect = getBoundingClientRect(parent);
  12128. var scrollParent = getScrollParent(children);
  12129. var styles = getStyleComputedProperty(parent);
  12130. var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
  12131. var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
  12132. // In cases where the parent is fixed, we must ignore negative scroll in offset calc
  12133. if (fixedPosition && isHTML) {
  12134. parentRect.top = Math.max(parentRect.top, 0);
  12135. parentRect.left = Math.max(parentRect.left, 0);
  12136. }
  12137. var offsets = getClientRect({
  12138. top: childrenRect.top - parentRect.top - borderTopWidth,
  12139. left: childrenRect.left - parentRect.left - borderLeftWidth,
  12140. width: childrenRect.width,
  12141. height: childrenRect.height
  12142. });
  12143. offsets.marginTop = 0;
  12144. offsets.marginLeft = 0;
  12145. // Subtract margins of documentElement in case it's being used as parent
  12146. // we do this only on HTML because it's the only element that behaves
  12147. // differently when margins are applied to it. The margins are included in
  12148. // the box of the documentElement, in the other cases not.
  12149. if (!isIE10 && isHTML) {
  12150. var marginTop = parseFloat(styles.marginTop, 10);
  12151. var marginLeft = parseFloat(styles.marginLeft, 10);
  12152. offsets.top -= borderTopWidth - marginTop;
  12153. offsets.bottom -= borderTopWidth - marginTop;
  12154. offsets.left -= borderLeftWidth - marginLeft;
  12155. offsets.right -= borderLeftWidth - marginLeft;
  12156. // Attach marginTop and marginLeft because in some circumstances we may need them
  12157. offsets.marginTop = marginTop;
  12158. offsets.marginLeft = marginLeft;
  12159. }
  12160. if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
  12161. offsets = includeScroll(offsets, parent);
  12162. }
  12163. return offsets;
  12164. }
  12165. function getViewportOffsetRectRelativeToArtbitraryNode(element) {
  12166. var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  12167. var html = element.ownerDocument.documentElement;
  12168. var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
  12169. var width = Math.max(html.clientWidth, window.innerWidth || 0);
  12170. var height = Math.max(html.clientHeight, window.innerHeight || 0);
  12171. var scrollTop = !excludeScroll ? getScroll(html) : 0;
  12172. var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
  12173. var offset = {
  12174. top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
  12175. left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
  12176. width: width,
  12177. height: height
  12178. };
  12179. return getClientRect(offset);
  12180. }
  12181. /**
  12182. * Check if the given element is fixed or is inside a fixed parent
  12183. * @method
  12184. * @memberof Popper.Utils
  12185. * @argument {Element} element
  12186. * @argument {Element} customContainer
  12187. * @returns {Boolean} answer to "isFixed?"
  12188. */
  12189. function isFixed(element) {
  12190. var nodeName = element.nodeName;
  12191. if (nodeName === 'BODY' || nodeName === 'HTML') {
  12192. return false;
  12193. }
  12194. if (getStyleComputedProperty(element, 'position') === 'fixed') {
  12195. return true;
  12196. }
  12197. return isFixed(getParentNode(element));
  12198. }
  12199. /**
  12200. * Finds the first parent of an element that has a transformed property defined
  12201. * @method
  12202. * @memberof Popper.Utils
  12203. * @argument {Element} element
  12204. * @returns {Element} first transformed parent or documentElement
  12205. */
  12206. function getFixedPositionOffsetParent(element) {
  12207. // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  12208. if (!element || !element.parentElement || isIE()) {
  12209. return document.documentElement;
  12210. }
  12211. var el = element.parentElement;
  12212. while (el && getStyleComputedProperty(el, 'transform') === 'none') {
  12213. el = el.parentElement;
  12214. }
  12215. return el || document.documentElement;
  12216. }
  12217. /**
  12218. * Computed the boundaries limits and return them
  12219. * @method
  12220. * @memberof Popper.Utils
  12221. * @param {HTMLElement} popper
  12222. * @param {HTMLElement} reference
  12223. * @param {number} padding
  12224. * @param {HTMLElement} boundariesElement - Element used to define the boundaries
  12225. * @param {Boolean} fixedPosition - Is in fixed position mode
  12226. * @returns {Object} Coordinates of the boundaries
  12227. */
  12228. function getBoundaries(popper, reference, padding, boundariesElement) {
  12229. var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
  12230. // NOTE: 1 DOM access here
  12231. var boundaries = { top: 0, left: 0 };
  12232. var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
  12233. // Handle viewport case
  12234. if (boundariesElement === 'viewport') {
  12235. boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
  12236. } else {
  12237. // Handle other cases based on DOM element used as boundaries
  12238. var boundariesNode = void 0;
  12239. if (boundariesElement === 'scrollParent') {
  12240. boundariesNode = getScrollParent(getParentNode(reference));
  12241. if (boundariesNode.nodeName === 'BODY') {
  12242. boundariesNode = popper.ownerDocument.documentElement;
  12243. }
  12244. } else if (boundariesElement === 'window') {
  12245. boundariesNode = popper.ownerDocument.documentElement;
  12246. } else {
  12247. boundariesNode = boundariesElement;
  12248. }
  12249. var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
  12250. // In case of HTML, we need a different computation
  12251. if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
  12252. var _getWindowSizes = getWindowSizes(popper.ownerDocument),
  12253. height = _getWindowSizes.height,
  12254. width = _getWindowSizes.width;
  12255. boundaries.top += offsets.top - offsets.marginTop;
  12256. boundaries.bottom = height + offsets.top;
  12257. boundaries.left += offsets.left - offsets.marginLeft;
  12258. boundaries.right = width + offsets.left;
  12259. } else {
  12260. // for all the other DOM elements, this one is good
  12261. boundaries = offsets;
  12262. }
  12263. }
  12264. // Add paddings
  12265. padding = padding || 0;
  12266. var isPaddingNumber = typeof padding === 'number';
  12267. boundaries.left += isPaddingNumber ? padding : padding.left || 0;
  12268. boundaries.top += isPaddingNumber ? padding : padding.top || 0;
  12269. boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
  12270. boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
  12271. return boundaries;
  12272. }
  12273. function getArea(_ref) {
  12274. var width = _ref.width,
  12275. height = _ref.height;
  12276. return width * height;
  12277. }
  12278. /**
  12279. * Utility used to transform the `auto` placement to the placement with more
  12280. * available space.
  12281. * @method
  12282. * @memberof Popper.Utils
  12283. * @argument {Object} data - The data object generated by update method
  12284. * @argument {Object} options - Modifiers configuration and options
  12285. * @returns {Object} The data object, properly modified
  12286. */
  12287. function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
  12288. var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
  12289. if (placement.indexOf('auto') === -1) {
  12290. return placement;
  12291. }
  12292. var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
  12293. var rects = {
  12294. top: {
  12295. width: boundaries.width,
  12296. height: refRect.top - boundaries.top
  12297. },
  12298. right: {
  12299. width: boundaries.right - refRect.right,
  12300. height: boundaries.height
  12301. },
  12302. bottom: {
  12303. width: boundaries.width,
  12304. height: boundaries.bottom - refRect.bottom
  12305. },
  12306. left: {
  12307. width: refRect.left - boundaries.left,
  12308. height: boundaries.height
  12309. }
  12310. };
  12311. var sortedAreas = Object.keys(rects).map(function (key) {
  12312. return _extends({
  12313. key: key
  12314. }, rects[key], {
  12315. area: getArea(rects[key])
  12316. });
  12317. }).sort(function (a, b) {
  12318. return b.area - a.area;
  12319. });
  12320. var filteredAreas = sortedAreas.filter(function (_ref2) {
  12321. var width = _ref2.width,
  12322. height = _ref2.height;
  12323. return width >= popper.clientWidth && height >= popper.clientHeight;
  12324. });
  12325. var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
  12326. var variation = placement.split('-')[1];
  12327. return computedPlacement + (variation ? '-' + variation : '');
  12328. }
  12329. /**
  12330. * Get offsets to the reference element
  12331. * @method
  12332. * @memberof Popper.Utils
  12333. * @param {Object} state
  12334. * @param {Element} popper - the popper element
  12335. * @param {Element} reference - the reference element (the popper will be relative to this)
  12336. * @param {Element} fixedPosition - is in fixed position mode
  12337. * @returns {Object} An object containing the offsets which will be applied to the popper
  12338. */
  12339. function getReferenceOffsets(state, popper, reference) {
  12340. var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  12341. var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
  12342. return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
  12343. }
  12344. /**
  12345. * Get the outer sizes of the given element (offset size + margins)
  12346. * @method
  12347. * @memberof Popper.Utils
  12348. * @argument {Element} element
  12349. * @returns {Object} object containing width and height properties
  12350. */
  12351. function getOuterSizes(element) {
  12352. var styles = getComputedStyle(element);
  12353. var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
  12354. var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
  12355. var result = {
  12356. width: element.offsetWidth + y,
  12357. height: element.offsetHeight + x
  12358. };
  12359. return result;
  12360. }
  12361. /**
  12362. * Get the opposite placement of the given one
  12363. * @method
  12364. * @memberof Popper.Utils
  12365. * @argument {String} placement
  12366. * @returns {String} flipped placement
  12367. */
  12368. function getOppositePlacement(placement) {
  12369. var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
  12370. return placement.replace(/left|right|bottom|top/g, function (matched) {
  12371. return hash[matched];
  12372. });
  12373. }
  12374. /**
  12375. * Get offsets to the popper
  12376. * @method
  12377. * @memberof Popper.Utils
  12378. * @param {Object} position - CSS position the Popper will get applied
  12379. * @param {HTMLElement} popper - the popper element
  12380. * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
  12381. * @param {String} placement - one of the valid placement options
  12382. * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
  12383. */
  12384. function getPopperOffsets(popper, referenceOffsets, placement) {
  12385. placement = placement.split('-')[0];
  12386. // Get popper node sizes
  12387. var popperRect = getOuterSizes(popper);
  12388. // Add position, width and height to our offsets object
  12389. var popperOffsets = {
  12390. width: popperRect.width,
  12391. height: popperRect.height
  12392. };
  12393. // depending by the popper placement we have to compute its offsets slightly differently
  12394. var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
  12395. var mainSide = isHoriz ? 'top' : 'left';
  12396. var secondarySide = isHoriz ? 'left' : 'top';
  12397. var measurement = isHoriz ? 'height' : 'width';
  12398. var secondaryMeasurement = !isHoriz ? 'height' : 'width';
  12399. popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
  12400. if (placement === secondarySide) {
  12401. popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
  12402. } else {
  12403. popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
  12404. }
  12405. return popperOffsets;
  12406. }
  12407. /**
  12408. * Mimics the `find` method of Array
  12409. * @method
  12410. * @memberof Popper.Utils
  12411. * @argument {Array} arr
  12412. * @argument prop
  12413. * @argument value
  12414. * @returns index or -1
  12415. */
  12416. function find(arr, check) {
  12417. // use native find if supported
  12418. if (Array.prototype.find) {
  12419. return arr.find(check);
  12420. }
  12421. // use `filter` to obtain the same behavior of `find`
  12422. return arr.filter(check)[0];
  12423. }
  12424. /**
  12425. * Return the index of the matching object
  12426. * @method
  12427. * @memberof Popper.Utils
  12428. * @argument {Array} arr
  12429. * @argument prop
  12430. * @argument value
  12431. * @returns index or -1
  12432. */
  12433. function findIndex(arr, prop, value) {
  12434. // use native findIndex if supported
  12435. if (Array.prototype.findIndex) {
  12436. return arr.findIndex(function (cur) {
  12437. return cur[prop] === value;
  12438. });
  12439. }
  12440. // use `find` + `indexOf` if `findIndex` isn't supported
  12441. var match = find(arr, function (obj) {
  12442. return obj[prop] === value;
  12443. });
  12444. return arr.indexOf(match);
  12445. }
  12446. /**
  12447. * Loop trough the list of modifiers and run them in order,
  12448. * each of them will then edit the data object.
  12449. * @method
  12450. * @memberof Popper.Utils
  12451. * @param {dataObject} data
  12452. * @param {Array} modifiers
  12453. * @param {String} ends - Optional modifier name used as stopper
  12454. * @returns {dataObject}
  12455. */
  12456. function runModifiers(modifiers, data, ends) {
  12457. var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
  12458. modifiersToRun.forEach(function (modifier) {
  12459. if (modifier['function']) {
  12460. // eslint-disable-line dot-notation
  12461. console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
  12462. }
  12463. var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
  12464. if (modifier.enabled && isFunction(fn)) {
  12465. // Add properties to offsets to make them a complete clientRect object
  12466. // we do this before each modifier to make sure the previous one doesn't
  12467. // mess with these values
  12468. data.offsets.popper = getClientRect(data.offsets.popper);
  12469. data.offsets.reference = getClientRect(data.offsets.reference);
  12470. data = fn(data, modifier);
  12471. }
  12472. });
  12473. return data;
  12474. }
  12475. /**
  12476. * Updates the position of the popper, computing the new offsets and applying
  12477. * the new style.<br />
  12478. * Prefer `scheduleUpdate` over `update` because of performance reasons.
  12479. * @method
  12480. * @memberof Popper
  12481. */
  12482. function update() {
  12483. // if popper is destroyed, don't perform any further update
  12484. if (this.state.isDestroyed) {
  12485. return;
  12486. }
  12487. var data = {
  12488. instance: this,
  12489. styles: {},
  12490. arrowStyles: {},
  12491. attributes: {},
  12492. flipped: false,
  12493. offsets: {}
  12494. };
  12495. // compute reference element offsets
  12496. data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
  12497. // compute auto placement, store placement inside the data object,
  12498. // modifiers will be able to edit `placement` if needed
  12499. // and refer to originalPlacement to know the original value
  12500. data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
  12501. // store the computed placement inside `originalPlacement`
  12502. data.originalPlacement = data.placement;
  12503. data.positionFixed = this.options.positionFixed;
  12504. // compute the popper offsets
  12505. data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
  12506. data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
  12507. // run the modifiers
  12508. data = runModifiers(this.modifiers, data);
  12509. // the first `update` will call `onCreate` callback
  12510. // the other ones will call `onUpdate` callback
  12511. if (!this.state.isCreated) {
  12512. this.state.isCreated = true;
  12513. this.options.onCreate(data);
  12514. } else {
  12515. this.options.onUpdate(data);
  12516. }
  12517. }
  12518. /**
  12519. * Helper used to know if the given modifier is enabled.
  12520. * @method
  12521. * @memberof Popper.Utils
  12522. * @returns {Boolean}
  12523. */
  12524. function isModifierEnabled(modifiers, modifierName) {
  12525. return modifiers.some(function (_ref) {
  12526. var name = _ref.name,
  12527. enabled = _ref.enabled;
  12528. return enabled && name === modifierName;
  12529. });
  12530. }
  12531. /**
  12532. * Get the prefixed supported property name
  12533. * @method
  12534. * @memberof Popper.Utils
  12535. * @argument {String} property (camelCase)
  12536. * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
  12537. */
  12538. function getSupportedPropertyName(property) {
  12539. var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
  12540. var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
  12541. for (var i = 0; i < prefixes.length; i++) {
  12542. var prefix = prefixes[i];
  12543. var toCheck = prefix ? '' + prefix + upperProp : property;
  12544. if (typeof document.body.style[toCheck] !== 'undefined') {
  12545. return toCheck;
  12546. }
  12547. }
  12548. return null;
  12549. }
  12550. /**
  12551. * Destroys the popper.
  12552. * @method
  12553. * @memberof Popper
  12554. */
  12555. function destroy() {
  12556. this.state.isDestroyed = true;
  12557. // touch DOM only if `applyStyle` modifier is enabled
  12558. if (isModifierEnabled(this.modifiers, 'applyStyle')) {
  12559. this.popper.removeAttribute('x-placement');
  12560. this.popper.style.position = '';
  12561. this.popper.style.top = '';
  12562. this.popper.style.left = '';
  12563. this.popper.style.right = '';
  12564. this.popper.style.bottom = '';
  12565. this.popper.style.willChange = '';
  12566. this.popper.style[getSupportedPropertyName('transform')] = '';
  12567. }
  12568. this.disableEventListeners();
  12569. // remove the popper if user explicity asked for the deletion on destroy
  12570. // do not use `remove` because IE11 doesn't support it
  12571. if (this.options.removeOnDestroy) {
  12572. this.popper.parentNode.removeChild(this.popper);
  12573. }
  12574. return this;
  12575. }
  12576. /**
  12577. * Get the window associated with the element
  12578. * @argument {Element} element
  12579. * @returns {Window}
  12580. */
  12581. function getWindow(element) {
  12582. var ownerDocument = element.ownerDocument;
  12583. return ownerDocument ? ownerDocument.defaultView : window;
  12584. }
  12585. function attachToScrollParents(scrollParent, event, callback, scrollParents) {
  12586. var isBody = scrollParent.nodeName === 'BODY';
  12587. var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
  12588. target.addEventListener(event, callback, { passive: true });
  12589. if (!isBody) {
  12590. attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
  12591. }
  12592. scrollParents.push(target);
  12593. }
  12594. /**
  12595. * Setup needed event listeners used to update the popper position
  12596. * @method
  12597. * @memberof Popper.Utils
  12598. * @private
  12599. */
  12600. function setupEventListeners(reference, options, state, updateBound) {
  12601. // Resize event listener on window
  12602. state.updateBound = updateBound;
  12603. getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
  12604. // Scroll event listener on scroll parents
  12605. var scrollElement = getScrollParent(reference);
  12606. attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
  12607. state.scrollElement = scrollElement;
  12608. state.eventsEnabled = true;
  12609. return state;
  12610. }
  12611. /**
  12612. * It will add resize/scroll events and start recalculating
  12613. * position of the popper element when they are triggered.
  12614. * @method
  12615. * @memberof Popper
  12616. */
  12617. function enableEventListeners() {
  12618. if (!this.state.eventsEnabled) {
  12619. this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
  12620. }
  12621. }
  12622. /**
  12623. * Remove event listeners used to update the popper position
  12624. * @method
  12625. * @memberof Popper.Utils
  12626. * @private
  12627. */
  12628. function removeEventListeners(reference, state) {
  12629. // Remove resize event listener on window
  12630. getWindow(reference).removeEventListener('resize', state.updateBound);
  12631. // Remove scroll event listener on scroll parents
  12632. state.scrollParents.forEach(function (target) {
  12633. target.removeEventListener('scroll', state.updateBound);
  12634. });
  12635. // Reset state
  12636. state.updateBound = null;
  12637. state.scrollParents = [];
  12638. state.scrollElement = null;
  12639. state.eventsEnabled = false;
  12640. return state;
  12641. }
  12642. /**
  12643. * It will remove resize/scroll events and won't recalculate popper position
  12644. * when they are triggered. It also won't trigger `onUpdate` callback anymore,
  12645. * unless you call `update` method manually.
  12646. * @method
  12647. * @memberof Popper
  12648. */
  12649. function disableEventListeners() {
  12650. if (this.state.eventsEnabled) {
  12651. cancelAnimationFrame(this.scheduleUpdate);
  12652. this.state = removeEventListeners(this.reference, this.state);
  12653. }
  12654. }
  12655. /**
  12656. * Tells if a given input is a number
  12657. * @method
  12658. * @memberof Popper.Utils
  12659. * @param {*} input to check
  12660. * @return {Boolean}
  12661. */
  12662. function isNumeric(n) {
  12663. return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
  12664. }
  12665. /**
  12666. * Set the style to the given popper
  12667. * @method
  12668. * @memberof Popper.Utils
  12669. * @argument {Element} element - Element to apply the style to
  12670. * @argument {Object} styles
  12671. * Object with a list of properties and values which will be applied to the element
  12672. */
  12673. function setStyles(element, styles) {
  12674. Object.keys(styles).forEach(function (prop) {
  12675. var unit = '';
  12676. // add unit if the value is numeric and is one of the following
  12677. if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
  12678. unit = 'px';
  12679. }
  12680. element.style[prop] = styles[prop] + unit;
  12681. });
  12682. }
  12683. /**
  12684. * Set the attributes to the given popper
  12685. * @method
  12686. * @memberof Popper.Utils
  12687. * @argument {Element} element - Element to apply the attributes to
  12688. * @argument {Object} styles
  12689. * Object with a list of properties and values which will be applied to the element
  12690. */
  12691. function setAttributes(element, attributes) {
  12692. Object.keys(attributes).forEach(function (prop) {
  12693. var value = attributes[prop];
  12694. if (value !== false) {
  12695. element.setAttribute(prop, attributes[prop]);
  12696. } else {
  12697. element.removeAttribute(prop);
  12698. }
  12699. });
  12700. }
  12701. /**
  12702. * @function
  12703. * @memberof Modifiers
  12704. * @argument {Object} data - The data object generated by `update` method
  12705. * @argument {Object} data.styles - List of style properties - values to apply to popper element
  12706. * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
  12707. * @argument {Object} options - Modifiers configuration and options
  12708. * @returns {Object} The same data object
  12709. */
  12710. function applyStyle(data) {
  12711. // any property present in `data.styles` will be applied to the popper,
  12712. // in this way we can make the 3rd party modifiers add custom styles to it
  12713. // Be aware, modifiers could override the properties defined in the previous
  12714. // lines of this modifier!
  12715. setStyles(data.instance.popper, data.styles);
  12716. // any property present in `data.attributes` will be applied to the popper,
  12717. // they will be set as HTML attributes of the element
  12718. setAttributes(data.instance.popper, data.attributes);
  12719. // if arrowElement is defined and arrowStyles has some properties
  12720. if (data.arrowElement && Object.keys(data.arrowStyles).length) {
  12721. setStyles(data.arrowElement, data.arrowStyles);
  12722. }
  12723. return data;
  12724. }
  12725. /**
  12726. * Set the x-placement attribute before everything else because it could be used
  12727. * to add margins to the popper margins needs to be calculated to get the
  12728. * correct popper offsets.
  12729. * @method
  12730. * @memberof Popper.modifiers
  12731. * @param {HTMLElement} reference - The reference element used to position the popper
  12732. * @param {HTMLElement} popper - The HTML element used as popper
  12733. * @param {Object} options - Popper.js options
  12734. */
  12735. function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
  12736. // compute reference element offsets
  12737. var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
  12738. // compute auto placement, store placement inside the data object,
  12739. // modifiers will be able to edit `placement` if needed
  12740. // and refer to originalPlacement to know the original value
  12741. var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
  12742. popper.setAttribute('x-placement', placement);
  12743. // Apply `position` to popper before anything else because
  12744. // without the position applied we can't guarantee correct computations
  12745. setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
  12746. return options;
  12747. }
  12748. /**
  12749. * @function
  12750. * @memberof Modifiers
  12751. * @argument {Object} data - The data object generated by `update` method
  12752. * @argument {Object} options - Modifiers configuration and options
  12753. * @returns {Object} The data object, properly modified
  12754. */
  12755. function computeStyle(data, options) {
  12756. var x = options.x,
  12757. y = options.y;
  12758. var popper = data.offsets.popper;
  12759. // Remove this legacy support in Popper.js v2
  12760. var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
  12761. return modifier.name === 'applyStyle';
  12762. }).gpuAcceleration;
  12763. if (legacyGpuAccelerationOption !== undefined) {
  12764. console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
  12765. }
  12766. var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
  12767. var offsetParent = getOffsetParent(data.instance.popper);
  12768. var offsetParentRect = getBoundingClientRect(offsetParent);
  12769. // Styles
  12770. var styles = {
  12771. position: popper.position
  12772. };
  12773. // Avoid blurry text by using full pixel integers.
  12774. // For pixel-perfect positioning, top/bottom prefers rounded
  12775. // values, while left/right prefers floored values.
  12776. var offsets = {
  12777. left: Math.floor(popper.left),
  12778. top: Math.round(popper.top),
  12779. bottom: Math.round(popper.bottom),
  12780. right: Math.floor(popper.right)
  12781. };
  12782. var sideA = x === 'bottom' ? 'top' : 'bottom';
  12783. var sideB = y === 'right' ? 'left' : 'right';
  12784. // if gpuAcceleration is set to `true` and transform is supported,
  12785. // we use `translate3d` to apply the position to the popper we
  12786. // automatically use the supported prefixed version if needed
  12787. var prefixedProperty = getSupportedPropertyName('transform');
  12788. // now, let's make a step back and look at this code closely (wtf?)
  12789. // If the content of the popper grows once it's been positioned, it
  12790. // may happen that the popper gets misplaced because of the new content
  12791. // overflowing its reference element
  12792. // To avoid this problem, we provide two options (x and y), which allow
  12793. // the consumer to define the offset origin.
  12794. // If we position a popper on top of a reference element, we can set
  12795. // `x` to `top` to make the popper grow towards its top instead of
  12796. // its bottom.
  12797. var left = void 0,
  12798. top = void 0;
  12799. if (sideA === 'bottom') {
  12800. // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
  12801. // and not the bottom of the html element
  12802. if (offsetParent.nodeName === 'HTML') {
  12803. top = -offsetParent.clientHeight + offsets.bottom;
  12804. } else {
  12805. top = -offsetParentRect.height + offsets.bottom;
  12806. }
  12807. } else {
  12808. top = offsets.top;
  12809. }
  12810. if (sideB === 'right') {
  12811. if (offsetParent.nodeName === 'HTML') {
  12812. left = -offsetParent.clientWidth + offsets.right;
  12813. } else {
  12814. left = -offsetParentRect.width + offsets.right;
  12815. }
  12816. } else {
  12817. left = offsets.left;
  12818. }
  12819. if (gpuAcceleration && prefixedProperty) {
  12820. styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
  12821. styles[sideA] = 0;
  12822. styles[sideB] = 0;
  12823. styles.willChange = 'transform';
  12824. } else {
  12825. // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
  12826. var invertTop = sideA === 'bottom' ? -1 : 1;
  12827. var invertLeft = sideB === 'right' ? -1 : 1;
  12828. styles[sideA] = top * invertTop;
  12829. styles[sideB] = left * invertLeft;
  12830. styles.willChange = sideA + ', ' + sideB;
  12831. }
  12832. // Attributes
  12833. var attributes = {
  12834. 'x-placement': data.placement
  12835. };
  12836. // Update `data` attributes, styles and arrowStyles
  12837. data.attributes = _extends({}, attributes, data.attributes);
  12838. data.styles = _extends({}, styles, data.styles);
  12839. data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
  12840. return data;
  12841. }
  12842. /**
  12843. * Helper used to know if the given modifier depends from another one.<br />
  12844. * It checks if the needed modifier is listed and enabled.
  12845. * @method
  12846. * @memberof Popper.Utils
  12847. * @param {Array} modifiers - list of modifiers
  12848. * @param {String} requestingName - name of requesting modifier
  12849. * @param {String} requestedName - name of requested modifier
  12850. * @returns {Boolean}
  12851. */
  12852. function isModifierRequired(modifiers, requestingName, requestedName) {
  12853. var requesting = find(modifiers, function (_ref) {
  12854. var name = _ref.name;
  12855. return name === requestingName;
  12856. });
  12857. var isRequired = !!requesting && modifiers.some(function (modifier) {
  12858. return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
  12859. });
  12860. if (!isRequired) {
  12861. var _requesting = '`' + requestingName + '`';
  12862. var requested = '`' + requestedName + '`';
  12863. console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
  12864. }
  12865. return isRequired;
  12866. }
  12867. /**
  12868. * @function
  12869. * @memberof Modifiers
  12870. * @argument {Object} data - The data object generated by update method
  12871. * @argument {Object} options - Modifiers configuration and options
  12872. * @returns {Object} The data object, properly modified
  12873. */
  12874. function arrow(data, options) {
  12875. var _data$offsets$arrow;
  12876. // arrow depends on keepTogether in order to work
  12877. if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
  12878. return data;
  12879. }
  12880. var arrowElement = options.element;
  12881. // if arrowElement is a string, suppose it's a CSS selector
  12882. if (typeof arrowElement === 'string') {
  12883. arrowElement = data.instance.popper.querySelector(arrowElement);
  12884. // if arrowElement is not found, don't run the modifier
  12885. if (!arrowElement) {
  12886. return data;
  12887. }
  12888. } else {
  12889. // if the arrowElement isn't a query selector we must check that the
  12890. // provided DOM node is child of its popper node
  12891. if (!data.instance.popper.contains(arrowElement)) {
  12892. console.warn('WARNING: `arrow.element` must be child of its popper element!');
  12893. return data;
  12894. }
  12895. }
  12896. var placement = data.placement.split('-')[0];
  12897. var _data$offsets = data.offsets,
  12898. popper = _data$offsets.popper,
  12899. reference = _data$offsets.reference;
  12900. var isVertical = ['left', 'right'].indexOf(placement) !== -1;
  12901. var len = isVertical ? 'height' : 'width';
  12902. var sideCapitalized = isVertical ? 'Top' : 'Left';
  12903. var side = sideCapitalized.toLowerCase();
  12904. var altSide = isVertical ? 'left' : 'top';
  12905. var opSide = isVertical ? 'bottom' : 'right';
  12906. var arrowElementSize = getOuterSizes(arrowElement)[len];
  12907. //
  12908. // extends keepTogether behavior making sure the popper and its
  12909. // reference have enough pixels in conjunction
  12910. //
  12911. // top/left side
  12912. if (reference[opSide] - arrowElementSize < popper[side]) {
  12913. data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
  12914. }
  12915. // bottom/right side
  12916. if (reference[side] + arrowElementSize > popper[opSide]) {
  12917. data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
  12918. }
  12919. data.offsets.popper = getClientRect(data.offsets.popper);
  12920. // compute center of the popper
  12921. var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
  12922. // Compute the sideValue using the updated popper offsets
  12923. // take popper margin in account because we don't have this info available
  12924. var css = getStyleComputedProperty(data.instance.popper);
  12925. var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
  12926. var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
  12927. var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
  12928. // prevent arrowElement from being placed not contiguously to its popper
  12929. sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
  12930. data.arrowElement = arrowElement;
  12931. data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
  12932. return data;
  12933. }
  12934. /**
  12935. * Get the opposite placement variation of the given one
  12936. * @method
  12937. * @memberof Popper.Utils
  12938. * @argument {String} placement variation
  12939. * @returns {String} flipped placement variation
  12940. */
  12941. function getOppositeVariation(variation) {
  12942. if (variation === 'end') {
  12943. return 'start';
  12944. } else if (variation === 'start') {
  12945. return 'end';
  12946. }
  12947. return variation;
  12948. }
  12949. /**
  12950. * List of accepted placements to use as values of the `placement` option.<br />
  12951. * Valid placements are:
  12952. * - `auto`
  12953. * - `top`
  12954. * - `right`
  12955. * - `bottom`
  12956. * - `left`
  12957. *
  12958. * Each placement can have a variation from this list:
  12959. * - `-start`
  12960. * - `-end`
  12961. *
  12962. * Variations are interpreted easily if you think of them as the left to right
  12963. * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
  12964. * is right.<br />
  12965. * Vertically (`left` and `right`), `start` is top and `end` is bottom.
  12966. *
  12967. * Some valid examples are:
  12968. * - `top-end` (on top of reference, right aligned)
  12969. * - `right-start` (on right of reference, top aligned)
  12970. * - `bottom` (on bottom, centered)
  12971. * - `auto-end` (on the side with more space available, alignment depends by placement)
  12972. *
  12973. * @static
  12974. * @type {Array}
  12975. * @enum {String}
  12976. * @readonly
  12977. * @method placements
  12978. * @memberof Popper
  12979. */
  12980. var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
  12981. // Get rid of `auto` `auto-start` and `auto-end`
  12982. var validPlacements = placements.slice(3);
  12983. /**
  12984. * Given an initial placement, returns all the subsequent placements
  12985. * clockwise (or counter-clockwise).
  12986. *
  12987. * @method
  12988. * @memberof Popper.Utils
  12989. * @argument {String} placement - A valid placement (it accepts variations)
  12990. * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
  12991. * @returns {Array} placements including their variations
  12992. */
  12993. function clockwise(placement) {
  12994. var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  12995. var index = validPlacements.indexOf(placement);
  12996. var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
  12997. return counter ? arr.reverse() : arr;
  12998. }
  12999. var BEHAVIORS = {
  13000. FLIP: 'flip',
  13001. CLOCKWISE: 'clockwise',
  13002. COUNTERCLOCKWISE: 'counterclockwise'
  13003. };
  13004. /**
  13005. * @function
  13006. * @memberof Modifiers
  13007. * @argument {Object} data - The data object generated by update method
  13008. * @argument {Object} options - Modifiers configuration and options
  13009. * @returns {Object} The data object, properly modified
  13010. */
  13011. function flip(data, options) {
  13012. // if `inner` modifier is enabled, we can't use the `flip` modifier
  13013. if (isModifierEnabled(data.instance.modifiers, 'inner')) {
  13014. return data;
  13015. }
  13016. if (data.flipped && data.placement === data.originalPlacement) {
  13017. // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
  13018. return data;
  13019. }
  13020. var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
  13021. var placement = data.placement.split('-')[0];
  13022. var placementOpposite = getOppositePlacement(placement);
  13023. var variation = data.placement.split('-')[1] || '';
  13024. var flipOrder = [];
  13025. switch (options.behavior) {
  13026. case BEHAVIORS.FLIP:
  13027. flipOrder = [placement, placementOpposite];
  13028. break;
  13029. case BEHAVIORS.CLOCKWISE:
  13030. flipOrder = clockwise(placement);
  13031. break;
  13032. case BEHAVIORS.COUNTERCLOCKWISE:
  13033. flipOrder = clockwise(placement, true);
  13034. break;
  13035. default:
  13036. flipOrder = options.behavior;
  13037. }
  13038. flipOrder.forEach(function (step, index) {
  13039. if (placement !== step || flipOrder.length === index + 1) {
  13040. return data;
  13041. }
  13042. placement = data.placement.split('-')[0];
  13043. placementOpposite = getOppositePlacement(placement);
  13044. var popperOffsets = data.offsets.popper;
  13045. var refOffsets = data.offsets.reference;
  13046. // using floor because the reference offsets may contain decimals we are not going to consider here
  13047. var floor = Math.floor;
  13048. var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
  13049. var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
  13050. var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
  13051. var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
  13052. var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
  13053. var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
  13054. // flip the variation if required
  13055. var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
  13056. var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
  13057. if (overlapsRef || overflowsBoundaries || flippedVariation) {
  13058. // this boolean to detect any flip loop
  13059. data.flipped = true;
  13060. if (overlapsRef || overflowsBoundaries) {
  13061. placement = flipOrder[index + 1];
  13062. }
  13063. if (flippedVariation) {
  13064. variation = getOppositeVariation(variation);
  13065. }
  13066. data.placement = placement + (variation ? '-' + variation : '');
  13067. // this object contains `position`, we want to preserve it along with
  13068. // any additional property we may add in the future
  13069. data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
  13070. data = runModifiers(data.instance.modifiers, data, 'flip');
  13071. }
  13072. });
  13073. return data;
  13074. }
  13075. /**
  13076. * @function
  13077. * @memberof Modifiers
  13078. * @argument {Object} data - The data object generated by update method
  13079. * @argument {Object} options - Modifiers configuration and options
  13080. * @returns {Object} The data object, properly modified
  13081. */
  13082. function keepTogether(data) {
  13083. var _data$offsets = data.offsets,
  13084. popper = _data$offsets.popper,
  13085. reference = _data$offsets.reference;
  13086. var placement = data.placement.split('-')[0];
  13087. var floor = Math.floor;
  13088. var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
  13089. var side = isVertical ? 'right' : 'bottom';
  13090. var opSide = isVertical ? 'left' : 'top';
  13091. var measurement = isVertical ? 'width' : 'height';
  13092. if (popper[side] < floor(reference[opSide])) {
  13093. data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
  13094. }
  13095. if (popper[opSide] > floor(reference[side])) {
  13096. data.offsets.popper[opSide] = floor(reference[side]);
  13097. }
  13098. return data;
  13099. }
  13100. /**
  13101. * Converts a string containing value + unit into a px value number
  13102. * @function
  13103. * @memberof {modifiers~offset}
  13104. * @private
  13105. * @argument {String} str - Value + unit string
  13106. * @argument {String} measurement - `height` or `width`
  13107. * @argument {Object} popperOffsets
  13108. * @argument {Object} referenceOffsets
  13109. * @returns {Number|String}
  13110. * Value in pixels, or original string if no values were extracted
  13111. */
  13112. function toValue(str, measurement, popperOffsets, referenceOffsets) {
  13113. // separate value from unit
  13114. var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
  13115. var value = +split[1];
  13116. var unit = split[2];
  13117. // If it's not a number it's an operator, I guess
  13118. if (!value) {
  13119. return str;
  13120. }
  13121. if (unit.indexOf('%') === 0) {
  13122. var element = void 0;
  13123. switch (unit) {
  13124. case '%p':
  13125. element = popperOffsets;
  13126. break;
  13127. case '%':
  13128. case '%r':
  13129. default:
  13130. element = referenceOffsets;
  13131. }
  13132. var rect = getClientRect(element);
  13133. return rect[measurement] / 100 * value;
  13134. } else if (unit === 'vh' || unit === 'vw') {
  13135. // if is a vh or vw, we calculate the size based on the viewport
  13136. var size = void 0;
  13137. if (unit === 'vh') {
  13138. size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  13139. } else {
  13140. size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  13141. }
  13142. return size / 100 * value;
  13143. } else {
  13144. // if is an explicit pixel unit, we get rid of the unit and keep the value
  13145. // if is an implicit unit, it's px, and we return just the value
  13146. return value;
  13147. }
  13148. }
  13149. /**
  13150. * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
  13151. * @function
  13152. * @memberof {modifiers~offset}
  13153. * @private
  13154. * @argument {String} offset
  13155. * @argument {Object} popperOffsets
  13156. * @argument {Object} referenceOffsets
  13157. * @argument {String} basePlacement
  13158. * @returns {Array} a two cells array with x and y offsets in numbers
  13159. */
  13160. function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
  13161. var offsets = [0, 0];
  13162. // Use height if placement is left or right and index is 0 otherwise use width
  13163. // in this way the first offset will use an axis and the second one
  13164. // will use the other one
  13165. var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
  13166. // Split the offset string to obtain a list of values and operands
  13167. // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
  13168. var fragments = offset.split(/(\+|\-)/).map(function (frag) {
  13169. return frag.trim();
  13170. });
  13171. // Detect if the offset string contains a pair of values or a single one
  13172. // they could be separated by comma or space
  13173. var divider = fragments.indexOf(find(fragments, function (frag) {
  13174. return frag.search(/,|\s/) !== -1;
  13175. }));
  13176. if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
  13177. console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
  13178. }
  13179. // If divider is found, we divide the list of values and operands to divide
  13180. // them by ofset X and Y.
  13181. var splitRegex = /\s*,\s*|\s+/;
  13182. var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
  13183. // Convert the values with units to absolute pixels to allow our computations
  13184. ops = ops.map(function (op, index) {
  13185. // Most of the units rely on the orientation of the popper
  13186. var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
  13187. var mergeWithPrevious = false;
  13188. return op
  13189. // This aggregates any `+` or `-` sign that aren't considered operators
  13190. // e.g.: 10 + +5 => [10, +, +5]
  13191. .reduce(function (a, b) {
  13192. if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
  13193. a[a.length - 1] = b;
  13194. mergeWithPrevious = true;
  13195. return a;
  13196. } else if (mergeWithPrevious) {
  13197. a[a.length - 1] += b;
  13198. mergeWithPrevious = false;
  13199. return a;
  13200. } else {
  13201. return a.concat(b);
  13202. }
  13203. }, [])
  13204. // Here we convert the string values into number values (in px)
  13205. .map(function (str) {
  13206. return toValue(str, measurement, popperOffsets, referenceOffsets);
  13207. });
  13208. });
  13209. // Loop trough the offsets arrays and execute the operations
  13210. ops.forEach(function (op, index) {
  13211. op.forEach(function (frag, index2) {
  13212. if (isNumeric(frag)) {
  13213. offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
  13214. }
  13215. });
  13216. });
  13217. return offsets;
  13218. }
  13219. /**
  13220. * @function
  13221. * @memberof Modifiers
  13222. * @argument {Object} data - The data object generated by update method
  13223. * @argument {Object} options - Modifiers configuration and options
  13224. * @argument {Number|String} options.offset=0
  13225. * The offset value as described in the modifier description
  13226. * @returns {Object} The data object, properly modified
  13227. */
  13228. function offset(data, _ref) {
  13229. var offset = _ref.offset;
  13230. var placement = data.placement,
  13231. _data$offsets = data.offsets,
  13232. popper = _data$offsets.popper,
  13233. reference = _data$offsets.reference;
  13234. var basePlacement = placement.split('-')[0];
  13235. var offsets = void 0;
  13236. if (isNumeric(+offset)) {
  13237. offsets = [+offset, 0];
  13238. } else {
  13239. offsets = parseOffset(offset, popper, reference, basePlacement);
  13240. }
  13241. if (basePlacement === 'left') {
  13242. popper.top += offsets[0];
  13243. popper.left -= offsets[1];
  13244. } else if (basePlacement === 'right') {
  13245. popper.top += offsets[0];
  13246. popper.left += offsets[1];
  13247. } else if (basePlacement === 'top') {
  13248. popper.left += offsets[0];
  13249. popper.top -= offsets[1];
  13250. } else if (basePlacement === 'bottom') {
  13251. popper.left += offsets[0];
  13252. popper.top += offsets[1];
  13253. }
  13254. data.popper = popper;
  13255. return data;
  13256. }
  13257. /**
  13258. * @function
  13259. * @memberof Modifiers
  13260. * @argument {Object} data - The data object generated by `update` method
  13261. * @argument {Object} options - Modifiers configuration and options
  13262. * @returns {Object} The data object, properly modified
  13263. */
  13264. function preventOverflow(data, options) {
  13265. var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
  13266. // If offsetParent is the reference element, we really want to
  13267. // go one step up and use the next offsetParent as reference to
  13268. // avoid to make this modifier completely useless and look like broken
  13269. if (data.instance.reference === boundariesElement) {
  13270. boundariesElement = getOffsetParent(boundariesElement);
  13271. }
  13272. // NOTE: DOM access here
  13273. // resets the popper's position so that the document size can be calculated excluding
  13274. // the size of the popper element itself
  13275. var transformProp = getSupportedPropertyName('transform');
  13276. var popperStyles = data.instance.popper.style; // assignment to help minification
  13277. var top = popperStyles.top,
  13278. left = popperStyles.left,
  13279. transform = popperStyles[transformProp];
  13280. popperStyles.top = '';
  13281. popperStyles.left = '';
  13282. popperStyles[transformProp] = '';
  13283. var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
  13284. // NOTE: DOM access here
  13285. // restores the original style properties after the offsets have been computed
  13286. popperStyles.top = top;
  13287. popperStyles.left = left;
  13288. popperStyles[transformProp] = transform;
  13289. options.boundaries = boundaries;
  13290. var order = options.priority;
  13291. var popper = data.offsets.popper;
  13292. var check = {
  13293. primary: function primary(placement) {
  13294. var value = popper[placement];
  13295. if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
  13296. value = Math.max(popper[placement], boundaries[placement]);
  13297. }
  13298. return defineProperty({}, placement, value);
  13299. },
  13300. secondary: function secondary(placement) {
  13301. var mainSide = placement === 'right' ? 'left' : 'top';
  13302. var value = popper[mainSide];
  13303. if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
  13304. value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
  13305. }
  13306. return defineProperty({}, mainSide, value);
  13307. }
  13308. };
  13309. order.forEach(function (placement) {
  13310. var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
  13311. popper = _extends({}, popper, check[side](placement));
  13312. });
  13313. data.offsets.popper = popper;
  13314. return data;
  13315. }
  13316. /**
  13317. * @function
  13318. * @memberof Modifiers
  13319. * @argument {Object} data - The data object generated by `update` method
  13320. * @argument {Object} options - Modifiers configuration and options
  13321. * @returns {Object} The data object, properly modified
  13322. */
  13323. function shift(data) {
  13324. var placement = data.placement;
  13325. var basePlacement = placement.split('-')[0];
  13326. var shiftvariation = placement.split('-')[1];
  13327. // if shift shiftvariation is specified, run the modifier
  13328. if (shiftvariation) {
  13329. var _data$offsets = data.offsets,
  13330. reference = _data$offsets.reference,
  13331. popper = _data$offsets.popper;
  13332. var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
  13333. var side = isVertical ? 'left' : 'top';
  13334. var measurement = isVertical ? 'width' : 'height';
  13335. var shiftOffsets = {
  13336. start: defineProperty({}, side, reference[side]),
  13337. end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
  13338. };
  13339. data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
  13340. }
  13341. return data;
  13342. }
  13343. /**
  13344. * @function
  13345. * @memberof Modifiers
  13346. * @argument {Object} data - The data object generated by update method
  13347. * @argument {Object} options - Modifiers configuration and options
  13348. * @returns {Object} The data object, properly modified
  13349. */
  13350. function hide(data) {
  13351. if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
  13352. return data;
  13353. }
  13354. var refRect = data.offsets.reference;
  13355. var bound = find(data.instance.modifiers, function (modifier) {
  13356. return modifier.name === 'preventOverflow';
  13357. }).boundaries;
  13358. if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
  13359. // Avoid unnecessary DOM access if visibility hasn't changed
  13360. if (data.hide === true) {
  13361. return data;
  13362. }
  13363. data.hide = true;
  13364. data.attributes['x-out-of-boundaries'] = '';
  13365. } else {
  13366. // Avoid unnecessary DOM access if visibility hasn't changed
  13367. if (data.hide === false) {
  13368. return data;
  13369. }
  13370. data.hide = false;
  13371. data.attributes['x-out-of-boundaries'] = false;
  13372. }
  13373. return data;
  13374. }
  13375. /**
  13376. * @function
  13377. * @memberof Modifiers
  13378. * @argument {Object} data - The data object generated by `update` method
  13379. * @argument {Object} options - Modifiers configuration and options
  13380. * @returns {Object} The data object, properly modified
  13381. */
  13382. function inner(data) {
  13383. var placement = data.placement;
  13384. var basePlacement = placement.split('-')[0];
  13385. var _data$offsets = data.offsets,
  13386. popper = _data$offsets.popper,
  13387. reference = _data$offsets.reference;
  13388. var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
  13389. var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
  13390. popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
  13391. data.placement = getOppositePlacement(placement);
  13392. data.offsets.popper = getClientRect(popper);
  13393. return data;
  13394. }
  13395. /**
  13396. * Modifier function, each modifier can have a function of this type assigned
  13397. * to its `fn` property.<br />
  13398. * These functions will be called on each update, this means that you must
  13399. * make sure they are performant enough to avoid performance bottlenecks.
  13400. *
  13401. * @function ModifierFn
  13402. * @argument {dataObject} data - The data object generated by `update` method
  13403. * @argument {Object} options - Modifiers configuration and options
  13404. * @returns {dataObject} The data object, properly modified
  13405. */
  13406. /**
  13407. * Modifiers are plugins used to alter the behavior of your poppers.<br />
  13408. * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
  13409. * needed by the library.
  13410. *
  13411. * Usually you don't want to override the `order`, `fn` and `onLoad` props.
  13412. * All the other properties are configurations that could be tweaked.
  13413. * @namespace modifiers
  13414. */
  13415. var modifiers = {
  13416. /**
  13417. * Modifier used to shift the popper on the start or end of its reference
  13418. * element.<br />
  13419. * It will read the variation of the `placement` property.<br />
  13420. * It can be one either `-end` or `-start`.
  13421. * @memberof modifiers
  13422. * @inner
  13423. */
  13424. shift: {
  13425. /** @prop {number} order=100 - Index used to define the order of execution */
  13426. order: 100,
  13427. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13428. enabled: true,
  13429. /** @prop {ModifierFn} */
  13430. fn: shift
  13431. },
  13432. /**
  13433. * The `offset` modifier can shift your popper on both its axis.
  13434. *
  13435. * It accepts the following units:
  13436. * - `px` or unit-less, interpreted as pixels
  13437. * - `%` or `%r`, percentage relative to the length of the reference element
  13438. * - `%p`, percentage relative to the length of the popper element
  13439. * - `vw`, CSS viewport width unit
  13440. * - `vh`, CSS viewport height unit
  13441. *
  13442. * For length is intended the main axis relative to the placement of the popper.<br />
  13443. * This means that if the placement is `top` or `bottom`, the length will be the
  13444. * `width`. In case of `left` or `right`, it will be the `height`.
  13445. *
  13446. * You can provide a single value (as `Number` or `String`), or a pair of values
  13447. * as `String` divided by a comma or one (or more) white spaces.<br />
  13448. * The latter is a deprecated method because it leads to confusion and will be
  13449. * removed in v2.<br />
  13450. * Additionally, it accepts additions and subtractions between different units.
  13451. * Note that multiplications and divisions aren't supported.
  13452. *
  13453. * Valid examples are:
  13454. * ```
  13455. * 10
  13456. * '10%'
  13457. * '10, 10'
  13458. * '10%, 10'
  13459. * '10 + 10%'
  13460. * '10 - 5vh + 3%'
  13461. * '-10px + 5vh, 5px - 6%'
  13462. * ```
  13463. * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
  13464. * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
  13465. * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
  13466. *
  13467. * @memberof modifiers
  13468. * @inner
  13469. */
  13470. offset: {
  13471. /** @prop {number} order=200 - Index used to define the order of execution */
  13472. order: 200,
  13473. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13474. enabled: true,
  13475. /** @prop {ModifierFn} */
  13476. fn: offset,
  13477. /** @prop {Number|String} offset=0
  13478. * The offset value as described in the modifier description
  13479. */
  13480. offset: 0
  13481. },
  13482. /**
  13483. * Modifier used to prevent the popper from being positioned outside the boundary.
  13484. *
  13485. * A scenario exists where the reference itself is not within the boundaries.<br />
  13486. * We can say it has "escaped the boundaries" — or just "escaped".<br />
  13487. * In this case we need to decide whether the popper should either:
  13488. *
  13489. * - detach from the reference and remain "trapped" in the boundaries, or
  13490. * - if it should ignore the boundary and "escape with its reference"
  13491. *
  13492. * When `escapeWithReference` is set to`true` and reference is completely
  13493. * outside its boundaries, the popper will overflow (or completely leave)
  13494. * the boundaries in order to remain attached to the edge of the reference.
  13495. *
  13496. * @memberof modifiers
  13497. * @inner
  13498. */
  13499. preventOverflow: {
  13500. /** @prop {number} order=300 - Index used to define the order of execution */
  13501. order: 300,
  13502. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13503. enabled: true,
  13504. /** @prop {ModifierFn} */
  13505. fn: preventOverflow,
  13506. /**
  13507. * @prop {Array} [priority=['left','right','top','bottom']]
  13508. * Popper will try to prevent overflow following these priorities by default,
  13509. * then, it could overflow on the left and on top of the `boundariesElement`
  13510. */
  13511. priority: ['left', 'right', 'top', 'bottom'],
  13512. /**
  13513. * @prop {number} padding=5
  13514. * Amount of pixel used to define a minimum distance between the boundaries
  13515. * and the popper. This makes sure the popper always has a little padding
  13516. * between the edges of its container
  13517. */
  13518. padding: 5,
  13519. /**
  13520. * @prop {String|HTMLElement} boundariesElement='scrollParent'
  13521. * Boundaries used by the modifier. Can be `scrollParent`, `window`,
  13522. * `viewport` or any DOM element.
  13523. */
  13524. boundariesElement: 'scrollParent'
  13525. },
  13526. /**
  13527. * Modifier used to make sure the reference and its popper stay near each other
  13528. * without leaving any gap between the two. Especially useful when the arrow is
  13529. * enabled and you want to ensure that it points to its reference element.
  13530. * It cares only about the first axis. You can still have poppers with margin
  13531. * between the popper and its reference element.
  13532. * @memberof modifiers
  13533. * @inner
  13534. */
  13535. keepTogether: {
  13536. /** @prop {number} order=400 - Index used to define the order of execution */
  13537. order: 400,
  13538. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13539. enabled: true,
  13540. /** @prop {ModifierFn} */
  13541. fn: keepTogether
  13542. },
  13543. /**
  13544. * This modifier is used to move the `arrowElement` of the popper to make
  13545. * sure it is positioned between the reference element and its popper element.
  13546. * It will read the outer size of the `arrowElement` node to detect how many
  13547. * pixels of conjunction are needed.
  13548. *
  13549. * It has no effect if no `arrowElement` is provided.
  13550. * @memberof modifiers
  13551. * @inner
  13552. */
  13553. arrow: {
  13554. /** @prop {number} order=500 - Index used to define the order of execution */
  13555. order: 500,
  13556. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13557. enabled: true,
  13558. /** @prop {ModifierFn} */
  13559. fn: arrow,
  13560. /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
  13561. element: '[x-arrow]'
  13562. },
  13563. /**
  13564. * Modifier used to flip the popper's placement when it starts to overlap its
  13565. * reference element.
  13566. *
  13567. * Requires the `preventOverflow` modifier before it in order to work.
  13568. *
  13569. * **NOTE:** this modifier will interrupt the current update cycle and will
  13570. * restart it if it detects the need to flip the placement.
  13571. * @memberof modifiers
  13572. * @inner
  13573. */
  13574. flip: {
  13575. /** @prop {number} order=600 - Index used to define the order of execution */
  13576. order: 600,
  13577. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13578. enabled: true,
  13579. /** @prop {ModifierFn} */
  13580. fn: flip,
  13581. /**
  13582. * @prop {String|Array} behavior='flip'
  13583. * The behavior used to change the popper's placement. It can be one of
  13584. * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
  13585. * placements (with optional variations)
  13586. */
  13587. behavior: 'flip',
  13588. /**
  13589. * @prop {number} padding=5
  13590. * The popper will flip if it hits the edges of the `boundariesElement`
  13591. */
  13592. padding: 5,
  13593. /**
  13594. * @prop {String|HTMLElement} boundariesElement='viewport'
  13595. * The element which will define the boundaries of the popper position.
  13596. * The popper will never be placed outside of the defined boundaries
  13597. * (except if `keepTogether` is enabled)
  13598. */
  13599. boundariesElement: 'viewport'
  13600. },
  13601. /**
  13602. * Modifier used to make the popper flow toward the inner of the reference element.
  13603. * By default, when this modifier is disabled, the popper will be placed outside
  13604. * the reference element.
  13605. * @memberof modifiers
  13606. * @inner
  13607. */
  13608. inner: {
  13609. /** @prop {number} order=700 - Index used to define the order of execution */
  13610. order: 700,
  13611. /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
  13612. enabled: false,
  13613. /** @prop {ModifierFn} */
  13614. fn: inner
  13615. },
  13616. /**
  13617. * Modifier used to hide the popper when its reference element is outside of the
  13618. * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
  13619. * be used to hide with a CSS selector the popper when its reference is
  13620. * out of boundaries.
  13621. *
  13622. * Requires the `preventOverflow` modifier before it in order to work.
  13623. * @memberof modifiers
  13624. * @inner
  13625. */
  13626. hide: {
  13627. /** @prop {number} order=800 - Index used to define the order of execution */
  13628. order: 800,
  13629. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13630. enabled: true,
  13631. /** @prop {ModifierFn} */
  13632. fn: hide
  13633. },
  13634. /**
  13635. * Computes the style that will be applied to the popper element to gets
  13636. * properly positioned.
  13637. *
  13638. * Note that this modifier will not touch the DOM, it just prepares the styles
  13639. * so that `applyStyle` modifier can apply it. This separation is useful
  13640. * in case you need to replace `applyStyle` with a custom implementation.
  13641. *
  13642. * This modifier has `850` as `order` value to maintain backward compatibility
  13643. * with previous versions of Popper.js. Expect the modifiers ordering method
  13644. * to change in future major versions of the library.
  13645. *
  13646. * @memberof modifiers
  13647. * @inner
  13648. */
  13649. computeStyle: {
  13650. /** @prop {number} order=850 - Index used to define the order of execution */
  13651. order: 850,
  13652. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13653. enabled: true,
  13654. /** @prop {ModifierFn} */
  13655. fn: computeStyle,
  13656. /**
  13657. * @prop {Boolean} gpuAcceleration=true
  13658. * If true, it uses the CSS 3D transformation to position the popper.
  13659. * Otherwise, it will use the `top` and `left` properties
  13660. */
  13661. gpuAcceleration: true,
  13662. /**
  13663. * @prop {string} [x='bottom']
  13664. * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
  13665. * Change this if your popper should grow in a direction different from `bottom`
  13666. */
  13667. x: 'bottom',
  13668. /**
  13669. * @prop {string} [x='left']
  13670. * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
  13671. * Change this if your popper should grow in a direction different from `right`
  13672. */
  13673. y: 'right'
  13674. },
  13675. /**
  13676. * Applies the computed styles to the popper element.
  13677. *
  13678. * All the DOM manipulations are limited to this modifier. This is useful in case
  13679. * you want to integrate Popper.js inside a framework or view library and you
  13680. * want to delegate all the DOM manipulations to it.
  13681. *
  13682. * Note that if you disable this modifier, you must make sure the popper element
  13683. * has its position set to `absolute` before Popper.js can do its work!
  13684. *
  13685. * Just disable this modifier and define your own to achieve the desired effect.
  13686. *
  13687. * @memberof modifiers
  13688. * @inner
  13689. */
  13690. applyStyle: {
  13691. /** @prop {number} order=900 - Index used to define the order of execution */
  13692. order: 900,
  13693. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13694. enabled: true,
  13695. /** @prop {ModifierFn} */
  13696. fn: applyStyle,
  13697. /** @prop {Function} */
  13698. onLoad: applyStyleOnLoad,
  13699. /**
  13700. * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
  13701. * @prop {Boolean} gpuAcceleration=true
  13702. * If true, it uses the CSS 3D transformation to position the popper.
  13703. * Otherwise, it will use the `top` and `left` properties
  13704. */
  13705. gpuAcceleration: undefined
  13706. }
  13707. };
  13708. /**
  13709. * The `dataObject` is an object containing all the information used by Popper.js.
  13710. * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
  13711. * @name dataObject
  13712. * @property {Object} data.instance The Popper.js instance
  13713. * @property {String} data.placement Placement applied to popper
  13714. * @property {String} data.originalPlacement Placement originally defined on init
  13715. * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
  13716. * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
  13717. * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
  13718. * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
  13719. * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
  13720. * @property {Object} data.boundaries Offsets of the popper boundaries
  13721. * @property {Object} data.offsets The measurements of popper, reference and arrow elements
  13722. * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
  13723. * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
  13724. * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
  13725. */
  13726. /**
  13727. * Default options provided to Popper.js constructor.<br />
  13728. * These can be overridden using the `options` argument of Popper.js.<br />
  13729. * To override an option, simply pass an object with the same
  13730. * structure of the `options` object, as the 3rd argument. For example:
  13731. * ```
  13732. * new Popper(ref, pop, {
  13733. * modifiers: {
  13734. * preventOverflow: { enabled: false }
  13735. * }
  13736. * })
  13737. * ```
  13738. * @type {Object}
  13739. * @static
  13740. * @memberof Popper
  13741. */
  13742. var Defaults = {
  13743. /**
  13744. * Popper's placement.
  13745. * @prop {Popper.placements} placement='bottom'
  13746. */
  13747. placement: 'bottom',
  13748. /**
  13749. * Set this to true if you want popper to position it self in 'fixed' mode
  13750. * @prop {Boolean} positionFixed=false
  13751. */
  13752. positionFixed: false,
  13753. /**
  13754. * Whether events (resize, scroll) are initially enabled.
  13755. * @prop {Boolean} eventsEnabled=true
  13756. */
  13757. eventsEnabled: true,
  13758. /**
  13759. * Set to true if you want to automatically remove the popper when
  13760. * you call the `destroy` method.
  13761. * @prop {Boolean} removeOnDestroy=false
  13762. */
  13763. removeOnDestroy: false,
  13764. /**
  13765. * Callback called when the popper is created.<br />
  13766. * By default, it is set to no-op.<br />
  13767. * Access Popper.js instance with `data.instance`.
  13768. * @prop {onCreate}
  13769. */
  13770. onCreate: function onCreate() {},
  13771. /**
  13772. * Callback called when the popper is updated. This callback is not called
  13773. * on the initialization/creation of the popper, but only on subsequent
  13774. * updates.<br />
  13775. * By default, it is set to no-op.<br />
  13776. * Access Popper.js instance with `data.instance`.
  13777. * @prop {onUpdate}
  13778. */
  13779. onUpdate: function onUpdate() {},
  13780. /**
  13781. * List of modifiers used to modify the offsets before they are applied to the popper.
  13782. * They provide most of the functionalities of Popper.js.
  13783. * @prop {modifiers}
  13784. */
  13785. modifiers: modifiers
  13786. };
  13787. /**
  13788. * @callback onCreate
  13789. * @param {dataObject} data
  13790. */
  13791. /**
  13792. * @callback onUpdate
  13793. * @param {dataObject} data
  13794. */
  13795. // Utils
  13796. // Methods
  13797. var Popper = function () {
  13798. /**
  13799. * Creates a new Popper.js instance.
  13800. * @class Popper
  13801. * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
  13802. * @param {HTMLElement} popper - The HTML element used as the popper
  13803. * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
  13804. * @return {Object} instance - The generated Popper.js instance
  13805. */
  13806. function Popper(reference, popper) {
  13807. var _this = this;
  13808. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  13809. classCallCheck(this, Popper);
  13810. this.scheduleUpdate = function () {
  13811. return requestAnimationFrame(_this.update);
  13812. };
  13813. // make update() debounced, so that it only runs at most once-per-tick
  13814. this.update = debounce(this.update.bind(this));
  13815. // with {} we create a new object with the options inside it
  13816. this.options = _extends({}, Popper.Defaults, options);
  13817. // init state
  13818. this.state = {
  13819. isDestroyed: false,
  13820. isCreated: false,
  13821. scrollParents: []
  13822. };
  13823. // get reference and popper elements (allow jQuery wrappers)
  13824. this.reference = reference && reference.jquery ? reference[0] : reference;
  13825. this.popper = popper && popper.jquery ? popper[0] : popper;
  13826. // Deep merge modifiers options
  13827. this.options.modifiers = {};
  13828. Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
  13829. _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
  13830. });
  13831. // Refactoring modifiers' list (Object => Array)
  13832. this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
  13833. return _extends({
  13834. name: name
  13835. }, _this.options.modifiers[name]);
  13836. })
  13837. // sort the modifiers by order
  13838. .sort(function (a, b) {
  13839. return a.order - b.order;
  13840. });
  13841. // modifiers have the ability to execute arbitrary code when Popper.js get inited
  13842. // such code is executed in the same order of its modifier
  13843. // they could add new properties to their options configuration
  13844. // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
  13845. this.modifiers.forEach(function (modifierOptions) {
  13846. if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
  13847. modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
  13848. }
  13849. });
  13850. // fire the first update to position the popper in the right place
  13851. this.update();
  13852. var eventsEnabled = this.options.eventsEnabled;
  13853. if (eventsEnabled) {
  13854. // setup event listeners, they will take care of update the position in specific situations
  13855. this.enableEventListeners();
  13856. }
  13857. this.state.eventsEnabled = eventsEnabled;
  13858. }
  13859. // We can't use class properties because they don't get listed in the
  13860. // class prototype and break stuff like Sinon stubs
  13861. createClass(Popper, [{
  13862. key: 'update',
  13863. value: function update$$1() {
  13864. return update.call(this);
  13865. }
  13866. }, {
  13867. key: 'destroy',
  13868. value: function destroy$$1() {
  13869. return destroy.call(this);
  13870. }
  13871. }, {
  13872. key: 'enableEventListeners',
  13873. value: function enableEventListeners$$1() {
  13874. return enableEventListeners.call(this);
  13875. }
  13876. }, {
  13877. key: 'disableEventListeners',
  13878. value: function disableEventListeners$$1() {
  13879. return disableEventListeners.call(this);
  13880. }
  13881. /**
  13882. * Schedules an update. It will run on the next UI update available.
  13883. * @method scheduleUpdate
  13884. * @memberof Popper
  13885. */
  13886. /**
  13887. * Collection of utilities useful when writing custom modifiers.
  13888. * Starting from version 1.7, this method is available only if you
  13889. * include `popper-utils.js` before `popper.js`.
  13890. *
  13891. * **DEPRECATION**: This way to access PopperUtils is deprecated
  13892. * and will be removed in v2! Use the PopperUtils module directly instead.
  13893. * Due to the high instability of the methods contained in Utils, we can't
  13894. * guarantee them to follow semver. Use them at your own risk!
  13895. * @static
  13896. * @private
  13897. * @type {Object}
  13898. * @deprecated since version 1.8
  13899. * @member Utils
  13900. * @memberof Popper
  13901. */
  13902. }]);
  13903. return Popper;
  13904. }();
  13905. /**
  13906. * The `referenceObject` is an object that provides an interface compatible with Popper.js
  13907. * and lets you use it as replacement of a real DOM node.<br />
  13908. * You can use this method to position a popper relatively to a set of coordinates
  13909. * in case you don't have a DOM node to use as reference.
  13910. *
  13911. * ```
  13912. * new Popper(referenceObject, popperNode);
  13913. * ```
  13914. *
  13915. * NB: This feature isn't supported in Internet Explorer 10.
  13916. * @name referenceObject
  13917. * @property {Function} data.getBoundingClientRect
  13918. * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
  13919. * @property {number} data.clientWidth
  13920. * An ES6 getter that will return the width of the virtual reference element.
  13921. * @property {number} data.clientHeight
  13922. * An ES6 getter that will return the height of the virtual reference element.
  13923. */
  13924. Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
  13925. Popper.placements = placements;
  13926. Popper.Defaults = Defaults;
  13927. /* harmony default export */ __webpack_exports__["default"] = (Popper);
  13928. //# sourceMappingURL=popper.js.map
  13929. /* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(4)))
  13930. /***/ }),
  13931. /* 4 */
  13932. /***/ (function(module, exports) {
  13933. var g;
  13934. // This works in non-strict mode
  13935. g = (function() {
  13936. return this;
  13937. })();
  13938. try {
  13939. // This works if eval is allowed (see CSP)
  13940. g = g || Function("return this")() || (1,eval)("this");
  13941. } catch(e) {
  13942. // This works if the window reference is available
  13943. if(typeof window === "object")
  13944. g = window;
  13945. }
  13946. // g can still be undefined, but nothing to do about it...
  13947. // We return undefined, instead of nothing here, so it's
  13948. // easier to handle this case. if(!global) { ...}
  13949. module.exports = g;
  13950. /***/ }),
  13951. /* 5 */
  13952. /***/ (function(module, exports, __webpack_require__) {
  13953. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  13954. * Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
  13955. *
  13956. * Copyright 2013-2017 bootstrap-select
  13957. * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
  13958. */
  13959. (function (root, factory) {
  13960. if (true) {
  13961. // AMD. Register as an anonymous module unless amdModuleId is set
  13962. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = function (a0) {
  13963. return (factory(a0));
  13964. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  13965. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  13966. } else if (typeof module === 'object' && module.exports) {
  13967. // Node. Does not work with strict CommonJS, but
  13968. // only CommonJS-like environments that support module.exports,
  13969. // like Node.
  13970. module.exports = factory(require("jquery"));
  13971. } else {
  13972. factory(root["jQuery"]);
  13973. }
  13974. }(this, function (jQuery) {
  13975. (function ($) {
  13976. 'use strict';
  13977. //<editor-fold desc="Shims">
  13978. if (!String.prototype.includes) {
  13979. (function () {
  13980. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  13981. var toString = {}.toString;
  13982. var defineProperty = (function () {
  13983. // IE 8 only supports `Object.defineProperty` on DOM elements
  13984. try {
  13985. var object = {};
  13986. var $defineProperty = Object.defineProperty;
  13987. var result = $defineProperty(object, object, object) && $defineProperty;
  13988. } catch (error) {
  13989. }
  13990. return result;
  13991. }());
  13992. var indexOf = ''.indexOf;
  13993. var includes = function (search) {
  13994. if (this == null) {
  13995. throw new TypeError();
  13996. }
  13997. var string = String(this);
  13998. if (search && toString.call(search) == '[object RegExp]') {
  13999. throw new TypeError();
  14000. }
  14001. var stringLength = string.length;
  14002. var searchString = String(search);
  14003. var searchLength = searchString.length;
  14004. var position = arguments.length > 1 ? arguments[1] : undefined;
  14005. // `ToInteger`
  14006. var pos = position ? Number(position) : 0;
  14007. if (pos != pos) { // better `isNaN`
  14008. pos = 0;
  14009. }
  14010. var start = Math.min(Math.max(pos, 0), stringLength);
  14011. // Avoid the `indexOf` call if no match is possible
  14012. if (searchLength + start > stringLength) {
  14013. return false;
  14014. }
  14015. return indexOf.call(string, searchString, pos) != -1;
  14016. };
  14017. if (defineProperty) {
  14018. defineProperty(String.prototype, 'includes', {
  14019. 'value': includes,
  14020. 'configurable': true,
  14021. 'writable': true
  14022. });
  14023. } else {
  14024. String.prototype.includes = includes;
  14025. }
  14026. }());
  14027. }
  14028. if (!String.prototype.startsWith) {
  14029. (function () {
  14030. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  14031. var defineProperty = (function () {
  14032. // IE 8 only supports `Object.defineProperty` on DOM elements
  14033. try {
  14034. var object = {};
  14035. var $defineProperty = Object.defineProperty;
  14036. var result = $defineProperty(object, object, object) && $defineProperty;
  14037. } catch (error) {
  14038. }
  14039. return result;
  14040. }());
  14041. var toString = {}.toString;
  14042. var startsWith = function (search) {
  14043. if (this == null) {
  14044. throw new TypeError();
  14045. }
  14046. var string = String(this);
  14047. if (search && toString.call(search) == '[object RegExp]') {
  14048. throw new TypeError();
  14049. }
  14050. var stringLength = string.length;
  14051. var searchString = String(search);
  14052. var searchLength = searchString.length;
  14053. var position = arguments.length > 1 ? arguments[1] : undefined;
  14054. // `ToInteger`
  14055. var pos = position ? Number(position) : 0;
  14056. if (pos != pos) { // better `isNaN`
  14057. pos = 0;
  14058. }
  14059. var start = Math.min(Math.max(pos, 0), stringLength);
  14060. // Avoid the `indexOf` call if no match is possible
  14061. if (searchLength + start > stringLength) {
  14062. return false;
  14063. }
  14064. var index = -1;
  14065. while (++index < searchLength) {
  14066. if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
  14067. return false;
  14068. }
  14069. }
  14070. return true;
  14071. };
  14072. if (defineProperty) {
  14073. defineProperty(String.prototype, 'startsWith', {
  14074. 'value': startsWith,
  14075. 'configurable': true,
  14076. 'writable': true
  14077. });
  14078. } else {
  14079. String.prototype.startsWith = startsWith;
  14080. }
  14081. }());
  14082. }
  14083. if (!Object.keys) {
  14084. Object.keys = function (
  14085. o, // object
  14086. k, // key
  14087. r // result array
  14088. ){
  14089. // initialize object and result
  14090. r=[];
  14091. // iterate over object keys
  14092. for (k in o)
  14093. // fill result array with non-prototypical keys
  14094. r.hasOwnProperty.call(o, k) && r.push(k);
  14095. // return result
  14096. return r;
  14097. };
  14098. }
  14099. // set data-selected on select element if the value has been programmatically selected
  14100. // prior to initialization of bootstrap-select
  14101. // * consider removing or replacing an alternative method *
  14102. var valHooks = {
  14103. useDefault: false,
  14104. _set: $.valHooks.select.set
  14105. };
  14106. $.valHooks.select.set = function(elem, value) {
  14107. if (value && !valHooks.useDefault) $(elem).data('selected', true);
  14108. return valHooks._set.apply(this, arguments);
  14109. };
  14110. var changed_arguments = null;
  14111. var EventIsSupported = (function() {
  14112. try {
  14113. new Event('change');
  14114. return true;
  14115. } catch (e) {
  14116. return false;
  14117. }
  14118. })();
  14119. $.fn.triggerNative = function (eventName) {
  14120. var el = this[0],
  14121. event;
  14122. if (el.dispatchEvent) { // for modern browsers & IE9+
  14123. if (EventIsSupported) {
  14124. // For modern browsers
  14125. event = new Event(eventName, {
  14126. bubbles: true
  14127. });
  14128. } else {
  14129. // For IE since it doesn't support Event constructor
  14130. event = document.createEvent('Event');
  14131. event.initEvent(eventName, true, false);
  14132. }
  14133. el.dispatchEvent(event);
  14134. } else if (el.fireEvent) { // for IE8
  14135. event = document.createEventObject();
  14136. event.eventType = eventName;
  14137. el.fireEvent('on' + eventName, event);
  14138. } else {
  14139. // fall back to jQuery.trigger
  14140. this.trigger(eventName);
  14141. }
  14142. };
  14143. //</editor-fold>
  14144. // Case insensitive contains search
  14145. $.expr.pseudos.icontains = function (obj, index, meta) {
  14146. var $obj = $(obj).find('a');
  14147. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  14148. return haystack.includes(meta[3].toUpperCase());
  14149. };
  14150. // Case insensitive begins search
  14151. $.expr.pseudos.ibegins = function (obj, index, meta) {
  14152. var $obj = $(obj).find('a');
  14153. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  14154. return haystack.startsWith(meta[3].toUpperCase());
  14155. };
  14156. // Case and accent insensitive contains search
  14157. $.expr.pseudos.aicontains = function (obj, index, meta) {
  14158. var $obj = $(obj).find('a');
  14159. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  14160. return haystack.includes(meta[3].toUpperCase());
  14161. };
  14162. // Case and accent insensitive begins search
  14163. $.expr.pseudos.aibegins = function (obj, index, meta) {
  14164. var $obj = $(obj).find('a');
  14165. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  14166. return haystack.startsWith(meta[3].toUpperCase());
  14167. };
  14168. /**
  14169. * Remove all diatrics from the given text.
  14170. * @access private
  14171. * @param {String} text
  14172. * @returns {String}
  14173. */
  14174. function normalizeToBase(text) {
  14175. var rExps = [
  14176. {re: /[\xC0-\xC6]/g, ch: "A"},
  14177. {re: /[\xE0-\xE6]/g, ch: "a"},
  14178. {re: /[\xC8-\xCB]/g, ch: "E"},
  14179. {re: /[\xE8-\xEB]/g, ch: "e"},
  14180. {re: /[\xCC-\xCF]/g, ch: "I"},
  14181. {re: /[\xEC-\xEF]/g, ch: "i"},
  14182. {re: /[\xD2-\xD6]/g, ch: "O"},
  14183. {re: /[\xF2-\xF6]/g, ch: "o"},
  14184. {re: /[\xD9-\xDC]/g, ch: "U"},
  14185. {re: /[\xF9-\xFC]/g, ch: "u"},
  14186. {re: /[\xC7-\xE7]/g, ch: "c"},
  14187. {re: /[\xD1]/g, ch: "N"},
  14188. {re: /[\xF1]/g, ch: "n"}
  14189. ];
  14190. $.each(rExps, function () {
  14191. text = text ? text.replace(this.re, this.ch) : '';
  14192. });
  14193. return text;
  14194. }
  14195. // List of HTML entities for escaping.
  14196. var escapeMap = {
  14197. '&': '&amp;',
  14198. '<': '&lt;',
  14199. '>': '&gt;',
  14200. '"': '&quot;',
  14201. "'": '&#x27;',
  14202. '`': '&#x60;'
  14203. };
  14204. var unescapeMap = {
  14205. '&amp;': '&',
  14206. '&lt;': '<',
  14207. '&gt;': '>',
  14208. '&quot;': '"',
  14209. '&#x27;': "'",
  14210. '&#x60;': '`'
  14211. };
  14212. // Functions for escaping and unescaping strings to/from HTML interpolation.
  14213. var createEscaper = function(map) {
  14214. var escaper = function(match) {
  14215. return map[match];
  14216. };
  14217. // Regexes for identifying a key that needs to be escaped.
  14218. var source = '(?:' + Object.keys(map).join('|') + ')';
  14219. var testRegexp = RegExp(source);
  14220. var replaceRegexp = RegExp(source, 'g');
  14221. return function(string) {
  14222. string = string == null ? '' : '' + string;
  14223. return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
  14224. };
  14225. };
  14226. var htmlEscape = createEscaper(escapeMap);
  14227. var htmlUnescape = createEscaper(unescapeMap);
  14228. var Selectpicker = function (element, options) {
  14229. // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
  14230. if (!valHooks.useDefault) {
  14231. $.valHooks.select.set = valHooks._set;
  14232. valHooks.useDefault = true;
  14233. }
  14234. this.$element = $(element);
  14235. this.$newElement = null;
  14236. this.$button = null;
  14237. this.$menu = null;
  14238. this.$lis = null;
  14239. this.options = options;
  14240. // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
  14241. // data-attribute)
  14242. if (this.options.title === null) {
  14243. this.options.title = this.$element.attr('title');
  14244. }
  14245. // Format window padding
  14246. var winPad = this.options.windowPadding;
  14247. if (typeof winPad === 'number') {
  14248. this.options.windowPadding = [winPad, winPad, winPad, winPad];
  14249. }
  14250. //Expose public methods
  14251. this.val = Selectpicker.prototype.val;
  14252. this.render = Selectpicker.prototype.render;
  14253. this.refresh = Selectpicker.prototype.refresh;
  14254. this.setStyle = Selectpicker.prototype.setStyle;
  14255. this.selectAll = Selectpicker.prototype.selectAll;
  14256. this.deselectAll = Selectpicker.prototype.deselectAll;
  14257. this.destroy = Selectpicker.prototype.destroy;
  14258. this.remove = Selectpicker.prototype.remove;
  14259. this.show = Selectpicker.prototype.show;
  14260. this.hide = Selectpicker.prototype.hide;
  14261. this.init();
  14262. };
  14263. Selectpicker.VERSION = '1.12.4';
  14264. // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
  14265. Selectpicker.DEFAULTS = {
  14266. noneSelectedText: 'Nothing selected',
  14267. noneResultsText: 'No results matched {0}',
  14268. countSelectedText: function (numSelected, numTotal) {
  14269. return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
  14270. },
  14271. maxOptionsText: function (numAll, numGroup) {
  14272. return [
  14273. (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
  14274. (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
  14275. ];
  14276. },
  14277. selectAllText: 'Select All',
  14278. deselectAllText: 'Deselect All',
  14279. doneButton: false,
  14280. doneButtonText: 'Close',
  14281. multipleSeparator: ', ',
  14282. styleBase: 'btn',
  14283. style: 'btn-default',
  14284. size: 'auto',
  14285. title: null,
  14286. selectedTextFormat: 'values',
  14287. width: false,
  14288. container: false,
  14289. hideDisabled: false,
  14290. showSubtext: false,
  14291. showIcon: true,
  14292. showContent: true,
  14293. dropupAuto: true,
  14294. header: false,
  14295. liveSearch: false,
  14296. liveSearchPlaceholder: null,
  14297. liveSearchNormalize: false,
  14298. liveSearchStyle: 'contains',
  14299. actionsBox: false,
  14300. iconBase: 'glyphicon',
  14301. tickIcon: 'glyphicon-ok',
  14302. showTick: false,
  14303. template: {
  14304. caret: '<span class="caret"></span>'
  14305. },
  14306. maxOptions: false,
  14307. mobile: false,
  14308. selectOnTab: false,
  14309. dropdownAlignRight: false,
  14310. windowPadding: 0
  14311. };
  14312. Selectpicker.prototype = {
  14313. constructor: Selectpicker,
  14314. init: function () {
  14315. var that = this,
  14316. id = this.$element.attr('id');
  14317. this.$element.addClass('bs-select-hidden');
  14318. // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
  14319. // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
  14320. this.liObj = {};
  14321. this.multiple = this.$element.prop('multiple');
  14322. this.autofocus = this.$element.prop('autofocus');
  14323. this.$newElement = this.createView();
  14324. this.$element
  14325. .after(this.$newElement)
  14326. .appendTo(this.$newElement);
  14327. this.$button = this.$newElement.children('button');
  14328. this.$menu = this.$newElement.children('.dropdown-menu');
  14329. this.$menuInner = this.$menu.children('.inner');
  14330. this.$searchbox = this.$menu.find('input');
  14331. this.$element.removeClass('bs-select-hidden');
  14332. if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
  14333. if (typeof id !== 'undefined') {
  14334. this.$button.attr('data-id', id);
  14335. $('label[for="' + id + '"]').click(function (e) {
  14336. e.preventDefault();
  14337. that.$button.focus();
  14338. });
  14339. }
  14340. this.checkDisabled();
  14341. this.clickListener();
  14342. if (this.options.liveSearch) this.liveSearchListener();
  14343. this.render();
  14344. this.setStyle();
  14345. this.setWidth();
  14346. if (this.options.container) this.selectPosition();
  14347. this.$menu.data('this', this);
  14348. this.$newElement.data('this', this);
  14349. if (this.options.mobile) this.mobile();
  14350. this.$newElement.on({
  14351. 'hide.bs.dropdown': function (e) {
  14352. that.$menuInner.attr('aria-expanded', false);
  14353. that.$element.trigger('hide.bs.select', e);
  14354. },
  14355. 'hidden.bs.dropdown': function (e) {
  14356. that.$element.trigger('hidden.bs.select', e);
  14357. },
  14358. 'show.bs.dropdown': function (e) {
  14359. that.$menuInner.attr('aria-expanded', true);
  14360. that.$element.trigger('show.bs.select', e);
  14361. },
  14362. 'shown.bs.dropdown': function (e) {
  14363. that.$element.trigger('shown.bs.select', e);
  14364. }
  14365. });
  14366. if (that.$element[0].hasAttribute('required')) {
  14367. this.$element.on('invalid', function () {
  14368. that.$button.addClass('bs-invalid');
  14369. that.$element.on({
  14370. 'focus.bs.select': function () {
  14371. that.$button.focus();
  14372. that.$element.off('focus.bs.select');
  14373. },
  14374. 'shown.bs.select': function () {
  14375. that.$element
  14376. .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
  14377. .off('shown.bs.select');
  14378. },
  14379. 'rendered.bs.select': function () {
  14380. // if select is no longer invalid, remove the bs-invalid class
  14381. if (this.validity.valid) that.$button.removeClass('bs-invalid');
  14382. that.$element.off('rendered.bs.select');
  14383. }
  14384. });
  14385. that.$button.on('blur.bs.select', function() {
  14386. that.$element.focus().blur();
  14387. that.$button.off('blur.bs.select');
  14388. });
  14389. });
  14390. }
  14391. setTimeout(function () {
  14392. that.$element.trigger('loaded.bs.select');
  14393. });
  14394. },
  14395. createDropdown: function () {
  14396. // Options
  14397. // If we are multiple or showTick option is set, then add the show-tick class
  14398. var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
  14399. inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
  14400. autofocus = this.autofocus ? ' autofocus' : '';
  14401. // Elements
  14402. var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
  14403. var searchbox = this.options.liveSearch ?
  14404. '<div class="bs-searchbox">' +
  14405. '<input type="text" class="form-control" autocomplete="off"' +
  14406. (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
  14407. '</div>'
  14408. : '';
  14409. var actionsbox = this.multiple && this.options.actionsBox ?
  14410. '<div class="bs-actionsbox">' +
  14411. '<div class="btn-group btn-group-sm btn-block">' +
  14412. '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
  14413. this.options.selectAllText +
  14414. '</button>' +
  14415. '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
  14416. this.options.deselectAllText +
  14417. '</button>' +
  14418. '</div>' +
  14419. '</div>'
  14420. : '';
  14421. var donebutton = this.multiple && this.options.doneButton ?
  14422. '<div class="bs-donebutton">' +
  14423. '<div class="btn-group btn-block">' +
  14424. '<button type="button" class="btn btn-sm btn-default">' +
  14425. this.options.doneButtonText +
  14426. '</button>' +
  14427. '</div>' +
  14428. '</div>'
  14429. : '';
  14430. var drop =
  14431. '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
  14432. '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
  14433. '<span class="filter-option pull-left"></span>&nbsp;' +
  14434. '<span class="bs-caret">' +
  14435. this.options.template.caret +
  14436. '</span>' +
  14437. '</button>' +
  14438. '<div class="dropdown-menu open" role="combobox">' +
  14439. header +
  14440. searchbox +
  14441. actionsbox +
  14442. '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
  14443. '</ul>' +
  14444. donebutton +
  14445. '</div>' +
  14446. '</div>';
  14447. return $(drop);
  14448. },
  14449. createView: function () {
  14450. var $drop = this.createDropdown(),
  14451. li = this.createLi();
  14452. $drop.find('ul')[0].innerHTML = li;
  14453. return $drop;
  14454. },
  14455. reloadLi: function () {
  14456. // rebuild
  14457. var li = this.createLi();
  14458. this.$menuInner[0].innerHTML = li;
  14459. },
  14460. createLi: function () {
  14461. var that = this,
  14462. _li = [],
  14463. optID = 0,
  14464. titleOption = document.createElement('option'),
  14465. liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
  14466. // Helper functions
  14467. /**
  14468. * @param content
  14469. * @param [index]
  14470. * @param [classes]
  14471. * @param [optgroup]
  14472. * @returns {string}
  14473. */
  14474. var generateLI = function (content, index, classes, optgroup) {
  14475. return '<li' +
  14476. ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
  14477. ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
  14478. ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
  14479. '>' + content + '</li>';
  14480. };
  14481. /**
  14482. * @param text
  14483. * @param [classes]
  14484. * @param [inline]
  14485. * @param [tokens]
  14486. * @returns {string}
  14487. */
  14488. var generateA = function (text, classes, inline, tokens) {
  14489. return '<a tabindex="0"' +
  14490. (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
  14491. (inline ? ' style="' + inline + '"' : '') +
  14492. (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
  14493. (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
  14494. ' role="option">' + text +
  14495. '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
  14496. '</a>';
  14497. };
  14498. if (this.options.title && !this.multiple) {
  14499. // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
  14500. // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
  14501. liIndex--;
  14502. if (!this.$element.find('.bs-title-option').length) {
  14503. // Use native JS to prepend option (faster)
  14504. var element = this.$element[0];
  14505. titleOption.className = 'bs-title-option';
  14506. titleOption.innerHTML = this.options.title;
  14507. titleOption.value = '';
  14508. element.insertBefore(titleOption, element.firstChild);
  14509. // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
  14510. // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
  14511. // if so, the select will have the data-selected attribute
  14512. var $opt = $(element.options[element.selectedIndex]);
  14513. if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
  14514. titleOption.selected = true;
  14515. }
  14516. }
  14517. }
  14518. var $selectOptions = this.$element.find('option');
  14519. $selectOptions.each(function (index) {
  14520. var $this = $(this);
  14521. liIndex++;
  14522. if ($this.hasClass('bs-title-option')) return;
  14523. // Get the class and text for the option
  14524. var optionClass = this.className || '',
  14525. inline = htmlEscape(this.style.cssText),
  14526. text = $this.data('content') ? $this.data('content') : $this.html(),
  14527. tokens = $this.data('tokens') ? $this.data('tokens') : null,
  14528. subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
  14529. icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
  14530. $parent = $this.parent(),
  14531. isOptgroup = $parent[0].tagName === 'OPTGROUP',
  14532. isOptgroupDisabled = isOptgroup && $parent[0].disabled,
  14533. isDisabled = this.disabled || isOptgroupDisabled,
  14534. prevHiddenIndex;
  14535. if (icon !== '' && isDisabled) {
  14536. icon = '<span>' + icon + '</span>';
  14537. }
  14538. if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
  14539. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  14540. // used to determine whether or not a divider should be placed after an optgroup if there are
  14541. // hidden options between the optgroup and the first visible option
  14542. prevHiddenIndex = $this.data('prevHiddenIndex');
  14543. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  14544. liIndex--;
  14545. return;
  14546. }
  14547. if (!$this.data('content')) {
  14548. // Prepend any icon and append any subtext to the main text.
  14549. text = icon + '<span class="text">' + text + subtext + '</span>';
  14550. }
  14551. if (isOptgroup && $this.data('divider') !== true) {
  14552. if (that.options.hideDisabled && isDisabled) {
  14553. if ($parent.data('allOptionsDisabled') === undefined) {
  14554. var $options = $parent.children();
  14555. $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
  14556. }
  14557. if ($parent.data('allOptionsDisabled')) {
  14558. liIndex--;
  14559. return;
  14560. }
  14561. }
  14562. var optGroupClass = ' ' + $parent[0].className || '';
  14563. if ($this.index() === 0) { // Is it the first option of the optgroup?
  14564. optID += 1;
  14565. // Get the opt group label
  14566. var label = $parent[0].label,
  14567. labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
  14568. labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
  14569. label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
  14570. if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
  14571. liIndex++;
  14572. _li.push(generateLI('', null, 'divider', optID + 'div'));
  14573. }
  14574. liIndex++;
  14575. _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
  14576. }
  14577. if (that.options.hideDisabled && isDisabled) {
  14578. liIndex--;
  14579. return;
  14580. }
  14581. _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
  14582. } else if ($this.data('divider') === true) {
  14583. _li.push(generateLI('', index, 'divider'));
  14584. } else if ($this.data('hidden') === true) {
  14585. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  14586. // used to determine whether or not a divider should be placed after an optgroup if there are
  14587. // hidden options between the optgroup and the first visible option
  14588. prevHiddenIndex = $this.data('prevHiddenIndex');
  14589. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  14590. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
  14591. } else {
  14592. var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
  14593. // if previous element is not an optgroup and hideDisabled is true
  14594. if (!showDivider && that.options.hideDisabled) {
  14595. prevHiddenIndex = $this.data('prevHiddenIndex');
  14596. if (prevHiddenIndex !== undefined) {
  14597. // select the element **before** the first hidden element in the group
  14598. var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
  14599. if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
  14600. showDivider = true;
  14601. }
  14602. }
  14603. }
  14604. if (showDivider) {
  14605. liIndex++;
  14606. _li.push(generateLI('', null, 'divider', optID + 'div'));
  14607. }
  14608. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
  14609. }
  14610. that.liObj[index] = liIndex;
  14611. });
  14612. //If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
  14613. if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
  14614. this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
  14615. }
  14616. return _li.join('');
  14617. },
  14618. findLis: function () {
  14619. if (this.$lis == null) this.$lis = this.$menu.find('li');
  14620. return this.$lis;
  14621. },
  14622. /**
  14623. * @param [updateLi] defaults to true
  14624. */
  14625. render: function (updateLi) {
  14626. var that = this,
  14627. notDisabled,
  14628. $selectOptions = this.$element.find('option');
  14629. //Update the LI to match the SELECT
  14630. if (updateLi !== false) {
  14631. $selectOptions.each(function (index) {
  14632. var $lis = that.findLis().eq(that.liObj[index]);
  14633. that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
  14634. that.setSelected(index, this.selected, $lis);
  14635. });
  14636. }
  14637. this.togglePlaceholder();
  14638. this.tabIndex();
  14639. var selectedItems = $selectOptions.map(function () {
  14640. if (this.selected) {
  14641. if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
  14642. var $this = $(this),
  14643. icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
  14644. subtext;
  14645. if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
  14646. subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
  14647. } else {
  14648. subtext = '';
  14649. }
  14650. if (typeof $this.attr('title') !== 'undefined') {
  14651. return $this.attr('title');
  14652. } else if ($this.data('content') && that.options.showContent) {
  14653. return $this.data('content').toString();
  14654. } else {
  14655. return icon + $this.html() + subtext;
  14656. }
  14657. }
  14658. }).toArray();
  14659. //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
  14660. //Convert all the values into a comma delimited string
  14661. var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
  14662. //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
  14663. if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
  14664. var max = this.options.selectedTextFormat.split('>');
  14665. if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
  14666. notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
  14667. var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
  14668. tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
  14669. title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
  14670. }
  14671. }
  14672. if (this.options.title == undefined) {
  14673. this.options.title = this.$element.attr('title');
  14674. }
  14675. if (this.options.selectedTextFormat == 'static') {
  14676. title = this.options.title;
  14677. }
  14678. //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
  14679. if (!title) {
  14680. title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
  14681. }
  14682. //strip all HTML tags and trim the result, then unescape any escaped tags
  14683. this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
  14684. this.$button.children('.filter-option').html(title);
  14685. this.$element.trigger('rendered.bs.select');
  14686. },
  14687. /**
  14688. * @param [style]
  14689. * @param [status]
  14690. */
  14691. setStyle: function (style, status) {
  14692. if (this.$element.attr('class')) {
  14693. this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
  14694. }
  14695. var buttonClass = style ? style : this.options.style;
  14696. if (status == 'add') {
  14697. this.$button.addClass(buttonClass);
  14698. } else if (status == 'remove') {
  14699. this.$button.removeClass(buttonClass);
  14700. } else {
  14701. this.$button.removeClass(this.options.style);
  14702. this.$button.addClass(buttonClass);
  14703. }
  14704. },
  14705. liHeight: function (refresh) {
  14706. if (!refresh && (this.options.size === false || this.sizeInfo)) return;
  14707. var newElement = document.createElement('div'),
  14708. menu = document.createElement('div'),
  14709. menuInner = document.createElement('ul'),
  14710. divider = document.createElement('li'),
  14711. li = document.createElement('li'),
  14712. a = document.createElement('a'),
  14713. text = document.createElement('span'),
  14714. header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
  14715. search = this.options.liveSearch ? document.createElement('div') : null,
  14716. actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
  14717. doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
  14718. text.className = 'text';
  14719. newElement.className = this.$menu[0].parentNode.className + ' open';
  14720. menu.className = 'dropdown-menu open';
  14721. menuInner.className = 'dropdown-menu inner';
  14722. divider.className = 'divider';
  14723. text.appendChild(document.createTextNode('Inner text'));
  14724. a.appendChild(text);
  14725. li.appendChild(a);
  14726. menuInner.appendChild(li);
  14727. menuInner.appendChild(divider);
  14728. if (header) menu.appendChild(header);
  14729. if (search) {
  14730. var input = document.createElement('input');
  14731. search.className = 'bs-searchbox';
  14732. input.className = 'form-control';
  14733. search.appendChild(input);
  14734. menu.appendChild(search);
  14735. }
  14736. if (actions) menu.appendChild(actions);
  14737. menu.appendChild(menuInner);
  14738. if (doneButton) menu.appendChild(doneButton);
  14739. newElement.appendChild(menu);
  14740. document.body.appendChild(newElement);
  14741. var liHeight = a.offsetHeight,
  14742. headerHeight = header ? header.offsetHeight : 0,
  14743. searchHeight = search ? search.offsetHeight : 0,
  14744. actionsHeight = actions ? actions.offsetHeight : 0,
  14745. doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
  14746. dividerHeight = $(divider).outerHeight(true),
  14747. // fall back to jQuery if getComputedStyle is not supported
  14748. menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
  14749. $menu = menuStyle ? null : $(menu),
  14750. menuPadding = {
  14751. vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
  14752. parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
  14753. parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
  14754. parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
  14755. horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
  14756. parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
  14757. parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
  14758. parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
  14759. },
  14760. menuExtras = {
  14761. vert: menuPadding.vert +
  14762. parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
  14763. parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
  14764. horiz: menuPadding.horiz +
  14765. parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
  14766. parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
  14767. }
  14768. document.body.removeChild(newElement);
  14769. this.sizeInfo = {
  14770. liHeight: liHeight,
  14771. headerHeight: headerHeight,
  14772. searchHeight: searchHeight,
  14773. actionsHeight: actionsHeight,
  14774. doneButtonHeight: doneButtonHeight,
  14775. dividerHeight: dividerHeight,
  14776. menuPadding: menuPadding,
  14777. menuExtras: menuExtras
  14778. };
  14779. },
  14780. setSize: function () {
  14781. this.findLis();
  14782. this.liHeight();
  14783. if (this.options.header) this.$menu.css('padding-top', 0);
  14784. if (this.options.size === false) return;
  14785. var that = this,
  14786. $menu = this.$menu,
  14787. $menuInner = this.$menuInner,
  14788. $window = $(window),
  14789. selectHeight = this.$newElement[0].offsetHeight,
  14790. selectWidth = this.$newElement[0].offsetWidth,
  14791. liHeight = this.sizeInfo['liHeight'],
  14792. headerHeight = this.sizeInfo['headerHeight'],
  14793. searchHeight = this.sizeInfo['searchHeight'],
  14794. actionsHeight = this.sizeInfo['actionsHeight'],
  14795. doneButtonHeight = this.sizeInfo['doneButtonHeight'],
  14796. divHeight = this.sizeInfo['dividerHeight'],
  14797. menuPadding = this.sizeInfo['menuPadding'],
  14798. menuExtras = this.sizeInfo['menuExtras'],
  14799. notDisabled = this.options.hideDisabled ? '.disabled' : '',
  14800. menuHeight,
  14801. menuWidth,
  14802. getHeight,
  14803. getWidth,
  14804. selectOffsetTop,
  14805. selectOffsetBot,
  14806. selectOffsetLeft,
  14807. selectOffsetRight,
  14808. getPos = function() {
  14809. var pos = that.$newElement.offset(),
  14810. $container = $(that.options.container),
  14811. containerPos;
  14812. if (that.options.container && !$container.is('body')) {
  14813. containerPos = $container.offset();
  14814. containerPos.top += parseInt($container.css('borderTopWidth'));
  14815. containerPos.left += parseInt($container.css('borderLeftWidth'));
  14816. } else {
  14817. containerPos = { top: 0, left: 0 };
  14818. }
  14819. var winPad = that.options.windowPadding;
  14820. selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
  14821. selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
  14822. selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
  14823. selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
  14824. selectOffsetTop -= winPad[0];
  14825. selectOffsetLeft -= winPad[3];
  14826. };
  14827. getPos();
  14828. if (this.options.size === 'auto') {
  14829. var getSize = function () {
  14830. var minHeight,
  14831. hasClass = function (className, include) {
  14832. return function (element) {
  14833. if (include) {
  14834. return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  14835. } else {
  14836. return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  14837. }
  14838. };
  14839. },
  14840. lis = that.$menuInner[0].getElementsByTagName('li'),
  14841. lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
  14842. optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
  14843. getPos();
  14844. menuHeight = selectOffsetBot - menuExtras.vert;
  14845. menuWidth = selectOffsetRight - menuExtras.horiz;
  14846. if (that.options.container) {
  14847. if (!$menu.data('height')) $menu.data('height', $menu.height());
  14848. getHeight = $menu.data('height');
  14849. if (!$menu.data('width')) $menu.data('width', $menu.width());
  14850. getWidth = $menu.data('width');
  14851. } else {
  14852. getHeight = $menu.height();
  14853. getWidth = $menu.width();
  14854. }
  14855. if (that.options.dropupAuto) {
  14856. that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  14857. }
  14858. if (that.$newElement.hasClass('dropup')) {
  14859. menuHeight = selectOffsetTop - menuExtras.vert;
  14860. }
  14861. if (that.options.dropdownAlignRight === 'auto') {
  14862. $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
  14863. }
  14864. if ((lisVisible.length + optGroup.length) > 3) {
  14865. minHeight = liHeight * 3 + menuExtras.vert - 2;
  14866. } else {
  14867. minHeight = 0;
  14868. }
  14869. $menu.css({
  14870. 'max-height': menuHeight + 'px',
  14871. 'overflow': 'hidden',
  14872. 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
  14873. });
  14874. $menuInner.css({
  14875. 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
  14876. 'overflow-y': 'auto',
  14877. 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
  14878. });
  14879. };
  14880. getSize();
  14881. this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
  14882. $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
  14883. } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
  14884. var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
  14885. divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
  14886. menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
  14887. if (that.options.container) {
  14888. if (!$menu.data('height')) $menu.data('height', $menu.height());
  14889. getHeight = $menu.data('height');
  14890. } else {
  14891. getHeight = $menu.height();
  14892. }
  14893. if (that.options.dropupAuto) {
  14894. //noinspection JSUnusedAssignment
  14895. this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  14896. }
  14897. $menu.css({
  14898. 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
  14899. 'overflow': 'hidden',
  14900. 'min-height': ''
  14901. });
  14902. $menuInner.css({
  14903. 'max-height': menuHeight - menuPadding.vert + 'px',
  14904. 'overflow-y': 'auto',
  14905. 'min-height': ''
  14906. });
  14907. }
  14908. },
  14909. setWidth: function () {
  14910. if (this.options.width === 'auto') {
  14911. this.$menu.css('min-width', '0');
  14912. // Get correct width if element is hidden
  14913. var $selectClone = this.$menu.parent().clone().appendTo('body'),
  14914. $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
  14915. ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
  14916. btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
  14917. $selectClone.remove();
  14918. $selectClone2.remove();
  14919. // Set width to whatever's larger, button title or longest option
  14920. this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
  14921. } else if (this.options.width === 'fit') {
  14922. // Remove inline min-width so width can be changed from 'auto'
  14923. this.$menu.css('min-width', '');
  14924. this.$newElement.css('width', '').addClass('fit-width');
  14925. } else if (this.options.width) {
  14926. // Remove inline min-width so width can be changed from 'auto'
  14927. this.$menu.css('min-width', '');
  14928. this.$newElement.css('width', this.options.width);
  14929. } else {
  14930. // Remove inline min-width/width so width can be changed
  14931. this.$menu.css('min-width', '');
  14932. this.$newElement.css('width', '');
  14933. }
  14934. // Remove fit-width class if width is changed programmatically
  14935. if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
  14936. this.$newElement.removeClass('fit-width');
  14937. }
  14938. },
  14939. selectPosition: function () {
  14940. this.$bsContainer = $('<div class="bs-container" />');
  14941. var that = this,
  14942. $container = $(this.options.container),
  14943. pos,
  14944. containerPos,
  14945. actualHeight,
  14946. getPlacement = function ($element) {
  14947. that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
  14948. pos = $element.offset();
  14949. if (!$container.is('body')) {
  14950. containerPos = $container.offset();
  14951. containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
  14952. containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
  14953. } else {
  14954. containerPos = { top: 0, left: 0 };
  14955. }
  14956. actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
  14957. that.$bsContainer.css({
  14958. 'top': pos.top - containerPos.top + actualHeight,
  14959. 'left': pos.left - containerPos.left,
  14960. 'width': $element[0].offsetWidth
  14961. });
  14962. };
  14963. this.$button.on('click', function () {
  14964. var $this = $(this);
  14965. if (that.isDisabled()) {
  14966. return;
  14967. }
  14968. getPlacement(that.$newElement);
  14969. that.$bsContainer
  14970. .appendTo(that.options.container)
  14971. .toggleClass('open', !$this.hasClass('open'))
  14972. .append(that.$menu);
  14973. });
  14974. $(window).on('resize scroll', function () {
  14975. getPlacement(that.$newElement);
  14976. });
  14977. this.$element.on('hide.bs.select', function () {
  14978. that.$menu.data('height', that.$menu.height());
  14979. that.$bsContainer.detach();
  14980. });
  14981. },
  14982. /**
  14983. * @param {number} index - the index of the option that is being changed
  14984. * @param {boolean} selected - true if the option is being selected, false if being deselected
  14985. * @param {JQuery} $lis - the 'li' element that is being modified
  14986. */
  14987. setSelected: function (index, selected, $lis) {
  14988. if (!$lis) {
  14989. this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
  14990. $lis = this.findLis().eq(this.liObj[index]);
  14991. }
  14992. $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
  14993. },
  14994. /**
  14995. * @param {number} index - the index of the option that is being disabled
  14996. * @param {boolean} disabled - true if the option is being disabled, false if being enabled
  14997. * @param {JQuery} $lis - the 'li' element that is being modified
  14998. */
  14999. setDisabled: function (index, disabled, $lis) {
  15000. if (!$lis) {
  15001. $lis = this.findLis().eq(this.liObj[index]);
  15002. }
  15003. if (disabled) {
  15004. $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
  15005. } else {
  15006. $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
  15007. }
  15008. },
  15009. isDisabled: function () {
  15010. return this.$element[0].disabled;
  15011. },
  15012. checkDisabled: function () {
  15013. var that = this;
  15014. if (this.isDisabled()) {
  15015. this.$newElement.addClass('disabled');
  15016. this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
  15017. } else {
  15018. if (this.$button.hasClass('disabled')) {
  15019. this.$newElement.removeClass('disabled');
  15020. this.$button.removeClass('disabled').attr('aria-disabled', false);
  15021. }
  15022. if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
  15023. this.$button.removeAttr('tabindex');
  15024. }
  15025. }
  15026. this.$button.click(function () {
  15027. return !that.isDisabled();
  15028. });
  15029. },
  15030. togglePlaceholder: function () {
  15031. var value = this.$element.val();
  15032. this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
  15033. },
  15034. tabIndex: function () {
  15035. if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
  15036. (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
  15037. this.$element.data('tabindex', this.$element.attr('tabindex'));
  15038. this.$button.attr('tabindex', this.$element.data('tabindex'));
  15039. }
  15040. this.$element.attr('tabindex', -98);
  15041. },
  15042. clickListener: function () {
  15043. var that = this,
  15044. $document = $(document);
  15045. $document.data('spaceSelect', false);
  15046. this.$button.on('keyup', function (e) {
  15047. if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
  15048. e.preventDefault();
  15049. $document.data('spaceSelect', false);
  15050. }
  15051. });
  15052. this.$button.on('click', function () {
  15053. that.setSize();
  15054. });
  15055. this.$element.on('shown.bs.select', function () {
  15056. if (!that.options.liveSearch && !that.multiple) {
  15057. that.$menuInner.find('.selected a').focus();
  15058. } else if (!that.multiple) {
  15059. var selectedIndex = that.liObj[that.$element[0].selectedIndex];
  15060. if (typeof selectedIndex !== 'number' || that.options.size === false) return;
  15061. // scroll to selected option
  15062. var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
  15063. offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
  15064. that.$menuInner[0].scrollTop = offset;
  15065. }
  15066. });
  15067. this.$menuInner.on('click', 'li a', function (e) {
  15068. var $this = $(this),
  15069. clickedIndex = $this.parent().data('originalIndex'),
  15070. prevValue = that.$element.val(),
  15071. prevIndex = that.$element.prop('selectedIndex'),
  15072. triggerChange = true;
  15073. // Don't close on multi choice menu
  15074. if (that.multiple && that.options.maxOptions !== 1) {
  15075. e.stopPropagation();
  15076. }
  15077. e.preventDefault();
  15078. //Don't run if we have been disabled
  15079. if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
  15080. var $options = that.$element.find('option'),
  15081. $option = $options.eq(clickedIndex),
  15082. state = $option.prop('selected'),
  15083. $optgroup = $option.parent('optgroup'),
  15084. maxOptions = that.options.maxOptions,
  15085. maxOptionsGrp = $optgroup.data('maxOptions') || false;
  15086. if (!that.multiple) { // Deselect all others if not multi select box
  15087. $options.prop('selected', false);
  15088. $option.prop('selected', true);
  15089. that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
  15090. that.setSelected(clickedIndex, true);
  15091. } else { // Toggle the one we have chosen if we are multi select.
  15092. $option.prop('selected', !state);
  15093. that.setSelected(clickedIndex, !state);
  15094. $this.blur();
  15095. if (maxOptions !== false || maxOptionsGrp !== false) {
  15096. var maxReached = maxOptions < $options.filter(':selected').length,
  15097. maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
  15098. if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
  15099. if (maxOptions && maxOptions == 1) {
  15100. $options.prop('selected', false);
  15101. $option.prop('selected', true);
  15102. that.$menuInner.find('.selected').removeClass('selected');
  15103. that.setSelected(clickedIndex, true);
  15104. } else if (maxOptionsGrp && maxOptionsGrp == 1) {
  15105. $optgroup.find('option:selected').prop('selected', false);
  15106. $option.prop('selected', true);
  15107. var optgroupID = $this.parent().data('optgroup');
  15108. that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
  15109. that.setSelected(clickedIndex, true);
  15110. } else {
  15111. var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
  15112. maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
  15113. maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
  15114. maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
  15115. $notify = $('<div class="notify"></div>');
  15116. // If {var} is set in array, replace it
  15117. /** @deprecated */
  15118. if (maxOptionsArr[2]) {
  15119. maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
  15120. maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
  15121. }
  15122. $option.prop('selected', false);
  15123. that.$menu.append($notify);
  15124. if (maxOptions && maxReached) {
  15125. $notify.append($('<div>' + maxTxt + '</div>'));
  15126. triggerChange = false;
  15127. that.$element.trigger('maxReached.bs.select');
  15128. }
  15129. if (maxOptionsGrp && maxReachedGrp) {
  15130. $notify.append($('<div>' + maxTxtGrp + '</div>'));
  15131. triggerChange = false;
  15132. that.$element.trigger('maxReachedGrp.bs.select');
  15133. }
  15134. setTimeout(function () {
  15135. that.setSelected(clickedIndex, false);
  15136. }, 10);
  15137. $notify.delay(750).fadeOut(300, function () {
  15138. $(this).remove();
  15139. });
  15140. }
  15141. }
  15142. }
  15143. }
  15144. if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
  15145. that.$button.focus();
  15146. } else if (that.options.liveSearch) {
  15147. that.$searchbox.focus();
  15148. }
  15149. // Trigger select 'change'
  15150. if (triggerChange) {
  15151. if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
  15152. // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
  15153. changed_arguments = [clickedIndex, $option.prop('selected'), state];
  15154. that.$element
  15155. .triggerNative('change');
  15156. }
  15157. }
  15158. }
  15159. });
  15160. this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
  15161. if (e.currentTarget == this) {
  15162. e.preventDefault();
  15163. e.stopPropagation();
  15164. if (that.options.liveSearch && !$(e.target).hasClass('close')) {
  15165. that.$searchbox.focus();
  15166. } else {
  15167. that.$button.focus();
  15168. }
  15169. }
  15170. });
  15171. this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
  15172. e.preventDefault();
  15173. e.stopPropagation();
  15174. if (that.options.liveSearch) {
  15175. that.$searchbox.focus();
  15176. } else {
  15177. that.$button.focus();
  15178. }
  15179. });
  15180. this.$menu.on('click', '.popover-title .close', function () {
  15181. that.$button.click();
  15182. });
  15183. this.$searchbox.on('click', function (e) {
  15184. e.stopPropagation();
  15185. });
  15186. this.$menu.on('click', '.actions-btn', function (e) {
  15187. if (that.options.liveSearch) {
  15188. that.$searchbox.focus();
  15189. } else {
  15190. that.$button.focus();
  15191. }
  15192. e.preventDefault();
  15193. e.stopPropagation();
  15194. if ($(this).hasClass('bs-select-all')) {
  15195. that.selectAll();
  15196. } else {
  15197. that.deselectAll();
  15198. }
  15199. });
  15200. this.$element.change(function () {
  15201. that.render(false);
  15202. that.$element.trigger('changed.bs.select', changed_arguments);
  15203. changed_arguments = null;
  15204. });
  15205. },
  15206. liveSearchListener: function () {
  15207. var that = this,
  15208. $no_results = $('<li class="no-results"></li>');
  15209. this.$button.on('click.dropdown.data-api', function () {
  15210. that.$menuInner.find('.active').removeClass('active');
  15211. if (!!that.$searchbox.val()) {
  15212. that.$searchbox.val('');
  15213. that.$lis.not('.is-hidden').removeClass('hidden');
  15214. if (!!$no_results.parent().length) $no_results.remove();
  15215. }
  15216. if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
  15217. setTimeout(function () {
  15218. that.$searchbox.focus();
  15219. }, 10);
  15220. });
  15221. this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
  15222. e.stopPropagation();
  15223. });
  15224. this.$searchbox.on('input propertychange', function () {
  15225. that.$lis.not('.is-hidden').removeClass('hidden');
  15226. that.$lis.filter('.active').removeClass('active');
  15227. $no_results.remove();
  15228. if (that.$searchbox.val()) {
  15229. var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
  15230. $hideItems;
  15231. if (that.options.liveSearchNormalize) {
  15232. $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
  15233. } else {
  15234. $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
  15235. }
  15236. if ($hideItems.length === $searchBase.length) {
  15237. $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
  15238. that.$menuInner.append($no_results);
  15239. that.$lis.addClass('hidden');
  15240. } else {
  15241. $hideItems.addClass('hidden');
  15242. var $lisVisible = that.$lis.not('.hidden'),
  15243. $foundDiv;
  15244. // hide divider if first or last visible, or if followed by another divider
  15245. $lisVisible.each(function (index) {
  15246. var $this = $(this);
  15247. if ($this.hasClass('divider')) {
  15248. if ($foundDiv === undefined) {
  15249. $this.addClass('hidden');
  15250. } else {
  15251. if ($foundDiv) $foundDiv.addClass('hidden');
  15252. $foundDiv = $this;
  15253. }
  15254. } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
  15255. $this.addClass('hidden');
  15256. } else {
  15257. $foundDiv = null;
  15258. }
  15259. });
  15260. if ($foundDiv) $foundDiv.addClass('hidden');
  15261. $searchBase.not('.hidden').first().addClass('active');
  15262. that.$menuInner.scrollTop(0);
  15263. }
  15264. }
  15265. });
  15266. },
  15267. _searchStyle: function () {
  15268. var styles = {
  15269. begins: 'ibegins',
  15270. startsWith: 'ibegins'
  15271. };
  15272. return styles[this.options.liveSearchStyle] || 'icontains';
  15273. },
  15274. val: function (value) {
  15275. if (typeof value !== 'undefined') {
  15276. this.$element.val(value);
  15277. this.render();
  15278. return this.$element;
  15279. } else {
  15280. return this.$element.val();
  15281. }
  15282. },
  15283. changeAll: function (status) {
  15284. if (!this.multiple) return;
  15285. if (typeof status === 'undefined') status = true;
  15286. this.findLis();
  15287. var $options = this.$element.find('option'),
  15288. $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
  15289. lisVisLen = $lisVisible.length,
  15290. selectedOptions = [];
  15291. if (status) {
  15292. if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
  15293. } else {
  15294. if ($lisVisible.filter('.selected').length === 0) return;
  15295. }
  15296. $lisVisible.toggleClass('selected', status);
  15297. for (var i = 0; i < lisVisLen; i++) {
  15298. var origIndex = $lisVisible[i].getAttribute('data-original-index');
  15299. selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
  15300. }
  15301. $(selectedOptions).prop('selected', status);
  15302. this.render(false);
  15303. this.togglePlaceholder();
  15304. this.$element
  15305. .triggerNative('change');
  15306. },
  15307. selectAll: function () {
  15308. return this.changeAll(true);
  15309. },
  15310. deselectAll: function () {
  15311. return this.changeAll(false);
  15312. },
  15313. toggle: function (e) {
  15314. e = e || window.event;
  15315. if (e) e.stopPropagation();
  15316. this.$button.trigger('click');
  15317. },
  15318. keydown: function (e) {
  15319. var $this = $(this),
  15320. $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
  15321. $items,
  15322. that = $parent.data('this'),
  15323. index,
  15324. prevIndex,
  15325. isActive,
  15326. selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
  15327. keyCodeMap = {
  15328. 32: ' ',
  15329. 48: '0',
  15330. 49: '1',
  15331. 50: '2',
  15332. 51: '3',
  15333. 52: '4',
  15334. 53: '5',
  15335. 54: '6',
  15336. 55: '7',
  15337. 56: '8',
  15338. 57: '9',
  15339. 59: ';',
  15340. 65: 'a',
  15341. 66: 'b',
  15342. 67: 'c',
  15343. 68: 'd',
  15344. 69: 'e',
  15345. 70: 'f',
  15346. 71: 'g',
  15347. 72: 'h',
  15348. 73: 'i',
  15349. 74: 'j',
  15350. 75: 'k',
  15351. 76: 'l',
  15352. 77: 'm',
  15353. 78: 'n',
  15354. 79: 'o',
  15355. 80: 'p',
  15356. 81: 'q',
  15357. 82: 'r',
  15358. 83: 's',
  15359. 84: 't',
  15360. 85: 'u',
  15361. 86: 'v',
  15362. 87: 'w',
  15363. 88: 'x',
  15364. 89: 'y',
  15365. 90: 'z',
  15366. 96: '0',
  15367. 97: '1',
  15368. 98: '2',
  15369. 99: '3',
  15370. 100: '4',
  15371. 101: '5',
  15372. 102: '6',
  15373. 103: '7',
  15374. 104: '8',
  15375. 105: '9'
  15376. };
  15377. isActive = that.$newElement.hasClass('open');
  15378. if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
  15379. if (!that.options.container) {
  15380. that.setSize();
  15381. that.$menu.parent().addClass('open');
  15382. isActive = true;
  15383. } else {
  15384. that.$button.trigger('click');
  15385. }
  15386. that.$searchbox.focus();
  15387. return;
  15388. }
  15389. if (that.options.liveSearch) {
  15390. if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
  15391. e.preventDefault();
  15392. e.stopPropagation();
  15393. that.$menuInner.click();
  15394. that.$button.focus();
  15395. }
  15396. }
  15397. if (/(38|40)/.test(e.keyCode.toString(10))) {
  15398. $items = that.$lis.filter(selector);
  15399. if (!$items.length) return;
  15400. if (!that.options.liveSearch) {
  15401. index = $items.index($items.find('a').filter(':focus').parent());
  15402. } else {
  15403. index = $items.index($items.filter('.active'));
  15404. }
  15405. prevIndex = that.$menuInner.data('prevIndex');
  15406. if (e.keyCode == 38) {
  15407. if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
  15408. if (index < 0) index += $items.length;
  15409. } else if (e.keyCode == 40) {
  15410. if (that.options.liveSearch || index == prevIndex) index++;
  15411. index = index % $items.length;
  15412. }
  15413. that.$menuInner.data('prevIndex', index);
  15414. if (!that.options.liveSearch) {
  15415. $items.eq(index).children('a').focus();
  15416. } else {
  15417. e.preventDefault();
  15418. if (!$this.hasClass('dropdown-toggle')) {
  15419. $items.removeClass('active').eq(index).addClass('active').children('a').focus();
  15420. $this.focus();
  15421. }
  15422. }
  15423. } else if (!$this.is('input')) {
  15424. var keyIndex = [],
  15425. count,
  15426. prevKey;
  15427. $items = that.$lis.filter(selector);
  15428. $items.each(function (i) {
  15429. if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
  15430. keyIndex.push(i);
  15431. }
  15432. });
  15433. count = $(document).data('keycount');
  15434. count++;
  15435. $(document).data('keycount', count);
  15436. prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
  15437. if (prevKey != keyCodeMap[e.keyCode]) {
  15438. count = 1;
  15439. $(document).data('keycount', count);
  15440. } else if (count >= keyIndex.length) {
  15441. $(document).data('keycount', 0);
  15442. if (count > keyIndex.length) count = 1;
  15443. }
  15444. $items.eq(keyIndex[count - 1]).children('a').focus();
  15445. }
  15446. // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
  15447. if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
  15448. if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
  15449. if (!that.options.liveSearch) {
  15450. var elem = $(':focus');
  15451. elem.click();
  15452. // Bring back focus for multiselects
  15453. elem.focus();
  15454. // Prevent screen from scrolling if the user hit the spacebar
  15455. e.preventDefault();
  15456. // Fixes spacebar selection of dropdown items in FF & IE
  15457. $(document).data('spaceSelect', true);
  15458. } else if (!/(32)/.test(e.keyCode.toString(10))) {
  15459. that.$menuInner.find('.active a').click();
  15460. $this.focus();
  15461. }
  15462. $(document).data('keycount', 0);
  15463. }
  15464. if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
  15465. that.$menu.parent().removeClass('open');
  15466. if (that.options.container) that.$newElement.removeClass('open');
  15467. that.$button.focus();
  15468. }
  15469. },
  15470. mobile: function () {
  15471. this.$element.addClass('mobile-device');
  15472. },
  15473. refresh: function () {
  15474. this.$lis = null;
  15475. this.liObj = {};
  15476. this.reloadLi();
  15477. this.render();
  15478. this.checkDisabled();
  15479. this.liHeight(true);
  15480. this.setStyle();
  15481. this.setWidth();
  15482. if (this.$lis) this.$searchbox.trigger('propertychange');
  15483. this.$element.trigger('refreshed.bs.select');
  15484. },
  15485. hide: function () {
  15486. this.$newElement.hide();
  15487. },
  15488. show: function () {
  15489. this.$newElement.show();
  15490. },
  15491. remove: function () {
  15492. this.$newElement.remove();
  15493. this.$element.remove();
  15494. },
  15495. destroy: function () {
  15496. this.$newElement.before(this.$element).remove();
  15497. if (this.$bsContainer) {
  15498. this.$bsContainer.remove();
  15499. } else {
  15500. this.$menu.remove();
  15501. }
  15502. this.$element
  15503. .off('.bs.select')
  15504. .removeData('selectpicker')
  15505. .removeClass('bs-select-hidden selectpicker');
  15506. }
  15507. };
  15508. // SELECTPICKER PLUGIN DEFINITION
  15509. // ==============================
  15510. function Plugin(option) {
  15511. // get the args of the outer function..
  15512. var args = arguments;
  15513. // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
  15514. // to get lost/corrupted in android 2.3 and IE9 #715 #775
  15515. var _option = option;
  15516. [].shift.apply(args);
  15517. var value;
  15518. var chain = this.each(function () {
  15519. var $this = $(this);
  15520. if ($this.is('select')) {
  15521. var data = $this.data('selectpicker'),
  15522. options = typeof _option == 'object' && _option;
  15523. if (!data) {
  15524. var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
  15525. config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
  15526. $this.data('selectpicker', (data = new Selectpicker(this, config)));
  15527. } else if (options) {
  15528. for (var i in options) {
  15529. if (options.hasOwnProperty(i)) {
  15530. data.options[i] = options[i];
  15531. }
  15532. }
  15533. }
  15534. if (typeof _option == 'string') {
  15535. if (data[_option] instanceof Function) {
  15536. value = data[_option].apply(data, args);
  15537. } else {
  15538. value = data.options[_option];
  15539. }
  15540. }
  15541. }
  15542. });
  15543. if (typeof value !== 'undefined') {
  15544. //noinspection JSUnusedAssignment
  15545. return value;
  15546. } else {
  15547. return chain;
  15548. }
  15549. }
  15550. var old = $.fn.selectpicker;
  15551. $.fn.selectpicker = Plugin;
  15552. $.fn.selectpicker.Constructor = Selectpicker;
  15553. // SELECTPICKER NO CONFLICT
  15554. // ========================
  15555. $.fn.selectpicker.noConflict = function () {
  15556. $.fn.selectpicker = old;
  15557. return this;
  15558. };
  15559. $(document)
  15560. .data('keycount', 0)
  15561. .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
  15562. .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
  15563. e.stopPropagation();
  15564. });
  15565. // SELECTPICKER DATA-API
  15566. // =====================
  15567. $(window).on('load.bs.select.data-api', function () {
  15568. $('.selectpicker').each(function () {
  15569. var $selectpicker = $(this);
  15570. Plugin.call($selectpicker, $selectpicker.data());
  15571. })
  15572. });
  15573. })(jQuery);
  15574. }));
  15575. /***/ }),
  15576. /* 6 */
  15577. /***/ (function(module, exports, __webpack_require__) {
  15578. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  15579. * Bootstrap (plugin): validator.js v0.11.9
  15580. * ========================================================================
  15581. * The MIT License (MIT)
  15582. *
  15583. * Copyright (c) 2016 Cina Saffary.
  15584. * Made by @1000hz in the style of Bootstrap 3 era @fat
  15585. *
  15586. * Permission is hereby granted, free of charge, to any person obtaining a copy
  15587. * of this software and associated documentation files (the "Software"), to deal
  15588. * in the Software without restriction, including without limitation the rights
  15589. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15590. * copies of the Software, and to permit persons to whom the Software is
  15591. * furnished to do so, subject to the following conditions:
  15592. *
  15593. * The above copyright notice and this permission notice shall be included in
  15594. * all copies or substantial portions of the Software.
  15595. *
  15596. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15597. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15598. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15599. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15600. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15601. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  15602. * THE SOFTWARE.
  15603. * ======================================================================== */
  15604. +function ($) {
  15605. 'use strict';
  15606. // VALIDATOR CLASS DEFINITION
  15607. // ==========================
  15608. function getValue($el) {
  15609. return $el.is('[type="checkbox"]') ? $el.prop('checked') :
  15610. $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
  15611. $el.is('select[multiple]') ? ($el.val() || []).length :
  15612. $el.val()
  15613. }
  15614. var Validator = function (element, options) {
  15615. this.options = options
  15616. this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
  15617. this.$element = $(element)
  15618. this.$btn = $('button[type="submit"], input[type="submit"]')
  15619. .filter('[form="' + this.$element.attr('id') + '"]')
  15620. .add(this.$element.find('input[type="submit"], button[type="submit"]'))
  15621. this.update()
  15622. this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this))
  15623. this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
  15624. this.$element.on('reset.bs.validator', $.proxy(this.reset, this))
  15625. this.$element.find('[data-match]').each(function () {
  15626. var $this = $(this)
  15627. var target = $this.attr('data-match')
  15628. $(target).on('input.bs.validator', function (e) {
  15629. getValue($this) && $this.trigger('input.bs.validator')
  15630. })
  15631. })
  15632. // run validators for fields with values, but don't clobber server-side errors
  15633. this.$inputs.filter(function () {
  15634. return getValue($(this)) && !$(this).closest('.has-error').length
  15635. }).trigger('focusout')
  15636. this.$element.attr('novalidate', true) // disable automatic native validation
  15637. }
  15638. Validator.VERSION = '0.11.9'
  15639. Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'
  15640. Validator.FOCUS_OFFSET = 20
  15641. Validator.DEFAULTS = {
  15642. delay: 500,
  15643. html: false,
  15644. disable: true,
  15645. focus: true,
  15646. custom: {},
  15647. errors: {
  15648. match: 'Does not match',
  15649. minlength: 'Not long enough'
  15650. },
  15651. feedback: {
  15652. success: 'glyphicon-ok',
  15653. error: 'glyphicon-remove'
  15654. }
  15655. }
  15656. Validator.VALIDATORS = {
  15657. 'native': function ($el) {
  15658. var el = $el[0]
  15659. if (el.checkValidity) {
  15660. return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
  15661. }
  15662. },
  15663. 'match': function ($el) {
  15664. var target = $el.attr('data-match')
  15665. return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
  15666. },
  15667. 'minlength': function ($el) {
  15668. var minlength = $el.attr('data-minlength')
  15669. return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
  15670. }
  15671. }
  15672. Validator.prototype.update = function () {
  15673. var self = this
  15674. this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
  15675. .add(this.$element.find('[data-validate="true"]'))
  15676. .not(this.$element.find('[data-validate="false"]')
  15677. .each(function () { self.clearErrors($(this)) })
  15678. )
  15679. this.toggleSubmit()
  15680. return this
  15681. }
  15682. Validator.prototype.onInput = function (e) {
  15683. var self = this
  15684. var $el = $(e.target)
  15685. var deferErrors = e.type !== 'focusout'
  15686. if (!this.$inputs.is($el)) return
  15687. this.validateInput($el, deferErrors).done(function () {
  15688. self.toggleSubmit()
  15689. })
  15690. }
  15691. Validator.prototype.validateInput = function ($el, deferErrors) {
  15692. var value = getValue($el)
  15693. var prevErrors = $el.data('bs.validator.errors')
  15694. if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
  15695. var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
  15696. this.$element.trigger(e)
  15697. if (e.isDefaultPrevented()) return
  15698. var self = this
  15699. return this.runValidators($el).done(function (errors) {
  15700. $el.data('bs.validator.errors', errors)
  15701. errors.length
  15702. ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
  15703. : self.clearErrors($el)
  15704. if (!prevErrors || errors.toString() !== prevErrors.toString()) {
  15705. e = errors.length
  15706. ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
  15707. : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
  15708. self.$element.trigger(e)
  15709. }
  15710. self.toggleSubmit()
  15711. self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
  15712. })
  15713. }
  15714. Validator.prototype.runValidators = function ($el) {
  15715. var errors = []
  15716. var deferred = $.Deferred()
  15717. $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
  15718. $el.data('bs.validator.deferred', deferred)
  15719. function getValidatorSpecificError(key) {
  15720. return $el.attr('data-' + key + '-error')
  15721. }
  15722. function getValidityStateError() {
  15723. var validity = $el[0].validity
  15724. return validity.typeMismatch ? $el.attr('data-type-error')
  15725. : validity.patternMismatch ? $el.attr('data-pattern-error')
  15726. : validity.stepMismatch ? $el.attr('data-step-error')
  15727. : validity.rangeOverflow ? $el.attr('data-max-error')
  15728. : validity.rangeUnderflow ? $el.attr('data-min-error')
  15729. : validity.valueMissing ? $el.attr('data-required-error')
  15730. : null
  15731. }
  15732. function getGenericError() {
  15733. return $el.attr('data-error')
  15734. }
  15735. function getErrorMessage(key) {
  15736. return getValidatorSpecificError(key)
  15737. || getValidityStateError()
  15738. || getGenericError()
  15739. }
  15740. $.each(this.validators, $.proxy(function (key, validator) {
  15741. var error = null
  15742. if ((getValue($el) || $el.attr('required')) &&
  15743. ($el.attr('data-' + key) !== undefined || key == 'native') &&
  15744. (error = validator.call(this, $el))) {
  15745. error = getErrorMessage(key) || error
  15746. !~errors.indexOf(error) && errors.push(error)
  15747. }
  15748. }, this))
  15749. if (!errors.length && getValue($el) && $el.attr('data-remote')) {
  15750. this.defer($el, function () {
  15751. var data = {}
  15752. data[$el.attr('name')] = getValue($el)
  15753. $.get($el.attr('data-remote'), data)
  15754. .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
  15755. .always(function () { deferred.resolve(errors)})
  15756. })
  15757. } else deferred.resolve(errors)
  15758. return deferred.promise()
  15759. }
  15760. Validator.prototype.validate = function () {
  15761. var self = this
  15762. $.when(this.$inputs.map(function (el) {
  15763. return self.validateInput($(this), false)
  15764. })).then(function () {
  15765. self.toggleSubmit()
  15766. self.focusError()
  15767. })
  15768. return this
  15769. }
  15770. Validator.prototype.focusError = function () {
  15771. if (!this.options.focus) return
  15772. var $input = this.$element.find(".has-error:first :input")
  15773. if ($input.length === 0) return
  15774. $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
  15775. $input.focus()
  15776. }
  15777. Validator.prototype.showErrors = function ($el) {
  15778. var method = this.options.html ? 'html' : 'text'
  15779. var errors = $el.data('bs.validator.errors')
  15780. var $group = $el.closest('.form-group')
  15781. var $block = $group.find('.help-block.with-errors')
  15782. var $feedback = $group.find('.form-control-feedback')
  15783. if (!errors.length) return
  15784. errors = $('<ul/>')
  15785. .addClass('list-unstyled')
  15786. .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
  15787. $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
  15788. $block.empty().append(errors)
  15789. $group.addClass('has-error has-danger')
  15790. $group.hasClass('has-feedback')
  15791. && $feedback.removeClass(this.options.feedback.success)
  15792. && $feedback.addClass(this.options.feedback.error)
  15793. && $group.removeClass('has-success')
  15794. }
  15795. Validator.prototype.clearErrors = function ($el) {
  15796. var $group = $el.closest('.form-group')
  15797. var $block = $group.find('.help-block.with-errors')
  15798. var $feedback = $group.find('.form-control-feedback')
  15799. $block.html($block.data('bs.validator.originalContent'))
  15800. $group.removeClass('has-error has-danger has-success')
  15801. $group.hasClass('has-feedback')
  15802. && $feedback.removeClass(this.options.feedback.error)
  15803. && $feedback.removeClass(this.options.feedback.success)
  15804. && getValue($el)
  15805. && $feedback.addClass(this.options.feedback.success)
  15806. && $group.addClass('has-success')
  15807. }
  15808. Validator.prototype.hasErrors = function () {
  15809. function fieldErrors() {
  15810. return !!($(this).data('bs.validator.errors') || []).length
  15811. }
  15812. return !!this.$inputs.filter(fieldErrors).length
  15813. }
  15814. Validator.prototype.isIncomplete = function () {
  15815. function fieldIncomplete() {
  15816. var value = getValue($(this))
  15817. return !(typeof value == "string" ? $.trim(value) : value)
  15818. }
  15819. return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  15820. }
  15821. Validator.prototype.onSubmit = function (e) {
  15822. this.validate()
  15823. if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  15824. }
  15825. Validator.prototype.toggleSubmit = function () {
  15826. if (!this.options.disable) return
  15827. this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  15828. }
  15829. Validator.prototype.defer = function ($el, callback) {
  15830. callback = $.proxy(callback, this, $el)
  15831. if (!this.options.delay) return callback()
  15832. window.clearTimeout($el.data('bs.validator.timeout'))
  15833. $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  15834. }
  15835. Validator.prototype.reset = function () {
  15836. this.$element.find('.form-control-feedback')
  15837. .removeClass(this.options.feedback.error)
  15838. .removeClass(this.options.feedback.success)
  15839. this.$inputs
  15840. .removeData(['bs.validator.errors', 'bs.validator.deferred'])
  15841. .each(function () {
  15842. var $this = $(this)
  15843. var timeout = $this.data('bs.validator.timeout')
  15844. window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
  15845. })
  15846. this.$element.find('.help-block.with-errors')
  15847. .each(function () {
  15848. var $this = $(this)
  15849. var originalContent = $this.data('bs.validator.originalContent')
  15850. $this
  15851. .removeData('bs.validator.originalContent')
  15852. .html(originalContent)
  15853. })
  15854. this.$btn.removeClass('disabled')
  15855. this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
  15856. return this
  15857. }
  15858. Validator.prototype.destroy = function () {
  15859. this.reset()
  15860. this.$element
  15861. .removeAttr('novalidate')
  15862. .removeData('bs.validator')
  15863. .off('.bs.validator')
  15864. this.$inputs
  15865. .off('.bs.validator')
  15866. this.options = null
  15867. this.validators = null
  15868. this.$element = null
  15869. this.$btn = null
  15870. this.$inputs = null
  15871. return this
  15872. }
  15873. // VALIDATOR PLUGIN DEFINITION
  15874. // ===========================
  15875. function Plugin(option) {
  15876. return this.each(function () {
  15877. var $this = $(this)
  15878. var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
  15879. var data = $this.data('bs.validator')
  15880. if (!data && option == 'destroy') return
  15881. if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
  15882. if (typeof option == 'string') data[option]()
  15883. })
  15884. }
  15885. var old = $.fn.validator
  15886. $.fn.validator = Plugin
  15887. $.fn.validator.Constructor = Validator
  15888. // VALIDATOR NO CONFLICT
  15889. // =====================
  15890. $.fn.validator.noConflict = function () {
  15891. $.fn.validator = old
  15892. return this
  15893. }
  15894. // VALIDATOR DATA-API
  15895. // ==================
  15896. $(window).on('load', function () {
  15897. $('form[data-toggle="validator"]').each(function () {
  15898. var $form = $(this)
  15899. Plugin.call($form, $form.data())
  15900. })
  15901. })
  15902. }(jQuery);
  15903. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  15904. /***/ }),
  15905. /* 7 */
  15906. /***/ (function(module, exports, __webpack_require__) {
  15907. var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  15908. * bootstrap-fileinput v4.4.2
  15909. * http://plugins.krajee.com/file-input
  15910. *
  15911. * Author: Kartik Visweswaran
  15912. * Copyright: 2014 - 2017, Kartik Visweswaran, Krajee.com
  15913. *
  15914. * Licensed under the BSD 3-Clause
  15915. * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
  15916. */
  15917. (function (factory) {
  15918. "use strict";
  15919. //noinspection JSUnresolvedVariable
  15920. if (true) { // jshint ignore:line
  15921. // AMD. Register as an anonymous module.
  15922. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
  15923. __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
  15924. (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
  15925. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // jshint ignore:line
  15926. } else { // noinspection JSUnresolvedVariable
  15927. if (typeof module === 'object' && module.exports) { // jshint ignore:line
  15928. // Node/CommonJS
  15929. // noinspection JSUnresolvedVariable
  15930. module.exports = factory(require('jquery')); // jshint ignore:line
  15931. } else {
  15932. // Browser globals
  15933. factory(window.jQuery);
  15934. }
  15935. }
  15936. }(function ($) {
  15937. "use strict";
  15938. $.fn.fileinputLocales = {};
  15939. $.fn.fileinputThemes = {};
  15940. String.prototype.setTokens = function (replacePairs) {
  15941. var str = this.toString(), key, re;
  15942. for (key in replacePairs) {
  15943. if (replacePairs.hasOwnProperty(key)) {
  15944. re = new RegExp("\{" + key + "\}", "g");
  15945. str = str.replace(re, replacePairs[key]);
  15946. }
  15947. }
  15948. return str;
  15949. };
  15950. var $h, FileInput;
  15951. // fileinput helper object for all global variables and internal helper methods
  15952. //noinspection JSUnresolvedVariable
  15953. $h = {
  15954. FRAMES: '.kv-preview-thumb',
  15955. SORT_CSS: 'file-sortable',
  15956. STYLE_SETTING: 'style="width:{width};height:{height};"',
  15957. OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
  15958. '<param name="allowFullScreen" value="true" />\n' +
  15959. '<param name="allowScriptAccess" value="always" />\n' +
  15960. '<param name="autoPlay" value="false" />\n' +
  15961. '<param name="autoStart" value="false" />\n' +
  15962. '<param name="quality" value="high" />\n',
  15963. DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
  15964. '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
  15965. '</div>',
  15966. MODAL_ID: 'kvFileinputModal',
  15967. MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
  15968. objUrl: window.URL || window.webkitURL,
  15969. compare: function (input, str, exact) {
  15970. return input !== undefined && (exact ? input === str : input.match(str));
  15971. },
  15972. isIE: function (ver) {
  15973. // check for IE versions < 11
  15974. if (navigator.appName !== 'Microsoft Internet Explorer') {
  15975. return false;
  15976. }
  15977. if (ver === 10) {
  15978. return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
  15979. }
  15980. var div = document.createElement("div"), status;
  15981. div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
  15982. status = div.getElementsByTagName("i").length;
  15983. document.body.appendChild(div);
  15984. div.parentNode.removeChild(div);
  15985. return status;
  15986. },
  15987. initModal: function ($modal) {
  15988. var $body = $('body');
  15989. if ($body.length) {
  15990. $modal.appendTo($body);
  15991. }
  15992. },
  15993. isEmpty: function (value, trim) {
  15994. return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
  15995. },
  15996. isArray: function (a) {
  15997. return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
  15998. },
  15999. ifSet: function (needle, haystack, def) {
  16000. def = def || '';
  16001. return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
  16002. },
  16003. cleanArray: function (arr) {
  16004. if (!(arr instanceof Array)) {
  16005. arr = [];
  16006. }
  16007. return arr.filter(function (e) {
  16008. return (e !== undefined && e !== null);
  16009. });
  16010. },
  16011. spliceArray: function (arr, index) {
  16012. var i, j = 0, out = [];
  16013. if (!(arr instanceof Array)) {
  16014. return [];
  16015. }
  16016. for (i = 0; i < arr.length; i++) {
  16017. if (i !== index) {
  16018. out[j] = arr[i];
  16019. j++;
  16020. }
  16021. }
  16022. return out;
  16023. },
  16024. getNum: function (num, def) {
  16025. def = def || 0;
  16026. if (typeof num === "number") {
  16027. return num;
  16028. }
  16029. if (typeof num === "string") {
  16030. num = parseFloat(num);
  16031. }
  16032. return isNaN(num) ? def : num;
  16033. },
  16034. hasFileAPISupport: function () {
  16035. return !!(window.File && window.FileReader);
  16036. },
  16037. hasDragDropSupport: function () {
  16038. var div = document.createElement('div');
  16039. /** @namespace div.draggable */
  16040. /** @namespace div.ondragstart */
  16041. /** @namespace div.ondrop */
  16042. return !$h.isIE(9) &&
  16043. (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
  16044. },
  16045. hasFileUploadSupport: function () {
  16046. return $h.hasFileAPISupport() && window.FormData;
  16047. },
  16048. hasBlobSupport: function () {
  16049. try {
  16050. return !!window.Blob && Boolean(new Blob());
  16051. } catch (e) {
  16052. return false;
  16053. }
  16054. },
  16055. hasArrayBufferViewSupport: function () {
  16056. try {
  16057. return new Blob([new Uint8Array(100)]).size === 100;
  16058. } catch (e) {
  16059. return false;
  16060. }
  16061. },
  16062. dataURI2Blob: function (dataURI) {
  16063. //noinspection JSUnresolvedVariable
  16064. var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
  16065. window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
  16066. canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
  16067. if (!canProceed) {
  16068. return null;
  16069. }
  16070. if (dataURI.split(',')[0].indexOf('base64') >= 0) {
  16071. byteStr = atob(dataURI.split(',')[1]);
  16072. } else {
  16073. byteStr = decodeURIComponent(dataURI.split(',')[1]);
  16074. }
  16075. arrayBuffer = new ArrayBuffer(byteStr.length);
  16076. intArray = new Uint8Array(arrayBuffer);
  16077. for (i = 0; i < byteStr.length; i += 1) {
  16078. intArray[i] = byteStr.charCodeAt(i);
  16079. }
  16080. mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
  16081. if (canBlob) {
  16082. return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
  16083. }
  16084. bb = new BlobBuilder();
  16085. bb.append(arrayBuffer);
  16086. return bb.getBlob(mimeStr);
  16087. },
  16088. addCss: function ($el, css) {
  16089. $el.removeClass(css).addClass(css);
  16090. },
  16091. getElement: function (options, param, value) {
  16092. return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
  16093. },
  16094. uniqId: function () {
  16095. return Math.round(new Date().getTime() + (Math.random() * 100));
  16096. },
  16097. htmlEncode: function (str) {
  16098. return str.replace(/&/g, '&amp;')
  16099. .replace(/</g, '&lt;')
  16100. .replace(/>/g, '&gt;')
  16101. .replace(/"/g, '&quot;')
  16102. .replace(/'/g, '&apos;');
  16103. },
  16104. replaceTags: function (str, tags) {
  16105. var out = str;
  16106. if (!tags) {
  16107. return out;
  16108. }
  16109. $.each(tags, function (key, value) {
  16110. if (typeof value === "function") {
  16111. value = value();
  16112. }
  16113. out = out.split(key).join(value);
  16114. });
  16115. return out;
  16116. },
  16117. cleanMemory: function ($thumb) {
  16118. var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
  16119. /** @namespace $h.objUrl.revokeObjectURL */
  16120. $h.objUrl.revokeObjectURL(data);
  16121. },
  16122. findFileName: function (filePath) {
  16123. var sepIndex = filePath.lastIndexOf('/');
  16124. if (sepIndex === -1) {
  16125. sepIndex = filePath.lastIndexOf('\\');
  16126. }
  16127. return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
  16128. },
  16129. checkFullScreen: function () {
  16130. //noinspection JSUnresolvedVariable
  16131. return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
  16132. document.msFullscreenElement;
  16133. },
  16134. toggleFullScreen: function (maximize) {
  16135. var doc = document, de = doc.documentElement;
  16136. if (de && maximize && !$h.checkFullScreen()) {
  16137. /** @namespace document.requestFullscreen */
  16138. /** @namespace document.msRequestFullscreen */
  16139. /** @namespace document.mozRequestFullScreen */
  16140. /** @namespace document.webkitRequestFullscreen */
  16141. /** @namespace Element.ALLOW_KEYBOARD_INPUT */
  16142. if (de.requestFullscreen) {
  16143. de.requestFullscreen();
  16144. } else if (de.msRequestFullscreen) {
  16145. de.msRequestFullscreen();
  16146. } else if (de.mozRequestFullScreen) {
  16147. de.mozRequestFullScreen();
  16148. } else if (de.webkitRequestFullscreen) {
  16149. de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  16150. }
  16151. } else {
  16152. /** @namespace document.exitFullscreen */
  16153. /** @namespace document.msExitFullscreen */
  16154. /** @namespace document.mozCancelFullScreen */
  16155. /** @namespace document.webkitExitFullscreen */
  16156. if (doc.exitFullscreen) {
  16157. doc.exitFullscreen();
  16158. } else if (doc.msExitFullscreen) {
  16159. doc.msExitFullscreen();
  16160. } else if (doc.mozCancelFullScreen) {
  16161. doc.mozCancelFullScreen();
  16162. } else if (doc.webkitExitFullscreen) {
  16163. doc.webkitExitFullscreen();
  16164. }
  16165. }
  16166. },
  16167. moveArray: function (arr, oldIndex, newIndex) {
  16168. if (newIndex >= arr.length) {
  16169. var k = newIndex - arr.length;
  16170. while ((k--) + 1) {
  16171. arr.push(undefined);
  16172. }
  16173. }
  16174. arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);
  16175. return arr;
  16176. },
  16177. cleanZoomCache: function ($el) {
  16178. var $cache = $el.closest('.kv-zoom-cache-theme');
  16179. if (!$cache.length) {
  16180. $cache = $el.closest('.kv-zoom-cache');
  16181. }
  16182. $cache.remove();
  16183. },
  16184. setOrientation: function (buffer, callback) {
  16185. var scanner = new DataView(buffer), idx = 0, value = 1, // Non-rotated is the default
  16186. maxBytes, uInt16, exifLength;
  16187. if (scanner.getUint16(idx) !== 0xFFD8 || buffer.length < 2) {
  16188. return; // not a proper JPEG
  16189. }
  16190. idx += 2;
  16191. maxBytes = scanner.byteLength;
  16192. while (idx < maxBytes - 2) {
  16193. uInt16 = scanner.getUint16(idx);
  16194. idx += 2;
  16195. switch (uInt16) {
  16196. case 0xFFE1: // Start of EXIF
  16197. exifLength = scanner.getUint16(idx);
  16198. maxBytes = exifLength - idx;
  16199. idx += 2;
  16200. break;
  16201. case 0x0112: // Orientation tag
  16202. value = scanner.getUint16(idx + 6, false);
  16203. maxBytes = 0; // Stop scanning
  16204. break;
  16205. }
  16206. }
  16207. if (callback) {
  16208. callback(value);
  16209. }
  16210. },
  16211. validateOrientation: function (file, callback) {
  16212. if (!window.FileReader || !window.DataView) {
  16213. return; // skip orientation if pre-requisite libraries not supported by browser
  16214. }
  16215. var reader = new FileReader(), buffer;
  16216. reader.onloadend = function () {
  16217. buffer = reader.result;
  16218. $h.setOrientation(buffer, callback);
  16219. };
  16220. reader.readAsArrayBuffer(file);
  16221. },
  16222. adjustOrientedImage: function ($img, isZoom) {
  16223. var offsetContTop, offsetTop, newTop;
  16224. if (!$img.hasClass('is-portrait-gt4')) {
  16225. return;
  16226. }
  16227. if (isZoom) {
  16228. $img.css({width: $img.parent().height()});
  16229. return;
  16230. } else {
  16231. $img.css({height: 'auto', width: $img.height()});
  16232. }
  16233. offsetContTop = $img.parent().offset().top;
  16234. offsetTop = $img.offset().top;
  16235. newTop = offsetContTop - offsetTop;
  16236. $img.css('margin-top', newTop);
  16237. }
  16238. };
  16239. FileInput = function (element, options) {
  16240. var self = this;
  16241. self.$element = $(element);
  16242. if (!self._validate()) {
  16243. return;
  16244. }
  16245. self.isPreviewable = $h.hasFileAPISupport();
  16246. self.isIE9 = $h.isIE(9);
  16247. self.isIE10 = $h.isIE(10);
  16248. if (self.isPreviewable || self.isIE9) {
  16249. self._init(options);
  16250. self._listen();
  16251. } else {
  16252. self.$element.removeClass('file-loading');
  16253. }
  16254. };
  16255. //noinspection JSUnusedGlobalSymbols
  16256. FileInput.prototype = {
  16257. constructor: FileInput,
  16258. _cleanup: function () {
  16259. var self = this;
  16260. self.reader = null;
  16261. self.formdata = {};
  16262. self.uploadCount = 0;
  16263. self.uploadStatus = {};
  16264. self.uploadLog = [];
  16265. self.uploadAsyncCount = 0;
  16266. self.loadedImages = [];
  16267. self.totalImagesCount = 0;
  16268. self.ajaxRequests = [];
  16269. self.clearStack();
  16270. self.fileInputCleared = false;
  16271. self.fileBatchCompleted = true;
  16272. if (!self.isPreviewable) {
  16273. self.showPreview = false;
  16274. }
  16275. self.isError = false;
  16276. self.ajaxAborted = false;
  16277. self.cancelling = false;
  16278. },
  16279. _init: function (options) {
  16280. var self = this, $el = self.$element, $cont, t, tmp;
  16281. self.options = options;
  16282. $.each(options, function (key, value) {
  16283. switch (key) {
  16284. case 'minFileCount':
  16285. case 'maxFileCount':
  16286. case 'minFileSize':
  16287. case 'maxFileSize':
  16288. case 'maxFilePreviewSize':
  16289. case 'resizeImageQuality':
  16290. case 'resizeIfSizeMoreThan':
  16291. case 'progressUploadThreshold':
  16292. case 'initialPreviewCount':
  16293. case 'zoomModalHeight':
  16294. case 'minImageHeight':
  16295. case 'maxImageHeight':
  16296. case 'minImageWidth':
  16297. case 'maxImageWidth':
  16298. self[key] = $h.getNum(value);
  16299. break;
  16300. default:
  16301. self[key] = value;
  16302. break;
  16303. }
  16304. });
  16305. if (self.rtl) { // swap buttons for rtl
  16306. tmp = self.previewZoomButtonIcons.prev;
  16307. self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
  16308. self.previewZoomButtonIcons.next = tmp;
  16309. }
  16310. self._cleanup();
  16311. self.$form = $el.closest('form');
  16312. self._initTemplateDefaults();
  16313. self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
  16314. t = self._getLayoutTemplate('progress');
  16315. self.progressTemplate = t.replace('{class}', self.progressClass);
  16316. self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
  16317. self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
  16318. self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
  16319. self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
  16320. if (self.isDisabled) {
  16321. $el.attr('disabled', true);
  16322. }
  16323. self.isUploadable = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
  16324. self.isClickable = self.browseOnZoneClick && self.showPreview &&
  16325. (self.isUploadable && self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
  16326. self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self._slugDefault;
  16327. self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
  16328. self.captionTemplate = self._getLayoutTemplate('caption');
  16329. self.previewGenericTemplate = self._getPreviewTemplate('generic');
  16330. if (self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
  16331. self.imageCanvas = document.createElement('canvas');
  16332. self.imageCanvasContext = self.imageCanvas.getContext('2d');
  16333. }
  16334. if ($h.isEmpty($el.attr('id'))) {
  16335. $el.attr('id', $h.uniqId());
  16336. }
  16337. self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
  16338. if (self.$container === undefined) {
  16339. self.$container = self._createContainer();
  16340. } else {
  16341. self._refreshContainer();
  16342. }
  16343. $cont = self.$container;
  16344. self.$dropZone = $cont.find('.file-drop-zone');
  16345. self.$progress = $cont.find('.kv-upload-progress');
  16346. self.$btnUpload = $cont.find('.fileinput-upload');
  16347. self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
  16348. self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
  16349. self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
  16350. self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
  16351. self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
  16352. self.$errorContainer = $h.getElement(options, 'elErrorContainer',
  16353. self.$previewContainer.find('.kv-fileinput-error'));
  16354. if (!$h.isEmpty(self.msgErrorClass)) {
  16355. $h.addCss(self.$errorContainer, self.msgErrorClass);
  16356. }
  16357. self.$errorContainer.hide();
  16358. self.previewInitId = "preview-" + $h.uniqId();
  16359. self._initPreviewCache();
  16360. self._initPreview(true);
  16361. self._initPreviewActions();
  16362. self._setFileDropZoneTitle();
  16363. $el.removeClass('file-loading');
  16364. if ($el.attr('disabled')) {
  16365. self.disable();
  16366. }
  16367. self._initZoom();
  16368. if (self.hideThumbnailContent) {
  16369. $h.addCss(self.$preview, 'hide-content');
  16370. }
  16371. },
  16372. _initTemplateDefaults: function () {
  16373. var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
  16374. tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionZoom,
  16375. tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage, tText, tVideo,
  16376. tAudio, tFlash, tObject, tPdf, tOther, tZoomCache, vDefaultDim;
  16377. tMain1 = '{preview}\n' +
  16378. '<div class="kv-upload-progress hide"></div>\n' +
  16379. '<div class="input-group {class}">\n' +
  16380. ' {caption}\n' +
  16381. ' <div class="input-group-btn">\n' +
  16382. ' {remove}\n' +
  16383. ' {cancel}\n' +
  16384. ' {upload}\n' +
  16385. ' {browse}\n' +
  16386. ' </div>\n' +
  16387. '</div>';
  16388. tMain2 = '{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
  16389. tPreview = '<div class="file-preview {class}">\n' +
  16390. ' {close}' +
  16391. ' <div class="{dropClass}">\n' +
  16392. ' <div class="file-preview-thumbnails">\n' +
  16393. ' </div>\n' +
  16394. ' <div class="clearfix"></div>' +
  16395. ' <div class="file-preview-status text-center text-success"></div>\n' +
  16396. ' <div class="kv-fileinput-error"></div>\n' +
  16397. ' </div>\n' +
  16398. '</div>';
  16399. tClose = '<div class="close fileinput-remove">&times;</div>\n';
  16400. tFileIcon = '<i class="glyphicon glyphicon-file kv-caption-icon"></i>';
  16401. tCaption = '<div tabindex="500" class="form-control file-caption {class}">\n' +
  16402. ' <div class="file-caption-name"></div>\n' +
  16403. '</div>\n';
  16404. //noinspection HtmlUnknownAttribute
  16405. tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" ' +
  16406. '{status}>{icon} {label}</button>';
  16407. //noinspection HtmlUnknownAttribute
  16408. tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon} {label}</a>';
  16409. //noinspection HtmlUnknownAttribute
  16410. tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon} {label}</div>';
  16411. tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
  16412. 'tabindex="-1" aria-labelledby="' + $h.MODAL_ID + 'Label"></div>';
  16413. tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
  16414. ' <div class="modal-content">\n' +
  16415. ' <div class="modal-header">\n' +
  16416. ' <div class="kv-zoom-actions pull-right">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
  16417. ' <h3 class="modal-title">{heading} <small><span class="kv-zoom-title"></span></small></h3>\n' +
  16418. ' </div>\n' +
  16419. ' <div class="modal-body">\n' +
  16420. ' <div class="floating-buttons"></div>\n' +
  16421. ' <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
  16422. ' </div>\n' +
  16423. ' </div>\n' +
  16424. '</div>\n';
  16425. tProgress = '<div class="progress">\n' +
  16426. ' <div class="{class}" role="progressbar"' +
  16427. ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
  16428. ' {status}\n' +
  16429. ' </div>\n' +
  16430. '</div>';
  16431. tSize = ' <samp>({sizeText})</samp>';
  16432. tFooter = '<div class="file-thumbnail-footer">\n' +
  16433. ' <div class="file-footer-caption" title="{caption}">{caption}<br>{size}</div>\n' +
  16434. ' {progress} {indicator} {actions}\n' +
  16435. '</div>';
  16436. tActions = '{drag}\n' +
  16437. '<div class="file-actions">\n' +
  16438. ' <div class="file-footer-buttons">\n' +
  16439. ' {upload} {delete} {zoom} {other}' +
  16440. ' </div>\n' +
  16441. ' <div class="clearfix"></div>\n' +
  16442. '</div>';
  16443. //noinspection HtmlUnknownAttribute
  16444. tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
  16445. 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
  16446. tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
  16447. '{uploadIcon}</button>';
  16448. tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
  16449. 'title="{zoomTitle}">{zoomIcon}</button>';
  16450. tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
  16451. tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
  16452. tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  16453. ' data-template="{template}"';
  16454. tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
  16455. tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
  16456. tTagAft = '</div>{footer}\n</div>\n';
  16457. tGeneric = '{content}\n';
  16458. tHtml = '<div class="kv-preview-data file-preview-html" title="{caption}" ' + $h.STYLE_SETTING +
  16459. '>{data}</div>\n';
  16460. tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{caption}" alt="{caption}" ' +
  16461. $h.STYLE_SETTING + '>\n';
  16462. tText = '<textarea class="kv-preview-data file-preview-text" title="{caption}" readonly ' +
  16463. $h.STYLE_SETTING + '>{data}</textarea>\n';
  16464. tVideo = '<video class="kv-preview-data file-preview-video" width="{width}" ' +
  16465. 'height="{height}" controls>\n' + '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW +
  16466. '\n</video>\n';
  16467. tAudio = '<div class="file-preview-audio"><audio class="kv-preview-data" controls>\n<source src="{data}" ' +
  16468. 'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio></div>\n';
  16469. tFlash = '<object class="kv-preview-data file-object" type="application/x-shockwave-flash" ' +
  16470. 'width="{width}" height="{height}" data="{data}">\n' + $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW +
  16471. '\n</object>\n';
  16472. tObject = '<object class="kv-preview-data file-object {typeCss}" data="{data}" type="{type}" ' +
  16473. 'width="{width}" height="{height}">\n' + '<param name="movie" value="{caption}" />\n' +
  16474. $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
  16475. tPdf = '<embed class="kv-preview-data" src="{data}" ' +
  16476. 'width="{width}" height="{height}" type="application/pdf">\n';
  16477. tOther = '<div class="kv-preview-data file-preview-other-frame">\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
  16478. tZoomCache = '<div class="kv-zoom-cache" style="display:none">{zoomContent}</div>';
  16479. vDefaultDim = {width: "100%", height: "100%", 'min-height': "480px"};
  16480. self.defaults = {
  16481. layoutTemplates: {
  16482. main1: tMain1,
  16483. main2: tMain2,
  16484. preview: tPreview,
  16485. close: tClose,
  16486. fileIcon: tFileIcon,
  16487. caption: tCaption,
  16488. modalMain: tModalMain,
  16489. modal: tModal,
  16490. progress: tProgress,
  16491. size: tSize,
  16492. footer: tFooter,
  16493. indicator: tIndicator,
  16494. actions: tActions,
  16495. actionDelete: tActionDelete,
  16496. actionUpload: tActionUpload,
  16497. actionZoom: tActionZoom,
  16498. actionDrag: tActionDrag,
  16499. btnDefault: tBtnDefault,
  16500. btnLink: tBtnLink,
  16501. btnBrowse: tBtnBrowse,
  16502. zoomCache: tZoomCache
  16503. },
  16504. previewMarkupTags: {
  16505. tagBefore1: tTagBef1,
  16506. tagBefore2: tTagBef2,
  16507. tagAfter: tTagAft
  16508. },
  16509. previewContentTemplates: {
  16510. generic: tGeneric,
  16511. html: tHtml,
  16512. image: tImage,
  16513. text: tText,
  16514. video: tVideo,
  16515. audio: tAudio,
  16516. flash: tFlash,
  16517. object: tObject,
  16518. pdf: tPdf,
  16519. other: tOther
  16520. },
  16521. allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
  16522. previewTemplates: {},
  16523. previewSettings: {
  16524. image: {width: "auto", height: "160px"},
  16525. html: {width: "213px", height: "160px"},
  16526. text: {width: "213px", height: "160px"},
  16527. video: {width: "auto", height: "100%", 'max-width': "100%"},
  16528. audio: {width: "100%", height: "30px"},
  16529. flash: {width: "auto", height: "100%", 'max-width': "100%"},
  16530. object: {height: "100%"},
  16531. pdf: {width: "160px", height: "160px"},
  16532. other: {width: "160px", height: "160px"}
  16533. },
  16534. previewZoomSettings: {
  16535. image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
  16536. html: vDefaultDim,
  16537. text: vDefaultDim,
  16538. video: {width: "auto", height: "100%", 'max-width': "100%"},
  16539. audio: {width: "100%", height: "30px"},
  16540. flash: {width: "auto", height: "480px"},
  16541. object: {width: "auto", height: "100%", 'max-width': "100%", 'min-height': "480px"},
  16542. pdf: vDefaultDim,
  16543. other: {width: "auto", height: "100%", 'min-height': "480px"}
  16544. },
  16545. fileTypeSettings: {
  16546. image: function (vType, vName) {
  16547. return $h.compare(vType, 'image.*') || $h.compare(vName, /\.(gif|png|jpe?g)$/i);
  16548. },
  16549. html: function (vType, vName) {
  16550. return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
  16551. },
  16552. text: function (vType, vName) {
  16553. return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
  16554. $h.compare(vName, /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
  16555. },
  16556. video: function (vType, vName) {
  16557. return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
  16558. $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
  16559. },
  16560. audio: function (vType, vName) {
  16561. return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
  16562. $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
  16563. },
  16564. flash: function (vType, vName) {
  16565. return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName, /\.(swf)$/i);
  16566. },
  16567. pdf: function (vType, vName) {
  16568. return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
  16569. },
  16570. object: function () {
  16571. return true;
  16572. },
  16573. other: function () {
  16574. return true;
  16575. }
  16576. },
  16577. fileActionSettings: {
  16578. showRemove: true,
  16579. showUpload: true,
  16580. showZoom: true,
  16581. showDrag: true,
  16582. removeIcon: '<i class="glyphicon glyphicon-trash text-danger"></i>',
  16583. removeClass: 'btn btn-xs btn-default',
  16584. removeTitle: 'Remove file',
  16585. uploadIcon: '<i class="glyphicon glyphicon-upload text-info"></i>',
  16586. uploadClass: 'btn btn-xs btn-default',
  16587. uploadTitle: 'Upload file',
  16588. zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
  16589. zoomClass: 'btn btn-xs btn-default',
  16590. zoomTitle: 'View Details',
  16591. dragIcon: '<i class="glyphicon glyphicon-menu-hamburger"></i>',
  16592. dragClass: 'text-info',
  16593. dragTitle: 'Move / Rearrange',
  16594. dragSettings: {},
  16595. indicatorNew: '<i class="glyphicon glyphicon-hand-down text-warning"></i>',
  16596. indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
  16597. indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
  16598. indicatorLoading: '<i class="glyphicon glyphicon-hand-up text-muted"></i>',
  16599. indicatorNewTitle: 'Not uploaded yet',
  16600. indicatorSuccessTitle: 'Uploaded',
  16601. indicatorErrorTitle: 'Upload Error',
  16602. indicatorLoadingTitle: 'Uploading ...'
  16603. }
  16604. };
  16605. $.each(self.defaults, function (key, setting) {
  16606. if (key === 'allowedPreviewTypes') {
  16607. if (self.allowedPreviewTypes === undefined) {
  16608. self.allowedPreviewTypes = setting;
  16609. }
  16610. return;
  16611. }
  16612. self[key] = $.extend(true, {}, setting, self[key]);
  16613. });
  16614. self._initPreviewTemplates();
  16615. },
  16616. _initPreviewTemplates: function () {
  16617. var self = this, cfg = self.defaults, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
  16618. $.each(cfg.previewContentTemplates, function (key, value) {
  16619. if ($h.isEmpty(self.previewTemplates[key])) {
  16620. tagBef = tags.tagBefore2;
  16621. if (key === 'generic' || key === 'image' || key === 'html' || key === 'text') {
  16622. tagBef = tags.tagBefore1;
  16623. }
  16624. self.previewTemplates[key] = tagBef + value + tagAft;
  16625. }
  16626. });
  16627. },
  16628. _initPreviewCache: function () {
  16629. var self = this;
  16630. self.previewCache = {
  16631. data: {},
  16632. init: function () {
  16633. var content = self.initialPreview;
  16634. if (content.length > 0 && !$h.isArray(content)) {
  16635. content = content.split(self.initialPreviewDelimiter);
  16636. }
  16637. self.previewCache.data = {
  16638. content: content,
  16639. config: self.initialPreviewConfig,
  16640. tags: self.initialPreviewThumbTags
  16641. };
  16642. },
  16643. fetch: function () {
  16644. return self.previewCache.data.content.filter(function (n) {
  16645. return n !== null;
  16646. });
  16647. },
  16648. count: function (all) {
  16649. return !!self.previewCache.data && !!self.previewCache.data.content ?
  16650. (all ? self.previewCache.data.content.length : self.previewCache.fetch().length) : 0;
  16651. },
  16652. get: function (i, isDisabled) {
  16653. var ind = 'init_' + i, data = self.previewCache.data, config = data.config[i],
  16654. content = data.content[i], previewId = self.previewInitId + '-' + ind, out, $tmp, cat, ftr,
  16655. fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
  16656. parseTemplate = function (cat, dat, fn, ft, id, ftr, ind, fc, t) {
  16657. fc = ' file-preview-initial ' + $h.SORT_CSS + (fc ? ' ' + fc : '');
  16658. return self._generatePreviewTemplate(cat, dat, fn, ft, id, false, null, fc, ftr, ind, t);
  16659. };
  16660. if (!content) {
  16661. return '';
  16662. }
  16663. isDisabled = isDisabled === undefined ? true : isDisabled;
  16664. cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
  16665. fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
  16666. ftype = $h.ifSet('filetype', config, cat);
  16667. ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
  16668. frameClass = $h.ifSet('frameClass', config);
  16669. if (asData) {
  16670. out = parseTemplate(cat, content, fname, ftype, previewId, ftr, ind, frameClass);
  16671. } else {
  16672. out = parseTemplate('generic', content, fname, ftype, previewId, ftr, ind, frameClass, cat)
  16673. .setTokens({'content': data.content[i]});
  16674. }
  16675. if (data.tags.length && data.tags[i]) {
  16676. out = $h.replaceTags(out, data.tags[i]);
  16677. }
  16678. /** @namespace config.frameAttr */
  16679. if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
  16680. $tmp = $(document.createElement('div')).html(out);
  16681. $tmp.find('.file-preview-initial').attr(config.frameAttr);
  16682. out = $tmp.html();
  16683. $tmp.remove();
  16684. }
  16685. return out;
  16686. },
  16687. add: function (content, config, tags, append) {
  16688. var data = self.previewCache.data, index;
  16689. if (!$h.isArray(content)) {
  16690. content = content.split(self.initialPreviewDelimiter);
  16691. }
  16692. if (append) {
  16693. index = data.content.push(content) - 1;
  16694. data.config[index] = config;
  16695. data.tags[index] = tags;
  16696. } else {
  16697. index = content.length - 1;
  16698. data.content = content;
  16699. data.config = config;
  16700. data.tags = tags;
  16701. }
  16702. self.previewCache.data = data;
  16703. return index;
  16704. },
  16705. set: function (content, config, tags, append) {
  16706. var data = self.previewCache.data, i, chk;
  16707. if (!content || !content.length) {
  16708. return;
  16709. }
  16710. if (!$h.isArray(content)) {
  16711. content = content.split(self.initialPreviewDelimiter);
  16712. }
  16713. chk = content.filter(function (n) {
  16714. return n !== null;
  16715. });
  16716. if (!chk.length) {
  16717. return;
  16718. }
  16719. if (data.content === undefined) {
  16720. data.content = [];
  16721. }
  16722. if (data.config === undefined) {
  16723. data.config = [];
  16724. }
  16725. if (data.tags === undefined) {
  16726. data.tags = [];
  16727. }
  16728. if (append) {
  16729. for (i = 0; i < content.length; i++) {
  16730. if (content[i]) {
  16731. data.content.push(content[i]);
  16732. }
  16733. }
  16734. for (i = 0; i < config.length; i++) {
  16735. if (config[i]) {
  16736. data.config.push(config[i]);
  16737. }
  16738. }
  16739. for (i = 0; i < tags.length; i++) {
  16740. if (tags[i]) {
  16741. data.tags.push(tags[i]);
  16742. }
  16743. }
  16744. } else {
  16745. data.content = content;
  16746. data.config = config;
  16747. data.tags = tags;
  16748. }
  16749. self.previewCache.data = data;
  16750. },
  16751. unset: function (index) {
  16752. var chk = self.previewCache.count();
  16753. if (!chk) {
  16754. return;
  16755. }
  16756. if (chk === 1) {
  16757. self.previewCache.data.content = [];
  16758. self.previewCache.data.config = [];
  16759. self.previewCache.data.tags = [];
  16760. self.initialPreview = [];
  16761. self.initialPreviewConfig = [];
  16762. self.initialPreviewThumbTags = [];
  16763. return;
  16764. }
  16765. self.previewCache.data.content[index] = null;
  16766. self.previewCache.data.config[index] = null;
  16767. self.previewCache.data.tags[index] = null;
  16768. },
  16769. out: function () {
  16770. var html = '', caption, len = self.previewCache.count(true), i;
  16771. if (len === 0) {
  16772. return {content: '', caption: ''};
  16773. }
  16774. for (i = 0; i < len; i++) {
  16775. html += self.previewCache.get(i);
  16776. }
  16777. caption = self._getMsgSelected(self.previewCache.count());
  16778. return {content: html, caption: caption};
  16779. },
  16780. footer: function (i, isDisabled, size) {
  16781. var data = self.previewCache.data;
  16782. if (!data || !data.config || data.config.length === 0 || $h.isEmpty(data.config[i])) {
  16783. return '';
  16784. }
  16785. isDisabled = isDisabled === undefined ? true : isDisabled;
  16786. var config = data.config[i], caption = $h.ifSet('caption', config), actions,
  16787. width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
  16788. key = $h.ifSet('key', config, null), fs = self.fileActionSettings,
  16789. initPreviewShowDel = self.initialPreviewShowDelete || false,
  16790. showDel = $h.ifSet('showDelete', config, $h.ifSet('showDelete', fs, initPreviewShowDel)),
  16791. showZoom = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
  16792. showDrag = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
  16793. disabled = (url === false) && isDisabled;
  16794. actions = self._renderFileActions(false, showDel, showZoom, showDrag, disabled, url, key, true);
  16795. return self._getLayoutTemplate('footer').setTokens({
  16796. 'progress': self._renderThumbProgress(),
  16797. 'actions': actions,
  16798. 'caption': caption,
  16799. 'size': self._getSize(size),
  16800. 'width': width,
  16801. 'indicator': ''
  16802. });
  16803. }
  16804. };
  16805. self.previewCache.init();
  16806. },
  16807. _handler: function ($el, event, callback) {
  16808. var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
  16809. if (!$el || !$el.length) {
  16810. return;
  16811. }
  16812. $el.off(ev).on(ev, callback);
  16813. },
  16814. _log: function (msg) {
  16815. var self = this, id = self.$element.attr('id');
  16816. if (id) {
  16817. msg = '"' + id + '": ' + msg;
  16818. }
  16819. if (typeof window.console.log !== "undefined") {
  16820. window.console.log(msg);
  16821. } else {
  16822. window.alert(msg);
  16823. }
  16824. },
  16825. _validate: function () {
  16826. var self = this, status = self.$element.attr('type') === 'file';
  16827. if (!status) {
  16828. self._log('The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.');
  16829. }
  16830. return status;
  16831. },
  16832. _errorsExist: function () {
  16833. var self = this, $err;
  16834. if (self.$errorContainer.find('li').length) {
  16835. return true;
  16836. }
  16837. $err = $(document.createElement('div')).html(self.$errorContainer.html());
  16838. $err.find('span.kv-error-close').remove();
  16839. $err.find('ul').remove();
  16840. return $.trim($err.text()).length ? true : false;
  16841. },
  16842. _errorHandler: function (evt, caption) {
  16843. var self = this, err = evt.target.error, showError = function (msg) {
  16844. self._showError(msg.replace('{name}', caption));
  16845. };
  16846. /** @namespace err.NOT_FOUND_ERR */
  16847. /** @namespace err.SECURITY_ERR */
  16848. /** @namespace err.NOT_READABLE_ERR */
  16849. if (err.code === err.NOT_FOUND_ERR) {
  16850. showError(self.msgFileNotFound);
  16851. } else if (err.code === err.SECURITY_ERR) {
  16852. showError(self.msgFileSecured);
  16853. } else if (err.code === err.NOT_READABLE_ERR) {
  16854. showError(self.msgFileNotReadable);
  16855. } else if (err.code === err.ABORT_ERR) {
  16856. showError(self.msgFilePreviewAborted);
  16857. } else {
  16858. showError(self.msgFilePreviewError);
  16859. }
  16860. },
  16861. _addError: function (msg) {
  16862. var self = this, $error = self.$errorContainer;
  16863. if (msg && $error.length) {
  16864. $error.html(self.errorCloseButton + msg);
  16865. self._handler($error.find('.kv-error-close'), 'click', function () {
  16866. $error.fadeOut('slow');
  16867. });
  16868. }
  16869. },
  16870. _resetErrors: function (fade) {
  16871. var self = this, $error = self.$errorContainer;
  16872. self.isError = false;
  16873. self.$container.removeClass('has-error');
  16874. $error.html('');
  16875. if (fade) {
  16876. $error.fadeOut('slow');
  16877. } else {
  16878. $error.hide();
  16879. }
  16880. },
  16881. _showFolderError: function (folders) {
  16882. var self = this, $error = self.$errorContainer, msg;
  16883. if (!folders) {
  16884. return;
  16885. }
  16886. msg = self.msgFoldersNotAllowed.replace('{n}', folders);
  16887. self._addError(msg);
  16888. $h.addCss(self.$container, 'has-error');
  16889. $error.fadeIn(800);
  16890. self._raise('filefoldererror', [folders, msg]);
  16891. },
  16892. _showUploadError: function (msg, params, event) {
  16893. var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror', e = params && params.id ?
  16894. '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
  16895. if ($error.find('ul').length === 0) {
  16896. self._addError('<ul>' + e + '</ul>');
  16897. } else {
  16898. $error.find('ul').append(e);
  16899. }
  16900. $error.fadeIn(800);
  16901. self._raise(ev, [params, msg]);
  16902. self.$container.removeClass('file-input-new');
  16903. $h.addCss(self.$container, 'has-error');
  16904. return true;
  16905. },
  16906. _showError: function (msg, params, event) {
  16907. var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
  16908. params = params || {};
  16909. params.reader = self.reader;
  16910. self._addError(msg);
  16911. $error.fadeIn(800);
  16912. self._raise(ev, [params, msg]);
  16913. if (!self.isUploadable) {
  16914. self._clearFileInput();
  16915. }
  16916. self.$container.removeClass('file-input-new');
  16917. $h.addCss(self.$container, 'has-error');
  16918. self.$btnUpload.attr('disabled', true);
  16919. return true;
  16920. },
  16921. _noFilesError: function (params) {
  16922. var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
  16923. msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
  16924. $error = self.$errorContainer;
  16925. self._addError(msg);
  16926. self.isError = true;
  16927. self._updateFileDetails(0);
  16928. $error.fadeIn(800);
  16929. self._raise('fileerror', [params, msg]);
  16930. self._clearFileInput();
  16931. $h.addCss(self.$container, 'has-error');
  16932. },
  16933. _parseError: function (operation, jqXHR, errorThrown, fileName) {
  16934. /** @namespace jqXHR.responseJSON */
  16935. var self = this, errMsg = $.trim(errorThrown + ''), dot = errMsg.slice(-1) === '.' ? '' : '.',
  16936. text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
  16937. jqXHR.responseJSON.error : jqXHR.responseText;
  16938. if (self.cancelling && self.msgUploadAborted) {
  16939. errMsg = self.msgUploadAborted;
  16940. }
  16941. if (self.showAjaxErrorDetails && text) {
  16942. text = $.trim(text.replace(/\n\s*\n/g, '\n'));
  16943. text = text.length > 0 ? '<pre>' + text + '</pre>' : '';
  16944. errMsg += dot + text;
  16945. } else {
  16946. errMsg += dot;
  16947. }
  16948. if (errMsg === dot) {
  16949. errMsg = self.msgAjaxError.replace('{operation}', operation);
  16950. }
  16951. self.cancelling = false;
  16952. return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
  16953. },
  16954. _parseFileType: function (file) {
  16955. var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
  16956. for (i = 0; i < types.length; i++) {
  16957. cat = types[i];
  16958. isValid = self.fileTypeSettings[cat];
  16959. vType = isValid(file.type, file.name) ? cat : '';
  16960. if (!$h.isEmpty(vType)) {
  16961. return vType;
  16962. }
  16963. }
  16964. return 'other';
  16965. },
  16966. _getPreviewIcon: function (fname) {
  16967. var self = this, ext, out = null;
  16968. if (fname && fname.indexOf('.') > -1) {
  16969. ext = fname.split('.').pop();
  16970. if (self.previewFileIconSettings) {
  16971. out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
  16972. }
  16973. if (self.previewFileExtSettings) {
  16974. $.each(self.previewFileExtSettings, function (key, func) {
  16975. if (self.previewFileIconSettings[key] && func(ext)) {
  16976. out = self.previewFileIconSettings[key];
  16977. //noinspection UnnecessaryReturnStatementJS
  16978. return;
  16979. }
  16980. });
  16981. }
  16982. }
  16983. return out;
  16984. },
  16985. _parseFilePreviewIcon: function (content, fname) {
  16986. var self = this, icn = self._getPreviewIcon(fname) || self.previewFileIcon, out = content;
  16987. if (out.indexOf('{previewFileIcon}') > -1) {
  16988. out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
  16989. }
  16990. return out;
  16991. },
  16992. _raise: function (event, params) {
  16993. var self = this, e = $.Event(event);
  16994. if (params !== undefined) {
  16995. self.$element.trigger(e, params);
  16996. } else {
  16997. self.$element.trigger(e);
  16998. }
  16999. if (e.isDefaultPrevented() || e.result === false) {
  17000. return false;
  17001. }
  17002. switch (event) {
  17003. // ignore these events
  17004. case 'filebatchuploadcomplete':
  17005. case 'filebatchuploadsuccess':
  17006. case 'fileuploaded':
  17007. case 'fileclear':
  17008. case 'filecleared':
  17009. case 'filereset':
  17010. case 'fileerror':
  17011. case 'filefoldererror':
  17012. case 'fileuploaderror':
  17013. case 'filebatchuploaderror':
  17014. case 'filedeleteerror':
  17015. case 'filecustomerror':
  17016. case 'filesuccessremove':
  17017. break;
  17018. // receive data response via `filecustomerror` event`
  17019. default:
  17020. if (!self.ajaxAborted) {
  17021. self.ajaxAborted = e.result;
  17022. }
  17023. break;
  17024. }
  17025. return true;
  17026. },
  17027. _listenFullScreen: function (isFullScreen) {
  17028. var self = this, $modal = self.$modal, $btnFull, $btnBord;
  17029. if (!$modal || !$modal.length) {
  17030. return;
  17031. }
  17032. $btnFull = $modal && $modal.find('.btn-fullscreen');
  17033. $btnBord = $modal && $modal.find('.btn-borderless');
  17034. if (!$btnFull.length || !$btnBord.length) {
  17035. return;
  17036. }
  17037. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17038. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17039. if (isFullScreen) {
  17040. $btnFull.addClass('active').attr('aria-pressed', 'true');
  17041. } else {
  17042. $btnBord.addClass('active').attr('aria-pressed', 'true');
  17043. }
  17044. if ($modal.hasClass('file-zoom-fullscreen')) {
  17045. self._maximizeZoomDialog();
  17046. } else {
  17047. if (isFullScreen) {
  17048. self._maximizeZoomDialog();
  17049. } else {
  17050. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17051. }
  17052. }
  17053. },
  17054. _listen: function () {
  17055. var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEvents;
  17056. self._handler($el, 'change', $.proxy(self._change, self));
  17057. if (self.showBrowse) {
  17058. self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
  17059. }
  17060. self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
  17061. self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
  17062. self._initDragDrop();
  17063. self._handler($form, 'reset', $.proxy(self.reset, self));
  17064. if (!self.isUploadable) {
  17065. self._handler($form, 'submit', $.proxy(self._submitForm, self));
  17066. }
  17067. self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
  17068. self._handler($(window), 'resize', function () {
  17069. self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
  17070. });
  17071. fullScreenEvents = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
  17072. self._handler($(document), fullScreenEvents, function () {
  17073. self._listenFullScreen($h.checkFullScreen());
  17074. });
  17075. self._initClickable();
  17076. },
  17077. _initClickable: function () {
  17078. var self = this, $zone;
  17079. if (!self.isClickable) {
  17080. return;
  17081. }
  17082. $zone = self.isUploadable ? self.$dropZone : self.$preview.find('.file-default-preview');
  17083. $h.addCss($zone, 'clickable');
  17084. $zone.attr('tabindex', -1);
  17085. self._handler($zone, 'click', function (e) {
  17086. var $tar = $(e.target);
  17087. if (!$tar.parents('.file-preview-thumbnails').length || $tar.parents('.file-default-preview').length) {
  17088. self.$element.trigger('click');
  17089. $zone.blur();
  17090. }
  17091. });
  17092. },
  17093. _initDragDrop: function () {
  17094. var self = this, $zone = self.$dropZone;
  17095. if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
  17096. self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
  17097. self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
  17098. self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
  17099. self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
  17100. }
  17101. },
  17102. _zoneDragDropInit: function (e) {
  17103. e.stopPropagation();
  17104. e.preventDefault();
  17105. },
  17106. _zoneDragEnter: function (e) {
  17107. var self = this, hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
  17108. self._zoneDragDropInit(e);
  17109. if (self.isDisabled || !hasFiles) {
  17110. e.originalEvent.dataTransfer.effectAllowed = 'none';
  17111. e.originalEvent.dataTransfer.dropEffect = 'none';
  17112. return;
  17113. }
  17114. $h.addCss(self.$dropZone, 'file-highlighted');
  17115. },
  17116. _zoneDragLeave: function (e) {
  17117. var self = this;
  17118. self._zoneDragDropInit(e);
  17119. if (self.isDisabled) {
  17120. return;
  17121. }
  17122. self.$dropZone.removeClass('file-highlighted');
  17123. },
  17124. _zoneDrop: function (e) {
  17125. var self = this;
  17126. e.preventDefault();
  17127. /** @namespace e.originalEvent.dataTransfer */
  17128. if (self.isDisabled || $h.isEmpty(e.originalEvent.dataTransfer.files)) {
  17129. return;
  17130. }
  17131. self._change(e, 'dragdrop');
  17132. self.$dropZone.removeClass('file-highlighted');
  17133. },
  17134. _uploadClick: function (e) {
  17135. var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
  17136. isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
  17137. if (e && e.isDefaultPrevented()) {
  17138. return;
  17139. }
  17140. if (!self.isUploadable) {
  17141. if (isEnabled && $btn.attr('type') !== 'submit') {
  17142. $form = $btn.closest('form');
  17143. // downgrade to normal form submit if possible
  17144. if ($form.length) {
  17145. $form.trigger('submit');
  17146. }
  17147. e.preventDefault();
  17148. }
  17149. return;
  17150. }
  17151. e.preventDefault();
  17152. if (isEnabled) {
  17153. self.upload();
  17154. }
  17155. },
  17156. _submitForm: function () {
  17157. var self = this;
  17158. return self._isFileSelectionValid() && !self._abort({});
  17159. },
  17160. _clearPreview: function () {
  17161. var self = this, $p = self.$preview,
  17162. $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
  17163. $thumbs.each(function () {
  17164. var $thumb = $(this);
  17165. $thumb.remove();
  17166. $h.cleanZoomCache($p.find('#zoom-' + $thumb.attr('id')));
  17167. });
  17168. if (!self.getFrames().length || !self.showPreview) {
  17169. self._resetUpload();
  17170. }
  17171. self._validateDefaultPreview();
  17172. },
  17173. _initSortable: function () {
  17174. var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS;
  17175. if (!window.KvSortable || $el.find(selector).length === 0) {
  17176. return;
  17177. }
  17178. //noinspection JSUnusedGlobalSymbols
  17179. settings = {
  17180. handle: '.drag-handle-init',
  17181. dataIdAttr: 'data-preview-id',
  17182. scroll: false,
  17183. draggable: selector,
  17184. onSort: function (e) {
  17185. var oldIndex = e.oldIndex, newIndex = e.newIndex, key, $frame;
  17186. self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex);
  17187. self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex);
  17188. self.previewCache.init();
  17189. for (var i = 0; i < self.initialPreviewConfig.length; i++) {
  17190. if (self.initialPreviewConfig[i] !== null) {
  17191. key = self.initialPreviewConfig[i].key;
  17192. $frame = $(".kv-file-remove[data-key='" + key + "']").closest($h.FRAMES);
  17193. $frame.attr('data-fileindex', 'init_' + i).attr('data-fileindex', 'init_' + i);
  17194. }
  17195. }
  17196. self._raise('filesorted', {
  17197. previewId: $(e.item).attr('id'),
  17198. 'oldIndex': oldIndex,
  17199. 'newIndex': newIndex,
  17200. stack: self.initialPreviewConfig
  17201. });
  17202. }
  17203. };
  17204. if ($el.data('kvsortable')) {
  17205. $el.kvsortable('destroy');
  17206. }
  17207. $.extend(true, settings, self.fileActionSettings.dragSettings);
  17208. $el.kvsortable(settings);
  17209. },
  17210. _initPreview: function (isInit) {
  17211. var self = this, cap = self.initialCaption || '', out;
  17212. if (!self.previewCache.count()) {
  17213. self._clearPreview();
  17214. if (isInit) {
  17215. self._setCaption(cap);
  17216. } else {
  17217. self._initCaption();
  17218. }
  17219. return;
  17220. }
  17221. out = self.previewCache.out();
  17222. cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
  17223. self.$preview.html(out.content);
  17224. self._setInitThumbAttr();
  17225. self._setCaption(cap);
  17226. self._initSortable();
  17227. if (!$h.isEmpty(out.content)) {
  17228. self.$container.removeClass('file-input-new');
  17229. }
  17230. },
  17231. _getZoomButton: function (type) {
  17232. var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
  17233. title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ',
  17234. params = title + (type === 'close' ? ' data-dismiss="modal" aria-hidden="true"' : '');
  17235. if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
  17236. params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
  17237. }
  17238. return '<button type="button" class="' + css + ' btn-' + type + '"' + params + '>' + label + '</button>';
  17239. },
  17240. _getModalContent: function () {
  17241. var self = this;
  17242. return self._getLayoutTemplate('modal').setTokens({
  17243. 'rtl': self.rtl ? ' kv-rtl' : '',
  17244. 'zoomFrameClass': self.frameClass,
  17245. 'heading': self.msgZoomModalHeading,
  17246. 'prev': self._getZoomButton('prev'),
  17247. 'next': self._getZoomButton('next'),
  17248. 'toggleheader': self._getZoomButton('toggleheader'),
  17249. 'fullscreen': self._getZoomButton('fullscreen'),
  17250. 'borderless': self._getZoomButton('borderless'),
  17251. 'close': self._getZoomButton('close')
  17252. });
  17253. },
  17254. _listenModalEvent: function (event) {
  17255. var self = this, $modal = self.$modal, getParams = function (e) {
  17256. return {
  17257. sourceEvent: e,
  17258. previewId: $modal.data('previewId'),
  17259. modal: $modal
  17260. };
  17261. };
  17262. $modal.on(event + '.bs.modal', function (e) {
  17263. var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
  17264. self._raise('filezoom' + event, getParams(e));
  17265. if (event === 'shown') {
  17266. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17267. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17268. if ($modal.hasClass('file-zoom-fullscreen')) {
  17269. self._maximizeZoomDialog();
  17270. if ($h.checkFullScreen()) {
  17271. $btnFull.addClass('active').attr('aria-pressed', 'true');
  17272. } else {
  17273. $btnBord.addClass('active').attr('aria-pressed', 'true');
  17274. }
  17275. }
  17276. }
  17277. });
  17278. },
  17279. _initZoom: function () {
  17280. var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
  17281. if (!self.showPreview) {
  17282. return;
  17283. }
  17284. self.$modal = $(modalId);
  17285. if (!self.$modal || !self.$modal.length) {
  17286. $dialog = $(document.createElement('div')).html(modalMain).insertAfter(self.$container);
  17287. self.$modal = $(modalId).insertBefore($dialog);
  17288. $dialog.remove();
  17289. }
  17290. $h.initModal(self.$modal);
  17291. self.$modal.html(self._getModalContent());
  17292. $.each($h.MODAL_EVENTS, function (key, event) {
  17293. self._listenModalEvent(event);
  17294. });
  17295. },
  17296. _initZoomButtons: function () {
  17297. var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
  17298. thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-prev'),
  17299. $next = self.$modal.find('.btn-next');
  17300. if (thumbs.length < 2) {
  17301. $prev.hide();
  17302. $next.hide();
  17303. return;
  17304. } else {
  17305. $prev.show();
  17306. $next.show();
  17307. }
  17308. if (!len) {
  17309. return;
  17310. }
  17311. $first = $(thumbs[0]);
  17312. $last = $(thumbs[len - 1]);
  17313. $prev.removeAttr('disabled');
  17314. $next.removeAttr('disabled');
  17315. if ($first.length && $first.attr('id') === previewId) {
  17316. $prev.attr('disabled', true);
  17317. }
  17318. if ($last.length && $last.attr('id') === previewId) {
  17319. $next.attr('disabled', true);
  17320. }
  17321. },
  17322. _maximizeZoomDialog: function () {
  17323. var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
  17324. $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.modal-body'),
  17325. h = $(window).height(), diff = 0;
  17326. $modal.addClass('file-zoom-fullscreen');
  17327. if ($head && $head.length) {
  17328. h -= $head.outerHeight(true);
  17329. }
  17330. if ($foot && $foot.length) {
  17331. h -= $foot.outerHeight(true);
  17332. }
  17333. if ($body && $body.length) {
  17334. diff = $body.outerHeight(true) - $body.height();
  17335. h -= diff;
  17336. }
  17337. $modal.find('.kv-zoom-body').height(h);
  17338. },
  17339. _resizeZoomDialog: function (fullScreen) {
  17340. var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-fullscreen'),
  17341. $btnBord = $modal.find('.btn-borderless');
  17342. if ($modal.hasClass('file-zoom-fullscreen')) {
  17343. $h.toggleFullScreen(false);
  17344. if (!fullScreen) {
  17345. if (!$btnFull.hasClass('active')) {
  17346. $modal.removeClass('file-zoom-fullscreen');
  17347. self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
  17348. } else {
  17349. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17350. }
  17351. } else {
  17352. if (!$btnFull.hasClass('active')) {
  17353. $modal.removeClass('file-zoom-fullscreen');
  17354. self._resizeZoomDialog(true);
  17355. if ($btnBord.hasClass('active')) {
  17356. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17357. }
  17358. }
  17359. }
  17360. } else {
  17361. if (!fullScreen) {
  17362. self._maximizeZoomDialog();
  17363. return;
  17364. }
  17365. $h.toggleFullScreen(true);
  17366. }
  17367. $modal.focus();
  17368. },
  17369. _setZoomContent: function ($frame, animate) {
  17370. var self = this, $content, tmplt, body, title, $body, $dataEl, config, pid = $frame.attr('id'),
  17371. $modal = self.$modal, $prev = $modal.find('.btn-prev'), $next = $modal.find('.btn-next'), $tmp,
  17372. $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless'), cap, size,
  17373. $btnTogh = $modal.find('.btn-toggleheader'), $zoomPreview = self.$preview.find('#zoom-' + pid);
  17374. tmplt = $zoomPreview.attr('data-template') || 'generic';
  17375. $content = $zoomPreview.find('.kv-file-content');
  17376. body = $content.length ? $content.html() : '';
  17377. cap = $frame.data('caption') || '';
  17378. size = $frame.data('size') || '';
  17379. title = cap + ' ' + size;
  17380. $modal.find('.kv-zoom-title').html(title);
  17381. $body = $modal.find('.kv-zoom-body');
  17382. $modal.removeClass('kv-single-content');
  17383. if (animate) {
  17384. $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
  17385. $body.html(body).hide();
  17386. $tmp.fadeOut('fast', function () {
  17387. $body.fadeIn('fast', function () {
  17388. $body.removeClass('file-thumb-loading');
  17389. });
  17390. $tmp.remove();
  17391. });
  17392. } else {
  17393. $body.html(body);
  17394. }
  17395. config = self.previewZoomSettings[tmplt];
  17396. if (config) {
  17397. $dataEl = $body.find('.kv-preview-data');
  17398. $h.addCss($dataEl, 'file-zoom-detail');
  17399. $.each(config, function (key, value) {
  17400. $dataEl.css(key, value);
  17401. if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
  17402. $dataEl.removeAttr(key);
  17403. }
  17404. });
  17405. }
  17406. $modal.data('previewId', pid);
  17407. var $img = $body.find('img');
  17408. if ($img.length) {
  17409. $h.adjustOrientedImage($img, true);
  17410. }
  17411. self._handler($prev, 'click', function () {
  17412. self._zoomSlideShow('prev', pid);
  17413. });
  17414. self._handler($next, 'click', function () {
  17415. self._zoomSlideShow('next', pid);
  17416. });
  17417. self._handler($btnFull, 'click', function () {
  17418. self._resizeZoomDialog(true);
  17419. });
  17420. self._handler($btnBord, 'click', function () {
  17421. self._resizeZoomDialog(false);
  17422. });
  17423. self._handler($btnTogh, 'click', function () {
  17424. var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.modal-body .floating-buttons'),
  17425. ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
  17426. var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
  17427. if ($modal.hasClass('file-zoom-fullscreen')) {
  17428. h = $body.outerHeight(true);
  17429. if (!height) {
  17430. h = h - $header.outerHeight(true);
  17431. }
  17432. }
  17433. $body.css('height', height ? h + height : h);
  17434. };
  17435. if ($header.is(':visible')) {
  17436. ht = $header.outerHeight(true);
  17437. $header.slideUp('slow', function () {
  17438. $actions.find('.btn').appendTo($floatBar);
  17439. resize(ht);
  17440. });
  17441. } else {
  17442. $floatBar.find('.btn').appendTo($actions);
  17443. $header.slideDown('slow', function () {
  17444. resize();
  17445. });
  17446. }
  17447. $modal.focus();
  17448. });
  17449. self._handler($modal, 'keydown', function (e) {
  17450. var key = e.which || e.keyCode;
  17451. if (key === 37 && !$prev.attr('disabled')) {
  17452. self._zoomSlideShow('prev', pid);
  17453. }
  17454. if (key === 39 && !$next.attr('disabled')) {
  17455. self._zoomSlideShow('next', pid);
  17456. }
  17457. });
  17458. },
  17459. _zoomPreview: function ($btn) {
  17460. var self = this, $frame, $modal = self.$modal;
  17461. if (!$btn.length) {
  17462. throw 'Cannot zoom to detailed preview!';
  17463. }
  17464. $h.initModal($modal);
  17465. $modal.html(self._getModalContent());
  17466. $frame = $btn.closest($h.FRAMES);
  17467. self._setZoomContent($frame);
  17468. $modal.modal('show');
  17469. self._initZoomButtons();
  17470. },
  17471. _zoomSlideShow: function (dir, previewId) {
  17472. var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-' + dir), $targFrame, i,
  17473. thumbs = self.getFrames().toArray(), len = thumbs.length, out;
  17474. if ($btn.attr('disabled')) {
  17475. return;
  17476. }
  17477. for (i = 0; i < len; i++) {
  17478. if ($(thumbs[i]).attr('id') === previewId) {
  17479. out = dir === 'prev' ? i - 1 : i + 1;
  17480. break;
  17481. }
  17482. }
  17483. if (out < 0 || out >= len || !thumbs[out]) {
  17484. return;
  17485. }
  17486. $targFrame = $(thumbs[out]);
  17487. if ($targFrame.length) {
  17488. self._setZoomContent($targFrame, true);
  17489. }
  17490. self._initZoomButtons();
  17491. self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
  17492. },
  17493. _initZoomButton: function () {
  17494. var self = this;
  17495. self.$preview.find('.kv-file-zoom').each(function () {
  17496. var $el = $(this);
  17497. self._handler($el, 'click', function () {
  17498. self._zoomPreview($el);
  17499. });
  17500. });
  17501. },
  17502. _clearObjects: function ($el) {
  17503. $el.find('video audio').each(function () {
  17504. this.pause();
  17505. $(this).remove();
  17506. });
  17507. $el.find('img object div').each(function () {
  17508. $(this).remove();
  17509. });
  17510. },
  17511. _clearFileInput: function () {
  17512. var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
  17513. self.fileInputCleared = true;
  17514. if ($h.isEmpty($el.val())) {
  17515. return;
  17516. }
  17517. // Fix for IE ver < 11, that does not clear file inputs. Requires a sequence of steps to prevent IE
  17518. // crashing but still allow clearing of the file input.
  17519. if (self.isIE9 || self.isIE10) {
  17520. $srcFrm = $el.closest('form');
  17521. $tmpFrm = $(document.createElement('form'));
  17522. $tmpEl = $(document.createElement('div'));
  17523. $el.before($tmpEl);
  17524. if ($srcFrm.length) {
  17525. $srcFrm.after($tmpFrm);
  17526. } else {
  17527. $tmpEl.after($tmpFrm);
  17528. }
  17529. $tmpFrm.append($el).trigger('reset');
  17530. $tmpEl.before($el).remove();
  17531. $tmpFrm.remove();
  17532. } else { // normal input clear behavior for other sane browsers
  17533. $el.val('');
  17534. }
  17535. },
  17536. _resetUpload: function () {
  17537. var self = this;
  17538. self.uploadCache = {content: [], config: [], tags: [], append: true};
  17539. self.uploadCount = 0;
  17540. self.uploadStatus = {};
  17541. self.uploadLog = [];
  17542. self.uploadAsyncCount = 0;
  17543. self.loadedImages = [];
  17544. self.totalImagesCount = 0;
  17545. self.$btnUpload.removeAttr('disabled');
  17546. self._setProgress(0);
  17547. $h.addCss(self.$progress, 'hide');
  17548. self._resetErrors(false);
  17549. self.ajaxAborted = false;
  17550. self.ajaxRequests = [];
  17551. self._resetCanvas();
  17552. self.cacheInitialPreview = {};
  17553. if (self.overwriteInitial) {
  17554. self.initialPreview = [];
  17555. self.initialPreviewConfig = [];
  17556. self.initialPreviewThumbTags = [];
  17557. self.previewCache.data = {
  17558. content: [],
  17559. config: [],
  17560. tags: []
  17561. };
  17562. }
  17563. },
  17564. _resetCanvas: function () {
  17565. var self = this;
  17566. if (self.canvas && self.imageCanvasContext) {
  17567. self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
  17568. }
  17569. },
  17570. _hasInitialPreview: function () {
  17571. var self = this;
  17572. return !self.overwriteInitial && self.previewCache.count();
  17573. },
  17574. _resetPreview: function () {
  17575. var self = this, out, cap;
  17576. if (self.previewCache.count()) {
  17577. out = self.previewCache.out();
  17578. self.$preview.html(out.content);
  17579. self._setInitThumbAttr();
  17580. cap = self.initialCaption ? self.initialCaption : out.caption;
  17581. self._setCaption(cap);
  17582. } else {
  17583. self._clearPreview();
  17584. self._initCaption();
  17585. }
  17586. if (self.showPreview) {
  17587. self._initZoom();
  17588. self._initSortable();
  17589. }
  17590. },
  17591. _clearDefaultPreview: function () {
  17592. var self = this;
  17593. self.$preview.find('.file-default-preview').remove();
  17594. },
  17595. _validateDefaultPreview: function () {
  17596. var self = this;
  17597. if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
  17598. return;
  17599. }
  17600. self.$preview.html('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
  17601. self.$container.removeClass('file-input-new');
  17602. self._initClickable();
  17603. },
  17604. _resetPreviewThumbs: function (isAjax) {
  17605. var self = this, out;
  17606. if (isAjax) {
  17607. self._clearPreview();
  17608. self.clearStack();
  17609. return;
  17610. }
  17611. if (self._hasInitialPreview()) {
  17612. out = self.previewCache.out();
  17613. self.$preview.html(out.content);
  17614. self._setInitThumbAttr();
  17615. self._setCaption(out.caption);
  17616. self._initPreviewActions();
  17617. } else {
  17618. self._clearPreview();
  17619. }
  17620. },
  17621. _getLayoutTemplate: function (t) {
  17622. var self = this, template = self.layoutTemplates[t];
  17623. if ($h.isEmpty(self.customLayoutTags)) {
  17624. return template;
  17625. }
  17626. return $h.replaceTags(template, self.customLayoutTags);
  17627. },
  17628. _getPreviewTemplate: function (t) {
  17629. var self = this, template = self.previewTemplates[t];
  17630. if ($h.isEmpty(self.customPreviewTags)) {
  17631. return template;
  17632. }
  17633. return $h.replaceTags(template, self.customPreviewTags);
  17634. },
  17635. _getOutData: function (jqXHR, responseData, filesData) {
  17636. var self = this;
  17637. jqXHR = jqXHR || {};
  17638. responseData = responseData || {};
  17639. filesData = filesData || self.filestack.slice(0) || {};
  17640. return {
  17641. form: self.formdata,
  17642. files: filesData,
  17643. filenames: self.filenames,
  17644. filescount: self.getFilesCount(),
  17645. extra: self._getExtraData(),
  17646. response: responseData,
  17647. reader: self.reader,
  17648. jqXHR: jqXHR
  17649. };
  17650. },
  17651. _getMsgSelected: function (n) {
  17652. var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
  17653. return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) : self.msgNoFilesSelected;
  17654. },
  17655. _getFrame: function (id) {
  17656. var self = this, $frame = $('#' + id);
  17657. if (!$frame.length) {
  17658. self._log('Invalid thumb frame with id: "' + id + '".');
  17659. return null;
  17660. }
  17661. return $frame;
  17662. },
  17663. _getThumbs: function (css) {
  17664. css = css || '';
  17665. return this.getFrames(':not(.file-preview-initial)' + css);
  17666. },
  17667. _getExtraData: function (previewId, index) {
  17668. var self = this, data = self.uploadExtraData;
  17669. if (typeof self.uploadExtraData === "function") {
  17670. data = self.uploadExtraData(previewId, index);
  17671. }
  17672. return data;
  17673. },
  17674. _initXhr: function (xhrobj, previewId, fileCount) {
  17675. var self = this;
  17676. if (xhrobj.upload) {
  17677. xhrobj.upload.addEventListener('progress', function (event) {
  17678. var pct = 0, total = event.total, position = event.loaded || event.position;
  17679. /** @namespace event.lengthComputable */
  17680. if (event.lengthComputable) {
  17681. pct = Math.floor(position / total * 100);
  17682. }
  17683. if (previewId) {
  17684. self._setAsyncUploadStatus(previewId, pct, fileCount);
  17685. } else {
  17686. self._setProgress(pct);
  17687. }
  17688. }, false);
  17689. }
  17690. return xhrobj;
  17691. },
  17692. _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
  17693. var self = this, settings;
  17694. if (!self._raise('filepreajax', [previewId, index])) {
  17695. return;
  17696. }
  17697. self._uploadExtra(previewId, index);
  17698. settings = $.extend(true, {}, {
  17699. xhr: function () {
  17700. var xhrobj = $.ajaxSettings.xhr();
  17701. return self._initXhr(xhrobj, previewId, self.getFileStack().length);
  17702. },
  17703. url: self.uploadUrl,
  17704. type: 'POST',
  17705. dataType: 'json',
  17706. data: self.formdata,
  17707. cache: false,
  17708. processData: false,
  17709. contentType: false,
  17710. beforeSend: fnBefore,
  17711. success: fnSuccess,
  17712. complete: fnComplete,
  17713. error: fnError
  17714. }, self.ajaxSettings);
  17715. self.ajaxRequests.push($.ajax(settings));
  17716. },
  17717. _mergeArray: function (prop, content) {
  17718. var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
  17719. self[prop] = arr1.concat(arr2);
  17720. },
  17721. _initUploadSuccess: function (out, $thumb, allFiles) {
  17722. var self = this, append, data, index, $div, $newCache, content, config, tags, i;
  17723. if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
  17724. return;
  17725. }
  17726. if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
  17727. self.hasInitData = true;
  17728. content = out.initialPreview || [];
  17729. config = out.initialPreviewConfig || [];
  17730. tags = out.initialPreviewThumbTags || [];
  17731. append = out.append === undefined || out.append ? true : false;
  17732. if (content.length > 0 && !$h.isArray(content)) {
  17733. content = content.split(self.initialPreviewDelimiter);
  17734. }
  17735. self._mergeArray('initialPreview', content);
  17736. self._mergeArray('initialPreviewConfig', config);
  17737. self._mergeArray('initialPreviewThumbTags', tags);
  17738. if ($thumb !== undefined) {
  17739. if (!allFiles) {
  17740. index = self.previewCache.add(content, config[0], tags[0], append);
  17741. data = self.previewCache.get(index, false);
  17742. $div = $(document.createElement('div')).html(data).hide().insertAfter($thumb);
  17743. $newCache = $div.find('.kv-zoom-cache');
  17744. if ($newCache && $newCache.length) {
  17745. $newCache.insertAfter($thumb);
  17746. }
  17747. $thumb.fadeOut('slow', function () {
  17748. var $newThumb = $div.find('.file-preview-frame');
  17749. if ($newThumb && $newThumb.length) {
  17750. $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
  17751. }
  17752. self._initPreviewActions();
  17753. self._clearFileInput();
  17754. $h.cleanZoomCache(self.$preview.find('#zoom-' + $thumb.attr('id')));
  17755. $thumb.remove();
  17756. $div.remove();
  17757. self._initSortable();
  17758. });
  17759. } else {
  17760. i = $thumb.attr('data-fileindex');
  17761. self.uploadCache.content[i] = content[0];
  17762. self.uploadCache.config[i] = config[0] || [];
  17763. self.uploadCache.tags[i] = tags[0] || [];
  17764. self.uploadCache.append = append;
  17765. }
  17766. } else {
  17767. self.previewCache.set(content, config, tags, append);
  17768. self._initPreview();
  17769. self._initPreviewActions();
  17770. }
  17771. }
  17772. },
  17773. _initSuccessThumbs: function () {
  17774. var self = this;
  17775. if (!self.showPreview) {
  17776. return;
  17777. }
  17778. self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
  17779. var $thumb = $(this), $preview = self.$preview, $remove = $thumb.find('.kv-file-remove');
  17780. $remove.removeAttr('disabled');
  17781. self._handler($remove, 'click', function () {
  17782. var id = $thumb.attr('id'),
  17783. out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
  17784. $h.cleanMemory($thumb);
  17785. if (out === false) {
  17786. return;
  17787. }
  17788. $thumb.fadeOut('slow', function () {
  17789. $h.cleanZoomCache($preview.find('#zoom-' + id));
  17790. $thumb.remove();
  17791. if (!self.getFrames().length) {
  17792. self.reset();
  17793. }
  17794. });
  17795. });
  17796. });
  17797. },
  17798. _checkAsyncComplete: function () {
  17799. var self = this, previewId, i;
  17800. for (i = 0; i < self.filestack.length; i++) {
  17801. if (self.filestack[i]) {
  17802. previewId = self.previewInitId + "-" + i;
  17803. if ($.inArray(previewId, self.uploadLog) === -1) {
  17804. return false;
  17805. }
  17806. }
  17807. }
  17808. return (self.uploadAsyncCount === self.uploadLog.length);
  17809. },
  17810. _uploadExtra: function (previewId, index) {
  17811. var self = this, data = self._getExtraData(previewId, index);
  17812. if (data.length === 0) {
  17813. return;
  17814. }
  17815. $.each(data, function (key, value) {
  17816. self.formdata.append(key, value);
  17817. });
  17818. },
  17819. _uploadSingle: function (i, files, allFiles) {
  17820. var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
  17821. previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
  17822. hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  17823. $prog = $('#' + previewId).find('.file-thumb-progress'),
  17824. fnBefore, fnSuccess, fnComplete, fnError, updateUploadLog, params = {id: previewId, index: i},
  17825. uploadFailed, multiUploadMode = !$h.isEmpty(self.$element.attr('multiple'));
  17826. self.formdata = formdata;
  17827. if (self.showPreview) {
  17828. $thumb = $('#' + previewId + ':not(.file-preview-initial)');
  17829. $btnUpload = $thumb.find('.kv-file-upload');
  17830. $btnDelete = $thumb.find('.kv-file-remove');
  17831. $prog.removeClass('hide');
  17832. }
  17833. if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self._abort(params)) {
  17834. return;
  17835. }
  17836. updateUploadLog = function (i, previewId) {
  17837. if (multiUploadMode || !uploadFailed) {
  17838. self.updateStack(i, undefined);
  17839. }
  17840. self.uploadLog.push(previewId);
  17841. if (self._checkAsyncComplete()) {
  17842. self.fileBatchCompleted = true;
  17843. }
  17844. };
  17845. chkComplete = function () {
  17846. var u = self.uploadCache, $initThumbs, i, j, len = 0, data = self.cacheInitialPreview;
  17847. if (!self.fileBatchCompleted) {
  17848. return;
  17849. }
  17850. if (data && data.content) {
  17851. len = data.content.length;
  17852. }
  17853. setTimeout(function () {
  17854. var triggerReset = multiUploadMode || !uploadFailed;
  17855. if (self.showPreview) {
  17856. self.previewCache.set(u.content, u.config, u.tags, u.append);
  17857. if (len) {
  17858. for (i = 0; i < u.content.length; i++) {
  17859. j = i + len;
  17860. data.content[j] = u.content[i];
  17861. //noinspection JSUnresolvedVariable
  17862. if (data.config.length) {
  17863. data.config[j] = u.config[i];
  17864. }
  17865. if (data.tags.length) {
  17866. data.tags[j] = u.tags[i];
  17867. }
  17868. }
  17869. self.initialPreview = $h.cleanArray(data.content);
  17870. self.initialPreviewConfig = $h.cleanArray(data.config);
  17871. self.initialPreviewThumbTags = $h.cleanArray(data.tags);
  17872. } else {
  17873. self.initialPreview = u.content;
  17874. self.initialPreviewConfig = u.config;
  17875. self.initialPreviewThumbTags = u.tags;
  17876. }
  17877. self.cacheInitialPreview = {};
  17878. if (self.hasInitData) {
  17879. self._initPreview();
  17880. self._initPreviewActions();
  17881. }
  17882. }
  17883. self.unlock(triggerReset);
  17884. if (triggerReset) {
  17885. self._clearFileInput();
  17886. }
  17887. $initThumbs = self.$preview.find('.file-preview-initial');
  17888. if (self.uploadAsync && $initThumbs.length) {
  17889. $h.addCss($initThumbs, $h.SORT_CSS);
  17890. self._initSortable();
  17891. }
  17892. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  17893. self.uploadCount = 0;
  17894. self.uploadStatus = {};
  17895. self.uploadLog = [];
  17896. self._setProgress(101);
  17897. }, 100);
  17898. };
  17899. fnBefore = function (jqXHR) {
  17900. outData = self._getOutData(jqXHR);
  17901. self.fileBatchCompleted = false;
  17902. if (self.showPreview) {
  17903. if (!$thumb.hasClass('file-preview-success')) {
  17904. self._setThumbStatus($thumb, 'Loading');
  17905. $h.addCss($thumb, 'file-uploading');
  17906. }
  17907. $btnUpload.attr('disabled', true);
  17908. $btnDelete.attr('disabled', true);
  17909. }
  17910. if (!allFiles) {
  17911. self.lock();
  17912. }
  17913. self._raise('filepreupload', [outData, previewId, i]);
  17914. $.extend(true, params, outData);
  17915. if (self._abort(params)) {
  17916. jqXHR.abort();
  17917. self._setProgressCancelled();
  17918. }
  17919. };
  17920. fnSuccess = function (data, textStatus, jqXHR) {
  17921. var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
  17922. outData = self._getOutData(jqXHR, data);
  17923. $.extend(true, params, outData);
  17924. setTimeout(function () {
  17925. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  17926. if (self.showPreview) {
  17927. self._setThumbStatus($thumb, 'Success');
  17928. $btnUpload.hide();
  17929. self._initUploadSuccess(data, $thumb, allFiles);
  17930. self._setProgress(101, $prog);
  17931. }
  17932. self._raise('fileuploaded', [outData, pid, i]);
  17933. if (!allFiles) {
  17934. self.updateStack(i, undefined);
  17935. } else {
  17936. updateUploadLog(i, pid);
  17937. }
  17938. } else {
  17939. uploadFailed = true;
  17940. self._showUploadError(data.error, params);
  17941. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  17942. if (allFiles) {
  17943. updateUploadLog(i, pid);
  17944. }
  17945. }
  17946. }, 100);
  17947. };
  17948. fnComplete = function () {
  17949. setTimeout(function () {
  17950. if (self.showPreview) {
  17951. $btnUpload.removeAttr('disabled');
  17952. $btnDelete.removeAttr('disabled');
  17953. $thumb.removeClass('file-uploading');
  17954. }
  17955. if (!allFiles) {
  17956. self.unlock(false);
  17957. self._clearFileInput();
  17958. } else {
  17959. chkComplete();
  17960. }
  17961. self._initSuccessThumbs();
  17962. }, 100);
  17963. };
  17964. fnError = function (jqXHR, textStatus, errorThrown) {
  17965. var op = self.ajaxOperations.uploadThumb,
  17966. errMsg = self._parseError(op, jqXHR, errorThrown, (allFiles ? files[i].name : null));
  17967. uploadFailed = true;
  17968. setTimeout(function () {
  17969. if (allFiles) {
  17970. updateUploadLog(i, previewId);
  17971. }
  17972. self.uploadStatus[previewId] = 100;
  17973. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  17974. $.extend(true, params, self._getOutData(jqXHR));
  17975. self._setProgress(101, $prog, self.msgAjaxProgressError.replace('{operation}', op));
  17976. self._showUploadError(errMsg, params);
  17977. }, 100);
  17978. };
  17979. formdata.append(self.uploadFileAttr, files[i], self.filenames[i]);
  17980. formdata.append('file_id', i);
  17981. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
  17982. },
  17983. _uploadBatch: function () {
  17984. var self = this, files = self.filestack, total = files.length, params = {}, fnBefore, fnSuccess, fnError,
  17985. fnComplete, hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  17986. setAllUploaded;
  17987. self.formdata = new FormData();
  17988. if (total === 0 || !hasPostData || self._abort(params)) {
  17989. return;
  17990. }
  17991. setAllUploaded = function () {
  17992. $.each(files, function (key) {
  17993. self.updateStack(key, undefined);
  17994. });
  17995. self._clearFileInput();
  17996. };
  17997. fnBefore = function (jqXHR) {
  17998. self.lock();
  17999. var outData = self._getOutData(jqXHR);
  18000. if (self.showPreview) {
  18001. self._getThumbs().each(function () {
  18002. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
  18003. $btnDelete = $thumb.find('.kv-file-remove');
  18004. if (!$thumb.hasClass('file-preview-success')) {
  18005. self._setThumbStatus($thumb, 'Loading');
  18006. $h.addCss($thumb, 'file-uploading');
  18007. }
  18008. $btnUpload.attr('disabled', true);
  18009. $btnDelete.attr('disabled', true);
  18010. });
  18011. }
  18012. self._raise('filebatchpreupload', [outData]);
  18013. if (self._abort(outData)) {
  18014. jqXHR.abort();
  18015. self._setProgressCancelled();
  18016. }
  18017. };
  18018. fnSuccess = function (data, textStatus, jqXHR) {
  18019. /** @namespace data.errorkeys */
  18020. var outData = self._getOutData(jqXHR, data), $thumbs = self._getThumbs(':not(.file-preview-error)'),
  18021. key = 0,
  18022. keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
  18023. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18024. self._raise('filebatchuploadsuccess', [outData]);
  18025. setAllUploaded();
  18026. if (self.showPreview) {
  18027. $thumbs.each(function () {
  18028. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload');
  18029. $thumb.find('.kv-file-upload').hide();
  18030. self._setThumbStatus($thumb, 'Success');
  18031. $thumb.removeClass('file-uploading');
  18032. $btnUpload.removeAttr('disabled');
  18033. });
  18034. self._initUploadSuccess(data);
  18035. } else {
  18036. self.reset();
  18037. }
  18038. self._setProgress(101);
  18039. } else {
  18040. if (self.showPreview) {
  18041. $thumbs.each(function () {
  18042. var $thumb = $(this), $btnDelete = $thumb.find('.kv-file-remove'),
  18043. $btnUpload = $thumb.find('.kv-file-upload');
  18044. $thumb.removeClass('file-uploading');
  18045. $btnUpload.removeAttr('disabled');
  18046. $btnDelete.removeAttr('disabled');
  18047. if (keys.length === 0) {
  18048. self._setPreviewError($thumb);
  18049. return;
  18050. }
  18051. if ($.inArray(key, keys) !== -1) {
  18052. self._setPreviewError($thumb);
  18053. } else {
  18054. $thumb.find('.kv-file-upload').hide();
  18055. self._setThumbStatus($thumb, 'Success');
  18056. self.updateStack(key, undefined);
  18057. }
  18058. key++;
  18059. });
  18060. self._initUploadSuccess(data);
  18061. }
  18062. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  18063. }
  18064. };
  18065. fnComplete = function () {
  18066. self.unlock();
  18067. self._initSuccessThumbs();
  18068. self._clearFileInput();
  18069. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  18070. };
  18071. fnError = function (jqXHR, textStatus, errorThrown) {
  18072. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadBatch,
  18073. errMsg = self._parseError(op, jqXHR, errorThrown);
  18074. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  18075. self.uploadFileCount = total - 1;
  18076. if (!self.showPreview) {
  18077. return;
  18078. }
  18079. self._getThumbs().each(function () {
  18080. var $thumb = $(this), key = $thumb.attr('data-fileindex');
  18081. $thumb.removeClass('file-uploading');
  18082. if (self.filestack[key] !== undefined) {
  18083. self._setPreviewError($thumb);
  18084. }
  18085. });
  18086. self._getThumbs().removeClass('file-uploading');
  18087. self._getThumbs(' .kv-file-upload').removeAttr('disabled');
  18088. self._getThumbs(' .kv-file-delete').removeAttr('disabled');
  18089. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  18090. };
  18091. $.each(files, function (key, data) {
  18092. if (!$h.isEmpty(files[key])) {
  18093. self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
  18094. }
  18095. });
  18096. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  18097. },
  18098. _uploadExtraOnly: function () {
  18099. var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
  18100. self.formdata = new FormData();
  18101. if (self._abort(params)) {
  18102. return;
  18103. }
  18104. fnBefore = function (jqXHR) {
  18105. self.lock();
  18106. var outData = self._getOutData(jqXHR);
  18107. self._raise('filebatchpreupload', [outData]);
  18108. self._setProgress(50);
  18109. params.data = outData;
  18110. params.xhr = jqXHR;
  18111. if (self._abort(params)) {
  18112. jqXHR.abort();
  18113. self._setProgressCancelled();
  18114. }
  18115. };
  18116. fnSuccess = function (data, textStatus, jqXHR) {
  18117. var outData = self._getOutData(jqXHR, data);
  18118. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18119. self._raise('filebatchuploadsuccess', [outData]);
  18120. self._clearFileInput();
  18121. self._initUploadSuccess(data);
  18122. self._setProgress(101);
  18123. } else {
  18124. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  18125. }
  18126. };
  18127. fnComplete = function () {
  18128. self.unlock();
  18129. self._clearFileInput();
  18130. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  18131. };
  18132. fnError = function (jqXHR, textStatus, errorThrown) {
  18133. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadExtra,
  18134. errMsg = self._parseError(op, jqXHR, errorThrown);
  18135. params.data = outData;
  18136. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  18137. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  18138. };
  18139. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  18140. },
  18141. _deleteFileIndex: function ($frame) {
  18142. var self = this, ind = $frame.attr('data-fileindex');
  18143. if (ind.substring(0, 5) === 'init_') {
  18144. ind = parseInt(ind.replace('init_', ''));
  18145. self.initialPreview = $h.spliceArray(self.initialPreview, ind);
  18146. self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind);
  18147. self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind);
  18148. self.getFrames().each(function () {
  18149. var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
  18150. if (nInd.substring(0, 5) === 'init_') {
  18151. nInd = parseInt(nInd.replace('init_', ''));
  18152. if (nInd > ind) {
  18153. nInd--;
  18154. $nFrame.attr('data-fileindex', 'init_' + nInd);
  18155. }
  18156. }
  18157. });
  18158. if (self.uploadAsync) {
  18159. self.cacheInitialPreview = self.getPreview();
  18160. }
  18161. }
  18162. },
  18163. _initFileActions: function () {
  18164. var self = this, $preview = self.$preview;
  18165. if (!self.showPreview) {
  18166. return;
  18167. }
  18168. self._initZoomButton();
  18169. self.getFrames(' .kv-file-remove').each(function () {
  18170. var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
  18171. ind = $frame.attr('data-fileindex'), n, cap, status;
  18172. self._handler($el, 'click', function () {
  18173. status = self._raise('filepreremove', [id, ind]);
  18174. if (status === false || !self._validateMinCount()) {
  18175. return false;
  18176. }
  18177. hasError = $frame.hasClass('file-preview-error');
  18178. $h.cleanMemory($frame);
  18179. $frame.fadeOut('slow', function () {
  18180. $h.cleanZoomCache($preview.find('#zoom-' + id));
  18181. self.updateStack(ind, undefined);
  18182. self._clearObjects($frame);
  18183. $frame.remove();
  18184. if (id && hasError) {
  18185. self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
  18186. $(this).remove();
  18187. if (!self._errorsExist()) {
  18188. self._resetErrors();
  18189. }
  18190. });
  18191. }
  18192. self._clearFileInput();
  18193. var filestack = self.getFileStack(true), chk = self.previewCache.count(),
  18194. len = filestack.length, hasThumb = self.showPreview && self.getFrames().length;
  18195. if (len === 0 && chk === 0 && !hasThumb) {
  18196. self.reset();
  18197. } else {
  18198. n = chk + len;
  18199. cap = n > 1 ? self._getMsgSelected(n) : (filestack[0] ? self._getFileNames()[0] : '');
  18200. self._setCaption(cap);
  18201. }
  18202. self._raise('fileremoved', [id, ind]);
  18203. });
  18204. });
  18205. });
  18206. self.getFrames(' .kv-file-upload').each(function () {
  18207. var $el = $(this);
  18208. self._handler($el, 'click', function () {
  18209. var $frame = $el.closest($h.FRAMES), ind = $frame.attr('data-fileindex');
  18210. if (!$frame.hasClass('file-preview-error')) {
  18211. self._uploadSingle(ind, self.filestack, false);
  18212. }
  18213. });
  18214. });
  18215. },
  18216. _initPreviewActions: function () {
  18217. var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
  18218. btnRemove = $h.FRAMES + ' .kv-file-remove',
  18219. resetProgress = function () {
  18220. var hasFiles = self.isUploadable ? self.previewCache.count() : self.$element.get(0).files.length;
  18221. if ($preview.find(btnRemove).length === 0 && !hasFiles) {
  18222. self.reset();
  18223. self.initialCaption = '';
  18224. }
  18225. };
  18226. self._initZoomButton();
  18227. $preview.find(btnRemove).each(function () {
  18228. var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
  18229. if ($h.isEmpty(vUrl) || vKey === undefined) {
  18230. return;
  18231. }
  18232. var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data,
  18233. settings, params, index = $frame.attr('data-fileindex'), config, extraData;
  18234. index = parseInt(index.replace('init_', ''));
  18235. config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
  18236. extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
  18237. if (typeof extraData === "function") {
  18238. extraData = extraData();
  18239. }
  18240. params = {id: $el.attr('id'), key: vKey, extra: extraData};
  18241. settings = $.extend(true, {}, {
  18242. url: vUrl,
  18243. type: 'POST',
  18244. dataType: 'json',
  18245. data: $.extend(true, {}, {key: vKey}, extraData),
  18246. beforeSend: function (jqXHR) {
  18247. self.ajaxAborted = false;
  18248. self._raise('filepredelete', [vKey, jqXHR, extraData]);
  18249. if (self.ajaxAborted) {
  18250. jqXHR.abort();
  18251. } else {
  18252. $h.addCss($frame, 'file-uploading');
  18253. $h.addCss($el, 'disabled');
  18254. }
  18255. },
  18256. success: function (data, textStatus, jqXHR) {
  18257. var n, cap;
  18258. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18259. index = parseInt(($frame.attr('data-fileindex')).replace('init_', ''));
  18260. self.previewCache.unset(index);
  18261. n = self.previewCache.count();
  18262. cap = n > 0 ? self._getMsgSelected(n) : '';
  18263. self._deleteFileIndex($frame);
  18264. self._setCaption(cap);
  18265. self._raise('filedeleted', [vKey, jqXHR, extraData]);
  18266. } else {
  18267. params.jqXHR = jqXHR;
  18268. params.response = data;
  18269. self._showError(data.error, params, 'filedeleteerror');
  18270. $frame.removeClass('file-uploading');
  18271. $el.removeClass('disabled');
  18272. resetProgress();
  18273. return;
  18274. }
  18275. $frame.removeClass('file-uploading').addClass('file-deleted');
  18276. $frame.fadeOut('slow', function () {
  18277. $h.cleanZoomCache($preview.find('#zoom-' + $frame.attr('id')));
  18278. self._clearObjects($frame);
  18279. $frame.remove();
  18280. resetProgress();
  18281. if (!n && self.getFileStack().length === 0) {
  18282. self._setCaption('');
  18283. self.reset();
  18284. }
  18285. });
  18286. },
  18287. error: function (jqXHR, textStatus, errorThrown) {
  18288. var op = self.ajaxOperations.deleteThumb, errMsg = self._parseError(op, jqXHR, errorThrown);
  18289. params.jqXHR = jqXHR;
  18290. params.response = {};
  18291. self._showError(errMsg, params, 'filedeleteerror');
  18292. $frame.removeClass('file-uploading');
  18293. resetProgress();
  18294. }
  18295. }, self.ajaxDeleteSettings);
  18296. self._handler($el, 'click', function () {
  18297. if (!self._validateMinCount()) {
  18298. return false;
  18299. }
  18300. $.ajax(settings);
  18301. });
  18302. });
  18303. },
  18304. _hideFileIcon: function () {
  18305. if (this.overwriteInitial) {
  18306. this.$captionContainer.find('.kv-caption-icon').hide();
  18307. }
  18308. },
  18309. _showFileIcon: function () {
  18310. this.$captionContainer.find('.kv-caption-icon').show();
  18311. },
  18312. _getSize: function (bytes) {
  18313. var self = this, size = parseFloat(bytes), i, func = self.fileSizeGetter, sizes, out;
  18314. if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
  18315. return '';
  18316. }
  18317. if (typeof func === 'function') {
  18318. out = func(size);
  18319. } else {
  18320. if (size === 0) {
  18321. out = '0.00 B';
  18322. } else {
  18323. i = Math.floor(Math.log(size) / Math.log(1024));
  18324. sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  18325. out = (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
  18326. }
  18327. }
  18328. return self._getLayoutTemplate('size').replace('{sizeText}', out);
  18329. },
  18330. _generatePreviewTemplate: function (cat, data, fname, ftype, previewId, isError, size, frameClass, foot, ind, templ) {
  18331. var self = this, caption = self.slug(fname), prevContent, zoomContent = '',
  18332. config = self.previewSettings[cat] || self.defaults.previewSettings[cat],
  18333. w = config && config.width ? config.width : '', h = config && config.height ? config.height : '',
  18334. footer = foot || self._renderFileFooter(caption, size, ($h.isEmpty(w) ? 'auto' : w), isError),
  18335. hasIconSetting = self._getPreviewIcon(fname), typeCss = 'type-default',
  18336. forcePrevIcon = hasIconSetting && self.preferIconicPreview,
  18337. forceZoomIcon = hasIconSetting && self.preferIconicZoomPreview,
  18338. getContent = function (c, d, zoom, frameCss) {
  18339. var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(c),
  18340. css = (frameClass || '') + ' ' + frameCss;
  18341. if (self.frameClass) {
  18342. css = self.frameClass + ' ' + css;
  18343. }
  18344. if (zoom) {
  18345. css = css.replace(' ' + $h.SORT_CSS, '');
  18346. }
  18347. tmplt = self._parseFilePreviewIcon(tmplt, fname);
  18348. if (c === 'text') {
  18349. d = $h.htmlEncode(d);
  18350. }
  18351. if (cat === 'object' && !ftype) {
  18352. $.each(self.defaults.fileTypeSettings, function (key, func) {
  18353. if (key === 'object' || key === 'other') {
  18354. return;
  18355. }
  18356. if (func(fname, ftype)) {
  18357. typeCss = 'type-' + key;
  18358. }
  18359. });
  18360. }
  18361. return tmplt.setTokens({
  18362. 'previewId': id,
  18363. 'caption': caption,
  18364. 'frameClass': css,
  18365. 'type': ftype,
  18366. 'fileindex': ind,
  18367. 'width': w,
  18368. 'height': h,
  18369. 'typeCss': typeCss,
  18370. 'footer': footer,
  18371. 'data': d,
  18372. 'template': templ || cat
  18373. });
  18374. };
  18375. ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
  18376. if (self.fileActionSettings.showZoom) {
  18377. zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb');
  18378. }
  18379. zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
  18380. prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb');
  18381. return prevContent + zoomContent;
  18382. },
  18383. _previewDefault: function (file, previewId, isDisabled) {
  18384. var self = this, $preview = self.$preview;
  18385. if (!self.showPreview) {
  18386. return;
  18387. }
  18388. var fname = file ? file.name : '', ftype = file ? file.type : '', content, size = file.size || 0,
  18389. caption = self.slug(fname), isError = isDisabled === true && !self.isUploadable,
  18390. data = $h.objUrl.createObjectURL(file);
  18391. self._clearDefaultPreview();
  18392. content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, isError, size);
  18393. $preview.append("\n" + content);
  18394. self._setThumbAttr(previewId, caption, size);
  18395. if (isDisabled === true && self.isUploadable) {
  18396. self._setThumbStatus($('#' + previewId), 'Error');
  18397. }
  18398. },
  18399. _previewFile: function (i, file, theFile, previewId, data) {
  18400. if (!this.showPreview) {
  18401. return;
  18402. }
  18403. var self = this, cat = self._parseFileType(file), fname = file ? file.name : '', caption = self.slug(fname),
  18404. types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes, $preview = self.$preview,
  18405. chkTypes = types && types.indexOf(cat) >= 0, fsize = file.size || 0, ftype = file.type,
  18406. iData = (cat === 'text' || cat === 'html' || cat === 'image') ? theFile.target.result : data, content,
  18407. chkMimes = mimes && mimes.indexOf(ftype) !== -1;
  18408. /** @namespace window.DOMPurify */
  18409. if (cat === 'html' && self.purifyHtml && window.DOMPurify) {
  18410. iData = window.DOMPurify.sanitize(iData);
  18411. }
  18412. if (chkTypes || chkMimes) {
  18413. content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, false, fsize);
  18414. self._clearDefaultPreview();
  18415. $preview.append("\n" + content);
  18416. var $img = $preview.find('#' + previewId + ' img');
  18417. if ($img.length && self.autoOrientImage) {
  18418. $h.validateOrientation(file, function (value) {
  18419. if (value) {
  18420. var $zoomImg = $preview.find('#zoom-' + previewId + ' img'), css = 'rotate-' + value;
  18421. if (value > 4) {
  18422. css += ($img.width() > $img.height() ? ' is-portrait-gt4' : ' is-landscape-gt4');
  18423. }
  18424. $h.addCss($img, css);
  18425. $h.addCss($zoomImg, css);
  18426. self._raise('fileimageoriented', {'$img': $img, 'file': file});
  18427. }
  18428. self._validateImage(previewId, caption, ftype, fsize, iData);
  18429. $h.adjustOrientedImage($img);
  18430. });
  18431. } else {
  18432. self._validateImage(previewId, caption, ftype, fsize, iData);
  18433. }
  18434. } else {
  18435. self._previewDefault(file, previewId);
  18436. }
  18437. self._setThumbAttr(previewId, caption, fsize);
  18438. self._initSortable();
  18439. },
  18440. _setThumbAttr: function (id, caption, size) {
  18441. var self = this, $frame = $('#' + id);
  18442. if ($frame.length) {
  18443. size = size && size > 0 ? self._getSize(size) : '';
  18444. $frame.data({'caption': caption, 'size': size});
  18445. }
  18446. },
  18447. _setInitThumbAttr: function () {
  18448. var self = this, data = self.previewCache.data, len = self.previewCache.count(true), config,
  18449. caption, size, previewId;
  18450. if (len === 0) {
  18451. return;
  18452. }
  18453. for (var i = 0; i < len; i++) {
  18454. config = data.config[i];
  18455. previewId = self.previewInitId + '-' + 'init_' + i;
  18456. caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
  18457. size = $h.ifSet('size', config);
  18458. self._setThumbAttr(previewId, caption, size);
  18459. }
  18460. },
  18461. _slugDefault: function (text) {
  18462. return $h.isEmpty(text) ? '' : String(text).replace(/[\-\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
  18463. },
  18464. _readFiles: function (files) {
  18465. this.reader = new FileReader();
  18466. var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
  18467. $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
  18468. msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
  18469. settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
  18470. fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
  18471. fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
  18472. maxPreviewSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize),
  18473. canPreview = $preview.length && (!maxPreviewSize || isNaN(maxPreviewSize)),
  18474. throwError = function (msg, file, previewId, index) {
  18475. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  18476. p2 = {id: previewId, index: index, file: file, files: files};
  18477. self._previewDefault(file, previewId, true);
  18478. if (self.isUploadable) {
  18479. self.addToStack(undefined);
  18480. setTimeout(function () {
  18481. readFile(index + 1);
  18482. }, 100);
  18483. }
  18484. self._initFileActions();
  18485. if (self.removeFromPreviewOnError) {
  18486. $('#' + previewId).remove();
  18487. }
  18488. return self.isUploadable ? self._showUploadError(msg, p1) : self._showError(msg, p2);
  18489. };
  18490. self.loadedImages = [];
  18491. self.totalImagesCount = 0;
  18492. $.each(files, function (key, file) {
  18493. var func = self.fileTypeSettings.image;
  18494. if (func && func(file.type)) {
  18495. self.totalImagesCount++;
  18496. }
  18497. });
  18498. readFile = function (i) {
  18499. if ($h.isEmpty($el.attr('multiple'))) {
  18500. numFiles = 1;
  18501. }
  18502. if (i >= numFiles) {
  18503. if (self.isUploadable && self.filestack.length > 0) {
  18504. self._raise('filebatchselected', [self.getFileStack()]);
  18505. } else {
  18506. self._raise('filebatchselected', [files]);
  18507. }
  18508. $container.removeClass('file-thumb-loading');
  18509. $status.html('');
  18510. return;
  18511. }
  18512. var node = ctr + i, previewId = previewInitId + "-" + node, isText, isImage, file = files[i], fSizeKB,
  18513. caption = file.name ? self.slug(file.name) : '', fileSize = (file.size || 0) / 1000, j, msg,
  18514. fileExtExpr = '', previewData = $h.objUrl.createObjectURL(file), typ, chk, typ1, typ2,
  18515. fileCount = 0, strTypes = '', func;
  18516. if (typLen > 0) {
  18517. for (j = 0; j < typLen; j++) {
  18518. typ1 = fileTypes[j];
  18519. typ2 = self.msgFileTypes[typ1] || typ1;
  18520. strTypes += j === 0 ? typ2 : ', ' + typ2;
  18521. }
  18522. }
  18523. if (caption === false) {
  18524. readFile(i + 1);
  18525. return;
  18526. }
  18527. if (caption.length === 0) {
  18528. msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode(file.name));
  18529. self.isError = throwError(msg, file, previewId, i);
  18530. return;
  18531. }
  18532. if (!$h.isEmpty(fileExt)) {
  18533. fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
  18534. }
  18535. fSizeKB = fileSize.toFixed(2);
  18536. if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
  18537. msg = self.msgSizeTooLarge.setTokens({
  18538. 'name': caption,
  18539. 'size': fSizeKB,
  18540. 'maxSize': self.maxFileSize
  18541. });
  18542. self.isError = throwError(msg, file, previewId, i);
  18543. return;
  18544. }
  18545. if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
  18546. msg = self.msgSizeTooSmall.setTokens({
  18547. 'name': caption,
  18548. 'size': fSizeKB,
  18549. 'minSize': self.minFileSize
  18550. });
  18551. self.isError = throwError(msg, file, previewId, i);
  18552. return;
  18553. }
  18554. if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
  18555. for (j = 0; j < fileTypes.length; j += 1) {
  18556. typ = fileTypes[j];
  18557. func = settings[typ];
  18558. fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type, file.name) ? 1 : 0);
  18559. }
  18560. if (fileCount === 0) {
  18561. msg = self.msgInvalidFileType.setTokens({'name': caption, 'types': strTypes});
  18562. self.isError = throwError(msg, file, previewId, i);
  18563. return;
  18564. }
  18565. }
  18566. if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
  18567. chk = $h.compare(caption, fileExtExpr);
  18568. fileCount += $h.isEmpty(chk) ? 0 : chk.length;
  18569. if (fileCount === 0) {
  18570. msg = self.msgInvalidFileExtension.setTokens({'name': caption, 'extensions': strExt});
  18571. self.isError = throwError(msg, file, previewId, i);
  18572. return;
  18573. }
  18574. }
  18575. if (!self.showPreview) {
  18576. if (self.isUploadable) {
  18577. self.addToStack(file);
  18578. }
  18579. setTimeout(function () {
  18580. readFile(i + 1);
  18581. self._updateFileDetails(numFiles);
  18582. }, 100);
  18583. self._raise('fileloaded', [file, previewId, i, reader]);
  18584. return;
  18585. }
  18586. if (!canPreview && fileSize > maxPreviewSize) {
  18587. self.addToStack(file);
  18588. $container.addClass('file-thumb-loading');
  18589. self._previewDefault(file, previewId);
  18590. self._initFileActions();
  18591. self._updateFileDetails(numFiles);
  18592. readFile(i + 1);
  18593. return;
  18594. }
  18595. if ($preview.length && FileReader !== undefined) {
  18596. $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
  18597. $container.addClass('file-thumb-loading');
  18598. reader.onerror = function (evt) {
  18599. self._errorHandler(evt, caption);
  18600. };
  18601. reader.onload = function (theFile) {
  18602. self._previewFile(i, file, theFile, previewId, previewData);
  18603. self._initFileActions();
  18604. };
  18605. reader.onloadend = function () {
  18606. msg = msgProgress.setTokens({
  18607. 'index': i + 1,
  18608. 'files': numFiles,
  18609. 'percent': 50,
  18610. 'name': caption
  18611. });
  18612. setTimeout(function () {
  18613. $status.html(msg);
  18614. self._updateFileDetails(numFiles);
  18615. readFile(i + 1);
  18616. }, 100);
  18617. self._raise('fileloaded', [file, previewId, i, reader]);
  18618. };
  18619. reader.onprogress = function (data) {
  18620. if (data.lengthComputable) {
  18621. var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
  18622. msg = msgProgress.setTokens({
  18623. 'index': i + 1,
  18624. 'files': numFiles,
  18625. 'percent': progress,
  18626. 'name': caption
  18627. });
  18628. setTimeout(function () {
  18629. $status.html(msg);
  18630. }, 100);
  18631. }
  18632. };
  18633. isText = settings.text;
  18634. isImage = settings.image;
  18635. if (isText(file.type, caption)) {
  18636. reader.readAsText(file, self.textEncoding);
  18637. } else {
  18638. if (isImage(file.type, caption)) {
  18639. reader.readAsDataURL(file);
  18640. } else {
  18641. reader.readAsArrayBuffer(file);
  18642. }
  18643. }
  18644. } else {
  18645. self._previewDefault(file, previewId);
  18646. setTimeout(function () {
  18647. readFile(i + 1);
  18648. self._updateFileDetails(numFiles);
  18649. }, 100);
  18650. self._raise('fileloaded', [file, previewId, i, reader]);
  18651. }
  18652. self.addToStack(file);
  18653. };
  18654. readFile(0);
  18655. self._updateFileDetails(numFiles, false);
  18656. },
  18657. _updateFileDetails: function (numFiles) {
  18658. var self = this, $el = self.$element, fileStack = self.getFileStack(),
  18659. name = ($h.isIE(9) && $h.findFileName($el.val())) ||
  18660. ($el[0].files[0] && $el[0].files[0].name) || (fileStack.length && fileStack[0].name) || '',
  18661. label = self.slug(name), n = self.isUploadable ? fileStack.length : numFiles,
  18662. nFiles = self.previewCache.count() + n, log = n > 1 ? self._getMsgSelected(nFiles) : label;
  18663. if (self.isError) {
  18664. self.$previewContainer.removeClass('file-thumb-loading');
  18665. self.$previewStatus.html('');
  18666. self.$captionContainer.find('.kv-caption-icon').hide();
  18667. } else {
  18668. self._showFileIcon();
  18669. }
  18670. self._setCaption(log, self.isError);
  18671. self.$container.removeClass('file-input-new file-input-ajax-new');
  18672. if (arguments.length === 1) {
  18673. self._raise('fileselect', [numFiles, label]);
  18674. }
  18675. if (self.previewCache.count()) {
  18676. self._initPreviewActions();
  18677. }
  18678. },
  18679. _setThumbStatus: function ($thumb, status) {
  18680. var self = this;
  18681. if (!self.showPreview) {
  18682. return;
  18683. }
  18684. var icon = 'indicator' + status, msg = icon + 'Title',
  18685. css = 'file-preview-' + status.toLowerCase(),
  18686. $indicator = $thumb.find('.file-upload-indicator'),
  18687. config = self.fileActionSettings;
  18688. $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
  18689. if (status === 'Error') {
  18690. $thumb.find('.kv-file-upload').attr('disabled', true);
  18691. }
  18692. if (status === 'Success') {
  18693. $thumb.find('.file-drag-handle').remove();
  18694. $indicator.css('margin-left', 0);
  18695. }
  18696. $indicator.html(config[icon]);
  18697. $indicator.attr('title', config[msg]);
  18698. $thumb.addClass(css);
  18699. },
  18700. _setProgressCancelled: function () {
  18701. var self = this;
  18702. self._setProgress(101, self.$progress, self.msgCancelled);
  18703. },
  18704. _setProgress: function (p, $el, error) {
  18705. var self = this, pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
  18706. t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
  18707. template = pct < 100 ? self.progressTemplate : (error ? self.progressErrorTemplate : t);
  18708. $el = $el || self.$progress;
  18709. if (!$h.isEmpty(template)) {
  18710. if (pctLimit && pct > pctLimit && p <= 100) {
  18711. out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
  18712. } else {
  18713. out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
  18714. }
  18715. $el.html(out);
  18716. if (error) {
  18717. $el.find('[role="progressbar"]').html(error);
  18718. }
  18719. }
  18720. },
  18721. _setFileDropZoneTitle: function () {
  18722. var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
  18723. if (self.isClickable) {
  18724. strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
  18725. title += self.dropZoneClickTitle.replace('{files}', strFiles);
  18726. }
  18727. $zone.find('.' + self.dropZoneTitleClass).remove();
  18728. if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
  18729. return;
  18730. }
  18731. if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
  18732. $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
  18733. }
  18734. self.$container.removeClass('file-input-new');
  18735. $h.addCss(self.$container, 'file-input-ajax-new');
  18736. },
  18737. _setAsyncUploadStatus: function (previewId, pct, total) {
  18738. var self = this, sum = 0;
  18739. self._setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
  18740. self.uploadStatus[previewId] = pct;
  18741. $.each(self.uploadStatus, function (key, value) {
  18742. sum += value;
  18743. });
  18744. self._setProgress(Math.floor(sum / total));
  18745. },
  18746. _validateMinCount: function () {
  18747. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  18748. if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
  18749. self._noFilesError({});
  18750. return false;
  18751. }
  18752. return true;
  18753. },
  18754. _getFileCount: function (fileCount) {
  18755. var self = this, addCount = 0;
  18756. if (self.validateInitialCount && !self.overwriteInitial) {
  18757. addCount = self.previewCache.count();
  18758. fileCount += addCount;
  18759. }
  18760. return fileCount;
  18761. },
  18762. _getFileId: function (file) {
  18763. var self = this, custom = self.generateFileId, relativePath;
  18764. if (typeof custom === 'function') {
  18765. return custom(file, event);
  18766. }
  18767. if (!file) {
  18768. return null;
  18769. }
  18770. /** @namespace file.webkitRelativePath */
  18771. relativePath = file.webkitRelativePath || file.fileName || file.name || null;
  18772. if (!relativePath) {
  18773. return null;
  18774. }
  18775. return (file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
  18776. },
  18777. _getFileName: function (file) {
  18778. return file && file.name ? this.slug(file.name) : undefined;
  18779. },
  18780. _getFileIds: function (skipNull) {
  18781. var self = this;
  18782. return self.fileids.filter(function (n) {
  18783. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  18784. });
  18785. },
  18786. _getFileNames: function (skipNull) {
  18787. var self = this;
  18788. return self.filenames.filter(function (n) {
  18789. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  18790. });
  18791. },
  18792. _setPreviewError: function ($thumb, i, val) {
  18793. var self = this;
  18794. if (i !== undefined) {
  18795. self.updateStack(i, val);
  18796. }
  18797. if (self.removeFromPreviewOnError) {
  18798. $thumb.remove();
  18799. } else {
  18800. self._setThumbStatus($thumb, 'Error');
  18801. }
  18802. },
  18803. _checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
  18804. var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type],
  18805. $imgEl, isValid;
  18806. if ($h.isEmpty(limit) || !$img.length) {
  18807. return;
  18808. }
  18809. $imgEl = $img[0];
  18810. dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
  18811. isValid = chk === 'Small' ? dim >= limit : dim <= limit;
  18812. if (isValid) {
  18813. return;
  18814. }
  18815. msg = self['msgImage' + type + chk].setTokens({'name': fname, 'size': limit});
  18816. self._showUploadError(msg, params);
  18817. self._setPreviewError($thumb, i, null);
  18818. },
  18819. _validateImage: function (previewId, fname, ftype, fsize, iData) {
  18820. var self = this, $preview = self.$preview, params, w1, w2, $thumb = $preview.find("#" + previewId),
  18821. i = $thumb.attr('data-fileindex'), $img = $thumb.find('img'), exifObject;
  18822. fname = fname || 'Untitled';
  18823. $img.one('load', function () {
  18824. w1 = $thumb.width();
  18825. w2 = $preview.width();
  18826. if (w1 > w2) {
  18827. $img.css('width', '100%');
  18828. }
  18829. params = {ind: i, id: previewId};
  18830. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
  18831. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
  18832. if (!self.resizeImage) {
  18833. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
  18834. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
  18835. }
  18836. self._raise('fileimageloaded', [previewId]);
  18837. exifObject = window.piexif ? window.piexif.load(iData) : null;
  18838. self.loadedImages.push({
  18839. ind: i,
  18840. img: $img,
  18841. thumb: $thumb,
  18842. pid: previewId,
  18843. typ: ftype,
  18844. siz: fsize,
  18845. validated: false,
  18846. imgData: iData,
  18847. exifObj: exifObject
  18848. });
  18849. $thumb.data('exif', exifObject);
  18850. self._validateAllImages();
  18851. }).one('error', function () {
  18852. self._raise('fileimageloaderror', [previewId]);
  18853. }).each(function () {
  18854. if (this.complete) {
  18855. $(this).trigger('load');
  18856. } else {
  18857. if (this.error) {
  18858. $(this).trigger('error');
  18859. }
  18860. }
  18861. });
  18862. },
  18863. _validateAllImages: function () {
  18864. var self = this, i, counter = {val: 0}, numImgs = self.loadedImages.length, config,
  18865. fsize, minSize = self.resizeIfSizeMoreThan;
  18866. if (numImgs !== self.totalImagesCount) {
  18867. return;
  18868. }
  18869. self._raise('fileimagesloaded');
  18870. if (!self.resizeImage) {
  18871. return;
  18872. }
  18873. for (i = 0; i < self.loadedImages.length; i++) {
  18874. config = self.loadedImages[i];
  18875. if (config.validated) {
  18876. continue;
  18877. }
  18878. fsize = config.siz;
  18879. if (fsize && fsize > minSize * 1000) {
  18880. self._getResizedImage(config, counter, numImgs);
  18881. }
  18882. self.loadedImages[i].validated = true;
  18883. }
  18884. },
  18885. _getResizedImage: function (config, counter, numImgs) {
  18886. var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
  18887. ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
  18888. isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
  18889. context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
  18890. $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr;
  18891. throwError = function (msg, params, ev) {
  18892. if (self.isUploadable) {
  18893. self._showUploadError(msg, params, ev);
  18894. } else {
  18895. self._showError(msg, params, ev);
  18896. }
  18897. self._setPreviewError($thumb, ind);
  18898. };
  18899. if (!self.filestack[ind] || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
  18900. if (isValidImage && self.filestack[ind]) {
  18901. self._raise('fileimageresized', [pid, ind]);
  18902. }
  18903. counter.val++;
  18904. if (counter.val === numImgs) {
  18905. self._raise('fileimagesresized');
  18906. }
  18907. if (!isValidImage) {
  18908. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  18909. return;
  18910. }
  18911. }
  18912. type = type || self.resizeDefaultImageType;
  18913. chkWidth = width > maxWidth;
  18914. chkHeight = height > maxHeight;
  18915. if (self.resizePreference === 'width') {
  18916. ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
  18917. } else {
  18918. ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
  18919. }
  18920. self._resetCanvas();
  18921. width *= ratio;
  18922. height *= ratio;
  18923. canvas.width = width;
  18924. canvas.height = height;
  18925. try {
  18926. context.drawImage(img, 0, 0, width, height);
  18927. dataURI = canvas.toDataURL(type, self.resizeQuality);
  18928. if (exifObj) {
  18929. exifStr = window.piexif.dump(exifObj);
  18930. dataURI = window.piexif.insert(exifStr, dataURI);
  18931. }
  18932. blob = $h.dataURI2Blob(dataURI);
  18933. self.filestack[ind] = blob;
  18934. self._raise('fileimageresized', [pid, ind]);
  18935. counter.val++;
  18936. if (counter.val === numImgs) {
  18937. self._raise('fileimagesresized', [undefined, undefined]);
  18938. }
  18939. if (!(blob instanceof Blob)) {
  18940. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  18941. }
  18942. }
  18943. catch (err) {
  18944. counter.val++;
  18945. if (counter.val === numImgs) {
  18946. self._raise('fileimagesresized', [undefined, undefined]);
  18947. }
  18948. msg = self.msgImageResizeException.replace('{errors}', err.message);
  18949. throwError(msg, {id: pid, 'index': ind}, 'fileimageresizeexception');
  18950. }
  18951. },
  18952. _initBrowse: function ($container) {
  18953. var self = this;
  18954. if (self.showBrowse) {
  18955. self.$btnFile = $container.find('.btn-file');
  18956. self.$btnFile.append(self.$element);
  18957. } else {
  18958. self.$element.hide();
  18959. }
  18960. },
  18961. _initCaption: function () {
  18962. var self = this, cap = self.initialCaption || '';
  18963. if (self.overwriteInitial || $h.isEmpty(cap)) {
  18964. self.$caption.html('');
  18965. return false;
  18966. }
  18967. self._setCaption(cap);
  18968. return true;
  18969. },
  18970. _setCaption: function (content, isError) {
  18971. var self = this, title, out, n, cap, stack = self.getFileStack();
  18972. if (!self.$caption.length) {
  18973. return;
  18974. }
  18975. if (isError) {
  18976. title = $('<div>' + self.msgValidationError + '</div>').text();
  18977. n = stack.length;
  18978. if (n) {
  18979. cap = n === 1 && stack[0] ? self._getFileNames()[0] : self._getMsgSelected(n);
  18980. } else {
  18981. cap = self._getMsgSelected(self.msgNo);
  18982. }
  18983. out = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon +
  18984. ($h.isEmpty(content) ? cap : content) + '</span>';
  18985. } else {
  18986. if ($h.isEmpty(content)) {
  18987. return;
  18988. }
  18989. title = $('<div>' + content + '</div>').text();
  18990. out = self._getLayoutTemplate('fileIcon') + title;
  18991. }
  18992. self.$caption.html(out);
  18993. self.$caption.attr('title', title);
  18994. self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
  18995. },
  18996. _createContainer: function () {
  18997. var self = this, attribs = {"class": 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
  18998. $container = $(document.createElement("div")).attr(attribs).html(self._renderMain());
  18999. self.$element.before($container);
  19000. self._initBrowse($container);
  19001. if (self.theme) {
  19002. $container.addClass('theme-' + self.theme);
  19003. }
  19004. return $container;
  19005. },
  19006. _refreshContainer: function () {
  19007. var self = this, $container = self.$container;
  19008. $container.before(self.$element);
  19009. $container.html(self._renderMain());
  19010. self._initBrowse($container);
  19011. },
  19012. _renderMain: function () {
  19013. var self = this,
  19014. dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : 'file-drop-disabled',
  19015. close = !self.showClose ? '' : self._getLayoutTemplate('close'),
  19016. preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
  19017. .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
  19018. css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
  19019. caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
  19020. return self.mainTemplate.setTokens({
  19021. 'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
  19022. 'preview': preview,
  19023. 'close': close,
  19024. 'caption': caption,
  19025. 'upload': self._renderButton('upload'),
  19026. 'remove': self._renderButton('remove'),
  19027. 'cancel': self._renderButton('cancel'),
  19028. 'browse': self._renderButton('browse')
  19029. });
  19030. },
  19031. _renderButton: function (type) {
  19032. var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
  19033. title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
  19034. status = self.isDisabled ? ' disabled' : '', btnType = 'button';
  19035. switch (type) {
  19036. case 'remove':
  19037. if (!self.showRemove) {
  19038. return '';
  19039. }
  19040. break;
  19041. case 'cancel':
  19042. if (!self.showCancel) {
  19043. return '';
  19044. }
  19045. css += ' hide';
  19046. break;
  19047. case 'upload':
  19048. if (!self.showUpload) {
  19049. return '';
  19050. }
  19051. if (self.isUploadable && !self.isDisabled) {
  19052. tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
  19053. } else {
  19054. btnType = 'submit';
  19055. }
  19056. break;
  19057. case 'browse':
  19058. if (!self.showBrowse) {
  19059. return '';
  19060. }
  19061. tmplt = self._getLayoutTemplate('btnBrowse');
  19062. break;
  19063. default:
  19064. return '';
  19065. }
  19066. css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
  19067. if (!$h.isEmpty(label)) {
  19068. label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
  19069. }
  19070. return tmplt.setTokens({
  19071. 'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
  19072. });
  19073. },
  19074. _renderThumbProgress: function () {
  19075. var self = this;
  19076. return '<div class="file-thumb-progress hide">' +
  19077. self.progressTemplate.setTokens({'percent': '0', 'status': self.msgUploadBegin}) +
  19078. '</div>';
  19079. },
  19080. _renderFileFooter: function (caption, size, width, isError) {
  19081. var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
  19082. upl = config.showUpload, zoom = config.showZoom, out, template = self._getLayoutTemplate('footer'),
  19083. ind = isError ? config.indicatorError : config.indicatorNew,
  19084. tInd = self._getLayoutTemplate('indicator'),
  19085. title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
  19086. indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
  19087. size = self._getSize(size);
  19088. if (self.isUploadable) {
  19089. out = template.setTokens({
  19090. 'actions': self._renderFileActions(upl, rem, zoom, drg, false, false, false),
  19091. 'caption': caption,
  19092. 'size': size,
  19093. 'width': width,
  19094. 'progress': self._renderThumbProgress(),
  19095. 'indicator': indicator
  19096. });
  19097. } else {
  19098. out = template.setTokens({
  19099. 'actions': self._renderFileActions(false, false, zoom, drg, false, false, false),
  19100. 'caption': caption,
  19101. 'size': size,
  19102. 'width': width,
  19103. 'progress': '',
  19104. 'indicator': indicator
  19105. });
  19106. }
  19107. out = $h.replaceTags(out, self.previewThumbTags);
  19108. return out;
  19109. },
  19110. _renderFileActions: function (showUpload, showDelete, showZoom, showDrag, disabled, url, key, isInit) {
  19111. if (!showUpload && !showDelete && !showZoom && !showDrag) {
  19112. return '';
  19113. }
  19114. var self = this, vUrl = url === false ? '' : ' data-url="' + url + '"',
  19115. vKey = key === false ? '' : ' data-key="' + key + '"',
  19116. btnDelete = '', btnUpload = '', btnZoom = '', btnDrag = '', css,
  19117. template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
  19118. otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey}),
  19119. removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
  19120. if (showDelete) {
  19121. btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
  19122. 'removeClass': removeClass,
  19123. 'removeIcon': config.removeIcon,
  19124. 'removeTitle': config.removeTitle,
  19125. 'dataUrl': vUrl,
  19126. 'dataKey': vKey
  19127. });
  19128. }
  19129. if (showUpload) {
  19130. btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
  19131. 'uploadClass': config.uploadClass,
  19132. 'uploadIcon': config.uploadIcon,
  19133. 'uploadTitle': config.uploadTitle
  19134. });
  19135. }
  19136. if (showZoom) {
  19137. btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
  19138. 'zoomClass': config.zoomClass,
  19139. 'zoomIcon': config.zoomIcon,
  19140. 'zoomTitle': config.zoomTitle
  19141. });
  19142. }
  19143. if (showDrag && isInit) {
  19144. css = 'drag-handle-init ' + config.dragClass;
  19145. btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
  19146. 'dragClass': css,
  19147. 'dragTitle': config.dragTitle,
  19148. 'dragIcon': config.dragIcon
  19149. });
  19150. }
  19151. return template.setTokens({
  19152. 'delete': btnDelete,
  19153. 'upload': btnUpload,
  19154. 'zoom': btnZoom,
  19155. 'drag': btnDrag,
  19156. 'other': otherButtons
  19157. });
  19158. },
  19159. _browse: function (e) {
  19160. var self = this;
  19161. self._raise('filebrowse');
  19162. if (e && e.isDefaultPrevented()) {
  19163. return;
  19164. }
  19165. if (self.isError && !self.isUploadable) {
  19166. self.clear();
  19167. }
  19168. self.$captionContainer.focus();
  19169. },
  19170. _filterDuplicate: function (file, files, fileIds) {
  19171. var self = this, fileId = self._getFileId(file);
  19172. if (fileId && fileIds && fileIds.indexOf(fileId) > -1) {
  19173. return;
  19174. }
  19175. if (!fileIds) {
  19176. fileIds = [];
  19177. }
  19178. files.push(file);
  19179. fileIds.push(fileId);
  19180. },
  19181. _change: function (e) {
  19182. var self = this, $el = self.$element;
  19183. if (!self.isUploadable && $h.isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
  19184. self.fileInputCleared = false;
  19185. return;
  19186. }
  19187. self.fileInputCleared = false;
  19188. var tfiles = [], msg, total, isDragDrop = arguments.length > 1, isAjaxUpload = self.isUploadable, n, len,
  19189. files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files, ctr = self.filestack.length,
  19190. isSingleUpload = $h.isEmpty($el.attr('multiple')), flagSingle = (isSingleUpload && ctr > 0),
  19191. folders = 0, fileIds = self._getFileIds(), throwError = function (mesg, file, previewId, index) {
  19192. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  19193. p2 = {id: previewId, index: index, file: file, files: files};
  19194. return self.isUploadable ? self._showUploadError(mesg, p1) : self._showError(mesg, p2);
  19195. };
  19196. self.reader = null;
  19197. self._resetUpload();
  19198. self._hideFileIcon();
  19199. if (self.isUploadable) {
  19200. self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
  19201. }
  19202. if (isDragDrop) {
  19203. $.each(files, function (i, f) {
  19204. if (f && !f.type && f.size !== undefined && f.size % 4096 === 0) {
  19205. folders++;
  19206. } else {
  19207. self._filterDuplicate(f, tfiles, fileIds);
  19208. }
  19209. });
  19210. } else {
  19211. if (e.target && e.target.files === undefined) {
  19212. files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
  19213. } else {
  19214. files = e.target.files || {};
  19215. }
  19216. if (isAjaxUpload) {
  19217. $.each(files, function (i, f) {
  19218. self._filterDuplicate(f, tfiles, fileIds);
  19219. });
  19220. } else {
  19221. tfiles = files;
  19222. }
  19223. }
  19224. if ($h.isEmpty(tfiles) || tfiles.length === 0) {
  19225. if (!isAjaxUpload) {
  19226. self.clear();
  19227. }
  19228. self._showFolderError(folders);
  19229. self._raise('fileselectnone');
  19230. return;
  19231. }
  19232. self._resetErrors();
  19233. len = tfiles.length;
  19234. total = self._getFileCount(self.isUploadable ? (self.getFileStack().length + len) : len);
  19235. if (self.maxFileCount > 0 && total > self.maxFileCount) {
  19236. if (!self.autoReplace || len > self.maxFileCount) {
  19237. n = (self.autoReplace && len > self.maxFileCount) ? len : total;
  19238. msg = self.msgFilesTooMany.replace('{m}', self.maxFileCount).replace('{n}', n);
  19239. self.isError = throwError(msg, null, null, null);
  19240. self.$captionContainer.find('.kv-caption-icon').hide();
  19241. self._setCaption('', true);
  19242. self.$container.removeClass('file-input-new file-input-ajax-new');
  19243. return;
  19244. }
  19245. if (total > self.maxFileCount) {
  19246. self._resetPreviewThumbs(isAjaxUpload);
  19247. }
  19248. } else {
  19249. if (!isAjaxUpload || flagSingle) {
  19250. self._resetPreviewThumbs(false);
  19251. if (flagSingle) {
  19252. self.clearStack();
  19253. }
  19254. } else {
  19255. if (isAjaxUpload && ctr === 0 && (!self.previewCache.count() || self.overwriteInitial)) {
  19256. self._resetPreviewThumbs(true);
  19257. }
  19258. }
  19259. }
  19260. if (self.isPreviewable) {
  19261. self._readFiles(tfiles);
  19262. } else {
  19263. self._updateFileDetails(1);
  19264. }
  19265. self._showFolderError(folders);
  19266. },
  19267. _abort: function (params) {
  19268. var self = this, data;
  19269. if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
  19270. data = $.extend(true, {}, self._getOutData(), params);
  19271. data.abortData = self.ajaxAborted.data || {};
  19272. data.abortMessage = self.ajaxAborted.message;
  19273. self._setProgress(101, self.$progress, self.msgCancelled);
  19274. self._showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
  19275. self.cancel();
  19276. return true;
  19277. }
  19278. return false;
  19279. },
  19280. _resetFileStack: function () {
  19281. var self = this, i = 0, newstack = [], newnames = [], newids = [];
  19282. self._getThumbs().each(function () {
  19283. var $thumb = $(this), ind = $thumb.attr('data-fileindex'), file = self.filestack[ind],
  19284. pid = $thumb.attr('id'), newId;
  19285. if (ind === '-1' || ind === -1) {
  19286. return;
  19287. }
  19288. if (file !== undefined) {
  19289. newstack[i] = file;
  19290. newnames[i] = self._getFileName(file);
  19291. newids[i] = self._getFileId(file);
  19292. $thumb.attr({'id': self.previewInitId + '-' + i, 'data-fileindex': i});
  19293. i++;
  19294. } else {
  19295. newId = 'uploaded-' + $h.uniqId();
  19296. $thumb.attr({'id': newId, 'data-fileindex': '-1'});
  19297. self.$preview.find('#zoom-' + pid).attr('id', 'zoom-' + newId);
  19298. }
  19299. });
  19300. self.filestack = newstack;
  19301. self.filenames = newnames;
  19302. self.fileids = newids;
  19303. },
  19304. _isFileSelectionValid: function (cnt) {
  19305. var self = this;
  19306. cnt = cnt || 0;
  19307. if (self.required && !self.getFilesCount()) {
  19308. self.$errorContainer.html('');
  19309. self._showUploadError(self.msgFileRequired);
  19310. return false;
  19311. }
  19312. if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
  19313. self._noFilesError({});
  19314. return false;
  19315. }
  19316. return true;
  19317. },
  19318. clearStack: function () {
  19319. var self = this;
  19320. self.filestack = [];
  19321. self.filenames = [];
  19322. self.fileids = [];
  19323. return self.$element;
  19324. },
  19325. updateStack: function (i, file) {
  19326. var self = this;
  19327. self.filestack[i] = file;
  19328. self.filenames[i] = self._getFileName(file);
  19329. self.fileids[i] = file && self._getFileId(file) || null;
  19330. return self.$element;
  19331. },
  19332. addToStack: function (file) {
  19333. var self = this;
  19334. self.filestack.push(file);
  19335. self.filenames.push(self._getFileName(file));
  19336. self.fileids.push(self._getFileId(file));
  19337. return self.$element;
  19338. },
  19339. getFileStack: function (skipNull) {
  19340. var self = this;
  19341. return self.filestack.filter(function (n) {
  19342. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  19343. });
  19344. },
  19345. getFilesCount: function () {
  19346. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  19347. return self._getFileCount(len);
  19348. },
  19349. lock: function () {
  19350. var self = this;
  19351. self._resetErrors();
  19352. self.disable();
  19353. if (self.showRemove) {
  19354. $h.addCss(self.$container.find('.fileinput-remove'), 'hide');
  19355. }
  19356. if (self.showCancel) {
  19357. self.$container.find('.fileinput-cancel').removeClass('hide');
  19358. }
  19359. self._raise('filelock', [self.filestack, self._getExtraData()]);
  19360. return self.$element;
  19361. },
  19362. unlock: function (reset) {
  19363. var self = this;
  19364. if (reset === undefined) {
  19365. reset = true;
  19366. }
  19367. self.enable();
  19368. if (self.showCancel) {
  19369. $h.addCss(self.$container.find('.fileinput-cancel'), 'hide');
  19370. }
  19371. if (self.showRemove) {
  19372. self.$container.find('.fileinput-remove').removeClass('hide');
  19373. }
  19374. if (reset) {
  19375. self._resetFileStack();
  19376. }
  19377. self._raise('fileunlock', [self.filestack, self._getExtraData()]);
  19378. return self.$element;
  19379. },
  19380. cancel: function () {
  19381. var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
  19382. if (len > 0) {
  19383. for (i = 0; i < len; i += 1) {
  19384. self.cancelling = true;
  19385. xhr[i].abort();
  19386. }
  19387. }
  19388. self._setProgressCancelled();
  19389. self._getThumbs().each(function () {
  19390. var $thumb = $(this), ind = $thumb.attr('data-fileindex');
  19391. $thumb.removeClass('file-uploading');
  19392. if (self.filestack[ind] !== undefined) {
  19393. $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
  19394. $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
  19395. }
  19396. self.unlock();
  19397. });
  19398. return self.$element;
  19399. },
  19400. clear: function () {
  19401. var self = this, cap;
  19402. if (!self._raise('fileclear')) {
  19403. return;
  19404. }
  19405. self.$btnUpload.removeAttr('disabled');
  19406. self._getThumbs().find('video,audio,img').each(function () {
  19407. $h.cleanMemory($(this));
  19408. });
  19409. self._resetUpload();
  19410. self.clearStack();
  19411. self._clearFileInput();
  19412. self._resetErrors(true);
  19413. if (self._hasInitialPreview()) {
  19414. self._showFileIcon();
  19415. self._resetPreview();
  19416. self._initPreviewActions();
  19417. self.$container.removeClass('file-input-new');
  19418. } else {
  19419. self._getThumbs().each(function () {
  19420. self._clearObjects($(this));
  19421. });
  19422. if (self.isUploadable) {
  19423. self.previewCache.data = {};
  19424. }
  19425. self.$preview.html('');
  19426. cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
  19427. self.$caption.html(cap);
  19428. self.$caption.attr('title', '');
  19429. $h.addCss(self.$container, 'file-input-new');
  19430. self._validateDefaultPreview();
  19431. }
  19432. if (self.$container.find($h.FRAMES).length === 0) {
  19433. if (!self._initCaption()) {
  19434. self.$captionContainer.find('.kv-caption-icon').hide();
  19435. }
  19436. }
  19437. self._hideFileIcon();
  19438. self._raise('filecleared');
  19439. self.$captionContainer.focus();
  19440. self._setFileDropZoneTitle();
  19441. return self.$element;
  19442. },
  19443. reset: function () {
  19444. var self = this;
  19445. if (!self._raise('filereset')) {
  19446. return;
  19447. }
  19448. self._resetPreview();
  19449. self.$container.find('.fileinput-filename').text('');
  19450. $h.addCss(self.$container, 'file-input-new');
  19451. if (self.getFrames().length || self.isUploadable && self.dropZoneEnabled) {
  19452. self.$container.removeClass('file-input-new');
  19453. }
  19454. self._setFileDropZoneTitle();
  19455. self.clearStack();
  19456. self.formdata = {};
  19457. return self.$element;
  19458. },
  19459. disable: function () {
  19460. var self = this;
  19461. self.isDisabled = true;
  19462. self._raise('filedisabled');
  19463. self.$element.attr('disabled', 'disabled');
  19464. self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
  19465. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  19466. .attr("disabled", true);
  19467. self._initDragDrop();
  19468. return self.$element;
  19469. },
  19470. enable: function () {
  19471. var self = this;
  19472. self.isDisabled = false;
  19473. self._raise('fileenabled');
  19474. self.$element.removeAttr('disabled');
  19475. self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
  19476. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  19477. .removeAttr("disabled");
  19478. self._initDragDrop();
  19479. return self.$element;
  19480. },
  19481. upload: function () {
  19482. var self = this, totLen = self.getFileStack().length, i, outData, len,
  19483. hasExtraData = !$.isEmptyObject(self._getExtraData());
  19484. if (!self.isUploadable || self.isDisabled || !self._isFileSelectionValid(totLen)) {
  19485. return;
  19486. }
  19487. self._resetUpload();
  19488. if (totLen === 0 && !hasExtraData) {
  19489. self._showUploadError(self.msgUploadEmpty);
  19490. return;
  19491. }
  19492. self.$progress.removeClass('hide');
  19493. self.uploadCount = 0;
  19494. self.uploadStatus = {};
  19495. self.uploadLog = [];
  19496. self.lock();
  19497. self._setProgress(2);
  19498. if (totLen === 0 && hasExtraData) {
  19499. self._uploadExtraOnly();
  19500. return;
  19501. }
  19502. len = self.filestack.length;
  19503. self.hasInitData = false;
  19504. if (self.uploadAsync) {
  19505. outData = self._getOutData();
  19506. self._raise('filebatchpreupload', [outData]);
  19507. self.fileBatchCompleted = false;
  19508. self.uploadCache = {content: [], config: [], tags: [], append: true};
  19509. self.uploadAsyncCount = self.getFileStack().length;
  19510. for (i = 0; i < len; i++) {
  19511. self.uploadCache.content[i] = null;
  19512. self.uploadCache.config[i] = null;
  19513. self.uploadCache.tags[i] = null;
  19514. }
  19515. self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
  19516. self._initSortable();
  19517. self.cacheInitialPreview = self.getPreview();
  19518. for (i = 0; i < len; i++) {
  19519. if (self.filestack[i] !== undefined) {
  19520. self._uploadSingle(i, self.filestack, true);
  19521. }
  19522. }
  19523. return;
  19524. }
  19525. self._uploadBatch();
  19526. return self.$element;
  19527. },
  19528. destroy: function () {
  19529. var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
  19530. $(document).off(ns);
  19531. $(window).off(ns);
  19532. if ($form && $form.length) {
  19533. $form.off(ns);
  19534. }
  19535. if (self.isUploadable) {
  19536. self._clearFileInput();
  19537. }
  19538. self._cleanup();
  19539. self._initPreviewCache();
  19540. $el.insertBefore($cont).off(ns).removeData();
  19541. $cont.off().remove();
  19542. return $el;
  19543. },
  19544. refresh: function (options) {
  19545. var self = this, $el = self.$element;
  19546. options = options ? $.extend(true, {}, self.options, options) : self.options;
  19547. self.destroy();
  19548. $el.fileinput(options);
  19549. self = $el.data('fileinput');
  19550. if (self.isUploadable) {
  19551. self._clearFileInput();
  19552. }
  19553. if ($el.val()) {
  19554. $el.trigger('change.fileinput');
  19555. }
  19556. return $el;
  19557. },
  19558. zoom: function (frameId) {
  19559. var self = this, $frame = self._getFrame(frameId), $modal = self.$modal;
  19560. if (!$frame) {
  19561. return;
  19562. }
  19563. $h.initModal($modal);
  19564. $modal.html(self._getModalContent());
  19565. self._setZoomContent($frame);
  19566. $modal.modal('show');
  19567. self._initZoomButtons();
  19568. },
  19569. getExif: function (frameId) {
  19570. var self = this, $frame = self._getFrame(frameId);
  19571. return $frame && $frame.data('exif') || null;
  19572. },
  19573. getFrames: function (cssFilter) {
  19574. var self = this;
  19575. cssFilter = cssFilter || '';
  19576. return self.$preview.find($h.FRAMES + cssFilter);
  19577. },
  19578. getPreview: function () {
  19579. var self = this;
  19580. return {
  19581. content: self.initialPreview,
  19582. config: self.initialPreviewConfig,
  19583. tags: self.initialPreviewThumbTags
  19584. };
  19585. }
  19586. };
  19587. $.fn.fileinput = function (option) {
  19588. if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
  19589. return;
  19590. }
  19591. var args = Array.apply(null, arguments), retvals = [];
  19592. args.shift();
  19593. this.each(function () {
  19594. var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
  19595. theme = options.theme || self.data('theme'), l = {}, t = {},
  19596. lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
  19597. if (!data) {
  19598. if (theme) {
  19599. t = $.fn.fileinputThemes[theme] || {};
  19600. }
  19601. if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
  19602. l = $.fn.fileinputLocales[lang] || {};
  19603. }
  19604. opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
  19605. data = new FileInput(this, opt);
  19606. self.data('fileinput', data);
  19607. }
  19608. if (typeof option === 'string') {
  19609. retvals.push(data[option].apply(data, args));
  19610. }
  19611. });
  19612. switch (retvals.length) {
  19613. case 0:
  19614. return this;
  19615. case 1:
  19616. return retvals[0];
  19617. default:
  19618. return retvals;
  19619. }
  19620. };
  19621. $.fn.fileinput.defaults = {
  19622. language: 'en',
  19623. showCaption: true,
  19624. showBrowse: true,
  19625. showPreview: true,
  19626. showRemove: true,
  19627. showUpload: true,
  19628. showCancel: true,
  19629. showClose: true,
  19630. showUploadedThumbs: true,
  19631. browseOnZoneClick: false,
  19632. autoReplace: false,
  19633. autoOrientImage: true, // for JPEG images based on EXIF orientation tag
  19634. required: false,
  19635. rtl: false,
  19636. hideThumbnailContent: false,
  19637. generateFileId: null,
  19638. previewClass: '',
  19639. captionClass: '',
  19640. frameClass: 'krajee-default',
  19641. mainClass: 'file-caption-main',
  19642. mainTemplate: null,
  19643. purifyHtml: true,
  19644. fileSizeGetter: null,
  19645. initialCaption: '',
  19646. initialPreview: [],
  19647. initialPreviewDelimiter: '*$$*',
  19648. initialPreviewAsData: false,
  19649. initialPreviewFileType: 'image',
  19650. initialPreviewConfig: [],
  19651. initialPreviewThumbTags: [],
  19652. previewThumbTags: {},
  19653. initialPreviewShowDelete: true,
  19654. removeFromPreviewOnError: false,
  19655. deleteUrl: '',
  19656. deleteExtraData: {},
  19657. overwriteInitial: true,
  19658. previewZoomButtonIcons: {
  19659. prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
  19660. next: '<i class="glyphicon glyphicon-triangle-right"></i>',
  19661. toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
  19662. fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
  19663. borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
  19664. close: '<i class="glyphicon glyphicon-remove"></i>'
  19665. },
  19666. previewZoomButtonClasses: {
  19667. prev: 'btn btn-navigate',
  19668. next: 'btn btn-navigate',
  19669. toggleheader: 'btn btn-default btn-header-toggle',
  19670. fullscreen: 'btn btn-default',
  19671. borderless: 'btn btn-default',
  19672. close: 'btn btn-default'
  19673. },
  19674. preferIconicPreview: false,
  19675. preferIconicZoomPreview: false,
  19676. allowedPreviewTypes: undefined,
  19677. allowedPreviewMimeTypes: null,
  19678. allowedFileTypes: null,
  19679. allowedFileExtensions: null,
  19680. defaultPreviewContent: null,
  19681. customLayoutTags: {},
  19682. customPreviewTags: {},
  19683. previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
  19684. previewFileIconClass: 'file-other-icon',
  19685. previewFileIconSettings: {},
  19686. previewFileExtSettings: {},
  19687. buttonLabelClass: 'hidden-xs',
  19688. browseIcon: '<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',
  19689. browseClass: 'btn btn-primary',
  19690. removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
  19691. removeClass: 'btn btn-default',
  19692. cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
  19693. cancelClass: 'btn btn-default',
  19694. uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
  19695. uploadClass: 'btn btn-default',
  19696. uploadUrl: null,
  19697. uploadAsync: true,
  19698. uploadExtraData: {},
  19699. zoomModalHeight: 480,
  19700. minImageWidth: null,
  19701. minImageHeight: null,
  19702. maxImageWidth: null,
  19703. maxImageHeight: null,
  19704. resizeImage: false,
  19705. resizePreference: 'width',
  19706. resizeQuality: 0.92,
  19707. resizeDefaultImageType: 'image/jpeg',
  19708. resizeIfSizeMoreThan: 0, // in KB
  19709. minFileSize: 0,
  19710. maxFileSize: 0,
  19711. maxFilePreviewSize: 25600, // 25 MB
  19712. minFileCount: 0,
  19713. maxFileCount: 0,
  19714. validateInitialCount: false,
  19715. msgValidationErrorClass: 'text-danger',
  19716. msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
  19717. msgErrorClass: 'file-error-message',
  19718. progressThumbClass: "progress-bar progress-bar-success progress-bar-striped active",
  19719. progressClass: "progress-bar progress-bar-success progress-bar-striped active",
  19720. progressCompleteClass: "progress-bar progress-bar-success",
  19721. progressErrorClass: "progress-bar progress-bar-danger",
  19722. progressUploadThreshold: 99,
  19723. previewFileType: 'image',
  19724. elCaptionContainer: null,
  19725. elCaptionText: null,
  19726. elPreviewContainer: null,
  19727. elPreviewImage: null,
  19728. elPreviewStatus: null,
  19729. elErrorContainer: null,
  19730. errorCloseButton: '<span class="close kv-error-close">&times;</span>',
  19731. slugCallback: null,
  19732. dropZoneEnabled: true,
  19733. dropZoneTitleClass: 'file-drop-zone-title',
  19734. fileActionSettings: {},
  19735. otherActionButtons: '',
  19736. textEncoding: 'UTF-8',
  19737. ajaxSettings: {},
  19738. ajaxDeleteSettings: {},
  19739. showAjaxErrorDetails: true
  19740. };
  19741. $.fn.fileinputLocales.en = {
  19742. fileSingle: 'file',
  19743. filePlural: 'files',
  19744. browseLabel: 'Browse &hellip;',
  19745. removeLabel: 'Remove',
  19746. removeTitle: 'Clear selected files',
  19747. cancelLabel: 'Cancel',
  19748. cancelTitle: 'Abort ongoing upload',
  19749. uploadLabel: 'Upload',
  19750. uploadTitle: 'Upload selected files',
  19751. msgNo: 'No',
  19752. msgNoFilesSelected: 'No files selected',
  19753. msgCancelled: 'Cancelled',
  19754. msgZoomModalHeading: 'Detailed Preview',
  19755. msgFileRequired: 'You must select a file to upload.',
  19756. msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
  19757. msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
  19758. msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
  19759. msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
  19760. msgFileNotFound: 'File "{name}" not found!',
  19761. msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
  19762. msgFileNotReadable: 'File "{name}" is not readable.',
  19763. msgFilePreviewAborted: 'File preview aborted for "{name}".',
  19764. msgFilePreviewError: 'An error occurred while reading the file "{name}".',
  19765. msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
  19766. msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
  19767. msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
  19768. msgFileTypes: {
  19769. 'image': 'image',
  19770. 'html': 'HTML',
  19771. 'text': 'text',
  19772. 'video': 'video',
  19773. 'audio': 'audio',
  19774. 'flash': 'flash',
  19775. 'pdf': 'PDF',
  19776. 'object': 'object'
  19777. },
  19778. msgUploadAborted: 'The file upload was aborted',
  19779. msgUploadThreshold: 'Processing...',
  19780. msgUploadBegin: 'Initializing...',
  19781. msgUploadEnd: 'Done',
  19782. msgUploadEmpty: 'No valid data available for upload.',
  19783. msgValidationError: 'Validation Error',
  19784. msgLoading: 'Loading file {index} of {files} &hellip;',
  19785. msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
  19786. msgSelected: '{n} {files} selected',
  19787. msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
  19788. msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
  19789. msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
  19790. msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
  19791. msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
  19792. msgImageResizeError: 'Could not get the image dimensions to resize.',
  19793. msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
  19794. msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
  19795. msgAjaxProgressError: '{operation} failed',
  19796. ajaxOperations: {
  19797. deleteThumb: 'file delete',
  19798. uploadThumb: 'file upload',
  19799. uploadBatch: 'batch file upload',
  19800. uploadExtra: 'form data upload'
  19801. },
  19802. dropZoneTitle: 'Drag & drop files here &hellip;',
  19803. dropZoneClickTitle: '<br>(or click to select {files})',
  19804. previewZoomButtonTitles: {
  19805. prev: 'View previous file',
  19806. next: 'View next file',
  19807. toggleheader: 'Toggle header',
  19808. fullscreen: 'Toggle full screen',
  19809. borderless: 'Toggle borderless mode',
  19810. close: 'Close detailed preview'
  19811. }
  19812. };
  19813. $.fn.fileinput.Constructor = FileInput;
  19814. /**
  19815. * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
  19816. */
  19817. $(document).ready(function () {
  19818. var $input = $('input.file[type=file]');
  19819. if ($input.length) {
  19820. $input.fileinput();
  19821. }
  19822. });
  19823. }));
  19824. /***/ }),
  19825. /* 8 */
  19826. /***/ (function(module, exports) {
  19827. // removed by extract-text-webpack-plugin
  19828. /***/ }),
  19829. /* 9 */
  19830. /***/ (function(module, exports) {
  19831. // removed by extract-text-webpack-plugin
  19832. /***/ }),
  19833. /* 10 */
  19834. /***/ (function(module, exports) {
  19835. // removed by extract-text-webpack-plugin
  19836. /***/ }),
  19837. /* 11 */
  19838. /***/ (function(module, exports) {
  19839. // removed by extract-text-webpack-plugin
  19840. /***/ })
  19841. /******/ ]);
  19842. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgMTk4MDQ5MzBkOTE4YmY5ZWZhYmUiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS9kaXN0L2pxdWVyeS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2pzL2Jvb3RzdHJhcC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcG9wcGVyLmpzL2Rpc3QvZXNtL3BvcHBlci5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtc2VsZWN0L2Rpc3QvanMvYm9vdHN0cmFwLXNlbGVjdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXZhbGlkYXRvci9qcy92YWxpZGF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvanMvZmlsZWlucHV0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9jc3MvYm9vdHN0cmFwLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLWZpbGVpbnB1dC9jc3MvZmlsZWlucHV0LmNzcyIsIndlYnBhY2s6Ly8vLi9zcmMvc3R5bGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7OztBQzdEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxZQUFZOztBQUVwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUYsb0JBQW9COztBQUVwQjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLFNBQVM7QUFDbEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTLFlBQVk7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsU0FBUztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLGdCQUFnQixJQUFJOztBQUVwQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSx3Q0FBd0MsSUFBSTtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhLHlCQUF5QjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRLDZCQUE2QjtBQUNoRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCLGFBQWEsdUJBQXVCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsZUFBZTtBQUMxQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsZUFBZTtBQUMxQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsVUFBVTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsY0FBYztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsZ0NBQWdDLE1BQU07QUFDdEM7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsZUFBZTs7QUFFZixTQUFTOztBQUVUO0FBQ0EsUUFBUSxpQ0FBaUM7QUFDekMsUUFBUSxvQkFBb0I7QUFDNUIsUUFBUSxzQ0FBc0M7QUFDOUMsUUFBUTtBQUNSLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixhQUFhLEVBQUU7QUFDL0I7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLDREQUE0RDs7QUFFNUQ7QUFDQTtBQUNBO0FBQ0EseUNBQXlDOztBQUV6QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQ7O0FBRTdEO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQzs7QUFFMUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnRUFBZ0U7O0FBRWhFO0FBQ0E7QUFDQTtBQUNBLDZDQUE2Qzs7QUFFN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxpRUFBaUUsVUFBVTtBQUMzRSxzQ0FBc0MsMkJBQTJCO0FBQ2pFO0FBQ0EsZ0NBQWdDLE1BQU07QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLFVBQVU7QUFDcEI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxjQUFjO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBOztBQUVBO0FBQ0EsWUFBWSx1RUFBdUU7QUFDbkY7QUFDQTtBQUNBLFlBQVksNEJBQTRCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLDJEQUEyRDs7QUFFM0Q7QUFDQTtBQUNBLG9GQUFvRjs7QUFFcEY7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUEsbUNBQW1DO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLFNBQVM7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxpREFBaUQ7QUFDeEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpREFBaUQ7QUFDakQsVUFBVSx3Q0FBd0M7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxnQkFBZ0I7QUFDM0I7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsTUFBTTtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTs7QUFFQSxDQUFDOzs7O0FBSUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUEsUUFBUSxHQUFHO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7Ozs7QUFJQTs7QUFFQTs7QUFFQTtBQUNBOzs7O0FBSUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZ0IsU0FBUztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQSxjQUFjLFNBQVM7QUFDdkI7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVLE9BQU87QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQiwwQkFBMEIsd0JBQXdCOztBQUVsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQSwwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7QUFDRDs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1COztBQUVuQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLGNBQWM7QUFDeEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROztBQUVSO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSx3Q0FBd0Msc0NBQXNDO0FBQzlFLG9DQUFvQyx1Q0FBdUM7QUFDM0Usb0NBQW9DLHNDQUFzQztBQUMxRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSLE9BQU87QUFDUDtBQUNBLE1BQU07QUFDTixLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVOztBQUVWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DO0FBQ3BDLHFDQUFxQztBQUNyQyxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7Ozs7QUFLQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLFNBQVM7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsYUFBYTtBQUNwQyxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9CQUFvQixTQUFTO0FBQzdCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBOzs7QUFHQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRLGdCQUFnQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsZ0JBQWdCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDO0FBQ0Q7O0FBRUE7O0FBRUE7Ozs7QUFJQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEVBQUU7QUFDRjs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxPQUFPO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsT0FBTztBQUNmOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFLGdCQUFnQjtBQUNsQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsV0FBVzs7QUFFWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDJDQUEyQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7O0FBRUE7QUFDQTs7QUFFQSxjQUFjLHNCQUFzQjtBQUNwQztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsK0RBQStEO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsVUFBVSxjQUFjOztBQUV4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLG1CQUFtQjtBQUNwQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLHVDQUF1QztBQUNqRTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsdURBQXVEO0FBQzlFOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsY0FBYztBQUNuRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7O0FBR0Q7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQ0FBMkMsT0FBTztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4Qjs7QUFFOUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLGdCQUFnQjtBQUNoQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsK0JBQStCO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSx1Q0FBdUMsT0FBTztBQUM5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3Q0FBd0MsT0FBTztBQUMvQztBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVMscUNBQXFDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUEsU0FBUyw4QkFBOEI7QUFDdkM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFlBQVksT0FBTztBQUNuQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVMsV0FBVztBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7Ozs7QUFJQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwwQkFBMEI7QUFDMUIsc0JBQXNCLGNBQWM7QUFDcEMsZ0JBQWdCLFdBQVcsWUFBWTtBQUN2QyxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsVUFBVSxTQUFTLE1BQU0sYUFBYTtBQUMzRSxhQUFhLGVBQWU7QUFDNUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRixDQUFDOzs7QUFHRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLCtEQUErRDtBQUMzRTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQSxRQUFRLE9BQU87O0FBRWY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBOztBQUVBLFVBQVUsT0FBTztBQUNqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFdBQVcsU0FBUztBQUNwQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBLFFBQVEsT0FBTztBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSxnQkFBZ0I7QUFDeEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixpREFBaUQsMEJBQTBCO0FBQzNFOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsVUFBVSxnQkFBZ0I7QUFDMUI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxnQkFBZ0I7QUFDM0I7QUFDQTs7QUFFQSw2Q0FBNkM7QUFDN0M7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBLFFBQVEsZ0JBQWdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxnQkFBZ0I7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0IsY0FBYztBQUNsQyxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpREFBaUQ7O0FBRWpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsK0JBQStCLFNBQVM7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCLFNBQVM7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQixnQkFBZ0I7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLGtCQUFrQjtBQUM1QixXQUFXLGtCQUFrQjtBQUM3QixjQUFjO0FBQ2QsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxRQUFRLG1CQUFtQjtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBLGlDQUFpQztBQUNqQztBQUNBOztBQUVBLElBQUk7QUFDSjs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFNBQVM7QUFDcEI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7OztBQUdBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNDQUFzQztBQUN0QztBQUNBO0FBQ0E7O0FBRUE7O0FBRUEseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsOENBQThDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDO0FBQzNDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxLQUFLO0FBQ2Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHFDQUFxQzs7QUFFcEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYixLQUFLO0FBQ0w7O0FBRUEsV0FBVztBQUNYLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCOztBQUVoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCOztBQUVoQixnREFBZ0Q7QUFDaEQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxtQkFBbUI7QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQjtBQUNqQixTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0RBQWtEOztBQUVsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQjs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQSxzQkFBc0I7QUFDdEIsMkJBQTJCOztBQUUzQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBLG1EQUFtRDtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsdUJBQXVCO0FBQ2xDLFdBQVcseUJBQXlCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSDs7QUFFQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EscURBQXFEO0FBQ3JEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkIsNERBQTRELGVBQWU7QUFDM0U7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0EsY0FBYyxzREFBc0Q7QUFDcEU7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQSxjQUFjLG1DQUFtQztBQUNqRCxlQUFlLDZEQUE2RDtBQUM1RTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsRUFBRTtBQUNGLENBQUM7OztBQUdEOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFBQTtBQUNGOzs7OztBQUtBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDNWdVRDtBQUFBO0FBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLGVBQWU7QUFDOUIsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLCtCQUErQiwyQkFBMkI7QUFDMUQsMENBQTBDLGVBQWU7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsbUJBQW1CLG1CQUFtQjs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsbUJBQW1CLG1CQUFtQjs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQix1QkFBdUI7O0FBRXREO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsNEJBQTRCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLHVCQUF1QixhQUFhLEdBQUcsV0FBVyxHQUFHLGFBQWEsR0FBRyxjQUFjO0FBQ25GO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUEsQ0FBQzs7Ozs7OztBQ25KRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDLENBQUMscUNBQXFDOztBQUV0QztBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLGtCQUFrQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsc0JBQXNCO0FBQ3pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDOztBQUV2QztBQUNBLGVBQWU7QUFDZjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEU7O0FBRUEsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRDtBQUNoRCxTQUFTOztBQUVUO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBLHFFQUFxRTs7QUFFckU7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87OztBQUdQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDOztBQUVoQyxpQ0FBaUM7O0FBRWpDLHFDQUFxQzs7QUFFckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87OztBQUdQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDOztBQUV4QztBQUNBLHNDQUFzQztBQUN0Qzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHFDQUFxQzs7QUFFckM7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQSw2Q0FBNkMsU0FBUztBQUN0RDs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0RBQWdELFNBQVM7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUIsd0JBQXdCO0FBQ2pEO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0EsaUNBQWlDO0FBQ2pDLCtDQUErQzs7QUFFL0M7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSx1Q0FBdUM7O0FBRXZDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLDJFQUEyRTs7QUFFbkg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCOztBQUU1QiwyQkFBMkI7O0FBRTNCLHdCQUF3Qjs7QUFFeEIsOEJBQThCOztBQUU5QixnQ0FBZ0M7O0FBRWhDLHFDQUFxQzs7QUFFckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsc0RBQXNEOztBQUV0RDtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsMkNBQTJDLHlEQUF5RDtBQUNwRztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLDZDQUE2QyxTQUFTO0FBQ3REOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCOztBQUU1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7O0FBRVQ7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0dBQWdHOztBQUVoRztBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsRUFBRTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUyxFQUFFOztBQUVYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLEVBQUU7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQSx3Q0FBd0MsZ0ZBQWdGOztBQUV4SDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNEVBQTRFOztBQUU1RTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0Qjs7QUFFNUI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCw2Q0FBNkM7QUFDN0M7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7O0FBRVQ7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGlDQUFpQyx5R0FBeUc7O0FBRTFJO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTCxzQ0FBc0M7QUFDdEM7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOENBQThDOztBQUU5Qzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0EsaUNBQWlDLDZEQUE2RDs7QUFFOUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxrQ0FBa0MsS0FBSztBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsZ0RBQWdEOzs7QUFHaEQ7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSwyQ0FBMkM7QUFDM0M7O0FBRUEsa0lBQWtJOztBQUVsSTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxLQUFLO0FBQ3pDOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdEQUFnRCxjQUFjOztBQUU5RCxDQUFDO0FBQ0Q7Ozs7Ozs7OztBQ3YySEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGVBQWUsa0NBQWtDO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFNBQVM7QUFDdEIsWUFBWTtBQUNaO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLElBQUk7QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsWUFBWTtBQUN2QixXQUFXLFFBQVE7QUFDbkIsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLG9CQUFvQjtBQUMvQjtBQUNBLFdBQVcsT0FBTztBQUNsQixZQUFZLE9BQU87QUFDbkI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLGtCQUFrQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7O0FBTUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixzQkFBc0I7QUFDdkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsWUFBWTtBQUN2QixZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFlBQVk7QUFDdkIsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsT0FBTztBQUNsQixXQUFXLFlBQVk7QUFDdkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsb0JBQW9CO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFlBQVk7QUFDdkIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxXQUFXO0FBQ3RCLFdBQVcsTUFBTTtBQUNqQixXQUFXLE9BQU87QUFDbEIsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYztBQUNkLG1CQUFtQjtBQUNuQixrQkFBa0I7QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIscUJBQXFCO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QyxnQkFBZ0I7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFLGdCQUFnQjs7QUFFdEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7QUFDYixZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsWUFBWTtBQUN2QixXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQix5REFBeUQ7O0FBRTlFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBQzNCLGdDQUFnQzs7QUFFaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVixVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLFFBQVE7QUFDdEIsYUFBYSxNQUFNO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHVDQUF1Qzs7QUFFdkM7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE1BQU07QUFDbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsY0FBYztBQUM1QjtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRDtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUIsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEIsR0FBRzs7QUFFSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4QkFBOEI7QUFDOUIsNEJBQTRCO0FBQzVCOztBQUVBLHFDQUFxQztBQUNyQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxXQUFXO0FBQ3pCLGNBQWMsT0FBTztBQUNyQixhQUFhLFdBQVc7QUFDeEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLGVBQWUsY0FBYztBQUM3QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxtQkFBbUI7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsZUFBZSxtQkFBbUI7QUFDbEM7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBO0FBQ0EsY0FBYyxhQUFhO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLGVBQWUsU0FBUztBQUN4QjtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxRQUFRO0FBQ3RCLGNBQWMsUUFBUTtBQUN0QixjQUFjLFlBQVk7QUFDMUIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSxJQUFJO0FBQ0o7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxrQkFBa0I7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0Esa0NBQWtDOztBQUVsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsV0FBVztBQUN0Qjs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxXQUFXO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsNEJBQTRCO0FBQ3pDLGFBQWEsWUFBWTtBQUN6QixhQUFhLE9BQU87QUFDcEIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWM7QUFDZCw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQixpREFBaUQsdUNBQXVDLGtEQUFrRDtBQUMxSSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsU0FBUztBQUN2QjtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7QUNuK0VBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDOzs7Ozs7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUFBO0FBQ0wsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSyx5QkFBeUI7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyx1QkFBdUI7QUFDOUIsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGNBQWM7QUFDZCxjQUFjO0FBQ2QsZ0JBQWdCO0FBQ2hCLGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEI7O0FBRUE7QUFDQSxVQUFVO0FBQ1YsU0FBUztBQUNULFNBQVM7QUFDVCxXQUFXO0FBQ1gsV0FBVztBQUNYLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxFQUFFO0FBQzVDO0FBQ0Esb0NBQW9DLEVBQUUsb0JBQW9CLEVBQUU7QUFDNUQsS0FBSztBQUNMO0FBQ0E7QUFDQSx5Q0FBeUMsRUFBRSwrQkFBK0IsRUFBRTtBQUM1RSxpREFBaUQsRUFBRSxxQ0FBcUMsRUFBRTtBQUMxRjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtSUFBbUk7QUFDbkk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7O0FBRXZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxvQ0FBb0M7QUFDcEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLEVBQUUsOENBQThDLEVBQUU7QUFDdkY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDhCQUE4QjtBQUM5Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiw4QkFBOEI7QUFDOUI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsMERBQTBELEVBQUU7QUFDNUQsNkRBQTZELEVBQUU7QUFDL0Q7QUFDQSx5QkFBeUIsSUFBSTtBQUM3QjtBQUNBO0FBQ0EsOENBQThDLElBQUk7QUFDbEQsb0RBQW9ELElBQUk7QUFDeEQ7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBLG9FQUFvRSxFQUFFO0FBQ3RFO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQSxxQkFBcUIsZUFBZTtBQUNwQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyx5REFBeUQ7QUFDM0YsdUNBQXVDLHdHQUF3RztBQUMvSTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxDQUFDOzs7QUFHRCxDQUFDOzs7Ozs7O0FDLzBERDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLDRCQUE0QjtBQUN2RDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLDhDQUE4QyxzQkFBc0I7QUFDcEU7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDLHNDQUFzQztBQUNuRiwyQ0FBMkMsMENBQTBDOztBQUVyRjtBQUNBOztBQUVBOztBQUVBLCtEQUErRCxzQkFBc0I7QUFDckYsS0FBSztBQUNMOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxrREFBa0Q7QUFDdkcsK0JBQStCLDBCQUEwQjtBQUN6RCxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw2QkFBNkIsd0RBQXdEO0FBQ3JGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw4Q0FBOEMsbUNBQW1DOztBQUVqRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDN1pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBcUQ7QUFDckQ7QUFDQTtBQUFBO0FBQUE7QUFBQSxxR0FBb0M7QUFDcEMsS0FBSyxPQUFPO0FBQ1osMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQSx3REFBd0Q7QUFDeEQsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsYUFBYTtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsT0FBTyxRQUFRLFFBQVE7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIscUJBQXFCLEdBQUcsZ0JBQWdCO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsZ0JBQWdCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLG9CQUFvQjtBQUMzQztBQUNBO0FBQ0Esa0VBQWtFO0FBQ2xFO0FBQ0EsNEZBQTRGLGNBQWM7QUFDMUc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSwyQ0FBMkM7QUFDM0Msb0NBQW9DO0FBQ3BDLG9DQUFvQztBQUNwQyxzQ0FBc0M7QUFDdEMsc0NBQXNDO0FBQ3RDLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsOEJBQThCO0FBQ3hEO0FBQ0EsYUFBYTtBQUNiLDBCQUEwQixxQ0FBcUM7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELE1BQU07QUFDdEQsd0RBQXdELE1BQU07QUFDOUQscURBQXFELE1BQU07QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsUUFBUTtBQUMvQjtBQUNBLDBDQUEwQyxNQUFNO0FBQ2hELHFCQUFxQixRQUFRO0FBQzdCO0FBQ0EseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEM7QUFDQTtBQUNBLHVCQUF1QixRQUFRLGdEQUFnRCxPQUFPLEdBQUcsT0FBTyxHQUFHLE9BQU8sR0FBRyxPQUFPO0FBQ3BILGtEQUFrRCxNQUFNO0FBQ3hELHNCQUFzQixNQUFNO0FBQzVCLGtDQUFrQyxVQUFVO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0EsOEVBQThFLE1BQU07QUFDcEY7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLEtBQUsseUJBQXlCLE1BQU0sVUFBVSxJQUFJO0FBQzVGLGtCQUFrQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDeEM7QUFDQSxrQ0FBa0MsS0FBSyx5QkFBeUIsTUFBTSxVQUFVLElBQUksR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDN0c7QUFDQSxzREFBc0QsSUFBSSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTTtBQUNuRjtBQUNBO0FBQ0Esd0RBQXdELElBQUk7QUFDNUQ7QUFDQTtBQUNBLGdFQUFnRSxjQUFjLFlBQVksWUFBWSxNQUFNO0FBQzVHLGdEQUFnRCxRQUFRO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxlQUFlLGdCQUFnQixLQUFLLEVBQUUsS0FBSztBQUM5RztBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxNQUFNO0FBQ3hDLGtDQUFrQyxRQUFRLHNEQUFzRCxRQUFRLEVBQUU7QUFDMUcsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBLDhCQUE4QixTQUFTO0FBQ3ZDO0FBQ0EsOERBQThELFFBQVEsR0FBRyxRQUFRLEtBQUssS0FBSztBQUMzRixzQkFBc0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRO0FBQ3JEO0FBQ0EseUJBQXlCLEtBQUs7QUFDOUI7QUFDQTtBQUNBLDBCQUEwQixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFLFlBQVk7QUFDdEYseUJBQXlCLFlBQVksR0FBRyxTQUFTLFFBQVEsRUFBRSxXQUFXO0FBQ3RFLDBFQUEwRSxZQUFZLFVBQVUsWUFBWTtBQUM1RyxrQkFBa0IsV0FBVztBQUM3QixzRUFBc0UsVUFBVTtBQUNoRix5QkFBeUIsVUFBVSxHQUFHLFNBQVM7QUFDL0MsMERBQTBELFVBQVUsVUFBVSxVQUFVLEdBQUcsU0FBUztBQUNwRyxxRUFBcUUsZUFBZSxHQUFHLFVBQVU7QUFDakcsdURBQXVELFdBQVcsT0FBTyxVQUFVLG1CQUFtQixVQUFVO0FBQ2hILGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0EsMkNBQTJDLFFBQVE7QUFDbkQsOEJBQThCLE9BQU87QUFDckMseUJBQXlCLFFBQVE7QUFDakMsNEVBQTRFLFFBQVE7QUFDcEYsbUJBQW1CLEtBQUs7QUFDeEIsaUNBQWlDLEtBQUsscURBQXFELFFBQVEsUUFBUSxRQUFRO0FBQ25IO0FBQ0EsaUZBQWlGLFFBQVE7QUFDekYsc0NBQXNDLEtBQUs7QUFDM0MsZ0ZBQWdGLE1BQU07QUFDdEYsMEJBQTBCLE9BQU8sZ0NBQWdDLEtBQUssU0FBUyxLQUFLO0FBQ3BGO0FBQ0EsOEdBQThHLEtBQUs7QUFDbkgsd0JBQXdCLEtBQUs7QUFDN0I7QUFDQSx5QkFBeUIsTUFBTSxXQUFXLE9BQU8sU0FBUyxLQUFLO0FBQy9EO0FBQ0EsbUVBQW1FLFFBQVEsU0FBUyxLQUFLLFNBQVMsS0FBSztBQUN2Ryx5QkFBeUIsTUFBTSxXQUFXLE9BQU8scUNBQXFDLFFBQVE7QUFDOUY7QUFDQSx5REFBeUQsS0FBSztBQUM5RCx5QkFBeUIsTUFBTSxXQUFXLE9BQU87QUFDakQ7QUFDQSwyRUFBMkUsWUFBWTtBQUN2RiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0EsNEJBQTRCLCtCQUErQjtBQUMzRCwyQkFBMkIsZ0NBQWdDO0FBQzNELDJCQUEyQixnQ0FBZ0M7QUFDM0QsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QixtREFBbUQ7QUFDL0UsNkJBQTZCLGVBQWU7QUFDNUMsMEJBQTBCLGdDQUFnQztBQUMxRCw0QkFBNEI7QUFDNUIsaUJBQWlCO0FBQ2pCO0FBQ0EsNEJBQTRCLHlFQUF5RTtBQUNyRztBQUNBO0FBQ0EsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QiwrQkFBK0I7QUFDM0QsNkJBQTZCLDBFQUEwRTtBQUN2RztBQUNBLDRCQUE0QjtBQUM1QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QyxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLHdDQUF3QywyQkFBMkI7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxvQkFBb0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsbUJBQW1CO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLGlCQUFpQjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0EsK0JBQStCLFNBQVM7QUFDeEM7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsOENBQThDLEtBQUs7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxFQUFFO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EscURBQXFELEVBQUUsZ0NBQWdDLE1BQU07QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EscURBQXFELFVBQVU7QUFDL0Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1QkFBdUIsa0JBQWtCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLDhCQUE4QixnQkFBZ0I7QUFDOUMscUNBQXFDLDBFQUEwRTtBQUMvRztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGtFQUFrRTtBQUNsRSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsc0NBQXNDO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLDJDQUEyQztBQUN0RixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHNEQUFzRCxFQUFFLGdCQUFnQixNQUFNO0FBQzlFLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLDJCQUEyQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUZBQXFGLHdCQUF3QjtBQUM3RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsc0JBQXNCO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNGQUFzRixVQUFVO0FBQ2hHO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0Esc0ZBQXNGO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0EsbUdBQW1HO0FBQ25HO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsR0FBRyxVQUFVO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QixxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsU0FBUztBQUN0RSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLFlBQVk7QUFDNUY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThELDJCQUEyQjtBQUN6RjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsaUNBQWlDO0FBQzlEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixTQUFTO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLDZFQUE2RSxFQUFFO0FBQy9FLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHFCQUFxQixJQUFJLFdBQVcsNEJBQTRCO0FBQzlHLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFlBQVk7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsS0FBSztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixzQkFBc0I7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRSxtQ0FBbUM7QUFDcEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxzQ0FBc0M7QUFDNUc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxNQUFNLG9CQUFvQixNQUFNO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsdURBQXVEO0FBQ3JHLGlCQUFpQjtBQUNqQiw4Q0FBOEMsb0VBQW9FO0FBQ2xIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxNQUFNO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCw2QkFBNkI7QUFDeEY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBLDJDQUEyQyxPQUFPO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsOEJBQThCO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsT0FBTztBQUNwRSxpQ0FBaUMsc0JBQXNCO0FBQ3ZEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QyxtRUFBbUU7QUFDM0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLGlEQUFpRDtBQUNqRjtBQUNBLDBEQUEwRCx1Q0FBdUM7QUFDakc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkVBQTZFLEtBQUs7QUFDbEYscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCw4Q0FBOEM7QUFDL0Y7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLDBDQUEwQztBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLGdCQUFnQjtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1RkFBdUY7QUFDdkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxxQkFBcUIsSUFBSSxXQUFXLDRCQUE0QjtBQUM5Ryw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0EsK0NBQStDLDBDQUEwQztBQUN6RixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCxFQUFFLGdDQUFnQyxFQUFFO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsd0RBQXdEO0FBQ3pGO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUNBQWlDLG9DQUFvQztBQUNyRTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFNBQVM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxRQUFRO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkMsa0NBQWtDO0FBQ2xDO0FBQ0EsMEVBQTBFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBLHdCQUF3QjtBQUN4Qiw4QkFBOEI7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxLQUFLLE9BQU8sS0FBSyxrREFBa0QsUUFBUTtBQUM1RyxpQ0FBaUMsS0FBSyxPQUFPLEtBQUssb0RBQW9ELFFBQVE7QUFDOUcsdURBQXVELEVBQUUsTUFBTSxNQUFNO0FBQ3JFLG1FQUFtRSxFQUFFLDJDQUEyQyxFQUFFO0FBQ2xILGlDQUFpQyxLQUFLO0FBQ3RDLDBFQUEwRSxLQUFLO0FBQy9FLG9DQUFvQyxLQUFLO0FBQ3pDLDJEQUEyRCxLQUFLO0FBQ2hFLHlFQUF5RSxLQUFLO0FBQzlFLDhFQUE4RSxLQUFLO0FBQ25GLHFEQUFxRCxLQUFLLFVBQVUsTUFBTTtBQUMxRSwrREFBK0QsS0FBSyxVQUFVLFdBQVc7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxNQUFNLEtBQUssTUFBTSxTQUFTO0FBQzdELG9DQUFvQyxNQUFNLEtBQUssTUFBTSxJQUFJLEtBQUssSUFBSSxRQUFRO0FBQzFFLHVCQUF1QixFQUFFLEVBQUUsTUFBTTtBQUNqQyx3REFBd0QsRUFBRTtBQUMxRCxtREFBbUQsS0FBSyxvQkFBb0IsS0FBSztBQUNqRixxREFBcUQsS0FBSyxvQkFBb0IsS0FBSztBQUNuRixtREFBbUQsS0FBSyxpQkFBaUIsS0FBSztBQUM5RSxxREFBcUQsS0FBSyxpQkFBaUIsS0FBSztBQUNoRjtBQUNBLHVFQUF1RSxPQUFPO0FBQzlFLHNEQUFzRCxVQUFVO0FBQ2hFLGdDQUFnQyxVQUFVO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsdURBQXVEO0FBQ3ZELHNEQUFzRCxNQUFNO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLENBQUMsRzs7Ozs7O0FDMzFIRCx5Qzs7Ozs7O0FDQUEseUM7Ozs7OztBQ0FBLHlDOzs7Ozs7QUNBQSx5QyIsImZpbGUiOiJtYWluLmJ1bmRsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbiBcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG4gXHRcdFx0XHRnZXQ6IGdldHRlclxuIFx0XHRcdH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDEpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIDE5ODA0OTMwZDkxOGJmOWVmYWJlIiwiLyohXG4gKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYzLjIuMVxuICogaHR0cHM6Ly9qcXVlcnkuY29tL1xuICpcbiAqIEluY2x1ZGVzIFNpenpsZS5qc1xuICogaHR0cHM6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IEpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKiBodHRwczovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTctMDMtMjBUMTg6NTlaXG4gKi9cbiggZnVuY3Rpb24oIGdsb2JhbCwgZmFjdG9yeSApIHtcblxuXHRcInVzZSBzdHJpY3RcIjtcblxuXHRpZiAoIHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0Ly8gRm9yIENvbW1vbkpTIGFuZCBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB3aGVyZSBhIHByb3BlciBgd2luZG93YFxuXHRcdC8vIGlzIHByZXNlbnQsIGV4ZWN1dGUgdGhlIGZhY3RvcnkgYW5kIGdldCBqUXVlcnkuXG5cdFx0Ly8gRm9yIGVudmlyb25tZW50cyB0aGF0IGRvIG5vdCBoYXZlIGEgYHdpbmRvd2Agd2l0aCBhIGBkb2N1bWVudGBcblx0XHQvLyAoc3VjaCBhcyBOb2RlLmpzKSwgZXhwb3NlIGEgZmFjdG9yeSBhcyBtb2R1bGUuZXhwb3J0cy5cblx0XHQvLyBUaGlzIGFjY2VudHVhdGVzIHRoZSBuZWVkIGZvciB0aGUgY3JlYXRpb24gb2YgYSByZWFsIGB3aW5kb3dgLlxuXHRcdC8vIGUuZy4gdmFyIGpRdWVyeSA9IHJlcXVpcmUoXCJqcXVlcnlcIikod2luZG93KTtcblx0XHQvLyBTZWUgdGlja2V0ICMxNDU0OSBmb3IgbW9yZSBpbmZvLlxuXHRcdG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsLmRvY3VtZW50ID9cblx0XHRcdGZhY3RvcnkoIGdsb2JhbCwgdHJ1ZSApIDpcblx0XHRcdGZ1bmN0aW9uKCB3ICkge1xuXHRcdFx0XHRpZiAoICF3LmRvY3VtZW50ICkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJqUXVlcnkgcmVxdWlyZXMgYSB3aW5kb3cgd2l0aCBhIGRvY3VtZW50XCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gZmFjdG9yeSggdyApO1xuXHRcdFx0fTtcblx0fSBlbHNlIHtcblx0XHRmYWN0b3J5KCBnbG9iYWwgKTtcblx0fVxuXG4vLyBQYXNzIHRoaXMgaWYgd2luZG93IGlzIG5vdCBkZWZpbmVkIHlldFxufSApKCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oIHdpbmRvdywgbm9HbG9iYWwgKSB7XG5cbi8vIEVkZ2UgPD0gMTIgLSAxMyssIEZpcmVmb3ggPD0xOCAtIDQ1KywgSUUgMTAgLSAxMSwgU2FmYXJpIDUuMSAtIDkrLCBpT1MgNiAtIDkuMVxuLy8gdGhyb3cgZXhjZXB0aW9ucyB3aGVuIG5vbi1zdHJpY3QgY29kZSAoZS5nLiwgQVNQLk5FVCA0LjUpIGFjY2Vzc2VzIHN0cmljdCBtb2RlXG4vLyBhcmd1bWVudHMuY2FsbGVlLmNhbGxlciAodHJhYy0xMzMzNSkuIEJ1dCBhcyBvZiBqUXVlcnkgMy4wICgyMDE2KSwgc3RyaWN0IG1vZGUgc2hvdWxkIGJlIGNvbW1vblxuLy8gZW5vdWdoIHRoYXQgYWxsIHN1Y2ggYXR0ZW1wdHMgYXJlIGd1YXJkZWQgaW4gYSB0cnkgYmxvY2suXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGFyciA9IFtdO1xuXG52YXIgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQ7XG5cbnZhciBnZXRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjtcblxudmFyIHNsaWNlID0gYXJyLnNsaWNlO1xuXG52YXIgY29uY2F0ID0gYXJyLmNvbmNhdDtcblxudmFyIHB1c2ggPSBhcnIucHVzaDtcblxudmFyIGluZGV4T2YgPSBhcnIuaW5kZXhPZjtcblxudmFyIGNsYXNzMnR5cGUgPSB7fTtcblxudmFyIHRvU3RyaW5nID0gY2xhc3MydHlwZS50b1N0cmluZztcblxudmFyIGhhc093biA9IGNsYXNzMnR5cGUuaGFzT3duUHJvcGVydHk7XG5cbnZhciBmblRvU3RyaW5nID0gaGFzT3duLnRvU3RyaW5nO1xuXG52YXIgT2JqZWN0RnVuY3Rpb25TdHJpbmcgPSBmblRvU3RyaW5nLmNhbGwoIE9iamVjdCApO1xuXG52YXIgc3VwcG9ydCA9IHt9O1xuXG5cblxuXHRmdW5jdGlvbiBET01FdmFsKCBjb2RlLCBkb2MgKSB7XG5cdFx0ZG9jID0gZG9jIHx8IGRvY3VtZW50O1xuXG5cdFx0dmFyIHNjcmlwdCA9IGRvYy5jcmVhdGVFbGVtZW50KCBcInNjcmlwdFwiICk7XG5cblx0XHRzY3JpcHQudGV4dCA9IGNvZGU7XG5cdFx0ZG9jLmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdCApLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHNjcmlwdCApO1xuXHR9XG4vKiBnbG9iYWwgU3ltYm9sICovXG4vLyBEZWZpbmluZyB0aGlzIGdsb2JhbCBpbiAuZXNsaW50cmMuanNvbiB3b3VsZCBjcmVhdGUgYSBkYW5nZXIgb2YgdXNpbmcgdGhlIGdsb2JhbFxuLy8gdW5ndWFyZGVkIGluIGFub3RoZXIgcGxhY2UsIGl0IHNlZW1zIHNhZmVyIHRvIGRlZmluZSBnbG9iYWwgb25seSBmb3IgdGhpcyBtb2R1bGVcblxuXG5cbnZhclxuXHR2ZXJzaW9uID0gXCIzLjIuMVwiLFxuXG5cdC8vIERlZmluZSBhIGxvY2FsIGNvcHkgb2YgalF1ZXJ5XG5cdGpRdWVyeSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblxuXHRcdC8vIFRoZSBqUXVlcnkgb2JqZWN0IGlzIGFjdHVhbGx5IGp1c3QgdGhlIGluaXQgY29uc3RydWN0b3IgJ2VuaGFuY2VkJ1xuXHRcdC8vIE5lZWQgaW5pdCBpZiBqUXVlcnkgaXMgY2FsbGVkIChqdXN0IGFsbG93IGVycm9yIHRvIGJlIHRocm93biBpZiBub3QgaW5jbHVkZWQpXG5cdFx0cmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHdlIHRyaW0gQk9NIGFuZCBOQlNQXG5cdHJ0cmltID0gL15bXFxzXFx1RkVGRlxceEEwXSt8W1xcc1xcdUZFRkZcXHhBMF0rJC9nLFxuXG5cdC8vIE1hdGNoZXMgZGFzaGVkIHN0cmluZyBmb3IgY2FtZWxpemluZ1xuXHRybXNQcmVmaXggPSAvXi1tcy0vLFxuXHRyZGFzaEFscGhhID0gLy0oW2Etel0pL2csXG5cblx0Ly8gVXNlZCBieSBqUXVlcnkuY2FtZWxDYXNlIGFzIGNhbGxiYWNrIHRvIHJlcGxhY2UoKVxuXHRmY2FtZWxDYXNlID0gZnVuY3Rpb24oIGFsbCwgbGV0dGVyICkge1xuXHRcdHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTtcblx0fTtcblxualF1ZXJ5LmZuID0galF1ZXJ5LnByb3RvdHlwZSA9IHtcblxuXHQvLyBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIGpRdWVyeSBiZWluZyB1c2VkXG5cdGpxdWVyeTogdmVyc2lvbixcblxuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LFxuXG5cdC8vIFRoZSBkZWZhdWx0IGxlbmd0aCBvZiBhIGpRdWVyeSBvYmplY3QgaXMgMFxuXHRsZW5ndGg6IDAsXG5cblx0dG9BcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SXG5cdC8vIEdldCB0aGUgd2hvbGUgbWF0Y2hlZCBlbGVtZW50IHNldCBhcyBhIGNsZWFuIGFycmF5XG5cdGdldDogZnVuY3Rpb24oIG51bSApIHtcblxuXHRcdC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGluIGEgY2xlYW4gYXJyYXlcblx0XHRpZiAoIG51bSA9PSBudWxsICkge1xuXHRcdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4ganVzdCB0aGUgb25lIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG5cdFx0cmV0dXJuIG51bSA8IDAgPyB0aGlzWyBudW0gKyB0aGlzLmxlbmd0aCBdIDogdGhpc1sgbnVtIF07XG5cdH0sXG5cblx0Ly8gVGFrZSBhbiBhcnJheSBvZiBlbGVtZW50cyBhbmQgcHVzaCBpdCBvbnRvIHRoZSBzdGFja1xuXHQvLyAocmV0dXJuaW5nIHRoZSBuZXcgbWF0Y2hlZCBlbGVtZW50IHNldClcblx0cHVzaFN0YWNrOiBmdW5jdGlvbiggZWxlbXMgKSB7XG5cblx0XHQvLyBCdWlsZCBhIG5ldyBqUXVlcnkgbWF0Y2hlZCBlbGVtZW50IHNldFxuXHRcdHZhciByZXQgPSBqUXVlcnkubWVyZ2UoIHRoaXMuY29uc3RydWN0b3IoKSwgZWxlbXMgKTtcblxuXHRcdC8vIEFkZCB0aGUgb2xkIG9iamVjdCBvbnRvIHRoZSBzdGFjayAoYXMgYSByZWZlcmVuY2UpXG5cdFx0cmV0LnByZXZPYmplY3QgPSB0aGlzO1xuXG5cdFx0Ly8gUmV0dXJuIHRoZSBuZXdseS1mb3JtZWQgZWxlbWVudCBzZXRcblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdC8vIEV4ZWN1dGUgYSBjYWxsYmFjayBmb3IgZXZlcnkgZWxlbWVudCBpbiB0aGUgbWF0Y2hlZCBzZXQuXG5cdGVhY2g6IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmVhY2goIHRoaXMsIGNhbGxiYWNrICk7XG5cdH0sXG5cblx0bWFwOiBmdW5jdGlvbiggY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkubWFwKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKCBlbGVtLCBpLCBlbGVtICk7XG5cdFx0fSApICk7XG5cdH0sXG5cblx0c2xpY2U6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggc2xpY2UuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApICk7XG5cdH0sXG5cblx0Zmlyc3Q6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVxKCAwICk7XG5cdH0sXG5cblx0bGFzdDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZXEoIC0xICk7XG5cdH0sXG5cblx0ZXE6IGZ1bmN0aW9uKCBpICkge1xuXHRcdHZhciBsZW4gPSB0aGlzLmxlbmd0aCxcblx0XHRcdGogPSAraSArICggaSA8IDAgPyBsZW4gOiAwICk7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqID49IDAgJiYgaiA8IGxlbiA/IFsgdGhpc1sgaiBdIF0gOiBbXSApO1xuXHR9LFxuXG5cdGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCk7XG5cdH0sXG5cblx0Ly8gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuXHQvLyBCZWhhdmVzIGxpa2UgYW4gQXJyYXkncyBtZXRob2QsIG5vdCBsaWtlIGEgalF1ZXJ5IG1ldGhvZC5cblx0cHVzaDogcHVzaCxcblx0c29ydDogYXJyLnNvcnQsXG5cdHNwbGljZTogYXJyLnNwbGljZVxufTtcblxualF1ZXJ5LmV4dGVuZCA9IGpRdWVyeS5mbi5leHRlbmQgPSBmdW5jdGlvbigpIHtcblx0dmFyIG9wdGlvbnMsIG5hbWUsIHNyYywgY29weSwgY29weUlzQXJyYXksIGNsb25lLFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgMCBdIHx8IHt9LFxuXHRcdGkgPSAxLFxuXHRcdGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cdFx0ZGVlcCA9IGZhbHNlO1xuXG5cdC8vIEhhbmRsZSBhIGRlZXAgY29weSBzaXR1YXRpb25cblx0aWYgKCB0eXBlb2YgdGFyZ2V0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRkZWVwID0gdGFyZ2V0O1xuXG5cdFx0Ly8gU2tpcCB0aGUgYm9vbGVhbiBhbmQgdGhlIHRhcmdldFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgaSBdIHx8IHt9O1xuXHRcdGkrKztcblx0fVxuXG5cdC8vIEhhbmRsZSBjYXNlIHdoZW4gdGFyZ2V0IGlzIGEgc3RyaW5nIG9yIHNvbWV0aGluZyAocG9zc2libGUgaW4gZGVlcCBjb3B5KVxuXHRpZiAoIHR5cGVvZiB0YXJnZXQgIT09IFwib2JqZWN0XCIgJiYgIWpRdWVyeS5pc0Z1bmN0aW9uKCB0YXJnZXQgKSApIHtcblx0XHR0YXJnZXQgPSB7fTtcblx0fVxuXG5cdC8vIEV4dGVuZCBqUXVlcnkgaXRzZWxmIGlmIG9ubHkgb25lIGFyZ3VtZW50IGlzIHBhc3NlZFxuXHRpZiAoIGkgPT09IGxlbmd0aCApIHtcblx0XHR0YXJnZXQgPSB0aGlzO1xuXHRcdGktLTtcblx0fVxuXG5cdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXG5cdFx0Ly8gT25seSBkZWFsIHdpdGggbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlc1xuXHRcdGlmICggKCBvcHRpb25zID0gYXJndW1lbnRzWyBpIF0gKSAhPSBudWxsICkge1xuXG5cdFx0XHQvLyBFeHRlbmQgdGhlIGJhc2Ugb2JqZWN0XG5cdFx0XHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRcdHNyYyA9IHRhcmdldFsgbmFtZSBdO1xuXHRcdFx0XHRjb3B5ID0gb3B0aW9uc1sgbmFtZSBdO1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbmV2ZXItZW5kaW5nIGxvb3Bcblx0XHRcdFx0aWYgKCB0YXJnZXQgPT09IGNvcHkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZWN1cnNlIGlmIHdlJ3JlIG1lcmdpbmcgcGxhaW4gb2JqZWN0cyBvciBhcnJheXNcblx0XHRcdFx0aWYgKCBkZWVwICYmIGNvcHkgJiYgKCBqUXVlcnkuaXNQbGFpbk9iamVjdCggY29weSApIHx8XG5cdFx0XHRcdFx0KCBjb3B5SXNBcnJheSA9IEFycmF5LmlzQXJyYXkoIGNvcHkgKSApICkgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGNvcHlJc0FycmF5ICkge1xuXHRcdFx0XHRcdFx0Y29weUlzQXJyYXkgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGNsb25lID0gc3JjICYmIEFycmF5LmlzQXJyYXkoIHNyYyApID8gc3JjIDogW107XG5cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIHNyYyApID8gc3JjIDoge307XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gTmV2ZXIgbW92ZSBvcmlnaW5hbCBvYmplY3RzLCBjbG9uZSB0aGVtXG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBqUXVlcnkuZXh0ZW5kKCBkZWVwLCBjbG9uZSwgY29weSApO1xuXG5cdFx0XHRcdC8vIERvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXNcblx0XHRcdFx0fSBlbHNlIGlmICggY29weSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHRhcmdldFsgbmFtZSBdID0gY29weTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbW9kaWZpZWQgb2JqZWN0XG5cdHJldHVybiB0YXJnZXQ7XG59O1xuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gVW5pcXVlIGZvciBlYWNoIGNvcHkgb2YgalF1ZXJ5IG9uIHRoZSBwYWdlXG5cdGV4cGFuZG86IFwialF1ZXJ5XCIgKyAoIHZlcnNpb24gKyBNYXRoLnJhbmRvbSgpICkucmVwbGFjZSggL1xcRC9nLCBcIlwiICksXG5cblx0Ly8gQXNzdW1lIGpRdWVyeSBpcyByZWFkeSB3aXRob3V0IHRoZSByZWFkeSBtb2R1bGVcblx0aXNSZWFkeTogdHJ1ZSxcblxuXHRlcnJvcjogZnVuY3Rpb24oIG1zZyApIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoIG1zZyApO1xuXHR9LFxuXG5cdG5vb3A6IGZ1bmN0aW9uKCkge30sXG5cblx0aXNGdW5jdGlvbjogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LnR5cGUoIG9iaiApID09PSBcImZ1bmN0aW9uXCI7XG5cdH0sXG5cblx0aXNXaW5kb3c6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0cmV0dXJuIG9iaiAhPSBudWxsICYmIG9iaiA9PT0gb2JqLndpbmRvdztcblx0fSxcblxuXHRpc051bWVyaWM6IGZ1bmN0aW9uKCBvYmogKSB7XG5cblx0XHQvLyBBcyBvZiBqUXVlcnkgMy4wLCBpc051bWVyaWMgaXMgbGltaXRlZCB0b1xuXHRcdC8vIHN0cmluZ3MgYW5kIG51bWJlcnMgKHByaW1pdGl2ZXMgb3Igb2JqZWN0cylcblx0XHQvLyB0aGF0IGNhbiBiZSBjb2VyY2VkIHRvIGZpbml0ZSBudW1iZXJzIChnaC0yNjYyKVxuXHRcdHZhciB0eXBlID0galF1ZXJ5LnR5cGUoIG9iaiApO1xuXHRcdHJldHVybiAoIHR5cGUgPT09IFwibnVtYmVyXCIgfHwgdHlwZSA9PT0gXCJzdHJpbmdcIiApICYmXG5cblx0XHRcdC8vIHBhcnNlRmxvYXQgTmFOcyBudW1lcmljLWNhc3QgZmFsc2UgcG9zaXRpdmVzIChcIlwiKVxuXHRcdFx0Ly8gLi4uYnV0IG1pc2ludGVycHJldHMgbGVhZGluZy1udW1iZXIgc3RyaW5ncywgcGFydGljdWxhcmx5IGhleCBsaXRlcmFscyAoXCIweC4uLlwiKVxuXHRcdFx0Ly8gc3VidHJhY3Rpb24gZm9yY2VzIGluZmluaXRpZXMgdG8gTmFOXG5cdFx0XHQhaXNOYU4oIG9iaiAtIHBhcnNlRmxvYXQoIG9iaiApICk7XG5cdH0sXG5cblx0aXNQbGFpbk9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHR2YXIgcHJvdG8sIEN0b3I7XG5cblx0XHQvLyBEZXRlY3Qgb2J2aW91cyBuZWdhdGl2ZXNcblx0XHQvLyBVc2UgdG9TdHJpbmcgaW5zdGVhZCBvZiBqUXVlcnkudHlwZSB0byBjYXRjaCBob3N0IG9iamVjdHNcblx0XHRpZiAoICFvYmogfHwgdG9TdHJpbmcuY2FsbCggb2JqICkgIT09IFwiW29iamVjdCBPYmplY3RdXCIgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cHJvdG8gPSBnZXRQcm90byggb2JqICk7XG5cblx0XHQvLyBPYmplY3RzIHdpdGggbm8gcHJvdG90eXBlIChlLmcuLCBgT2JqZWN0LmNyZWF0ZSggbnVsbCApYCkgYXJlIHBsYWluXG5cdFx0aWYgKCAhcHJvdG8gKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBPYmplY3RzIHdpdGggcHJvdG90eXBlIGFyZSBwbGFpbiBpZmYgdGhleSB3ZXJlIGNvbnN0cnVjdGVkIGJ5IGEgZ2xvYmFsIE9iamVjdCBmdW5jdGlvblxuXHRcdEN0b3IgPSBoYXNPd24uY2FsbCggcHJvdG8sIFwiY29uc3RydWN0b3JcIiApICYmIHByb3RvLmNvbnN0cnVjdG9yO1xuXHRcdHJldHVybiB0eXBlb2YgQ3RvciA9PT0gXCJmdW5jdGlvblwiICYmIGZuVG9TdHJpbmcuY2FsbCggQ3RvciApID09PSBPYmplY3RGdW5jdGlvblN0cmluZztcblx0fSxcblxuXHRpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiggb2JqICkge1xuXG5cdFx0LyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cblx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzbGludC9lc2xpbnQvaXNzdWVzLzYxMjVcblx0XHR2YXIgbmFtZTtcblxuXHRcdGZvciAoIG5hbWUgaW4gb2JqICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSxcblxuXHR0eXBlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdGlmICggb2JqID09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gb2JqICsgXCJcIjtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9Mi4zIG9ubHkgKGZ1bmN0aW9uaXNoIFJlZ0V4cClcblx0XHRyZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgP1xuXHRcdFx0Y2xhc3MydHlwZVsgdG9TdHJpbmcuY2FsbCggb2JqICkgXSB8fCBcIm9iamVjdFwiIDpcblx0XHRcdHR5cGVvZiBvYmo7XG5cdH0sXG5cblx0Ly8gRXZhbHVhdGVzIGEgc2NyaXB0IGluIGEgZ2xvYmFsIGNvbnRleHRcblx0Z2xvYmFsRXZhbDogZnVuY3Rpb24oIGNvZGUgKSB7XG5cdFx0RE9NRXZhbCggY29kZSApO1xuXHR9LFxuXG5cdC8vIENvbnZlcnQgZGFzaGVkIHRvIGNhbWVsQ2FzZTsgdXNlZCBieSB0aGUgY3NzIGFuZCBkYXRhIG1vZHVsZXNcblx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHQvLyBNaWNyb3NvZnQgZm9yZ290IHRvIGh1bXAgdGhlaXIgdmVuZG9yIHByZWZpeCAoIzk1NzIpXG5cdGNhbWVsQ2FzZTogZnVuY3Rpb24oIHN0cmluZyApIHtcblx0XHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoIHJtc1ByZWZpeCwgXCJtcy1cIiApLnJlcGxhY2UoIHJkYXNoQWxwaGEsIGZjYW1lbENhc2UgKTtcblx0fSxcblxuXHRlYWNoOiBmdW5jdGlvbiggb2JqLCBjYWxsYmFjayApIHtcblx0XHR2YXIgbGVuZ3RoLCBpID0gMDtcblxuXHRcdGlmICggaXNBcnJheUxpa2UoIG9iaiApICkge1xuXHRcdFx0bGVuZ3RoID0gb2JqLmxlbmd0aDtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIG9iaiApIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjay5jYWxsKCBvYmpbIGkgXSwgaSwgb2JqWyBpIF0gKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gb2JqO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seVxuXHR0cmltOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRyZXR1cm4gdGV4dCA9PSBudWxsID9cblx0XHRcdFwiXCIgOlxuXHRcdFx0KCB0ZXh0ICsgXCJcIiApLnJlcGxhY2UoIHJ0cmltLCBcIlwiICk7XG5cdH0sXG5cblx0Ly8gcmVzdWx0cyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYWtlQXJyYXk6IGZ1bmN0aW9uKCBhcnIsIHJlc3VsdHMgKSB7XG5cdFx0dmFyIHJldCA9IHJlc3VsdHMgfHwgW107XG5cblx0XHRpZiAoIGFyciAhPSBudWxsICkge1xuXHRcdFx0aWYgKCBpc0FycmF5TGlrZSggT2JqZWN0KCBhcnIgKSApICkge1xuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIHJldCxcblx0XHRcdFx0XHR0eXBlb2YgYXJyID09PSBcInN0cmluZ1wiID9cblx0XHRcdFx0XHRbIGFyciBdIDogYXJyXG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmNhbGwoIHJldCwgYXJyICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldDtcblx0fSxcblxuXHRpbkFycmF5OiBmdW5jdGlvbiggZWxlbSwgYXJyLCBpICkge1xuXHRcdHJldHVybiBhcnIgPT0gbnVsbCA/IC0xIDogaW5kZXhPZi5jYWxsKCBhcnIsIGVsZW0sIGkgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRtZXJnZTogZnVuY3Rpb24oIGZpcnN0LCBzZWNvbmQgKSB7XG5cdFx0dmFyIGxlbiA9ICtzZWNvbmQubGVuZ3RoLFxuXHRcdFx0aiA9IDAsXG5cdFx0XHRpID0gZmlyc3QubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRmaXJzdFsgaSsrIF0gPSBzZWNvbmRbIGogXTtcblx0XHR9XG5cblx0XHRmaXJzdC5sZW5ndGggPSBpO1xuXG5cdFx0cmV0dXJuIGZpcnN0O1xuXHR9LFxuXG5cdGdyZXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGludmVydCApIHtcblx0XHR2YXIgY2FsbGJhY2tJbnZlcnNlLFxuXHRcdFx0bWF0Y2hlcyA9IFtdLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsZW5ndGggPSBlbGVtcy5sZW5ndGgsXG5cdFx0XHRjYWxsYmFja0V4cGVjdCA9ICFpbnZlcnQ7XG5cblx0XHQvLyBHbyB0aHJvdWdoIHRoZSBhcnJheSwgb25seSBzYXZpbmcgdGhlIGl0ZW1zXG5cdFx0Ly8gdGhhdCBwYXNzIHRoZSB2YWxpZGF0b3IgZnVuY3Rpb25cblx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdGNhbGxiYWNrSW52ZXJzZSA9ICFjYWxsYmFjayggZWxlbXNbIGkgXSwgaSApO1xuXHRcdFx0aWYgKCBjYWxsYmFja0ludmVyc2UgIT09IGNhbGxiYWNrRXhwZWN0ICkge1xuXHRcdFx0XHRtYXRjaGVzLnB1c2goIGVsZW1zWyBpIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbWF0Y2hlcztcblx0fSxcblxuXHQvLyBhcmcgaXMgZm9yIGludGVybmFsIHVzYWdlIG9ubHlcblx0bWFwOiBmdW5jdGlvbiggZWxlbXMsIGNhbGxiYWNrLCBhcmcgKSB7XG5cdFx0dmFyIGxlbmd0aCwgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdHJldCA9IFtdO1xuXG5cdFx0Ly8gR28gdGhyb3VnaCB0aGUgYXJyYXksIHRyYW5zbGF0aW5nIGVhY2ggb2YgdGhlIGl0ZW1zIHRvIHRoZWlyIG5ldyB2YWx1ZXNcblx0XHRpZiAoIGlzQXJyYXlMaWtlKCBlbGVtcyApICkge1xuXHRcdFx0bGVuZ3RoID0gZWxlbXMubGVuZ3RoO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhbHVlID0gY2FsbGJhY2soIGVsZW1zWyBpIF0sIGksIGFyZyApO1xuXG5cdFx0XHRcdGlmICggdmFsdWUgIT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXQucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gR28gdGhyb3VnaCBldmVyeSBrZXkgb24gdGhlIG9iamVjdCxcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yICggaSBpbiBlbGVtcyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmxhdHRlbiBhbnkgbmVzdGVkIGFycmF5c1xuXHRcdHJldHVybiBjb25jYXQuYXBwbHkoIFtdLCByZXQgKTtcblx0fSxcblxuXHQvLyBBIGdsb2JhbCBHVUlEIGNvdW50ZXIgZm9yIG9iamVjdHNcblx0Z3VpZDogMSxcblxuXHQvLyBCaW5kIGEgZnVuY3Rpb24gdG8gYSBjb250ZXh0LCBvcHRpb25hbGx5IHBhcnRpYWxseSBhcHBseWluZyBhbnlcblx0Ly8gYXJndW1lbnRzLlxuXHRwcm94eTogZnVuY3Rpb24oIGZuLCBjb250ZXh0ICkge1xuXHRcdHZhciB0bXAsIGFyZ3MsIHByb3h5O1xuXG5cdFx0aWYgKCB0eXBlb2YgY29udGV4dCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRtcCA9IGZuWyBjb250ZXh0IF07XG5cdFx0XHRjb250ZXh0ID0gZm47XG5cdFx0XHRmbiA9IHRtcDtcblx0XHR9XG5cblx0XHQvLyBRdWljayBjaGVjayB0byBkZXRlcm1pbmUgaWYgdGFyZ2V0IGlzIGNhbGxhYmxlLCBpbiB0aGUgc3BlY1xuXHRcdC8vIHRoaXMgdGhyb3dzIGEgVHlwZUVycm9yLCBidXQgd2Ugd2lsbCBqdXN0IHJldHVybiB1bmRlZmluZWQuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIGZuICkgKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIFNpbXVsYXRlZCBiaW5kXG5cdFx0YXJncyA9IHNsaWNlLmNhbGwoIGFyZ3VtZW50cywgMiApO1xuXHRcdHByb3h5ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gZm4uYXBwbHkoIGNvbnRleHQgfHwgdGhpcywgYXJncy5jb25jYXQoIHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApICkgKTtcblx0XHR9O1xuXG5cdFx0Ly8gU2V0IHRoZSBndWlkIG9mIHVuaXF1ZSBoYW5kbGVyIHRvIHRoZSBzYW1lIG9mIG9yaWdpbmFsIGhhbmRsZXIsIHNvIGl0IGNhbiBiZSByZW1vdmVkXG5cdFx0cHJveHkuZ3VpZCA9IGZuLmd1aWQgPSBmbi5ndWlkIHx8IGpRdWVyeS5ndWlkKys7XG5cblx0XHRyZXR1cm4gcHJveHk7XG5cdH0sXG5cblx0bm93OiBEYXRlLm5vdyxcblxuXHQvLyBqUXVlcnkuc3VwcG9ydCBpcyBub3QgdXNlZCBpbiBDb3JlIGJ1dCBvdGhlciBwcm9qZWN0cyBhdHRhY2ggdGhlaXJcblx0Ly8gcHJvcGVydGllcyB0byBpdCBzbyBpdCBuZWVkcyB0byBleGlzdC5cblx0c3VwcG9ydDogc3VwcG9ydFxufSApO1xuXG5pZiAoIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiApIHtcblx0alF1ZXJ5LmZuWyBTeW1ib2wuaXRlcmF0b3IgXSA9IGFyclsgU3ltYm9sLml0ZXJhdG9yIF07XG59XG5cbi8vIFBvcHVsYXRlIHRoZSBjbGFzczJ0eXBlIG1hcFxualF1ZXJ5LmVhY2goIFwiQm9vbGVhbiBOdW1iZXIgU3RyaW5nIEZ1bmN0aW9uIEFycmF5IERhdGUgUmVnRXhwIE9iamVjdCBFcnJvciBTeW1ib2xcIi5zcGxpdCggXCIgXCIgKSxcbmZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRjbGFzczJ0eXBlWyBcIltvYmplY3QgXCIgKyBuYW1lICsgXCJdXCIgXSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbn0gKTtcblxuZnVuY3Rpb24gaXNBcnJheUxpa2UoIG9iaiApIHtcblxuXHQvLyBTdXBwb3J0OiByZWFsIGlPUyA4LjIgb25seSAobm90IHJlcHJvZHVjaWJsZSBpbiBzaW11bGF0b3IpXG5cdC8vIGBpbmAgY2hlY2sgdXNlZCB0byBwcmV2ZW50IEpJVCBlcnJvciAoZ2gtMjE0NSlcblx0Ly8gaGFzT3duIGlzbid0IHVzZWQgaGVyZSBkdWUgdG8gZmFsc2UgbmVnYXRpdmVzXG5cdC8vIHJlZ2FyZGluZyBOb2RlbGlzdCBsZW5ndGggaW4gSUVcblx0dmFyIGxlbmd0aCA9ICEhb2JqICYmIFwibGVuZ3RoXCIgaW4gb2JqICYmIG9iai5sZW5ndGgsXG5cdFx0dHlwZSA9IGpRdWVyeS50eXBlKCBvYmogKTtcblxuXHRpZiAoIHR5cGUgPT09IFwiZnVuY3Rpb25cIiB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHJldHVybiB0eXBlID09PSBcImFycmF5XCIgfHwgbGVuZ3RoID09PSAwIHx8XG5cdFx0dHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIiAmJiBsZW5ndGggPiAwICYmICggbGVuZ3RoIC0gMSApIGluIG9iajtcbn1cbnZhciBTaXp6bGUgPVxuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2Mi4zLjNcbiAqIGh0dHBzOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcbiAqXG4gKiBEYXRlOiAyMDE2LTA4LTA4XG4gKi9cbihmdW5jdGlvbiggd2luZG93ICkge1xuXG52YXIgaSxcblx0c3VwcG9ydCxcblx0RXhwcixcblx0Z2V0VGV4dCxcblx0aXNYTUwsXG5cdHRva2VuaXplLFxuXHRjb21waWxlLFxuXHRzZWxlY3QsXG5cdG91dGVybW9zdENvbnRleHQsXG5cdHNvcnRJbnB1dCxcblx0aGFzRHVwbGljYXRlLFxuXG5cdC8vIExvY2FsIGRvY3VtZW50IHZhcnNcblx0c2V0RG9jdW1lbnQsXG5cdGRvY3VtZW50LFxuXHRkb2NFbGVtLFxuXHRkb2N1bWVudElzSFRNTCxcblx0cmJ1Z2d5UVNBLFxuXHRyYnVnZ3lNYXRjaGVzLFxuXHRtYXRjaGVzLFxuXHRjb250YWlucyxcblxuXHQvLyBJbnN0YW5jZS1zcGVjaWZpYyBkYXRhXG5cdGV4cGFuZG8gPSBcInNpenpsZVwiICsgMSAqIG5ldyBEYXRlKCksXG5cdHByZWZlcnJlZERvYyA9IHdpbmRvdy5kb2N1bWVudCxcblx0ZGlycnVucyA9IDAsXG5cdGRvbmUgPSAwLFxuXHRjbGFzc0NhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0dG9rZW5DYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdGNvbXBpbGVyQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHRzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHtcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gMDtcblx0fSxcblxuXHQvLyBJbnN0YW5jZSBtZXRob2RzXG5cdGhhc093biA9ICh7fSkuaGFzT3duUHJvcGVydHksXG5cdGFyciA9IFtdLFxuXHRwb3AgPSBhcnIucG9wLFxuXHRwdXNoX25hdGl2ZSA9IGFyci5wdXNoLFxuXHRwdXNoID0gYXJyLnB1c2gsXG5cdHNsaWNlID0gYXJyLnNsaWNlLFxuXHQvLyBVc2UgYSBzdHJpcHBlZC1kb3duIGluZGV4T2YgYXMgaXQncyBmYXN0ZXIgdGhhbiBuYXRpdmVcblx0Ly8gaHR0cHM6Ly9qc3BlcmYuY29tL3Rob3ItaW5kZXhvZi12cy1mb3IvNVxuXHRpbmRleE9mID0gZnVuY3Rpb24oIGxpc3QsIGVsZW0gKSB7XG5cdFx0dmFyIGkgPSAwLFxuXHRcdFx0bGVuID0gbGlzdC5sZW5ndGg7XG5cdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRpZiAoIGxpc3RbaV0gPT09IGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gLTE7XG5cdH0sXG5cblx0Ym9vbGVhbnMgPSBcImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkXCIsXG5cblx0Ly8gUmVndWxhciBleHByZXNzaW9uc1xuXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc2VsZWN0b3JzLyN3aGl0ZXNwYWNlXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvQ1NTMjEvc3luZGF0YS5odG1sI3ZhbHVlLWRlZi1pZGVudGlmaWVyXG5cdGlkZW50aWZpZXIgPSBcIig/OlxcXFxcXFxcLnxbXFxcXHctXXxbXlxcMC1cXFxceGEwXSkrXCIsXG5cblx0Ly8gQXR0cmlidXRlIHNlbGVjdG9yczogaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNhdHRyaWJ1dGUtc2VsZWN0b3JzXG5cdGF0dHJpYnV0ZXMgPSBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFwiICsgaWRlbnRpZmllciArIFwiKSg/OlwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gT3BlcmF0b3IgKGNhcHR1cmUgMilcblx0XHRcIiooWypeJHwhfl0/PSlcIiArIHdoaXRlc3BhY2UgK1xuXHRcdC8vIFwiQXR0cmlidXRlIHZhbHVlcyBtdXN0IGJlIENTUyBpZGVudGlmaWVycyBbY2FwdHVyZSA1XSBvciBzdHJpbmdzIFtjYXB0dXJlIDMgb3IgY2FwdHVyZSA0XVwiXG5cdFx0XCIqKD86JygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwifChcIiArIGlkZW50aWZpZXIgKyBcIikpfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKlxcXFxdXCIsXG5cblx0cHNldWRvcyA9IFwiOihcIiArIGlkZW50aWZpZXIgKyBcIikoPzpcXFxcKChcIiArXG5cdFx0Ly8gVG8gcmVkdWNlIHRoZSBudW1iZXIgb2Ygc2VsZWN0b3JzIG5lZWRpbmcgdG9rZW5pemUgaW4gdGhlIHByZUZpbHRlciwgcHJlZmVyIGFyZ3VtZW50czpcblx0XHQvLyAxLiBxdW90ZWQgKGNhcHR1cmUgMzsgY2FwdHVyZSA0IG9yIGNhcHR1cmUgNSlcblx0XHRcIignKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJ10pKiknfFxcXCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFxcXFwiXSkqKVxcXCIpfFwiICtcblx0XHQvLyAyLiBzaW1wbGUgKGNhcHR1cmUgNilcblx0XHRcIigoPzpcXFxcXFxcXC58W15cXFxcXFxcXCgpW1xcXFxdXXxcIiArIGF0dHJpYnV0ZXMgKyBcIikqKXxcIiArXG5cdFx0Ly8gMy4gYW55dGhpbmcgZWxzZSAoY2FwdHVyZSAyKVxuXHRcdFwiLipcIiArXG5cdFx0XCIpXFxcXCl8KVwiLFxuXG5cdC8vIExlYWRpbmcgYW5kIG5vbi1lc2NhcGVkIHRyYWlsaW5nIHdoaXRlc3BhY2UsIGNhcHR1cmluZyBzb21lIG5vbi13aGl0ZXNwYWNlIGNoYXJhY3RlcnMgcHJlY2VkaW5nIHRoZSBsYXR0ZXJcblx0cndoaXRlc3BhY2UgPSBuZXcgUmVnRXhwKCB3aGl0ZXNwYWNlICsgXCIrXCIsIFwiZ1wiICksXG5cdHJ0cmltID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIrfCgoPzpefFteXFxcXFxcXFxdKSg/OlxcXFxcXFxcLikqKVwiICsgd2hpdGVzcGFjZSArIFwiKyRcIiwgXCJnXCIgKSxcblxuXHRyY29tbWEgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiosXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblx0cmNvbWJpbmF0b3JzID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFs+K35dfFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgd2hpdGVzcGFjZSArIFwiKlwiICksXG5cblx0cmF0dHJpYnV0ZVF1b3RlcyA9IG5ldyBSZWdFeHAoIFwiPVwiICsgd2hpdGVzcGFjZSArIFwiKihbXlxcXFxdJ1xcXCJdKj8pXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXF1cIiwgXCJnXCIgKSxcblxuXHRycHNldWRvID0gbmV3IFJlZ0V4cCggcHNldWRvcyApLFxuXHRyaWRlbnRpZmllciA9IG5ldyBSZWdFeHAoIFwiXlwiICsgaWRlbnRpZmllciArIFwiJFwiICksXG5cblx0bWF0Y2hFeHByID0ge1xuXHRcdFwiSURcIjogbmV3IFJlZ0V4cCggXCJeIyhcIiArIGlkZW50aWZpZXIgKyBcIilcIiApLFxuXHRcdFwiQ0xBU1NcIjogbmV3IFJlZ0V4cCggXCJeXFxcXC4oXCIgKyBpZGVudGlmaWVyICsgXCIpXCIgKSxcblx0XHRcIlRBR1wiOiBuZXcgUmVnRXhwKCBcIl4oXCIgKyBpZGVudGlmaWVyICsgXCJ8WypdKVwiICksXG5cdFx0XCJBVFRSXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgYXR0cmlidXRlcyApLFxuXHRcdFwiUFNFVURPXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgcHNldWRvcyApLFxuXHRcdFwiQ0hJTERcIjogbmV3IFJlZ0V4cCggXCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXFxcKFwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooZXZlbnxvZGR8KChbKy1dfCkoXFxcXGQqKW58KVwiICsgd2hpdGVzcGFjZSArIFwiKig/OihbKy1dfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFx0XCIqKFxcXFxkKyl8KSlcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpXCIsIFwiaVwiICksXG5cdFx0XCJib29sXCI6IG5ldyBSZWdFeHAoIFwiXig/OlwiICsgYm9vbGVhbnMgKyBcIikkXCIsIFwiaVwiICksXG5cdFx0Ly8gRm9yIHVzZSBpbiBsaWJyYXJpZXMgaW1wbGVtZW50aW5nIC5pcygpXG5cdFx0Ly8gV2UgdXNlIHRoaXMgZm9yIFBPUyBtYXRjaGluZyBpbiBgc2VsZWN0YFxuXHRcdFwibmVlZHNDb250ZXh0XCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFxcXChcIiArXG5cdFx0XHR3aGl0ZXNwYWNlICsgXCIqKCg/Oi1cXFxcZCk/XFxcXGQqKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfCkoPz1bXi1dfCQpXCIsIFwiaVwiIClcblx0fSxcblxuXHRyaW5wdXRzID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxcblx0cmhlYWRlciA9IC9eaFxcZCQvaSxcblxuXHRybmF0aXZlID0gL15bXntdK1xce1xccypcXFtuYXRpdmUgXFx3LyxcblxuXHQvLyBFYXNpbHktcGFyc2VhYmxlL3JldHJpZXZhYmxlIElEIG9yIFRBRyBvciBDTEFTUyBzZWxlY3RvcnNcblx0cnF1aWNrRXhwciA9IC9eKD86IyhbXFx3LV0rKXwoXFx3Kyl8XFwuKFtcXHctXSspKSQvLFxuXG5cdHJzaWJsaW5nID0gL1srfl0vLFxuXG5cdC8vIENTUyBlc2NhcGVzXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL0NTUzIxL3N5bmRhdGEuaHRtbCNlc2NhcGVkLWNoYXJhY3RlcnNcblx0cnVuZXNjYXBlID0gbmV3IFJlZ0V4cCggXCJcXFxcXFxcXChbXFxcXGRhLWZdezEsNn1cIiArIHdoaXRlc3BhY2UgKyBcIj98KFwiICsgd2hpdGVzcGFjZSArIFwiKXwuKVwiLCBcImlnXCIgKSxcblx0ZnVuZXNjYXBlID0gZnVuY3Rpb24oIF8sIGVzY2FwZWQsIGVzY2FwZWRXaGl0ZXNwYWNlICkge1xuXHRcdHZhciBoaWdoID0gXCIweFwiICsgZXNjYXBlZCAtIDB4MTAwMDA7XG5cdFx0Ly8gTmFOIG1lYW5zIG5vbi1jb2RlcG9pbnRcblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94PDI0XG5cdFx0Ly8gV29ya2Fyb3VuZCBlcnJvbmVvdXMgbnVtZXJpYyBpbnRlcnByZXRhdGlvbiBvZiArXCIweFwiXG5cdFx0cmV0dXJuIGhpZ2ggIT09IGhpZ2ggfHwgZXNjYXBlZFdoaXRlc3BhY2UgP1xuXHRcdFx0ZXNjYXBlZCA6XG5cdFx0XHRoaWdoIDwgMCA/XG5cdFx0XHRcdC8vIEJNUCBjb2RlcG9pbnRcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCArIDB4MTAwMDAgKSA6XG5cdFx0XHRcdC8vIFN1cHBsZW1lbnRhbCBQbGFuZSBjb2RlcG9pbnQgKHN1cnJvZ2F0ZSBwYWlyKVxuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoID4+IDEwIHwgMHhEODAwLCBoaWdoICYgMHgzRkYgfCAweERDMDAgKTtcblx0fSxcblxuXHQvLyBDU1Mgc3RyaW5nL2lkZW50aWZpZXIgc2VyaWFsaXphdGlvblxuXHQvLyBodHRwczovL2RyYWZ0cy5jc3N3Zy5vcmcvY3Nzb20vI2NvbW1vbi1zZXJpYWxpemluZy1pZGlvbXNcblx0cmNzc2VzY2FwZSA9IC8oW1xcMC1cXHgxZlxceDdmXXxeLT9cXGQpfF4tJHxbXlxcMC1cXHgxZlxceDdmLVxcdUZGRkZcXHctXS9nLFxuXHRmY3NzZXNjYXBlID0gZnVuY3Rpb24oIGNoLCBhc0NvZGVQb2ludCApIHtcblx0XHRpZiAoIGFzQ29kZVBvaW50ICkge1xuXG5cdFx0XHQvLyBVKzAwMDAgTlVMTCBiZWNvbWVzIFUrRkZGRCBSRVBMQUNFTUVOVCBDSEFSQUNURVJcblx0XHRcdGlmICggY2ggPT09IFwiXFwwXCIgKSB7XG5cdFx0XHRcdHJldHVybiBcIlxcdUZGRkRcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udHJvbCBjaGFyYWN0ZXJzIGFuZCAoZGVwZW5kZW50IHVwb24gcG9zaXRpb24pIG51bWJlcnMgZ2V0IGVzY2FwZWQgYXMgY29kZSBwb2ludHNcblx0XHRcdHJldHVybiBjaC5zbGljZSggMCwgLTEgKSArIFwiXFxcXFwiICsgY2guY2hhckNvZGVBdCggY2gubGVuZ3RoIC0gMSApLnRvU3RyaW5nKCAxNiApICsgXCIgXCI7XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXIgcG90ZW50aWFsbHktc3BlY2lhbCBBU0NJSSBjaGFyYWN0ZXJzIGdldCBiYWNrc2xhc2gtZXNjYXBlZFxuXHRcdHJldHVybiBcIlxcXFxcIiArIGNoO1xuXHR9LFxuXG5cdC8vIFVzZWQgZm9yIGlmcmFtZXNcblx0Ly8gU2VlIHNldERvY3VtZW50KClcblx0Ly8gUmVtb3ZpbmcgdGhlIGZ1bmN0aW9uIHdyYXBwZXIgY2F1c2VzIGEgXCJQZXJtaXNzaW9uIERlbmllZFwiXG5cdC8vIGVycm9yIGluIElFXG5cdHVubG9hZEhhbmRsZXIgPSBmdW5jdGlvbigpIHtcblx0XHRzZXREb2N1bWVudCgpO1xuXHR9LFxuXG5cdGRpc2FibGVkQW5jZXN0b3IgPSBhZGRDb21iaW5hdG9yKFxuXHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IHRydWUgJiYgKFwiZm9ybVwiIGluIGVsZW0gfHwgXCJsYWJlbFwiIGluIGVsZW0pO1xuXHRcdH0sXG5cdFx0eyBkaXI6IFwicGFyZW50Tm9kZVwiLCBuZXh0OiBcImxlZ2VuZFwiIH1cblx0KTtcblxuLy8gT3B0aW1pemUgZm9yIHB1c2guYXBwbHkoIF8sIE5vZGVMaXN0IClcbnRyeSB7XG5cdHB1c2guYXBwbHkoXG5cdFx0KGFyciA9IHNsaWNlLmNhbGwoIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzICkpLFxuXHRcdHByZWZlcnJlZERvYy5jaGlsZE5vZGVzXG5cdCk7XG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8NC4wXG5cdC8vIERldGVjdCBzaWxlbnRseSBmYWlsaW5nIHB1c2guYXBwbHlcblx0YXJyWyBwcmVmZXJyZWREb2MuY2hpbGROb2Rlcy5sZW5ndGggXS5ub2RlVHlwZTtcbn0gY2F0Y2ggKCBlICkge1xuXHRwdXNoID0geyBhcHBseTogYXJyLmxlbmd0aCA/XG5cblx0XHQvLyBMZXZlcmFnZSBzbGljZSBpZiBwb3NzaWJsZVxuXHRcdGZ1bmN0aW9uKCB0YXJnZXQsIGVscyApIHtcblx0XHRcdHB1c2hfbmF0aXZlLmFwcGx5KCB0YXJnZXQsIHNsaWNlLmNhbGwoZWxzKSApO1xuXHRcdH0gOlxuXG5cdFx0Ly8gU3VwcG9ydDogSUU8OVxuXHRcdC8vIE90aGVyd2lzZSBhcHBlbmQgZGlyZWN0bHlcblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHR2YXIgaiA9IHRhcmdldC5sZW5ndGgsXG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0Ly8gQ2FuJ3QgdHJ1c3QgTm9kZUxpc3QubGVuZ3RoXG5cdFx0XHR3aGlsZSAoICh0YXJnZXRbaisrXSA9IGVsc1tpKytdKSApIHt9XG5cdFx0XHR0YXJnZXQubGVuZ3RoID0gaiAtIDE7XG5cdFx0fVxuXHR9O1xufVxuXG5mdW5jdGlvbiBTaXp6bGUoIHNlbGVjdG9yLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICkge1xuXHR2YXIgbSwgaSwgZWxlbSwgbmlkLCBtYXRjaCwgZ3JvdXBzLCBuZXdTZWxlY3Rvcixcblx0XHRuZXdDb250ZXh0ID0gY29udGV4dCAmJiBjb250ZXh0Lm93bmVyRG9jdW1lbnQsXG5cblx0XHQvLyBub2RlVHlwZSBkZWZhdWx0cyB0byA5LCBzaW5jZSBjb250ZXh0IGRlZmF1bHRzIHRvIGRvY3VtZW50XG5cdFx0bm9kZVR5cGUgPSBjb250ZXh0ID8gY29udGV4dC5ub2RlVHlwZSA6IDk7XG5cblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0Ly8gUmV0dXJuIGVhcmx5IGZyb20gY2FsbHMgd2l0aCBpbnZhbGlkIHNlbGVjdG9yIG9yIGNvbnRleHRcblx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgfHwgIXNlbGVjdG9yIHx8XG5cdFx0bm9kZVR5cGUgIT09IDEgJiYgbm9kZVR5cGUgIT09IDkgJiYgbm9kZVR5cGUgIT09IDExICkge1xuXG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvLyBUcnkgdG8gc2hvcnRjdXQgZmluZCBvcGVyYXRpb25zIChhcyBvcHBvc2VkIHRvIGZpbHRlcnMpIGluIEhUTUwgZG9jdW1lbnRzXG5cdGlmICggIXNlZWQgKSB7XG5cblx0XHRpZiAoICggY29udGV4dCA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogcHJlZmVycmVkRG9jICkgIT09IGRvY3VtZW50ICkge1xuXHRcdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0XHR9XG5cdFx0Y29udGV4dCA9IGNvbnRleHQgfHwgZG9jdW1lbnQ7XG5cblx0XHRpZiAoIGRvY3VtZW50SXNIVE1MICkge1xuXG5cdFx0XHQvLyBJZiB0aGUgc2VsZWN0b3IgaXMgc3VmZmljaWVudGx5IHNpbXBsZSwgdHJ5IHVzaW5nIGEgXCJnZXQqQnkqXCIgRE9NIG1ldGhvZFxuXHRcdFx0Ly8gKGV4Y2VwdGluZyBEb2N1bWVudEZyYWdtZW50IGNvbnRleHQsIHdoZXJlIHRoZSBtZXRob2RzIGRvbid0IGV4aXN0KVxuXHRcdFx0aWYgKCBub2RlVHlwZSAhPT0gMTEgJiYgKG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHQvLyBJRCBzZWxlY3RvclxuXHRcdFx0XHRpZiAoIChtID0gbWF0Y2hbMV0pICkge1xuXG5cdFx0XHRcdFx0Ly8gRG9jdW1lbnQgY29udGV4dFxuXHRcdFx0XHRcdGlmICggbm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApKSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0XHQvLyBUT0RPOiBpZGVudGlmeSB2ZXJzaW9uc1xuXHRcdFx0XHRcdFx0XHQvLyBnZXRFbGVtZW50QnlJZCBjYW4gbWF0Y2ggZWxlbWVudHMgYnkgbmFtZSBpbnN0ZWFkIG9mIElEXG5cdFx0XHRcdFx0XHRcdGlmICggZWxlbS5pZCA9PT0gbSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBFbGVtZW50IGNvbnRleHRcblx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0Ly8gVE9ETzogaWRlbnRpZnkgdmVyc2lvbnNcblx0XHRcdFx0XHRcdC8vIGdldEVsZW1lbnRCeUlkIGNhbiBtYXRjaCBlbGVtZW50cyBieSBuYW1lIGluc3RlYWQgb2YgSURcblx0XHRcdFx0XHRcdGlmICggbmV3Q29udGV4dCAmJiAoZWxlbSA9IG5ld0NvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIG0gKSkgJiZcblx0XHRcdFx0XHRcdFx0Y29udGFpbnMoIGNvbnRleHQsIGVsZW0gKSAmJlxuXHRcdFx0XHRcdFx0XHRlbGVtLmlkID09PSBtICkge1xuXG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHlwZSBzZWxlY3RvclxuXHRcdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFsyXSApIHtcblx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCBzZWxlY3RvciApICk7XG5cdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdFx0Ly8gQ2xhc3Mgc2VsZWN0b3Jcblx0XHRcdFx0fSBlbHNlIGlmICggKG0gPSBtYXRjaFszXSkgJiYgc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmXG5cdFx0XHRcdFx0Y29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICkge1xuXG5cdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCBtICkgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUYWtlIGFkdmFudGFnZSBvZiBxdWVyeVNlbGVjdG9yQWxsXG5cdFx0XHRpZiAoIHN1cHBvcnQucXNhICYmXG5cdFx0XHRcdCFjb21waWxlckNhY2hlWyBzZWxlY3RvciArIFwiIFwiIF0gJiZcblx0XHRcdFx0KCFyYnVnZ3lRU0EgfHwgIXJidWdneVFTQS50ZXN0KCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHRpZiAoIG5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0XHRcdG5ld1NlbGVjdG9yID0gc2VsZWN0b3I7XG5cblx0XHRcdFx0Ly8gcVNBIGxvb2tzIG91dHNpZGUgRWxlbWVudCBjb250ZXh0LCB3aGljaCBpcyBub3Qgd2hhdCB3ZSB3YW50XG5cdFx0XHRcdC8vIFRoYW5rcyB0byBBbmRyZXcgRHVwb250IGZvciB0aGlzIHdvcmthcm91bmQgdGVjaG5pcXVlXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OFxuXHRcdFx0XHQvLyBFeGNsdWRlIG9iamVjdCBlbGVtZW50c1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHRcdFx0XHQvLyBDYXB0dXJlIHRoZSBjb250ZXh0IElELCBzZXR0aW5nIGl0IGZpcnN0IGlmIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdGlmICggKG5pZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKCBcImlkXCIgKSkgKSB7XG5cdFx0XHRcdFx0XHRuaWQgPSBuaWQucmVwbGFjZSggcmNzc2VzY2FwZSwgZmNzc2VzY2FwZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb250ZXh0LnNldEF0dHJpYnV0ZSggXCJpZFwiLCAobmlkID0gZXhwYW5kbykgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBQcmVmaXggZXZlcnkgc2VsZWN0b3IgaW4gdGhlIGxpc3Rcblx0XHRcdFx0XHRncm91cHMgPSB0b2tlbml6ZSggc2VsZWN0b3IgKTtcblx0XHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGdyb3Vwc1tpXSA9IFwiI1wiICsgbmlkICsgXCIgXCIgKyB0b1NlbGVjdG9yKCBncm91cHNbaV0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bmV3U2VsZWN0b3IgPSBncm91cHMuam9pbiggXCIsXCIgKTtcblxuXHRcdFx0XHRcdC8vIEV4cGFuZCBjb250ZXh0IGZvciBzaWJsaW5nIHNlbGVjdG9yc1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSByc2libGluZy50ZXN0KCBzZWxlY3RvciApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fFxuXHRcdFx0XHRcdFx0Y29udGV4dDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggbmV3U2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRcdG5ld0NvbnRleHQucXVlcnlTZWxlY3RvckFsbCggbmV3U2VsZWN0b3IgKVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKCBxc2FFcnJvciApIHtcblx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0aWYgKCBuaWQgPT09IGV4cGFuZG8gKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRleHQucmVtb3ZlQXR0cmlidXRlKCBcImlkXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBBbGwgb3RoZXJzXG5cdHJldHVybiBzZWxlY3QoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBrZXktdmFsdWUgY2FjaGVzIG9mIGxpbWl0ZWQgc2l6ZVxuICogQHJldHVybnMge2Z1bmN0aW9uKHN0cmluZywgb2JqZWN0KX0gUmV0dXJucyB0aGUgT2JqZWN0IGRhdGEgYWZ0ZXIgc3RvcmluZyBpdCBvbiBpdHNlbGYgd2l0aFxuICpcdHByb3BlcnR5IG5hbWUgdGhlIChzcGFjZS1zdWZmaXhlZCkgc3RyaW5nIGFuZCAoaWYgdGhlIGNhY2hlIGlzIGxhcmdlciB0aGFuIEV4cHIuY2FjaGVMZW5ndGgpXG4gKlx0ZGVsZXRpbmcgdGhlIG9sZGVzdCBlbnRyeVxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWNoZSgpIHtcblx0dmFyIGtleXMgPSBbXTtcblxuXHRmdW5jdGlvbiBjYWNoZSgga2V5LCB2YWx1ZSApIHtcblx0XHQvLyBVc2UgKGtleSArIFwiIFwiKSB0byBhdm9pZCBjb2xsaXNpb24gd2l0aCBuYXRpdmUgcHJvdG90eXBlIHByb3BlcnRpZXMgKHNlZSBJc3N1ZSAjMTU3KVxuXHRcdGlmICgga2V5cy5wdXNoKCBrZXkgKyBcIiBcIiApID4gRXhwci5jYWNoZUxlbmd0aCApIHtcblx0XHRcdC8vIE9ubHkga2VlcCB0aGUgbW9zdCByZWNlbnQgZW50cmllc1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBlbGVtZW50IGFuZCByZXR1cm5zIGEgYm9vbGVhbiByZXN1bHRcbiAqL1xuZnVuY3Rpb24gYXNzZXJ0KCBmbiApIHtcblx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImZpZWxkc2V0XCIpO1xuXG5cdHRyeSB7XG5cdFx0cmV0dXJuICEhZm4oIGVsICk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0gZmluYWxseSB7XG5cdFx0Ly8gUmVtb3ZlIGZyb20gaXRzIHBhcmVudCBieSBkZWZhdWx0XG5cdFx0aWYgKCBlbC5wYXJlbnROb2RlICkge1xuXHRcdFx0ZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggZWwgKTtcblx0XHR9XG5cdFx0Ly8gcmVsZWFzZSBtZW1vcnkgaW4gSUVcblx0XHRlbCA9IG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSBzYW1lIGhhbmRsZXIgZm9yIGFsbCBvZiB0aGUgc3BlY2lmaWVkIGF0dHJzXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cnMgUGlwZS1zZXBhcmF0ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIFRoZSBtZXRob2QgdGhhdCB3aWxsIGJlIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gYWRkSGFuZGxlKCBhdHRycywgaGFuZGxlciApIHtcblx0dmFyIGFyciA9IGF0dHJzLnNwbGl0KFwifFwiKSxcblx0XHRpID0gYXJyLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRFeHByLmF0dHJIYW5kbGVbIGFycltpXSBdID0gaGFuZGxlcjtcblx0fVxufVxuXG4vKipcbiAqIENoZWNrcyBkb2N1bWVudCBvcmRlciBvZiB0d28gc2libGluZ3NcbiAqIEBwYXJhbSB7RWxlbWVudH0gYVxuICogQHBhcmFtIHtFbGVtZW50fSBiXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIGxlc3MgdGhhbiAwIGlmIGEgcHJlY2VkZXMgYiwgZ3JlYXRlciB0aGFuIDAgaWYgYSBmb2xsb3dzIGJcbiAqL1xuZnVuY3Rpb24gc2libGluZ0NoZWNrKCBhLCBiICkge1xuXHR2YXIgY3VyID0gYiAmJiBhLFxuXHRcdGRpZmYgPSBjdXIgJiYgYS5ub2RlVHlwZSA9PT0gMSAmJiBiLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRhLnNvdXJjZUluZGV4IC0gYi5zb3VyY2VJbmRleDtcblxuXHQvLyBVc2UgSUUgc291cmNlSW5kZXggaWYgYXZhaWxhYmxlIG9uIGJvdGggbm9kZXNcblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0Ly8gQ2hlY2sgaWYgYiBmb2xsb3dzIGFcblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIDplbmFibGVkLzpkaXNhYmxlZFxuICogQHBhcmFtIHtCb29sZWFufSBkaXNhYmxlZCB0cnVlIGZvciA6ZGlzYWJsZWQ7IGZhbHNlIGZvciA6ZW5hYmxlZFxuICovXG5mdW5jdGlvbiBjcmVhdGVEaXNhYmxlZFBzZXVkbyggZGlzYWJsZWQgKSB7XG5cblx0Ly8gS25vd24gOmRpc2FibGVkIGZhbHNlIHBvc2l0aXZlczogZmllbGRzZXRbZGlzYWJsZWRdID4gbGVnZW5kOm50aC1vZi10eXBlKG4rMikgOmNhbi1kaXNhYmxlXG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE9ubHkgY2VydGFpbiBlbGVtZW50cyBjYW4gbWF0Y2ggOmVuYWJsZWQgb3IgOmRpc2FibGVkXG5cdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc2NyaXB0aW5nLmh0bWwjc2VsZWN0b3ItZW5hYmxlZFxuXHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3NjcmlwdGluZy5odG1sI3NlbGVjdG9yLWRpc2FibGVkXG5cdFx0aWYgKCBcImZvcm1cIiBpbiBlbGVtICkge1xuXG5cdFx0XHQvLyBDaGVjayBmb3IgaW5oZXJpdGVkIGRpc2FibGVkbmVzcyBvbiByZWxldmFudCBub24tZGlzYWJsZWQgZWxlbWVudHM6XG5cdFx0XHQvLyAqIGxpc3RlZCBmb3JtLWFzc29jaWF0ZWQgZWxlbWVudHMgaW4gYSBkaXNhYmxlZCBmaWVsZHNldFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NhdGVnb3J5LWxpc3RlZFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NvbmNlcHQtZmUtZGlzYWJsZWRcblx0XHRcdC8vICogb3B0aW9uIGVsZW1lbnRzIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdC8vICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvZm9ybXMuaHRtbCNjb25jZXB0LW9wdGlvbi1kaXNhYmxlZFxuXHRcdFx0Ly8gQWxsIHN1Y2ggZWxlbWVudHMgaGF2ZSBhIFwiZm9ybVwiIHByb3BlcnR5LlxuXHRcdFx0aWYgKCBlbGVtLnBhcmVudE5vZGUgJiYgZWxlbS5kaXNhYmxlZCA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdFx0Ly8gT3B0aW9uIGVsZW1lbnRzIGRlZmVyIHRvIGEgcGFyZW50IG9wdGdyb3VwIGlmIHByZXNlbnRcblx0XHRcdFx0aWYgKCBcImxhYmVsXCIgaW4gZWxlbSApIHtcblx0XHRcdFx0XHRpZiAoIFwibGFiZWxcIiBpbiBlbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5wYXJlbnROb2RlLmRpc2FibGVkID09PSBkaXNhYmxlZDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDYgLSAxMVxuXHRcdFx0XHQvLyBVc2UgdGhlIGlzRGlzYWJsZWQgc2hvcnRjdXQgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGRpc2FibGVkIGZpZWxkc2V0IGFuY2VzdG9yc1xuXHRcdFx0XHRyZXR1cm4gZWxlbS5pc0Rpc2FibGVkID09PSBkaXNhYmxlZCB8fFxuXG5cdFx0XHRcdFx0Ly8gV2hlcmUgdGhlcmUgaXMgbm8gaXNEaXNhYmxlZCwgY2hlY2sgbWFudWFsbHlcblx0XHRcdFx0XHQvKiBqc2hpbnQgLVcwMTggKi9cblx0XHRcdFx0XHRlbGVtLmlzRGlzYWJsZWQgIT09ICFkaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0ZGlzYWJsZWRBbmNlc3RvciggZWxlbSApID09PSBkaXNhYmxlZDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXG5cdFx0Ly8gVHJ5IHRvIHdpbm5vdyBvdXQgZWxlbWVudHMgdGhhdCBjYW4ndCBiZSBkaXNhYmxlZCBiZWZvcmUgdHJ1c3RpbmcgdGhlIGRpc2FibGVkIHByb3BlcnR5LlxuXHRcdC8vIFNvbWUgdmljdGltcyBnZXQgY2F1Z2h0IGluIG91ciBuZXQgKGxhYmVsLCBsZWdlbmQsIG1lbnUsIHRyYWNrKSwgYnV0IGl0IHNob3VsZG4ndFxuXHRcdC8vIGV2ZW4gZXhpc3Qgb24gdGhlbSwgbGV0IGFsb25lIGhhdmUgYSBib29sZWFuIHZhbHVlLlxuXHRcdH0gZWxzZSBpZiAoIFwibGFiZWxcIiBpbiBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdH1cblxuXHRcdC8vIFJlbWFpbmluZyBlbGVtZW50cyBhcmUgbmVpdGhlciA6ZW5hYmxlZCBub3IgOmRpc2FibGVkXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgcG9zaXRpb25hbHNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oIGZuICkge1xuXHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBhcmd1bWVudCApIHtcblx0XHRhcmd1bWVudCA9ICthcmd1bWVudDtcblx0XHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0dmFyIGosXG5cdFx0XHRcdG1hdGNoSW5kZXhlcyA9IGZuKCBbXSwgc2VlZC5sZW5ndGgsIGFyZ3VtZW50ICksXG5cdFx0XHRcdGkgPSBtYXRjaEluZGV4ZXMubGVuZ3RoO1xuXG5cdFx0XHQvLyBNYXRjaCBlbGVtZW50cyBmb3VuZCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4ZXNcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoIHNlZWRbIChqID0gbWF0Y2hJbmRleGVzW2ldKSBdICkge1xuXHRcdFx0XHRcdHNlZWRbal0gPSAhKG1hdGNoZXNbal0gPSBzZWVkW2pdKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBub2RlIGZvciB2YWxpZGl0eSBhcyBhIFNpenpsZSBjb250ZXh0XG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0PX0gY29udGV4dFxuICogQHJldHVybnMge0VsZW1lbnR8T2JqZWN0fEJvb2xlYW59IFRoZSBpbnB1dCBub2RlIGlmIGFjY2VwdGFibGUsIG90aGVyd2lzZSBhIGZhbHN5IHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHRlc3RDb250ZXh0KCBjb250ZXh0ICkge1xuXHRyZXR1cm4gY29udGV4dCAmJiB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjb250ZXh0O1xufVxuXG4vLyBFeHBvc2Ugc3VwcG9ydCB2YXJzIGZvciBjb252ZW5pZW5jZVxuc3VwcG9ydCA9IFNpenpsZS5zdXBwb3J0ID0ge307XG5cbi8qKlxuICogRGV0ZWN0cyBYTUwgbm9kZXNcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IGVsZW0gQW4gZWxlbWVudCBvciBhIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZmYgZWxlbSBpcyBhIG5vbi1IVE1MIFhNTCBub2RlXG4gKi9cbmlzWE1MID0gU2l6emxlLmlzWE1MID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdC8vIGRvY3VtZW50RWxlbWVudCBpcyB2ZXJpZmllZCBmb3IgY2FzZXMgd2hlcmUgaXQgZG9lc24ndCB5ZXQgZXhpc3Rcblx0Ly8gKHN1Y2ggYXMgbG9hZGluZyBpZnJhbWVzIGluIElFIC0gIzQ4MzMpXG5cdHZhciBkb2N1bWVudEVsZW1lbnQgPSBlbGVtICYmIChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSkuZG9jdW1lbnRFbGVtZW50O1xuXHRyZXR1cm4gZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lICE9PSBcIkhUTUxcIiA6IGZhbHNlO1xufTtcblxuLyoqXG4gKiBTZXRzIGRvY3VtZW50LXJlbGF0ZWQgdmFyaWFibGVzIG9uY2UgYmFzZWQgb24gdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IFtkb2NdIEFuIGVsZW1lbnQgb3IgZG9jdW1lbnQgb2JqZWN0IHRvIHVzZSB0byBzZXQgdGhlIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKi9cbnNldERvY3VtZW50ID0gU2l6emxlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oIG5vZGUgKSB7XG5cdHZhciBoYXNDb21wYXJlLCBzdWJXaW5kb3csXG5cdFx0ZG9jID0gbm9kZSA/IG5vZGUub3duZXJEb2N1bWVudCB8fCBub2RlIDogcHJlZmVycmVkRG9jO1xuXG5cdC8vIFJldHVybiBlYXJseSBpZiBkb2MgaXMgaW52YWxpZCBvciBhbHJlYWR5IHNlbGVjdGVkXG5cdGlmICggZG9jID09PSBkb2N1bWVudCB8fCBkb2Mubm9kZVR5cGUgIT09IDkgfHwgIWRvYy5kb2N1bWVudEVsZW1lbnQgKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50O1xuXHR9XG5cblx0Ly8gVXBkYXRlIGdsb2JhbCB2YXJpYWJsZXNcblx0ZG9jdW1lbnQgPSBkb2M7XG5cdGRvY0VsZW0gPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdGRvY3VtZW50SXNIVE1MID0gIWlzWE1MKCBkb2N1bWVudCApO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDktMTEsIEVkZ2Vcblx0Ly8gQWNjZXNzaW5nIGlmcmFtZSBkb2N1bWVudHMgYWZ0ZXIgdW5sb2FkIHRocm93cyBcInBlcm1pc3Npb24gZGVuaWVkXCIgZXJyb3JzIChqUXVlcnkgIzEzOTM2KVxuXHRpZiAoIHByZWZlcnJlZERvYyAhPT0gZG9jdW1lbnQgJiZcblx0XHQoc3ViV2luZG93ID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcpICYmIHN1YldpbmRvdy50b3AgIT09IHN1YldpbmRvdyApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDExLCBFZGdlXG5cdFx0aWYgKCBzdWJXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lciApIHtcblx0XHRcdHN1YldpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcInVubG9hZFwiLCB1bmxvYWRIYW5kbGVyLCBmYWxzZSApO1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgOSAtIDEwIG9ubHlcblx0XHR9IGVsc2UgaWYgKCBzdWJXaW5kb3cuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRzdWJXaW5kb3cuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgdW5sb2FkSGFuZGxlciApO1xuXHRcdH1cblx0fVxuXG5cdC8qIEF0dHJpYnV0ZXNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIFN1cHBvcnQ6IElFPDhcblx0Ly8gVmVyaWZ5IHRoYXQgZ2V0QXR0cmlidXRlIHJlYWxseSByZXR1cm5zIGF0dHJpYnV0ZXMgYW5kIG5vdCBwcm9wZXJ0aWVzXG5cdC8vIChleGNlcHRpbmcgSUU4IGJvb2xlYW5zKVxuXHRzdXBwb3J0LmF0dHJpYnV0ZXMgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmNsYXNzTmFtZSA9IFwiaVwiO1xuXHRcdHJldHVybiAhZWwuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpO1xuXHR9KTtcblxuXHQvKiBnZXRFbGVtZW50KHMpQnkqXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBDaGVjayBpZiBnZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikgcmV0dXJucyBvbmx5IGVsZW1lbnRzXG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVDb21tZW50KFwiXCIpICk7XG5cdFx0cmV0dXJuICFlbC5nZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBTdXBwb3J0OiBJRTw5XG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApO1xuXG5cdC8vIFN1cHBvcnQ6IElFPDEwXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRCeUlkIHJldHVybnMgZWxlbWVudHMgYnkgbmFtZVxuXHQvLyBUaGUgYnJva2VuIGdldEVsZW1lbnRCeUlkIG1ldGhvZHMgZG9uJ3QgcGljayB1cCBwcm9ncmFtbWF0aWNhbGx5LXNldCBuYW1lcyxcblx0Ly8gc28gdXNlIGEgcm91bmRhYm91dCBnZXRFbGVtZW50c0J5TmFtZSB0ZXN0XG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pZCA9IGV4cGFuZG87XG5cdFx0cmV0dXJuICFkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoIGV4cGFuZG8gKS5sZW5ndGg7XG5cdH0pO1xuXG5cdC8vIElEIGZpbHRlciBhbmQgZmluZFxuXHRpZiAoIHN1cHBvcnQuZ2V0QnlJZCApIHtcblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmdldEF0dHJpYnV0ZShcImlkXCIpID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cdFx0XHRcdHJldHVybiBlbGVtID8gWyBlbGVtIF0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSAgZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBub2RlID0gdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlTm9kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuXHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRyZXR1cm4gbm9kZSAmJiBub2RlLnZhbHVlID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA2IC0gNyBvbmx5XG5cdFx0Ly8gZ2V0RWxlbWVudEJ5SWQgaXMgbm90IHJlbGlhYmxlIGFzIGEgZmluZCBzaG9ydGN1dFxuXHRcdEV4cHIuZmluZFtcIklEXCJdID0gZnVuY3Rpb24oIGlkLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50QnlJZCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdFx0dmFyIG5vZGUsIGksIGVsZW1zLFxuXHRcdFx0XHRcdGVsZW0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBpZCApO1xuXG5cdFx0XHRcdGlmICggZWxlbSApIHtcblxuXHRcdFx0XHRcdC8vIFZlcmlmeSB0aGUgaWQgYXR0cmlidXRlXG5cdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdGlmICggbm9kZSAmJiBub2RlLnZhbHVlID09PSBpZCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBbIGVsZW0gXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBGYWxsIGJhY2sgb24gZ2V0RWxlbWVudHNCeU5hbWVcblx0XHRcdFx0XHRlbGVtcyA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeU5hbWUoIGlkICk7XG5cdFx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1zW2krK10pICkge1xuXHRcdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdFx0aWYgKCBub2RlICYmIG5vZGUudmFsdWUgPT09IGlkICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gWyBlbGVtIF07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvLyBUYWdcblx0RXhwci5maW5kW1wiVEFHXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/XG5cdFx0ZnVuY3Rpb24oIHRhZywgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRG9jdW1lbnRGcmFnbWVudCBub2RlcyBkb24ndCBoYXZlIGdFQlROXG5cdFx0XHR9IGVsc2UgaWYgKCBzdXBwb3J0LnFzYSApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCggdGFnICk7XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdHRtcCA9IFtdLFxuXHRcdFx0XHRpID0gMCxcblx0XHRcdFx0Ly8gQnkgaGFwcHkgY29pbmNpZGVuY2UsIGEgKGJyb2tlbikgZ0VCVE4gYXBwZWFycyBvbiBEb2N1bWVudEZyYWdtZW50IG5vZGVzIHRvb1xuXHRcdFx0XHRyZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnICk7XG5cblx0XHRcdC8vIEZpbHRlciBvdXQgcG9zc2libGUgY29tbWVudHNcblx0XHRcdGlmICggdGFnID09PSBcIipcIiApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRcdFx0dG1wLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdG1wO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0fTtcblxuXHQvLyBDbGFzc1xuXHRFeHByLmZpbmRbXCJDTEFTU1wiXSA9IHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBmdW5jdGlvbiggY2xhc3NOYW1lLCBjb250ZXh0ICkge1xuXHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIGNsYXNzTmFtZSApO1xuXHRcdH1cblx0fTtcblxuXHQvKiBRU0EvbWF0Y2hlc1NlbGVjdG9yXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBRU0EgYW5kIG1hdGNoZXNTZWxlY3RvciBzdXBwb3J0XG5cblx0Ly8gbWF0Y2hlc1NlbGVjdG9yKDphY3RpdmUpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChJRTkvT3BlcmEgMTEuNSlcblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdC8vIHFTYSg6Zm9jdXMpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChDaHJvbWUgMjEpXG5cdC8vIFdlIGFsbG93IHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBJRTgvOSB0aGF0IHRocm93cyBhbiBlcnJvclxuXHQvLyB3aGVuZXZlciBgZG9jdW1lbnQuYWN0aXZlRWxlbWVudGAgaXMgYWNjZXNzZWQgb24gYW4gaWZyYW1lXG5cdC8vIFNvLCB3ZSBhbGxvdyA6Zm9jdXMgdG8gcGFzcyB0aHJvdWdoIFFTQSBhbGwgdGhlIHRpbWUgdG8gYXZvaWQgdGhlIElFIGVycm9yXG5cdC8vIFNlZSBodHRwczovL2J1Z3MuanF1ZXJ5LmNvbS90aWNrZXQvMTMzNzhcblx0cmJ1Z2d5UVNBID0gW107XG5cblx0aWYgKCAoc3VwcG9ydC5xc2EgPSBybmF0aXZlLnRlc3QoIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwgKSkgKSB7XG5cdFx0Ly8gQnVpbGQgUVNBIHJlZ2V4XG5cdFx0Ly8gUmVnZXggc3RyYXRlZ3kgYWRvcHRlZCBmcm9tIERpZWdvIFBlcmluaVxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBTZWxlY3QgaXMgc2V0IHRvIGVtcHR5IHN0cmluZyBvbiBwdXJwb3NlXG5cdFx0XHQvLyBUaGlzIGlzIHRvIHRlc3QgSUUncyB0cmVhdG1lbnQgb2Ygbm90IGV4cGxpY2l0bHlcblx0XHRcdC8vIHNldHRpbmcgYSBib29sZWFuIGNvbnRlbnQgYXR0cmlidXRlLFxuXHRcdFx0Ly8gc2luY2UgaXRzIHByZXNlbmNlIHNob3VsZCBiZSBlbm91Z2hcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjM1OVxuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pbm5lckhUTUwgPSBcIjxhIGlkPSdcIiArIGV4cGFuZG8gKyBcIic+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGlkPSdcIiArIGV4cGFuZG8gKyBcIi1cXHJcXFxcJyBtc2FsbG93Y2FwdHVyZT0nJz5cIiArXG5cdFx0XHRcdFwiPG9wdGlvbiBzZWxlY3RlZD0nJz48L29wdGlvbj48L3NlbGVjdD5cIjtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4LCBPcGVyYSAxMS0xMi4xNlxuXHRcdFx0Ly8gTm90aGluZyBzaG91bGQgYmUgc2VsZWN0ZWQgd2hlbiBlbXB0eSBzdHJpbmdzIGZvbGxvdyBePSBvciAkPSBvciAqPVxuXHRcdFx0Ly8gVGhlIHRlc3QgYXR0cmlidXRlIG11c3QgYmUgdW5rbm93biBpbiBPcGVyYSBidXQgXCJzYWZlXCIgZm9yIFdpblJUXG5cdFx0XHQvLyBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2hoNDY1Mzg4LmFzcHgjYXR0cmlidXRlX3NlY3Rpb25cblx0XHRcdGlmICggZWwucXVlcnlTZWxlY3RvckFsbChcIlttc2FsbG93Y2FwdHVyZV49JyddXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiWypeJF09XCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86Jyd8XFxcIlxcXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4XG5cdFx0XHQvLyBCb29sZWFuIGF0dHJpYnV0ZXMgYW5kIFwidmFsdWVcIiBhcmUgbm90IHRyZWF0ZWQgY29ycmVjdGx5XG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW3NlbGVjdGVkXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86dmFsdWV8XCIgKyBib29sZWFucyArIFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IENocm9tZTwyOSwgQW5kcm9pZDw0LjQsIFNhZmFyaTw3LjArLCBpT1M8Ny4wKywgUGhhbnRvbUpTPDEuOS44K1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbCggXCJbaWR+PVwiICsgZXhwYW5kbyArIFwiLV1cIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCJ+PVwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gV2Via2l0L09wZXJhIC0gOmNoZWNrZWQgc2hvdWxkIHJldHVybiBzZWxlY3RlZCBvcHRpb24gZWxlbWVudHNcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMTEvUkVDLWNzczMtc2VsZWN0b3JzLTIwMTEwOTI5LyNjaGVja2VkXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbChcIjpjaGVja2VkXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCI6Y2hlY2tlZFwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogU2FmYXJpIDgrLCBpT1MgOCtcblx0XHRcdC8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzY4NTFcblx0XHRcdC8vIEluLXBhZ2UgYHNlbGVjdG9yI2lkIHNpYmxpbmctY29tYmluYXRvciBzZWxlY3RvcmAgZmFpbHNcblx0XHRcdGlmICggIWVsLnF1ZXJ5U2VsZWN0b3JBbGwoIFwiYSNcIiArIGV4cGFuZG8gKyBcIisqXCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKFwiLiMuK1srfl1cIik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdFx0ZWwuaW5uZXJIVE1MID0gXCI8YSBocmVmPScnIGRpc2FibGVkPSdkaXNhYmxlZCc+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGRpc2FibGVkPSdkaXNhYmxlZCc+PG9wdGlvbi8+PC9zZWxlY3Q+XCI7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IFdpbmRvd3MgOCBOYXRpdmUgQXBwc1xuXHRcdFx0Ly8gVGhlIHR5cGUgYW5kIG5hbWUgYXR0cmlidXRlcyBhcmUgcmVzdHJpY3RlZCBkdXJpbmcgLmlubmVySFRNTCBhc3NpZ25tZW50XG5cdFx0XHR2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG5cdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwidHlwZVwiLCBcImhpZGRlblwiICk7XG5cdFx0XHRlbC5hcHBlbmRDaGlsZCggaW5wdXQgKS5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcIkRcIiApO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRThcblx0XHRcdC8vIEVuZm9yY2UgY2FzZS1zZW5zaXRpdml0eSBvZiBuYW1lIGF0dHJpYnV0ZVxuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW25hbWU9ZF1cIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCJuYW1lXCIgKyB3aGl0ZXNwYWNlICsgXCIqWypeJHwhfl0/PVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZGIDMuNSAtIDplbmFibGVkLzpkaXNhYmxlZCBhbmQgaGlkZGVuIGVsZW1lbnRzIChoaWRkZW4gZWxlbWVudHMgYXJlIHN0aWxsIGVuYWJsZWQpXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiOmVuYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOS0xMStcblx0XHRcdC8vIElFJ3MgOmRpc2FibGVkIHNlbGVjdG9yIGRvZXMgbm90IHBpY2sgdXAgdGhlIGNoaWxkcmVuIG9mIGRpc2FibGVkIGZpZWxkc2V0c1xuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZGlzYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9wZXJhIDEwLTExIGRvZXMgbm90IHRocm93IG9uIHBvc3QtY29tbWEgaW52YWxpZCBwc2V1ZG9zXG5cdFx0XHRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiKiw6eFwiKTtcblx0XHRcdHJidWdneVFTQS5wdXNoKFwiLC4qOlwiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmICggKHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yID0gcm5hdGl2ZS50ZXN0KCAobWF0Y2hlcyA9IGRvY0VsZW0ubWF0Y2hlcyB8fFxuXHRcdGRvY0VsZW0ud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0ZG9jRWxlbS5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm9NYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1zTWF0Y2hlc1NlbGVjdG9yKSApKSApIHtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBDaGVjayB0byBzZWUgaWYgaXQncyBwb3NzaWJsZSB0byBkbyBtYXRjaGVzU2VsZWN0b3Jcblx0XHRcdC8vIG9uIGEgZGlzY29ubmVjdGVkIG5vZGUgKElFIDkpXG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBlbCwgXCIqXCIgKTtcblxuXHRcdFx0Ly8gVGhpcyBzaG91bGQgZmFpbCB3aXRoIGFuIGV4Y2VwdGlvblxuXHRcdFx0Ly8gR2Vja28gZG9lcyBub3QgZXJyb3IsIHJldHVybnMgZmFsc2UgaW5zdGVhZFxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBlbCwgXCJbcyE9JyddOnhcIiApO1xuXHRcdFx0cmJ1Z2d5TWF0Y2hlcy5wdXNoKCBcIiE9XCIsIHBzZXVkb3MgKTtcblx0XHR9KTtcblx0fVxuXG5cdHJidWdneVFTQSA9IHJidWdneVFTQS5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5UVNBLmpvaW4oXCJ8XCIpICk7XG5cdHJidWdneU1hdGNoZXMgPSByYnVnZ3lNYXRjaGVzLmxlbmd0aCAmJiBuZXcgUmVnRXhwKCByYnVnZ3lNYXRjaGVzLmpvaW4oXCJ8XCIpICk7XG5cblx0LyogQ29udGFpbnNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXHRoYXNDb21wYXJlID0gcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICk7XG5cblx0Ly8gRWxlbWVudCBjb250YWlucyBhbm90aGVyXG5cdC8vIFB1cnBvc2VmdWxseSBzZWxmLWV4Y2x1c2l2ZVxuXHQvLyBBcyBpbiwgYW4gZWxlbWVudCBkb2VzIG5vdCBjb250YWluIGl0c2VsZlxuXHRjb250YWlucyA9IGhhc0NvbXBhcmUgfHwgcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbnRhaW5zICkgP1xuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0dmFyIGFkb3duID0gYS5ub2RlVHlwZSA9PT0gOSA/IGEuZG9jdW1lbnRFbGVtZW50IDogYSxcblx0XHRcdFx0YnVwID0gYiAmJiBiLnBhcmVudE5vZGU7XG5cdFx0XHRyZXR1cm4gYSA9PT0gYnVwIHx8ICEhKCBidXAgJiYgYnVwLm5vZGVUeXBlID09PSAxICYmIChcblx0XHRcdFx0YWRvd24uY29udGFpbnMgP1xuXHRcdFx0XHRcdGFkb3duLmNvbnRhaW5zKCBidXAgKSA6XG5cdFx0XHRcdFx0YS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBidXAgKSAmIDE2XG5cdFx0XHQpKTtcblx0XHR9IDpcblx0XHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHRcdGlmICggYiApIHtcblx0XHRcdFx0d2hpbGUgKCAoYiA9IGIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBiID09PSBhICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcblxuXHQvKiBTb3J0aW5nXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBEb2N1bWVudCBvcmRlciBzb3J0aW5nXG5cdHNvcnRPcmRlciA9IGhhc0NvbXBhcmUgP1xuXHRmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdC8vIEZsYWcgZm9yIGR1cGxpY2F0ZSByZW1vdmFsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdC8vIFNvcnQgb24gbWV0aG9kIGV4aXN0ZW5jZSBpZiBvbmx5IG9uZSBpbnB1dCBoYXMgY29tcGFyZURvY3VtZW50UG9zaXRpb25cblx0XHR2YXIgY29tcGFyZSA9ICFhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uIC0gIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247XG5cdFx0aWYgKCBjb21wYXJlICkge1xuXHRcdFx0cmV0dXJuIGNvbXBhcmU7XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsY3VsYXRlIHBvc2l0aW9uIGlmIGJvdGggaW5wdXRzIGJlbG9uZyB0byB0aGUgc2FtZSBkb2N1bWVudFxuXHRcdGNvbXBhcmUgPSAoIGEub3duZXJEb2N1bWVudCB8fCBhICkgPT09ICggYi5vd25lckRvY3VtZW50IHx8IGIgKSA/XG5cdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBiICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugd2Uga25vdyB0aGV5IGFyZSBkaXNjb25uZWN0ZWRcblx0XHRcdDE7XG5cblx0XHQvLyBEaXNjb25uZWN0ZWQgbm9kZXNcblx0XHRpZiAoIGNvbXBhcmUgJiAxIHx8XG5cdFx0XHQoIXN1cHBvcnQuc29ydERldGFjaGVkICYmIGIuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGEgKSA9PT0gY29tcGFyZSkgKSB7XG5cblx0XHRcdC8vIENob29zZSB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IGlzIHJlbGF0ZWQgdG8gb3VyIHByZWZlcnJlZCBkb2N1bWVudFxuXHRcdFx0aWYgKCBhID09PSBkb2N1bWVudCB8fCBhLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGEpICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGIgPT09IGRvY3VtZW50IHx8IGIub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYikgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWludGFpbiBvcmlnaW5hbCBvcmRlclxuXHRcdFx0cmV0dXJuIHNvcnRJbnB1dCA/XG5cdFx0XHRcdCggaW5kZXhPZiggc29ydElucHV0LCBhICkgLSBpbmRleE9mKCBzb3J0SW5wdXQsIGIgKSApIDpcblx0XHRcdFx0MDtcblx0XHR9XG5cblx0XHRyZXR1cm4gY29tcGFyZSAmIDQgPyAtMSA6IDE7XG5cdH0gOlxuXHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHQvLyBFeGl0IGVhcmx5IGlmIHRoZSBub2RlcyBhcmUgaWRlbnRpY2FsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHZhciBjdXIsXG5cdFx0XHRpID0gMCxcblx0XHRcdGF1cCA9IGEucGFyZW50Tm9kZSxcblx0XHRcdGJ1cCA9IGIucGFyZW50Tm9kZSxcblx0XHRcdGFwID0gWyBhIF0sXG5cdFx0XHRicCA9IFsgYiBdO1xuXG5cdFx0Ly8gUGFyZW50bGVzcyBub2RlcyBhcmUgZWl0aGVyIGRvY3VtZW50cyBvciBkaXNjb25uZWN0ZWRcblx0XHRpZiAoICFhdXAgfHwgIWJ1cCApIHtcblx0XHRcdHJldHVybiBhID09PSBkb2N1bWVudCA/IC0xIDpcblx0XHRcdFx0YiA9PT0gZG9jdW1lbnQgPyAxIDpcblx0XHRcdFx0YXVwID8gLTEgOlxuXHRcdFx0XHRidXAgPyAxIDpcblx0XHRcdFx0c29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0Ly8gSWYgdGhlIG5vZGVzIGFyZSBzaWJsaW5ncywgd2UgY2FuIGRvIGEgcXVpY2sgY2hlY2tcblx0XHR9IGVsc2UgaWYgKCBhdXAgPT09IGJ1cCApIHtcblx0XHRcdHJldHVybiBzaWJsaW5nQ2hlY2soIGEsIGIgKTtcblx0XHR9XG5cblx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCBmdWxsIGxpc3RzIG9mIHRoZWlyIGFuY2VzdG9ycyBmb3IgY29tcGFyaXNvblxuXHRcdGN1ciA9IGE7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YXAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXHRcdGN1ciA9IGI7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YnAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXG5cdFx0Ly8gV2FsayBkb3duIHRoZSB0cmVlIGxvb2tpbmcgZm9yIGEgZGlzY3JlcGFuY3lcblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHQvLyBEbyBhIHNpYmxpbmcgY2hlY2sgaWYgdGhlIG5vZGVzIGhhdmUgYSBjb21tb24gYW5jZXN0b3Jcblx0XHRcdHNpYmxpbmdDaGVjayggYXBbaV0sIGJwW2ldICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugbm9kZXMgaW4gb3VyIGRvY3VtZW50IHNvcnQgZmlyc3Rcblx0XHRcdGFwW2ldID09PSBwcmVmZXJyZWREb2MgPyAtMSA6XG5cdFx0XHRicFtpXSA9PT0gcHJlZmVycmVkRG9jID8gMSA6XG5cdFx0XHQwO1xuXHR9O1xuXG5cdHJldHVybiBkb2N1bWVudDtcbn07XG5cblNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1lbnRzICkge1xuXHRyZXR1cm4gU2l6emxlKCBleHByLCBudWxsLCBudWxsLCBlbGVtZW50cyApO1xufTtcblxuU2l6emxlLm1hdGNoZXNTZWxlY3RvciA9IGZ1bmN0aW9uKCBlbGVtLCBleHByICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHQvLyBNYWtlIHN1cmUgdGhhdCBhdHRyaWJ1dGUgc2VsZWN0b3JzIGFyZSBxdW90ZWRcblx0ZXhwciA9IGV4cHIucmVwbGFjZSggcmF0dHJpYnV0ZVF1b3RlcywgXCI9JyQxJ11cIiApO1xuXG5cdGlmICggc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgJiYgZG9jdW1lbnRJc0hUTUwgJiZcblx0XHQhY29tcGlsZXJDYWNoZVsgZXhwciArIFwiIFwiIF0gJiZcblx0XHQoICFyYnVnZ3lNYXRjaGVzIHx8ICFyYnVnZ3lNYXRjaGVzLnRlc3QoIGV4cHIgKSApICYmXG5cdFx0KCAhcmJ1Z2d5UVNBICAgICB8fCAhcmJ1Z2d5UVNBLnRlc3QoIGV4cHIgKSApICkge1xuXG5cdFx0dHJ5IHtcblx0XHRcdHZhciByZXQgPSBtYXRjaGVzLmNhbGwoIGVsZW0sIGV4cHIgKTtcblxuXHRcdFx0Ly8gSUUgOSdzIG1hdGNoZXNTZWxlY3RvciByZXR1cm5zIGZhbHNlIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdFx0aWYgKCByZXQgfHwgc3VwcG9ydC5kaXNjb25uZWN0ZWRNYXRjaCB8fFxuXHRcdFx0XHRcdC8vIEFzIHdlbGwsIGRpc2Nvbm5lY3RlZCBub2RlcyBhcmUgc2FpZCB0byBiZSBpbiBhIGRvY3VtZW50XG5cdFx0XHRcdFx0Ly8gZnJhZ21lbnQgaW4gSUUgOVxuXHRcdFx0XHRcdGVsZW0uZG9jdW1lbnQgJiYgZWxlbS5kb2N1bWVudC5ub2RlVHlwZSAhPT0gMTEgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge31cblx0fVxuXG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIGRvY3VtZW50LCBudWxsLCBbIGVsZW0gXSApLmxlbmd0aCA+IDA7XG59O1xuXG5TaXp6bGUuY29udGFpbnMgPSBmdW5jdGlvbiggY29udGV4dCwgZWxlbSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgfHwgY29udGV4dCApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHR9XG5cdHJldHVybiBjb250YWlucyggY29udGV4dCwgZWxlbSApO1xufTtcblxuU2l6emxlLmF0dHIgPSBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHR9XG5cblx0dmFyIGZuID0gRXhwci5hdHRySGFuZGxlWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSxcblx0XHQvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IE9iamVjdC5wcm90b3R5cGUgcHJvcGVydGllcyAoalF1ZXJ5ICMxMzgwNylcblx0XHR2YWwgPSBmbiAmJiBoYXNPd24uY2FsbCggRXhwci5hdHRySGFuZGxlLCBuYW1lLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRmbiggZWxlbSwgbmFtZSwgIWRvY3VtZW50SXNIVE1MICkgOlxuXHRcdFx0dW5kZWZpbmVkO1xuXG5cdHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/XG5cdFx0dmFsIDpcblx0XHRzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWRvY3VtZW50SXNIVE1MID9cblx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICkgOlxuXHRcdFx0KHZhbCA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShuYW1lKSkgJiYgdmFsLnNwZWNpZmllZCA/XG5cdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG59O1xuXG5TaXp6bGUuZXNjYXBlID0gZnVuY3Rpb24oIHNlbCApIHtcblx0cmV0dXJuIChzZWwgKyBcIlwiKS5yZXBsYWNlKCByY3NzZXNjYXBlLCBmY3NzZXNjYXBlICk7XG59O1xuXG5TaXp6bGUuZXJyb3IgPSBmdW5jdGlvbiggbXNnICkge1xuXHR0aHJvdyBuZXcgRXJyb3IoIFwiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogXCIgKyBtc2cgKTtcbn07XG5cbi8qKlxuICogRG9jdW1lbnQgc29ydGluZyBhbmQgcmVtb3ZpbmcgZHVwbGljYXRlc1xuICogQHBhcmFtIHtBcnJheUxpa2V9IHJlc3VsdHNcbiAqL1xuU2l6emxlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbiggcmVzdWx0cyApIHtcblx0dmFyIGVsZW0sXG5cdFx0ZHVwbGljYXRlcyA9IFtdLFxuXHRcdGogPSAwLFxuXHRcdGkgPSAwO1xuXG5cdC8vIFVubGVzcyB3ZSAqa25vdyogd2UgY2FuIGRldGVjdCBkdXBsaWNhdGVzLCBhc3N1bWUgdGhlaXIgcHJlc2VuY2Vcblx0aGFzRHVwbGljYXRlID0gIXN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcztcblx0c29ydElucHV0ID0gIXN1cHBvcnQuc29ydFN0YWJsZSAmJiByZXN1bHRzLnNsaWNlKCAwICk7XG5cdHJlc3VsdHMuc29ydCggc29ydE9yZGVyICk7XG5cblx0aWYgKCBoYXNEdXBsaWNhdGUgKSB7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRpZiAoIGVsZW0gPT09IHJlc3VsdHNbIGkgXSApIHtcblx0XHRcdFx0aiA9IGR1cGxpY2F0ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdHJlc3VsdHMuc3BsaWNlKCBkdXBsaWNhdGVzWyBqIF0sIDEgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDbGVhciBpbnB1dCBhZnRlciBzb3J0aW5nIHRvIHJlbGVhc2Ugb2JqZWN0c1xuXHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9zaXp6bGUvcHVsbC8yMjVcblx0c29ydElucHV0ID0gbnVsbDtcblxuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiBmb3IgcmV0cmlldmluZyB0aGUgdGV4dCB2YWx1ZSBvZiBhbiBhcnJheSBvZiBET00gbm9kZXNcbiAqIEBwYXJhbSB7QXJyYXl8RWxlbWVudH0gZWxlbVxuICovXG5nZXRUZXh0ID0gU2l6emxlLmdldFRleHQgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0dmFyIG5vZGUsXG5cdFx0cmV0ID0gXCJcIixcblx0XHRpID0gMCxcblx0XHRub2RlVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0aWYgKCAhbm9kZVR5cGUgKSB7XG5cdFx0Ly8gSWYgbm8gbm9kZVR5cGUsIHRoaXMgaXMgZXhwZWN0ZWQgdG8gYmUgYW4gYXJyYXlcblx0XHR3aGlsZSAoIChub2RlID0gZWxlbVtpKytdKSApIHtcblx0XHRcdC8vIERvIG5vdCB0cmF2ZXJzZSBjb21tZW50IG5vZGVzXG5cdFx0XHRyZXQgKz0gZ2V0VGV4dCggbm9kZSApO1xuXHRcdH1cblx0fSBlbHNlIGlmICggbm9kZVR5cGUgPT09IDEgfHwgbm9kZVR5cGUgPT09IDkgfHwgbm9kZVR5cGUgPT09IDExICkge1xuXHRcdC8vIFVzZSB0ZXh0Q29udGVudCBmb3IgZWxlbWVudHNcblx0XHQvLyBpbm5lclRleHQgdXNhZ2UgcmVtb3ZlZCBmb3IgY29uc2lzdGVuY3kgb2YgbmV3IGxpbmVzIChqUXVlcnkgIzExMTUzKVxuXHRcdGlmICggdHlwZW9mIGVsZW0udGV4dENvbnRlbnQgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS50ZXh0Q29udGVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gVHJhdmVyc2UgaXRzIGNoaWxkcmVuXG5cdFx0XHRmb3IgKCBlbGVtID0gZWxlbS5maXJzdENoaWxkOyBlbGVtOyBlbGVtID0gZWxlbS5uZXh0U2libGluZyApIHtcblx0XHRcdFx0cmV0ICs9IGdldFRleHQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAzIHx8IG5vZGVUeXBlID09PSA0ICkge1xuXHRcdHJldHVybiBlbGVtLm5vZGVWYWx1ZTtcblx0fVxuXHQvLyBEbyBub3QgaW5jbHVkZSBjb21tZW50IG9yIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gbm9kZXNcblxuXHRyZXR1cm4gcmV0O1xufTtcblxuRXhwciA9IFNpenpsZS5zZWxlY3RvcnMgPSB7XG5cblx0Ly8gQ2FuIGJlIGFkanVzdGVkIGJ5IHRoZSB1c2VyXG5cdGNhY2hlTGVuZ3RoOiA1MCxcblxuXHRjcmVhdGVQc2V1ZG86IG1hcmtGdW5jdGlvbixcblxuXHRtYXRjaDogbWF0Y2hFeHByLFxuXG5cdGF0dHJIYW5kbGU6IHt9LFxuXG5cdGZpbmQ6IHt9LFxuXG5cdHJlbGF0aXZlOiB7XG5cdFx0XCI+XCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIiBcIjogeyBkaXI6IFwicGFyZW50Tm9kZVwiIH0sXG5cdFx0XCIrXCI6IHsgZGlyOiBcInByZXZpb3VzU2libGluZ1wiLCBmaXJzdDogdHJ1ZSB9LFxuXHRcdFwiflwiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiB9XG5cdH0sXG5cblx0cHJlRmlsdGVyOiB7XG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0Ly8gTW92ZSB0aGUgZ2l2ZW4gdmFsdWUgdG8gbWF0Y2hbM10gd2hldGhlciBxdW90ZWQgb3IgdW5xdW90ZWRcblx0XHRcdG1hdGNoWzNdID0gKCBtYXRjaFszXSB8fCBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiICkucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsyXSA9PT0gXCJ+PVwiICkge1xuXHRcdFx0XHRtYXRjaFszXSA9IFwiIFwiICsgbWF0Y2hbM10gKyBcIiBcIjtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCA0ICk7XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0LyogbWF0Y2hlcyBmcm9tIG1hdGNoRXhwcltcIkNISUxEXCJdXG5cdFx0XHRcdDEgdHlwZSAob25seXxudGh8Li4uKVxuXHRcdFx0XHQyIHdoYXQgKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdDMgYXJndW1lbnQgKGV2ZW58b2RkfFxcZCp8XFxkKm4oWystXVxcZCspP3wuLi4pXG5cdFx0XHRcdDQgeG4tY29tcG9uZW50IG9mIHhuK3kgYXJndW1lbnQgKFsrLV0/XFxkKm58KVxuXHRcdFx0XHQ1IHNpZ24gb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDYgeCBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NyBzaWduIG9mIHktY29tcG9uZW50XG5cdFx0XHRcdDggeSBvZiB5LWNvbXBvbmVudFxuXHRcdFx0Ki9cblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsxXS5zbGljZSggMCwgMyApID09PSBcIm50aFwiICkge1xuXHRcdFx0XHQvLyBudGgtKiByZXF1aXJlcyBhcmd1bWVudFxuXHRcdFx0XHRpZiAoICFtYXRjaFszXSApIHtcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBudW1lcmljIHggYW5kIHkgcGFyYW1ldGVycyBmb3IgRXhwci5maWx0ZXIuQ0hJTERcblx0XHRcdFx0Ly8gcmVtZW1iZXIgdGhhdCBmYWxzZS90cnVlIGNhc3QgcmVzcGVjdGl2ZWx5IHRvIDAvMVxuXHRcdFx0XHRtYXRjaFs0XSA9ICsoIG1hdGNoWzRdID8gbWF0Y2hbNV0gKyAobWF0Y2hbNl0gfHwgMSkgOiAyICogKCBtYXRjaFszXSA9PT0gXCJldmVuXCIgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKSApO1xuXHRcdFx0XHRtYXRjaFs1XSA9ICsoICggbWF0Y2hbN10gKyBtYXRjaFs4XSApIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICk7XG5cblx0XHRcdC8vIG90aGVyIHR5cGVzIHByb2hpYml0IGFyZ3VtZW50c1xuXHRcdFx0fSBlbHNlIGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdFNpenpsZS5lcnJvciggbWF0Y2hbMF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoO1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHR2YXIgZXhjZXNzLFxuXHRcdFx0XHR1bnF1b3RlZCA9ICFtYXRjaFs2XSAmJiBtYXRjaFsyXTtcblxuXHRcdFx0aWYgKCBtYXRjaEV4cHJbXCJDSElMRFwiXS50ZXN0KCBtYXRjaFswXSApICkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWNjZXB0IHF1b3RlZCBhcmd1bWVudHMgYXMtaXNcblx0XHRcdGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdG1hdGNoWzJdID0gbWF0Y2hbNF0gfHwgbWF0Y2hbNV0gfHwgXCJcIjtcblxuXHRcdFx0Ly8gU3RyaXAgZXhjZXNzIGNoYXJhY3RlcnMgZnJvbSB1bnF1b3RlZCBhcmd1bWVudHNcblx0XHRcdH0gZWxzZSBpZiAoIHVucXVvdGVkICYmIHJwc2V1ZG8udGVzdCggdW5xdW90ZWQgKSAmJlxuXHRcdFx0XHQvLyBHZXQgZXhjZXNzIGZyb20gdG9rZW5pemUgKHJlY3Vyc2l2ZWx5KVxuXHRcdFx0XHQoZXhjZXNzID0gdG9rZW5pemUoIHVucXVvdGVkLCB0cnVlICkpICYmXG5cdFx0XHRcdC8vIGFkdmFuY2UgdG8gdGhlIG5leHQgY2xvc2luZyBwYXJlbnRoZXNpc1xuXHRcdFx0XHQoZXhjZXNzID0gdW5xdW90ZWQuaW5kZXhPZiggXCIpXCIsIHVucXVvdGVkLmxlbmd0aCAtIGV4Y2VzcyApIC0gdW5xdW90ZWQubGVuZ3RoKSApIHtcblxuXHRcdFx0XHQvLyBleGNlc3MgaXMgYSBuZWdhdGl2ZSBpbmRleFxuXHRcdFx0XHRtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwLCBleGNlc3MgKTtcblx0XHRcdFx0bWF0Y2hbMl0gPSB1bnF1b3RlZC5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldHVybiBvbmx5IGNhcHR1cmVzIG5lZWRlZCBieSB0aGUgcHNldWRvIGZpbHRlciBtZXRob2QgKHR5cGUgYW5kIGFyZ3VtZW50KVxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCAzICk7XG5cdFx0fVxuXHR9LFxuXG5cdGZpbHRlcjoge1xuXG5cdFx0XCJUQUdcIjogZnVuY3Rpb24oIG5vZGVOYW1lU2VsZWN0b3IgKSB7XG5cdFx0XHR2YXIgbm9kZU5hbWUgPSBub2RlTmFtZVNlbGVjdG9yLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICkudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBub2RlTmFtZVNlbGVjdG9yID09PSBcIipcIiA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfSA6XG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbm9kZU5hbWU7XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0xBU1NcIjogZnVuY3Rpb24oIGNsYXNzTmFtZSApIHtcblx0XHRcdHZhciBwYXR0ZXJuID0gY2xhc3NDYWNoZVsgY2xhc3NOYW1lICsgXCIgXCIgXTtcblxuXHRcdFx0cmV0dXJuIHBhdHRlcm4gfHxcblx0XHRcdFx0KHBhdHRlcm4gPSBuZXcgUmVnRXhwKCBcIihefFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgY2xhc3NOYW1lICsgXCIoXCIgKyB3aGl0ZXNwYWNlICsgXCJ8JClcIiApKSAmJlxuXHRcdFx0XHRjbGFzc0NhY2hlKCBjbGFzc05hbWUsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXR0ZXJuLnRlc3QoIHR5cGVvZiBlbGVtLmNsYXNzTmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBlbGVtLmNsYXNzTmFtZSB8fCB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGUgIT09IFwidW5kZWZpbmVkXCIgJiYgZWxlbS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKSB8fCBcIlwiICk7XG5cdFx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRcIkFUVFJcIjogZnVuY3Rpb24oIG5hbWUsIG9wZXJhdG9yLCBjaGVjayApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IFNpenpsZS5hdHRyKCBlbGVtLCBuYW1lICk7XG5cblx0XHRcdFx0aWYgKCByZXN1bHQgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiIT1cIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoICFvcGVyYXRvciApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlc3VsdCArPSBcIlwiO1xuXG5cdFx0XHRcdHJldHVybiBvcGVyYXRvciA9PT0gXCI9XCIgPyByZXN1bHQgPT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIhPVwiID8gcmVzdWx0ICE9PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiXj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID09PSAwIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIqPVwiID8gY2hlY2sgJiYgcmVzdWx0LmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiJD1cIiA/IGNoZWNrICYmIHJlc3VsdC5zbGljZSggLWNoZWNrLmxlbmd0aCApID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifj1cIiA/ICggXCIgXCIgKyByZXN1bHQucmVwbGFjZSggcndoaXRlc3BhY2UsIFwiIFwiICkgKyBcIiBcIiApLmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifD1cIiA/IHJlc3VsdCA9PT0gY2hlY2sgfHwgcmVzdWx0LnNsaWNlKCAwLCBjaGVjay5sZW5ndGggKyAxICkgPT09IGNoZWNrICsgXCItXCIgOlxuXHRcdFx0XHRcdGZhbHNlO1xuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDSElMRFwiOiBmdW5jdGlvbiggdHlwZSwgd2hhdCwgYXJndW1lbnQsIGZpcnN0LCBsYXN0ICkge1xuXHRcdFx0dmFyIHNpbXBsZSA9IHR5cGUuc2xpY2UoIDAsIDMgKSAhPT0gXCJudGhcIixcblx0XHRcdFx0Zm9yd2FyZCA9IHR5cGUuc2xpY2UoIC00ICkgIT09IFwibGFzdFwiLFxuXHRcdFx0XHRvZlR5cGUgPSB3aGF0ID09PSBcIm9mLXR5cGVcIjtcblxuXHRcdFx0cmV0dXJuIGZpcnN0ID09PSAxICYmIGxhc3QgPT09IDAgP1xuXG5cdFx0XHRcdC8vIFNob3J0Y3V0IGZvciA6bnRoLSoobilcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuICEhZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0XHR9IDpcblxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBjYWNoZSwgdW5pcXVlQ2FjaGUsIG91dGVyQ2FjaGUsIG5vZGUsIG5vZGVJbmRleCwgc3RhcnQsXG5cdFx0XHRcdFx0XHRkaXIgPSBzaW1wbGUgIT09IGZvcndhcmQgPyBcIm5leHRTaWJsaW5nXCIgOiBcInByZXZpb3VzU2libGluZ1wiLFxuXHRcdFx0XHRcdFx0cGFyZW50ID0gZWxlbS5wYXJlbnROb2RlLFxuXHRcdFx0XHRcdFx0bmFtZSA9IG9mVHlwZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRcdFx0XHR1c2VDYWNoZSA9ICF4bWwgJiYgIW9mVHlwZSxcblx0XHRcdFx0XHRcdGRpZmYgPSBmYWxzZTtcblxuXHRcdFx0XHRcdGlmICggcGFyZW50ICkge1xuXG5cdFx0XHRcdFx0XHQvLyA6KGZpcnN0fGxhc3R8b25seSktKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdFx0XHRpZiAoIHNpbXBsZSApIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCBkaXIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW07XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9IG5vZGVbIGRpciBdKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggb2ZUeXBlID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDpcblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vIFJldmVyc2UgZGlyZWN0aW9uIGZvciA6b25seS0qIChpZiB3ZSBoYXZlbid0IHlldCBkb25lIHNvKVxuXHRcdFx0XHRcdFx0XHRcdHN0YXJ0ID0gZGlyID0gdHlwZSA9PT0gXCJvbmx5XCIgJiYgIXN0YXJ0ICYmIFwibmV4dFNpYmxpbmdcIjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0c3RhcnQgPSBbIGZvcndhcmQgPyBwYXJlbnQuZmlyc3RDaGlsZCA6IHBhcmVudC5sYXN0Q2hpbGQgXTtcblxuXHRcdFx0XHRcdFx0Ly8gbm9uLXhtbCA6bnRoLWNoaWxkKC4uLikgc3RvcmVzIGNhY2hlIGRhdGEgb24gYHBhcmVudGBcblx0XHRcdFx0XHRcdGlmICggZm9yd2FyZCAmJiB1c2VDYWNoZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTZWVrIGBlbGVtYCBmcm9tIGEgcHJldmlvdXNseS1jYWNoZWQgaW5kZXhcblxuXHRcdFx0XHRcdFx0XHQvLyAuLi5pbiBhIGd6aXAtZnJpZW5kbHkgd2F5XG5cdFx0XHRcdFx0XHRcdG5vZGUgPSBwYXJlbnQ7XG5cdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0Y2FjaGUgPSB1bmlxdWVDYWNoZVsgdHlwZSBdIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVsgMCBdID09PSBkaXJydW5zICYmIGNhY2hlWyAxIF07XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXggJiYgY2FjaGVbIDIgXTtcblx0XHRcdFx0XHRcdFx0bm9kZSA9IG5vZGVJbmRleCAmJiBwYXJlbnQuY2hpbGROb2Rlc1sgbm9kZUluZGV4IF07XG5cblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIHNlZWtpbmcgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBXaGVuIGZvdW5kLCBjYWNoZSBpbmRleGVzIG9uIGBwYXJlbnRgIGFuZCBicmVha1xuXHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSAmJiArK2RpZmYgJiYgbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIG5vZGVJbmRleCwgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFVzZSBwcmV2aW91c2x5LWNhY2hlZCBlbGVtZW50IGluZGV4IGlmIGF2YWlsYWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLmluIGEgZ3ppcC1mcmllbmRseSB3YXlcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gZWxlbTtcblx0XHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gbm9kZVsgZXhwYW5kbyBdIHx8IChub2RlWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHRjYWNoZSA9IHVuaXF1ZUNhY2hlWyB0eXBlIF0gfHwgW107XG5cdFx0XHRcdFx0XHRcdFx0bm9kZUluZGV4ID0gY2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBjYWNoZVsgMSBdO1xuXHRcdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXg7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvLyB4bWwgOm50aC1jaGlsZCguLi4pXG5cdFx0XHRcdFx0XHRcdC8vIG9yIDpudGgtbGFzdC1jaGlsZCguLi4pIG9yIDpudGgoLWxhc3QpPy1vZi10eXBlKC4uLilcblx0XHRcdFx0XHRcdFx0aWYgKCBkaWZmID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBVc2UgdGhlIHNhbWUgbG9vcCBhcyBhYm92ZSB0byBzZWVrIGBlbGVtYCBmcm9tIHRoZSBzdGFydFxuXHRcdFx0XHRcdFx0XHRcdHdoaWxlICggKG5vZGUgPSArK25vZGVJbmRleCAmJiBub2RlICYmIG5vZGVbIGRpciBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCAoIG9mVHlwZSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZSA6XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZVR5cGUgPT09IDEgKSAmJlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQrK2RpZmYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FjaGUgdGhlIGluZGV4IG9mIGVhY2ggZW5jb3VudGVyZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZlbmQgYWdhaW5zdCBjbG9uZWQgYXR0cm9wZXJ0aWVzIChqUXVlcnkgZ2gtMTcwOSlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIGRpZmYgXTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQvLyBJbmNvcnBvcmF0ZSB0aGUgb2Zmc2V0LCB0aGVuIGNoZWNrIGFnYWluc3QgY3ljbGUgc2l6ZVxuXHRcdFx0XHRcdFx0ZGlmZiAtPSBsYXN0O1xuXHRcdFx0XHRcdFx0cmV0dXJuIGRpZmYgPT09IGZpcnN0IHx8ICggZGlmZiAlIGZpcnN0ID09PSAwICYmIGRpZmYgLyBmaXJzdCA+PSAwICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggcHNldWRvLCBhcmd1bWVudCApIHtcblx0XHRcdC8vIHBzZXVkby1jbGFzcyBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZVxuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNwc2V1ZG8tY2xhc3Nlc1xuXHRcdFx0Ly8gUHJpb3JpdGl6ZSBieSBjYXNlIHNlbnNpdGl2aXR5IGluIGNhc2UgY3VzdG9tIHBzZXVkb3MgYXJlIGFkZGVkIHdpdGggdXBwZXJjYXNlIGxldHRlcnNcblx0XHRcdC8vIFJlbWVtYmVyIHRoYXQgc2V0RmlsdGVycyBpbmhlcml0cyBmcm9tIHBzZXVkb3Ncblx0XHRcdHZhciBhcmdzLFxuXHRcdFx0XHRmbiA9IEV4cHIucHNldWRvc1sgcHNldWRvIF0gfHwgRXhwci5zZXRGaWx0ZXJzWyBwc2V1ZG8udG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIHBzZXVkbzogXCIgKyBwc2V1ZG8gKTtcblxuXHRcdFx0Ly8gVGhlIHVzZXIgbWF5IHVzZSBjcmVhdGVQc2V1ZG8gdG8gaW5kaWNhdGUgdGhhdFxuXHRcdFx0Ly8gYXJndW1lbnRzIGFyZSBuZWVkZWQgdG8gY3JlYXRlIHRoZSBmaWx0ZXIgZnVuY3Rpb25cblx0XHRcdC8vIGp1c3QgYXMgU2l6emxlIGRvZXNcblx0XHRcdGlmICggZm5bIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZuKCBhcmd1bWVudCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBCdXQgbWFpbnRhaW4gc3VwcG9ydCBmb3Igb2xkIHNpZ25hdHVyZXNcblx0XHRcdGlmICggZm4ubGVuZ3RoID4gMSApIHtcblx0XHRcdFx0YXJncyA9IFsgcHNldWRvLCBwc2V1ZG8sIFwiXCIsIGFyZ3VtZW50IF07XG5cdFx0XHRcdHJldHVybiBFeHByLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoIHBzZXVkby50b0xvd2VyQ2FzZSgpICkgP1xuXHRcdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdFx0XHRcdHZhciBpZHgsXG5cdFx0XHRcdFx0XHRcdG1hdGNoZWQgPSBmbiggc2VlZCwgYXJndW1lbnQgKSxcblx0XHRcdFx0XHRcdFx0aSA9IG1hdGNoZWQubGVuZ3RoO1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlkeCA9IGluZGV4T2YoIHNlZWQsIG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdFx0c2VlZFsgaWR4IF0gPSAhKCBtYXRjaGVzWyBpZHggXSA9IG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZm4oIGVsZW0sIDAsIGFyZ3MgKTtcblx0XHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZm47XG5cdFx0fVxuXHR9LFxuXG5cdHBzZXVkb3M6IHtcblx0XHQvLyBQb3RlbnRpYWxseSBjb21wbGV4IHBzZXVkb3Ncblx0XHRcIm5vdFwiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0Ly8gVHJpbSB0aGUgc2VsZWN0b3IgcGFzc2VkIHRvIGNvbXBpbGVcblx0XHRcdC8vIHRvIGF2b2lkIHRyZWF0aW5nIGxlYWRpbmcgYW5kIHRyYWlsaW5nXG5cdFx0XHQvLyBzcGFjZXMgYXMgY29tYmluYXRvcnNcblx0XHRcdHZhciBpbnB1dCA9IFtdLFxuXHRcdFx0XHRyZXN1bHRzID0gW10sXG5cdFx0XHRcdG1hdGNoZXIgPSBjb21waWxlKCBzZWxlY3Rvci5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICkgKTtcblxuXHRcdFx0cmV0dXJuIG1hdGNoZXJbIGV4cGFuZG8gXSA/XG5cdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcywgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBlbGVtLFxuXHRcdFx0XHRcdFx0dW5tYXRjaGVkID0gbWF0Y2hlciggc2VlZCwgbnVsbCwgeG1sLCBbXSApLFxuXHRcdFx0XHRcdFx0aSA9IHNlZWQubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Ly8gTWF0Y2ggZWxlbWVudHMgdW5tYXRjaGVkIGJ5IGBtYXRjaGVyYFxuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdHNlZWRbaV0gPSAhKG1hdGNoZXNbaV0gPSBlbGVtKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pIDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdFx0XHRpbnB1dFswXSA9IGVsZW07XG5cdFx0XHRcdFx0bWF0Y2hlciggaW5wdXQsIG51bGwsIHhtbCwgcmVzdWx0cyApO1xuXHRcdFx0XHRcdC8vIERvbid0IGtlZXAgdGhlIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRcdFx0aW5wdXRbMF0gPSBudWxsO1xuXHRcdFx0XHRcdHJldHVybiAhcmVzdWx0cy5wb3AoKTtcblx0XHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiaGFzXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBTaXp6bGUoIHNlbGVjdG9yLCBlbGVtICkubGVuZ3RoID4gMDtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHRcImNvbnRhaW5zXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdHRleHQgPSB0ZXh0LnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lclRleHQgfHwgZ2V0VGV4dCggZWxlbSApICkuaW5kZXhPZiggdGV4dCApID4gLTE7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gXCJXaGV0aGVyIGFuIGVsZW1lbnQgaXMgcmVwcmVzZW50ZWQgYnkgYSA6bGFuZygpIHNlbGVjdG9yXG5cdFx0Ly8gaXMgYmFzZWQgc29sZWx5IG9uIHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWVcblx0XHQvLyBiZWluZyBlcXVhbCB0byB0aGUgaWRlbnRpZmllciBDLFxuXHRcdC8vIG9yIGJlZ2lubmluZyB3aXRoIHRoZSBpZGVudGlmaWVyIEMgaW1tZWRpYXRlbHkgZm9sbG93ZWQgYnkgXCItXCIuXG5cdFx0Ly8gVGhlIG1hdGNoaW5nIG9mIEMgYWdhaW5zdCB0aGUgZWxlbWVudCdzIGxhbmd1YWdlIHZhbHVlIGlzIHBlcmZvcm1lZCBjYXNlLWluc2Vuc2l0aXZlbHkuXG5cdFx0Ly8gVGhlIGlkZW50aWZpZXIgQyBkb2VzIG5vdCBoYXZlIHRvIGJlIGEgdmFsaWQgbGFuZ3VhZ2UgbmFtZS5cIlxuXHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jbGFuZy1wc2V1ZG9cblx0XHRcImxhbmdcIjogbWFya0Z1bmN0aW9uKCBmdW5jdGlvbiggbGFuZyApIHtcblx0XHRcdC8vIGxhbmcgdmFsdWUgbXVzdCBiZSBhIHZhbGlkIGlkZW50aWZpZXJcblx0XHRcdGlmICggIXJpZGVudGlmaWVyLnRlc3QobGFuZyB8fCBcIlwiKSApIHtcblx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIGxhbmc6IFwiICsgbGFuZyApO1xuXHRcdFx0fVxuXHRcdFx0bGFuZyA9IGxhbmcucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgZWxlbUxhbmc7XG5cdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtTGFuZyA9IGRvY3VtZW50SXNIVE1MID9cblx0XHRcdFx0XHRcdGVsZW0ubGFuZyA6XG5cdFx0XHRcdFx0XHRlbGVtLmdldEF0dHJpYnV0ZShcInhtbDpsYW5nXCIpIHx8IGVsZW0uZ2V0QXR0cmlidXRlKFwibGFuZ1wiKSkgKSB7XG5cblx0XHRcdFx0XHRcdGVsZW1MYW5nID0gZWxlbUxhbmcudG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtTGFuZyA9PT0gbGFuZyB8fCBlbGVtTGFuZy5pbmRleE9mKCBsYW5nICsgXCItXCIgKSA9PT0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gd2hpbGUgKCAoZWxlbSA9IGVsZW0ucGFyZW50Tm9kZSkgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gTWlzY2VsbGFuZW91c1xuXHRcdFwidGFyZ2V0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGhhc2ggPSB3aW5kb3cubG9jYXRpb24gJiYgd2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0XHRyZXR1cm4gaGFzaCAmJiBoYXNoLnNsaWNlKCAxICkgPT09IGVsZW0uaWQ7XG5cdFx0fSxcblxuXHRcdFwicm9vdFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBkb2NFbGVtO1xuXHRcdH0sXG5cblx0XHRcImZvY3VzXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKCFkb2N1bWVudC5oYXNGb2N1cyB8fCBkb2N1bWVudC5oYXNGb2N1cygpKSAmJiAhIShlbGVtLnR5cGUgfHwgZWxlbS5ocmVmIHx8IH5lbGVtLnRhYkluZGV4KTtcblx0XHR9LFxuXG5cdFx0Ly8gQm9vbGVhbiBwcm9wZXJ0aWVzXG5cdFx0XCJlbmFibGVkXCI6IGNyZWF0ZURpc2FibGVkUHNldWRvKCBmYWxzZSApLFxuXHRcdFwiZGlzYWJsZWRcIjogY3JlYXRlRGlzYWJsZWRQc2V1ZG8oIHRydWUgKSxcblxuXHRcdFwiY2hlY2tlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEluIENTUzMsIDpjaGVja2VkIHNob3VsZCByZXR1cm4gYm90aCBjaGVja2VkIGFuZCBzZWxlY3RlZCBlbGVtZW50c1xuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvMjAxMS9SRUMtY3NzMy1zZWxlY3RvcnMtMjAxMTA5MjkvI2NoZWNrZWRcblx0XHRcdHZhciBub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiAobm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiAhIWVsZW0uY2hlY2tlZCkgfHwgKG5vZGVOYW1lID09PSBcIm9wdGlvblwiICYmICEhZWxlbS5zZWxlY3RlZCk7XG5cdFx0fSxcblxuXHRcdFwic2VsZWN0ZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBBY2Nlc3NpbmcgdGhpcyBwcm9wZXJ0eSBtYWtlcyBzZWxlY3RlZC1ieS1kZWZhdWx0XG5cdFx0XHQvLyBvcHRpb25zIGluIFNhZmFyaSB3b3JrIHByb3Blcmx5XG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBlbGVtLnNlbGVjdGVkID09PSB0cnVlO1xuXHRcdH0sXG5cblx0XHQvLyBDb250ZW50c1xuXHRcdFwiZW1wdHlcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2VtcHR5LXBzZXVkb1xuXHRcdFx0Ly8gOmVtcHR5IGlzIG5lZ2F0ZWQgYnkgZWxlbWVudCAoMSkgb3IgY29udGVudCBub2RlcyAodGV4dDogMzsgY2RhdGE6IDQ7IGVudGl0eSByZWY6IDUpLFxuXHRcdFx0Ly8gICBidXQgbm90IGJ5IG90aGVycyAoY29tbWVudDogODsgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbjogNzsgZXRjLilcblx0XHRcdC8vIG5vZGVUeXBlIDwgNiB3b3JrcyBiZWNhdXNlIGF0dHJpYnV0ZXMgKDIpIGRvIG5vdCBhcHBlYXIgYXMgY2hpbGRyZW5cblx0XHRcdGZvciAoIGVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7IGVsZW07IGVsZW0gPSBlbGVtLm5leHRTaWJsaW5nICkge1xuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPCA2ICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblxuXHRcdFwicGFyZW50XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICFFeHByLnBzZXVkb3NbXCJlbXB0eVwiXSggZWxlbSApO1xuXHRcdH0sXG5cblx0XHQvLyBFbGVtZW50L2lucHV0IHR5cGVzXG5cdFx0XCJoZWFkZXJcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmhlYWRlci50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiaW5wdXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmlucHV0cy50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiYnV0dG9uXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIG5hbWUgPSBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gXCJidXR0b25cIiB8fCBuYW1lID09PSBcImJ1dHRvblwiO1xuXHRcdH0sXG5cblx0XHRcInRleHRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgYXR0cjtcblx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaW5wdXRcIiAmJlxuXHRcdFx0XHRlbGVtLnR5cGUgPT09IFwidGV4dFwiICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUU8OFxuXHRcdFx0XHQvLyBOZXcgSFRNTDUgYXR0cmlidXRlIHZhbHVlcyAoZS5nLiwgXCJzZWFyY2hcIikgYXBwZWFyIHdpdGggZWxlbS50eXBlID09PSBcInRleHRcIlxuXHRcdFx0XHQoIChhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpKSA9PSBudWxsIHx8IGF0dHIudG9Mb3dlckNhc2UoKSA9PT0gXCJ0ZXh0XCIgKTtcblx0XHR9LFxuXG5cdFx0Ly8gUG9zaXRpb24taW4tY29sbGVjdGlvblxuXHRcdFwiZmlyc3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBbIDAgXTtcblx0XHR9KSxcblxuXHRcdFwibGFzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHJldHVybiBbIGxlbmd0aCAtIDEgXTtcblx0XHR9KSxcblxuXHRcdFwiZXFcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0cmV0dXJuIFsgYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJldmVuXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0dmFyIGkgPSAwO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpICs9IDIgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJvZGRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDE7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcImx0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHZhciBpID0gYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudDtcblx0XHRcdGZvciAoIDsgLS1pID49IDA7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwiZ3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyArK2kgPCBsZW5ndGg7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KVxuXHR9XG59O1xuXG5FeHByLnBzZXVkb3NbXCJudGhcIl0gPSBFeHByLnBzZXVkb3NbXCJlcVwiXTtcblxuLy8gQWRkIGJ1dHRvbi9pbnB1dCB0eXBlIHBzZXVkb3NcbmZvciAoIGkgaW4geyByYWRpbzogdHJ1ZSwgY2hlY2tib3g6IHRydWUsIGZpbGU6IHRydWUsIHBhc3N3b3JkOiB0cnVlLCBpbWFnZTogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUlucHV0UHNldWRvKCBpICk7XG59XG5mb3IgKCBpIGluIHsgc3VibWl0OiB0cnVlLCByZXNldDogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUJ1dHRvblBzZXVkbyggaSApO1xufVxuXG4vLyBFYXN5IEFQSSBmb3IgY3JlYXRpbmcgbmV3IHNldEZpbHRlcnNcbmZ1bmN0aW9uIHNldEZpbHRlcnMoKSB7fVxuc2V0RmlsdGVycy5wcm90b3R5cGUgPSBFeHByLmZpbHRlcnMgPSBFeHByLnBzZXVkb3M7XG5FeHByLnNldEZpbHRlcnMgPSBuZXcgc2V0RmlsdGVycygpO1xuXG50b2tlbml6ZSA9IFNpenpsZS50b2tlbml6ZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgcGFyc2VPbmx5ICkge1xuXHR2YXIgbWF0Y2hlZCwgbWF0Y2gsIHRva2VucywgdHlwZSxcblx0XHRzb0ZhciwgZ3JvdXBzLCBwcmVGaWx0ZXJzLFxuXHRcdGNhY2hlZCA9IHRva2VuQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXTtcblxuXHRpZiAoIGNhY2hlZCApIHtcblx0XHRyZXR1cm4gcGFyc2VPbmx5ID8gMCA6IGNhY2hlZC5zbGljZSggMCApO1xuXHR9XG5cblx0c29GYXIgPSBzZWxlY3Rvcjtcblx0Z3JvdXBzID0gW107XG5cdHByZUZpbHRlcnMgPSBFeHByLnByZUZpbHRlcjtcblxuXHR3aGlsZSAoIHNvRmFyICkge1xuXG5cdFx0Ly8gQ29tbWEgYW5kIGZpcnN0IHJ1blxuXHRcdGlmICggIW1hdGNoZWQgfHwgKG1hdGNoID0gcmNvbW1hLmV4ZWMoIHNvRmFyICkpICkge1xuXHRcdFx0aWYgKCBtYXRjaCApIHtcblx0XHRcdFx0Ly8gRG9uJ3QgY29uc3VtZSB0cmFpbGluZyBjb21tYXMgYXMgdmFsaWRcblx0XHRcdFx0c29GYXIgPSBzb0Zhci5zbGljZSggbWF0Y2hbMF0ubGVuZ3RoICkgfHwgc29GYXI7XG5cdFx0XHR9XG5cdFx0XHRncm91cHMucHVzaCggKHRva2VucyA9IFtdKSApO1xuXHRcdH1cblxuXHRcdG1hdGNoZWQgPSBmYWxzZTtcblxuXHRcdC8vIENvbWJpbmF0b3JzXG5cdFx0aWYgKCAobWF0Y2ggPSByY29tYmluYXRvcnMuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0dmFsdWU6IG1hdGNoZWQsXG5cdFx0XHRcdC8vIENhc3QgZGVzY2VuZGFudCBjb21iaW5hdG9ycyB0byBzcGFjZVxuXHRcdFx0XHR0eXBlOiBtYXRjaFswXS5yZXBsYWNlKCBydHJpbSwgXCIgXCIgKVxuXHRcdFx0fSk7XG5cdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdH1cblxuXHRcdC8vIEZpbHRlcnNcblx0XHRmb3IgKCB0eXBlIGluIEV4cHIuZmlsdGVyICkge1xuXHRcdFx0aWYgKCAobWF0Y2ggPSBtYXRjaEV4cHJbIHR5cGUgXS5leGVjKCBzb0ZhciApKSAmJiAoIXByZUZpbHRlcnNbIHR5cGUgXSB8fFxuXHRcdFx0XHQobWF0Y2ggPSBwcmVGaWx0ZXJzWyB0eXBlIF0oIG1hdGNoICkpKSApIHtcblx0XHRcdFx0bWF0Y2hlZCA9IG1hdGNoLnNoaWZ0KCk7XG5cdFx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRcdG1hdGNoZXM6IG1hdGNoXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIW1hdGNoZWQgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHQvLyBSZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgaW52YWxpZCBleGNlc3Ncblx0Ly8gaWYgd2UncmUganVzdCBwYXJzaW5nXG5cdC8vIE90aGVyd2lzZSwgdGhyb3cgYW4gZXJyb3Igb3IgcmV0dXJuIHRva2Vuc1xuXHRyZXR1cm4gcGFyc2VPbmx5ID9cblx0XHRzb0Zhci5sZW5ndGggOlxuXHRcdHNvRmFyID9cblx0XHRcdFNpenpsZS5lcnJvciggc2VsZWN0b3IgKSA6XG5cdFx0XHQvLyBDYWNoZSB0aGUgdG9rZW5zXG5cdFx0XHR0b2tlbkNhY2hlKCBzZWxlY3RvciwgZ3JvdXBzICkuc2xpY2UoIDAgKTtcbn07XG5cbmZ1bmN0aW9uIHRvU2VsZWN0b3IoIHRva2VucyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGxlbiA9IHRva2Vucy5sZW5ndGgsXG5cdFx0c2VsZWN0b3IgPSBcIlwiO1xuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRzZWxlY3RvciArPSB0b2tlbnNbaV0udmFsdWU7XG5cdH1cblx0cmV0dXJuIHNlbGVjdG9yO1xufVxuXG5mdW5jdGlvbiBhZGRDb21iaW5hdG9yKCBtYXRjaGVyLCBjb21iaW5hdG9yLCBiYXNlICkge1xuXHR2YXIgZGlyID0gY29tYmluYXRvci5kaXIsXG5cdFx0c2tpcCA9IGNvbWJpbmF0b3IubmV4dCxcblx0XHRrZXkgPSBza2lwIHx8IGRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBrZXkgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGNsb3Nlc3QgYW5jZXN0b3IvcHJlY2VkaW5nIGVsZW1lbnRcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSA6XG5cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGFsbCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudHNcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCB1bmlxdWVDYWNoZSwgb3V0ZXJDYWNoZSxcblx0XHRcdFx0bmV3Q2FjaGUgPSBbIGRpcnJ1bnMsIGRvbmVOYW1lIF07XG5cblx0XHRcdC8vIFdlIGNhbid0IHNldCBhcmJpdHJhcnkgZGF0YSBvbiBYTUwgbm9kZXMsIHNvIHRoZXkgZG9uJ3QgYmVuZWZpdCBmcm9tIGNvbWJpbmF0b3IgY2FjaGluZ1xuXHRcdFx0aWYgKCB4bWwgKSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBlbGVtLnVuaXF1ZUlEIF0gfHwgKG91dGVyQ2FjaGVbIGVsZW0udW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0aWYgKCBza2lwICYmIHNraXAgPT09IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSApIHtcblx0XHRcdFx0XHRcdFx0ZWxlbSA9IGVsZW1bIGRpciBdIHx8IGVsZW07XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCAob2xkQ2FjaGUgPSB1bmlxdWVDYWNoZVsga2V5IF0pICYmXG5cdFx0XHRcdFx0XHRcdG9sZENhY2hlWyAwIF0gPT09IGRpcnJ1bnMgJiYgb2xkQ2FjaGVbIDEgXSA9PT0gZG9uZU5hbWUgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQXNzaWduIHRvIG5ld0NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0cmV0dXJuIChuZXdDYWNoZVsgMiBdID0gb2xkQ2FjaGVbIDIgXSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXVzZSBuZXdjYWNoZSBzbyByZXN1bHRzIGJhY2stcHJvcGFnYXRlIHRvIHByZXZpb3VzIGVsZW1lbnRzXG5cdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyBrZXkgXSA9IG5ld0NhY2hlO1xuXG5cdFx0XHRcdFx0XHRcdC8vIEEgbWF0Y2ggbWVhbnMgd2UncmUgZG9uZTsgYSBmYWlsIG1lYW5zIHdlIGhhdmUgdG8ga2VlcCBjaGVja2luZ1xuXHRcdFx0XHRcdFx0XHRpZiAoIChuZXdDYWNoZVsgMiBdID0gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkpICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcbn1cblxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICkge1xuXHRyZXR1cm4gbWF0Y2hlcnMubGVuZ3RoID4gMSA/XG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciBpID0gbWF0Y2hlcnMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggIW1hdGNoZXJzW2ldKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gOlxuXHRcdG1hdGNoZXJzWzBdO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciwgY29udGV4dHMsIHJlc3VsdHMgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBjb250ZXh0cy5sZW5ndGg7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHRzW2ldLCByZXN1bHRzICk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdHM7XG59XG5cbmZ1bmN0aW9uIGNvbmRlbnNlKCB1bm1hdGNoZWQsIG1hcCwgZmlsdGVyLCBjb250ZXh0LCB4bWwgKSB7XG5cdHZhciBlbGVtLFxuXHRcdG5ld1VubWF0Y2hlZCA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGxlbiA9IHVubWF0Y2hlZC5sZW5ndGgsXG5cdFx0bWFwcGVkID0gbWFwICE9IG51bGw7XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRpZiAoICFmaWx0ZXIgfHwgZmlsdGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0bmV3VW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0aWYgKCBtYXBwZWQgKSB7XG5cdFx0XHRcdFx0bWFwLnB1c2goIGkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBuZXdVbm1hdGNoZWQ7XG59XG5cbmZ1bmN0aW9uIHNldE1hdGNoZXIoIHByZUZpbHRlciwgc2VsZWN0b3IsIG1hdGNoZXIsIHBvc3RGaWx0ZXIsIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApIHtcblx0aWYgKCBwb3N0RmlsdGVyICYmICFwb3N0RmlsdGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbHRlciA9IHNldE1hdGNoZXIoIHBvc3RGaWx0ZXIgKTtcblx0fVxuXHRpZiAoIHBvc3RGaW5kZXIgJiYgIXBvc3RGaW5kZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmluZGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICk7XG5cdH1cblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgcmVzdWx0cywgY29udGV4dCwgeG1sICkge1xuXHRcdHZhciB0ZW1wLCBpLCBlbGVtLFxuXHRcdFx0cHJlTWFwID0gW10sXG5cdFx0XHRwb3N0TWFwID0gW10sXG5cdFx0XHRwcmVleGlzdGluZyA9IHJlc3VsdHMubGVuZ3RoLFxuXG5cdFx0XHQvLyBHZXQgaW5pdGlhbCBlbGVtZW50cyBmcm9tIHNlZWQgb3IgY29udGV4dFxuXHRcdFx0ZWxlbXMgPSBzZWVkIHx8IG11bHRpcGxlQ29udGV4dHMoIHNlbGVjdG9yIHx8IFwiKlwiLCBjb250ZXh0Lm5vZGVUeXBlID8gWyBjb250ZXh0IF0gOiBjb250ZXh0LCBbXSApLFxuXG5cdFx0XHQvLyBQcmVmaWx0ZXIgdG8gZ2V0IG1hdGNoZXIgaW5wdXQsIHByZXNlcnZpbmcgYSBtYXAgZm9yIHNlZWQtcmVzdWx0cyBzeW5jaHJvbml6YXRpb25cblx0XHRcdG1hdGNoZXJJbiA9IHByZUZpbHRlciAmJiAoIHNlZWQgfHwgIXNlbGVjdG9yICkgP1xuXHRcdFx0XHRjb25kZW5zZSggZWxlbXMsIHByZU1hcCwgcHJlRmlsdGVyLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdGVsZW1zLFxuXG5cdFx0XHRtYXRjaGVyT3V0ID0gbWF0Y2hlciA/XG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgYSBwb3N0RmluZGVyLCBvciBmaWx0ZXJlZCBzZWVkLCBvciBub24tc2VlZCBwb3N0RmlsdGVyIG9yIHByZWV4aXN0aW5nIHJlc3VsdHMsXG5cdFx0XHRcdHBvc3RGaW5kZXIgfHwgKCBzZWVkID8gcHJlRmlsdGVyIDogcHJlZXhpc3RpbmcgfHwgcG9zdEZpbHRlciApID9cblxuXHRcdFx0XHRcdC8vIC4uLmludGVybWVkaWF0ZSBwcm9jZXNzaW5nIGlzIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdFtdIDpcblxuXHRcdFx0XHRcdC8vIC4uLm90aGVyd2lzZSB1c2UgcmVzdWx0cyBkaXJlY3RseVxuXHRcdFx0XHRcdHJlc3VsdHMgOlxuXHRcdFx0XHRtYXRjaGVySW47XG5cblx0XHQvLyBGaW5kIHByaW1hcnkgbWF0Y2hlc1xuXHRcdGlmICggbWF0Y2hlciApIHtcblx0XHRcdG1hdGNoZXIoIG1hdGNoZXJJbiwgbWF0Y2hlck91dCwgY29udGV4dCwgeG1sICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgcG9zdEZpbHRlclxuXHRcdGlmICggcG9zdEZpbHRlciApIHtcblx0XHRcdHRlbXAgPSBjb25kZW5zZSggbWF0Y2hlck91dCwgcG9zdE1hcCApO1xuXHRcdFx0cG9zdEZpbHRlciggdGVtcCwgW10sIGNvbnRleHQsIHhtbCApO1xuXG5cdFx0XHQvLyBVbi1tYXRjaCBmYWlsaW5nIGVsZW1lbnRzIGJ5IG1vdmluZyB0aGVtIGJhY2sgdG8gbWF0Y2hlckluXG5cdFx0XHRpID0gdGVtcC5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAoZWxlbSA9IHRlbXBbaV0pICkge1xuXHRcdFx0XHRcdG1hdGNoZXJPdXRbIHBvc3RNYXBbaV0gXSA9ICEobWF0Y2hlckluWyBwb3N0TWFwW2ldIF0gPSBlbGVtKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggc2VlZCApIHtcblx0XHRcdGlmICggcG9zdEZpbmRlciB8fCBwcmVGaWx0ZXIgKSB7XG5cdFx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIGZpbmFsIG1hdGNoZXJPdXQgYnkgY29uZGVuc2luZyB0aGlzIGludGVybWVkaWF0ZSBpbnRvIHBvc3RGaW5kZXIgY29udGV4dHNcblx0XHRcdFx0XHR0ZW1wID0gW107XG5cdFx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIG1hdGNoZXJJbiBzaW5jZSBlbGVtIGlzIG5vdCB5ZXQgYSBmaW5hbCBtYXRjaFxuXHRcdFx0XHRcdFx0XHR0ZW1wLnB1c2goIChtYXRjaGVySW5baV0gPSBlbGVtKSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCAobWF0Y2hlck91dCA9IFtdKSwgdGVtcCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBNb3ZlIG1hdGNoZWQgZWxlbWVudHMgZnJvbSBzZWVkIHRvIHJlc3VsdHMgdG8ga2VlcCB0aGVtIHN5bmNocm9uaXplZFxuXHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSAmJlxuXHRcdFx0XHRcdFx0KHRlbXAgPSBwb3N0RmluZGVyID8gaW5kZXhPZiggc2VlZCwgZWxlbSApIDogcHJlTWFwW2ldKSA+IC0xICkge1xuXG5cdFx0XHRcdFx0XHRzZWVkW3RlbXBdID0gIShyZXN1bHRzW3RlbXBdID0gZWxlbSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBBZGQgZWxlbWVudHMgdG8gcmVzdWx0cywgdGhyb3VnaCBwb3N0RmluZGVyIGlmIGRlZmluZWRcblx0XHR9IGVsc2Uge1xuXHRcdFx0bWF0Y2hlck91dCA9IGNvbmRlbnNlKFxuXHRcdFx0XHRtYXRjaGVyT3V0ID09PSByZXN1bHRzID9cblx0XHRcdFx0XHRtYXRjaGVyT3V0LnNwbGljZSggcHJlZXhpc3RpbmcsIG1hdGNoZXJPdXQubGVuZ3RoICkgOlxuXHRcdFx0XHRcdG1hdGNoZXJPdXRcblx0XHRcdCk7XG5cdFx0XHRpZiAoIHBvc3RGaW5kZXIgKSB7XG5cdFx0XHRcdHBvc3RGaW5kZXIoIG51bGwsIHJlc3VsdHMsIG1hdGNoZXJPdXQsIHhtbCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgbWF0Y2hlck91dCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMgKSB7XG5cdHZhciBjaGVja0NvbnRleHQsIG1hdGNoZXIsIGosXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRsZWFkaW5nUmVsYXRpdmUgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbMF0udHlwZSBdLFxuXHRcdGltcGxpY2l0UmVsYXRpdmUgPSBsZWFkaW5nUmVsYXRpdmUgfHwgRXhwci5yZWxhdGl2ZVtcIiBcIl0sXG5cdFx0aSA9IGxlYWRpbmdSZWxhdGl2ZSA/IDEgOiAwLFxuXG5cdFx0Ly8gVGhlIGZvdW5kYXRpb25hbCBtYXRjaGVyIGVuc3VyZXMgdGhhdCBlbGVtZW50cyBhcmUgcmVhY2hhYmxlIGZyb20gdG9wLWxldmVsIGNvbnRleHQocylcblx0XHRtYXRjaENvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBjaGVja0NvbnRleHQ7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoQW55Q29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YoIGNoZWNrQ29udGV4dCwgZWxlbSApID4gLTE7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoZXJzID0gWyBmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIHJldCA9ICggIWxlYWRpbmdSZWxhdGl2ZSAmJiAoIHhtbCB8fCBjb250ZXh0ICE9PSBvdXRlcm1vc3RDb250ZXh0ICkgKSB8fCAoXG5cdFx0XHRcdChjaGVja0NvbnRleHQgPSBjb250ZXh0KS5ub2RlVHlwZSA/XG5cdFx0XHRcdFx0bWF0Y2hDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdFx0bWF0Y2hBbnlDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSApO1xuXHRcdFx0Ly8gQXZvaWQgaGFuZ2luZyBvbnRvIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRjaGVja0NvbnRleHQgPSBudWxsO1xuXHRcdFx0cmV0dXJuIHJldDtcblx0XHR9IF07XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAobWF0Y2hlciA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1tpXS50eXBlIF0pICkge1xuXHRcdFx0bWF0Y2hlcnMgPSBbIGFkZENvbWJpbmF0b3IoZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksIG1hdGNoZXIpIF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hdGNoZXIgPSBFeHByLmZpbHRlclsgdG9rZW5zW2ldLnR5cGUgXS5hcHBseSggbnVsbCwgdG9rZW5zW2ldLm1hdGNoZXMgKTtcblxuXHRcdFx0Ly8gUmV0dXJuIHNwZWNpYWwgdXBvbiBzZWVpbmcgYSBwb3NpdGlvbmFsIG1hdGNoZXJcblx0XHRcdGlmICggbWF0Y2hlclsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHQvLyBGaW5kIHRoZSBuZXh0IHJlbGF0aXZlIG9wZXJhdG9yIChpZiBhbnkpIGZvciBwcm9wZXIgaGFuZGxpbmdcblx0XHRcdFx0aiA9ICsraTtcblx0XHRcdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyB0b2tlbnNbal0udHlwZSBdICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBzZXRNYXRjaGVyKFxuXHRcdFx0XHRcdGkgPiAxICYmIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLFxuXHRcdFx0XHRcdGkgPiAxICYmIHRvU2VsZWN0b3IoXG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgcHJlY2VkaW5nIHRva2VuIHdhcyBhIGRlc2NlbmRhbnQgY29tYmluYXRvciwgaW5zZXJ0IGFuIGltcGxpY2l0IGFueS1lbGVtZW50IGAqYFxuXHRcdFx0XHRcdFx0dG9rZW5zLnNsaWNlKCAwLCBpIC0gMSApLmNvbmNhdCh7IHZhbHVlOiB0b2tlbnNbIGkgLSAyIF0udHlwZSA9PT0gXCIgXCIgPyBcIipcIiA6IFwiXCIgfSlcblx0XHRcdFx0XHQpLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSxcblx0XHRcdFx0XHRtYXRjaGVyLFxuXHRcdFx0XHRcdGkgPCBqICYmIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMuc2xpY2UoIGksIGogKSApLFxuXHRcdFx0XHRcdGogPCBsZW4gJiYgbWF0Y2hlckZyb21Ub2tlbnMoICh0b2tlbnMgPSB0b2tlbnMuc2xpY2UoIGogKSkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIHRvU2VsZWN0b3IoIHRva2VucyApXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVycy5wdXNoKCBtYXRjaGVyICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSB7XG5cdHZhciBieVNldCA9IHNldE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0YnlFbGVtZW50ID0gZWxlbWVudE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0c3VwZXJNYXRjaGVyID0gZnVuY3Rpb24oIHNlZWQsIGNvbnRleHQsIHhtbCwgcmVzdWx0cywgb3V0ZXJtb3N0ICkge1xuXHRcdFx0dmFyIGVsZW0sIGosIG1hdGNoZXIsXG5cdFx0XHRcdG1hdGNoZWRDb3VudCA9IDAsXG5cdFx0XHRcdGkgPSBcIjBcIixcblx0XHRcdFx0dW5tYXRjaGVkID0gc2VlZCAmJiBbXSxcblx0XHRcdFx0c2V0TWF0Y2hlZCA9IFtdLFxuXHRcdFx0XHRjb250ZXh0QmFja3VwID0gb3V0ZXJtb3N0Q29udGV4dCxcblx0XHRcdFx0Ly8gV2UgbXVzdCBhbHdheXMgaGF2ZSBlaXRoZXIgc2VlZCBlbGVtZW50cyBvciBvdXRlcm1vc3QgY29udGV4dFxuXHRcdFx0XHRlbGVtcyA9IHNlZWQgfHwgYnlFbGVtZW50ICYmIEV4cHIuZmluZFtcIlRBR1wiXSggXCIqXCIsIG91dGVybW9zdCApLFxuXHRcdFx0XHQvLyBVc2UgaW50ZWdlciBkaXJydW5zIGlmZiB0aGlzIGlzIHRoZSBvdXRlcm1vc3QgbWF0Y2hlclxuXHRcdFx0XHRkaXJydW5zVW5pcXVlID0gKGRpcnJ1bnMgKz0gY29udGV4dEJhY2t1cCA9PSBudWxsID8gMSA6IE1hdGgucmFuZG9tKCkgfHwgMC4xKSxcblx0XHRcdFx0bGVuID0gZWxlbXMubGVuZ3RoO1xuXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0b3V0ZXJtb3N0Q29udGV4dCA9IGNvbnRleHQgPT09IGRvY3VtZW50IHx8IGNvbnRleHQgfHwgb3V0ZXJtb3N0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgZWxlbWVudHMgcGFzc2luZyBlbGVtZW50TWF0Y2hlcnMgZGlyZWN0bHkgdG8gcmVzdWx0c1xuXHRcdFx0Ly8gU3VwcG9ydDogSUU8OSwgU2FmYXJpXG5cdFx0XHQvLyBUb2xlcmF0ZSBOb2RlTGlzdCBwcm9wZXJ0aWVzIChJRTogXCJsZW5ndGhcIjsgU2FmYXJpOiA8bnVtYmVyPikgbWF0Y2hpbmcgZWxlbWVudHMgYnkgaWRcblx0XHRcdGZvciAoIDsgaSAhPT0gbGVuICYmIChlbGVtID0gZWxlbXNbaV0pICE9IG51bGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBieUVsZW1lbnQgJiYgZWxlbSApIHtcblx0XHRcdFx0XHRqID0gMDtcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0ICYmIGVsZW0ub3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHRcdFx0XHRcdFx0eG1sID0gIWRvY3VtZW50SXNIVE1MO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR3aGlsZSAoIChtYXRjaGVyID0gZWxlbWVudE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVyKCBlbGVtLCBjb250ZXh0IHx8IGRvY3VtZW50LCB4bWwpICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHJhY2sgdW5tYXRjaGVkIGVsZW1lbnRzIGZvciBzZXQgZmlsdGVyc1xuXHRcdFx0XHRpZiAoIGJ5U2V0ICkge1xuXHRcdFx0XHRcdC8vIFRoZXkgd2lsbCBoYXZlIGdvbmUgdGhyb3VnaCBhbGwgcG9zc2libGUgbWF0Y2hlcnNcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBMZW5ndGhlbiB0aGUgYXJyYXkgZm9yIGV2ZXJ5IGVsZW1lbnQsIG1hdGNoZWQgb3Igbm90XG5cdFx0XHRcdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0XHRcdFx0dW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYGlgIGlzIG5vdyB0aGUgY291bnQgb2YgZWxlbWVudHMgdmlzaXRlZCBhYm92ZSwgYW5kIGFkZGluZyBpdCB0byBgbWF0Y2hlZENvdW50YFxuXHRcdFx0Ly8gbWFrZXMgdGhlIGxhdHRlciBub25uZWdhdGl2ZS5cblx0XHRcdG1hdGNoZWRDb3VudCArPSBpO1xuXG5cdFx0XHQvLyBBcHBseSBzZXQgZmlsdGVycyB0byB1bm1hdGNoZWQgZWxlbWVudHNcblx0XHRcdC8vIE5PVEU6IFRoaXMgY2FuIGJlIHNraXBwZWQgaWYgdGhlcmUgYXJlIG5vIHVubWF0Y2hlZCBlbGVtZW50cyAoaS5lLiwgYG1hdGNoZWRDb3VudGBcblx0XHRcdC8vIGVxdWFscyBgaWApLCB1bmxlc3Mgd2UgZGlkbid0IHZpc2l0IF9hbnlfIGVsZW1lbnRzIGluIHRoZSBhYm92ZSBsb29wIGJlY2F1c2Ugd2UgaGF2ZVxuXHRcdFx0Ly8gbm8gZWxlbWVudCBtYXRjaGVycyBhbmQgbm8gc2VlZC5cblx0XHRcdC8vIEluY3JlbWVudGluZyBhbiBpbml0aWFsbHktc3RyaW5nIFwiMFwiIGBpYCBhbGxvd3MgYGlgIHRvIHJlbWFpbiBhIHN0cmluZyBvbmx5IGluIHRoYXRcblx0XHRcdC8vIGNhc2UsIHdoaWNoIHdpbGwgcmVzdWx0IGluIGEgXCIwMFwiIGBtYXRjaGVkQ291bnRgIHRoYXQgZGlmZmVycyBmcm9tIGBpYCBidXQgaXMgYWxzb1xuXHRcdFx0Ly8gbnVtZXJpY2FsbHkgemVyby5cblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0Ly8gUmVpbnRlZ3JhdGUgZWxlbWVudCBtYXRjaGVzIHRvIGVsaW1pbmF0ZSB0aGUgbmVlZCBmb3Igc29ydGluZ1xuXHRcdFx0XHRcdGlmICggbWF0Y2hlZENvdW50ID4gMCApIHtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoICEodW5tYXRjaGVkW2ldIHx8IHNldE1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRcdHNldE1hdGNoZWRbaV0gPSBwb3AuY2FsbCggcmVzdWx0cyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRGlzY2FyZCBpbmRleCBwbGFjZWhvbGRlciB2YWx1ZXMgdG8gZ2V0IG9ubHkgYWN0dWFsIG1hdGNoZXNcblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBtYXRjaGVzIHRvIHJlc3VsdHNcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2V0TWF0Y2hlZCApO1xuXG5cdFx0XHRcdC8vIFNlZWRsZXNzIHNldCBtYXRjaGVzIHN1Y2NlZWRpbmcgbXVsdGlwbGUgc3VjY2Vzc2Z1bCBtYXRjaGVycyBzdGlwdWxhdGUgc29ydGluZ1xuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gT3ZlcnJpZGUgbWFuaXB1bGF0aW9uIG9mIGdsb2JhbHMgYnkgbmVzdGVkIG1hdGNoZXJzXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0QmFja3VwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdW5tYXRjaGVkO1xuXHRcdH07XG5cblx0cmV0dXJuIGJ5U2V0ID9cblx0XHRtYXJrRnVuY3Rpb24oIHN1cGVyTWF0Y2hlciApIDpcblx0XHRzdXBlck1hdGNoZXI7XG59XG5cbmNvbXBpbGUgPSBTaXp6bGUuY29tcGlsZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgbWF0Y2ggLyogSW50ZXJuYWwgVXNlIE9ubHkgKi8gKSB7XG5cdHZhciBpLFxuXHRcdHNldE1hdGNoZXJzID0gW10sXG5cdFx0ZWxlbWVudE1hdGNoZXJzID0gW10sXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggIWNhY2hlZCApIHtcblx0XHQvLyBHZW5lcmF0ZSBhIGZ1bmN0aW9uIG9mIHJlY3Vyc2l2ZSBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBjaGVjayBlYWNoIGVsZW1lbnRcblx0XHRpZiAoICFtYXRjaCApIHtcblx0XHRcdG1hdGNoID0gdG9rZW5pemUoIHNlbGVjdG9yICk7XG5cdFx0fVxuXHRcdGkgPSBtYXRjaC5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRjYWNoZWQgPSBtYXRjaGVyRnJvbVRva2VucyggbWF0Y2hbaV0gKTtcblx0XHRcdGlmICggY2FjaGVkWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdHNldE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENhY2hlIHRoZSBjb21waWxlZCBmdW5jdGlvblxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGUoIHNlbGVjdG9yLCBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSApO1xuXG5cdFx0Ly8gU2F2ZSBzZWxlY3RvciBhbmQgdG9rZW5pemF0aW9uXG5cdFx0Y2FjaGVkLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdH1cblx0cmV0dXJuIGNhY2hlZDtcbn07XG5cbi8qKlxuICogQSBsb3ctbGV2ZWwgc2VsZWN0aW9uIGZ1bmN0aW9uIHRoYXQgd29ya3Mgd2l0aCBTaXp6bGUncyBjb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHNlbGVjdG9yIEEgc2VsZWN0b3Igb3IgYSBwcmUtY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbiBidWlsdCB3aXRoIFNpenpsZS5jb21waWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHRzXVxuICogQHBhcmFtIHtBcnJheX0gW3NlZWRdIEEgc2V0IG9mIGVsZW1lbnRzIHRvIG1hdGNoIGFnYWluc3RcbiAqL1xuc2VsZWN0ID0gU2l6emxlLnNlbGVjdCA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIGksIHRva2VucywgdG9rZW4sIHR5cGUsIGZpbmQsXG5cdFx0Y29tcGlsZWQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiAmJiBzZWxlY3Rvcixcblx0XHRtYXRjaCA9ICFzZWVkICYmIHRva2VuaXplKCAoc2VsZWN0b3IgPSBjb21waWxlZC5zZWxlY3RvciB8fCBzZWxlY3RvcikgKTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBUcnkgdG8gbWluaW1pemUgb3BlcmF0aW9ucyBpZiB0aGVyZSBpcyBvbmx5IG9uZSBzZWxlY3RvciBpbiB0aGUgbGlzdCBhbmQgbm8gc2VlZFxuXHQvLyAodGhlIGxhdHRlciBvZiB3aGljaCBndWFyYW50ZWVzIHVzIGNvbnRleHQpXG5cdGlmICggbWF0Y2gubGVuZ3RoID09PSAxICkge1xuXG5cdFx0Ly8gUmVkdWNlIGNvbnRleHQgaWYgdGhlIGxlYWRpbmcgY29tcG91bmQgc2VsZWN0b3IgaXMgYW4gSURcblx0XHR0b2tlbnMgPSBtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwICk7XG5cdFx0aWYgKCB0b2tlbnMubGVuZ3RoID4gMiAmJiAodG9rZW4gPSB0b2tlbnNbMF0pLnR5cGUgPT09IFwiSURcIiAmJlxuXHRcdFx0XHRjb250ZXh0Lm5vZGVUeXBlID09PSA5ICYmIGRvY3VtZW50SXNIVE1MICYmIEV4cHIucmVsYXRpdmVbIHRva2Vuc1sxXS50eXBlIF0gKSB7XG5cblx0XHRcdGNvbnRleHQgPSAoIEV4cHIuZmluZFtcIklEXCJdKCB0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UocnVuZXNjYXBlLCBmdW5lc2NhcGUpLCBjb250ZXh0ICkgfHwgW10gKVswXTtcblx0XHRcdGlmICggIWNvbnRleHQgKSB7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXG5cdFx0XHQvLyBQcmVjb21waWxlZCBtYXRjaGVycyB3aWxsIHN0aWxsIHZlcmlmeSBhbmNlc3RyeSwgc28gc3RlcCB1cCBhIGxldmVsXG5cdFx0XHR9IGVsc2UgaWYgKCBjb21waWxlZCApIHtcblx0XHRcdFx0Y29udGV4dCA9IGNvbnRleHQucGFyZW50Tm9kZTtcblx0XHRcdH1cblxuXHRcdFx0c2VsZWN0b3IgPSBzZWxlY3Rvci5zbGljZSggdG9rZW5zLnNoaWZ0KCkudmFsdWUubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmV0Y2ggYSBzZWVkIHNldCBmb3IgcmlnaHQtdG8tbGVmdCBtYXRjaGluZ1xuXHRcdGkgPSBtYXRjaEV4cHJbXCJuZWVkc0NvbnRleHRcIl0udGVzdCggc2VsZWN0b3IgKSA/IDAgOiB0b2tlbnMubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG9rZW4gPSB0b2tlbnNbaV07XG5cblx0XHRcdC8vIEFib3J0IGlmIHdlIGhpdCBhIGNvbWJpbmF0b3Jcblx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgKHR5cGUgPSB0b2tlbi50eXBlKSBdICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggKGZpbmQgPSBFeHByLmZpbmRbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdC8vIFNlYXJjaCwgZXhwYW5kaW5nIGNvbnRleHQgZm9yIGxlYWRpbmcgc2libGluZyBjb21iaW5hdG9yc1xuXHRcdFx0XHRpZiAoIChzZWVkID0gZmluZChcblx0XHRcdFx0XHR0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICksXG5cdFx0XHRcdFx0cnNpYmxpbmcudGVzdCggdG9rZW5zWzBdLnR5cGUgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHRcdFx0XHQpKSApIHtcblxuXHRcdFx0XHRcdC8vIElmIHNlZWQgaXMgZW1wdHkgb3Igbm8gdG9rZW5zIHJlbWFpbiwgd2UgY2FuIHJldHVybiBlYXJseVxuXHRcdFx0XHRcdHRva2Vucy5zcGxpY2UoIGksIDEgKTtcblx0XHRcdFx0XHRzZWxlY3RvciA9IHNlZWQubGVuZ3RoICYmIHRvU2VsZWN0b3IoIHRva2VucyApO1xuXHRcdFx0XHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2VlZCApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDb21waWxlIGFuZCBleGVjdXRlIGEgZmlsdGVyaW5nIGZ1bmN0aW9uIGlmIG9uZSBpcyBub3QgcHJvdmlkZWRcblx0Ly8gUHJvdmlkZSBgbWF0Y2hgIHRvIGF2b2lkIHJldG9rZW5pemF0aW9uIGlmIHdlIG1vZGlmaWVkIHRoZSBzZWxlY3RvciBhYm92ZVxuXHQoIGNvbXBpbGVkIHx8IGNvbXBpbGUoIHNlbGVjdG9yLCBtYXRjaCApICkoXG5cdFx0c2VlZCxcblx0XHRjb250ZXh0LFxuXHRcdCFkb2N1bWVudElzSFRNTCxcblx0XHRyZXN1bHRzLFxuXHRcdCFjb250ZXh0IHx8IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHRcblx0KTtcblx0cmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vLyBPbmUtdGltZSBhc3NpZ25tZW50c1xuXG4vLyBTb3J0IHN0YWJpbGl0eVxuc3VwcG9ydC5zb3J0U3RhYmxlID0gZXhwYW5kby5zcGxpdChcIlwiKS5zb3J0KCBzb3J0T3JkZXIgKS5qb2luKFwiXCIpID09PSBleHBhbmRvO1xuXG4vLyBTdXBwb3J0OiBDaHJvbWUgMTQtMzUrXG4vLyBBbHdheXMgYXNzdW1lIGR1cGxpY2F0ZXMgaWYgdGhleSBhcmVuJ3QgcGFzc2VkIHRvIHRoZSBjb21wYXJpc29uIGZ1bmN0aW9uXG5zdXBwb3J0LmRldGVjdER1cGxpY2F0ZXMgPSAhIWhhc0R1cGxpY2F0ZTtcblxuLy8gSW5pdGlhbGl6ZSBhZ2FpbnN0IHRoZSBkZWZhdWx0IGRvY3VtZW50XG5zZXREb2N1bWVudCgpO1xuXG4vLyBTdXBwb3J0OiBXZWJraXQ8NTM3LjMyIC0gU2FmYXJpIDYuMC4zL0Nocm9tZSAyNSAoZml4ZWQgaW4gQ2hyb21lIDI3KVxuLy8gRGV0YWNoZWQgbm9kZXMgY29uZm91bmRpbmdseSBmb2xsb3cgKmVhY2ggb3RoZXIqXG5zdXBwb3J0LnNvcnREZXRhY2hlZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdC8vIFNob3VsZCByZXR1cm4gMSwgYnV0IHJldHVybnMgNCAoZm9sbG93aW5nKVxuXHRyZXR1cm4gZWwuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJmaWVsZHNldFwiKSApICYgMTtcbn0pO1xuXG4vLyBTdXBwb3J0OiBJRTw4XG4vLyBQcmV2ZW50IGF0dHJpYnV0ZS9wcm9wZXJ0eSBcImludGVycG9sYXRpb25cIlxuLy8gaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNjQyOSUyOFZTLjg1JTI5LmFzcHhcbmlmICggIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGEgaHJlZj0nIyc+PC9hPlwiO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZGVmYXVsdFZhbHVlIGluIHBsYWNlIG9mIGdldEF0dHJpYnV0ZShcInZhbHVlXCIpXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGlucHV0Lz5cIjtcblx0ZWwuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiApID09PSBcIlwiO1xufSkgKSB7XG5cdGFkZEhhbmRsZSggXCJ2YWx1ZVwiLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0aWYgKCAhaXNYTUwgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlucHV0XCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kZWZhdWx0VmFsdWU7XG5cdFx0fVxuXHR9KTtcbn1cblxuLy8gU3VwcG9ydDogSUU8OVxuLy8gVXNlIGdldEF0dHJpYnV0ZU5vZGUgdG8gZmV0Y2ggYm9vbGVhbnMgd2hlbiBnZXRBdHRyaWJ1dGUgbGllc1xuaWYgKCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0cmV0dXJuIGVsLmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxucmV0dXJuIFNpenpsZTtcblxufSkoIHdpbmRvdyApO1xuXG5cblxualF1ZXJ5LmZpbmQgPSBTaXp6bGU7XG5qUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7XG5cbi8vIERlcHJlY2F0ZWRcbmpRdWVyeS5leHByWyBcIjpcIiBdID0galF1ZXJ5LmV4cHIucHNldWRvcztcbmpRdWVyeS51bmlxdWVTb3J0ID0galF1ZXJ5LnVuaXF1ZSA9IFNpenpsZS51bmlxdWVTb3J0O1xualF1ZXJ5LnRleHQgPSBTaXp6bGUuZ2V0VGV4dDtcbmpRdWVyeS5pc1hNTERvYyA9IFNpenpsZS5pc1hNTDtcbmpRdWVyeS5jb250YWlucyA9IFNpenpsZS5jb250YWlucztcbmpRdWVyeS5lc2NhcGVTZWxlY3RvciA9IFNpenpsZS5lc2NhcGU7XG5cblxuXG5cbnZhciBkaXIgPSBmdW5jdGlvbiggZWxlbSwgZGlyLCB1bnRpbCApIHtcblx0dmFyIG1hdGNoZWQgPSBbXSxcblx0XHR0cnVuY2F0ZSA9IHVudGlsICE9PSB1bmRlZmluZWQ7XG5cblx0d2hpbGUgKCAoIGVsZW0gPSBlbGVtWyBkaXIgXSApICYmIGVsZW0ubm9kZVR5cGUgIT09IDkgKSB7XG5cdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0aWYgKCB0cnVuY2F0ZSAmJiBqUXVlcnkoIGVsZW0gKS5pcyggdW50aWwgKSApIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG1hdGNoZWQ7XG59O1xuXG5cbnZhciBzaWJsaW5ncyA9IGZ1bmN0aW9uKCBuLCBlbGVtICkge1xuXHR2YXIgbWF0Y2hlZCA9IFtdO1xuXG5cdGZvciAoIDsgbjsgbiA9IG4ubmV4dFNpYmxpbmcgKSB7XG5cdFx0aWYgKCBuLm5vZGVUeXBlID09PSAxICYmIG4gIT09IGVsZW0gKSB7XG5cdFx0XHRtYXRjaGVkLnB1c2goIG4gKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbWF0Y2hlZDtcbn07XG5cblxudmFyIHJuZWVkc0NvbnRleHQgPSBqUXVlcnkuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQ7XG5cblxuXG5mdW5jdGlvbiBub2RlTmFtZSggZWxlbSwgbmFtZSApIHtcblxuICByZXR1cm4gZWxlbS5ub2RlTmFtZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUudG9Mb3dlckNhc2UoKTtcblxufTtcbnZhciByc2luZ2xlVGFnID0gKCAvXjwoW2Etel1bXlxcL1xcMD46XFx4MjBcXHRcXHJcXG5cXGZdKilbXFx4MjBcXHRcXHJcXG5cXGZdKlxcLz8+KD86PFxcL1xcMT58KSQvaSApO1xuXG5cblxudmFyIHJpc1NpbXBsZSA9IC9eLlteOiNcXFtcXC4sXSokLztcblxuLy8gSW1wbGVtZW50IHRoZSBpZGVudGljYWwgZnVuY3Rpb25hbGl0eSBmb3IgZmlsdGVyIGFuZCBub3RcbmZ1bmN0aW9uIHdpbm5vdyggZWxlbWVudHMsIHF1YWxpZmllciwgbm90ICkge1xuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiAhIXF1YWxpZmllci5jYWxsKCBlbGVtLCBpLCBlbGVtICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBTaW5nbGUgZWxlbWVudFxuXHRpZiAoIHF1YWxpZmllci5ub2RlVHlwZSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGVsZW0gPT09IHF1YWxpZmllciApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gQXJyYXlsaWtlIG9mIGVsZW1lbnRzIChqUXVlcnksIGFyZ3VtZW50cywgQXJyYXkpXG5cdGlmICggdHlwZW9mIHF1YWxpZmllciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gU2ltcGxlIHNlbGVjdG9yIHRoYXQgY2FuIGJlIGZpbHRlcmVkIGRpcmVjdGx5LCByZW1vdmluZyBub24tRWxlbWVudHNcblx0aWYgKCByaXNTaW1wbGUudGVzdCggcXVhbGlmaWVyICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5maWx0ZXIoIHF1YWxpZmllciwgZWxlbWVudHMsIG5vdCApO1xuXHR9XG5cblx0Ly8gQ29tcGxleCBzZWxlY3RvciwgY29tcGFyZSB0aGUgdHdvIHNldHMsIHJlbW92aW5nIG5vbi1FbGVtZW50c1xuXHRxdWFsaWZpZXIgPSBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzICk7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3QgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMTtcblx0fSApO1xufVxuXG5qUXVlcnkuZmlsdGVyID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1zLCBub3QgKSB7XG5cdHZhciBlbGVtID0gZWxlbXNbIDAgXTtcblxuXHRpZiAoIG5vdCApIHtcblx0XHRleHByID0gXCI6bm90KFwiICsgZXhwciArIFwiKVwiO1xuXHR9XG5cblx0aWYgKCBlbGVtcy5sZW5ndGggPT09IDEgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBlbGVtLCBleHByICkgPyBbIGVsZW0gXSA6IFtdO1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeS5maW5kLm1hdGNoZXMoIGV4cHIsIGpRdWVyeS5ncmVwKCBlbGVtcywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7XG5cdH0gKSApO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmaW5kOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dmFyIGksIHJldCxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0c2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5KCBzZWxlY3RvciApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHNlbGZbIGkgXSwgdGhpcyApICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICkgKTtcblx0XHR9XG5cblx0XHRyZXQgPSB0aGlzLnB1c2hTdGFjayggW10gKTtcblxuXHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRqUXVlcnkuZmluZCggc2VsZWN0b3IsIHNlbGZbIGkgXSwgcmV0ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGxlbiA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggcmV0ICkgOiByZXQ7XG5cdH0sXG5cdGZpbHRlcjogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KCB0aGlzLCBzZWxlY3RvciB8fCBbXSwgZmFsc2UgKSApO1xuXHR9LFxuXHRub3Q6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHdpbm5vdyggdGhpcywgc2VsZWN0b3IgfHwgW10sIHRydWUgKSApO1xuXHR9LFxuXHRpczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiAhIXdpbm5vdyhcblx0XHRcdHRoaXMsXG5cblx0XHRcdC8vIElmIHRoaXMgaXMgYSBwb3NpdGlvbmFsL3JlbGF0aXZlIHNlbGVjdG9yLCBjaGVjayBtZW1iZXJzaGlwIGluIHRoZSByZXR1cm5lZCBzZXRcblx0XHRcdC8vIHNvICQoXCJwOmZpcnN0XCIpLmlzKFwicDpsYXN0XCIpIHdvbid0IHJldHVybiB0cnVlIGZvciBhIGRvYyB3aXRoIHR3byBcInBcIi5cblx0XHRcdHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiAmJiBybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICkgP1xuXHRcdFx0XHRqUXVlcnkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHRzZWxlY3RvciB8fCBbXSxcblx0XHRcdGZhbHNlXG5cdFx0KS5sZW5ndGg7XG5cdH1cbn0gKTtcblxuXG4vLyBJbml0aWFsaXplIGEgalF1ZXJ5IG9iamVjdFxuXG5cbi8vIEEgY2VudHJhbCByZWZlcmVuY2UgdG8gdGhlIHJvb3QgalF1ZXJ5KGRvY3VtZW50KVxudmFyIHJvb3RqUXVlcnksXG5cblx0Ly8gQSBzaW1wbGUgd2F5IHRvIGNoZWNrIGZvciBIVE1MIHN0cmluZ3Ncblx0Ly8gUHJpb3JpdGl6ZSAjaWQgb3ZlciA8dGFnPiB0byBhdm9pZCBYU1MgdmlhIGxvY2F0aW9uLmhhc2ggKCM5NTIxKVxuXHQvLyBTdHJpY3QgSFRNTCByZWNvZ25pdGlvbiAoIzExMjkwOiBtdXN0IHN0YXJ0IHdpdGggPClcblx0Ly8gU2hvcnRjdXQgc2ltcGxlICNpZCBjYXNlIGZvciBzcGVlZFxuXHRycXVpY2tFeHByID0gL14oPzpcXHMqKDxbXFx3XFxXXSs+KVtePl0qfCMoW1xcdy1dKykpJC8sXG5cblx0aW5pdCA9IGpRdWVyeS5mbi5pbml0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0LCByb290ICkge1xuXHRcdHZhciBtYXRjaCwgZWxlbTtcblxuXHRcdC8vIEhBTkRMRTogJChcIlwiKSwgJChudWxsKSwgJCh1bmRlZmluZWQpLCAkKGZhbHNlKVxuXHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Ly8gTWV0aG9kIGluaXQoKSBhY2NlcHRzIGFuIGFsdGVybmF0ZSByb290alF1ZXJ5XG5cdFx0Ly8gc28gbWlncmF0ZSBjYW4gc3VwcG9ydCBqUXVlcnkuc3ViIChnaC0yMTAxKVxuXHRcdHJvb3QgPSByb290IHx8IHJvb3RqUXVlcnk7XG5cblx0XHQvLyBIYW5kbGUgSFRNTCBzdHJpbmdzXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRpZiAoIHNlbGVjdG9yWyAwIF0gPT09IFwiPFwiICYmXG5cdFx0XHRcdHNlbGVjdG9yWyBzZWxlY3Rvci5sZW5ndGggLSAxIF0gPT09IFwiPlwiICYmXG5cdFx0XHRcdHNlbGVjdG9yLmxlbmd0aCA+PSAzICkge1xuXG5cdFx0XHRcdC8vIEFzc3VtZSB0aGF0IHN0cmluZ3MgdGhhdCBzdGFydCBhbmQgZW5kIHdpdGggPD4gYXJlIEhUTUwgYW5kIHNraXAgdGhlIHJlZ2V4IGNoZWNrXG5cdFx0XHRcdG1hdGNoID0gWyBudWxsLCBzZWxlY3RvciwgbnVsbCBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXRjaCA9IHJxdWlja0V4cHIuZXhlYyggc2VsZWN0b3IgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWF0Y2ggaHRtbCBvciBtYWtlIHN1cmUgbm8gY29udGV4dCBpcyBzcGVjaWZpZWQgZm9yICNpZFxuXHRcdFx0aWYgKCBtYXRjaCAmJiAoIG1hdGNoWyAxIF0gfHwgIWNvbnRleHQgKSApIHtcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCkgLT4gJChhcnJheSlcblx0XHRcdFx0aWYgKCBtYXRjaFsgMSBdICkge1xuXHRcdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgalF1ZXJ5ID8gY29udGV4dFsgMCBdIDogY29udGV4dDtcblxuXHRcdFx0XHRcdC8vIE9wdGlvbiB0byBydW4gc2NyaXB0cyBpcyB0cnVlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRcdC8vIEludGVudGlvbmFsbHkgbGV0IHRoZSBlcnJvciBiZSB0aHJvd24gaWYgcGFyc2VIVE1MIGlzIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLCBqUXVlcnkucGFyc2VIVE1MKFxuXHRcdFx0XHRcdFx0bWF0Y2hbIDEgXSxcblx0XHRcdFx0XHRcdGNvbnRleHQgJiYgY29udGV4dC5ub2RlVHlwZSA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogZG9jdW1lbnQsXG5cdFx0XHRcdFx0XHR0cnVlXG5cdFx0XHRcdFx0KSApO1xuXG5cdFx0XHRcdFx0Ly8gSEFORExFOiAkKGh0bWwsIHByb3BzKVxuXHRcdFx0XHRcdGlmICggcnNpbmdsZVRhZy50ZXN0KCBtYXRjaFsgMSBdICkgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGNvbnRleHQgKSApIHtcblx0XHRcdFx0XHRcdGZvciAoIG1hdGNoIGluIGNvbnRleHQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gUHJvcGVydGllcyBvZiBjb250ZXh0IGFyZSBjYWxsZWQgYXMgbWV0aG9kcyBpZiBwb3NzaWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB0aGlzWyBtYXRjaCBdICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpc1sgbWF0Y2ggXSggY29udGV4dFsgbWF0Y2ggXSApO1xuXG5cdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBvdGhlcndpc2Ugc2V0IGFzIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmF0dHIoIG1hdGNoLCBjb250ZXh0WyBtYXRjaCBdICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoI2lkKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggbWF0Y2hbIDIgXSApO1xuXG5cdFx0XHRcdFx0aWYgKCBlbGVtICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJbmplY3QgdGhlIGVsZW1lbnQgZGlyZWN0bHkgaW50byB0aGUgalF1ZXJ5IG9iamVjdFxuXHRcdFx0XHRcdFx0dGhpc1sgMCBdID0gZWxlbTtcblx0XHRcdFx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gSEFORExFOiAkKGV4cHIsICQoLi4uKSlcblx0XHRcdH0gZWxzZSBpZiAoICFjb250ZXh0IHx8IGNvbnRleHQuanF1ZXJ5ICkge1xuXHRcdFx0XHRyZXR1cm4gKCBjb250ZXh0IHx8IHJvb3QgKS5maW5kKCBzZWxlY3RvciApO1xuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgY29udGV4dClcblx0XHRcdC8vICh3aGljaCBpcyBqdXN0IGVxdWl2YWxlbnQgdG86ICQoY29udGV4dCkuZmluZChleHByKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29uc3RydWN0b3IoIGNvbnRleHQgKS5maW5kKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0Ly8gSEFORExFOiAkKERPTUVsZW1lbnQpXG5cdFx0fSBlbHNlIGlmICggc2VsZWN0b3Iubm9kZVR5cGUgKSB7XG5cdFx0XHR0aGlzWyAwIF0gPSBzZWxlY3Rvcjtcblx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0Ly8gSEFORExFOiAkKGZ1bmN0aW9uKVxuXHRcdC8vIFNob3J0Y3V0IGZvciBkb2N1bWVudCByZWFkeVxuXHRcdH0gZWxzZSBpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBzZWxlY3RvciApICkge1xuXHRcdFx0cmV0dXJuIHJvb3QucmVhZHkgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdHJvb3QucmVhZHkoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIEV4ZWN1dGUgaW1tZWRpYXRlbHkgaWYgcmVhZHkgaXMgbm90IHByZXNlbnRcblx0XHRcdFx0c2VsZWN0b3IoIGpRdWVyeSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciwgdGhpcyApO1xuXHR9O1xuXG4vLyBHaXZlIHRoZSBpbml0IGZ1bmN0aW9uIHRoZSBqUXVlcnkgcHJvdG90eXBlIGZvciBsYXRlciBpbnN0YW50aWF0aW9uXG5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjtcblxuLy8gSW5pdGlhbGl6ZSBjZW50cmFsIHJlZmVyZW5jZVxucm9vdGpRdWVyeSA9IGpRdWVyeSggZG9jdW1lbnQgKTtcblxuXG52YXIgcnBhcmVudHNwcmV2ID0gL14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sXG5cblx0Ly8gTWV0aG9kcyBndWFyYW50ZWVkIHRvIHByb2R1Y2UgYSB1bmlxdWUgc2V0IHdoZW4gc3RhcnRpbmcgZnJvbSBhIHVuaXF1ZSBzZXRcblx0Z3VhcmFudGVlZFVuaXF1ZSA9IHtcblx0XHRjaGlsZHJlbjogdHJ1ZSxcblx0XHRjb250ZW50czogdHJ1ZSxcblx0XHRuZXh0OiB0cnVlLFxuXHRcdHByZXY6IHRydWVcblx0fTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRoYXM6IGZ1bmN0aW9uKCB0YXJnZXQgKSB7XG5cdFx0dmFyIHRhcmdldHMgPSBqUXVlcnkoIHRhcmdldCwgdGhpcyApLFxuXHRcdFx0bCA9IHRhcmdldHMubGVuZ3RoO1xuXG5cdFx0cmV0dXJuIHRoaXMuZmlsdGVyKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpID0gMDtcblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHRoaXMsIHRhcmdldHNbIGkgXSApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGNsb3Nlc3Q6IGZ1bmN0aW9uKCBzZWxlY3RvcnMsIGNvbnRleHQgKSB7XG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0bWF0Y2hlZCA9IFtdLFxuXHRcdFx0dGFyZ2V0cyA9IHR5cGVvZiBzZWxlY3RvcnMgIT09IFwic3RyaW5nXCIgJiYgalF1ZXJ5KCBzZWxlY3RvcnMgKTtcblxuXHRcdC8vIFBvc2l0aW9uYWwgc2VsZWN0b3JzIG5ldmVyIG1hdGNoLCBzaW5jZSB0aGVyZSdzIG5vIF9zZWxlY3Rpb25fIGNvbnRleHRcblx0XHRpZiAoICFybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9ycyApICkge1xuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRmb3IgKCBjdXIgPSB0aGlzWyBpIF07IGN1ciAmJiBjdXIgIT09IGNvbnRleHQ7IGN1ciA9IGN1ci5wYXJlbnROb2RlICkge1xuXG5cdFx0XHRcdFx0Ly8gQWx3YXlzIHNraXAgZG9jdW1lbnQgZnJhZ21lbnRzXG5cdFx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPCAxMSAmJiAoIHRhcmdldHMgP1xuXHRcdFx0XHRcdFx0dGFyZ2V0cy5pbmRleCggY3VyICkgPiAtMSA6XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IHBhc3Mgbm9uLWVsZW1lbnRzIHRvIFNpenpsZVxuXHRcdFx0XHRcdFx0Y3VyLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kLm1hdGNoZXNTZWxlY3RvciggY3VyLCBzZWxlY3RvcnMgKSApICkge1xuXG5cdFx0XHRcdFx0XHRtYXRjaGVkLnB1c2goIGN1ciApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBtYXRjaGVkLmxlbmd0aCA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApIDogbWF0Y2hlZCApO1xuXHR9LFxuXG5cdC8vIERldGVybWluZSB0aGUgcG9zaXRpb24gb2YgYW4gZWxlbWVudCB3aXRoaW4gdGhlIHNldFxuXHRpbmRleDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHQvLyBObyBhcmd1bWVudCwgcmV0dXJuIGluZGV4IGluIHBhcmVudFxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gKCB0aGlzWyAwIF0gJiYgdGhpc1sgMCBdLnBhcmVudE5vZGUgKSA/IHRoaXMuZmlyc3QoKS5wcmV2QWxsKCkubGVuZ3RoIDogLTE7XG5cdFx0fVxuXG5cdFx0Ly8gSW5kZXggaW4gc2VsZWN0b3Jcblx0XHRpZiAoIHR5cGVvZiBlbGVtID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggalF1ZXJ5KCBlbGVtICksIHRoaXNbIDAgXSApO1xuXHRcdH1cblxuXHRcdC8vIExvY2F0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGRlc2lyZWQgZWxlbWVudFxuXHRcdHJldHVybiBpbmRleE9mLmNhbGwoIHRoaXMsXG5cblx0XHRcdC8vIElmIGl0IHJlY2VpdmVzIGEgalF1ZXJ5IG9iamVjdCwgdGhlIGZpcnN0IGVsZW1lbnQgaXMgdXNlZFxuXHRcdFx0ZWxlbS5qcXVlcnkgPyBlbGVtWyAwIF0gOiBlbGVtXG5cdFx0KTtcblx0fSxcblxuXHRhZGQ6IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soXG5cdFx0XHRqUXVlcnkudW5pcXVlU29ydChcblx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLmdldCgpLCBqUXVlcnkoIHNlbGVjdG9yLCBjb250ZXh0ICkgKVxuXHRcdFx0KVxuXHRcdCk7XG5cdH0sXG5cblx0YWRkQmFjazogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLmFkZCggc2VsZWN0b3IgPT0gbnVsbCA/XG5cdFx0XHR0aGlzLnByZXZPYmplY3QgOiB0aGlzLnByZXZPYmplY3QuZmlsdGVyKCBzZWxlY3RvciApXG5cdFx0KTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBzaWJsaW5nKCBjdXIsIGRpciApIHtcblx0d2hpbGUgKCAoIGN1ciA9IGN1clsgZGlyIF0gKSAmJiBjdXIubm9kZVR5cGUgIT09IDEgKSB7fVxuXHRyZXR1cm4gY3VyO1xufVxuXG5qUXVlcnkuZWFjaCgge1xuXHRwYXJlbnQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGU7XG5cdFx0cmV0dXJuIHBhcmVudCAmJiBwYXJlbnQubm9kZVR5cGUgIT09IDExID8gcGFyZW50IDogbnVsbDtcblx0fSxcblx0cGFyZW50czogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIgKTtcblx0fSxcblx0cGFyZW50c1VudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIsIHVudGlsICk7XG5cdH0sXG5cdG5leHQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5nKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmcoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dEFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiICk7XG5cdH0sXG5cdHByZXZBbGw6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBkaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dFVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRwcmV2VW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInByZXZpb3VzU2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRzaWJsaW5nczogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmdzKCAoIGVsZW0ucGFyZW50Tm9kZSB8fCB7fSApLmZpcnN0Q2hpbGQsIGVsZW0gKTtcblx0fSxcblx0Y2hpbGRyZW46IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5ncyggZWxlbS5maXJzdENoaWxkICk7XG5cdH0sXG5cdGNvbnRlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAgICAgaWYgKCBub2RlTmFtZSggZWxlbSwgXCJpZnJhbWVcIiApICkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0uY29udGVudERvY3VtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHksIGlPUyA3IG9ubHksIEFuZHJvaWQgQnJvd3NlciA8PTQuMyBvbmx5XG4gICAgICAgIC8vIFRyZWF0IHRoZSB0ZW1wbGF0ZSBlbGVtZW50IGFzIGEgcmVndWxhciBvbmUgaW4gYnJvd3NlcnMgdGhhdFxuICAgICAgICAvLyBkb24ndCBzdXBwb3J0IGl0LlxuICAgICAgICBpZiAoIG5vZGVOYW1lKCBlbGVtLCBcInRlbXBsYXRlXCIgKSApIHtcbiAgICAgICAgICAgIGVsZW0gPSBlbGVtLmNvbnRlbnQgfHwgZWxlbTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBlbGVtLmNoaWxkTm9kZXMgKTtcblx0fVxufSwgZnVuY3Rpb24oIG5hbWUsIGZuICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCB1bnRpbCwgc2VsZWN0b3IgKSB7XG5cdFx0dmFyIG1hdGNoZWQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiwgdW50aWwgKTtcblxuXHRcdGlmICggbmFtZS5zbGljZSggLTUgKSAhPT0gXCJVbnRpbFwiICkge1xuXHRcdFx0c2VsZWN0b3IgPSB1bnRpbDtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG1hdGNoZWQgPSBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgbWF0Y2hlZCApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sZW5ndGggPiAxICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgZHVwbGljYXRlc1xuXHRcdFx0aWYgKCAhZ3VhcmFudGVlZFVuaXF1ZVsgbmFtZSBdICkge1xuXHRcdFx0XHRqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXZlcnNlIG9yZGVyIGZvciBwYXJlbnRzKiBhbmQgcHJldi1kZXJpdmF0aXZlc1xuXHRcdFx0aWYgKCBycGFyZW50c3ByZXYudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRtYXRjaGVkLnJldmVyc2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQgKTtcblx0fTtcbn0gKTtcbnZhciBybm90aHRtbHdoaXRlID0gKCAvW15cXHgyMFxcdFxcclxcblxcZl0rL2cgKTtcblxuXG5cbi8vIENvbnZlcnQgU3RyaW5nLWZvcm1hdHRlZCBvcHRpb25zIGludG8gT2JqZWN0LWZvcm1hdHRlZCBvbmVzXG5mdW5jdGlvbiBjcmVhdGVPcHRpb25zKCBvcHRpb25zICkge1xuXHR2YXIgb2JqZWN0ID0ge307XG5cdGpRdWVyeS5lYWNoKCBvcHRpb25zLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10sIGZ1bmN0aW9uKCBfLCBmbGFnICkge1xuXHRcdG9iamVjdFsgZmxhZyBdID0gdHJ1ZTtcblx0fSApO1xuXHRyZXR1cm4gb2JqZWN0O1xufVxuXG4vKlxuICogQ3JlYXRlIGEgY2FsbGJhY2sgbGlzdCB1c2luZyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gKlxuICpcdG9wdGlvbnM6IGFuIG9wdGlvbmFsIGxpc3Qgb2Ygc3BhY2Utc2VwYXJhdGVkIG9wdGlvbnMgdGhhdCB3aWxsIGNoYW5nZSBob3dcbiAqXHRcdFx0dGhlIGNhbGxiYWNrIGxpc3QgYmVoYXZlcyBvciBhIG1vcmUgdHJhZGl0aW9uYWwgb3B0aW9uIG9iamVjdFxuICpcbiAqIEJ5IGRlZmF1bHQgYSBjYWxsYmFjayBsaXN0IHdpbGwgYWN0IGxpa2UgYW4gZXZlbnQgY2FsbGJhY2sgbGlzdCBhbmQgY2FuIGJlXG4gKiBcImZpcmVkXCIgbXVsdGlwbGUgdGltZXMuXG4gKlxuICogUG9zc2libGUgb3B0aW9uczpcbiAqXG4gKlx0b25jZTpcdFx0XHR3aWxsIGVuc3VyZSB0aGUgY2FsbGJhY2sgbGlzdCBjYW4gb25seSBiZSBmaXJlZCBvbmNlIChsaWtlIGEgRGVmZXJyZWQpXG4gKlxuICpcdG1lbW9yeTpcdFx0XHR3aWxsIGtlZXAgdHJhY2sgb2YgcHJldmlvdXMgdmFsdWVzIGFuZCB3aWxsIGNhbGwgYW55IGNhbGxiYWNrIGFkZGVkXG4gKlx0XHRcdFx0XHRhZnRlciB0aGUgbGlzdCBoYXMgYmVlbiBmaXJlZCByaWdodCBhd2F5IHdpdGggdGhlIGxhdGVzdCBcIm1lbW9yaXplZFwiXG4gKlx0XHRcdFx0XHR2YWx1ZXMgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0dW5pcXVlOlx0XHRcdHdpbGwgZW5zdXJlIGEgY2FsbGJhY2sgY2FuIG9ubHkgYmUgYWRkZWQgb25jZSAobm8gZHVwbGljYXRlIGluIHRoZSBsaXN0KVxuICpcbiAqXHRzdG9wT25GYWxzZTpcdGludGVycnVwdCBjYWxsaW5ncyB3aGVuIGEgY2FsbGJhY2sgcmV0dXJucyBmYWxzZVxuICpcbiAqL1xualF1ZXJ5LkNhbGxiYWNrcyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdC8vIENvbnZlcnQgb3B0aW9ucyBmcm9tIFN0cmluZy1mb3JtYXR0ZWQgdG8gT2JqZWN0LWZvcm1hdHRlZCBpZiBuZWVkZWRcblx0Ly8gKHdlIGNoZWNrIGluIGNhY2hlIGZpcnN0KVxuXHRvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIgP1xuXHRcdGNyZWF0ZU9wdGlvbnMoIG9wdGlvbnMgKSA6XG5cdFx0alF1ZXJ5LmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgLy8gRmxhZyB0byBrbm93IGlmIGxpc3QgaXMgY3VycmVudGx5IGZpcmluZ1xuXHRcdGZpcmluZyxcblxuXHRcdC8vIExhc3QgZmlyZSB2YWx1ZSBmb3Igbm9uLWZvcmdldHRhYmxlIGxpc3RzXG5cdFx0bWVtb3J5LFxuXG5cdFx0Ly8gRmxhZyB0byBrbm93IGlmIGxpc3Qgd2FzIGFscmVhZHkgZmlyZWRcblx0XHRmaXJlZCxcblxuXHRcdC8vIEZsYWcgdG8gcHJldmVudCBmaXJpbmdcblx0XHRsb2NrZWQsXG5cblx0XHQvLyBBY3R1YWwgY2FsbGJhY2sgbGlzdFxuXHRcdGxpc3QgPSBbXSxcblxuXHRcdC8vIFF1ZXVlIG9mIGV4ZWN1dGlvbiBkYXRhIGZvciByZXBlYXRhYmxlIGxpc3RzXG5cdFx0cXVldWUgPSBbXSxcblxuXHRcdC8vIEluZGV4IG9mIGN1cnJlbnRseSBmaXJpbmcgY2FsbGJhY2sgKG1vZGlmaWVkIGJ5IGFkZC9yZW1vdmUgYXMgbmVlZGVkKVxuXHRcdGZpcmluZ0luZGV4ID0gLTEsXG5cblx0XHQvLyBGaXJlIGNhbGxiYWNrc1xuXHRcdGZpcmUgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRW5mb3JjZSBzaW5nbGUtZmlyaW5nXG5cdFx0XHRsb2NrZWQgPSBsb2NrZWQgfHwgb3B0aW9ucy5vbmNlO1xuXG5cdFx0XHQvLyBFeGVjdXRlIGNhbGxiYWNrcyBmb3IgYWxsIHBlbmRpbmcgZXhlY3V0aW9ucyxcblx0XHRcdC8vIHJlc3BlY3RpbmcgZmlyaW5nSW5kZXggb3ZlcnJpZGVzIGFuZCBydW50aW1lIGNoYW5nZXNcblx0XHRcdGZpcmVkID0gZmlyaW5nID0gdHJ1ZTtcblx0XHRcdGZvciAoIDsgcXVldWUubGVuZ3RoOyBmaXJpbmdJbmRleCA9IC0xICkge1xuXHRcdFx0XHRtZW1vcnkgPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHR3aGlsZSAoICsrZmlyaW5nSW5kZXggPCBsaXN0Lmxlbmd0aCApIHtcblxuXHRcdFx0XHRcdC8vIFJ1biBjYWxsYmFjayBhbmQgY2hlY2sgZm9yIGVhcmx5IHRlcm1pbmF0aW9uXG5cdFx0XHRcdFx0aWYgKCBsaXN0WyBmaXJpbmdJbmRleCBdLmFwcGx5KCBtZW1vcnlbIDAgXSwgbWVtb3J5WyAxIF0gKSA9PT0gZmFsc2UgJiZcblx0XHRcdFx0XHRcdG9wdGlvbnMuc3RvcE9uRmFsc2UgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEp1bXAgdG8gZW5kIGFuZCBmb3JnZXQgdGhlIGRhdGEgc28gLmFkZCBkb2Vzbid0IHJlLWZpcmVcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRcdFx0XHRtZW1vcnkgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gRm9yZ2V0IHRoZSBkYXRhIGlmIHdlJ3JlIGRvbmUgd2l0aCBpdFxuXHRcdFx0aWYgKCAhb3B0aW9ucy5tZW1vcnkgKSB7XG5cdFx0XHRcdG1lbW9yeSA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRmaXJpbmcgPSBmYWxzZTtcblxuXHRcdFx0Ly8gQ2xlYW4gdXAgaWYgd2UncmUgZG9uZSBmaXJpbmcgZm9yIGdvb2Rcblx0XHRcdGlmICggbG9ja2VkICkge1xuXG5cdFx0XHRcdC8vIEtlZXAgYW4gZW1wdHkgbGlzdCBpZiB3ZSBoYXZlIGRhdGEgZm9yIGZ1dHVyZSBhZGQgY2FsbHNcblx0XHRcdFx0aWYgKCBtZW1vcnkgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IFtdO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSwgdGhpcyBvYmplY3QgaXMgc3BlbnRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsaXN0ID0gXCJcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvLyBBY3R1YWwgQ2FsbGJhY2tzIG9iamVjdFxuXHRcdHNlbGYgPSB7XG5cblx0XHRcdC8vIEFkZCBhIGNhbGxiYWNrIG9yIGEgY29sbGVjdGlvbiBvZiBjYWxsYmFja3MgdG8gdGhlIGxpc3Rcblx0XHRcdGFkZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblxuXHRcdFx0XHRcdC8vIElmIHdlIGhhdmUgbWVtb3J5IGZyb20gYSBwYXN0IHJ1biwgd2Ugc2hvdWxkIGZpcmUgYWZ0ZXIgYWRkaW5nXG5cdFx0XHRcdFx0aWYgKCBtZW1vcnkgJiYgIWZpcmluZyApIHtcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGggLSAxO1xuXHRcdFx0XHRcdFx0cXVldWUucHVzaCggbWVtb3J5ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0KCBmdW5jdGlvbiBhZGQoIGFyZ3MgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZWFjaCggYXJncywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYXJnICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhb3B0aW9ucy51bmlxdWUgfHwgIXNlbGYuaGFzKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGxpc3QucHVzaCggYXJnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBhcmcgJiYgYXJnLmxlbmd0aCAmJiBqUXVlcnkudHlwZSggYXJnICkgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBJbnNwZWN0IHJlY3Vyc2l2ZWx5XG5cdFx0XHRcdFx0XHRcdFx0YWRkKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gKSggYXJndW1lbnRzICk7XG5cblx0XHRcdFx0XHRpZiAoIG1lbW9yeSAmJiAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIFJlbW92ZSBhIGNhbGxiYWNrIGZyb20gdGhlIGxpc3Rcblx0XHRcdHJlbW92ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBfLCBhcmcgKSB7XG5cdFx0XHRcdFx0dmFyIGluZGV4O1xuXHRcdFx0XHRcdHdoaWxlICggKCBpbmRleCA9IGpRdWVyeS5pbkFycmF5KCBhcmcsIGxpc3QsIGluZGV4ICkgKSA+IC0xICkge1xuXHRcdFx0XHRcdFx0bGlzdC5zcGxpY2UoIGluZGV4LCAxICk7XG5cblx0XHRcdFx0XHRcdC8vIEhhbmRsZSBmaXJpbmcgaW5kZXhlc1xuXHRcdFx0XHRcdFx0aWYgKCBpbmRleCA8PSBmaXJpbmdJbmRleCApIHtcblx0XHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXgtLTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDaGVjayBpZiBhIGdpdmVuIGNhbGxiYWNrIGlzIGluIHRoZSBsaXN0LlxuXHRcdFx0Ly8gSWYgbm8gYXJndW1lbnQgaXMgZ2l2ZW4sIHJldHVybiB3aGV0aGVyIG9yIG5vdCBsaXN0IGhhcyBjYWxsYmFja3MgYXR0YWNoZWQuXG5cdFx0XHRoYXM6IGZ1bmN0aW9uKCBmbiApIHtcblx0XHRcdFx0cmV0dXJuIGZuID9cblx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggZm4sIGxpc3QgKSA+IC0xIDpcblx0XHRcdFx0XHRsaXN0Lmxlbmd0aCA+IDA7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBSZW1vdmUgYWxsIGNhbGxiYWNrcyBmcm9tIHRoZSBsaXN0XG5cdFx0XHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblx0XHRcdFx0XHRsaXN0ID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBEaXNhYmxlIC5maXJlIGFuZCAuYWRkXG5cdFx0XHQvLyBBYm9ydCBhbnkgY3VycmVudC9wZW5kaW5nIGV4ZWN1dGlvbnNcblx0XHRcdC8vIENsZWFyIGFsbCBjYWxsYmFja3MgYW5kIHZhbHVlc1xuXHRcdFx0ZGlzYWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGxvY2tlZCA9IHF1ZXVlID0gW107XG5cdFx0XHRcdGxpc3QgPSBtZW1vcnkgPSBcIlwiO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHRkaXNhYmxlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhbGlzdDtcblx0XHRcdH0sXG5cblx0XHRcdC8vIERpc2FibGUgLmZpcmVcblx0XHRcdC8vIEFsc28gZGlzYWJsZSAuYWRkIHVubGVzcyB3ZSBoYXZlIG1lbW9yeSAoc2luY2UgaXQgd291bGQgaGF2ZSBubyBlZmZlY3QpXG5cdFx0XHQvLyBBYm9ydCBhbnkgcGVuZGluZyBleGVjdXRpb25zXG5cdFx0XHRsb2NrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0bG9ja2VkID0gcXVldWUgPSBbXTtcblx0XHRcdFx0aWYgKCAhbWVtb3J5ICYmICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IG1lbW9yeSA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0bG9ja2VkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICEhbG9ja2VkO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhbGwgY2FsbGJhY2tzIHdpdGggdGhlIGdpdmVuIGNvbnRleHQgYW5kIGFyZ3VtZW50c1xuXHRcdFx0ZmlyZVdpdGg6IGZ1bmN0aW9uKCBjb250ZXh0LCBhcmdzICkge1xuXHRcdFx0XHRpZiAoICFsb2NrZWQgKSB7XG5cdFx0XHRcdFx0YXJncyA9IGFyZ3MgfHwgW107XG5cdFx0XHRcdFx0YXJncyA9IFsgY29udGV4dCwgYXJncy5zbGljZSA/IGFyZ3Muc2xpY2UoKSA6IGFyZ3MgXTtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBhcmdzICk7XG5cdFx0XHRcdFx0aWYgKCAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIENhbGwgYWxsIHRoZSBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gYXJndW1lbnRzXG5cdFx0XHRmaXJlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0c2VsZi5maXJlV2l0aCggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gVG8ga25vdyBpZiB0aGUgY2FsbGJhY2tzIGhhdmUgYWxyZWFkeSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlXG5cdFx0XHRmaXJlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhIWZpcmVkO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0cmV0dXJuIHNlbGY7XG59O1xuXG5cbmZ1bmN0aW9uIElkZW50aXR5KCB2ICkge1xuXHRyZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIFRocm93ZXIoIGV4ICkge1xuXHR0aHJvdyBleDtcbn1cblxuZnVuY3Rpb24gYWRvcHRWYWx1ZSggdmFsdWUsIHJlc29sdmUsIHJlamVjdCwgbm9WYWx1ZSApIHtcblx0dmFyIG1ldGhvZDtcblxuXHR0cnkge1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIHByb21pc2UgYXNwZWN0IGZpcnN0IHRvIHByaXZpbGVnZSBzeW5jaHJvbm91cyBiZWhhdmlvclxuXHRcdGlmICggdmFsdWUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oICggbWV0aG9kID0gdmFsdWUucHJvbWlzZSApICkgKSB7XG5cdFx0XHRtZXRob2QuY2FsbCggdmFsdWUgKS5kb25lKCByZXNvbHZlICkuZmFpbCggcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciB0aGVuYWJsZXNcblx0XHR9IGVsc2UgaWYgKCB2YWx1ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggKCBtZXRob2QgPSB2YWx1ZS50aGVuICkgKSApIHtcblx0XHRcdG1ldGhvZC5jYWxsKCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciBub24tdGhlbmFibGVzXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQ29udHJvbCBgcmVzb2x2ZWAgYXJndW1lbnRzIGJ5IGxldHRpbmcgQXJyYXkjc2xpY2UgY2FzdCBib29sZWFuIGBub1ZhbHVlYCB0byBpbnRlZ2VyOlxuXHRcdFx0Ly8gKiBmYWxzZTogWyB2YWx1ZSBdLnNsaWNlKCAwICkgPT4gcmVzb2x2ZSggdmFsdWUgKVxuXHRcdFx0Ly8gKiB0cnVlOiBbIHZhbHVlIF0uc2xpY2UoIDEgKSA9PiByZXNvbHZlKClcblx0XHRcdHJlc29sdmUuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdLnNsaWNlKCBub1ZhbHVlICkgKTtcblx0XHR9XG5cblx0Ly8gRm9yIFByb21pc2VzL0ErLCBjb252ZXJ0IGV4Y2VwdGlvbnMgaW50byByZWplY3Rpb25zXG5cdC8vIFNpbmNlIGpRdWVyeS53aGVuIGRvZXNuJ3QgdW53cmFwIHRoZW5hYmxlcywgd2UgY2FuIHNraXAgdGhlIGV4dHJhIGNoZWNrcyBhcHBlYXJpbmcgaW5cblx0Ly8gRGVmZXJyZWQjdGhlbiB0byBjb25kaXRpb25hbGx5IHN1cHByZXNzIHJlamVjdGlvbi5cblx0fSBjYXRjaCAoIHZhbHVlICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgb25seVxuXHRcdC8vIFN0cmljdCBtb2RlIGZ1bmN0aW9ucyBpbnZva2VkIHdpdGhvdXQgLmNhbGwvLmFwcGx5IGdldCBnbG9iYWwtb2JqZWN0IGNvbnRleHRcblx0XHRyZWplY3QuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdICk7XG5cdH1cbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdERlZmVycmVkOiBmdW5jdGlvbiggZnVuYyApIHtcblx0XHR2YXIgdHVwbGVzID0gW1xuXG5cdFx0XHRcdC8vIGFjdGlvbiwgYWRkIGxpc3RlbmVyLCBjYWxsYmFja3MsXG5cdFx0XHRcdC8vIC4uLiAudGhlbiBoYW5kbGVycywgYXJndW1lbnQgaW5kZXgsIFtmaW5hbCBzdGF0ZV1cblx0XHRcdFx0WyBcIm5vdGlmeVwiLCBcInByb2dyZXNzXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwibWVtb3J5XCIgKSxcblx0XHRcdFx0XHRqUXVlcnkuQ2FsbGJhY2tzKCBcIm1lbW9yeVwiICksIDIgXSxcblx0XHRcdFx0WyBcInJlc29sdmVcIiwgXCJkb25lXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXHRcdFx0XHRcdGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLCAwLCBcInJlc29sdmVkXCIgXSxcblx0XHRcdFx0WyBcInJlamVjdFwiLCBcImZhaWxcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cdFx0XHRcdFx0alF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksIDEsIFwicmVqZWN0ZWRcIiBdXG5cdFx0XHRdLFxuXHRcdFx0c3RhdGUgPSBcInBlbmRpbmdcIixcblx0XHRcdHByb21pc2UgPSB7XG5cdFx0XHRcdHN0YXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gc3RhdGU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGFsd2F5czogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQuZG9uZSggYXJndW1lbnRzICkuZmFpbCggYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFwiY2F0Y2hcIjogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlLnRoZW4oIG51bGwsIGZuICk7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gS2VlcCBwaXBlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRwaXBlOiBmdW5jdGlvbiggLyogZm5Eb25lLCBmbkZhaWwsIGZuUHJvZ3Jlc3MgKi8gKSB7XG5cdFx0XHRcdFx0dmFyIGZucyA9IGFyZ3VtZW50cztcblxuXHRcdFx0XHRcdHJldHVybiBqUXVlcnkuRGVmZXJyZWQoIGZ1bmN0aW9uKCBuZXdEZWZlciApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCB0dXBsZXMsIGZ1bmN0aW9uKCBpLCB0dXBsZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBNYXAgdHVwbGVzIChwcm9ncmVzcywgZG9uZSwgZmFpbCkgdG8gYXJndW1lbnRzIChkb25lLCBmYWlsLCBwcm9ncmVzcylcblx0XHRcdFx0XHRcdFx0dmFyIGZuID0galF1ZXJ5LmlzRnVuY3Rpb24oIGZuc1sgdHVwbGVbIDQgXSBdICkgJiYgZm5zWyB0dXBsZVsgNCBdIF07XG5cblx0XHRcdFx0XHRcdFx0Ly8gZGVmZXJyZWQucHJvZ3Jlc3MoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIubm90aWZ5IH0pXG5cdFx0XHRcdFx0XHRcdC8vIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIucmVzb2x2ZSB9KVxuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZC5mYWlsKGZ1bmN0aW9uKCkgeyBiaW5kIHRvIG5ld0RlZmVyIG9yIG5ld0RlZmVyLnJlamVjdCB9KVxuXHRcdFx0XHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDEgXSBdKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmV0dXJuZWQgPSBmbiAmJiBmbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCAmJiBqUXVlcnkuaXNGdW5jdGlvbiggcmV0dXJuZWQucHJvbWlzZSApICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQucHJvbWlzZSgpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5wcm9ncmVzcyggbmV3RGVmZXIubm90aWZ5IClcblx0XHRcdFx0XHRcdFx0XHRcdFx0LmRvbmUoIG5ld0RlZmVyLnJlc29sdmUgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZmFpbCggbmV3RGVmZXIucmVqZWN0ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyWyB0dXBsZVsgMCBdICsgXCJXaXRoXCIgXShcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm4gPyBbIHJldHVybmVkIF0gOiBhcmd1bWVudHNcblx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRmbnMgPSBudWxsO1xuXHRcdFx0XHRcdH0gKS5wcm9taXNlKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRoZW46IGZ1bmN0aW9uKCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb25Qcm9ncmVzcyApIHtcblx0XHRcdFx0XHR2YXIgbWF4RGVwdGggPSAwO1xuXHRcdFx0XHRcdGZ1bmN0aW9uIHJlc29sdmUoIGRlcHRoLCBkZWZlcnJlZCwgaGFuZGxlciwgc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHRoYXQgPSB0aGlzLFxuXHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBhcmd1bWVudHMsXG5cdFx0XHRcdFx0XHRcdFx0bWlnaHRUaHJvdyA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIHJldHVybmVkLCB0aGVuO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4zLjMuM1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBkb3VibGUtcmVzb2x1dGlvbiBhdHRlbXB0c1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCA8IG1heERlcHRoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkID0gaGFuZGxlci5hcHBseSggdGhhdCwgYXJncyApO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4xXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC00OFxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCA9PT0gZGVmZXJyZWQucHJvbWlzZSgpICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCBcIlRoZW5hYmxlIHNlbGYtcmVzb2x1dGlvblwiICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb25zIDIuMy4zLjEsIDMuNVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTRcblx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTc1XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBSZXRyaWV2ZSBgdGhlbmAgb25seSBvbmNlXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGVuID0gcmV0dXJuZWQgJiZcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy40XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTY0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgY2hlY2sgb2JqZWN0cyBhbmQgZnVuY3Rpb25zIGZvciB0aGVuYWJpbGl0eVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHR5cGVvZiByZXR1cm5lZCA9PT0gXCJvYmplY3RcIiB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHR5cGVvZiByZXR1cm5lZCA9PT0gXCJmdW5jdGlvblwiICkgJiZcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQudGhlbjtcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGEgcmV0dXJuZWQgdGhlbmFibGVcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHRoZW4gKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTcGVjaWFsIHByb2Nlc3NvcnMgKG5vdGlmeSkganVzdCB3YWl0IGZvciByZXNvbHV0aW9uXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGVuLmNhbGwoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgVGhyb3dlciwgc3BlY2lhbCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBOb3JtYWwgcHJvY2Vzc29ycyAocmVzb2x2ZSkgYWxzbyBob29rIGludG8gcHJvZ3Jlc3Ncblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBkaXNyZWdhcmQgb2xkZXIgcmVzb2x1dGlvbiB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtYXhEZXB0aCsrO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhlbi5jYWxsKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIElkZW50aXR5LCBzcGVjaWFsICksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIFRocm93ZXIsIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGFsbCBvdGhlciByZXR1cm5lZCB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gT25seSBzdWJzdGl0dXRlIGhhbmRsZXJzIHBhc3Mgb24gY29udGV4dFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBoYW5kbGVyICE9PSBJZGVudGl0eSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGF0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBbIHJldHVybmVkIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBQcm9jZXNzIHRoZSB2YWx1ZShzKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZhdWx0IHByb2Nlc3MgaXMgcmVzb2x2ZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHNwZWNpYWwgfHwgZGVmZXJyZWQucmVzb2x2ZVdpdGggKSggdGhhdCwgYXJncyApO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IG5vcm1hbCBwcm9jZXNzb3JzIChyZXNvbHZlKSBjYXRjaCBhbmQgcmVqZWN0IGV4Y2VwdGlvbnNcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzID0gc3BlY2lhbCA/XG5cdFx0XHRcdFx0XHRcdFx0XHRtaWdodFRocm93IDpcblx0XHRcdFx0XHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1pZ2h0VGhyb3coKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5leGNlcHRpb25Ib29rICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LkRlZmVycmVkLmV4Y2VwdGlvbkhvb2soIGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb2Nlc3Muc3RhY2tUcmFjZSApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy40LjFcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC02MVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBwb3N0LXJlc29sdXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggZGVwdGggKyAxID49IG1heERlcHRoICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IHN1YnN0aXR1dGUgaGFuZGxlcnMgcGFzcyBvbiBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggaGFuZGxlciAhPT0gVGhyb3dlciApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhhdCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YXJncyA9IFsgZSBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy4xXG5cdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTU3XG5cdFx0XHRcdFx0XHRcdC8vIFJlLXJlc29sdmUgcHJvbWlzZXMgaW1tZWRpYXRlbHkgdG8gZG9kZ2UgZmFsc2UgcmVqZWN0aW9uIGZyb21cblx0XHRcdFx0XHRcdFx0Ly8gc3Vic2VxdWVudCBlcnJvcnNcblx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCApIHtcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDYWxsIGFuIG9wdGlvbmFsIGhvb2sgdG8gcmVjb3JkIHRoZSBzdGFjaywgaW4gY2FzZSBvZiBleGNlcHRpb25cblx0XHRcdFx0XHRcdFx0XHQvLyBzaW5jZSBpdCdzIG90aGVyd2lzZSBsb3N0IHdoZW4gZXhlY3V0aW9uIGdvZXMgYXN5bmNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5nZXRTdGFja0hvb2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzLnN0YWNrVHJhY2UgPSBqUXVlcnkuRGVmZXJyZWQuZ2V0U3RhY2tIb29rKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBwcm9jZXNzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZCggZnVuY3Rpb24oIG5ld0RlZmVyICkge1xuXG5cdFx0XHRcdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDAgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvblByb2dyZXNzICkgP1xuXHRcdFx0XHRcdFx0XHRcdFx0b25Qcm9ncmVzcyA6XG5cdFx0XHRcdFx0XHRcdFx0XHRJZGVudGl0eSxcblx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlci5ub3RpZnlXaXRoXG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDEgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvbkZ1bGZpbGxlZCApID9cblx0XHRcdFx0XHRcdFx0XHRcdG9uRnVsZmlsbGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdElkZW50aXR5XG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIHJlamVjdGVkX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMiBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uUmVqZWN0ZWQgKSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRvblJlamVjdGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdFRocm93ZXJcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9ICkucHJvbWlzZSgpO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIEdldCBhIHByb21pc2UgZm9yIHRoaXMgZGVmZXJyZWRcblx0XHRcdFx0Ly8gSWYgb2JqIGlzIHByb3ZpZGVkLCB0aGUgcHJvbWlzZSBhc3BlY3QgaXMgYWRkZWQgdG8gdGhlIG9iamVjdFxuXHRcdFx0XHRwcm9taXNlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdFx0XHRcdHJldHVybiBvYmogIT0gbnVsbCA/IGpRdWVyeS5leHRlbmQoIG9iaiwgcHJvbWlzZSApIDogcHJvbWlzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlZmVycmVkID0ge307XG5cblx0XHQvLyBBZGQgbGlzdC1zcGVjaWZpYyBtZXRob2RzXG5cdFx0alF1ZXJ5LmVhY2goIHR1cGxlcywgZnVuY3Rpb24oIGksIHR1cGxlICkge1xuXHRcdFx0dmFyIGxpc3QgPSB0dXBsZVsgMiBdLFxuXHRcdFx0XHRzdGF0ZVN0cmluZyA9IHR1cGxlWyA1IF07XG5cblx0XHRcdC8vIHByb21pc2UucHJvZ3Jlc3MgPSBsaXN0LmFkZFxuXHRcdFx0Ly8gcHJvbWlzZS5kb25lID0gbGlzdC5hZGRcblx0XHRcdC8vIHByb21pc2UuZmFpbCA9IGxpc3QuYWRkXG5cdFx0XHRwcm9taXNlWyB0dXBsZVsgMSBdIF0gPSBsaXN0LmFkZDtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0YXRlXG5cdFx0XHRpZiAoIHN0YXRlU3RyaW5nICkge1xuXHRcdFx0XHRsaXN0LmFkZChcblx0XHRcdFx0XHRmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gc3RhdGUgPSBcInJlc29sdmVkXCIgKGkuZS4sIGZ1bGZpbGxlZClcblx0XHRcdFx0XHRcdC8vIHN0YXRlID0gXCJyZWplY3RlZFwiXG5cdFx0XHRcdFx0XHRzdGF0ZSA9IHN0YXRlU3RyaW5nO1xuXHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHQvLyByZWplY3RlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdHR1cGxlc1sgMyAtIGkgXVsgMiBdLmRpc2FibGUsXG5cblx0XHRcdFx0XHQvLyBwcm9ncmVzc19jYWxsYmFja3MubG9ja1xuXHRcdFx0XHRcdHR1cGxlc1sgMCBdWyAyIF0ubG9ja1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5maXJlXG5cdFx0XHQvLyBmdWxmaWxsZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0Ly8gcmVqZWN0ZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0bGlzdC5hZGQoIHR1cGxlWyAzIF0uZmlyZSApO1xuXG5cdFx0XHQvLyBkZWZlcnJlZC5ub3RpZnkgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQubm90aWZ5V2l0aCguLi4pIH1cblx0XHRcdC8vIGRlZmVycmVkLnJlc29sdmUgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVzb2x2ZVdpdGgoLi4uKSB9XG5cdFx0XHQvLyBkZWZlcnJlZC5yZWplY3QgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVqZWN0V2l0aCguLi4pIH1cblx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMCBdIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGVmZXJyZWRbIHR1cGxlWyAwIF0gKyBcIldpdGhcIiBdKCB0aGlzID09PSBkZWZlcnJlZCA/IHVuZGVmaW5lZCA6IHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH07XG5cblx0XHRcdC8vIGRlZmVycmVkLm5vdGlmeVdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHQvLyBkZWZlcnJlZC5yZXNvbHZlV2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdC8vIGRlZmVycmVkLnJlamVjdFdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0gPSBsaXN0LmZpcmVXaXRoO1xuXHRcdH0gKTtcblxuXHRcdC8vIE1ha2UgdGhlIGRlZmVycmVkIGEgcHJvbWlzZVxuXHRcdHByb21pc2UucHJvbWlzZSggZGVmZXJyZWQgKTtcblxuXHRcdC8vIENhbGwgZ2l2ZW4gZnVuYyBpZiBhbnlcblx0XHRpZiAoIGZ1bmMgKSB7XG5cdFx0XHRmdW5jLmNhbGwoIGRlZmVycmVkLCBkZWZlcnJlZCApO1xuXHRcdH1cblxuXHRcdC8vIEFsbCBkb25lIVxuXHRcdHJldHVybiBkZWZlcnJlZDtcblx0fSxcblxuXHQvLyBEZWZlcnJlZCBoZWxwZXJcblx0d2hlbjogZnVuY3Rpb24oIHNpbmdsZVZhbHVlICkge1xuXHRcdHZhclxuXG5cdFx0XHQvLyBjb3VudCBvZiB1bmNvbXBsZXRlZCBzdWJvcmRpbmF0ZXNcblx0XHRcdHJlbWFpbmluZyA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cblx0XHRcdC8vIGNvdW50IG9mIHVucHJvY2Vzc2VkIGFyZ3VtZW50c1xuXHRcdFx0aSA9IHJlbWFpbmluZyxcblxuXHRcdFx0Ly8gc3Vib3JkaW5hdGUgZnVsZmlsbG1lbnQgZGF0YVxuXHRcdFx0cmVzb2x2ZUNvbnRleHRzID0gQXJyYXkoIGkgKSxcblx0XHRcdHJlc29sdmVWYWx1ZXMgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSxcblxuXHRcdFx0Ly8gdGhlIG1hc3RlciBEZWZlcnJlZFxuXHRcdFx0bWFzdGVyID0galF1ZXJ5LkRlZmVycmVkKCksXG5cblx0XHRcdC8vIHN1Ym9yZGluYXRlIGNhbGxiYWNrIGZhY3Rvcnlcblx0XHRcdHVwZGF0ZUZ1bmMgPSBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXNvbHZlQ29udGV4dHNbIGkgXSA9IHRoaXM7XG5cdFx0XHRcdFx0cmVzb2x2ZVZhbHVlc1sgaSBdID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSA6IHZhbHVlO1xuXHRcdFx0XHRcdGlmICggISggLS1yZW1haW5pbmcgKSApIHtcblx0XHRcdFx0XHRcdG1hc3Rlci5yZXNvbHZlV2l0aCggcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fTtcblxuXHRcdC8vIFNpbmdsZS0gYW5kIGVtcHR5IGFyZ3VtZW50cyBhcmUgYWRvcHRlZCBsaWtlIFByb21pc2UucmVzb2x2ZVxuXHRcdGlmICggcmVtYWluaW5nIDw9IDEgKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCBzaW5nbGVWYWx1ZSwgbWFzdGVyLmRvbmUoIHVwZGF0ZUZ1bmMoIGkgKSApLnJlc29sdmUsIG1hc3Rlci5yZWplY3QsXG5cdFx0XHRcdCFyZW1haW5pbmcgKTtcblxuXHRcdFx0Ly8gVXNlIC50aGVuKCkgdG8gdW53cmFwIHNlY29uZGFyeSB0aGVuYWJsZXMgKGNmLiBnaC0zMDAwKVxuXHRcdFx0aWYgKCBtYXN0ZXIuc3RhdGUoKSA9PT0gXCJwZW5kaW5nXCIgfHxcblx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHJlc29sdmVWYWx1ZXNbIGkgXSAmJiByZXNvbHZlVmFsdWVzWyBpIF0udGhlbiApICkge1xuXG5cdFx0XHRcdHJldHVybiBtYXN0ZXIudGhlbigpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE11bHRpcGxlIGFyZ3VtZW50cyBhcmUgYWdncmVnYXRlZCBsaWtlIFByb21pc2UuYWxsIGFycmF5IGVsZW1lbnRzXG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCByZXNvbHZlVmFsdWVzWyBpIF0sIHVwZGF0ZUZ1bmMoIGkgKSwgbWFzdGVyLnJlamVjdCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBtYXN0ZXIucHJvbWlzZSgpO1xuXHR9XG59ICk7XG5cblxuLy8gVGhlc2UgdXN1YWxseSBpbmRpY2F0ZSBhIHByb2dyYW1tZXIgbWlzdGFrZSBkdXJpbmcgZGV2ZWxvcG1lbnQsXG4vLyB3YXJuIGFib3V0IHRoZW0gQVNBUCByYXRoZXIgdGhhbiBzd2FsbG93aW5nIHRoZW0gYnkgZGVmYXVsdC5cbnZhciByZXJyb3JOYW1lcyA9IC9eKEV2YWx8SW50ZXJuYWx8UmFuZ2V8UmVmZXJlbmNlfFN5bnRheHxUeXBlfFVSSSlFcnJvciQvO1xuXG5qUXVlcnkuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayA9IGZ1bmN0aW9uKCBlcnJvciwgc3RhY2sgKSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgOCAtIDkgb25seVxuXHQvLyBDb25zb2xlIGV4aXN0cyB3aGVuIGRldiB0b29scyBhcmUgb3Blbiwgd2hpY2ggY2FuIGhhcHBlbiBhdCBhbnkgdGltZVxuXHRpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLndhcm4gJiYgZXJyb3IgJiYgcmVycm9yTmFtZXMudGVzdCggZXJyb3IubmFtZSApICkge1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4oIFwialF1ZXJ5LkRlZmVycmVkIGV4Y2VwdGlvbjogXCIgKyBlcnJvci5tZXNzYWdlLCBlcnJvci5zdGFjaywgc3RhY2sgKTtcblx0fVxufTtcblxuXG5cblxualF1ZXJ5LnJlYWR5RXhjZXB0aW9uID0gZnVuY3Rpb24oIGVycm9yICkge1xuXHR3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXJyb3I7XG5cdH0gKTtcbn07XG5cblxuXG5cbi8vIFRoZSBkZWZlcnJlZCB1c2VkIG9uIERPTSByZWFkeVxudmFyIHJlYWR5TGlzdCA9IGpRdWVyeS5EZWZlcnJlZCgpO1xuXG5qUXVlcnkuZm4ucmVhZHkgPSBmdW5jdGlvbiggZm4gKSB7XG5cblx0cmVhZHlMaXN0XG5cdFx0LnRoZW4oIGZuIClcblxuXHRcdC8vIFdyYXAgalF1ZXJ5LnJlYWR5RXhjZXB0aW9uIGluIGEgZnVuY3Rpb24gc28gdGhhdCB0aGUgbG9va3VwXG5cdFx0Ly8gaGFwcGVucyBhdCB0aGUgdGltZSBvZiBlcnJvciBoYW5kbGluZyBpbnN0ZWFkIG9mIGNhbGxiYWNrXG5cdFx0Ly8gcmVnaXN0cmF0aW9uLlxuXHRcdC5jYXRjaCggZnVuY3Rpb24oIGVycm9yICkge1xuXHRcdFx0alF1ZXJ5LnJlYWR5RXhjZXB0aW9uKCBlcnJvciApO1xuXHRcdH0gKTtcblxuXHRyZXR1cm4gdGhpcztcbn07XG5cbmpRdWVyeS5leHRlbmQoIHtcblxuXHQvLyBJcyB0aGUgRE9NIHJlYWR5IHRvIGJlIHVzZWQ/IFNldCB0byB0cnVlIG9uY2UgaXQgb2NjdXJzLlxuXHRpc1JlYWR5OiBmYWxzZSxcblxuXHQvLyBBIGNvdW50ZXIgdG8gdHJhY2sgaG93IG1hbnkgaXRlbXMgdG8gd2FpdCBmb3IgYmVmb3JlXG5cdC8vIHRoZSByZWFkeSBldmVudCBmaXJlcy4gU2VlICM2NzgxXG5cdHJlYWR5V2FpdDogMSxcblxuXHQvLyBIYW5kbGUgd2hlbiB0aGUgRE9NIGlzIHJlYWR5XG5cdHJlYWR5OiBmdW5jdGlvbiggd2FpdCApIHtcblxuXHRcdC8vIEFib3J0IGlmIHRoZXJlIGFyZSBwZW5kaW5nIGhvbGRzIG9yIHdlJ3JlIGFscmVhZHkgcmVhZHlcblx0XHRpZiAoIHdhaXQgPT09IHRydWUgPyAtLWpRdWVyeS5yZWFkeVdhaXQgOiBqUXVlcnkuaXNSZWFkeSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBSZW1lbWJlciB0aGF0IHRoZSBET00gaXMgcmVhZHlcblx0XHRqUXVlcnkuaXNSZWFkeSA9IHRydWU7XG5cblx0XHQvLyBJZiBhIG5vcm1hbCBET00gUmVhZHkgZXZlbnQgZmlyZWQsIGRlY3JlbWVudCwgYW5kIHdhaXQgaWYgbmVlZCBiZVxuXHRcdGlmICggd2FpdCAhPT0gdHJ1ZSAmJiAtLWpRdWVyeS5yZWFkeVdhaXQgPiAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIElmIHRoZXJlIGFyZSBmdW5jdGlvbnMgYm91bmQsIHRvIGV4ZWN1dGVcblx0XHRyZWFkeUxpc3QucmVzb2x2ZVdpdGgoIGRvY3VtZW50LCBbIGpRdWVyeSBdICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LnJlYWR5LnRoZW4gPSByZWFkeUxpc3QudGhlbjtcblxuLy8gVGhlIHJlYWR5IGV2ZW50IGhhbmRsZXIgYW5kIHNlbGYgY2xlYW51cCBtZXRob2RcbmZ1bmN0aW9uIGNvbXBsZXRlZCgpIHtcblx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJsb2FkXCIsIGNvbXBsZXRlZCApO1xuXHRqUXVlcnkucmVhZHkoKTtcbn1cblxuLy8gQ2F0Y2ggY2FzZXMgd2hlcmUgJChkb2N1bWVudCkucmVhZHkoKSBpcyBjYWxsZWRcbi8vIGFmdGVyIHRoZSBicm93c2VyIGV2ZW50IGhhcyBhbHJlYWR5IG9jY3VycmVkLlxuLy8gU3VwcG9ydDogSUUgPD05IC0gMTAgb25seVxuLy8gT2xkZXIgSUUgc29tZXRpbWVzIHNpZ25hbHMgXCJpbnRlcmFjdGl2ZVwiIHRvbyBzb29uXG5pZiAoIGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIiB8fFxuXHQoIGRvY3VtZW50LnJlYWR5U3RhdGUgIT09IFwibG9hZGluZ1wiICYmICFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGwgKSApIHtcblxuXHQvLyBIYW5kbGUgaXQgYXN5bmNocm9ub3VzbHkgdG8gYWxsb3cgc2NyaXB0cyB0aGUgb3Bwb3J0dW5pdHkgdG8gZGVsYXkgcmVhZHlcblx0d2luZG93LnNldFRpbWVvdXQoIGpRdWVyeS5yZWFkeSApO1xuXG59IGVsc2Uge1xuXG5cdC8vIFVzZSB0aGUgaGFuZHkgZXZlbnQgY2FsbGJhY2tcblx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXG5cdC8vIEEgZmFsbGJhY2sgdG8gd2luZG93Lm9ubG9hZCwgdGhhdCB3aWxsIGFsd2F5cyB3b3JrXG5cdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkICk7XG59XG5cblxuXG5cbi8vIE11bHRpZnVuY3Rpb25hbCBtZXRob2QgdG8gZ2V0IGFuZCBzZXQgdmFsdWVzIG9mIGEgY29sbGVjdGlvblxuLy8gVGhlIHZhbHVlL3MgY2FuIG9wdGlvbmFsbHkgYmUgZXhlY3V0ZWQgaWYgaXQncyBhIGZ1bmN0aW9uXG52YXIgYWNjZXNzID0gZnVuY3Rpb24oIGVsZW1zLCBmbiwga2V5LCB2YWx1ZSwgY2hhaW5hYmxlLCBlbXB0eUdldCwgcmF3ICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gZWxlbXMubGVuZ3RoLFxuXHRcdGJ1bGsgPSBrZXkgPT0gbnVsbDtcblxuXHQvLyBTZXRzIG1hbnkgdmFsdWVzXG5cdGlmICggalF1ZXJ5LnR5cGUoIGtleSApID09PSBcIm9iamVjdFwiICkge1xuXHRcdGNoYWluYWJsZSA9IHRydWU7XG5cdFx0Zm9yICggaSBpbiBrZXkgKSB7XG5cdFx0XHRhY2Nlc3MoIGVsZW1zLCBmbiwgaSwga2V5WyBpIF0sIHRydWUsIGVtcHR5R2V0LCByYXcgKTtcblx0XHR9XG5cblx0Ly8gU2V0cyBvbmUgdmFsdWVcblx0fSBlbHNlIGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRjaGFpbmFibGUgPSB0cnVlO1xuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyYXcgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggYnVsayApIHtcblxuXHRcdFx0Ly8gQnVsayBvcGVyYXRpb25zIHJ1biBhZ2FpbnN0IHRoZSBlbnRpcmUgc2V0XG5cdFx0XHRpZiAoIHJhdyApIHtcblx0XHRcdFx0Zm4uY2FsbCggZWxlbXMsIHZhbHVlICk7XG5cdFx0XHRcdGZuID0gbnVsbDtcblxuXHRcdFx0Ly8gLi4uZXhjZXB0IHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uIHZhbHVlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YnVsayA9IGZuO1xuXHRcdFx0XHRmbiA9IGZ1bmN0aW9uKCBlbGVtLCBrZXksIHZhbHVlICkge1xuXHRcdFx0XHRcdHJldHVybiBidWxrLmNhbGwoIGpRdWVyeSggZWxlbSApLCB2YWx1ZSApO1xuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggZm4gKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0Zm4oXG5cdFx0XHRcdFx0ZWxlbXNbIGkgXSwga2V5LCByYXcgP1xuXHRcdFx0XHRcdHZhbHVlIDpcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCBlbGVtc1sgaSBdLCBpLCBmbiggZWxlbXNbIGkgXSwga2V5ICkgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggY2hhaW5hYmxlICkge1xuXHRcdHJldHVybiBlbGVtcztcblx0fVxuXG5cdC8vIEdldHNcblx0aWYgKCBidWxrICkge1xuXHRcdHJldHVybiBmbi5jYWxsKCBlbGVtcyApO1xuXHR9XG5cblx0cmV0dXJuIGxlbiA/IGZuKCBlbGVtc1sgMCBdLCBrZXkgKSA6IGVtcHR5R2V0O1xufTtcbnZhciBhY2NlcHREYXRhID0gZnVuY3Rpb24oIG93bmVyICkge1xuXG5cdC8vIEFjY2VwdHMgb25seTpcblx0Ly8gIC0gTm9kZVxuXHQvLyAgICAtIE5vZGUuRUxFTUVOVF9OT0RFXG5cdC8vICAgIC0gTm9kZS5ET0NVTUVOVF9OT0RFXG5cdC8vICAtIE9iamVjdFxuXHQvLyAgICAtIEFueVxuXHRyZXR1cm4gb3duZXIubm9kZVR5cGUgPT09IDEgfHwgb3duZXIubm9kZVR5cGUgPT09IDkgfHwgISggK293bmVyLm5vZGVUeXBlICk7XG59O1xuXG5cblxuXG5mdW5jdGlvbiBEYXRhKCkge1xuXHR0aGlzLmV4cGFuZG8gPSBqUXVlcnkuZXhwYW5kbyArIERhdGEudWlkKys7XG59XG5cbkRhdGEudWlkID0gMTtcblxuRGF0YS5wcm90b3R5cGUgPSB7XG5cblx0Y2FjaGU6IGZ1bmN0aW9uKCBvd25lciApIHtcblxuXHRcdC8vIENoZWNrIGlmIHRoZSBvd25lciBvYmplY3QgYWxyZWFkeSBoYXMgYSBjYWNoZVxuXHRcdHZhciB2YWx1ZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdC8vIElmIG5vdCwgY3JlYXRlIG9uZVxuXHRcdGlmICggIXZhbHVlICkge1xuXHRcdFx0dmFsdWUgPSB7fTtcblxuXHRcdFx0Ly8gV2UgY2FuIGFjY2VwdCBkYXRhIGZvciBub24tZWxlbWVudCBub2RlcyBpbiBtb2Rlcm4gYnJvd3NlcnMsXG5cdFx0XHQvLyBidXQgd2Ugc2hvdWxkIG5vdCwgc2VlICM4MzM1LlxuXHRcdFx0Ly8gQWx3YXlzIHJldHVybiBhbiBlbXB0eSBvYmplY3QuXG5cdFx0XHRpZiAoIGFjY2VwdERhdGEoIG93bmVyICkgKSB7XG5cblx0XHRcdFx0Ly8gSWYgaXQgaXMgYSBub2RlIHVubGlrZWx5IHRvIGJlIHN0cmluZ2lmeS1lZCBvciBsb29wZWQgb3ZlclxuXHRcdFx0XHQvLyB1c2UgcGxhaW4gYXNzaWdubWVudFxuXHRcdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSA9IHZhbHVlO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBzZWN1cmUgaXQgaW4gYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eVxuXHRcdFx0XHQvLyBjb25maWd1cmFibGUgbXVzdCBiZSB0cnVlIHRvIGFsbG93IHRoZSBwcm9wZXJ0eSB0byBiZVxuXHRcdFx0XHQvLyBkZWxldGVkIHdoZW4gZGF0YSBpcyByZW1vdmVkXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KCBvd25lciwgdGhpcy5leHBhbmRvLCB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogdmFsdWUsXG5cdFx0XHRcdFx0XHRjb25maWd1cmFibGU6IHRydWVcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdmFsdWU7XG5cdH0sXG5cdHNldDogZnVuY3Rpb24oIG93bmVyLCBkYXRhLCB2YWx1ZSApIHtcblx0XHR2YXIgcHJvcCxcblx0XHRcdGNhY2hlID0gdGhpcy5jYWNoZSggb3duZXIgKTtcblxuXHRcdC8vIEhhbmRsZTogWyBvd25lciwga2V5LCB2YWx1ZSBdIGFyZ3Ncblx0XHQvLyBBbHdheXMgdXNlIGNhbWVsQ2FzZSBrZXkgKGdoLTIyNTcpXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGNhY2hlWyBqUXVlcnkuY2FtZWxDYXNlKCBkYXRhICkgXSA9IHZhbHVlO1xuXG5cdFx0Ly8gSGFuZGxlOiBbIG93bmVyLCB7IHByb3BlcnRpZXMgfSBdIGFyZ3Ncblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBDb3B5IHRoZSBwcm9wZXJ0aWVzIG9uZS1ieS1vbmUgdG8gdGhlIGNhY2hlIG9iamVjdFxuXHRcdFx0Zm9yICggcHJvcCBpbiBkYXRhICkge1xuXHRcdFx0XHRjYWNoZVsgalF1ZXJ5LmNhbWVsQ2FzZSggcHJvcCApIF0gPSBkYXRhWyBwcm9wIF07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZTtcblx0fSxcblx0Z2V0OiBmdW5jdGlvbiggb3duZXIsIGtleSApIHtcblx0XHRyZXR1cm4ga2V5ID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcy5jYWNoZSggb3duZXIgKSA6XG5cblx0XHRcdC8vIEFsd2F5cyB1c2UgY2FtZWxDYXNlIGtleSAoZ2gtMjI1Nylcblx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSAmJiBvd25lclsgdGhpcy5leHBhbmRvIF1bIGpRdWVyeS5jYW1lbENhc2UoIGtleSApIF07XG5cdH0sXG5cdGFjY2VzczogZnVuY3Rpb24oIG93bmVyLCBrZXksIHZhbHVlICkge1xuXG5cdFx0Ly8gSW4gY2FzZXMgd2hlcmUgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBObyBrZXkgd2FzIHNwZWNpZmllZFxuXHRcdC8vICAgMi4gQSBzdHJpbmcga2V5IHdhcyBzcGVjaWZpZWQsIGJ1dCBubyB2YWx1ZSBwcm92aWRlZFxuXHRcdC8vXG5cdFx0Ly8gVGFrZSB0aGUgXCJyZWFkXCIgcGF0aCBhbmQgYWxsb3cgdGhlIGdldCBtZXRob2QgdG8gZGV0ZXJtaW5lXG5cdFx0Ly8gd2hpY2ggdmFsdWUgdG8gcmV0dXJuLCByZXNwZWN0aXZlbHkgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBUaGUgZW50aXJlIGNhY2hlIG9iamVjdFxuXHRcdC8vICAgMi4gVGhlIGRhdGEgc3RvcmVkIGF0IHRoZSBrZXlcblx0XHQvL1xuXHRcdGlmICgga2V5ID09PSB1bmRlZmluZWQgfHxcblx0XHRcdFx0KCAoIGtleSAmJiB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICkgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApICkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoIG93bmVyLCBrZXkgKTtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHRoZSBrZXkgaXMgbm90IGEgc3RyaW5nLCBvciBib3RoIGEga2V5IGFuZCB2YWx1ZVxuXHRcdC8vIGFyZSBzcGVjaWZpZWQsIHNldCBvciBleHRlbmQgKGV4aXN0aW5nIG9iamVjdHMpIHdpdGggZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBBbiBvYmplY3Qgb2YgcHJvcGVydGllc1xuXHRcdC8vICAgMi4gQSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly9cblx0XHR0aGlzLnNldCggb3duZXIsIGtleSwgdmFsdWUgKTtcblxuXHRcdC8vIFNpbmNlIHRoZSBcInNldFwiIHBhdGggY2FuIGhhdmUgdHdvIHBvc3NpYmxlIGVudHJ5IHBvaW50c1xuXHRcdC8vIHJldHVybiB0aGUgZXhwZWN0ZWQgZGF0YSBiYXNlZCBvbiB3aGljaCBwYXRoIHdhcyB0YWtlblsqXVxuXHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiBrZXk7XG5cdH0sXG5cdHJlbW92ZTogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0dmFyIGksXG5cdFx0XHRjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdGlmICggY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGtleSAhPT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHQvLyBTdXBwb3J0IGFycmF5IG9yIHNwYWNlIHNlcGFyYXRlZCBzdHJpbmcgb2Yga2V5c1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBrZXkgKSApIHtcblxuXHRcdFx0XHQvLyBJZiBrZXkgaXMgYW4gYXJyYXkgb2Yga2V5cy4uLlxuXHRcdFx0XHQvLyBXZSBhbHdheXMgc2V0IGNhbWVsQ2FzZSBrZXlzLCBzbyByZW1vdmUgdGhhdC5cblx0XHRcdFx0a2V5ID0ga2V5Lm1hcCggalF1ZXJ5LmNhbWVsQ2FzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0a2V5ID0galF1ZXJ5LmNhbWVsQ2FzZSgga2V5ICk7XG5cblx0XHRcdFx0Ly8gSWYgYSBrZXkgd2l0aCB0aGUgc3BhY2VzIGV4aXN0cywgdXNlIGl0LlxuXHRcdFx0XHQvLyBPdGhlcndpc2UsIGNyZWF0ZSBhbiBhcnJheSBieSBtYXRjaGluZyBub24td2hpdGVzcGFjZVxuXHRcdFx0XHRrZXkgPSBrZXkgaW4gY2FjaGUgP1xuXHRcdFx0XHRcdFsga2V5IF0gOlxuXHRcdFx0XHRcdCgga2V5Lm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10gKTtcblx0XHRcdH1cblxuXHRcdFx0aSA9IGtleS5sZW5ndGg7XG5cblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRkZWxldGUgY2FjaGVbIGtleVsgaSBdIF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIHRoZSBleHBhbmRvIGlmIHRoZXJlJ3Mgbm8gbW9yZSBkYXRhXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fCBqUXVlcnkuaXNFbXB0eU9iamVjdCggY2FjaGUgKSApIHtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NVxuXHRcdFx0Ly8gV2Via2l0ICYgQmxpbmsgcGVyZm9ybWFuY2Ugc3VmZmVycyB3aGVuIGRlbGV0aW5nIHByb3BlcnRpZXNcblx0XHRcdC8vIGZyb20gRE9NIG5vZGVzLCBzbyBzZXQgdG8gdW5kZWZpbmVkIGluc3RlYWRcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTM3ODYwNyAoYnVnIHJlc3RyaWN0ZWQpXG5cdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRvd25lclsgdGhpcy5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWxldGUgb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0aGFzRGF0YTogZnVuY3Rpb24oIG93bmVyICkge1xuXHRcdHZhciBjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblx0XHRyZXR1cm4gY2FjaGUgIT09IHVuZGVmaW5lZCAmJiAhalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGNhY2hlICk7XG5cdH1cbn07XG52YXIgZGF0YVByaXYgPSBuZXcgRGF0YSgpO1xuXG52YXIgZGF0YVVzZXIgPSBuZXcgRGF0YSgpO1xuXG5cblxuLy9cdEltcGxlbWVudGF0aW9uIFN1bW1hcnlcbi8vXG4vL1x0MS4gRW5mb3JjZSBBUEkgc3VyZmFjZSBhbmQgc2VtYW50aWMgY29tcGF0aWJpbGl0eSB3aXRoIDEuOS54IGJyYW5jaFxuLy9cdDIuIEltcHJvdmUgdGhlIG1vZHVsZSdzIG1haW50YWluYWJpbGl0eSBieSByZWR1Y2luZyB0aGUgc3RvcmFnZVxuLy9cdFx0cGF0aHMgdG8gYSBzaW5nbGUgbWVjaGFuaXNtLlxuLy9cdDMuIFVzZSB0aGUgc2FtZSBzaW5nbGUgbWVjaGFuaXNtIHRvIHN1cHBvcnQgXCJwcml2YXRlXCIgYW5kIFwidXNlclwiIGRhdGEuXG4vL1x0NC4gX05ldmVyXyBleHBvc2UgXCJwcml2YXRlXCIgZGF0YSB0byB1c2VyIGNvZGUgKFRPRE86IERyb3AgX2RhdGEsIF9yZW1vdmVEYXRhKVxuLy9cdDUuIEF2b2lkIGV4cG9zaW5nIGltcGxlbWVudGF0aW9uIGRldGFpbHMgb24gdXNlciBvYmplY3RzIChlZy4gZXhwYW5kbyBwcm9wZXJ0aWVzKVxuLy9cdDYuIFByb3ZpZGUgYSBjbGVhciBwYXRoIGZvciBpbXBsZW1lbnRhdGlvbiB1cGdyYWRlIHRvIFdlYWtNYXAgaW4gMjAxNFxuXG52YXIgcmJyYWNlID0gL14oPzpcXHtbXFx3XFxXXSpcXH18XFxbW1xcd1xcV10qXFxdKSQvLFxuXHRybXVsdGlEYXNoID0gL1tBLVpdL2c7XG5cbmZ1bmN0aW9uIGdldERhdGEoIGRhdGEgKSB7XG5cdGlmICggZGF0YSA9PT0gXCJ0cnVlXCIgKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwiZmFsc2VcIiApIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwibnVsbFwiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gT25seSBjb252ZXJ0IHRvIGEgbnVtYmVyIGlmIGl0IGRvZXNuJ3QgY2hhbmdlIHRoZSBzdHJpbmdcblx0aWYgKCBkYXRhID09PSArZGF0YSArIFwiXCIgKSB7XG5cdFx0cmV0dXJuICtkYXRhO1xuXHR9XG5cblx0aWYgKCByYnJhY2UudGVzdCggZGF0YSApICkge1xuXHRcdHJldHVybiBKU09OLnBhcnNlKCBkYXRhICk7XG5cdH1cblxuXHRyZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gZGF0YUF0dHIoIGVsZW0sIGtleSwgZGF0YSApIHtcblx0dmFyIG5hbWU7XG5cblx0Ly8gSWYgbm90aGluZyB3YXMgZm91bmQgaW50ZXJuYWxseSwgdHJ5IHRvIGZldGNoIGFueVxuXHQvLyBkYXRhIGZyb20gdGhlIEhUTUw1IGRhdGEtKiBhdHRyaWJ1dGVcblx0aWYgKCBkYXRhID09PSB1bmRlZmluZWQgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRuYW1lID0gXCJkYXRhLVwiICsga2V5LnJlcGxhY2UoIHJtdWx0aURhc2gsIFwiLSQmXCIgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGRhdGEgPSBlbGVtLmdldEF0dHJpYnV0ZSggbmFtZSApO1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBnZXREYXRhKCBkYXRhICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHt9XG5cblx0XHRcdC8vIE1ha2Ugc3VyZSB3ZSBzZXQgdGhlIGRhdGEgc28gaXQgaXNuJ3QgY2hhbmdlZCBsYXRlclxuXHRcdFx0ZGF0YVVzZXIuc2V0KCBlbGVtLCBrZXksIGRhdGEgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aGFzRGF0YTogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmhhc0RhdGEoIGVsZW0gKSB8fCBkYXRhUHJpdi5oYXNEYXRhKCBlbGVtICk7XG5cdH0sXG5cblx0ZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdHJlbW92ZURhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHRcdGRhdGFVc2VyLnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9LFxuXG5cdC8vIFRPRE86IE5vdyB0aGF0IGFsbCBjYWxscyB0byBfZGF0YSBhbmQgX3JlbW92ZURhdGEgaGF2ZSBiZWVuIHJlcGxhY2VkXG5cdC8vIHdpdGggZGlyZWN0IGNhbGxzIHRvIGRhdGFQcml2IG1ldGhvZHMsIHRoZXNlIGNhbiBiZSBkZXByZWNhdGVkLlxuXHRfZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFQcml2LmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdF9yZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIG5hbWUgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRhdGE6IGZ1bmN0aW9uKCBrZXksIHZhbHVlICkge1xuXHRcdHZhciBpLCBuYW1lLCBkYXRhLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGF0dHJzID0gZWxlbSAmJiBlbGVtLmF0dHJpYnV0ZXM7XG5cblx0XHQvLyBHZXRzIGFsbCB2YWx1ZXNcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdFx0ZGF0YSA9IGRhdGFVc2VyLmdldCggZWxlbSApO1xuXG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAhZGF0YVByaXYuZ2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiICkgKSB7XG5cdFx0XHRcdFx0aSA9IGF0dHJzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0XHRcdFx0Ly8gVGhlIGF0dHJzIGVsZW1lbnRzIGNhbiBiZSBudWxsICgjMTQ4OTQpXG5cdFx0XHRcdFx0XHRpZiAoIGF0dHJzWyBpIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG5hbWUgPSBhdHRyc1sgaSBdLm5hbWU7XG5cdFx0XHRcdFx0XHRcdGlmICggbmFtZS5pbmRleE9mKCBcImRhdGEtXCIgKSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZS5zbGljZSggNSApICk7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUF0dHIoIGVsZW0sIG5hbWUsIGRhdGFbIG5hbWUgXSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFQcml2LnNldCggZWxlbSwgXCJoYXNEYXRhQXR0cnNcIiwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdH1cblxuXHRcdC8vIFNldHMgbXVsdGlwbGUgdmFsdWVzXG5cdFx0aWYgKCB0eXBlb2Yga2V5ID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFVc2VyLnNldCggdGhpcywga2V5ICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGRhdGE7XG5cblx0XHRcdC8vIFRoZSBjYWxsaW5nIGpRdWVyeSBvYmplY3QgKGVsZW1lbnQgbWF0Y2hlcykgaXMgbm90IGVtcHR5XG5cdFx0XHQvLyAoYW5kIHRoZXJlZm9yZSBoYXMgYW4gZWxlbWVudCBhcHBlYXJzIGF0IHRoaXNbIDAgXSkgYW5kIHRoZVxuXHRcdFx0Ly8gYHZhbHVlYCBwYXJhbWV0ZXIgd2FzIG5vdCB1bmRlZmluZWQuIEFuIGVtcHR5IGpRdWVyeSBvYmplY3Rcblx0XHRcdC8vIHdpbGwgcmVzdWx0IGluIGB1bmRlZmluZWRgIGZvciBlbGVtID0gdGhpc1sgMCBdIHdoaWNoIHdpbGxcblx0XHRcdC8vIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBhbiBhdHRlbXB0IHRvIHJlYWQgYSBkYXRhIGNhY2hlIGlzIG1hZGUuXG5cdFx0XHRpZiAoIGVsZW0gJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHQvLyBBdHRlbXB0IHRvIGdldCBkYXRhIGZyb20gdGhlIGNhY2hlXG5cdFx0XHRcdC8vIFRoZSBrZXkgd2lsbCBhbHdheXMgYmUgY2FtZWxDYXNlZCBpbiBEYXRhXG5cdFx0XHRcdGRhdGEgPSBkYXRhVXNlci5nZXQoIGVsZW0sIGtleSApO1xuXHRcdFx0XHRpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gXCJkaXNjb3ZlclwiIHRoZSBkYXRhIGluXG5cdFx0XHRcdC8vIEhUTUw1IGN1c3RvbSBkYXRhLSogYXR0cnNcblx0XHRcdFx0ZGF0YSA9IGRhdGFBdHRyKCBlbGVtLCBrZXkgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB0cmllZCByZWFsbHkgaGFyZCwgYnV0IHRoZSBkYXRhIGRvZXNuJ3QgZXhpc3QuXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IHRoZSBkYXRhLi4uXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdC8vIFdlIGFsd2F5cyBzdG9yZSB0aGUgY2FtZWxDYXNlZCBrZXlcblx0XHRcdFx0ZGF0YVVzZXIuc2V0KCB0aGlzLCBrZXksIHZhbHVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fSwgbnVsbCwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxLCBudWxsLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlRGF0YTogZnVuY3Rpb24oIGtleSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGRhdGFVc2VyLnJlbW92ZSggdGhpcywga2V5ICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHF1ZXVlO1xuXG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0dHlwZSA9ICggdHlwZSB8fCBcImZ4XCIgKSArIFwicXVldWVcIjtcblx0XHRcdHF1ZXVlID0gZGF0YVByaXYuZ2V0KCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdC8vIFNwZWVkIHVwIGRlcXVldWUgYnkgZ2V0dGluZyBvdXQgcXVpY2tseSBpZiB0aGlzIGlzIGp1c3QgYSBsb29rdXBcblx0XHRcdGlmICggZGF0YSApIHtcblx0XHRcdFx0aWYgKCAhcXVldWUgfHwgQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdHF1ZXVlID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCB0eXBlLCBqUXVlcnkubWFrZUFycmF5KCBkYXRhICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBxdWV1ZSB8fCBbXTtcblx0XHR9XG5cdH0sXG5cblx0ZGVxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0dmFyIHF1ZXVlID0galF1ZXJ5LnF1ZXVlKCBlbGVtLCB0eXBlICksXG5cdFx0XHRzdGFydExlbmd0aCA9IHF1ZXVlLmxlbmd0aCxcblx0XHRcdGZuID0gcXVldWUuc2hpZnQoKSxcblx0XHRcdGhvb2tzID0galF1ZXJ5Ll9xdWV1ZUhvb2tzKCBlbGVtLCB0eXBlICksXG5cdFx0XHRuZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCBlbGVtLCB0eXBlICk7XG5cdFx0XHR9O1xuXG5cdFx0Ly8gSWYgdGhlIGZ4IHF1ZXVlIGlzIGRlcXVldWVkLCBhbHdheXMgcmVtb3ZlIHRoZSBwcm9ncmVzcyBzZW50aW5lbFxuXHRcdGlmICggZm4gPT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0c3RhcnRMZW5ndGgtLTtcblx0XHR9XG5cblx0XHRpZiAoIGZuICkge1xuXG5cdFx0XHQvLyBBZGQgYSBwcm9ncmVzcyBzZW50aW5lbCB0byBwcmV2ZW50IHRoZSBmeCBxdWV1ZSBmcm9tIGJlaW5nXG5cdFx0XHQvLyBhdXRvbWF0aWNhbGx5IGRlcXVldWVkXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiApIHtcblx0XHRcdFx0cXVldWUudW5zaGlmdCggXCJpbnByb2dyZXNzXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2xlYXIgdXAgdGhlIGxhc3QgcXVldWUgc3RvcCBmdW5jdGlvblxuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRmbi5jYWxsKCBlbGVtLCBuZXh0LCBob29rcyApO1xuXHRcdH1cblxuXHRcdGlmICggIXN0YXJ0TGVuZ3RoICYmIGhvb2tzICkge1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBOb3QgcHVibGljIC0gZ2VuZXJhdGUgYSBxdWV1ZUhvb2tzIG9iamVjdCwgb3IgcmV0dXJuIHRoZSBjdXJyZW50IG9uZVxuXHRfcXVldWVIb29rczogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dmFyIGtleSA9IHR5cGUgKyBcInF1ZXVlSG9va3NcIjtcblx0XHRyZXR1cm4gZGF0YVByaXYuZ2V0KCBlbGVtLCBrZXkgKSB8fCBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIGtleSwge1xuXHRcdFx0ZW1wdHk6IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLmFkZCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgWyB0eXBlICsgXCJxdWV1ZVwiLCBrZXkgXSApO1xuXHRcdFx0fSApXG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0cXVldWU6IGZ1bmN0aW9uKCB0eXBlLCBkYXRhICkge1xuXHRcdHZhciBzZXR0ZXIgPSAyO1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGRhdGEgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IFwiZnhcIjtcblx0XHRcdHNldHRlci0tO1xuXHRcdH1cblxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCA8IHNldHRlciApIHtcblx0XHRcdHJldHVybiBqUXVlcnkucXVldWUoIHRoaXNbIDAgXSwgdHlwZSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRhID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcyA6XG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIHRoaXMsIHR5cGUsIGRhdGEgKTtcblxuXHRcdFx0XHQvLyBFbnN1cmUgYSBob29rcyBmb3IgdGhpcyBxdWV1ZVxuXHRcdFx0XHRqUXVlcnkuX3F1ZXVlSG9va3MoIHRoaXMsIHR5cGUgKTtcblxuXHRcdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiAmJiBxdWV1ZVsgMCBdICE9PSBcImlucHJvZ3Jlc3NcIiApIHtcblx0XHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdH0sXG5cdGRlcXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIHR5cGUgKTtcblx0XHR9ICk7XG5cdH0sXG5cdGNsZWFyUXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0fSxcblxuXHQvLyBHZXQgYSBwcm9taXNlIHJlc29sdmVkIHdoZW4gcXVldWVzIG9mIGEgY2VydGFpbiB0eXBlXG5cdC8vIGFyZSBlbXB0aWVkIChmeCBpcyB0aGUgdHlwZSBieSBkZWZhdWx0KVxuXHRwcm9taXNlOiBmdW5jdGlvbiggdHlwZSwgb2JqICkge1xuXHRcdHZhciB0bXAsXG5cdFx0XHRjb3VudCA9IDEsXG5cdFx0XHRkZWZlciA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0ZWxlbWVudHMgPSB0aGlzLFxuXHRcdFx0aSA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0cmVzb2x2ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICEoIC0tY291bnQgKSApIHtcblx0XHRcdFx0XHRkZWZlci5yZXNvbHZlV2l0aCggZWxlbWVudHMsIFsgZWxlbWVudHMgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG9iaiA9IHR5cGU7XG5cdFx0XHR0eXBlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdHRtcCA9IGRhdGFQcml2LmdldCggZWxlbWVudHNbIGkgXSwgdHlwZSArIFwicXVldWVIb29rc1wiICk7XG5cdFx0XHRpZiAoIHRtcCAmJiB0bXAuZW1wdHkgKSB7XG5cdFx0XHRcdGNvdW50Kys7XG5cdFx0XHRcdHRtcC5lbXB0eS5hZGQoIHJlc29sdmUgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVzb2x2ZSgpO1xuXHRcdHJldHVybiBkZWZlci5wcm9taXNlKCBvYmogKTtcblx0fVxufSApO1xudmFyIHBudW0gPSAoIC9bKy1dPyg/OlxcZCpcXC58KVxcZCsoPzpbZUVdWystXT9cXGQrfCkvICkuc291cmNlO1xuXG52YXIgcmNzc051bSA9IG5ldyBSZWdFeHAoIFwiXig/OihbKy1dKT18KShcIiArIHBudW0gKyBcIikoW2EteiVdKikkXCIsIFwiaVwiICk7XG5cblxudmFyIGNzc0V4cGFuZCA9IFsgXCJUb3BcIiwgXCJSaWdodFwiLCBcIkJvdHRvbVwiLCBcIkxlZnRcIiBdO1xuXG52YXIgaXNIaWRkZW5XaXRoaW5UcmVlID0gZnVuY3Rpb24oIGVsZW0sIGVsICkge1xuXG5cdFx0Ly8gaXNIaWRkZW5XaXRoaW5UcmVlIG1pZ2h0IGJlIGNhbGxlZCBmcm9tIGpRdWVyeSNmaWx0ZXIgZnVuY3Rpb247XG5cdFx0Ly8gaW4gdGhhdCBjYXNlLCBlbGVtZW50IHdpbGwgYmUgc2Vjb25kIGFyZ3VtZW50XG5cdFx0ZWxlbSA9IGVsIHx8IGVsZW07XG5cblx0XHQvLyBJbmxpbmUgc3R5bGUgdHJ1bXBzIGFsbFxuXHRcdHJldHVybiBlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwibm9uZVwiIHx8XG5cdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwiXCIgJiZcblxuXHRcdFx0Ly8gT3RoZXJ3aXNlLCBjaGVjayBjb21wdXRlZCBzdHlsZVxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCA8PTQzIC0gNDVcblx0XHRcdC8vIERpc2Nvbm5lY3RlZCBlbGVtZW50cyBjYW4gaGF2ZSBjb21wdXRlZCBkaXNwbGF5OiBub25lLCBzbyBmaXJzdCBjb25maXJtIHRoYXQgZWxlbSBpc1xuXHRcdFx0Ly8gaW4gdGhlIGRvY3VtZW50LlxuXHRcdFx0alF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKSAmJlxuXG5cdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApID09PSBcIm5vbmVcIjtcblx0fTtcblxudmFyIHN3YXAgPSBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgY2FsbGJhY2ssIGFyZ3MgKSB7XG5cdHZhciByZXQsIG5hbWUsXG5cdFx0b2xkID0ge307XG5cblx0Ly8gUmVtZW1iZXIgdGhlIG9sZCB2YWx1ZXMsIGFuZCBpbnNlcnQgdGhlIG5ldyBvbmVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRvbGRbIG5hbWUgXSA9IGVsZW0uc3R5bGVbIG5hbWUgXTtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvcHRpb25zWyBuYW1lIF07XG5cdH1cblxuXHRyZXQgPSBjYWxsYmFjay5hcHBseSggZWxlbSwgYXJncyB8fCBbXSApO1xuXG5cdC8vIFJldmVydCB0aGUgb2xkIHZhbHVlc1xuXHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0ZWxlbS5zdHlsZVsgbmFtZSBdID0gb2xkWyBuYW1lIF07XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufTtcblxuXG5cblxuZnVuY3Rpb24gYWRqdXN0Q1NTKCBlbGVtLCBwcm9wLCB2YWx1ZVBhcnRzLCB0d2VlbiApIHtcblx0dmFyIGFkanVzdGVkLFxuXHRcdHNjYWxlID0gMSxcblx0XHRtYXhJdGVyYXRpb25zID0gMjAsXG5cdFx0Y3VycmVudFZhbHVlID0gdHdlZW4gP1xuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiB0d2Vlbi5jdXIoKTtcblx0XHRcdH0gOlxuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wLCBcIlwiICk7XG5cdFx0XHR9LFxuXHRcdGluaXRpYWwgPSBjdXJyZW50VmFsdWUoKSxcblx0XHR1bml0ID0gdmFsdWVQYXJ0cyAmJiB2YWx1ZVBhcnRzWyAzIF0gfHwgKCBqUXVlcnkuY3NzTnVtYmVyWyBwcm9wIF0gPyBcIlwiIDogXCJweFwiICksXG5cblx0XHQvLyBTdGFydGluZyB2YWx1ZSBjb21wdXRhdGlvbiBpcyByZXF1aXJlZCBmb3IgcG90ZW50aWFsIHVuaXQgbWlzbWF0Y2hlc1xuXHRcdGluaXRpYWxJblVuaXQgPSAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSB8fCB1bml0ICE9PSBcInB4XCIgJiYgK2luaXRpYWwgKSAmJlxuXHRcdFx0cmNzc051bS5leGVjKCBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wICkgKTtcblxuXHRpZiAoIGluaXRpYWxJblVuaXQgJiYgaW5pdGlhbEluVW5pdFsgMyBdICE9PSB1bml0ICkge1xuXG5cdFx0Ly8gVHJ1c3QgdW5pdHMgcmVwb3J0ZWQgYnkgalF1ZXJ5LmNzc1xuXHRcdHVuaXQgPSB1bml0IHx8IGluaXRpYWxJblVuaXRbIDMgXTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB3ZSB1cGRhdGUgdGhlIHR3ZWVuIHByb3BlcnRpZXMgbGF0ZXIgb25cblx0XHR2YWx1ZVBhcnRzID0gdmFsdWVQYXJ0cyB8fCBbXTtcblxuXHRcdC8vIEl0ZXJhdGl2ZWx5IGFwcHJveGltYXRlIGZyb20gYSBub256ZXJvIHN0YXJ0aW5nIHBvaW50XG5cdFx0aW5pdGlhbEluVW5pdCA9ICtpbml0aWFsIHx8IDE7XG5cblx0XHRkbyB7XG5cblx0XHRcdC8vIElmIHByZXZpb3VzIGl0ZXJhdGlvbiB6ZXJvZWQgb3V0LCBkb3VibGUgdW50aWwgd2UgZ2V0ICpzb21ldGhpbmcqLlxuXHRcdFx0Ly8gVXNlIHN0cmluZyBmb3IgZG91Ymxpbmcgc28gd2UgZG9uJ3QgYWNjaWRlbnRhbGx5IHNlZSBzY2FsZSBhcyB1bmNoYW5nZWQgYmVsb3dcblx0XHRcdHNjYWxlID0gc2NhbGUgfHwgXCIuNVwiO1xuXG5cdFx0XHQvLyBBZGp1c3QgYW5kIGFwcGx5XG5cdFx0XHRpbml0aWFsSW5Vbml0ID0gaW5pdGlhbEluVW5pdCAvIHNjYWxlO1xuXHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wLCBpbml0aWFsSW5Vbml0ICsgdW5pdCApO1xuXG5cdFx0Ly8gVXBkYXRlIHNjYWxlLCB0b2xlcmF0aW5nIHplcm8gb3IgTmFOIGZyb20gdHdlZW4uY3VyKClcblx0XHQvLyBCcmVhayB0aGUgbG9vcCBpZiBzY2FsZSBpcyB1bmNoYW5nZWQgb3IgcGVyZmVjdCwgb3IgaWYgd2UndmUganVzdCBoYWQgZW5vdWdoLlxuXHRcdH0gd2hpbGUgKFxuXHRcdFx0c2NhbGUgIT09ICggc2NhbGUgPSBjdXJyZW50VmFsdWUoKSAvIGluaXRpYWwgKSAmJiBzY2FsZSAhPT0gMSAmJiAtLW1heEl0ZXJhdGlvbnNcblx0XHQpO1xuXHR9XG5cblx0aWYgKCB2YWx1ZVBhcnRzICkge1xuXHRcdGluaXRpYWxJblVuaXQgPSAraW5pdGlhbEluVW5pdCB8fCAraW5pdGlhbCB8fCAwO1xuXG5cdFx0Ly8gQXBwbHkgcmVsYXRpdmUgb2Zmc2V0ICgrPS8tPSkgaWYgc3BlY2lmaWVkXG5cdFx0YWRqdXN0ZWQgPSB2YWx1ZVBhcnRzWyAxIF0gP1xuXHRcdFx0aW5pdGlhbEluVW5pdCArICggdmFsdWVQYXJ0c1sgMSBdICsgMSApICogdmFsdWVQYXJ0c1sgMiBdIDpcblx0XHRcdCt2YWx1ZVBhcnRzWyAyIF07XG5cdFx0aWYgKCB0d2VlbiApIHtcblx0XHRcdHR3ZWVuLnVuaXQgPSB1bml0O1xuXHRcdFx0dHdlZW4uc3RhcnQgPSBpbml0aWFsSW5Vbml0O1xuXHRcdFx0dHdlZW4uZW5kID0gYWRqdXN0ZWQ7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBhZGp1c3RlZDtcbn1cblxuXG52YXIgZGVmYXVsdERpc3BsYXlNYXAgPSB7fTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKSB7XG5cdHZhciB0ZW1wLFxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudCxcblx0XHRub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUsXG5cdFx0ZGlzcGxheSA9IGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdO1xuXG5cdGlmICggZGlzcGxheSApIHtcblx0XHRyZXR1cm4gZGlzcGxheTtcblx0fVxuXG5cdHRlbXAgPSBkb2MuYm9keS5hcHBlbmRDaGlsZCggZG9jLmNyZWF0ZUVsZW1lbnQoIG5vZGVOYW1lICkgKTtcblx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIHRlbXAsIFwiZGlzcGxheVwiICk7XG5cblx0dGVtcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCB0ZW1wICk7XG5cblx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRkaXNwbGF5ID0gXCJibG9ja1wiO1xuXHR9XG5cdGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdID0gZGlzcGxheTtcblxuXHRyZXR1cm4gZGlzcGxheTtcbn1cblxuZnVuY3Rpb24gc2hvd0hpZGUoIGVsZW1lbnRzLCBzaG93ICkge1xuXHR2YXIgZGlzcGxheSwgZWxlbSxcblx0XHR2YWx1ZXMgPSBbXSxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoO1xuXG5cdC8vIERldGVybWluZSBuZXcgZGlzcGxheSB2YWx1ZSBmb3IgZWxlbWVudHMgdGhhdCBuZWVkIHRvIGNoYW5nZVxuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGVsZW0gPSBlbGVtZW50c1sgaW5kZXggXTtcblx0XHRpZiAoICFlbGVtLnN0eWxlICkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0ZGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheTtcblx0XHRpZiAoIHNob3cgKSB7XG5cblx0XHRcdC8vIFNpbmNlIHdlIGZvcmNlIHZpc2liaWxpdHkgdXBvbiBjYXNjYWRlLWhpZGRlbiBlbGVtZW50cywgYW4gaW1tZWRpYXRlIChhbmQgc2xvdylcblx0XHRcdC8vIGNoZWNrIGlzIHJlcXVpcmVkIGluIHRoaXMgZmlyc3QgbG9vcCB1bmxlc3Mgd2UgaGF2ZSBhIG5vbmVtcHR5IGRpc3BsYXkgdmFsdWUgKGVpdGhlclxuXHRcdFx0Ly8gaW5saW5lIG9yIGFib3V0LXRvLWJlLXJlc3RvcmVkKVxuXHRcdFx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApIHx8IG51bGw7XG5cdFx0XHRcdGlmICggIXZhbHVlc1sgaW5kZXggXSApIHtcblx0XHRcdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJcIiAmJiBpc0hpZGRlbldpdGhpblRyZWUoIGVsZW0gKSApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBkaXNwbGF5ICE9PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gXCJub25lXCI7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgd2hhdCB3ZSdyZSBvdmVyd3JpdGluZ1xuXHRcdFx0XHRkYXRhUHJpdi5zZXQoIGVsZW0sIFwiZGlzcGxheVwiLCBkaXNwbGF5ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gU2V0IHRoZSBkaXNwbGF5IG9mIHRoZSBlbGVtZW50cyBpbiBhIHNlY29uZCBsb29wIHRvIGF2b2lkIGNvbnN0YW50IHJlZmxvd1xuXHRmb3IgKCBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGlmICggdmFsdWVzWyBpbmRleCBdICE9IG51bGwgKSB7XG5cdFx0XHRlbGVtZW50c1sgaW5kZXggXS5zdHlsZS5kaXNwbGF5ID0gdmFsdWVzWyBpbmRleCBdO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50cztcbn1cblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRzaG93OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMsIHRydWUgKTtcblx0fSxcblx0aGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNob3dIaWRlKCB0aGlzICk7XG5cdH0sXG5cdHRvZ2dsZTogZnVuY3Rpb24oIHN0YXRlICkge1xuXHRcdGlmICggdHlwZW9mIHN0YXRlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdHJldHVybiBzdGF0ZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGlzSGlkZGVuV2l0aGluVHJlZSggdGhpcyApICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5zaG93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG52YXIgcmNoZWNrYWJsZVR5cGUgPSAoIC9eKD86Y2hlY2tib3h8cmFkaW8pJC9pICk7XG5cbnZhciBydGFnTmFtZSA9ICggLzwoW2Etel1bXlxcL1xcMD5cXHgyMFxcdFxcclxcblxcZl0rKS9pICk7XG5cbnZhciByc2NyaXB0VHlwZSA9ICggL14kfFxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSApO1xuXG5cblxuLy8gV2UgaGF2ZSB0byBjbG9zZSB0aGVzZSB0YWdzIHRvIHN1cHBvcnQgWEhUTUwgKCMxMzIwMClcbnZhciB3cmFwTWFwID0ge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdG9wdGlvbjogWyAxLCBcIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz5cIiwgXCI8L3NlbGVjdD5cIiBdLFxuXG5cdC8vIFhIVE1MIHBhcnNlcnMgZG8gbm90IG1hZ2ljYWxseSBpbnNlcnQgZWxlbWVudHMgaW4gdGhlXG5cdC8vIHNhbWUgd2F5IHRoYXQgdGFnIHNvdXAgcGFyc2VycyBkby4gU28gd2UgY2Fubm90IHNob3J0ZW5cblx0Ly8gdGhpcyBieSBvbWl0dGluZyA8dGJvZHk+IG9yIG90aGVyIHJlcXVpcmVkIGVsZW1lbnRzLlxuXHR0aGVhZDogWyAxLCBcIjx0YWJsZT5cIiwgXCI8L3RhYmxlPlwiIF0sXG5cdGNvbDogWyAyLCBcIjx0YWJsZT48Y29sZ3JvdXA+XCIsIFwiPC9jb2xncm91cD48L3RhYmxlPlwiIF0sXG5cdHRyOiBbIDIsIFwiPHRhYmxlPjx0Ym9keT5cIiwgXCI8L3Rib2R5PjwvdGFibGU+XCIgXSxcblx0dGQ6IFsgMywgXCI8dGFibGU+PHRib2R5Pjx0cj5cIiwgXCI8L3RyPjwvdGJvZHk+PC90YWJsZT5cIiBdLFxuXG5cdF9kZWZhdWx0OiBbIDAsIFwiXCIsIFwiXCIgXVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbndyYXBNYXAub3B0Z3JvdXAgPSB3cmFwTWFwLm9wdGlvbjtcblxud3JhcE1hcC50Ym9keSA9IHdyYXBNYXAudGZvb3QgPSB3cmFwTWFwLmNvbGdyb3VwID0gd3JhcE1hcC5jYXB0aW9uID0gd3JhcE1hcC50aGVhZDtcbndyYXBNYXAudGggPSB3cmFwTWFwLnRkO1xuXG5cbmZ1bmN0aW9uIGdldEFsbCggY29udGV4dCwgdGFnICkge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0Ly8gVXNlIHR5cGVvZiB0byBhdm9pZCB6ZXJvLWFyZ3VtZW50IG1ldGhvZCBpbnZvY2F0aW9uIG9uIGhvc3Qgb2JqZWN0cyAoIzE1MTUxKVxuXHR2YXIgcmV0O1xuXG5cdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0cmV0ID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnIHx8IFwiKlwiICk7XG5cblx0fSBlbHNlIGlmICggdHlwZW9mIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRyZXQgPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIHRhZyB8fCBcIipcIiApO1xuXG5cdH0gZWxzZSB7XG5cdFx0cmV0ID0gW107XG5cdH1cblxuXHRpZiAoIHRhZyA9PT0gdW5kZWZpbmVkIHx8IHRhZyAmJiBub2RlTmFtZSggY29udGV4dCwgdGFnICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5tZXJnZSggWyBjb250ZXh0IF0sIHJldCApO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuXG4vLyBNYXJrIHNjcmlwdHMgYXMgaGF2aW5nIGFscmVhZHkgYmVlbiBldmFsdWF0ZWRcbmZ1bmN0aW9uIHNldEdsb2JhbEV2YWwoIGVsZW1zLCByZWZFbGVtZW50cyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdGRhdGFQcml2LnNldChcblx0XHRcdGVsZW1zWyBpIF0sXG5cdFx0XHRcImdsb2JhbEV2YWxcIixcblx0XHRcdCFyZWZFbGVtZW50cyB8fCBkYXRhUHJpdi5nZXQoIHJlZkVsZW1lbnRzWyBpIF0sIFwiZ2xvYmFsRXZhbFwiIClcblx0XHQpO1xuXHR9XG59XG5cblxudmFyIHJodG1sID0gLzx8JiM/XFx3KzsvO1xuXG5mdW5jdGlvbiBidWlsZEZyYWdtZW50KCBlbGVtcywgY29udGV4dCwgc2NyaXB0cywgc2VsZWN0aW9uLCBpZ25vcmVkICkge1xuXHR2YXIgZWxlbSwgdG1wLCB0YWcsIHdyYXAsIGNvbnRhaW5zLCBqLFxuXHRcdGZyYWdtZW50ID0gY29udGV4dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksXG5cdFx0bm9kZXMgPSBbXSxcblx0XHRpID0gMCxcblx0XHRsID0gZWxlbXMubGVuZ3RoO1xuXG5cdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRlbGVtID0gZWxlbXNbIGkgXTtcblxuXHRcdGlmICggZWxlbSB8fCBlbGVtID09PSAwICkge1xuXG5cdFx0XHQvLyBBZGQgbm9kZXMgZGlyZWN0bHlcblx0XHRcdGlmICggalF1ZXJ5LnR5cGUoIGVsZW0gKSA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0XHRcdFx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIG5vZGVzLCBlbGVtLm5vZGVUeXBlID8gWyBlbGVtIF0gOiBlbGVtICk7XG5cblx0XHRcdC8vIENvbnZlcnQgbm9uLWh0bWwgaW50byBhIHRleHQgbm9kZVxuXHRcdFx0fSBlbHNlIGlmICggIXJodG1sLnRlc3QoIGVsZW0gKSApIHtcblx0XHRcdFx0bm9kZXMucHVzaCggY29udGV4dC5jcmVhdGVUZXh0Tm9kZSggZWxlbSApICk7XG5cblx0XHRcdC8vIENvbnZlcnQgaHRtbCBpbnRvIERPTSBub2Rlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dG1wID0gdG1wIHx8IGZyYWdtZW50LmFwcGVuZENoaWxkKCBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSApO1xuXG5cdFx0XHRcdC8vIERlc2VyaWFsaXplIGEgc3RhbmRhcmQgcmVwcmVzZW50YXRpb25cblx0XHRcdFx0dGFnID0gKCBydGFnTmFtZS5leGVjKCBlbGVtICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdHdyYXAgPSB3cmFwTWFwWyB0YWcgXSB8fCB3cmFwTWFwLl9kZWZhdWx0O1xuXHRcdFx0XHR0bXAuaW5uZXJIVE1MID0gd3JhcFsgMSBdICsgalF1ZXJ5Lmh0bWxQcmVmaWx0ZXIoIGVsZW0gKSArIHdyYXBbIDIgXTtcblxuXHRcdFx0XHQvLyBEZXNjZW5kIHRocm91Z2ggd3JhcHBlcnMgdG8gdGhlIHJpZ2h0IGNvbnRlbnRcblx0XHRcdFx0aiA9IHdyYXBbIDAgXTtcblx0XHRcdFx0d2hpbGUgKCBqLS0gKSB7XG5cdFx0XHRcdFx0dG1wID0gdG1wLmxhc3RDaGlsZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIHRtcC5jaGlsZE5vZGVzICk7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgdGhlIHRvcC1sZXZlbCBjb250YWluZXJcblx0XHRcdFx0dG1wID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuXHRcdFx0XHQvLyBFbnN1cmUgdGhlIGNyZWF0ZWQgbm9kZXMgYXJlIG9ycGhhbmVkICgjMTIzOTIpXG5cdFx0XHRcdHRtcC50ZXh0Q29udGVudCA9IFwiXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmVtb3ZlIHdyYXBwZXIgZnJvbSBmcmFnbWVudFxuXHRmcmFnbWVudC50ZXh0Q29udGVudCA9IFwiXCI7XG5cblx0aSA9IDA7XG5cdHdoaWxlICggKCBlbGVtID0gbm9kZXNbIGkrKyBdICkgKSB7XG5cblx0XHQvLyBTa2lwIGVsZW1lbnRzIGFscmVhZHkgaW4gdGhlIGNvbnRleHQgY29sbGVjdGlvbiAodHJhYy00MDg3KVxuXHRcdGlmICggc2VsZWN0aW9uICYmIGpRdWVyeS5pbkFycmF5KCBlbGVtLCBzZWxlY3Rpb24gKSA+IC0xICkge1xuXHRcdFx0aWYgKCBpZ25vcmVkICkge1xuXHRcdFx0XHRpZ25vcmVkLnB1c2goIGVsZW0gKTtcblx0XHRcdH1cblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblxuXHRcdGNvbnRhaW5zID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdC8vIEFwcGVuZCB0byBmcmFnbWVudFxuXHRcdHRtcCA9IGdldEFsbCggZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGVsZW0gKSwgXCJzY3JpcHRcIiApO1xuXG5cdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdGlmICggY29udGFpbnMgKSB7XG5cdFx0XHRzZXRHbG9iYWxFdmFsKCB0bXAgKTtcblx0XHR9XG5cblx0XHQvLyBDYXB0dXJlIGV4ZWN1dGFibGVzXG5cdFx0aWYgKCBzY3JpcHRzICkge1xuXHRcdFx0aiA9IDA7XG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRtcFsgaisrIF0gKSApIHtcblx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBlbGVtLnR5cGUgfHwgXCJcIiApICkge1xuXHRcdFx0XHRcdHNjcmlwdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGZyYWdtZW50O1xufVxuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRkaXYgPSBmcmFnbWVudC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApICksXG5cdFx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCAtIDQuMyBvbmx5XG5cdC8vIENoZWNrIHN0YXRlIGxvc3QgaWYgdGhlIG5hbWUgaXMgc2V0ICgjMTEyMTcpXG5cdC8vIFN1cHBvcnQ6IFdpbmRvd3MgV2ViIEFwcHMgKFdXQSlcblx0Ly8gYG5hbWVgIGFuZCBgdHlwZWAgbXVzdCB1c2UgLnNldEF0dHJpYnV0ZSBmb3IgV1dBICgjMTQ5MDEpXG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIFwicmFkaW9cIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwiY2hlY2tlZFwiLCBcImNoZWNrZWRcIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcInRcIiApO1xuXG5cdGRpdi5hcHBlbmRDaGlsZCggaW5wdXQgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4xIG9ubHlcblx0Ly8gT2xkZXIgV2ViS2l0IGRvZXNuJ3QgY2xvbmUgY2hlY2tlZCBzdGF0ZSBjb3JyZWN0bHkgaW4gZnJhZ21lbnRzXG5cdHN1cHBvcnQuY2hlY2tDbG9uZSA9IGRpdi5jbG9uZU5vZGUoIHRydWUgKS5jbG9uZU5vZGUoIHRydWUgKS5sYXN0Q2hpbGQuY2hlY2tlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHRleHRhcmVhIChhbmQgY2hlY2tib3gpIGRlZmF1bHRWYWx1ZSBpcyBwcm9wZXJseSBjbG9uZWRcblx0ZGl2LmlubmVySFRNTCA9IFwiPHRleHRhcmVhPng8L3RleHRhcmVhPlwiO1xuXHRzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkID0gISFkaXYuY2xvbmVOb2RlKCB0cnVlICkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZTtcbn0gKSgpO1xudmFyIGRvY3VtZW50RWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuXG5cbnZhclxuXHRya2V5RXZlbnQgPSAvXmtleS8sXG5cdHJtb3VzZUV2ZW50ID0gL14oPzptb3VzZXxwb2ludGVyfGNvbnRleHRtZW51fGRyYWd8ZHJvcCl8Y2xpY2svLFxuXHRydHlwZW5hbWVzcGFjZSA9IC9eKFteLl0qKSg/OlxcLiguKyl8KS87XG5cbmZ1bmN0aW9uIHJldHVyblRydWUoKSB7XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZXR1cm5GYWxzZSgpIHtcblx0cmV0dXJuIGZhbHNlO1xufVxuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuLy8gU2VlICMxMzM5MyBmb3IgbW9yZSBpbmZvXG5mdW5jdGlvbiBzYWZlQWN0aXZlRWxlbWVudCgpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblx0fSBjYXRjaCAoIGVyciApIHsgfVxufVxuXG5mdW5jdGlvbiBvbiggZWxlbSwgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgb25lICkge1xuXHR2YXIgb3JpZ0ZuLCB0eXBlO1xuXG5cdC8vIFR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xuXHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdC8vICggdHlwZXMtT2JqZWN0LCBzZWxlY3RvciwgZGF0YSApXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMtT2JqZWN0LCBkYXRhIClcblx0XHRcdGRhdGEgPSBkYXRhIHx8IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRvbiggZWxlbSwgdHlwZSwgc2VsZWN0b3IsIGRhdGEsIHR5cGVzWyB0eXBlIF0sIG9uZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbTtcblx0fVxuXG5cdGlmICggZGF0YSA9PSBudWxsICYmIGZuID09IG51bGwgKSB7XG5cblx0XHQvLyAoIHR5cGVzLCBmbiApXG5cdFx0Zm4gPSBzZWxlY3Rvcjtcblx0XHRkYXRhID0gc2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdH0gZWxzZSBpZiAoIGZuID09IG51bGwgKSB7XG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMsIHNlbGVjdG9yLCBmbiApXG5cdFx0XHRmbiA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vICggdHlwZXMsIGRhdGEsIGZuIClcblx0XHRcdGZuID0gZGF0YTtcblx0XHRcdGRhdGEgPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRpZiAoIGZuID09PSBmYWxzZSApIHtcblx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHR9IGVsc2UgaWYgKCAhZm4gKSB7XG5cdFx0cmV0dXJuIGVsZW07XG5cdH1cblxuXHRpZiAoIG9uZSA9PT0gMSApIHtcblx0XHRvcmlnRm4gPSBmbjtcblx0XHRmbiA9IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0Ly8gQ2FuIHVzZSBhbiBlbXB0eSBzZXQsIHNpbmNlIGV2ZW50IGNvbnRhaW5zIHRoZSBpbmZvXG5cdFx0XHRqUXVlcnkoKS5vZmYoIGV2ZW50ICk7XG5cdFx0XHRyZXR1cm4gb3JpZ0ZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9O1xuXG5cdFx0Ly8gVXNlIHNhbWUgZ3VpZCBzbyBjYWxsZXIgY2FuIHJlbW92ZSB1c2luZyBvcmlnRm5cblx0XHRmbi5ndWlkID0gb3JpZ0ZuLmd1aWQgfHwgKCBvcmlnRm4uZ3VpZCA9IGpRdWVyeS5ndWlkKysgKTtcblx0fVxuXHRyZXR1cm4gZWxlbS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRqUXVlcnkuZXZlbnQuYWRkKCB0aGlzLCB0eXBlcywgZm4sIGRhdGEsIHNlbGVjdG9yICk7XG5cdH0gKTtcbn1cblxuLypcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIG1hbmFnaW5nIGV2ZW50cyAtLSBub3QgcGFydCBvZiB0aGUgcHVibGljIGludGVyZmFjZS5cbiAqIFByb3BzIHRvIERlYW4gRWR3YXJkcycgYWRkRXZlbnQgbGlicmFyeSBmb3IgbWFueSBvZiB0aGUgaWRlYXMuXG4gKi9cbmpRdWVyeS5ldmVudCA9IHtcblxuXHRnbG9iYWw6IHt9LFxuXG5cdGFkZDogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBkYXRhLCBzZWxlY3RvciApIHtcblxuXHRcdHZhciBoYW5kbGVPYmpJbiwgZXZlbnRIYW5kbGUsIHRtcCxcblx0XHRcdGV2ZW50cywgdCwgaGFuZGxlT2JqLFxuXHRcdFx0c3BlY2lhbCwgaGFuZGxlcnMsIHR5cGUsIG5hbWVzcGFjZXMsIG9yaWdUeXBlLFxuXHRcdFx0ZWxlbURhdGEgPSBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdC8vIERvbid0IGF0dGFjaCBldmVudHMgdG8gbm9EYXRhIG9yIHRleHQvY29tbWVudCBub2RlcyAoYnV0IGFsbG93IHBsYWluIG9iamVjdHMpXG5cdFx0aWYgKCAhZWxlbURhdGEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGVyIGNhbiBwYXNzIGluIGFuIG9iamVjdCBvZiBjdXN0b20gZGF0YSBpbiBsaWV1IG9mIHRoZSBoYW5kbGVyXG5cdFx0aWYgKCBoYW5kbGVyLmhhbmRsZXIgKSB7XG5cdFx0XHRoYW5kbGVPYmpJbiA9IGhhbmRsZXI7XG5cdFx0XHRoYW5kbGVyID0gaGFuZGxlT2JqSW4uaGFuZGxlcjtcblx0XHRcdHNlbGVjdG9yID0gaGFuZGxlT2JqSW4uc2VsZWN0b3I7XG5cdFx0fVxuXG5cdFx0Ly8gRW5zdXJlIHRoYXQgaW52YWxpZCBzZWxlY3RvcnMgdGhyb3cgZXhjZXB0aW9ucyBhdCBhdHRhY2ggdGltZVxuXHRcdC8vIEV2YWx1YXRlIGFnYWluc3QgZG9jdW1lbnRFbGVtZW50IGluIGNhc2UgZWxlbSBpcyBhIG5vbi1lbGVtZW50IG5vZGUgKGUuZy4sIGRvY3VtZW50KVxuXHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRqUXVlcnkuZmluZC5tYXRjaGVzU2VsZWN0b3IoIGRvY3VtZW50RWxlbWVudCwgc2VsZWN0b3IgKTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB0aGUgaGFuZGxlciBoYXMgYSB1bmlxdWUgSUQsIHVzZWQgdG8gZmluZC9yZW1vdmUgaXQgbGF0ZXJcblx0XHRpZiAoICFoYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRoYW5kbGVyLmd1aWQgPSBqUXVlcnkuZ3VpZCsrO1xuXHRcdH1cblxuXHRcdC8vIEluaXQgdGhlIGVsZW1lbnQncyBldmVudCBzdHJ1Y3R1cmUgYW5kIG1haW4gaGFuZGxlciwgaWYgdGhpcyBpcyB0aGUgZmlyc3Rcblx0XHRpZiAoICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0ZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzID0ge307XG5cdFx0fVxuXHRcdGlmICggISggZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgKSApIHtcblx0XHRcdGV2ZW50SGFuZGxlID0gZWxlbURhdGEuaGFuZGxlID0gZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdFx0Ly8gRGlzY2FyZCB0aGUgc2Vjb25kIGV2ZW50IG9mIGEgalF1ZXJ5LmV2ZW50LnRyaWdnZXIoKSBhbmRcblx0XHRcdFx0Ly8gd2hlbiBhbiBldmVudCBpcyBjYWxsZWQgYWZ0ZXIgYSBwYWdlIGhhcyB1bmxvYWRlZFxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICE9PSBlLnR5cGUgP1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5kaXNwYXRjaC5hcHBseSggZWxlbSwgYXJndW1lbnRzICkgOiB1bmRlZmluZWQ7XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIEhhbmRsZSBtdWx0aXBsZSBldmVudHMgc2VwYXJhdGVkIGJ5IGEgc3BhY2Vcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVGhlcmUgKm11c3QqIGJlIGEgdHlwZSwgbm8gYXR0YWNoaW5nIG5hbWVzcGFjZS1vbmx5IGhhbmRsZXJzXG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgZXZlbnQgY2hhbmdlcyBpdHMgdHlwZSwgdXNlIHRoZSBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgY2hhbmdlZCB0eXBlXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblxuXHRcdFx0Ly8gSWYgc2VsZWN0b3IgZGVmaW5lZCwgZGV0ZXJtaW5lIHNwZWNpYWwgZXZlbnQgYXBpIHR5cGUsIG90aGVyd2lzZSBnaXZlbiB0eXBlXG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cblx0XHRcdC8vIFVwZGF0ZSBzcGVjaWFsIGJhc2VkIG9uIG5ld2x5IHJlc2V0IHR5cGVcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXG5cdFx0XHQvLyBoYW5kbGVPYmogaXMgcGFzc2VkIHRvIGFsbCBldmVudCBoYW5kbGVyc1xuXHRcdFx0aGFuZGxlT2JqID0galF1ZXJ5LmV4dGVuZCgge1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRvcmlnVHlwZTogb3JpZ1R5cGUsXG5cdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdGhhbmRsZXI6IGhhbmRsZXIsXG5cdFx0XHRcdGd1aWQ6IGhhbmRsZXIuZ3VpZCxcblx0XHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0XHRuZWVkc0NvbnRleHQ6IHNlbGVjdG9yICYmIGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KCBzZWxlY3RvciApLFxuXHRcdFx0XHRuYW1lc3BhY2U6IG5hbWVzcGFjZXMuam9pbiggXCIuXCIgKVxuXHRcdFx0fSwgaGFuZGxlT2JqSW4gKTtcblxuXHRcdFx0Ly8gSW5pdCB0aGUgZXZlbnQgaGFuZGxlciBxdWV1ZSBpZiB3ZSdyZSB0aGUgZmlyc3Rcblx0XHRcdGlmICggISggaGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSApICkge1xuXHRcdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdID0gW107XG5cdFx0XHRcdGhhbmRsZXJzLmRlbGVnYXRlQ291bnQgPSAwO1xuXG5cdFx0XHRcdC8vIE9ubHkgdXNlIGFkZEV2ZW50TGlzdGVuZXIgaWYgdGhlIHNwZWNpYWwgZXZlbnRzIGhhbmRsZXIgcmV0dXJucyBmYWxzZVxuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnNldHVwIHx8XG5cdFx0XHRcdFx0c3BlY2lhbC5zZXR1cC5jYWxsKCBlbGVtLCBkYXRhLCBuYW1lc3BhY2VzLCBldmVudEhhbmRsZSApID09PSBmYWxzZSApIHtcblxuXHRcdFx0XHRcdGlmICggZWxlbS5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5hZGRFdmVudExpc3RlbmVyKCB0eXBlLCBldmVudEhhbmRsZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHNwZWNpYWwuYWRkICkge1xuXHRcdFx0XHRzcGVjaWFsLmFkZC5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblxuXHRcdFx0XHRpZiAoICFoYW5kbGVPYmouaGFuZGxlci5ndWlkICkge1xuXHRcdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyLmd1aWQgPSBoYW5kbGVyLmd1aWQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIHRvIHRoZSBlbGVtZW50J3MgaGFuZGxlciBsaXN0LCBkZWxlZ2F0ZXMgaW4gZnJvbnRcblx0XHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaGFuZGxlcnMuZGVsZWdhdGVDb3VudCsrLCAwLCBoYW5kbGVPYmogKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGhhbmRsZXJzLnB1c2goIGhhbmRsZU9iaiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBLZWVwIHRyYWNrIG9mIHdoaWNoIGV2ZW50cyBoYXZlIGV2ZXIgYmVlbiB1c2VkLCBmb3IgZXZlbnQgb3B0aW1pemF0aW9uXG5cdFx0XHRqUXVlcnkuZXZlbnQuZ2xvYmFsWyB0eXBlIF0gPSB0cnVlO1xuXHRcdH1cblxuXHR9LFxuXG5cdC8vIERldGFjaCBhbiBldmVudCBvciBzZXQgb2YgZXZlbnRzIGZyb20gYW4gZWxlbWVudFxuXHRyZW1vdmU6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlcywgaGFuZGxlciwgc2VsZWN0b3IsIG1hcHBlZFR5cGVzICkge1xuXG5cdFx0dmFyIGosIG9yaWdDb3VudCwgdG1wLFxuXHRcdFx0ZXZlbnRzLCB0LCBoYW5kbGVPYmosXG5cdFx0XHRzcGVjaWFsLCBoYW5kbGVycywgdHlwZSwgbmFtZXNwYWNlcywgb3JpZ1R5cGUsXG5cdFx0XHRlbGVtRGF0YSA9IGRhdGFQcml2Lmhhc0RhdGEoIGVsZW0gKSAmJiBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdGlmICggIWVsZW1EYXRhIHx8ICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIE9uY2UgZm9yIGVhY2ggdHlwZS5uYW1lc3BhY2UgaW4gdHlwZXM7IHR5cGUgbWF5IGJlIG9taXR0ZWRcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVW5iaW5kIGFsbCBldmVudHMgKG9uIHRoaXMgbmFtZXNwYWNlLCBpZiBwcm92aWRlZCkgZm9yIHRoZSBlbGVtZW50XG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCBlbGVtLCB0eXBlICsgdHlwZXNbIHQgXSwgaGFuZGxlciwgc2VsZWN0b3IsIHRydWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdIHx8IFtdO1xuXHRcdFx0dG1wID0gdG1wWyAyIF0gJiZcblx0XHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICk7XG5cblx0XHRcdC8vIFJlbW92ZSBtYXRjaGluZyBldmVudHNcblx0XHRcdG9yaWdDb3VudCA9IGogPSBoYW5kbGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGogXTtcblxuXHRcdFx0XHRpZiAoICggbWFwcGVkVHlwZXMgfHwgb3JpZ1R5cGUgPT09IGhhbmRsZU9iai5vcmlnVHlwZSApICYmXG5cdFx0XHRcdFx0KCAhaGFuZGxlciB8fCBoYW5kbGVyLmd1aWQgPT09IGhhbmRsZU9iai5ndWlkICkgJiZcblx0XHRcdFx0XHQoICF0bXAgfHwgdG1wLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApICYmXG5cdFx0XHRcdFx0KCAhc2VsZWN0b3IgfHwgc2VsZWN0b3IgPT09IGhhbmRsZU9iai5zZWxlY3RvciB8fFxuXHRcdFx0XHRcdFx0c2VsZWN0b3IgPT09IFwiKipcIiAmJiBoYW5kbGVPYmouc2VsZWN0b3IgKSApIHtcblx0XHRcdFx0XHRoYW5kbGVycy5zcGxpY2UoIGosIDEgKTtcblxuXHRcdFx0XHRcdGlmICggaGFuZGxlT2JqLnNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudC0tO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIHNwZWNpYWwucmVtb3ZlICkge1xuXHRcdFx0XHRcdFx0c3BlY2lhbC5yZW1vdmUuY2FsbCggZWxlbSwgaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlbW92ZSBnZW5lcmljIGV2ZW50IGhhbmRsZXIgaWYgd2UgcmVtb3ZlZCBzb21ldGhpbmcgYW5kIG5vIG1vcmUgaGFuZGxlcnMgZXhpc3Rcblx0XHRcdC8vIChhdm9pZHMgcG90ZW50aWFsIGZvciBlbmRsZXNzIHJlY3Vyc2lvbiBkdXJpbmcgcmVtb3ZhbCBvZiBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzKVxuXHRcdFx0aWYgKCBvcmlnQ291bnQgJiYgIWhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0aWYgKCAhc3BlY2lhbC50ZWFyZG93biB8fFxuXHRcdFx0XHRcdHNwZWNpYWwudGVhcmRvd24uY2FsbCggZWxlbSwgbmFtZXNwYWNlcywgZWxlbURhdGEuaGFuZGxlICkgPT09IGZhbHNlICkge1xuXG5cdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBlbGVtRGF0YS5oYW5kbGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlbGV0ZSBldmVudHNbIHR5cGUgXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgZGF0YSBhbmQgdGhlIGV4cGFuZG8gaWYgaXQncyBubyBsb25nZXIgdXNlZFxuXHRcdGlmICggalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGV2ZW50cyApICkge1xuXHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBlbGVtLCBcImhhbmRsZSBldmVudHNcIiApO1xuXHRcdH1cblx0fSxcblxuXHRkaXNwYXRjaDogZnVuY3Rpb24oIG5hdGl2ZUV2ZW50ICkge1xuXG5cdFx0Ly8gTWFrZSBhIHdyaXRhYmxlIGpRdWVyeS5FdmVudCBmcm9tIHRoZSBuYXRpdmUgZXZlbnQgb2JqZWN0XG5cdFx0dmFyIGV2ZW50ID0galF1ZXJ5LmV2ZW50LmZpeCggbmF0aXZlRXZlbnQgKTtcblxuXHRcdHZhciBpLCBqLCByZXQsIG1hdGNoZWQsIGhhbmRsZU9iaiwgaGFuZGxlclF1ZXVlLFxuXHRcdFx0YXJncyA9IG5ldyBBcnJheSggYXJndW1lbnRzLmxlbmd0aCApLFxuXHRcdFx0aGFuZGxlcnMgPSAoIGRhdGFQcml2LmdldCggdGhpcywgXCJldmVudHNcIiApIHx8IHt9IClbIGV2ZW50LnR5cGUgXSB8fCBbXSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZXZlbnQudHlwZSBdIHx8IHt9O1xuXG5cdFx0Ly8gVXNlIHRoZSBmaXgtZWQgalF1ZXJ5LkV2ZW50IHJhdGhlciB0aGFuIHRoZSAocmVhZC1vbmx5KSBuYXRpdmUgZXZlbnRcblx0XHRhcmdzWyAwIF0gPSBldmVudDtcblxuXHRcdGZvciAoIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0YXJnc1sgaSBdID0gYXJndW1lbnRzWyBpIF07XG5cdFx0fVxuXG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSB0aGlzO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgcHJlRGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlLCBhbmQgbGV0IGl0IGJhaWwgaWYgZGVzaXJlZFxuXHRcdGlmICggc3BlY2lhbC5wcmVEaXNwYXRjaCAmJiBzcGVjaWFsLnByZURpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBoYW5kbGVyc1xuXHRcdGhhbmRsZXJRdWV1ZSA9IGpRdWVyeS5ldmVudC5oYW5kbGVycy5jYWxsKCB0aGlzLCBldmVudCwgaGFuZGxlcnMgKTtcblxuXHRcdC8vIFJ1biBkZWxlZ2F0ZXMgZmlyc3Q7IHRoZXkgbWF5IHdhbnQgdG8gc3RvcCBwcm9wYWdhdGlvbiBiZW5lYXRoIHVzXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoIG1hdGNoZWQgPSBoYW5kbGVyUXVldWVbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cdFx0XHRldmVudC5jdXJyZW50VGFyZ2V0ID0gbWF0Y2hlZC5lbGVtO1xuXG5cdFx0XHRqID0gMDtcblx0XHRcdHdoaWxlICggKCBoYW5kbGVPYmogPSBtYXRjaGVkLmhhbmRsZXJzWyBqKysgXSApICYmXG5cdFx0XHRcdCFldmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpICkge1xuXG5cdFx0XHRcdC8vIFRyaWdnZXJlZCBldmVudCBtdXN0IGVpdGhlciAxKSBoYXZlIG5vIG5hbWVzcGFjZSwgb3IgMikgaGF2ZSBuYW1lc3BhY2Uocylcblx0XHRcdFx0Ly8gYSBzdWJzZXQgb3IgZXF1YWwgdG8gdGhvc2UgaW4gdGhlIGJvdW5kIGV2ZW50IChib3RoIGNhbiBoYXZlIG5vIG5hbWVzcGFjZSkuXG5cdFx0XHRcdGlmICggIWV2ZW50LnJuYW1lc3BhY2UgfHwgZXZlbnQucm5hbWVzcGFjZS50ZXN0KCBoYW5kbGVPYmoubmFtZXNwYWNlICkgKSB7XG5cblx0XHRcdFx0XHRldmVudC5oYW5kbGVPYmogPSBoYW5kbGVPYmo7XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSA9IGhhbmRsZU9iai5kYXRhO1xuXG5cdFx0XHRcdFx0cmV0ID0gKCAoIGpRdWVyeS5ldmVudC5zcGVjaWFsWyBoYW5kbGVPYmoub3JpZ1R5cGUgXSB8fCB7fSApLmhhbmRsZSB8fFxuXHRcdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIgKS5hcHBseSggbWF0Y2hlZC5lbGVtLCBhcmdzICk7XG5cblx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoIGV2ZW50LnJlc3VsdCA9IHJldCApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbCB0aGUgcG9zdERpc3BhdGNoIGhvb2sgZm9yIHRoZSBtYXBwZWQgdHlwZVxuXHRcdGlmICggc3BlY2lhbC5wb3N0RGlzcGF0Y2ggKSB7XG5cdFx0XHRzcGVjaWFsLnBvc3REaXNwYXRjaC5jYWxsKCB0aGlzLCBldmVudCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBldmVudC5yZXN1bHQ7XG5cdH0sXG5cblx0aGFuZGxlcnM6IGZ1bmN0aW9uKCBldmVudCwgaGFuZGxlcnMgKSB7XG5cdFx0dmFyIGksIGhhbmRsZU9iaiwgc2VsLCBtYXRjaGVkSGFuZGxlcnMsIG1hdGNoZWRTZWxlY3RvcnMsXG5cdFx0XHRoYW5kbGVyUXVldWUgPSBbXSxcblx0XHRcdGRlbGVnYXRlQ291bnQgPSBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LFxuXHRcdFx0Y3VyID0gZXZlbnQudGFyZ2V0O1xuXG5cdFx0Ly8gRmluZCBkZWxlZ2F0ZSBoYW5kbGVyc1xuXHRcdGlmICggZGVsZWdhdGVDb3VudCAmJlxuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTlcblx0XHRcdC8vIEJsYWNrLWhvbGUgU1ZHIDx1c2U+IGluc3RhbmNlIHRyZWVzICh0cmFjLTEzMTgwKVxuXHRcdFx0Y3VyLm5vZGVUeXBlICYmXG5cblx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggPD00MlxuXHRcdFx0Ly8gU3VwcHJlc3Mgc3BlYy12aW9sYXRpbmcgY2xpY2tzIGluZGljYXRpbmcgYSBub24tcHJpbWFyeSBwb2ludGVyIGJ1dHRvbiAodHJhYy0zODYxKVxuXHRcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnQtdHlwZS1jbGlja1xuXHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0Ly8gLi4uYnV0IG5vdCBhcnJvdyBrZXkgXCJjbGlja3NcIiBvZiByYWRpbyBpbnB1dHMsIHdoaWNoIGNhbiBoYXZlIGBidXR0b25gIC0xIChnaC0yMzQzKVxuXHRcdFx0ISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGV2ZW50LmJ1dHRvbiA+PSAxICkgKSB7XG5cblx0XHRcdGZvciAoIDsgY3VyICE9PSB0aGlzOyBjdXIgPSBjdXIucGFyZW50Tm9kZSB8fCB0aGlzICkge1xuXG5cdFx0XHRcdC8vIERvbid0IGNoZWNrIG5vbi1lbGVtZW50cyAoIzEzMjA4KVxuXHRcdFx0XHQvLyBEb24ndCBwcm9jZXNzIGNsaWNrcyBvbiBkaXNhYmxlZCBlbGVtZW50cyAoIzY5MTEsICM4MTY1LCAjMTEzODIsICMxMTc2NClcblx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPT09IDEgJiYgISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGN1ci5kaXNhYmxlZCA9PT0gdHJ1ZSApICkge1xuXHRcdFx0XHRcdG1hdGNoZWRIYW5kbGVycyA9IFtdO1xuXHRcdFx0XHRcdG1hdGNoZWRTZWxlY3RvcnMgPSB7fTtcblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGRlbGVnYXRlQ291bnQ7IGkrKyApIHtcblx0XHRcdFx0XHRcdGhhbmRsZU9iaiA9IGhhbmRsZXJzWyBpIF07XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IGNvbmZsaWN0IHdpdGggT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzICgjMTMyMDMpXG5cdFx0XHRcdFx0XHRzZWwgPSBoYW5kbGVPYmouc2VsZWN0b3IgKyBcIiBcIjtcblxuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9IGhhbmRsZU9iai5uZWVkc0NvbnRleHQgP1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggc2VsLCB0aGlzICkuaW5kZXgoIGN1ciApID4gLTEgOlxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kKCBzZWwsIHRoaXMsIG51bGwsIFsgY3VyIF0gKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkSGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggbWF0Y2hlZEhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdGhhbmRsZXJRdWV1ZS5wdXNoKCB7IGVsZW06IGN1ciwgaGFuZGxlcnM6IG1hdGNoZWRIYW5kbGVycyB9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIHRoZSByZW1haW5pbmcgKGRpcmVjdGx5LWJvdW5kKSBoYW5kbGVyc1xuXHRcdGN1ciA9IHRoaXM7XG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50IDwgaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goIHsgZWxlbTogY3VyLCBoYW5kbGVyczogaGFuZGxlcnMuc2xpY2UoIGRlbGVnYXRlQ291bnQgKSB9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGhhbmRsZXJRdWV1ZTtcblx0fSxcblxuXHRhZGRQcm9wOiBmdW5jdGlvbiggbmFtZSwgaG9vayApIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIGpRdWVyeS5FdmVudC5wcm90b3R5cGUsIG5hbWUsIHtcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cblx0XHRcdGdldDogalF1ZXJ5LmlzRnVuY3Rpb24oIGhvb2sgKSA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaG9vayggdGhpcy5vcmlnaW5hbEV2ZW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IDpcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnRbIG5hbWUgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cblx0XHRcdHNldDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIHRoaXMsIG5hbWUsIHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRmaXg6IGZ1bmN0aW9uKCBvcmlnaW5hbEV2ZW50ICkge1xuXHRcdHJldHVybiBvcmlnaW5hbEV2ZW50WyBqUXVlcnkuZXhwYW5kbyBdID9cblx0XHRcdG9yaWdpbmFsRXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggb3JpZ2luYWxFdmVudCApO1xuXHR9LFxuXG5cdHNwZWNpYWw6IHtcblx0XHRsb2FkOiB7XG5cblx0XHRcdC8vIFByZXZlbnQgdHJpZ2dlcmVkIGltYWdlLmxvYWQgZXZlbnRzIGZyb20gYnViYmxpbmcgdG8gd2luZG93LmxvYWRcblx0XHRcdG5vQnViYmxlOiB0cnVlXG5cdFx0fSxcblx0XHRmb2N1czoge1xuXG5cdFx0XHQvLyBGaXJlIG5hdGl2ZSBldmVudCBpZiBwb3NzaWJsZSBzbyBibHVyL2ZvY3VzIHNlcXVlbmNlIGlzIGNvcnJlY3Rcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMgIT09IHNhZmVBY3RpdmVFbGVtZW50KCkgJiYgdGhpcy5mb2N1cyApIHtcblx0XHRcdFx0XHR0aGlzLmZvY3VzKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3VzaW5cIlxuXHRcdH0sXG5cdFx0Ymx1cjoge1xuXHRcdFx0dHJpZ2dlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdGhpcyA9PT0gc2FmZUFjdGl2ZUVsZW1lbnQoKSAmJiB0aGlzLmJsdXIgKSB7XG5cdFx0XHRcdFx0dGhpcy5ibHVyKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3Vzb3V0XCJcblx0XHR9LFxuXHRcdGNsaWNrOiB7XG5cblx0XHRcdC8vIEZvciBjaGVja2JveCwgZmlyZSBuYXRpdmUgZXZlbnQgc28gY2hlY2tlZCBzdGF0ZSB3aWxsIGJlIHJpZ2h0XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzLnR5cGUgPT09IFwiY2hlY2tib3hcIiAmJiB0aGlzLmNsaWNrICYmIG5vZGVOYW1lKCB0aGlzLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR0aGlzLmNsaWNrKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGb3IgY3Jvc3MtYnJvd3NlciBjb25zaXN0ZW5jeSwgZG9uJ3QgZmlyZSBuYXRpdmUgLmNsaWNrKCkgb24gbGlua3Ncblx0XHRcdF9kZWZhdWx0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHJldHVybiBub2RlTmFtZSggZXZlbnQudGFyZ2V0LCBcImFcIiApO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRiZWZvcmV1bmxvYWQ6IHtcblx0XHRcdHBvc3REaXNwYXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggMjArXG5cdFx0XHRcdC8vIEZpcmVmb3ggZG9lc24ndCBhbGVydCBpZiB0aGUgcmV0dXJuVmFsdWUgZmllbGQgaXMgbm90IHNldC5cblx0XHRcdFx0aWYgKCBldmVudC5yZXN1bHQgIT09IHVuZGVmaW5lZCAmJiBldmVudC5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdGV2ZW50Lm9yaWdpbmFsRXZlbnQucmV0dXJuVmFsdWUgPSBldmVudC5yZXN1bHQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn07XG5cbmpRdWVyeS5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCBoYW5kbGUgKSB7XG5cblx0Ly8gVGhpcyBcImlmXCIgaXMgbmVlZGVkIGZvciBwbGFpbiBvYmplY3RzXG5cdGlmICggZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyICkge1xuXHRcdGVsZW0ucmVtb3ZlRXZlbnRMaXN0ZW5lciggdHlwZSwgaGFuZGxlICk7XG5cdH1cbn07XG5cbmpRdWVyeS5FdmVudCA9IGZ1bmN0aW9uKCBzcmMsIHByb3BzICkge1xuXG5cdC8vIEFsbG93IGluc3RhbnRpYXRpb24gd2l0aG91dCB0aGUgJ25ldycga2V5d29yZFxuXHRpZiAoICEoIHRoaXMgaW5zdGFuY2VvZiBqUXVlcnkuRXZlbnQgKSApIHtcblx0XHRyZXR1cm4gbmV3IGpRdWVyeS5FdmVudCggc3JjLCBwcm9wcyApO1xuXHR9XG5cblx0Ly8gRXZlbnQgb2JqZWN0XG5cdGlmICggc3JjICYmIHNyYy50eXBlICkge1xuXHRcdHRoaXMub3JpZ2luYWxFdmVudCA9IHNyYztcblx0XHR0aGlzLnR5cGUgPSBzcmMudHlwZTtcblxuXHRcdC8vIEV2ZW50cyBidWJibGluZyB1cCB0aGUgZG9jdW1lbnQgbWF5IGhhdmUgYmVlbiBtYXJrZWQgYXMgcHJldmVudGVkXG5cdFx0Ly8gYnkgYSBoYW5kbGVyIGxvd2VyIGRvd24gdGhlIHRyZWU7IHJlZmxlY3QgdGhlIGNvcnJlY3QgdmFsdWUuXG5cdFx0dGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBzcmMuZGVmYXVsdFByZXZlbnRlZCB8fFxuXHRcdFx0XHRzcmMuZGVmYXVsdFByZXZlbnRlZCA9PT0gdW5kZWZpbmVkICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTIuMyBvbmx5XG5cdFx0XHRcdHNyYy5yZXR1cm5WYWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0cmV0dXJuVHJ1ZSA6XG5cdFx0XHRyZXR1cm5GYWxzZTtcblxuXHRcdC8vIENyZWF0ZSB0YXJnZXQgcHJvcGVydGllc1xuXHRcdC8vIFN1cHBvcnQ6IFNhZmFyaSA8PTYgLSA3IG9ubHlcblx0XHQvLyBUYXJnZXQgc2hvdWxkIG5vdCBiZSBhIHRleHQgbm9kZSAoIzUwNCwgIzEzMTQzKVxuXHRcdHRoaXMudGFyZ2V0ID0gKCBzcmMudGFyZ2V0ICYmIHNyYy50YXJnZXQubm9kZVR5cGUgPT09IDMgKSA/XG5cdFx0XHRzcmMudGFyZ2V0LnBhcmVudE5vZGUgOlxuXHRcdFx0c3JjLnRhcmdldDtcblxuXHRcdHRoaXMuY3VycmVudFRhcmdldCA9IHNyYy5jdXJyZW50VGFyZ2V0O1xuXHRcdHRoaXMucmVsYXRlZFRhcmdldCA9IHNyYy5yZWxhdGVkVGFyZ2V0O1xuXG5cdC8vIEV2ZW50IHR5cGVcblx0fSBlbHNlIHtcblx0XHR0aGlzLnR5cGUgPSBzcmM7XG5cdH1cblxuXHQvLyBQdXQgZXhwbGljaXRseSBwcm92aWRlZCBwcm9wZXJ0aWVzIG9udG8gdGhlIGV2ZW50IG9iamVjdFxuXHRpZiAoIHByb3BzICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRoaXMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSB0aW1lc3RhbXAgaWYgaW5jb21pbmcgZXZlbnQgZG9lc24ndCBoYXZlIG9uZVxuXHR0aGlzLnRpbWVTdGFtcCA9IHNyYyAmJiBzcmMudGltZVN0YW1wIHx8IGpRdWVyeS5ub3coKTtcblxuXHQvLyBNYXJrIGl0IGFzIGZpeGVkXG5cdHRoaXNbIGpRdWVyeS5leHBhbmRvIF0gPSB0cnVlO1xufTtcblxuLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nXG4vLyBodHRwczovL3d3dy53My5vcmcvVFIvMjAwMy9XRC1ET00tTGV2ZWwtMy1FdmVudHMtMjAwMzAzMzEvZWNtYS1zY3JpcHQtYmluZGluZy5odG1sXG5qUXVlcnkuRXZlbnQucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LkV2ZW50LFxuXHRpc0RlZmF1bHRQcmV2ZW50ZWQ6IHJldHVybkZhbHNlLFxuXHRpc1Byb3BhZ2F0aW9uU3RvcHBlZDogcmV0dXJuRmFsc2UsXG5cdGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNTaW11bGF0ZWQ6IGZhbHNlLFxuXG5cdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9LFxuXHRzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0dGhpcy5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9IHJldHVyblRydWU7XG5cblx0XHRpZiAoIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgKSB7XG5cdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdH1cblxuXHRcdHRoaXMuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdH1cbn07XG5cbi8vIEluY2x1ZGVzIGFsbCBjb21tb24gZXZlbnQgcHJvcHMgaW5jbHVkaW5nIEtleUV2ZW50IGFuZCBNb3VzZUV2ZW50IHNwZWNpZmljIHByb3BzXG5qUXVlcnkuZWFjaCgge1xuXHRhbHRLZXk6IHRydWUsXG5cdGJ1YmJsZXM6IHRydWUsXG5cdGNhbmNlbGFibGU6IHRydWUsXG5cdGNoYW5nZWRUb3VjaGVzOiB0cnVlLFxuXHRjdHJsS2V5OiB0cnVlLFxuXHRkZXRhaWw6IHRydWUsXG5cdGV2ZW50UGhhc2U6IHRydWUsXG5cdG1ldGFLZXk6IHRydWUsXG5cdHBhZ2VYOiB0cnVlLFxuXHRwYWdlWTogdHJ1ZSxcblx0c2hpZnRLZXk6IHRydWUsXG5cdHZpZXc6IHRydWUsXG5cdFwiY2hhclwiOiB0cnVlLFxuXHRjaGFyQ29kZTogdHJ1ZSxcblx0a2V5OiB0cnVlLFxuXHRrZXlDb2RlOiB0cnVlLFxuXHRidXR0b246IHRydWUsXG5cdGJ1dHRvbnM6IHRydWUsXG5cdGNsaWVudFg6IHRydWUsXG5cdGNsaWVudFk6IHRydWUsXG5cdG9mZnNldFg6IHRydWUsXG5cdG9mZnNldFk6IHRydWUsXG5cdHBvaW50ZXJJZDogdHJ1ZSxcblx0cG9pbnRlclR5cGU6IHRydWUsXG5cdHNjcmVlblg6IHRydWUsXG5cdHNjcmVlblk6IHRydWUsXG5cdHRhcmdldFRvdWNoZXM6IHRydWUsXG5cdHRvRWxlbWVudDogdHJ1ZSxcblx0dG91Y2hlczogdHJ1ZSxcblxuXHR3aGljaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdHZhciBidXR0b24gPSBldmVudC5idXR0b247XG5cblx0XHQvLyBBZGQgd2hpY2ggZm9yIGtleSBldmVudHNcblx0XHRpZiAoIGV2ZW50LndoaWNoID09IG51bGwgJiYgcmtleUV2ZW50LnRlc3QoIGV2ZW50LnR5cGUgKSApIHtcblx0XHRcdHJldHVybiBldmVudC5jaGFyQ29kZSAhPSBudWxsID8gZXZlbnQuY2hhckNvZGUgOiBldmVudC5rZXlDb2RlO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB3aGljaCBmb3IgY2xpY2s6IDEgPT09IGxlZnQ7IDIgPT09IG1pZGRsZTsgMyA9PT0gcmlnaHRcblx0XHRpZiAoICFldmVudC53aGljaCAmJiBidXR0b24gIT09IHVuZGVmaW5lZCAmJiBybW91c2VFdmVudC50ZXN0KCBldmVudC50eXBlICkgKSB7XG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDEgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDIgKSB7XG5cdFx0XHRcdHJldHVybiAzO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDQgKSB7XG5cdFx0XHRcdHJldHVybiAyO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnQud2hpY2g7XG5cdH1cbn0sIGpRdWVyeS5ldmVudC5hZGRQcm9wICk7XG5cbi8vIENyZWF0ZSBtb3VzZWVudGVyL2xlYXZlIGV2ZW50cyB1c2luZyBtb3VzZW92ZXIvb3V0IGFuZCBldmVudC10aW1lIGNoZWNrc1xuLy8gc28gdGhhdCBldmVudCBkZWxlZ2F0aW9uIHdvcmtzIGluIGpRdWVyeS5cbi8vIERvIHRoZSBzYW1lIGZvciBwb2ludGVyZW50ZXIvcG9pbnRlcmxlYXZlIGFuZCBwb2ludGVyb3Zlci9wb2ludGVyb3V0XG4vL1xuLy8gU3VwcG9ydDogU2FmYXJpIDcgb25seVxuLy8gU2FmYXJpIHNlbmRzIG1vdXNlZW50ZXIgdG9vIG9mdGVuOyBzZWU6XG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NzAyNThcbi8vIGZvciB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGJ1ZyAoaXQgZXhpc3RlZCBpbiBvbGRlciBDaHJvbWUgdmVyc2lvbnMgYXMgd2VsbCkuXG5qUXVlcnkuZWFjaCgge1xuXHRtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuXHRtb3VzZWxlYXZlOiBcIm1vdXNlb3V0XCIsXG5cdHBvaW50ZXJlbnRlcjogXCJwb2ludGVyb3ZlclwiLFxuXHRwb2ludGVybGVhdmU6IFwicG9pbnRlcm91dFwiXG59LCBmdW5jdGlvbiggb3JpZywgZml4ICkge1xuXHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgb3JpZyBdID0ge1xuXHRcdGRlbGVnYXRlVHlwZTogZml4LFxuXHRcdGJpbmRUeXBlOiBmaXgsXG5cblx0XHRoYW5kbGU6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdHZhciByZXQsXG5cdFx0XHRcdHRhcmdldCA9IHRoaXMsXG5cdFx0XHRcdHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0LFxuXHRcdFx0XHRoYW5kbGVPYmogPSBldmVudC5oYW5kbGVPYmo7XG5cblx0XHRcdC8vIEZvciBtb3VzZWVudGVyL2xlYXZlIGNhbGwgdGhlIGhhbmRsZXIgaWYgcmVsYXRlZCBpcyBvdXRzaWRlIHRoZSB0YXJnZXQuXG5cdFx0XHQvLyBOQjogTm8gcmVsYXRlZFRhcmdldCBpZiB0aGUgbW91c2UgbGVmdC9lbnRlcmVkIHRoZSBicm93c2VyIHdpbmRvd1xuXHRcdFx0aWYgKCAhcmVsYXRlZCB8fCAoIHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhalF1ZXJ5LmNvbnRhaW5zKCB0YXJnZXQsIHJlbGF0ZWQgKSApICkge1xuXHRcdFx0XHRldmVudC50eXBlID0gaGFuZGxlT2JqLm9yaWdUeXBlO1xuXHRcdFx0XHRyZXQgPSBoYW5kbGVPYmouaGFuZGxlci5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBmaXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXG5cdG9uOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4gKTtcblx0fSxcblx0b25lOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4sIDEgKTtcblx0fSxcblx0b2ZmOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBmbiApIHtcblx0XHR2YXIgaGFuZGxlT2JqLCB0eXBlO1xuXHRcdGlmICggdHlwZXMgJiYgdHlwZXMucHJldmVudERlZmF1bHQgJiYgdHlwZXMuaGFuZGxlT2JqICkge1xuXG5cdFx0XHQvLyAoIGV2ZW50ICkgIGRpc3BhdGNoZWQgalF1ZXJ5LkV2ZW50XG5cdFx0XHRoYW5kbGVPYmogPSB0eXBlcy5oYW5kbGVPYmo7XG5cdFx0XHRqUXVlcnkoIHR5cGVzLmRlbGVnYXRlVGFyZ2V0ICkub2ZmKFxuXHRcdFx0XHRoYW5kbGVPYmoubmFtZXNwYWNlID9cblx0XHRcdFx0XHRoYW5kbGVPYmoub3JpZ1R5cGUgKyBcIi5cIiArIGhhbmRsZU9iai5uYW1lc3BhY2UgOlxuXHRcdFx0XHRcdGhhbmRsZU9iai5vcmlnVHlwZSxcblx0XHRcdFx0aGFuZGxlT2JqLnNlbGVjdG9yLFxuXHRcdFx0XHRoYW5kbGVPYmouaGFuZGxlclxuXHRcdFx0KTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcy1vYmplY3QgWywgc2VsZWN0b3JdIClcblx0XHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRcdHRoaXMub2ZmKCB0eXBlLCBzZWxlY3RvciwgdHlwZXNbIHR5cGUgXSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggc2VsZWN0b3IgPT09IGZhbHNlIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICkge1xuXG5cdFx0XHQvLyAoIHR5cGVzIFssIGZuXSApXG5cdFx0XHRmbiA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGlmICggZm4gPT09IGZhbHNlICkge1xuXHRcdFx0Zm4gPSByZXR1cm5GYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCB0aGlzLCB0eXBlcywgZm4sIHNlbGVjdG9yICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxudmFyXG5cblx0LyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuXG5cdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZXNsaW50L2VzbGludC9pc3N1ZXMvMzIyOVxuXHRyeGh0bWxUYWcgPSAvPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbYS16XVteXFwvXFwwPlxceDIwXFx0XFxyXFxuXFxmXSopW14+XSopXFwvPi9naSxcblxuXHQvKiBlc2xpbnQtZW5hYmxlICovXG5cblx0Ly8gU3VwcG9ydDogSUUgPD0xMCAtIDExLCBFZGdlIDEyIC0gMTNcblx0Ly8gSW4gSUUvRWRnZSB1c2luZyByZWdleCBncm91cHMgaGVyZSBjYXVzZXMgc2V2ZXJlIHNsb3dkb3ducy5cblx0Ly8gU2VlIGh0dHBzOi8vY29ubmVjdC5taWNyb3NvZnQuY29tL0lFL2ZlZWRiYWNrL2RldGFpbHMvMTczNjUxMi9cblx0cm5vSW5uZXJodG1sID0gLzxzY3JpcHR8PHN0eWxlfDxsaW5rL2ksXG5cblx0Ly8gY2hlY2tlZD1cImNoZWNrZWRcIiBvciBjaGVja2VkXG5cdHJjaGVja2VkID0gL2NoZWNrZWRcXHMqKD86W149XXw9XFxzKi5jaGVja2VkLikvaSxcblx0cnNjcmlwdFR5cGVNYXNrZWQgPSAvXnRydWVcXC8oLiopLyxcblx0cmNsZWFuU2NyaXB0ID0gL15cXHMqPCEoPzpcXFtDREFUQVxcW3wtLSl8KD86XFxdXFxdfC0tKT5cXHMqJC9nO1xuXG4vLyBQcmVmZXIgYSB0Ym9keSBvdmVyIGl0cyBwYXJlbnQgdGFibGUgZm9yIGNvbnRhaW5pbmcgbmV3IHJvd3NcbmZ1bmN0aW9uIG1hbmlwdWxhdGlvblRhcmdldCggZWxlbSwgY29udGVudCApIHtcblx0aWYgKCBub2RlTmFtZSggZWxlbSwgXCJ0YWJsZVwiICkgJiZcblx0XHRub2RlTmFtZSggY29udGVudC5ub2RlVHlwZSAhPT0gMTEgPyBjb250ZW50IDogY29udGVudC5maXJzdENoaWxkLCBcInRyXCIgKSApIHtcblxuXHRcdHJldHVybiBqUXVlcnkoIFwiPnRib2R5XCIsIGVsZW0gKVsgMCBdIHx8IGVsZW07XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxuLy8gUmVwbGFjZS9yZXN0b3JlIHRoZSB0eXBlIGF0dHJpYnV0ZSBvZiBzY3JpcHQgZWxlbWVudHMgZm9yIHNhZmUgRE9NIG1hbmlwdWxhdGlvblxuZnVuY3Rpb24gZGlzYWJsZVNjcmlwdCggZWxlbSApIHtcblx0ZWxlbS50eXBlID0gKCBlbGVtLmdldEF0dHJpYnV0ZSggXCJ0eXBlXCIgKSAhPT0gbnVsbCApICsgXCIvXCIgKyBlbGVtLnR5cGU7XG5cdHJldHVybiBlbGVtO1xufVxuZnVuY3Rpb24gcmVzdG9yZVNjcmlwdCggZWxlbSApIHtcblx0dmFyIG1hdGNoID0gcnNjcmlwdFR5cGVNYXNrZWQuZXhlYyggZWxlbS50eXBlICk7XG5cblx0aWYgKCBtYXRjaCApIHtcblx0XHRlbGVtLnR5cGUgPSBtYXRjaFsgMSBdO1xuXHR9IGVsc2Uge1xuXHRcdGVsZW0ucmVtb3ZlQXR0cmlidXRlKCBcInR5cGVcIiApO1xuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmZ1bmN0aW9uIGNsb25lQ29weUV2ZW50KCBzcmMsIGRlc3QgKSB7XG5cdHZhciBpLCBsLCB0eXBlLCBwZGF0YU9sZCwgcGRhdGFDdXIsIHVkYXRhT2xkLCB1ZGF0YUN1ciwgZXZlbnRzO1xuXG5cdGlmICggZGVzdC5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyAxLiBDb3B5IHByaXZhdGUgZGF0YTogZXZlbnRzLCBoYW5kbGVycywgZXRjLlxuXHRpZiAoIGRhdGFQcml2Lmhhc0RhdGEoIHNyYyApICkge1xuXHRcdHBkYXRhT2xkID0gZGF0YVByaXYuYWNjZXNzKCBzcmMgKTtcblx0XHRwZGF0YUN1ciA9IGRhdGFQcml2LnNldCggZGVzdCwgcGRhdGFPbGQgKTtcblx0XHRldmVudHMgPSBwZGF0YU9sZC5ldmVudHM7XG5cblx0XHRpZiAoIGV2ZW50cyApIHtcblx0XHRcdGRlbGV0ZSBwZGF0YUN1ci5oYW5kbGU7XG5cdFx0XHRwZGF0YUN1ci5ldmVudHMgPSB7fTtcblxuXHRcdFx0Zm9yICggdHlwZSBpbiBldmVudHMgKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwLCBsID0gZXZlbnRzWyB0eXBlIF0ubGVuZ3RoOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5hZGQoIGRlc3QsIHR5cGUsIGV2ZW50c1sgdHlwZSBdWyBpIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIDIuIENvcHkgdXNlciBkYXRhXG5cdGlmICggZGF0YVVzZXIuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0dWRhdGFPbGQgPSBkYXRhVXNlci5hY2Nlc3MoIHNyYyApO1xuXHRcdHVkYXRhQ3VyID0galF1ZXJ5LmV4dGVuZCgge30sIHVkYXRhT2xkICk7XG5cblx0XHRkYXRhVXNlci5zZXQoIGRlc3QsIHVkYXRhQ3VyICk7XG5cdH1cbn1cblxuLy8gRml4IElFIGJ1Z3MsIHNlZSBzdXBwb3J0IHRlc3RzXG5mdW5jdGlvbiBmaXhJbnB1dCggc3JjLCBkZXN0ICkge1xuXHR2YXIgbm9kZU5hbWUgPSBkZXN0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0Ly8gRmFpbHMgdG8gcGVyc2lzdCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiBhIGNsb25lZCBjaGVja2JveCBvciByYWRpbyBidXR0b24uXG5cdGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiByY2hlY2thYmxlVHlwZS50ZXN0KCBzcmMudHlwZSApICkge1xuXHRcdGRlc3QuY2hlY2tlZCA9IHNyYy5jaGVja2VkO1xuXG5cdC8vIEZhaWxzIHRvIHJldHVybiB0aGUgc2VsZWN0ZWQgb3B0aW9uIHRvIHRoZSBkZWZhdWx0IHNlbGVjdGVkIHN0YXRlIHdoZW4gY2xvbmluZyBvcHRpb25zXG5cdH0gZWxzZSBpZiAoIG5vZGVOYW1lID09PSBcImlucHV0XCIgfHwgbm9kZU5hbWUgPT09IFwidGV4dGFyZWFcIiApIHtcblx0XHRkZXN0LmRlZmF1bHRWYWx1ZSA9IHNyYy5kZWZhdWx0VmFsdWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gZG9tTWFuaXAoIGNvbGxlY3Rpb24sIGFyZ3MsIGNhbGxiYWNrLCBpZ25vcmVkICkge1xuXG5cdC8vIEZsYXR0ZW4gYW55IG5lc3RlZCBhcnJheXNcblx0YXJncyA9IGNvbmNhdC5hcHBseSggW10sIGFyZ3MgKTtcblxuXHR2YXIgZnJhZ21lbnQsIGZpcnN0LCBzY3JpcHRzLCBoYXNTY3JpcHRzLCBub2RlLCBkb2MsXG5cdFx0aSA9IDAsXG5cdFx0bCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuXHRcdGlOb0Nsb25lID0gbCAtIDEsXG5cdFx0dmFsdWUgPSBhcmdzWyAwIF0sXG5cdFx0aXNGdW5jdGlvbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApO1xuXG5cdC8vIFdlIGNhbid0IGNsb25lTm9kZSBmcmFnbWVudHMgdGhhdCBjb250YWluIGNoZWNrZWQsIGluIFdlYktpdFxuXHRpZiAoIGlzRnVuY3Rpb24gfHxcblx0XHRcdCggbCA+IDEgJiYgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmXG5cdFx0XHRcdCFzdXBwb3J0LmNoZWNrQ2xvbmUgJiYgcmNoZWNrZWQudGVzdCggdmFsdWUgKSApICkge1xuXHRcdHJldHVybiBjb2xsZWN0aW9uLmVhY2goIGZ1bmN0aW9uKCBpbmRleCApIHtcblx0XHRcdHZhciBzZWxmID0gY29sbGVjdGlvbi5lcSggaW5kZXggKTtcblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0YXJnc1sgMCBdID0gdmFsdWUuY2FsbCggdGhpcywgaW5kZXgsIHNlbGYuaHRtbCgpICk7XG5cdFx0XHR9XG5cdFx0XHRkb21NYW5pcCggc2VsZiwgYXJncywgY2FsbGJhY2ssIGlnbm9yZWQgKTtcblx0XHR9ICk7XG5cdH1cblxuXHRpZiAoIGwgKSB7XG5cdFx0ZnJhZ21lbnQgPSBidWlsZEZyYWdtZW50KCBhcmdzLCBjb2xsZWN0aW9uWyAwIF0ub3duZXJEb2N1bWVudCwgZmFsc2UsIGNvbGxlY3Rpb24sIGlnbm9yZWQgKTtcblx0XHRmaXJzdCA9IGZyYWdtZW50LmZpcnN0Q2hpbGQ7XG5cblx0XHRpZiAoIGZyYWdtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAxICkge1xuXHRcdFx0ZnJhZ21lbnQgPSBmaXJzdDtcblx0XHR9XG5cblx0XHQvLyBSZXF1aXJlIGVpdGhlciBuZXcgY29udGVudCBvciBhbiBpbnRlcmVzdCBpbiBpZ25vcmVkIGVsZW1lbnRzIHRvIGludm9rZSB0aGUgY2FsbGJhY2tcblx0XHRpZiAoIGZpcnN0IHx8IGlnbm9yZWQgKSB7XG5cdFx0XHRzY3JpcHRzID0galF1ZXJ5Lm1hcCggZ2V0QWxsKCBmcmFnbWVudCwgXCJzY3JpcHRcIiApLCBkaXNhYmxlU2NyaXB0ICk7XG5cdFx0XHRoYXNTY3JpcHRzID0gc2NyaXB0cy5sZW5ndGg7XG5cblx0XHRcdC8vIFVzZSB0aGUgb3JpZ2luYWwgZnJhZ21lbnQgZm9yIHRoZSBsYXN0IGl0ZW1cblx0XHRcdC8vIGluc3RlYWQgb2YgdGhlIGZpcnN0IGJlY2F1c2UgaXQgY2FuIGVuZCB1cFxuXHRcdFx0Ly8gYmVpbmcgZW1wdGllZCBpbmNvcnJlY3RseSBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgKCM4MDcwKS5cblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0bm9kZSA9IGZyYWdtZW50O1xuXG5cdFx0XHRcdGlmICggaSAhPT0gaU5vQ2xvbmUgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IGpRdWVyeS5jbG9uZSggbm9kZSwgdHJ1ZSwgdHJ1ZSApO1xuXG5cdFx0XHRcdFx0Ly8gS2VlcCByZWZlcmVuY2VzIHRvIGNsb25lZCBzY3JpcHRzIGZvciBsYXRlciByZXN0b3JhdGlvblxuXHRcdFx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIHNjcmlwdHMsIGdldEFsbCggbm9kZSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FsbGJhY2suY2FsbCggY29sbGVjdGlvblsgaSBdLCBub2RlLCBpICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblx0XHRcdFx0ZG9jID0gc2NyaXB0c1sgc2NyaXB0cy5sZW5ndGggLSAxIF0ub3duZXJEb2N1bWVudDtcblxuXHRcdFx0XHQvLyBSZWVuYWJsZSBzY3JpcHRzXG5cdFx0XHRcdGpRdWVyeS5tYXAoIHNjcmlwdHMsIHJlc3RvcmVTY3JpcHQgKTtcblxuXHRcdFx0XHQvLyBFdmFsdWF0ZSBleGVjdXRhYmxlIHNjcmlwdHMgb24gZmlyc3QgZG9jdW1lbnQgaW5zZXJ0aW9uXG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgaGFzU2NyaXB0czsgaSsrICkge1xuXHRcdFx0XHRcdG5vZGUgPSBzY3JpcHRzWyBpIF07XG5cdFx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBub2RlLnR5cGUgfHwgXCJcIiApICYmXG5cdFx0XHRcdFx0XHQhZGF0YVByaXYuYWNjZXNzKCBub2RlLCBcImdsb2JhbEV2YWxcIiApICYmXG5cdFx0XHRcdFx0XHRqUXVlcnkuY29udGFpbnMoIGRvYywgbm9kZSApICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIG5vZGUuc3JjICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIE9wdGlvbmFsIEFKQVggZGVwZW5kZW5jeSwgYnV0IHdvbid0IHJ1biBzY3JpcHRzIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5Ll9ldmFsVXJsICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5fZXZhbFVybCggbm9kZS5zcmMgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0RE9NRXZhbCggbm9kZS50ZXh0Q29udGVudC5yZXBsYWNlKCByY2xlYW5TY3JpcHQsIFwiXCIgKSwgZG9jICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGNvbGxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSggZWxlbSwgc2VsZWN0b3IsIGtlZXBEYXRhICkge1xuXHR2YXIgbm9kZSxcblx0XHRub2RlcyA9IHNlbGVjdG9yID8galF1ZXJ5LmZpbHRlciggc2VsZWN0b3IsIGVsZW0gKSA6IGVsZW0sXG5cdFx0aSA9IDA7XG5cblx0Zm9yICggOyAoIG5vZGUgPSBub2Rlc1sgaSBdICkgIT0gbnVsbDsgaSsrICkge1xuXHRcdGlmICggIWtlZXBEYXRhICYmIG5vZGUubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIG5vZGUgKSApO1xuXHRcdH1cblxuXHRcdGlmICggbm9kZS5wYXJlbnROb2RlICkge1xuXHRcdFx0aWYgKCBrZWVwRGF0YSAmJiBqUXVlcnkuY29udGFpbnMoIG5vZGUub3duZXJEb2N1bWVudCwgbm9kZSApICkge1xuXHRcdFx0XHRzZXRHbG9iYWxFdmFsKCBnZXRBbGwoIG5vZGUsIFwic2NyaXB0XCIgKSApO1xuXHRcdFx0fVxuXHRcdFx0bm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBub2RlICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aHRtbFByZWZpbHRlcjogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0cmV0dXJuIGh0bWwucmVwbGFjZSggcnhodG1sVGFnLCBcIjwkMT48LyQyPlwiICk7XG5cdH0sXG5cblx0Y2xvbmU6IGZ1bmN0aW9uKCBlbGVtLCBkYXRhQW5kRXZlbnRzLCBkZWVwRGF0YUFuZEV2ZW50cyApIHtcblx0XHR2YXIgaSwgbCwgc3JjRWxlbWVudHMsIGRlc3RFbGVtZW50cyxcblx0XHRcdGNsb25lID0gZWxlbS5jbG9uZU5vZGUoIHRydWUgKSxcblx0XHRcdGluUGFnZSA9IGpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICk7XG5cblx0XHQvLyBGaXggSUUgY2xvbmluZyBpc3N1ZXNcblx0XHRpZiAoICFzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkICYmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBlbGVtLm5vZGVUeXBlID09PSAxMSApICYmXG5cdFx0XHRcdCFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblxuXHRcdFx0Ly8gV2UgZXNjaGV3IFNpenpsZSBoZXJlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zOiBodHRwczovL2pzcGVyZi5jb20vZ2V0YWxsLXZzLXNpenpsZS8yXG5cdFx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lICk7XG5cdFx0XHRzcmNFbGVtZW50cyA9IGdldEFsbCggZWxlbSApO1xuXG5cdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0Zml4SW5wdXQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ29weSB0aGUgZXZlbnRzIGZyb20gdGhlIG9yaWdpbmFsIHRvIHRoZSBjbG9uZVxuXHRcdGlmICggZGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdGlmICggZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0XHRcdHNyY0VsZW1lbnRzID0gc3JjRWxlbWVudHMgfHwgZ2V0QWxsKCBlbGVtICk7XG5cdFx0XHRcdGRlc3RFbGVtZW50cyA9IGRlc3RFbGVtZW50cyB8fCBnZXRBbGwoIGNsb25lICk7XG5cblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBzcmNFbGVtZW50cy5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNsb25lQ29weUV2ZW50KCBlbGVtLCBjbG9uZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIHNjcmlwdCBldmFsdWF0aW9uIGhpc3Rvcnlcblx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lLCBcInNjcmlwdFwiICk7XG5cdFx0aWYgKCBkZXN0RWxlbWVudHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIGRlc3RFbGVtZW50cywgIWluUGFnZSAmJiBnZXRBbGwoIGVsZW0sIFwic2NyaXB0XCIgKSApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0aGUgY2xvbmVkIHNldFxuXHRcdHJldHVybiBjbG9uZTtcblx0fSxcblxuXHRjbGVhbkRhdGE6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblx0XHR2YXIgZGF0YSwgZWxlbSwgdHlwZSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbCxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoIGVsZW0gPSBlbGVtc1sgaSBdICkgIT09IHVuZGVmaW5lZDsgaSsrICkge1xuXHRcdFx0aWYgKCBhY2NlcHREYXRhKCBlbGVtICkgKSB7XG5cdFx0XHRcdGlmICggKCBkYXRhID0gZWxlbVsgZGF0YVByaXYuZXhwYW5kbyBdICkgKSB7XG5cdFx0XHRcdFx0aWYgKCBkYXRhLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdGZvciAoIHR5cGUgaW4gZGF0YS5ldmVudHMgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbFsgdHlwZSBdICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIGVsZW0sIHR5cGUgKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYXZvaWQgalF1ZXJ5LmV2ZW50LnJlbW92ZSdzIG92ZXJoZWFkXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBkYXRhLmhhbmRsZSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NStcblx0XHRcdFx0XHQvLyBBc3NpZ24gdW5kZWZpbmVkIGluc3RlYWQgb2YgdXNpbmcgZGVsZXRlLCBzZWUgRGF0YSNyZW1vdmVcblx0XHRcdFx0XHRlbGVtWyBkYXRhUHJpdi5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBlbGVtWyBkYXRhVXNlci5leHBhbmRvIF0gKSB7XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1K1xuXHRcdFx0XHRcdC8vIEFzc2lnbiB1bmRlZmluZWQgaW5zdGVhZCBvZiB1c2luZyBkZWxldGUsIHNlZSBEYXRhI3JlbW92ZVxuXHRcdFx0XHRcdGVsZW1bIGRhdGFVc2VyLmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRldGFjaDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiByZW1vdmUoIHRoaXMsIHNlbGVjdG9yLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHJlbW92ZSggdGhpcywgc2VsZWN0b3IgKTtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkudGV4dCggdGhpcyApIDpcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdFx0dGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0YXBwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0dmFyIHRhcmdldCA9IG1hbmlwdWxhdGlvblRhcmdldCggdGhpcywgZWxlbSApO1xuXHRcdFx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0cHJlcGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBtYW5pcHVsYXRpb25UYXJnZXQoIHRoaXMsIGVsZW0gKTtcblx0XHRcdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSggZWxlbSwgdGFyZ2V0LmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0YmVmb3JlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRhZnRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoIGVsZW0sIHRoaXMubmV4dFNpYmxpbmcgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0ZW1wdHk6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7ICggZWxlbSA9IHRoaXNbIGkgXSApICE9IG51bGw7IGkrKyApIHtcblx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHQvLyBQcmV2ZW50IG1lbW9yeSBsZWFrc1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIGVsZW0sIGZhbHNlICkgKTtcblxuXHRcdFx0XHQvLyBSZW1vdmUgYW55IHJlbWFpbmluZyBub2Rlc1xuXHRcdFx0XHRlbGVtLnRleHRDb250ZW50ID0gXCJcIjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRjbG9uZTogZnVuY3Rpb24oIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICkge1xuXHRcdGRhdGFBbmRFdmVudHMgPSBkYXRhQW5kRXZlbnRzID09IG51bGwgPyBmYWxzZSA6IGRhdGFBbmRFdmVudHM7XG5cdFx0ZGVlcERhdGFBbmRFdmVudHMgPSBkZWVwRGF0YUFuZEV2ZW50cyA9PSBudWxsID8gZGF0YUFuZEV2ZW50cyA6IGRlZXBEYXRhQW5kRXZlbnRzO1xuXG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBqUXVlcnkuY2xvbmUoIHRoaXMsIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdGh0bWw6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXSB8fCB7fSxcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdGwgPSB0aGlzLmxlbmd0aDtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmlubmVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2VlIGlmIHdlIGNhbiB0YWtlIGEgc2hvcnRjdXQgYW5kIGp1c3QgdXNlIGlubmVySFRNTFxuXHRcdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgIXJub0lubmVyaHRtbC50ZXN0KCB2YWx1ZSApICYmXG5cdFx0XHRcdCF3cmFwTWFwWyAoIHJ0YWdOYW1lLmV4ZWMoIHZhbHVlICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCkgXSApIHtcblxuXHRcdFx0XHR2YWx1ZSA9IGpRdWVyeS5odG1sUHJlZmlsdGVyKCB2YWx1ZSApO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdFx0ZWxlbSA9IHRoaXNbIGkgXSB8fCB7fTtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXHRcdFx0XHRcdFx0XHRlbGVtLmlubmVySFRNTCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsZW0gPSAwO1xuXG5cdFx0XHRcdC8vIElmIHVzaW5nIGlubmVySFRNTCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB1c2UgdGhlIGZhbGxiYWNrIG1ldGhvZFxuXHRcdFx0XHR9IGNhdGNoICggZSApIHt9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZWxlbSApIHtcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmFwcGVuZCggdmFsdWUgKTtcblx0XHRcdH1cblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCApO1xuXHR9LFxuXG5cdHJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaWdub3JlZCA9IFtdO1xuXG5cdFx0Ly8gTWFrZSB0aGUgY2hhbmdlcywgcmVwbGFjaW5nIGVhY2ggbm9uLWlnbm9yZWQgY29udGV4dCBlbGVtZW50IHdpdGggdGhlIG5ldyBjb250ZW50XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIHBhcmVudCA9IHRoaXMucGFyZW50Tm9kZTtcblxuXHRcdFx0aWYgKCBqUXVlcnkuaW5BcnJheSggdGhpcywgaWdub3JlZCApIDwgMCApIHtcblx0XHRcdFx0alF1ZXJ5LmNsZWFuRGF0YSggZ2V0QWxsKCB0aGlzICkgKTtcblx0XHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cdFx0XHRcdFx0cGFyZW50LnJlcGxhY2VDaGlsZCggZWxlbSwgdGhpcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBGb3JjZSBjYWxsYmFjayBpbnZvY2F0aW9uXG5cdFx0fSwgaWdub3JlZCApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCB7XG5cdGFwcGVuZFRvOiBcImFwcGVuZFwiLFxuXHRwcmVwZW5kVG86IFwicHJlcGVuZFwiLFxuXHRpbnNlcnRCZWZvcmU6IFwiYmVmb3JlXCIsXG5cdGluc2VydEFmdGVyOiBcImFmdGVyXCIsXG5cdHJlcGxhY2VBbGw6IFwicmVwbGFjZVdpdGhcIlxufSwgZnVuY3Rpb24oIG5hbWUsIG9yaWdpbmFsICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgZWxlbXMsXG5cdFx0XHRyZXQgPSBbXSxcblx0XHRcdGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKSxcblx0XHRcdGxhc3QgPSBpbnNlcnQubGVuZ3RoIC0gMSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyBpIDw9IGxhc3Q7IGkrKyApIHtcblx0XHRcdGVsZW1zID0gaSA9PT0gbGFzdCA/IHRoaXMgOiB0aGlzLmNsb25lKCB0cnVlICk7XG5cdFx0XHRqUXVlcnkoIGluc2VydFsgaSBdIClbIG9yaWdpbmFsIF0oIGVsZW1zICk7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0Ly8gLmdldCgpIGJlY2F1c2UgcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0cHVzaC5hcHBseSggcmV0LCBlbGVtcy5nZXQoKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggcmV0ICk7XG5cdH07XG59ICk7XG52YXIgcm1hcmdpbiA9ICggL15tYXJnaW4vICk7XG5cbnZhciBybnVtbm9ucHggPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBwbnVtICsgXCIpKD8hcHgpW2EteiVdKyRcIiwgXCJpXCIgKTtcblxudmFyIGdldFN0eWxlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5LCBGaXJlZm94IDw9MzAgKCMxNTA5OCwgIzE0MTUwKVxuXHRcdC8vIElFIHRocm93cyBvbiBlbGVtZW50cyBjcmVhdGVkIGluIHBvcHVwc1xuXHRcdC8vIEZGIG1lYW53aGlsZSB0aHJvd3Mgb24gZnJhbWUgZWxlbWVudHMgdGhyb3VnaCBcImRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGVcIlxuXHRcdHZhciB2aWV3ID0gZWxlbS5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3O1xuXG5cdFx0aWYgKCAhdmlldyB8fCAhdmlldy5vcGVuZXIgKSB7XG5cdFx0XHR2aWV3ID0gd2luZG93O1xuXHRcdH1cblxuXHRcdHJldHVybiB2aWV3LmdldENvbXB1dGVkU3R5bGUoIGVsZW0gKTtcblx0fTtcblxuXG5cbiggZnVuY3Rpb24oKSB7XG5cblx0Ly8gRXhlY3V0aW5nIGJvdGggcGl4ZWxQb3NpdGlvbiAmIGJveFNpemluZ1JlbGlhYmxlIHRlc3RzIHJlcXVpcmUgb25seSBvbmUgbGF5b3V0XG5cdC8vIHNvIHRoZXkncmUgZXhlY3V0ZWQgYXQgdGhlIHNhbWUgdGltZSB0byBzYXZlIHRoZSBzZWNvbmQgY29tcHV0YXRpb24uXG5cdGZ1bmN0aW9uIGNvbXB1dGVTdHlsZVRlc3RzKCkge1xuXG5cdFx0Ly8gVGhpcyBpcyBhIHNpbmdsZXRvbiwgd2UgbmVlZCB0byBleGVjdXRlIGl0IG9ubHkgb25jZVxuXHRcdGlmICggIWRpdiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRkaXYuc3R5bGUuY3NzVGV4dCA9XG5cdFx0XHRcImJveC1zaXppbmc6Ym9yZGVyLWJveDtcIiArXG5cdFx0XHRcInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7XCIgK1xuXHRcdFx0XCJtYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O1wiICtcblx0XHRcdFwidG9wOjElO3dpZHRoOjUwJVwiO1xuXHRcdGRpdi5pbm5lckhUTUwgPSBcIlwiO1xuXHRcdGRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHR2YXIgZGl2U3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSggZGl2ICk7XG5cdFx0cGl4ZWxQb3NpdGlvblZhbCA9IGRpdlN0eWxlLnRvcCAhPT0gXCIxJVwiO1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgLSA0LjMgb25seSwgRmlyZWZveCA8PTMgLSA0NFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdFZhbCA9IGRpdlN0eWxlLm1hcmdpbkxlZnQgPT09IFwiMnB4XCI7XG5cdFx0Ym94U2l6aW5nUmVsaWFibGVWYWwgPSBkaXZTdHlsZS53aWR0aCA9PT0gXCI0cHhcIjtcblxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgNC4wIC0gNC4zIG9ubHlcblx0XHQvLyBTb21lIHN0eWxlcyBjb21lIGJhY2sgd2l0aCBwZXJjZW50YWdlIHZhbHVlcywgZXZlbiB0aG91Z2ggdGhleSBzaG91bGRuJ3Rcblx0XHRkaXYuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjUwJVwiO1xuXHRcdHBpeGVsTWFyZ2luUmlnaHRWYWwgPSBkaXZTdHlsZS5tYXJnaW5SaWdodCA9PT0gXCI0cHhcIjtcblxuXHRcdGRvY3VtZW50RWxlbWVudC5yZW1vdmVDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHQvLyBOdWxsaWZ5IHRoZSBkaXYgc28gaXQgd291bGRuJ3QgYmUgc3RvcmVkIGluIHRoZSBtZW1vcnkgYW5kXG5cdFx0Ly8gaXQgd2lsbCBhbHNvIGJlIGEgc2lnbiB0aGF0IGNoZWNrcyBhbHJlYWR5IHBlcmZvcm1lZFxuXHRcdGRpdiA9IG51bGw7XG5cdH1cblxuXHR2YXIgcGl4ZWxQb3NpdGlvblZhbCwgYm94U2l6aW5nUmVsaWFibGVWYWwsIHBpeGVsTWFyZ2luUmlnaHRWYWwsIHJlbGlhYmxlTWFyZ2luTGVmdFZhbCxcblx0XHRjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICksXG5cdFx0ZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApO1xuXG5cdC8vIEZpbmlzaCBlYXJseSBpbiBsaW1pdGVkIChub24tYnJvd3NlcikgZW52aXJvbm1lbnRzXG5cdGlmICggIWRpdi5zdHlsZSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSBvbmx5XG5cdC8vIFN0eWxlIG9mIGNsb25lZCBlbGVtZW50IGFmZmVjdHMgc291cmNlIGVsZW1lbnQgY2xvbmVkICgjODkwOClcblx0ZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID0gXCJjb250ZW50LWJveFwiO1xuXHRkaXYuY2xvbmVOb2RlKCB0cnVlICkuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcIlwiO1xuXHRzdXBwb3J0LmNsZWFyQ2xvbmVTdHlsZSA9IGRpdi5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9PT0gXCJjb250ZW50LWJveFwiO1xuXG5cdGNvbnRhaW5lci5zdHlsZS5jc3NUZXh0ID0gXCJib3JkZXI6MDt3aWR0aDo4cHg7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4O1wiICtcblx0XHRcInBhZGRpbmc6MDttYXJnaW4tdG9wOjFweDtwb3NpdGlvbjphYnNvbHV0ZVwiO1xuXHRjb250YWluZXIuYXBwZW5kQ2hpbGQoIGRpdiApO1xuXG5cdGpRdWVyeS5leHRlbmQoIHN1cHBvcnQsIHtcblx0XHRwaXhlbFBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxQb3NpdGlvblZhbDtcblx0XHR9LFxuXHRcdGJveFNpemluZ1JlbGlhYmxlOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gYm94U2l6aW5nUmVsaWFibGVWYWw7XG5cdFx0fSxcblx0XHRwaXhlbE1hcmdpblJpZ2h0OiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxNYXJnaW5SaWdodFZhbDtcblx0XHR9LFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRjb21wdXRlU3R5bGVUZXN0cygpO1xuXHRcdFx0cmV0dXJuIHJlbGlhYmxlTWFyZ2luTGVmdFZhbDtcblx0XHR9XG5cdH0gKTtcbn0gKSgpO1xuXG5cbmZ1bmN0aW9uIGN1ckNTUyggZWxlbSwgbmFtZSwgY29tcHV0ZWQgKSB7XG5cdHZhciB3aWR0aCwgbWluV2lkdGgsIG1heFdpZHRoLCByZXQsXG5cblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDUxK1xuXHRcdC8vIFJldHJpZXZpbmcgc3R5bGUgYmVmb3JlIGNvbXB1dGVkIHNvbWVob3dcblx0XHQvLyBmaXhlcyBhbiBpc3N1ZSB3aXRoIGdldHRpbmcgd3JvbmcgdmFsdWVzXG5cdFx0Ly8gb24gZGV0YWNoZWQgZWxlbWVudHNcblx0XHRzdHlsZSA9IGVsZW0uc3R5bGU7XG5cblx0Y29tcHV0ZWQgPSBjb21wdXRlZCB8fCBnZXRTdHlsZXMoIGVsZW0gKTtcblxuXHQvLyBnZXRQcm9wZXJ0eVZhbHVlIGlzIG5lZWRlZCBmb3I6XG5cdC8vICAgLmNzcygnZmlsdGVyJykgKElFIDkgb25seSwgIzEyNTM3KVxuXHQvLyAgIC5jc3MoJy0tY3VzdG9tUHJvcGVydHkpICgjMzE0NClcblx0aWYgKCBjb21wdXRlZCApIHtcblx0XHRyZXQgPSBjb21wdXRlZC5nZXRQcm9wZXJ0eVZhbHVlKCBuYW1lICkgfHwgY29tcHV0ZWRbIG5hbWUgXTtcblxuXHRcdGlmICggcmV0ID09PSBcIlwiICYmICFqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICkge1xuXHRcdFx0cmV0ID0galF1ZXJ5LnN0eWxlKCBlbGVtLCBuYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gQSB0cmlidXRlIHRvIHRoZSBcImF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHNcIlxuXHRcdC8vIEFuZHJvaWQgQnJvd3NlciByZXR1cm5zIHBlcmNlbnRhZ2UgZm9yIHNvbWUgdmFsdWVzLFxuXHRcdC8vIGJ1dCB3aWR0aCBzZWVtcyB0byBiZSByZWxpYWJseSBwaXhlbHMuXG5cdFx0Ly8gVGhpcyBpcyBhZ2FpbnN0IHRoZSBDU1NPTSBkcmFmdCBzcGVjOlxuXHRcdC8vIGh0dHBzOi8vZHJhZnRzLmNzc3dnLm9yZy9jc3NvbS8jcmVzb2x2ZWQtdmFsdWVzXG5cdFx0aWYgKCAhc3VwcG9ydC5waXhlbE1hcmdpblJpZ2h0KCkgJiYgcm51bW5vbnB4LnRlc3QoIHJldCApICYmIHJtYXJnaW4udGVzdCggbmFtZSApICkge1xuXG5cdFx0XHQvLyBSZW1lbWJlciB0aGUgb3JpZ2luYWwgdmFsdWVzXG5cdFx0XHR3aWR0aCA9IHN0eWxlLndpZHRoO1xuXHRcdFx0bWluV2lkdGggPSBzdHlsZS5taW5XaWR0aDtcblx0XHRcdG1heFdpZHRoID0gc3R5bGUubWF4V2lkdGg7XG5cblx0XHRcdC8vIFB1dCBpbiB0aGUgbmV3IHZhbHVlcyB0byBnZXQgYSBjb21wdXRlZCB2YWx1ZSBvdXRcblx0XHRcdHN0eWxlLm1pbldpZHRoID0gc3R5bGUubWF4V2lkdGggPSBzdHlsZS53aWR0aCA9IHJldDtcblx0XHRcdHJldCA9IGNvbXB1dGVkLndpZHRoO1xuXG5cdFx0XHQvLyBSZXZlcnQgdGhlIGNoYW5nZWQgdmFsdWVzXG5cdFx0XHRzdHlsZS53aWR0aCA9IHdpZHRoO1xuXHRcdFx0c3R5bGUubWluV2lkdGggPSBtaW5XaWR0aDtcblx0XHRcdHN0eWxlLm1heFdpZHRoID0gbWF4V2lkdGg7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHJldCAhPT0gdW5kZWZpbmVkID9cblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0XHQvLyBJRSByZXR1cm5zIHpJbmRleCB2YWx1ZSBhcyBhbiBpbnRlZ2VyLlxuXHRcdHJldCArIFwiXCIgOlxuXHRcdHJldDtcbn1cblxuXG5mdW5jdGlvbiBhZGRHZXRIb29rSWYoIGNvbmRpdGlvbkZuLCBob29rRm4gKSB7XG5cblx0Ly8gRGVmaW5lIHRoZSBob29rLCB3ZSdsbCBjaGVjayBvbiB0aGUgZmlyc3QgcnVuIGlmIGl0J3MgcmVhbGx5IG5lZWRlZC5cblx0cmV0dXJuIHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCBjb25kaXRpb25GbigpICkge1xuXG5cdFx0XHRcdC8vIEhvb2sgbm90IG5lZWRlZCAob3IgaXQncyBub3QgcG9zc2libGUgdG8gdXNlIGl0IGR1ZVxuXHRcdFx0XHQvLyB0byBtaXNzaW5nIGRlcGVuZGVuY3kpLCByZW1vdmUgaXQuXG5cdFx0XHRcdGRlbGV0ZSB0aGlzLmdldDtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBIb29rIG5lZWRlZDsgcmVkZWZpbmUgaXQgc28gdGhhdCB0aGUgc3VwcG9ydCB0ZXN0IGlzIG5vdCBleGVjdXRlZCBhZ2Fpbi5cblx0XHRcdHJldHVybiAoIHRoaXMuZ2V0ID0gaG9va0ZuICkuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0fTtcbn1cblxuXG52YXJcblxuXHQvLyBTd2FwcGFibGUgaWYgZGlzcGxheSBpcyBub25lIG9yIHN0YXJ0cyB3aXRoIHRhYmxlXG5cdC8vIGV4Y2VwdCBcInRhYmxlXCIsIFwidGFibGUtY2VsbFwiLCBvciBcInRhYmxlLWNhcHRpb25cIlxuXHQvLyBTZWUgaGVyZSBmb3IgZGlzcGxheSB2YWx1ZXM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvQ1NTL2Rpc3BsYXlcblx0cmRpc3BsYXlzd2FwID0gL14obm9uZXx0YWJsZSg/IS1jW2VhXSkuKykvLFxuXHRyY3VzdG9tUHJvcCA9IC9eLS0vLFxuXHRjc3NTaG93ID0geyBwb3NpdGlvbjogXCJhYnNvbHV0ZVwiLCB2aXNpYmlsaXR5OiBcImhpZGRlblwiLCBkaXNwbGF5OiBcImJsb2NrXCIgfSxcblx0Y3NzTm9ybWFsVHJhbnNmb3JtID0ge1xuXHRcdGxldHRlclNwYWNpbmc6IFwiMFwiLFxuXHRcdGZvbnRXZWlnaHQ6IFwiNDAwXCJcblx0fSxcblxuXHRjc3NQcmVmaXhlcyA9IFsgXCJXZWJraXRcIiwgXCJNb3pcIiwgXCJtc1wiIF0sXG5cdGVtcHR5U3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkuc3R5bGU7XG5cbi8vIFJldHVybiBhIGNzcyBwcm9wZXJ0eSBtYXBwZWQgdG8gYSBwb3RlbnRpYWxseSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHlcbmZ1bmN0aW9uIHZlbmRvclByb3BOYW1lKCBuYW1lICkge1xuXG5cdC8vIFNob3J0Y3V0IGZvciBuYW1lcyB0aGF0IGFyZSBub3QgdmVuZG9yIHByZWZpeGVkXG5cdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdHJldHVybiBuYW1lO1xuXHR9XG5cblx0Ly8gQ2hlY2sgZm9yIHZlbmRvciBwcmVmaXhlZCBuYW1lc1xuXHR2YXIgY2FwTmFtZSA9IG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApLFxuXHRcdGkgPSBjc3NQcmVmaXhlcy5sZW5ndGg7XG5cblx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0bmFtZSA9IGNzc1ByZWZpeGVzWyBpIF0gKyBjYXBOYW1lO1xuXHRcdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdFx0cmV0dXJuIG5hbWU7XG5cdFx0fVxuXHR9XG59XG5cbi8vIFJldHVybiBhIHByb3BlcnR5IG1hcHBlZCBhbG9uZyB3aGF0IGpRdWVyeS5jc3NQcm9wcyBzdWdnZXN0cyBvciB0b1xuLy8gYSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHkuXG5mdW5jdGlvbiBmaW5hbFByb3BOYW1lKCBuYW1lICkge1xuXHR2YXIgcmV0ID0galF1ZXJ5LmNzc1Byb3BzWyBuYW1lIF07XG5cdGlmICggIXJldCApIHtcblx0XHRyZXQgPSBqUXVlcnkuY3NzUHJvcHNbIG5hbWUgXSA9IHZlbmRvclByb3BOYW1lKCBuYW1lICkgfHwgbmFtZTtcblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICkge1xuXG5cdC8vIEFueSByZWxhdGl2ZSAoKy8tKSB2YWx1ZXMgaGF2ZSBhbHJlYWR5IGJlZW5cblx0Ly8gbm9ybWFsaXplZCBhdCB0aGlzIHBvaW50XG5cdHZhciBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApO1xuXHRyZXR1cm4gbWF0Y2hlcyA/XG5cblx0XHQvLyBHdWFyZCBhZ2FpbnN0IHVuZGVmaW5lZCBcInN1YnRyYWN0XCIsIGUuZy4sIHdoZW4gdXNlZCBhcyBpbiBjc3NIb29rc1xuXHRcdE1hdGgubWF4KCAwLCBtYXRjaGVzWyAyIF0gLSAoIHN1YnRyYWN0IHx8IDAgKSApICsgKCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgOlxuXHRcdHZhbHVlO1xufVxuXG5mdW5jdGlvbiBhdWdtZW50V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEsIGlzQm9yZGVyQm94LCBzdHlsZXMgKSB7XG5cdHZhciBpLFxuXHRcdHZhbCA9IDA7XG5cblx0Ly8gSWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBtZWFzdXJlbWVudCwgYXZvaWQgYXVnbWVudGF0aW9uXG5cdGlmICggZXh0cmEgPT09ICggaXNCb3JkZXJCb3ggPyBcImJvcmRlclwiIDogXCJjb250ZW50XCIgKSApIHtcblx0XHRpID0gNDtcblxuXHQvLyBPdGhlcndpc2UgaW5pdGlhbGl6ZSBmb3IgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBwcm9wZXJ0aWVzXG5cdH0gZWxzZSB7XG5cdFx0aSA9IG5hbWUgPT09IFwid2lkdGhcIiA/IDEgOiAwO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgNDsgaSArPSAyICkge1xuXG5cdFx0Ly8gQm90aCBib3ggbW9kZWxzIGV4Y2x1ZGUgbWFyZ2luLCBzbyBhZGQgaXQgaWYgd2Ugd2FudCBpdFxuXHRcdGlmICggZXh0cmEgPT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHR2YWwgKz0galF1ZXJ5LmNzcyggZWxlbSwgZXh0cmEgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpc0JvcmRlckJveCApIHtcblxuXHRcdFx0Ly8gYm9yZGVyLWJveCBpbmNsdWRlcyBwYWRkaW5nLCBzbyByZW1vdmUgaXQgaWYgd2Ugd2FudCBjb250ZW50XG5cdFx0XHRpZiAoIGV4dHJhID09PSBcImNvbnRlbnRcIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBib3JkZXIgbm9yIG1hcmdpbiwgc28gcmVtb3ZlIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJtYXJnaW5cIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCwgc28gYWRkIHBhZGRpbmdcblx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBhZGRpbmdcIiArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCBub3IgcGFkZGluZywgc28gYWRkIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJwYWRkaW5nXCIgKSB7XG5cdFx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcImJvcmRlclwiICsgY3NzRXhwYW5kWyBpIF0gKyBcIldpZHRoXCIsIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICkge1xuXG5cdC8vIFN0YXJ0IHdpdGggY29tcHV0ZWQgc3R5bGVcblx0dmFyIHZhbHVlSXNCb3JkZXJCb3gsXG5cdFx0c3R5bGVzID0gZ2V0U3R5bGVzKCBlbGVtICksXG5cdFx0dmFsID0gY3VyQ1NTKCBlbGVtLCBuYW1lLCBzdHlsZXMgKSxcblx0XHRpc0JvcmRlckJveCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm94U2l6aW5nXCIsIGZhbHNlLCBzdHlsZXMgKSA9PT0gXCJib3JkZXItYm94XCI7XG5cblx0Ly8gQ29tcHV0ZWQgdW5pdCBpcyBub3QgcGl4ZWxzLiBTdG9wIGhlcmUgYW5kIHJldHVybi5cblx0aWYgKCBybnVtbm9ucHgudGVzdCggdmFsICkgKSB7XG5cdFx0cmV0dXJuIHZhbDtcblx0fVxuXG5cdC8vIENoZWNrIGZvciBzdHlsZSBpbiBjYXNlIGEgYnJvd3NlciB3aGljaCByZXR1cm5zIHVucmVsaWFibGUgdmFsdWVzXG5cdC8vIGZvciBnZXRDb21wdXRlZFN0eWxlIHNpbGVudGx5IGZhbGxzIGJhY2sgdG8gdGhlIHJlbGlhYmxlIGVsZW0uc3R5bGVcblx0dmFsdWVJc0JvcmRlckJveCA9IGlzQm9yZGVyQm94ICYmXG5cdFx0KCBzdXBwb3J0LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgdmFsID09PSBlbGVtLnN0eWxlWyBuYW1lIF0gKTtcblxuXHQvLyBGYWxsIGJhY2sgdG8gb2Zmc2V0V2lkdGgvSGVpZ2h0IHdoZW4gdmFsdWUgaXMgXCJhdXRvXCJcblx0Ly8gVGhpcyBoYXBwZW5zIGZvciBpbmxpbmUgZWxlbWVudHMgd2l0aCBubyBleHBsaWNpdCBzZXR0aW5nIChnaC0zNTcxKVxuXHRpZiAoIHZhbCA9PT0gXCJhdXRvXCIgKSB7XG5cdFx0dmFsID0gZWxlbVsgXCJvZmZzZXRcIiArIG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApIF07XG5cdH1cblxuXHQvLyBOb3JtYWxpemUgXCJcIiwgYXV0bywgYW5kIHByZXBhcmUgZm9yIGV4dHJhXG5cdHZhbCA9IHBhcnNlRmxvYXQoIHZhbCApIHx8IDA7XG5cblx0Ly8gVXNlIHRoZSBhY3RpdmUgYm94LXNpemluZyBtb2RlbCB0byBhZGQvc3VidHJhY3QgaXJyZWxldmFudCBzdHlsZXNcblx0cmV0dXJuICggdmFsICtcblx0XHRhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdGVsZW0sXG5cdFx0XHRuYW1lLFxuXHRcdFx0ZXh0cmEgfHwgKCBpc0JvcmRlckJveCA/IFwiYm9yZGVyXCIgOiBcImNvbnRlbnRcIiApLFxuXHRcdFx0dmFsdWVJc0JvcmRlckJveCxcblx0XHRcdHN0eWxlc1xuXHRcdClcblx0KSArIFwicHhcIjtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIEFkZCBpbiBzdHlsZSBwcm9wZXJ0eSBob29rcyBmb3Igb3ZlcnJpZGluZyB0aGUgZGVmYXVsdFxuXHQvLyBiZWhhdmlvciBvZiBnZXR0aW5nIGFuZCBzZXR0aW5nIGEgc3R5bGUgcHJvcGVydHlcblx0Y3NzSG9va3M6IHtcblx0XHRvcGFjaXR5OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblxuXHRcdFx0XHRcdC8vIFdlIHNob3VsZCBhbHdheXMgZ2V0IGEgbnVtYmVyIGJhY2sgZnJvbSBvcGFjaXR5XG5cdFx0XHRcdFx0dmFyIHJldCA9IGN1ckNTUyggZWxlbSwgXCJvcGFjaXR5XCIgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmV0ID09PSBcIlwiID8gXCIxXCIgOiByZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0Ly8gRG9uJ3QgYXV0b21hdGljYWxseSBhZGQgXCJweFwiIHRvIHRoZXNlIHBvc3NpYmx5LXVuaXRsZXNzIHByb3BlcnRpZXNcblx0Y3NzTnVtYmVyOiB7XG5cdFx0XCJhbmltYXRpb25JdGVyYXRpb25Db3VudFwiOiB0cnVlLFxuXHRcdFwiY29sdW1uQ291bnRcIjogdHJ1ZSxcblx0XHRcImZpbGxPcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJmbGV4R3Jvd1wiOiB0cnVlLFxuXHRcdFwiZmxleFNocmlua1wiOiB0cnVlLFxuXHRcdFwiZm9udFdlaWdodFwiOiB0cnVlLFxuXHRcdFwibGluZUhlaWdodFwiOiB0cnVlLFxuXHRcdFwib3BhY2l0eVwiOiB0cnVlLFxuXHRcdFwib3JkZXJcIjogdHJ1ZSxcblx0XHRcIm9ycGhhbnNcIjogdHJ1ZSxcblx0XHRcIndpZG93c1wiOiB0cnVlLFxuXHRcdFwiekluZGV4XCI6IHRydWUsXG5cdFx0XCJ6b29tXCI6IHRydWVcblx0fSxcblxuXHQvLyBBZGQgaW4gcHJvcGVydGllcyB3aG9zZSBuYW1lcyB5b3Ugd2lzaCB0byBmaXggYmVmb3JlXG5cdC8vIHNldHRpbmcgb3IgZ2V0dGluZyB0aGUgdmFsdWVcblx0Y3NzUHJvcHM6IHtcblx0XHRcImZsb2F0XCI6IFwiY3NzRmxvYXRcIlxuXHR9LFxuXG5cdC8vIEdldCBhbmQgc2V0IHRoZSBzdHlsZSBwcm9wZXJ0eSBvbiBhIERPTSBOb2RlXG5cdHN0eWxlOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUsIGV4dHJhICkge1xuXG5cdFx0Ly8gRG9uJ3Qgc2V0IHN0eWxlcyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBlbGVtLm5vZGVUeXBlID09PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT09IDggfHwgIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lXG5cdFx0dmFyIHJldCwgdHlwZSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKSxcblx0XHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIHF1ZXJ5IHRoZSB2YWx1ZSBpZiBpdCBpcyBhIENTUyBjdXN0b20gcHJvcGVydHlcblx0XHQvLyBzaW5jZSB0aGV5IGFyZSB1c2VyLWRlZmluZWQuXG5cdFx0aWYgKCAhaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0bmFtZSA9IGZpbmFsUHJvcE5hbWUoIG9yaWdOYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0cyBob29rIGZvciB0aGUgcHJlZml4ZWQgdmVyc2lvbiwgdGhlbiB1bnByZWZpeGVkIHZlcnNpb25cblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIENoZWNrIGlmIHdlJ3JlIHNldHRpbmcgYSB2YWx1ZVxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cblx0XHRcdC8vIENvbnZlcnQgXCIrPVwiIG9yIFwiLT1cIiB0byByZWxhdGl2ZSBudW1iZXJzICgjNzM0NSlcblx0XHRcdGlmICggdHlwZSA9PT0gXCJzdHJpbmdcIiAmJiAoIHJldCA9IHJjc3NOdW0uZXhlYyggdmFsdWUgKSApICYmIHJldFsgMSBdICkge1xuXHRcdFx0XHR2YWx1ZSA9IGFkanVzdENTUyggZWxlbSwgbmFtZSwgcmV0ICk7XG5cblx0XHRcdFx0Ly8gRml4ZXMgYnVnICM5MjM3XG5cdFx0XHRcdHR5cGUgPSBcIm51bWJlclwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgdGhhdCBudWxsIGFuZCBOYU4gdmFsdWVzIGFyZW4ndCBzZXQgKCM3MTE2KVxuXHRcdFx0aWYgKCB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBhIG51bWJlciB3YXMgcGFzc2VkIGluLCBhZGQgdGhlIHVuaXQgKGV4Y2VwdCBmb3IgY2VydGFpbiBDU1MgcHJvcGVydGllcylcblx0XHRcdGlmICggdHlwZSA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsdWUgKz0gcmV0ICYmIHJldFsgMyBdIHx8ICggalF1ZXJ5LmNzc051bWJlclsgb3JpZ05hbWUgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gYmFja2dyb3VuZC0qIHByb3BzIGFmZmVjdCBvcmlnaW5hbCBjbG9uZSdzIHZhbHVlc1xuXHRcdFx0aWYgKCAhc3VwcG9ydC5jbGVhckNsb25lU3R5bGUgJiYgdmFsdWUgPT09IFwiXCIgJiYgbmFtZS5pbmRleE9mKCBcImJhY2tncm91bmRcIiApID09PSAwICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gXCJpbmhlcml0XCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0IHZhbHVlLCBvdGhlcndpc2UganVzdCBzZXQgdGhlIHNwZWNpZmllZCB2YWx1ZVxuXHRcdFx0aWYgKCAhaG9va3MgfHwgISggXCJzZXRcIiBpbiBob29rcyApIHx8XG5cdFx0XHRcdCggdmFsdWUgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBleHRyYSApICkgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHRpZiAoIGlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdFx0XHRzdHlsZS5zZXRQcm9wZXJ0eSggbmFtZSwgdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBub24tY29tcHV0ZWQgdmFsdWUgZnJvbSB0aGVyZVxuXHRcdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBmYWxzZSwgZXh0cmEgKSApICE9PSB1bmRlZmluZWQgKSB7XG5cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gT3RoZXJ3aXNlIGp1c3QgZ2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBzdHlsZSBvYmplY3Rcblx0XHRcdHJldHVybiBzdHlsZVsgbmFtZSBdO1xuXHRcdH1cblx0fSxcblxuXHRjc3M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBleHRyYSwgc3R5bGVzICkge1xuXHRcdHZhciB2YWwsIG51bSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIG1vZGlmeSB0aGUgdmFsdWUgaWYgaXQgaXMgYSBDU1MgY3VzdG9tIHByb3BlcnR5XG5cdFx0Ly8gc2luY2UgdGhleSBhcmUgdXNlci1kZWZpbmVkLlxuXHRcdGlmICggIWlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdG5hbWUgPSBmaW5hbFByb3BOYW1lKCBvcmlnTmFtZSApO1xuXHRcdH1cblxuXHRcdC8vIFRyeSBwcmVmaXhlZCBuYW1lIGZvbGxvd2VkIGJ5IHRoZSB1bnByZWZpeGVkIG5hbWVcblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsID0gaG9va3MuZ2V0KCBlbGVtLCB0cnVlLCBleHRyYSApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSwgaWYgYSB3YXkgdG8gZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbCA9IGN1ckNTUyggZWxlbSwgbmFtZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udmVydCBcIm5vcm1hbFwiIHRvIGNvbXB1dGVkIHZhbHVlXG5cdFx0aWYgKCB2YWwgPT09IFwibm9ybWFsXCIgJiYgbmFtZSBpbiBjc3NOb3JtYWxUcmFuc2Zvcm0gKSB7XG5cdFx0XHR2YWwgPSBjc3NOb3JtYWxUcmFuc2Zvcm1bIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIG51bWVyaWMgaWYgZm9yY2VkIG9yIGEgcXVhbGlmaWVyIHdhcyBwcm92aWRlZCBhbmQgdmFsIGxvb2tzIG51bWVyaWNcblx0XHRpZiAoIGV4dHJhID09PSBcIlwiIHx8IGV4dHJhICkge1xuXHRcdFx0bnVtID0gcGFyc2VGbG9hdCggdmFsICk7XG5cdFx0XHRyZXR1cm4gZXh0cmEgPT09IHRydWUgfHwgaXNGaW5pdGUoIG51bSApID8gbnVtIHx8IDAgOiB2YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbDtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImhlaWdodFwiLCBcIndpZHRoXCIgXSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdID0ge1xuXHRcdGdldDogZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkLCBleHRyYSApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cblx0XHRcdFx0Ly8gQ2VydGFpbiBlbGVtZW50cyBjYW4gaGF2ZSBkaW1lbnNpb24gaW5mbyBpZiB3ZSBpbnZpc2libHkgc2hvdyB0aGVtXG5cdFx0XHRcdC8vIGJ1dCBpdCBtdXN0IGhhdmUgYSBjdXJyZW50IGRpc3BsYXkgc3R5bGUgdGhhdCB3b3VsZCBiZW5lZml0XG5cdFx0XHRcdHJldHVybiByZGlzcGxheXN3YXAudGVzdCggalF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKSApICYmXG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCtcblx0XHRcdFx0XHQvLyBUYWJsZSBjb2x1bW5zIGluIFNhZmFyaSBoYXZlIG5vbi16ZXJvIG9mZnNldFdpZHRoICYgemVyb1xuXHRcdFx0XHRcdC8vIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIHVubGVzcyBkaXNwbGF5IGlzIGNoYW5nZWQuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0XHRcdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYSBkaXNjb25uZWN0ZWQgbm9kZVxuXHRcdFx0XHRcdC8vIGluIElFIHRocm93cyBhbiBlcnJvci5cblx0XHRcdFx0XHQoICFlbGVtLmdldENsaWVudFJlY3RzKCkubGVuZ3RoIHx8ICFlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoICkgP1xuXHRcdFx0XHRcdFx0c3dhcCggZWxlbSwgY3NzU2hvdywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBnZXRXaWR0aE9ySGVpZ2h0KCBlbGVtLCBuYW1lLCBleHRyYSApO1xuXHRcdFx0XHRcdFx0fSApIDpcblx0XHRcdFx0XHRcdGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBleHRyYSApIHtcblx0XHRcdHZhciBtYXRjaGVzLFxuXHRcdFx0XHRzdHlsZXMgPSBleHRyYSAmJiBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHRcdFx0c3VidHJhY3QgPSBleHRyYSAmJiBhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdFx0XHRlbGVtLFxuXHRcdFx0XHRcdG5hbWUsXG5cdFx0XHRcdFx0ZXh0cmEsXG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIixcblx0XHRcdFx0XHRzdHlsZXNcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gQ29udmVydCB0byBwaXhlbHMgaWYgdmFsdWUgYWRqdXN0bWVudCBpcyBuZWVkZWRcblx0XHRcdGlmICggc3VidHJhY3QgJiYgKCBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApICkgJiZcblx0XHRcdFx0KCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgIT09IFwicHhcIiApIHtcblxuXHRcdFx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdFx0dmFsdWUgPSBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICk7XG5cdFx0fVxuXHR9O1xufSApO1xuXG5qUXVlcnkuY3NzSG9va3MubWFyZ2luTGVmdCA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5yZWxpYWJsZU1hcmdpbkxlZnQsXG5cdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRpZiAoIGNvbXB1dGVkICkge1xuXHRcdFx0cmV0dXJuICggcGFyc2VGbG9hdCggY3VyQ1NTKCBlbGVtLCBcIm1hcmdpbkxlZnRcIiApICkgfHxcblx0XHRcdFx0ZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC1cblx0XHRcdFx0XHRzd2FwKCBlbGVtLCB7IG1hcmdpbkxlZnQ6IDAgfSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuXHRcdFx0XHRcdH0gKVxuXHRcdFx0XHQpICsgXCJweFwiO1xuXHRcdH1cblx0fVxuKTtcblxuLy8gVGhlc2UgaG9va3MgYXJlIHVzZWQgYnkgYW5pbWF0ZSB0byBleHBhbmQgcHJvcGVydGllc1xualF1ZXJ5LmVhY2goIHtcblx0bWFyZ2luOiBcIlwiLFxuXHRwYWRkaW5nOiBcIlwiLFxuXHRib3JkZXI6IFwiV2lkdGhcIlxufSwgZnVuY3Rpb24oIHByZWZpeCwgc3VmZml4ICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdID0ge1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGkgPSAwLFxuXHRcdFx0XHRleHBhbmRlZCA9IHt9LFxuXG5cdFx0XHRcdC8vIEFzc3VtZXMgYSBzaW5nbGUgbnVtYmVyIGlmIG5vdCBhIHN0cmluZ1xuXHRcdFx0XHRwYXJ0cyA9IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlLnNwbGl0KCBcIiBcIiApIDogWyB2YWx1ZSBdO1xuXG5cdFx0XHRmb3IgKCA7IGkgPCA0OyBpKysgKSB7XG5cdFx0XHRcdGV4cGFuZGVkWyBwcmVmaXggKyBjc3NFeHBhbmRbIGkgXSArIHN1ZmZpeCBdID1cblx0XHRcdFx0XHRwYXJ0c1sgaSBdIHx8IHBhcnRzWyBpIC0gMiBdIHx8IHBhcnRzWyAwIF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBleHBhbmRlZDtcblx0XHR9XG5cdH07XG5cblx0aWYgKCAhcm1hcmdpbi50ZXN0KCBwcmVmaXggKSApIHtcblx0XHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdLnNldCA9IHNldFBvc2l0aXZlTnVtYmVyO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0Y3NzOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0dmFyIHN0eWxlcywgbGVuLFxuXHRcdFx0XHRtYXAgPSB7fSxcblx0XHRcdFx0aSA9IDA7XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggbmFtZSApICkge1xuXHRcdFx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKTtcblx0XHRcdFx0bGVuID0gbmFtZS5sZW5ndGg7XG5cblx0XHRcdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0bWFwWyBuYW1lWyBpIF0gXSA9IGpRdWVyeS5jc3MoIGVsZW0sIG5hbWVbIGkgXSwgZmFsc2UsIHN0eWxlcyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIG1hcDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUsIHZhbHVlICkgOlxuXHRcdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0fSwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH1cbn0gKTtcblxuXG5mdW5jdGlvbiBUd2VlbiggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKSB7XG5cdHJldHVybiBuZXcgVHdlZW4ucHJvdG90eXBlLmluaXQoIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nICk7XG59XG5qUXVlcnkuVHdlZW4gPSBUd2VlbjtcblxuVHdlZW4ucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogVHdlZW4sXG5cdGluaXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZywgdW5pdCApIHtcblx0XHR0aGlzLmVsZW0gPSBlbGVtO1xuXHRcdHRoaXMucHJvcCA9IHByb3A7XG5cdFx0dGhpcy5lYXNpbmcgPSBlYXNpbmcgfHwgalF1ZXJ5LmVhc2luZy5fZGVmYXVsdDtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHRcdHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCk7XG5cdFx0dGhpcy5lbmQgPSBlbmQ7XG5cdFx0dGhpcy51bml0ID0gdW5pdCB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0fSxcblx0Y3VyOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0cmV0dXJuIGhvb2tzICYmIGhvb2tzLmdldCA/XG5cdFx0XHRob29rcy5nZXQoIHRoaXMgKSA6XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuZ2V0KCB0aGlzICk7XG5cdH0sXG5cdHJ1bjogZnVuY3Rpb24oIHBlcmNlbnQgKSB7XG5cdFx0dmFyIGVhc2VkLFxuXHRcdFx0aG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0galF1ZXJ5LmVhc2luZ1sgdGhpcy5lYXNpbmcgXShcblx0XHRcdFx0cGVyY2VudCwgdGhpcy5vcHRpb25zLmR1cmF0aW9uICogcGVyY2VudCwgMCwgMSwgdGhpcy5vcHRpb25zLmR1cmF0aW9uXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0gcGVyY2VudDtcblx0XHR9XG5cdFx0dGhpcy5ub3cgPSAoIHRoaXMuZW5kIC0gdGhpcy5zdGFydCApICogZWFzZWQgKyB0aGlzLnN0YXJ0O1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc3RlcCApIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zdGVwLmNhbGwoIHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMgKTtcblx0XHR9XG5cblx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnNldCApIHtcblx0XHRcdGhvb2tzLnNldCggdGhpcyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KCB0aGlzICk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59O1xuXG5Ud2Vlbi5wcm90b3R5cGUuaW5pdC5wcm90b3R5cGUgPSBUd2Vlbi5wcm90b3R5cGU7XG5cblR3ZWVuLnByb3BIb29rcyA9IHtcblx0X2RlZmF1bHQ6IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRcdHZhciByZXN1bHQ7XG5cblx0XHRcdC8vIFVzZSBhIHByb3BlcnR5IG9uIHRoZSBlbGVtZW50IGRpcmVjdGx5IHdoZW4gaXQgaXMgbm90IGEgRE9NIGVsZW1lbnQsXG5cdFx0XHQvLyBvciB3aGVuIHRoZXJlIGlzIG5vIG1hdGNoaW5nIHN0eWxlIHByb3BlcnR5IHRoYXQgZXhpc3RzLlxuXHRcdFx0aWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlICE9PSAxIHx8XG5cdFx0XHRcdHR3ZWVuLmVsZW1bIHR3ZWVuLnByb3AgXSAhPSBudWxsICYmIHR3ZWVuLmVsZW0uc3R5bGVbIHR3ZWVuLnByb3AgXSA9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gdHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQYXNzaW5nIGFuIGVtcHR5IHN0cmluZyBhcyBhIDNyZCBwYXJhbWV0ZXIgdG8gLmNzcyB3aWxsIGF1dG9tYXRpY2FsbHlcblx0XHRcdC8vIGF0dGVtcHQgYSBwYXJzZUZsb2F0IGFuZCBmYWxsYmFjayB0byBhIHN0cmluZyBpZiB0aGUgcGFyc2UgZmFpbHMuXG5cdFx0XHQvLyBTaW1wbGUgdmFsdWVzIHN1Y2ggYXMgXCIxMHB4XCIgYXJlIHBhcnNlZCB0byBGbG9hdDtcblx0XHRcdC8vIGNvbXBsZXggdmFsdWVzIHN1Y2ggYXMgXCJyb3RhdGUoMXJhZClcIiBhcmUgcmV0dXJuZWQgYXMtaXMuXG5cdFx0XHRyZXN1bHQgPSBqUXVlcnkuY3NzKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCBcIlwiICk7XG5cblx0XHRcdC8vIEVtcHR5IHN0cmluZ3MsIG51bGwsIHVuZGVmaW5lZCBhbmQgXCJhdXRvXCIgYXJlIGNvbnZlcnRlZCB0byAwLlxuXHRcdFx0cmV0dXJuICFyZXN1bHQgfHwgcmVzdWx0ID09PSBcImF1dG9cIiA/IDAgOiByZXN1bHQ7XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblxuXHRcdFx0Ly8gVXNlIHN0ZXAgaG9vayBmb3IgYmFjayBjb21wYXQuXG5cdFx0XHQvLyBVc2UgY3NzSG9vayBpZiBpdHMgdGhlcmUuXG5cdFx0XHQvLyBVc2UgLnN0eWxlIGlmIGF2YWlsYWJsZSBhbmQgdXNlIHBsYWluIHByb3BlcnRpZXMgd2hlcmUgYXZhaWxhYmxlLlxuXHRcdFx0aWYgKCBqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdICkge1xuXHRcdFx0XHRqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdKCB0d2VlbiApO1xuXHRcdFx0fSBlbHNlIGlmICggdHdlZW4uZWxlbS5ub2RlVHlwZSA9PT0gMSAmJlxuXHRcdFx0XHQoIHR3ZWVuLmVsZW0uc3R5bGVbIGpRdWVyeS5jc3NQcm9wc1sgdHdlZW4ucHJvcCBdIF0gIT0gbnVsbCB8fFxuXHRcdFx0XHRcdGpRdWVyeS5jc3NIb29rc1sgdHdlZW4ucHJvcCBdICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgdHdlZW4ucHJvcCwgdHdlZW4ubm93ICsgdHdlZW4udW5pdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbi8vIFBhbmljIGJhc2VkIGFwcHJvYWNoIHRvIHNldHRpbmcgdGhpbmdzIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuVHdlZW4ucHJvcEhvb2tzLnNjcm9sbFRvcCA9IFR3ZWVuLnByb3BIb29rcy5zY3JvbGxMZWZ0ID0ge1xuXHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRpZiAoIHR3ZWVuLmVsZW0ubm9kZVR5cGUgJiYgdHdlZW4uZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmVhc2luZyA9IHtcblx0bGluZWFyOiBmdW5jdGlvbiggcCApIHtcblx0XHRyZXR1cm4gcDtcblx0fSxcblx0c3dpbmc6IGZ1bmN0aW9uKCBwICkge1xuXHRcdHJldHVybiAwLjUgLSBNYXRoLmNvcyggcCAqIE1hdGguUEkgKSAvIDI7XG5cdH0sXG5cdF9kZWZhdWx0OiBcInN3aW5nXCJcbn07XG5cbmpRdWVyeS5meCA9IFR3ZWVuLnByb3RvdHlwZS5pbml0O1xuXG4vLyBCYWNrIGNvbXBhdCA8MS44IGV4dGVuc2lvbiBwb2ludFxualF1ZXJ5LmZ4LnN0ZXAgPSB7fTtcblxuXG5cblxudmFyXG5cdGZ4Tm93LCBpblByb2dyZXNzLFxuXHRyZnh0eXBlcyA9IC9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxcblx0cnJ1biA9IC9xdWV1ZUhvb2tzJC87XG5cbmZ1bmN0aW9uIHNjaGVkdWxlKCkge1xuXHRpZiAoIGluUHJvZ3Jlc3MgKSB7XG5cdFx0aWYgKCBkb2N1bWVudC5oaWRkZW4gPT09IGZhbHNlICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgKSB7XG5cdFx0XHR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBzY2hlZHVsZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCggc2NoZWR1bGUsIGpRdWVyeS5meC5pbnRlcnZhbCApO1xuXHRcdH1cblxuXHRcdGpRdWVyeS5meC50aWNrKCk7XG5cdH1cbn1cblxuLy8gQW5pbWF0aW9ucyBjcmVhdGVkIHN5bmNocm9ub3VzbHkgd2lsbCBydW4gc3luY2hyb25vdXNseVxuZnVuY3Rpb24gY3JlYXRlRnhOb3coKSB7XG5cdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRmeE5vdyA9IHVuZGVmaW5lZDtcblx0fSApO1xuXHRyZXR1cm4gKCBmeE5vdyA9IGpRdWVyeS5ub3coKSApO1xufVxuXG4vLyBHZW5lcmF0ZSBwYXJhbWV0ZXJzIHRvIGNyZWF0ZSBhIHN0YW5kYXJkIGFuaW1hdGlvblxuZnVuY3Rpb24gZ2VuRngoIHR5cGUsIGluY2x1ZGVXaWR0aCApIHtcblx0dmFyIHdoaWNoLFxuXHRcdGkgPSAwLFxuXHRcdGF0dHJzID0geyBoZWlnaHQ6IHR5cGUgfTtcblxuXHQvLyBJZiB3ZSBpbmNsdWRlIHdpZHRoLCBzdGVwIHZhbHVlIGlzIDEgdG8gZG8gYWxsIGNzc0V4cGFuZCB2YWx1ZXMsXG5cdC8vIG90aGVyd2lzZSBzdGVwIHZhbHVlIGlzIDIgdG8gc2tpcCBvdmVyIExlZnQgYW5kIFJpZ2h0XG5cdGluY2x1ZGVXaWR0aCA9IGluY2x1ZGVXaWR0aCA/IDEgOiAwO1xuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgLSBpbmNsdWRlV2lkdGggKSB7XG5cdFx0d2hpY2ggPSBjc3NFeHBhbmRbIGkgXTtcblx0XHRhdHRyc1sgXCJtYXJnaW5cIiArIHdoaWNoIF0gPSBhdHRyc1sgXCJwYWRkaW5nXCIgKyB3aGljaCBdID0gdHlwZTtcblx0fVxuXG5cdGlmICggaW5jbHVkZVdpZHRoICkge1xuXHRcdGF0dHJzLm9wYWNpdHkgPSBhdHRycy53aWR0aCA9IHR5cGU7XG5cdH1cblxuXHRyZXR1cm4gYXR0cnM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR3ZWVuKCB2YWx1ZSwgcHJvcCwgYW5pbWF0aW9uICkge1xuXHR2YXIgdHdlZW4sXG5cdFx0Y29sbGVjdGlvbiA9ICggQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW10gKS5jb25jYXQoIEFuaW1hdGlvbi50d2VlbmVyc1sgXCIqXCIgXSApLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRpZiAoICggdHdlZW4gPSBjb2xsZWN0aW9uWyBpbmRleCBdLmNhbGwoIGFuaW1hdGlvbiwgcHJvcCwgdmFsdWUgKSApICkge1xuXG5cdFx0XHQvLyBXZSdyZSBkb25lIHdpdGggdGhpcyBwcm9wZXJ0eVxuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBkZWZhdWx0UHJlZmlsdGVyKCBlbGVtLCBwcm9wcywgb3B0cyApIHtcblx0dmFyIHByb3AsIHZhbHVlLCB0b2dnbGUsIGhvb2tzLCBvbGRmaXJlLCBwcm9wVHdlZW4sIHJlc3RvcmVEaXNwbGF5LCBkaXNwbGF5LFxuXHRcdGlzQm94ID0gXCJ3aWR0aFwiIGluIHByb3BzIHx8IFwiaGVpZ2h0XCIgaW4gcHJvcHMsXG5cdFx0YW5pbSA9IHRoaXMsXG5cdFx0b3JpZyA9IHt9LFxuXHRcdHN0eWxlID0gZWxlbS5zdHlsZSxcblx0XHRoaWRkZW4gPSBlbGVtLm5vZGVUeXBlICYmIGlzSGlkZGVuV2l0aGluVHJlZSggZWxlbSApLFxuXHRcdGRhdGFTaG93ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImZ4c2hvd1wiICk7XG5cblx0Ly8gUXVldWUtc2tpcHBpbmcgYW5pbWF0aW9ucyBoaWphY2sgdGhlIGZ4IGhvb2tzXG5cdGlmICggIW9wdHMucXVldWUgKSB7XG5cdFx0aG9va3MgPSBqUXVlcnkuX3F1ZXVlSG9va3MoIGVsZW0sIFwiZnhcIiApO1xuXHRcdGlmICggaG9va3MudW5xdWV1ZWQgPT0gbnVsbCApIHtcblx0XHRcdGhvb2tzLnVucXVldWVkID0gMDtcblx0XHRcdG9sZGZpcmUgPSBob29rcy5lbXB0eS5maXJlO1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICFob29rcy51bnF1ZXVlZCApIHtcblx0XHRcdFx0XHRvbGRmaXJlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fVxuXHRcdGhvb2tzLnVucXVldWVkKys7XG5cblx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIEVuc3VyZSB0aGUgY29tcGxldGUgaGFuZGxlciBpcyBjYWxsZWQgYmVmb3JlIHRoaXMgY29tcGxldGVzXG5cdFx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGhvb2tzLnVucXVldWVkLS07XG5cdFx0XHRcdGlmICggIWpRdWVyeS5xdWV1ZSggZWxlbSwgXCJmeFwiICkubGVuZ3RoICkge1xuXHRcdFx0XHRcdGhvb2tzLmVtcHR5LmZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIERldGVjdCBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRmb3IgKCBwcm9wIGluIHByb3BzICkge1xuXHRcdHZhbHVlID0gcHJvcHNbIHByb3AgXTtcblx0XHRpZiAoIHJmeHR5cGVzLnRlc3QoIHZhbHVlICkgKSB7XG5cdFx0XHRkZWxldGUgcHJvcHNbIHByb3AgXTtcblx0XHRcdHRvZ2dsZSA9IHRvZ2dsZSB8fCB2YWx1ZSA9PT0gXCJ0b2dnbGVcIjtcblx0XHRcdGlmICggdmFsdWUgPT09ICggaGlkZGVuID8gXCJoaWRlXCIgOiBcInNob3dcIiApICkge1xuXG5cdFx0XHRcdC8vIFByZXRlbmQgdG8gYmUgaGlkZGVuIGlmIHRoaXMgaXMgYSBcInNob3dcIiBhbmRcblx0XHRcdFx0Ly8gdGhlcmUgaXMgc3RpbGwgZGF0YSBmcm9tIGEgc3RvcHBlZCBzaG93L2hpZGVcblx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gXCJzaG93XCIgJiYgZGF0YVNob3cgJiYgZGF0YVNob3dbIHByb3AgXSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdGhpZGRlbiA9IHRydWU7XG5cblx0XHRcdFx0Ly8gSWdub3JlIGFsbCBvdGhlciBuby1vcCBzaG93L2hpZGUgZGF0YVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvcmlnWyBwcm9wIF0gPSBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdIHx8IGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIEJhaWwgb3V0IGlmIHRoaXMgaXMgYSBuby1vcCBsaWtlIC5oaWRlKCkuaGlkZSgpXG5cdHByb3BUd2VlbiA9ICFqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcHMgKTtcblx0aWYgKCAhcHJvcFR3ZWVuICYmIGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBvcmlnICkgKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Ly8gUmVzdHJpY3QgXCJvdmVyZmxvd1wiIGFuZCBcImRpc3BsYXlcIiBzdHlsZXMgZHVyaW5nIGJveCBhbmltYXRpb25zXG5cdGlmICggaXNCb3ggJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExLCBFZGdlIDEyIC0gMTNcblx0XHQvLyBSZWNvcmQgYWxsIDMgb3ZlcmZsb3cgYXR0cmlidXRlcyBiZWNhdXNlIElFIGRvZXMgbm90IGluZmVyIHRoZSBzaG9ydGhhbmRcblx0XHQvLyBmcm9tIGlkZW50aWNhbGx5LXZhbHVlZCBvdmVyZmxvd1ggYW5kIG92ZXJmbG93WVxuXHRcdG9wdHMub3ZlcmZsb3cgPSBbIHN0eWxlLm92ZXJmbG93LCBzdHlsZS5vdmVyZmxvd1gsIHN0eWxlLm92ZXJmbG93WSBdO1xuXG5cdFx0Ly8gSWRlbnRpZnkgYSBkaXNwbGF5IHR5cGUsIHByZWZlcnJpbmcgb2xkIHNob3cvaGlkZSBkYXRhIG92ZXIgdGhlIENTUyBjYXNjYWRlXG5cdFx0cmVzdG9yZURpc3BsYXkgPSBkYXRhU2hvdyAmJiBkYXRhU2hvdy5kaXNwbGF5O1xuXHRcdGlmICggcmVzdG9yZURpc3BsYXkgPT0gbnVsbCApIHtcblx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApO1xuXHRcdH1cblx0XHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKTtcblx0XHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSApIHtcblx0XHRcdFx0ZGlzcGxheSA9IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHQvLyBHZXQgbm9uZW1wdHkgdmFsdWUocykgYnkgdGVtcG9yYXJpbHkgZm9yY2luZyB2aXNpYmlsaXR5XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSwgdHJ1ZSApO1xuXHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheSB8fCByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFuaW1hdGUgaW5saW5lIGVsZW1lbnRzIGFzIGlubGluZS1ibG9ja1xuXHRcdGlmICggZGlzcGxheSA9PT0gXCJpbmxpbmVcIiB8fCBkaXNwbGF5ID09PSBcImlubGluZS1ibG9ja1wiICYmIHJlc3RvcmVEaXNwbGF5ICE9IG51bGwgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwiZmxvYXRcIiApID09PSBcIm5vbmVcIiApIHtcblxuXHRcdFx0XHQvLyBSZXN0b3JlIHRoZSBvcmlnaW5hbCBkaXNwbGF5IHZhbHVlIGF0IHRoZSBlbmQgb2YgcHVyZSBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRcdFx0XHRpZiAoICFwcm9wVHdlZW4gKSB7XG5cdFx0XHRcdFx0YW5pbS5kb25lKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0ZGlzcGxheSA9IHN0eWxlLmRpc3BsYXk7XG5cdFx0XHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGRpc3BsYXkgPT09IFwibm9uZVwiID8gXCJcIiA6IGRpc3BsYXk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggb3B0cy5vdmVyZmxvdyApIHtcblx0XHRzdHlsZS5vdmVyZmxvdyA9IFwiaGlkZGVuXCI7XG5cdFx0YW5pbS5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0c3R5bGUub3ZlcmZsb3cgPSBvcHRzLm92ZXJmbG93WyAwIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1ggPSBvcHRzLm92ZXJmbG93WyAxIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1kgPSBvcHRzLm92ZXJmbG93WyAyIF07XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50IHNob3cvaGlkZSBhbmltYXRpb25zXG5cdHByb3BUd2VlbiA9IGZhbHNlO1xuXHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cblx0XHQvLyBHZW5lcmFsIHNob3cvaGlkZSBzZXR1cCBmb3IgdGhpcyBlbGVtZW50IGFuaW1hdGlvblxuXHRcdGlmICggIXByb3BUd2VlbiApIHtcblx0XHRcdGlmICggZGF0YVNob3cgKSB7XG5cdFx0XHRcdGlmICggXCJoaWRkZW5cIiBpbiBkYXRhU2hvdyApIHtcblx0XHRcdFx0XHRoaWRkZW4gPSBkYXRhU2hvdy5oaWRkZW47XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFTaG93ID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCBcImZ4c2hvd1wiLCB7IGRpc3BsYXk6IHJlc3RvcmVEaXNwbGF5IH0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RvcmUgaGlkZGVuL3Zpc2libGUgZm9yIHRvZ2dsZSBzbyBgLnN0b3AoKS50b2dnbGUoKWAgXCJyZXZlcnNlc1wiXG5cdFx0XHRpZiAoIHRvZ2dsZSApIHtcblx0XHRcdFx0ZGF0YVNob3cuaGlkZGVuID0gIWhpZGRlbjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2hvdyBlbGVtZW50cyBiZWZvcmUgYW5pbWF0aW5nIHRoZW1cblx0XHRcdGlmICggaGlkZGVuICkge1xuXHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0sIHRydWUgKTtcblx0XHRcdH1cblxuXHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdGFuaW0uZG9uZSggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdFx0Ly8gVGhlIGZpbmFsIHN0ZXAgb2YgYSBcImhpZGVcIiBhbmltYXRpb24gaXMgYWN0dWFsbHkgaGlkaW5nIHRoZSBlbGVtZW50XG5cdFx0XHRcdGlmICggIWhpZGRlbiApIHtcblx0XHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIFwiZnhzaG93XCIgKTtcblx0XHRcdFx0Zm9yICggcHJvcCBpbiBvcmlnICkge1xuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCwgb3JpZ1sgcHJvcCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHQvLyBQZXItcHJvcGVydHkgc2V0dXBcblx0XHRwcm9wVHdlZW4gPSBjcmVhdGVUd2VlbiggaGlkZGVuID8gZGF0YVNob3dbIHByb3AgXSA6IDAsIHByb3AsIGFuaW0gKTtcblx0XHRpZiAoICEoIHByb3AgaW4gZGF0YVNob3cgKSApIHtcblx0XHRcdGRhdGFTaG93WyBwcm9wIF0gPSBwcm9wVHdlZW4uc3RhcnQ7XG5cdFx0XHRpZiAoIGhpZGRlbiApIHtcblx0XHRcdFx0cHJvcFR3ZWVuLmVuZCA9IHByb3BUd2Vlbi5zdGFydDtcblx0XHRcdFx0cHJvcFR3ZWVuLnN0YXJ0ID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJvcEZpbHRlciggcHJvcHMsIHNwZWNpYWxFYXNpbmcgKSB7XG5cdHZhciBpbmRleCwgbmFtZSwgZWFzaW5nLCB2YWx1ZSwgaG9va3M7XG5cblx0Ly8gY2FtZWxDYXNlLCBzcGVjaWFsRWFzaW5nIGFuZCBleHBhbmQgY3NzSG9vayBwYXNzXG5cdGZvciAoIGluZGV4IGluIHByb3BzICkge1xuXHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBpbmRleCApO1xuXHRcdGVhc2luZyA9IHNwZWNpYWxFYXNpbmdbIG5hbWUgXTtcblx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdO1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsdWUgKSApIHtcblx0XHRcdGVhc2luZyA9IHZhbHVlWyAxIF07XG5cdFx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdID0gdmFsdWVbIDAgXTtcblx0XHR9XG5cblx0XHRpZiAoIGluZGV4ICE9PSBuYW1lICkge1xuXHRcdFx0cHJvcHNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0ZGVsZXRlIHByb3BzWyBpbmRleCBdO1xuXHRcdH1cblxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF07XG5cdFx0aWYgKCBob29rcyAmJiBcImV4cGFuZFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsdWUgPSBob29rcy5leHBhbmQoIHZhbHVlICk7XG5cdFx0XHRkZWxldGUgcHJvcHNbIG5hbWUgXTtcblxuXHRcdFx0Ly8gTm90IHF1aXRlICQuZXh0ZW5kLCB0aGlzIHdvbid0IG92ZXJ3cml0ZSBleGlzdGluZyBrZXlzLlxuXHRcdFx0Ly8gUmV1c2luZyAnaW5kZXgnIGJlY2F1c2Ugd2UgaGF2ZSB0aGUgY29ycmVjdCBcIm5hbWVcIlxuXHRcdFx0Zm9yICggaW5kZXggaW4gdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggISggaW5kZXggaW4gcHJvcHMgKSApIHtcblx0XHRcdFx0XHRwcm9wc1sgaW5kZXggXSA9IHZhbHVlWyBpbmRleCBdO1xuXHRcdFx0XHRcdHNwZWNpYWxFYXNpbmdbIGluZGV4IF0gPSBlYXNpbmc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0c3BlY2lhbEVhc2luZ1sgbmFtZSBdID0gZWFzaW5nO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBBbmltYXRpb24oIGVsZW0sIHByb3BlcnRpZXMsIG9wdGlvbnMgKSB7XG5cdHZhciByZXN1bHQsXG5cdFx0c3RvcHBlZCxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gQW5pbWF0aW9uLnByZWZpbHRlcnMubGVuZ3RoLFxuXHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCkuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRG9uJ3QgbWF0Y2ggZWxlbSBpbiB0aGUgOmFuaW1hdGVkIHNlbGVjdG9yXG5cdFx0XHRkZWxldGUgdGljay5lbGVtO1xuXHRcdH0gKSxcblx0XHR0aWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50VGltZSA9IGZ4Tm93IHx8IGNyZWF0ZUZ4Tm93KCksXG5cdFx0XHRcdHJlbWFpbmluZyA9IE1hdGgubWF4KCAwLCBhbmltYXRpb24uc3RhcnRUaW1lICsgYW5pbWF0aW9uLmR1cmF0aW9uIC0gY3VycmVudFRpbWUgKSxcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDIuMyBvbmx5XG5cdFx0XHRcdC8vIEFyY2hhaWMgY3Jhc2ggYnVnIHdvbid0IGFsbG93IHVzIHRvIHVzZSBgMSAtICggMC41IHx8IDAgKWAgKCMxMjQ5Nylcblx0XHRcdFx0dGVtcCA9IHJlbWFpbmluZyAvIGFuaW1hdGlvbi5kdXJhdGlvbiB8fCAwLFxuXHRcdFx0XHRwZXJjZW50ID0gMSAtIHRlbXAsXG5cdFx0XHRcdGluZGV4ID0gMCxcblx0XHRcdFx0bGVuZ3RoID0gYW5pbWF0aW9uLnR3ZWVucy5sZW5ndGg7XG5cblx0XHRcdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCBwZXJjZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBwZXJjZW50LCByZW1haW5pbmcgXSApO1xuXG5cdFx0XHQvLyBJZiB0aGVyZSdzIG1vcmUgdG8gZG8sIHlpZWxkXG5cdFx0XHRpZiAoIHBlcmNlbnQgPCAxICYmIGxlbmd0aCApIHtcblx0XHRcdFx0cmV0dXJuIHJlbWFpbmluZztcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgdGhpcyB3YXMgYW4gZW1wdHkgYW5pbWF0aW9uLCBzeW50aGVzaXplIGEgZmluYWwgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uXG5cdFx0XHRpZiAoICFsZW5ndGggKSB7XG5cdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCAxLCAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVzb2x2ZSB0aGUgYW5pbWF0aW9uIGFuZCByZXBvcnQgaXRzIGNvbmNsdXNpb25cblx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiBdICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSxcblx0XHRhbmltYXRpb24gPSBkZWZlcnJlZC5wcm9taXNlKCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0cHJvcHM6IGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wZXJ0aWVzICksXG5cdFx0XHRvcHRzOiBqUXVlcnkuZXh0ZW5kKCB0cnVlLCB7XG5cdFx0XHRcdHNwZWNpYWxFYXNpbmc6IHt9LFxuXHRcdFx0XHRlYXNpbmc6IGpRdWVyeS5lYXNpbmcuX2RlZmF1bHRcblx0XHRcdH0sIG9wdGlvbnMgKSxcblx0XHRcdG9yaWdpbmFsUHJvcGVydGllczogcHJvcGVydGllcyxcblx0XHRcdG9yaWdpbmFsT3B0aW9uczogb3B0aW9ucyxcblx0XHRcdHN0YXJ0VGltZTogZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuXHRcdFx0dHdlZW5zOiBbXSxcblx0XHRcdGNyZWF0ZVR3ZWVuOiBmdW5jdGlvbiggcHJvcCwgZW5kICkge1xuXHRcdFx0XHR2YXIgdHdlZW4gPSBqUXVlcnkuVHdlZW4oIGVsZW0sIGFuaW1hdGlvbi5vcHRzLCBwcm9wLCBlbmQsXG5cdFx0XHRcdFx0XHRhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nWyBwcm9wIF0gfHwgYW5pbWF0aW9uLm9wdHMuZWFzaW5nICk7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnMucHVzaCggdHdlZW4gKTtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdFx0fSxcblx0XHRcdHN0b3A6IGZ1bmN0aW9uKCBnb3RvRW5kICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwLFxuXG5cdFx0XHRcdFx0Ly8gSWYgd2UgYXJlIGdvaW5nIHRvIHRoZSBlbmQsIHdlIHdhbnQgdG8gcnVuIGFsbCB0aGUgdHdlZW5zXG5cdFx0XHRcdFx0Ly8gb3RoZXJ3aXNlIHdlIHNraXAgdGhpcyBwYXJ0XG5cdFx0XHRcdFx0bGVuZ3RoID0gZ290b0VuZCA/IGFuaW1hdGlvbi50d2VlbnMubGVuZ3RoIDogMDtcblx0XHRcdFx0aWYgKCBzdG9wcGVkICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCAxICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZXNvbHZlIHdoZW4gd2UgcGxheWVkIHRoZSBsYXN0IGZyYW1lOyBvdGhlcndpc2UsIHJlamVjdFxuXHRcdFx0XHRpZiAoIGdvdG9FbmQgKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIDEsIDAgXSApO1xuXHRcdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgZ290b0VuZCBdICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIGdvdG9FbmQgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH0gKSxcblx0XHRwcm9wcyA9IGFuaW1hdGlvbi5wcm9wcztcblxuXHRwcm9wRmlsdGVyKCBwcm9wcywgYW5pbWF0aW9uLm9wdHMuc3BlY2lhbEVhc2luZyApO1xuXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0cmVzdWx0ID0gQW5pbWF0aW9uLnByZWZpbHRlcnNbIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBlbGVtLCBwcm9wcywgYW5pbWF0aW9uLm9wdHMgKTtcblx0XHRpZiAoIHJlc3VsdCApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHJlc3VsdC5zdG9wICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggYW5pbWF0aW9uLmVsZW0sIGFuaW1hdGlvbi5vcHRzLnF1ZXVlICkuc3RvcCA9XG5cdFx0XHRcdFx0alF1ZXJ5LnByb3h5KCByZXN1bHQuc3RvcCwgcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblx0fVxuXG5cdGpRdWVyeS5tYXAoIHByb3BzLCBjcmVhdGVUd2VlbiwgYW5pbWF0aW9uICk7XG5cblx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYW5pbWF0aW9uLm9wdHMuc3RhcnQgKSApIHtcblx0XHRhbmltYXRpb24ub3B0cy5zdGFydC5jYWxsKCBlbGVtLCBhbmltYXRpb24gKTtcblx0fVxuXG5cdC8vIEF0dGFjaCBjYWxsYmFja3MgZnJvbSBvcHRpb25zXG5cdGFuaW1hdGlvblxuXHRcdC5wcm9ncmVzcyggYW5pbWF0aW9uLm9wdHMucHJvZ3Jlc3MgKVxuXHRcdC5kb25lKCBhbmltYXRpb24ub3B0cy5kb25lLCBhbmltYXRpb24ub3B0cy5jb21wbGV0ZSApXG5cdFx0LmZhaWwoIGFuaW1hdGlvbi5vcHRzLmZhaWwgKVxuXHRcdC5hbHdheXMoIGFuaW1hdGlvbi5vcHRzLmFsd2F5cyApO1xuXG5cdGpRdWVyeS5meC50aW1lcihcblx0XHRqUXVlcnkuZXh0ZW5kKCB0aWNrLCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0YW5pbTogYW5pbWF0aW9uLFxuXHRcdFx0cXVldWU6IGFuaW1hdGlvbi5vcHRzLnF1ZXVlXG5cdFx0fSApXG5cdCk7XG5cblx0cmV0dXJuIGFuaW1hdGlvbjtcbn1cblxualF1ZXJ5LkFuaW1hdGlvbiA9IGpRdWVyeS5leHRlbmQoIEFuaW1hdGlvbiwge1xuXG5cdHR3ZWVuZXJzOiB7XG5cdFx0XCIqXCI6IFsgZnVuY3Rpb24oIHByb3AsIHZhbHVlICkge1xuXHRcdFx0dmFyIHR3ZWVuID0gdGhpcy5jcmVhdGVUd2VlbiggcHJvcCwgdmFsdWUgKTtcblx0XHRcdGFkanVzdENTUyggdHdlZW4uZWxlbSwgcHJvcCwgcmNzc051bS5leGVjKCB2YWx1ZSApLCB0d2VlbiApO1xuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH0gXVxuXHR9LFxuXG5cdHR3ZWVuZXI6IGZ1bmN0aW9uKCBwcm9wcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcHJvcHMgKSApIHtcblx0XHRcdGNhbGxiYWNrID0gcHJvcHM7XG5cdFx0XHRwcm9wcyA9IFsgXCIqXCIgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvcHMgPSBwcm9wcy5tYXRjaCggcm5vdGh0bWx3aGl0ZSApO1xuXHRcdH1cblxuXHRcdHZhciBwcm9wLFxuXHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0bGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdHByb3AgPSBwcm9wc1sgaW5kZXggXTtcblx0XHRcdEFuaW1hdGlvbi50d2VlbmVyc1sgcHJvcCBdID0gQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW107XG5cdFx0XHRBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXS51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH1cblx0fSxcblxuXHRwcmVmaWx0ZXJzOiBbIGRlZmF1bHRQcmVmaWx0ZXIgXSxcblxuXHRwcmVmaWx0ZXI6IGZ1bmN0aW9uKCBjYWxsYmFjaywgcHJlcGVuZCApIHtcblx0XHRpZiAoIHByZXBlbmQgKSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy5wdXNoKCBjYWxsYmFjayApO1xuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuc3BlZWQgPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgZm4gKSB7XG5cdHZhciBvcHQgPSBzcGVlZCAmJiB0eXBlb2Ygc3BlZWQgPT09IFwib2JqZWN0XCIgPyBqUXVlcnkuZXh0ZW5kKCB7fSwgc3BlZWQgKSA6IHtcblx0XHRjb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fFxuXHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHNwZWVkICkgJiYgc3BlZWQsXG5cdFx0ZHVyYXRpb246IHNwZWVkLFxuXHRcdGVhc2luZzogZm4gJiYgZWFzaW5nIHx8IGVhc2luZyAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIGVhc2luZyApICYmIGVhc2luZ1xuXHR9O1xuXG5cdC8vIEdvIHRvIHRoZSBlbmQgc3RhdGUgaWYgZnggYXJlIG9mZlxuXHRpZiAoIGpRdWVyeS5meC5vZmYgKSB7XG5cdFx0b3B0LmR1cmF0aW9uID0gMDtcblxuXHR9IGVsc2Uge1xuXHRcdGlmICggdHlwZW9mIG9wdC5kdXJhdGlvbiAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdGlmICggb3B0LmR1cmF0aW9uIGluIGpRdWVyeS5meC5zcGVlZHMgKSB7XG5cdFx0XHRcdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5zcGVlZHNbIG9wdC5kdXJhdGlvbiBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvcHQuZHVyYXRpb24gPSBqUXVlcnkuZnguc3BlZWRzLl9kZWZhdWx0O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBvcHQucXVldWUgLSB0cnVlL3VuZGVmaW5lZC9udWxsIC0+IFwiZnhcIlxuXHRpZiAoIG9wdC5xdWV1ZSA9PSBudWxsIHx8IG9wdC5xdWV1ZSA9PT0gdHJ1ZSApIHtcblx0XHRvcHQucXVldWUgPSBcImZ4XCI7XG5cdH1cblxuXHQvLyBRdWV1ZWluZ1xuXHRvcHQub2xkID0gb3B0LmNvbXBsZXRlO1xuXG5cdG9wdC5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIG9wdC5vbGQgKSApIHtcblx0XHRcdG9wdC5vbGQuY2FsbCggdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0LnF1ZXVlICkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIG9wdC5xdWV1ZSApO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gb3B0O1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmYWRlVG86IGZ1bmN0aW9uKCBzcGVlZCwgdG8sIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cblx0XHQvLyBTaG93IGFueSBoaWRkZW4gZWxlbWVudHMgYWZ0ZXIgc2V0dGluZyBvcGFjaXR5IHRvIDBcblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGlzSGlkZGVuV2l0aGluVHJlZSApLmNzcyggXCJvcGFjaXR5XCIsIDAgKS5zaG93KClcblxuXHRcdFx0Ly8gQW5pbWF0ZSB0byB0aGUgdmFsdWUgc3BlY2lmaWVkXG5cdFx0XHQuZW5kKCkuYW5pbWF0ZSggeyBvcGFjaXR5OiB0byB9LCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9LFxuXHRhbmltYXRlOiBmdW5jdGlvbiggcHJvcCwgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0dmFyIGVtcHR5ID0galF1ZXJ5LmlzRW1wdHlPYmplY3QoIHByb3AgKSxcblx0XHRcdG9wdGFsbCA9IGpRdWVyeS5zcGVlZCggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSxcblx0XHRcdGRvQW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0Ly8gT3BlcmF0ZSBvbiBhIGNvcHkgb2YgcHJvcCBzbyBwZXItcHJvcGVydHkgZWFzaW5nIHdvbid0IGJlIGxvc3Rcblx0XHRcdFx0dmFyIGFuaW0gPSBBbmltYXRpb24oIHRoaXMsIGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wICksIG9wdGFsbCApO1xuXG5cdFx0XHRcdC8vIEVtcHR5IGFuaW1hdGlvbnMsIG9yIGZpbmlzaGluZyByZXNvbHZlcyBpbW1lZGlhdGVseVxuXHRcdFx0XHRpZiAoIGVtcHR5IHx8IGRhdGFQcml2LmdldCggdGhpcywgXCJmaW5pc2hcIiApICkge1xuXHRcdFx0XHRcdGFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0ZG9BbmltYXRpb24uZmluaXNoID0gZG9BbmltYXRpb247XG5cblx0XHRyZXR1cm4gZW1wdHkgfHwgb3B0YWxsLnF1ZXVlID09PSBmYWxzZSA/XG5cdFx0XHR0aGlzLmVhY2goIGRvQW5pbWF0aW9uICkgOlxuXHRcdFx0dGhpcy5xdWV1ZSggb3B0YWxsLnF1ZXVlLCBkb0FuaW1hdGlvbiApO1xuXHR9LFxuXHRzdG9wOiBmdW5jdGlvbiggdHlwZSwgY2xlYXJRdWV1ZSwgZ290b0VuZCApIHtcblx0XHR2YXIgc3RvcFF1ZXVlID0gZnVuY3Rpb24oIGhvb2tzICkge1xuXHRcdFx0dmFyIHN0b3AgPSBob29rcy5zdG9wO1xuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRzdG9wKCBnb3RvRW5kICk7XG5cdFx0fTtcblxuXHRcdGlmICggdHlwZW9mIHR5cGUgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRnb3RvRW5kID0gY2xlYXJRdWV1ZTtcblx0XHRcdGNsZWFyUXVldWUgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKCBjbGVhclF1ZXVlICYmIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dGhpcy5xdWV1ZSggdHlwZSB8fCBcImZ4XCIsIFtdICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgZGVxdWV1ZSA9IHRydWUsXG5cdFx0XHRcdGluZGV4ID0gdHlwZSAhPSBudWxsICYmIHR5cGUgKyBcInF1ZXVlSG9va3NcIixcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApO1xuXG5cdFx0XHRpZiAoIGluZGV4ICkge1xuXHRcdFx0XHRpZiAoIGRhdGFbIGluZGV4IF0gJiYgZGF0YVsgaW5kZXggXS5zdG9wICkge1xuXHRcdFx0XHRcdHN0b3BRdWV1ZSggZGF0YVsgaW5kZXggXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCBpbmRleCBpbiBkYXRhICkge1xuXHRcdFx0XHRcdGlmICggZGF0YVsgaW5kZXggXSAmJiBkYXRhWyBpbmRleCBdLnN0b3AgJiYgcnJ1bi50ZXN0KCBpbmRleCApICkge1xuXHRcdFx0XHRcdFx0c3RvcFF1ZXVlKCBkYXRhWyBpbmRleCBdICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGluZGV4ID0gdGltZXJzLmxlbmd0aDsgaW5kZXgtLTsgKSB7XG5cdFx0XHRcdGlmICggdGltZXJzWyBpbmRleCBdLmVsZW0gPT09IHRoaXMgJiZcblx0XHRcdFx0XHQoIHR5cGUgPT0gbnVsbCB8fCB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSApIHtcblxuXHRcdFx0XHRcdHRpbWVyc1sgaW5kZXggXS5hbmltLnN0b3AoIGdvdG9FbmQgKTtcblx0XHRcdFx0XHRkZXF1ZXVlID0gZmFsc2U7XG5cdFx0XHRcdFx0dGltZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFydCB0aGUgbmV4dCBpbiB0aGUgcXVldWUgaWYgdGhlIGxhc3Qgc3RlcCB3YXNuJ3QgZm9yY2VkLlxuXHRcdFx0Ly8gVGltZXJzIGN1cnJlbnRseSB3aWxsIGNhbGwgdGhlaXIgY29tcGxldGUgY2FsbGJhY2tzLCB3aGljaFxuXHRcdFx0Ly8gd2lsbCBkZXF1ZXVlIGJ1dCBvbmx5IGlmIHRoZXkgd2VyZSBnb3RvRW5kLlxuXHRcdFx0aWYgKCBkZXF1ZXVlIHx8ICFnb3RvRW5kICkge1xuXHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblx0ZmluaXNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRpZiAoIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpbmRleCxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApLFxuXHRcdFx0XHRxdWV1ZSA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlXCIgXSxcblx0XHRcdFx0aG9va3MgPSBkYXRhWyB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgXSxcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0bGVuZ3RoID0gcXVldWUgPyBxdWV1ZS5sZW5ndGggOiAwO1xuXG5cdFx0XHQvLyBFbmFibGUgZmluaXNoaW5nIGZsYWcgb24gcHJpdmF0ZSBkYXRhXG5cdFx0XHRkYXRhLmZpbmlzaCA9IHRydWU7XG5cblx0XHRcdC8vIEVtcHR5IHRoZSBxdWV1ZSBmaXJzdFxuXHRcdFx0alF1ZXJ5LnF1ZXVlKCB0aGlzLCB0eXBlLCBbXSApO1xuXG5cdFx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnN0b3AgKSB7XG5cdFx0XHRcdGhvb2tzLnN0b3AuY2FsbCggdGhpcywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYWN0aXZlIGFuaW1hdGlvbnMsIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJiB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSB7XG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTG9vayBmb3IgYW55IGFuaW1hdGlvbnMgaW4gdGhlIG9sZCBxdWV1ZSBhbmQgZmluaXNoIHRoZW1cblx0XHRcdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGlmICggcXVldWVbIGluZGV4IF0gJiYgcXVldWVbIGluZGV4IF0uZmluaXNoICkge1xuXHRcdFx0XHRcdHF1ZXVlWyBpbmRleCBdLmZpbmlzaC5jYWxsKCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVHVybiBvZmYgZmluaXNoaW5nIGZsYWdcblx0XHRcdGRlbGV0ZSBkYXRhLmZpbmlzaDtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmVhY2goIFsgXCJ0b2dnbGVcIiwgXCJzaG93XCIsIFwiaGlkZVwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgY3NzRm4gPSBqUXVlcnkuZm5bIG5hbWUgXTtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHNwZWVkID09IG51bGwgfHwgdHlwZW9mIHNwZWVkID09PSBcImJvb2xlYW5cIiA/XG5cdFx0XHRjc3NGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOlxuXHRcdFx0dGhpcy5hbmltYXRlKCBnZW5GeCggbmFtZSwgdHJ1ZSApLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG4vLyBHZW5lcmF0ZSBzaG9ydGN1dHMgZm9yIGN1c3RvbSBhbmltYXRpb25zXG5qUXVlcnkuZWFjaCgge1xuXHRzbGlkZURvd246IGdlbkZ4KCBcInNob3dcIiApLFxuXHRzbGlkZVVwOiBnZW5GeCggXCJoaWRlXCIgKSxcblx0c2xpZGVUb2dnbGU6IGdlbkZ4KCBcInRvZ2dsZVwiICksXG5cdGZhZGVJbjogeyBvcGFjaXR5OiBcInNob3dcIiB9LFxuXHRmYWRlT3V0OiB7IG9wYWNpdHk6IFwiaGlkZVwiIH0sXG5cdGZhZGVUb2dnbGU6IHsgb3BhY2l0eTogXCJ0b2dnbGVcIiB9XG59LCBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLmFuaW1hdGUoIHByb3BzLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG5qUXVlcnkudGltZXJzID0gW107XG5qUXVlcnkuZngudGljayA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgdGltZXIsXG5cdFx0aSA9IDAsXG5cdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycztcblxuXHRmeE5vdyA9IGpRdWVyeS5ub3coKTtcblxuXHRmb3IgKCA7IGkgPCB0aW1lcnMubGVuZ3RoOyBpKysgKSB7XG5cdFx0dGltZXIgPSB0aW1lcnNbIGkgXTtcblxuXHRcdC8vIFJ1biB0aGUgdGltZXIgYW5kIHNhZmVseSByZW1vdmUgaXQgd2hlbiBkb25lIChhbGxvd2luZyBmb3IgZXh0ZXJuYWwgcmVtb3ZhbClcblx0XHRpZiAoICF0aW1lcigpICYmIHRpbWVyc1sgaSBdID09PSB0aW1lciApIHtcblx0XHRcdHRpbWVycy5zcGxpY2UoIGktLSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIXRpbWVycy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0b3AoKTtcblx0fVxuXHRmeE5vdyA9IHVuZGVmaW5lZDtcbn07XG5cbmpRdWVyeS5meC50aW1lciA9IGZ1bmN0aW9uKCB0aW1lciApIHtcblx0alF1ZXJ5LnRpbWVycy5wdXNoKCB0aW1lciApO1xuXHRqUXVlcnkuZnguc3RhcnQoKTtcbn07XG5cbmpRdWVyeS5meC5pbnRlcnZhbCA9IDEzO1xualF1ZXJ5LmZ4LnN0YXJ0ID0gZnVuY3Rpb24oKSB7XG5cdGlmICggaW5Qcm9ncmVzcyApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpblByb2dyZXNzID0gdHJ1ZTtcblx0c2NoZWR1bGUoKTtcbn07XG5cbmpRdWVyeS5meC5zdG9wID0gZnVuY3Rpb24oKSB7XG5cdGluUHJvZ3Jlc3MgPSBudWxsO1xufTtcblxualF1ZXJ5LmZ4LnNwZWVkcyA9IHtcblx0c2xvdzogNjAwLFxuXHRmYXN0OiAyMDAsXG5cblx0Ly8gRGVmYXVsdCBzcGVlZFxuXHRfZGVmYXVsdDogNDAwXG59O1xuXG5cbi8vIEJhc2VkIG9mZiBvZiB0aGUgcGx1Z2luIGJ5IENsaW50IEhlbGZlcnMsIHdpdGggcGVybWlzc2lvbi5cbi8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDEwMDMyNDAxNDc0Ny9odHRwOi8vYmxpbmRzaWduYWxzLmNvbS9pbmRleC5waHAvMjAwOS8wNy9qcXVlcnktZGVsYXkvXG5qUXVlcnkuZm4uZGVsYXkgPSBmdW5jdGlvbiggdGltZSwgdHlwZSApIHtcblx0dGltZSA9IGpRdWVyeS5meCA/IGpRdWVyeS5meC5zcGVlZHNbIHRpbWUgXSB8fCB0aW1lIDogdGltZTtcblx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlLCBmdW5jdGlvbiggbmV4dCwgaG9va3MgKSB7XG5cdFx0dmFyIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCggbmV4dCwgdGltZSApO1xuXHRcdGhvb2tzLnN0b3AgPSBmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5jbGVhclRpbWVvdXQoIHRpbWVvdXQgKTtcblx0XHR9O1xuXHR9ICk7XG59O1xuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApLFxuXHRcdHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwic2VsZWN0XCIgKSxcblx0XHRvcHQgPSBzZWxlY3QuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwib3B0aW9uXCIgKSApO1xuXG5cdGlucHV0LnR5cGUgPSBcImNoZWNrYm94XCI7XG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMyBvbmx5XG5cdC8vIERlZmF1bHQgdmFsdWUgZm9yIGEgY2hlY2tib3ggc2hvdWxkIGJlIFwib25cIlxuXHRzdXBwb3J0LmNoZWNrT24gPSBpbnB1dC52YWx1ZSAhPT0gXCJcIjtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTXVzdCBhY2Nlc3Mgc2VsZWN0ZWRJbmRleCB0byBtYWtlIGRlZmF1bHQgb3B0aW9ucyBzZWxlY3Rcblx0c3VwcG9ydC5vcHRTZWxlY3RlZCA9IG9wdC5zZWxlY3RlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gQW4gaW5wdXQgbG9zZXMgaXRzIHZhbHVlIGFmdGVyIGJlY29taW5nIGEgcmFkaW9cblx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblx0aW5wdXQudmFsdWUgPSBcInRcIjtcblx0aW5wdXQudHlwZSA9IFwicmFkaW9cIjtcblx0c3VwcG9ydC5yYWRpb1ZhbHVlID0gaW5wdXQudmFsdWUgPT09IFwidFwiO1xufSApKCk7XG5cblxudmFyIGJvb2xIb29rLFxuXHRhdHRySGFuZGxlID0galF1ZXJ5LmV4cHIuYXR0ckhhbmRsZTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgalF1ZXJ5LmF0dHIsIG5hbWUsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoID4gMSApO1xuXHR9LFxuXG5cdHJlbW92ZUF0dHI6IGZ1bmN0aW9uKCBuYW1lICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIHRoaXMsIG5hbWUgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBEb24ndCBnZXQvc2V0IGF0dHJpYnV0ZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBGYWxsYmFjayB0byBwcm9wIHdoZW4gYXR0cmlidXRlcyBhcmUgbm90IHN1cHBvcnRlZFxuXHRcdGlmICggdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlID09PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5wcm9wKCBlbGVtLCBuYW1lLCB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdC8vIEF0dHJpYnV0ZSBob29rcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgbG93ZXJjYXNlIHZlcnNpb25cblx0XHQvLyBHcmFiIG5lY2Vzc2FyeSBob29rIGlmIG9uZSBpcyBkZWZpbmVkXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5hdHRySG9va3NbIG5hbWUudG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdCggalF1ZXJ5LmV4cHIubWF0Y2guYm9vbC50ZXN0KCBuYW1lICkgPyBib29sSG9vayA6IHVuZGVmaW5lZCApO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGlmICggdmFsdWUgPT09IG51bGwgKSB7XG5cdFx0XHRcdGpRdWVyeS5yZW1vdmVBdHRyKCBlbGVtLCBuYW1lICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBob29rcyAmJiBcInNldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3Muc2V0KCBlbGVtLCB2YWx1ZSwgbmFtZSApICkgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIG5hbWUsIHZhbHVlICsgXCJcIiApO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdC8vIE5vbi1leGlzdGVudCBhdHRyaWJ1dGVzIHJldHVybiBudWxsLCB3ZSBub3JtYWxpemUgdG8gdW5kZWZpbmVkXG5cdFx0cmV0dXJuIHJldCA9PSBudWxsID8gdW5kZWZpbmVkIDogcmV0O1xuXHR9LFxuXG5cdGF0dHJIb29rczoge1xuXHRcdHR5cGU6IHtcblx0XHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0XHRpZiAoICFzdXBwb3J0LnJhZGlvVmFsdWUgJiYgdmFsdWUgPT09IFwicmFkaW9cIiAmJlxuXHRcdFx0XHRcdG5vZGVOYW1lKCBlbGVtLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsID0gZWxlbS52YWx1ZTtcblx0XHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLnZhbHVlID0gdmFsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cmVtb3ZlQXR0cjogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdHZhciBuYW1lLFxuXHRcdFx0aSA9IDAsXG5cblx0XHRcdC8vIEF0dHJpYnV0ZSBuYW1lcyBjYW4gY29udGFpbiBub24tSFRNTCB3aGl0ZXNwYWNlIGNoYXJhY3RlcnNcblx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3N5bnRheC5odG1sI2F0dHJpYnV0ZXMtMlxuXHRcdFx0YXR0ck5hbWVzID0gdmFsdWUgJiYgdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKTtcblxuXHRcdGlmICggYXR0ck5hbWVzICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHR3aGlsZSAoICggbmFtZSA9IGF0dHJOYW1lc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIG5hbWUgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSG9va3MgZm9yIGJvb2xlYW4gYXR0cmlidXRlc1xuYm9vbEhvb2sgPSB7XG5cdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBuYW1lICkge1xuXHRcdGlmICggdmFsdWUgPT09IGZhbHNlICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgYm9vbGVhbiBhdHRyaWJ1dGVzIHdoZW4gc2V0IHRvIGZhbHNlXG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggZWxlbSwgbmFtZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgbmFtZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxufTtcblxualF1ZXJ5LmVhY2goIGpRdWVyeS5leHByLm1hdGNoLmJvb2wuc291cmNlLm1hdGNoKCAvXFx3Ky9nICksIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgZ2V0dGVyID0gYXR0ckhhbmRsZVsgbmFtZSBdIHx8IGpRdWVyeS5maW5kLmF0dHI7XG5cblx0YXR0ckhhbmRsZVsgbmFtZSBdID0gZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciByZXQsIGhhbmRsZSxcblx0XHRcdGxvd2VyY2FzZU5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAoICFpc1hNTCApIHtcblxuXHRcdFx0Ly8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcCBieSB0ZW1wb3JhcmlseSByZW1vdmluZyB0aGlzIGZ1bmN0aW9uIGZyb20gdGhlIGdldHRlclxuXHRcdFx0aGFuZGxlID0gYXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdO1xuXHRcdFx0YXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdID0gcmV0O1xuXHRcdFx0cmV0ID0gZ2V0dGVyKCBlbGVtLCBuYW1lLCBpc1hNTCApICE9IG51bGwgP1xuXHRcdFx0XHRsb3dlcmNhc2VOYW1lIDpcblx0XHRcdFx0bnVsbDtcblx0XHRcdGF0dHJIYW5kbGVbIGxvd2VyY2FzZU5hbWUgXSA9IGhhbmRsZTtcblx0XHR9XG5cdFx0cmV0dXJuIHJldDtcblx0fTtcbn0gKTtcblxuXG5cblxudmFyIHJmb2N1c2FibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFxuXHRyY2xpY2thYmxlID0gL14oPzphfGFyZWEpJC9pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHByb3A6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBqUXVlcnkucHJvcCwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH0sXG5cblx0cmVtb3ZlUHJvcDogZnVuY3Rpb24oIG5hbWUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRkZWxldGUgdGhpc1sgalF1ZXJ5LnByb3BGaXhbIG5hbWUgXSB8fCBuYW1lIF07XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0cHJvcDogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdHZhciByZXQsIGhvb2tzLFxuXHRcdFx0blR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuXG5cdFx0Ly8gRG9uJ3QgZ2V0L3NldCBwcm9wZXJ0aWVzIG9uIHRleHQsIGNvbW1lbnQgYW5kIGF0dHJpYnV0ZSBub2Rlc1xuXHRcdGlmICggblR5cGUgPT09IDMgfHwgblR5cGUgPT09IDggfHwgblR5cGUgPT09IDIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cblx0XHRcdC8vIEZpeCBuYW1lIGFuZCBhdHRhY2ggaG9va3Ncblx0XHRcdG5hbWUgPSBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWU7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5wcm9wSG9va3NbIG5hbWUgXTtcblx0XHR9XG5cblx0XHRpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIGhvb2tzICYmIFwic2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gKCBlbGVtWyBuYW1lIF0gPSB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldHVybiBlbGVtWyBuYW1lIF07XG5cdH0sXG5cblx0cHJvcEhvb2tzOiB7XG5cdFx0dGFiSW5kZXg6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHRcdFx0XHQvLyBlbGVtLnRhYkluZGV4IGRvZXNuJ3QgYWx3YXlzIHJldHVybiB0aGVcblx0XHRcdFx0Ly8gY29ycmVjdCB2YWx1ZSB3aGVuIGl0IGhhc24ndCBiZWVuIGV4cGxpY2l0bHkgc2V0XG5cdFx0XHRcdC8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDE0MTExNjIzMzM0Ny9odHRwOi8vZmx1aWRwcm9qZWN0Lm9yZy9ibG9nLzIwMDgvMDEvMDkvZ2V0dGluZy1zZXR0aW5nLWFuZC1yZW1vdmluZy10YWJpbmRleC12YWx1ZXMtd2l0aC1qYXZhc2NyaXB0L1xuXHRcdFx0XHQvLyBVc2UgcHJvcGVyIGF0dHJpYnV0ZSByZXRyaWV2YWwoIzEyMDcyKVxuXHRcdFx0XHR2YXIgdGFiaW5kZXggPSBqUXVlcnkuZmluZC5hdHRyKCBlbGVtLCBcInRhYmluZGV4XCIgKTtcblxuXHRcdFx0XHRpZiAoIHRhYmluZGV4ICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXJzZUludCggdGFiaW5kZXgsIDEwICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0cmZvY3VzYWJsZS50ZXN0KCBlbGVtLm5vZGVOYW1lICkgfHxcblx0XHRcdFx0XHRyY2xpY2thYmxlLnRlc3QoIGVsZW0ubm9kZU5hbWUgKSAmJlxuXHRcdFx0XHRcdGVsZW0uaHJlZlxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cHJvcEZpeDoge1xuXHRcdFwiZm9yXCI6IFwiaHRtbEZvclwiLFxuXHRcdFwiY2xhc3NcIjogXCJjbGFzc05hbWVcIlxuXHR9XG59ICk7XG5cbi8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuLy8gQWNjZXNzaW5nIHRoZSBzZWxlY3RlZEluZGV4IHByb3BlcnR5XG4vLyBmb3JjZXMgdGhlIGJyb3dzZXIgdG8gcmVzcGVjdCBzZXR0aW5nIHNlbGVjdGVkXG4vLyBvbiB0aGUgb3B0aW9uXG4vLyBUaGUgZ2V0dGVyIGVuc3VyZXMgYSBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZFxuLy8gd2hlbiBpbiBhbiBvcHRncm91cFxuLy8gZXNsaW50IHJ1bGUgXCJuby11bnVzZWQtZXhwcmVzc2lvbnNcIiBpcyBkaXNhYmxlZCBmb3IgdGhpcyBjb2RlXG4vLyBzaW5jZSBpdCBjb25zaWRlcnMgc3VjaCBhY2Nlc3Npb25zIG5vb3BcbmlmICggIXN1cHBvcnQub3B0U2VsZWN0ZWQgKSB7XG5cdGpRdWVyeS5wcm9wSG9va3Muc2VsZWN0ZWQgPSB7XG5cdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0LyogZXNsaW50IG5vLXVudXNlZC1leHByZXNzaW9uczogXCJvZmZcIiAqL1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgJiYgcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9LFxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdC8qIGVzbGludCBuby11bnVzZWQtZXhwcmVzc2lvbnM6IFwib2ZmXCIgKi9cblxuXHRcdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRcdGlmICggcGFyZW50ICkge1xuXHRcdFx0XHRwYXJlbnQuc2VsZWN0ZWRJbmRleDtcblxuXHRcdFx0XHRpZiAoIHBhcmVudC5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbmpRdWVyeS5lYWNoKCBbXG5cdFwidGFiSW5kZXhcIixcblx0XCJyZWFkT25seVwiLFxuXHRcIm1heExlbmd0aFwiLFxuXHRcImNlbGxTcGFjaW5nXCIsXG5cdFwiY2VsbFBhZGRpbmdcIixcblx0XCJyb3dTcGFuXCIsXG5cdFwiY29sU3BhblwiLFxuXHRcInVzZU1hcFwiLFxuXHRcImZyYW1lQm9yZGVyXCIsXG5cdFwiY29udGVudEVkaXRhYmxlXCJcbl0sIGZ1bmN0aW9uKCkge1xuXHRqUXVlcnkucHJvcEZpeFsgdGhpcy50b0xvd2VyQ2FzZSgpIF0gPSB0aGlzO1xufSApO1xuXG5cblxuXG5cdC8vIFN0cmlwIGFuZCBjb2xsYXBzZSB3aGl0ZXNwYWNlIGFjY29yZGluZyB0byBIVE1MIHNwZWNcblx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvaW5mcmFzdHJ1Y3R1cmUuaHRtbCNzdHJpcC1hbmQtY29sbGFwc2Utd2hpdGVzcGFjZVxuXHRmdW5jdGlvbiBzdHJpcEFuZENvbGxhcHNlKCB2YWx1ZSApIHtcblx0XHR2YXIgdG9rZW5zID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblx0XHRyZXR1cm4gdG9rZW5zLmpvaW4oIFwiIFwiICk7XG5cdH1cblxuXG5mdW5jdGlvbiBnZXRDbGFzcyggZWxlbSApIHtcblx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlICYmIGVsZW0uZ2V0QXR0cmlidXRlKCBcImNsYXNzXCIgKSB8fCBcIlwiO1xufVxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGFkZENsYXNzOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGNsYXNzZXMsIGVsZW0sIGN1ciwgY3VyVmFsdWUsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmFkZENsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCBnZXRDbGFzcyggdGhpcyApICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZSApIHtcblx0XHRcdGNsYXNzZXMgPSB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRoaXNbIGkrKyBdICkgKSB7XG5cdFx0XHRcdGN1clZhbHVlID0gZ2V0Q2xhc3MoIGVsZW0gKTtcblx0XHRcdFx0Y3VyID0gZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAoIFwiIFwiICsgc3RyaXBBbmRDb2xsYXBzZSggY3VyVmFsdWUgKSArIFwiIFwiICk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGNsYXp6ID0gY2xhc3Nlc1sgaisrIF0gKSApIHtcblx0XHRcdFx0XHRcdGlmICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApIDwgMCApIHtcblx0XHRcdFx0XHRcdFx0Y3VyICs9IGNsYXp6ICsgXCIgXCI7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVDbGFzczogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBjbGFzc2VzLCBlbGVtLCBjdXIsIGN1clZhbHVlLCBjbGF6eiwgaiwgZmluYWxWYWx1ZSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBqICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZW1vdmVDbGFzcyggdmFsdWUuY2FsbCggdGhpcywgaiwgZ2V0Q2xhc3MoIHRoaXMgKSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiB0aGlzLmF0dHIoIFwiY2xhc3NcIiwgXCJcIiApO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlICkge1xuXHRcdFx0Y2xhc3NlcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdHdoaWxlICggKCBlbGVtID0gdGhpc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0Y3VyVmFsdWUgPSBnZXRDbGFzcyggZWxlbSApO1xuXG5cdFx0XHRcdC8vIFRoaXMgZXhwcmVzc2lvbiBpcyBoZXJlIGZvciBiZXR0ZXIgY29tcHJlc3NpYmlsaXR5IChzZWUgYWRkQ2xhc3MpXG5cdFx0XHRcdGN1ciA9IGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgKCBcIiBcIiArIHN0cmlwQW5kQ29sbGFwc2UoIGN1clZhbHVlICkgKyBcIiBcIiApO1xuXG5cdFx0XHRcdGlmICggY3VyICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKCBjbGF6eiA9IGNsYXNzZXNbIGorKyBdICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIFJlbW92ZSAqYWxsKiBpbnN0YW5jZXNcblx0XHRcdFx0XHRcdHdoaWxlICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApID4gLTEgKSB7XG5cdFx0XHRcdFx0XHRcdGN1ciA9IGN1ci5yZXBsYWNlKCBcIiBcIiArIGNsYXp6ICsgXCIgXCIsIFwiIFwiICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR0b2dnbGVDbGFzczogZnVuY3Rpb24oIHZhbHVlLCBzdGF0ZVZhbCApIHtcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdGlmICggdHlwZW9mIHN0YXRlVmFsID09PSBcImJvb2xlYW5cIiAmJiB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlVmFsID8gdGhpcy5hZGRDbGFzcyggdmFsdWUgKSA6IHRoaXMucmVtb3ZlQ2xhc3MoIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS50b2dnbGVDbGFzcyhcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCB0aGlzLCBpLCBnZXRDbGFzcyggdGhpcyApLCBzdGF0ZVZhbCApLFxuXHRcdFx0XHRcdHN0YXRlVmFsXG5cdFx0XHRcdCk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2xhc3NOYW1lLCBpLCBzZWxmLCBjbGFzc05hbWVzO1xuXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0Ly8gVG9nZ2xlIGluZGl2aWR1YWwgY2xhc3MgbmFtZXNcblx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdHNlbGYgPSBqUXVlcnkoIHRoaXMgKTtcblx0XHRcdFx0Y2xhc3NOYW1lcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdFx0d2hpbGUgKCAoIGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbIGkrKyBdICkgKSB7XG5cblx0XHRcdFx0XHQvLyBDaGVjayBlYWNoIGNsYXNzTmFtZSBnaXZlbiwgc3BhY2Ugc2VwYXJhdGVkIGxpc3Rcblx0XHRcdFx0XHRpZiAoIHNlbGYuaGFzQ2xhc3MoIGNsYXNzTmFtZSApICkge1xuXHRcdFx0XHRcdFx0c2VsZi5yZW1vdmVDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuYWRkQ2xhc3MoIGNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb2dnbGUgd2hvbGUgY2xhc3MgbmFtZVxuXHRcdFx0fSBlbHNlIGlmICggdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdFx0Y2xhc3NOYW1lID0gZ2V0Q2xhc3MoIHRoaXMgKTtcblx0XHRcdFx0aWYgKCBjbGFzc05hbWUgKSB7XG5cblx0XHRcdFx0XHQvLyBTdG9yZSBjbGFzc05hbWUgaWYgc2V0XG5cdFx0XHRcdFx0ZGF0YVByaXYuc2V0KCB0aGlzLCBcIl9fY2xhc3NOYW1lX19cIiwgY2xhc3NOYW1lICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBJZiB0aGUgZWxlbWVudCBoYXMgYSBjbGFzcyBuYW1lIG9yIGlmIHdlJ3JlIHBhc3NlZCBgZmFsc2VgLFxuXHRcdFx0XHQvLyB0aGVuIHJlbW92ZSB0aGUgd2hvbGUgY2xhc3NuYW1lIChpZiB0aGVyZSB3YXMgb25lLCB0aGUgYWJvdmUgc2F2ZWQgaXQpLlxuXHRcdFx0XHQvLyBPdGhlcndpc2UgYnJpbmcgYmFjayB3aGF0ZXZlciB3YXMgcHJldmlvdXNseSBzYXZlZCAoaWYgYW55dGhpbmcpLFxuXHRcdFx0XHQvLyBmYWxsaW5nIGJhY2sgdG8gdGhlIGVtcHR5IHN0cmluZyBpZiBub3RoaW5nIHdhcyBzdG9yZWQuXG5cdFx0XHRcdGlmICggdGhpcy5zZXRBdHRyaWJ1dGUgKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIixcblx0XHRcdFx0XHRcdGNsYXNzTmFtZSB8fCB2YWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0XHRcdFx0XCJcIiA6XG5cdFx0XHRcdFx0XHRkYXRhUHJpdi5nZXQoIHRoaXMsIFwiX19jbGFzc05hbWVfX1wiICkgfHwgXCJcIlxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0aGFzQ2xhc3M6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgY2xhc3NOYW1lLCBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRjbGFzc05hbWUgPSBcIiBcIiArIHNlbGVjdG9yICsgXCIgXCI7XG5cdFx0d2hpbGUgKCAoIGVsZW0gPSB0aGlzWyBpKysgXSApICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdCggXCIgXCIgKyBzdHJpcEFuZENvbGxhcHNlKCBnZXRDbGFzcyggZWxlbSApICkgKyBcIiBcIiApLmluZGV4T2YoIGNsYXNzTmFtZSApID4gLTEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBycmV0dXJuID0gL1xcci9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHZhbDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBob29rcywgcmV0LCBpc0Z1bmN0aW9uLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRcdGhvb2tzID0galF1ZXJ5LnZhbEhvb2tzWyBlbGVtLnR5cGUgXSB8fFxuXHRcdFx0XHRcdGpRdWVyeS52YWxIb29rc1sgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdFx0aWYgKCBob29rcyAmJlxuXHRcdFx0XHRcdFwiZ2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0XHQoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgXCJ2YWx1ZVwiICkgKSAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXQgPSBlbGVtLnZhbHVlO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSBtb3N0IGNvbW1vbiBzdHJpbmcgY2FzZXNcblx0XHRcdFx0aWYgKCB0eXBlb2YgcmV0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHRcdHJldHVybiByZXQucmVwbGFjZSggcnJldHVybiwgXCJcIiApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gSGFuZGxlIGNhc2VzIHdoZXJlIHZhbHVlIGlzIG51bGwvdW5kZWYgb3IgbnVtYmVyXG5cdFx0XHRcdHJldHVybiByZXQgPT0gbnVsbCA/IFwiXCIgOiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdHZhciB2YWw7XG5cblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGlzRnVuY3Rpb24gKSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlLmNhbGwoIHRoaXMsIGksIGpRdWVyeSggdGhpcyApLnZhbCgpICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVHJlYXQgbnVsbC91bmRlZmluZWQgYXMgXCJcIjsgY29udmVydCBudW1iZXJzIHRvIHN0cmluZ1xuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0dmFsID0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggdHlwZW9mIHZhbCA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsICs9IFwiXCI7XG5cblx0XHRcdH0gZWxzZSBpZiAoIEFycmF5LmlzQXJyYXkoIHZhbCApICkge1xuXHRcdFx0XHR2YWwgPSBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSArIFwiXCI7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0aG9va3MgPSBqUXVlcnkudmFsSG9va3NbIHRoaXMudHlwZSBdIHx8IGpRdWVyeS52YWxIb29rc1sgdGhpcy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdC8vIElmIHNldCByZXR1cm5zIHVuZGVmaW5lZCwgZmFsbCBiYWNrIHRvIG5vcm1hbCBzZXR0aW5nXG5cdFx0XHRpZiAoICFob29rcyB8fCAhKCBcInNldFwiIGluIGhvb2tzICkgfHwgaG9va3Muc2V0KCB0aGlzLCB2YWwsIFwidmFsdWVcIiApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMudmFsdWUgPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0dmFsSG9va3M6IHtcblx0XHRvcHRpb246IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0dmFyIHZhbCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIFwidmFsdWVcIiApO1xuXHRcdFx0XHRyZXR1cm4gdmFsICE9IG51bGwgP1xuXHRcdFx0XHRcdHZhbCA6XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTEwIC0gMTEgb25seVxuXHRcdFx0XHRcdC8vIG9wdGlvbi50ZXh0IHRocm93cyBleGNlcHRpb25zICgjMTQ2ODYsICMxNDg1OClcblx0XHRcdFx0XHQvLyBTdHJpcCBhbmQgY29sbGFwc2Ugd2hpdGVzcGFjZVxuXHRcdFx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvI3N0cmlwLWFuZC1jb2xsYXBzZS13aGl0ZXNwYWNlXG5cdFx0XHRcdFx0c3RyaXBBbmRDb2xsYXBzZSggalF1ZXJ5LnRleHQoIGVsZW0gKSApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c2VsZWN0OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgdmFsdWUsIG9wdGlvbiwgaSxcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdGluZGV4ID0gZWxlbS5zZWxlY3RlZEluZGV4LFxuXHRcdFx0XHRcdG9uZSA9IGVsZW0udHlwZSA9PT0gXCJzZWxlY3Qtb25lXCIsXG5cdFx0XHRcdFx0dmFsdWVzID0gb25lID8gbnVsbCA6IFtdLFxuXHRcdFx0XHRcdG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdGlmICggaW5kZXggPCAwICkge1xuXHRcdFx0XHRcdGkgPSBtYXg7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpID0gb25lID8gaW5kZXggOiAwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTG9vcCB0aHJvdWdoIGFsbCB0aGUgc2VsZWN0ZWQgb3B0aW9uc1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBtYXg7IGkrKyApIHtcblx0XHRcdFx0XHRvcHRpb24gPSBvcHRpb25zWyBpIF07XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuXHRcdFx0XHRcdC8vIElFOC05IGRvZXNuJ3QgdXBkYXRlIHNlbGVjdGVkIGFmdGVyIGZvcm0gcmVzZXQgKCMyNTUxKVxuXHRcdFx0XHRcdGlmICggKCBvcHRpb24uc2VsZWN0ZWQgfHwgaSA9PT0gaW5kZXggKSAmJlxuXG5cdFx0XHRcdFx0XHRcdC8vIERvbid0IHJldHVybiBvcHRpb25zIHRoYXQgYXJlIGRpc2FibGVkIG9yIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdFx0XHRcdFx0IW9wdGlvbi5kaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0XHQoICFvcHRpb24ucGFyZW50Tm9kZS5kaXNhYmxlZCB8fFxuXHRcdFx0XHRcdFx0XHRcdCFub2RlTmFtZSggb3B0aW9uLnBhcmVudE5vZGUsIFwib3B0Z3JvdXBcIiApICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEdldCB0aGUgc3BlY2lmaWMgdmFsdWUgZm9yIHRoZSBvcHRpb25cblx0XHRcdFx0XHRcdHZhbHVlID0galF1ZXJ5KCBvcHRpb24gKS52YWwoKTtcblxuXHRcdFx0XHRcdFx0Ly8gV2UgZG9uJ3QgbmVlZCBhbiBhcnJheSBmb3Igb25lIHNlbGVjdHNcblx0XHRcdFx0XHRcdGlmICggb25lICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIE11bHRpLVNlbGVjdHMgcmV0dXJuIGFuIGFycmF5XG5cdFx0XHRcdFx0XHR2YWx1ZXMucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fSxcblxuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBvcHRpb25TZXQsIG9wdGlvbixcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdHZhbHVlcyA9IGpRdWVyeS5tYWtlQXJyYXkoIHZhbHVlICksXG5cdFx0XHRcdFx0aSA9IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG5cblx0XHRcdFx0XHRpZiAoIG9wdGlvbi5zZWxlY3RlZCA9XG5cdFx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggalF1ZXJ5LnZhbEhvb2tzLm9wdGlvbi5nZXQoIG9wdGlvbiApLCB2YWx1ZXMgKSA+IC0xXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRvcHRpb25TZXQgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tY29uZC1hc3NpZ24gKi9cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcmNlIGJyb3dzZXJzIHRvIGJlaGF2ZSBjb25zaXN0ZW50bHkgd2hlbiBub24tbWF0Y2hpbmcgdmFsdWUgaXMgc2V0XG5cdFx0XHRcdGlmICggIW9wdGlvblNldCApIHtcblx0XHRcdFx0XHRlbGVtLnNlbGVjdGVkSW5kZXggPSAtMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG4vLyBSYWRpb3MgYW5kIGNoZWNrYm94ZXMgZ2V0dGVyL3NldHRlclxualF1ZXJ5LmVhY2goIFsgXCJyYWRpb1wiLCBcImNoZWNrYm94XCIgXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdID0ge1xuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWx1ZSApICkge1xuXHRcdFx0XHRyZXR1cm4gKCBlbGVtLmNoZWNrZWQgPSBqUXVlcnkuaW5BcnJheSggalF1ZXJ5KCBlbGVtICkudmFsKCksIHZhbHVlICkgPiAtMSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0aWYgKCAhc3VwcG9ydC5jaGVja09uICkge1xuXHRcdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdLmdldCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gbnVsbCA/IFwib25cIiA6IGVsZW0udmFsdWU7XG5cdFx0fTtcblx0fVxufSApO1xuXG5cblxuXG4vLyBSZXR1cm4galF1ZXJ5IGZvciBhdHRyaWJ1dGVzLW9ubHkgaW5jbHVzaW9uXG5cblxudmFyIHJmb2N1c01vcnBoID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvO1xuXG5qUXVlcnkuZXh0ZW5kKCBqUXVlcnkuZXZlbnQsIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggZXZlbnQsIGRhdGEsIGVsZW0sIG9ubHlIYW5kbGVycyApIHtcblxuXHRcdHZhciBpLCBjdXIsIHRtcCwgYnViYmxlVHlwZSwgb250eXBlLCBoYW5kbGUsIHNwZWNpYWwsXG5cdFx0XHRldmVudFBhdGggPSBbIGVsZW0gfHwgZG9jdW1lbnQgXSxcblx0XHRcdHR5cGUgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwidHlwZVwiICkgPyBldmVudC50eXBlIDogZXZlbnQsXG5cdFx0XHRuYW1lc3BhY2VzID0gaGFzT3duLmNhbGwoIGV2ZW50LCBcIm5hbWVzcGFjZVwiICkgPyBldmVudC5uYW1lc3BhY2Uuc3BsaXQoIFwiLlwiICkgOiBbXTtcblxuXHRcdGN1ciA9IHRtcCA9IGVsZW0gPSBlbGVtIHx8IGRvY3VtZW50O1xuXG5cdFx0Ly8gRG9uJ3QgZG8gZXZlbnRzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBmb2N1cy9ibHVyIG1vcnBocyB0byBmb2N1c2luL291dDsgZW5zdXJlIHdlJ3JlIG5vdCBmaXJpbmcgdGhlbSByaWdodCBub3dcblx0XHRpZiAoIHJmb2N1c01vcnBoLnRlc3QoIHR5cGUgKyBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlLmluZGV4T2YoIFwiLlwiICkgPiAtMSApIHtcblxuXHRcdFx0Ly8gTmFtZXNwYWNlZCB0cmlnZ2VyOyBjcmVhdGUgYSByZWdleHAgdG8gbWF0Y2ggZXZlbnQgdHlwZSBpbiBoYW5kbGUoKVxuXHRcdFx0bmFtZXNwYWNlcyA9IHR5cGUuc3BsaXQoIFwiLlwiICk7XG5cdFx0XHR0eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpO1xuXHRcdFx0bmFtZXNwYWNlcy5zb3J0KCk7XG5cdFx0fVxuXHRcdG9udHlwZSA9IHR5cGUuaW5kZXhPZiggXCI6XCIgKSA8IDAgJiYgXCJvblwiICsgdHlwZTtcblxuXHRcdC8vIENhbGxlciBjYW4gcGFzcyBpbiBhIGpRdWVyeS5FdmVudCBvYmplY3QsIE9iamVjdCwgb3IganVzdCBhbiBldmVudCB0eXBlIHN0cmluZ1xuXHRcdGV2ZW50ID0gZXZlbnRbIGpRdWVyeS5leHBhbmRvIF0gP1xuXHRcdFx0ZXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggdHlwZSwgdHlwZW9mIGV2ZW50ID09PSBcIm9iamVjdFwiICYmIGV2ZW50ICk7XG5cblx0XHQvLyBUcmlnZ2VyIGJpdG1hc2s6ICYgMSBmb3IgbmF0aXZlIGhhbmRsZXJzOyAmIDIgZm9yIGpRdWVyeSAoYWx3YXlzIHRydWUpXG5cdFx0ZXZlbnQuaXNUcmlnZ2VyID0gb25seUhhbmRsZXJzID8gMiA6IDM7XG5cdFx0ZXZlbnQubmFtZXNwYWNlID0gbmFtZXNwYWNlcy5qb2luKCBcIi5cIiApO1xuXHRcdGV2ZW50LnJuYW1lc3BhY2UgPSBldmVudC5uYW1lc3BhY2UgP1xuXHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICkgOlxuXHRcdFx0bnVsbDtcblxuXHRcdC8vIENsZWFuIHVwIHRoZSBldmVudCBpbiBjYXNlIGl0IGlzIGJlaW5nIHJldXNlZFxuXHRcdGV2ZW50LnJlc3VsdCA9IHVuZGVmaW5lZDtcblx0XHRpZiAoICFldmVudC50YXJnZXQgKSB7XG5cdFx0XHRldmVudC50YXJnZXQgPSBlbGVtO1xuXHRcdH1cblxuXHRcdC8vIENsb25lIGFueSBpbmNvbWluZyBkYXRhIGFuZCBwcmVwZW5kIHRoZSBldmVudCwgY3JlYXRpbmcgdGhlIGhhbmRsZXIgYXJnIGxpc3Rcblx0XHRkYXRhID0gZGF0YSA9PSBudWxsID9cblx0XHRcdFsgZXZlbnQgXSA6XG5cdFx0XHRqUXVlcnkubWFrZUFycmF5KCBkYXRhLCBbIGV2ZW50IF0gKTtcblxuXHRcdC8vIEFsbG93IHNwZWNpYWwgZXZlbnRzIHRvIGRyYXcgb3V0c2lkZSB0aGUgbGluZXNcblx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgc3BlY2lhbC50cmlnZ2VyICYmIHNwZWNpYWwudHJpZ2dlci5hcHBseSggZWxlbSwgZGF0YSApID09PSBmYWxzZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgZXZlbnQgcHJvcGFnYXRpb24gcGF0aCBpbiBhZHZhbmNlLCBwZXIgVzNDIGV2ZW50cyBzcGVjICgjOTk1MSlcblx0XHQvLyBCdWJibGUgdXAgdG8gZG9jdW1lbnQsIHRoZW4gdG8gd2luZG93OyB3YXRjaCBmb3IgYSBnbG9iYWwgb3duZXJEb2N1bWVudCB2YXIgKCM5NzI0KVxuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhc3BlY2lhbC5ub0J1YmJsZSAmJiAhalF1ZXJ5LmlzV2luZG93KCBlbGVtICkgKSB7XG5cblx0XHRcdGJ1YmJsZVR5cGUgPSBzcGVjaWFsLmRlbGVnYXRlVHlwZSB8fCB0eXBlO1xuXHRcdFx0aWYgKCAhcmZvY3VzTW9ycGgudGVzdCggYnViYmxlVHlwZSArIHR5cGUgKSApIHtcblx0XHRcdFx0Y3VyID0gY3VyLnBhcmVudE5vZGU7XG5cdFx0XHR9XG5cdFx0XHRmb3IgKCA7IGN1cjsgY3VyID0gY3VyLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdGV2ZW50UGF0aC5wdXNoKCBjdXIgKTtcblx0XHRcdFx0dG1wID0gY3VyO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPbmx5IGFkZCB3aW5kb3cgaWYgd2UgZ290IHRvIGRvY3VtZW50IChlLmcuLCBub3QgcGxhaW4gb2JqIG9yIGRldGFjaGVkIERPTSlcblx0XHRcdGlmICggdG1wID09PSAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudCApICkge1xuXHRcdFx0XHRldmVudFBhdGgucHVzaCggdG1wLmRlZmF1bHRWaWV3IHx8IHRtcC5wYXJlbnRXaW5kb3cgfHwgd2luZG93ICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZSBoYW5kbGVycyBvbiB0aGUgZXZlbnQgcGF0aFxuXHRcdGkgPSAwO1xuXHRcdHdoaWxlICggKCBjdXIgPSBldmVudFBhdGhbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdGV2ZW50LnR5cGUgPSBpID4gMSA/XG5cdFx0XHRcdGJ1YmJsZVR5cGUgOlxuXHRcdFx0XHRzcGVjaWFsLmJpbmRUeXBlIHx8IHR5cGU7XG5cblx0XHRcdC8vIGpRdWVyeSBoYW5kbGVyXG5cdFx0XHRoYW5kbGUgPSAoIGRhdGFQcml2LmdldCggY3VyLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdICYmXG5cdFx0XHRcdGRhdGFQcml2LmdldCggY3VyLCBcImhhbmRsZVwiICk7XG5cdFx0XHRpZiAoIGhhbmRsZSApIHtcblx0XHRcdFx0aGFuZGxlLmFwcGx5KCBjdXIsIGRhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTmF0aXZlIGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9IG9udHlwZSAmJiBjdXJbIG9udHlwZSBdO1xuXHRcdFx0aWYgKCBoYW5kbGUgJiYgaGFuZGxlLmFwcGx5ICYmIGFjY2VwdERhdGEoIGN1ciApICkge1xuXHRcdFx0XHRldmVudC5yZXN1bHQgPSBoYW5kbGUuYXBwbHkoIGN1ciwgZGF0YSApO1xuXHRcdFx0XHRpZiAoIGV2ZW50LnJlc3VsdCA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRldmVudC50eXBlID0gdHlwZTtcblxuXHRcdC8vIElmIG5vYm9keSBwcmV2ZW50ZWQgdGhlIGRlZmF1bHQgYWN0aW9uLCBkbyBpdCBub3dcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgIWV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpICkge1xuXG5cdFx0XHRpZiAoICggIXNwZWNpYWwuX2RlZmF1bHQgfHxcblx0XHRcdFx0c3BlY2lhbC5fZGVmYXVsdC5hcHBseSggZXZlbnRQYXRoLnBvcCgpLCBkYXRhICkgPT09IGZhbHNlICkgJiZcblx0XHRcdFx0YWNjZXB0RGF0YSggZWxlbSApICkge1xuXG5cdFx0XHRcdC8vIENhbGwgYSBuYXRpdmUgRE9NIG1ldGhvZCBvbiB0aGUgdGFyZ2V0IHdpdGggdGhlIHNhbWUgbmFtZSBhcyB0aGUgZXZlbnQuXG5cdFx0XHRcdC8vIERvbid0IGRvIGRlZmF1bHQgYWN0aW9ucyBvbiB3aW5kb3csIHRoYXQncyB3aGVyZSBnbG9iYWwgdmFyaWFibGVzIGJlICgjNjE3MClcblx0XHRcdFx0aWYgKCBvbnR5cGUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIGVsZW1bIHR5cGUgXSApICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vIERvbid0IHJlLXRyaWdnZXIgYW4gb25GT08gZXZlbnQgd2hlbiB3ZSBjYWxsIGl0cyBGT08oKSBtZXRob2Rcblx0XHRcdFx0XHR0bXAgPSBlbGVtWyBvbnR5cGUgXTtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSBudWxsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZXZlbnQgcmUtdHJpZ2dlcmluZyBvZiB0aGUgc2FtZSBldmVudCwgc2luY2Ugd2UgYWxyZWFkeSBidWJibGVkIGl0IGFib3ZlXG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHR5cGU7XG5cdFx0XHRcdFx0ZWxlbVsgdHlwZSBdKCk7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSB0bXA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHQvLyBQaWdneWJhY2sgb24gYSBkb25vciBldmVudCB0byBzaW11bGF0ZSBhIGRpZmZlcmVudCBvbmVcblx0Ly8gVXNlZCBvbmx5IGZvciBgZm9jdXMoaW4gfCBvdXQpYCBldmVudHNcblx0c2ltdWxhdGU6IGZ1bmN0aW9uKCB0eXBlLCBlbGVtLCBldmVudCApIHtcblx0XHR2YXIgZSA9IGpRdWVyeS5leHRlbmQoXG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCksXG5cdFx0XHRldmVudCxcblx0XHRcdHtcblx0XHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdFx0aXNTaW11bGF0ZWQ6IHRydWVcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIGUsIG51bGwsIGVsZW0gKTtcblx0fVxuXG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7XG5cdFx0fSApO1xuXHR9LFxuXHR0cmlnZ2VySGFuZGxlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIGVsZW0gPSB0aGlzWyAwIF07XG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCBlbGVtLCB0cnVlICk7XG5cdFx0fVxuXHR9XG59ICk7XG5cblxualF1ZXJ5LmVhY2goICggXCJibHVyIGZvY3VzIGZvY3VzaW4gZm9jdXNvdXQgcmVzaXplIHNjcm9sbCBjbGljayBkYmxjbGljayBcIiArXG5cdFwibW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgXCIgK1xuXHRcImNoYW5nZSBzZWxlY3Qgc3VibWl0IGtleWRvd24ga2V5cHJlc3Mga2V5dXAgY29udGV4dG1lbnVcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRmdW5jdGlvbiggaSwgbmFtZSApIHtcblxuXHQvLyBIYW5kbGUgZXZlbnQgYmluZGluZ1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDAgP1xuXHRcdFx0dGhpcy5vbiggbmFtZSwgbnVsbCwgZGF0YSwgZm4gKSA6XG5cdFx0XHR0aGlzLnRyaWdnZXIoIG5hbWUgKTtcblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRob3ZlcjogZnVuY3Rpb24oIGZuT3ZlciwgZm5PdXQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubW91c2VlbnRlciggZm5PdmVyICkubW91c2VsZWF2ZSggZm5PdXQgfHwgZm5PdmVyICk7XG5cdH1cbn0gKTtcblxuXG5cblxuc3VwcG9ydC5mb2N1c2luID0gXCJvbmZvY3VzaW5cIiBpbiB3aW5kb3c7XG5cblxuLy8gU3VwcG9ydDogRmlyZWZveCA8PTQ0XG4vLyBGaXJlZm94IGRvZXNuJ3QgaGF2ZSBmb2N1cyhpbiB8IG91dCkgZXZlbnRzXG4vLyBSZWxhdGVkIHRpY2tldCAtIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY4Nzc4N1xuLy9cbi8vIFN1cHBvcnQ6IENocm9tZSA8PTQ4IC0gNDksIFNhZmFyaSA8PTkuMCAtIDkuMVxuLy8gZm9jdXMoaW4gfCBvdXQpIGV2ZW50cyBmaXJlIGFmdGVyIGZvY3VzICYgYmx1ciBldmVudHMsXG4vLyB3aGljaCBpcyBzcGVjIHZpb2xhdGlvbiAtIGh0dHA6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnRzLWZvY3VzZXZlbnQtZXZlbnQtb3JkZXJcbi8vIFJlbGF0ZWQgdGlja2V0IC0gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQ5ODU3XG5pZiAoICFzdXBwb3J0LmZvY3VzaW4gKSB7XG5cdGpRdWVyeS5lYWNoKCB7IGZvY3VzOiBcImZvY3VzaW5cIiwgYmx1cjogXCJmb2N1c291dFwiIH0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cblx0XHQvLyBBdHRhY2ggYSBzaW5nbGUgY2FwdHVyaW5nIGhhbmRsZXIgb24gdGhlIGRvY3VtZW50IHdoaWxlIHNvbWVvbmUgd2FudHMgZm9jdXNpbi9mb2N1c291dFxuXHRcdHZhciBoYW5kbGVyID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnNpbXVsYXRlKCBmaXgsIGV2ZW50LnRhcmdldCwgalF1ZXJ5LmV2ZW50LmZpeCggZXZlbnQgKSApO1xuXHRcdH07XG5cblx0XHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZml4IF0gPSB7XG5cdFx0XHRzZXR1cDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBkb2MgPSB0aGlzLm93bmVyRG9jdW1lbnQgfHwgdGhpcyxcblx0XHRcdFx0XHRhdHRhY2hlcyA9IGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXggKTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MuYWRkRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsICggYXR0YWNoZXMgfHwgMCApICsgMSApO1xuXHRcdFx0fSxcblx0XHRcdHRlYXJkb3duOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCApIC0gMTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZG9jLCBmaXggKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsIGF0dGFjaGVzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9ICk7XG59XG52YXIgbG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb247XG5cbnZhciBub25jZSA9IGpRdWVyeS5ub3coKTtcblxudmFyIHJxdWVyeSA9ICggL1xcPy8gKTtcblxuXG5cbi8vIENyb3NzLWJyb3dzZXIgeG1sIHBhcnNpbmdcbmpRdWVyeS5wYXJzZVhNTCA9IGZ1bmN0aW9uKCBkYXRhICkge1xuXHR2YXIgeG1sO1xuXHRpZiAoICFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHlcblx0Ly8gSUUgdGhyb3dzIG9uIHBhcnNlRnJvbVN0cmluZyB3aXRoIGludmFsaWQgaW5wdXQuXG5cdHRyeSB7XG5cdFx0eG1sID0gKCBuZXcgd2luZG93LkRPTVBhcnNlcigpICkucGFyc2VGcm9tU3RyaW5nKCBkYXRhLCBcInRleHQveG1sXCIgKTtcblx0fSBjYXRjaCAoIGUgKSB7XG5cdFx0eG1sID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0aWYgKCAheG1sIHx8IHhtbC5nZXRFbGVtZW50c0J5VGFnTmFtZSggXCJwYXJzZXJlcnJvclwiICkubGVuZ3RoICkge1xuXHRcdGpRdWVyeS5lcnJvciggXCJJbnZhbGlkIFhNTDogXCIgKyBkYXRhICk7XG5cdH1cblx0cmV0dXJuIHhtbDtcbn07XG5cblxudmFyXG5cdHJicmFja2V0ID0gL1xcW1xcXSQvLFxuXHRyQ1JMRiA9IC9cXHI/XFxuL2csXG5cdHJzdWJtaXR0ZXJUeXBlcyA9IC9eKD86c3VibWl0fGJ1dHRvbnxpbWFnZXxyZXNldHxmaWxlKSQvaSxcblx0cnN1Ym1pdHRhYmxlID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pO1xuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyggcHJlZml4LCBvYmosIHRyYWRpdGlvbmFsLCBhZGQgKSB7XG5cdHZhciBuYW1lO1xuXG5cdGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgYXJyYXkgaXRlbS5cblx0XHRqUXVlcnkuZWFjaCggb2JqLCBmdW5jdGlvbiggaSwgdiApIHtcblx0XHRcdGlmICggdHJhZGl0aW9uYWwgfHwgcmJyYWNrZXQudGVzdCggcHJlZml4ICkgKSB7XG5cblx0XHRcdFx0Ly8gVHJlYXQgZWFjaCBhcnJheSBpdGVtIGFzIGEgc2NhbGFyLlxuXHRcdFx0XHRhZGQoIHByZWZpeCwgdiApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIEl0ZW0gaXMgbm9uLXNjYWxhciAoYXJyYXkgb3Igb2JqZWN0KSwgZW5jb2RlIGl0cyBudW1lcmljIGluZGV4LlxuXHRcdFx0XHRidWlsZFBhcmFtcyhcblx0XHRcdFx0XHRwcmVmaXggKyBcIltcIiArICggdHlwZW9mIHYgPT09IFwib2JqZWN0XCIgJiYgdiAhPSBudWxsID8gaSA6IFwiXCIgKSArIFwiXVwiLFxuXHRcdFx0XHRcdHYsXG5cdFx0XHRcdFx0dHJhZGl0aW9uYWwsXG5cdFx0XHRcdFx0YWRkXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdH0gZWxzZSBpZiAoICF0cmFkaXRpb25hbCAmJiBqUXVlcnkudHlwZSggb2JqICkgPT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgb2JqZWN0IGl0ZW0uXG5cdFx0Zm9yICggbmFtZSBpbiBvYmogKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4ICsgXCJbXCIgKyBuYW1lICsgXCJdXCIsIG9ialsgbmFtZSBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXG5cdH0gZWxzZSB7XG5cblx0XHQvLyBTZXJpYWxpemUgc2NhbGFyIGl0ZW0uXG5cdFx0YWRkKCBwcmVmaXgsIG9iaiApO1xuXHR9XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzIG9yIGEgc2V0IG9mXG4vLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmdcbmpRdWVyeS5wYXJhbSA9IGZ1bmN0aW9uKCBhLCB0cmFkaXRpb25hbCApIHtcblx0dmFyIHByZWZpeCxcblx0XHRzID0gW10sXG5cdFx0YWRkID0gZnVuY3Rpb24oIGtleSwgdmFsdWVPckZ1bmN0aW9uICkge1xuXG5cdFx0XHQvLyBJZiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCBpbnZva2UgaXQgYW5kIHVzZSBpdHMgcmV0dXJuIHZhbHVlXG5cdFx0XHR2YXIgdmFsdWUgPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWVPckZ1bmN0aW9uICkgP1xuXHRcdFx0XHR2YWx1ZU9yRnVuY3Rpb24oKSA6XG5cdFx0XHRcdHZhbHVlT3JGdW5jdGlvbjtcblxuXHRcdFx0c1sgcy5sZW5ndGggXSA9IGVuY29kZVVSSUNvbXBvbmVudCgga2V5ICkgKyBcIj1cIiArXG5cdFx0XHRcdGVuY29kZVVSSUNvbXBvbmVudCggdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSApO1xuXHRcdH07XG5cblx0Ly8gSWYgYW4gYXJyYXkgd2FzIHBhc3NlZCBpbiwgYXNzdW1lIHRoYXQgaXQgaXMgYW4gYXJyYXkgb2YgZm9ybSBlbGVtZW50cy5cblx0aWYgKCBBcnJheS5pc0FycmF5KCBhICkgfHwgKCBhLmpxdWVyeSAmJiAhalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGEgKSApICkge1xuXG5cdFx0Ly8gU2VyaWFsaXplIHRoZSBmb3JtIGVsZW1lbnRzXG5cdFx0alF1ZXJ5LmVhY2goIGEsIGZ1bmN0aW9uKCkge1xuXHRcdFx0YWRkKCB0aGlzLm5hbWUsIHRoaXMudmFsdWUgKTtcblx0XHR9ICk7XG5cblx0fSBlbHNlIHtcblxuXHRcdC8vIElmIHRyYWRpdGlvbmFsLCBlbmNvZGUgdGhlIFwib2xkXCIgd2F5ICh0aGUgd2F5IDEuMy4yIG9yIG9sZGVyXG5cdFx0Ly8gZGlkIGl0KSwgb3RoZXJ3aXNlIGVuY29kZSBwYXJhbXMgcmVjdXJzaXZlbHkuXG5cdFx0Zm9yICggcHJlZml4IGluIGEgKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4LCBhWyBwcmVmaXggXSwgdHJhZGl0aW9uYWwsIGFkZCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgcmVzdWx0aW5nIHNlcmlhbGl6YXRpb25cblx0cmV0dXJuIHMuam9pbiggXCImXCIgKTtcbn07XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0c2VyaWFsaXplOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4galF1ZXJ5LnBhcmFtKCB0aGlzLnNlcmlhbGl6ZUFycmF5KCkgKTtcblx0fSxcblx0c2VyaWFsaXplQXJyYXk6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIENhbiBhZGQgcHJvcEhvb2sgZm9yIFwiZWxlbWVudHNcIiB0byBmaWx0ZXIgb3IgYWRkIGZvcm0gZWxlbWVudHNcblx0XHRcdHZhciBlbGVtZW50cyA9IGpRdWVyeS5wcm9wKCB0aGlzLCBcImVsZW1lbnRzXCIgKTtcblx0XHRcdHJldHVybiBlbGVtZW50cyA/IGpRdWVyeS5tYWtlQXJyYXkoIGVsZW1lbnRzICkgOiB0aGlzO1xuXHRcdH0gKVxuXHRcdC5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLnR5cGU7XG5cblx0XHRcdC8vIFVzZSAuaXMoIFwiOmRpc2FibGVkXCIgKSBzbyB0aGF0IGZpZWxkc2V0W2Rpc2FibGVkXSB3b3Jrc1xuXHRcdFx0cmV0dXJuIHRoaXMubmFtZSAmJiAhalF1ZXJ5KCB0aGlzICkuaXMoIFwiOmRpc2FibGVkXCIgKSAmJlxuXHRcdFx0XHRyc3VibWl0dGFibGUudGVzdCggdGhpcy5ub2RlTmFtZSApICYmICFyc3VibWl0dGVyVHlwZXMudGVzdCggdHlwZSApICYmXG5cdFx0XHRcdCggdGhpcy5jaGVja2VkIHx8ICFyY2hlY2thYmxlVHlwZS50ZXN0KCB0eXBlICkgKTtcblx0XHR9IClcblx0XHQubWFwKCBmdW5jdGlvbiggaSwgZWxlbSApIHtcblx0XHRcdHZhciB2YWwgPSBqUXVlcnkoIHRoaXMgKS52YWwoKTtcblxuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsICkgKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHsgbmFtZTogZWxlbS5uYW1lLCB2YWx1ZTogdmFsLnJlcGxhY2UoIHJDUkxGLCBcIlxcclxcblwiICkgfTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4geyBuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWwucmVwbGFjZSggckNSTEYsIFwiXFxyXFxuXCIgKSB9O1xuXHRcdH0gKS5nZXQoKTtcblx0fVxufSApO1xuXG5cbnZhclxuXHRyMjAgPSAvJTIwL2csXG5cdHJoYXNoID0gLyMuKiQvLFxuXHRyYW50aUNhY2hlID0gLyhbPyZdKV89W14mXSovLFxuXHRyaGVhZGVycyA9IC9eKC4qPyk6WyBcXHRdKihbXlxcclxcbl0qKSQvbWcsXG5cblx0Ly8gIzc2NTMsICM4MTI1LCAjODE1MjogbG9jYWwgcHJvdG9jb2wgZGV0ZWN0aW9uXG5cdHJsb2NhbFByb3RvY29sID0gL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8sXG5cdHJub0NvbnRlbnQgPSAvXig/OkdFVHxIRUFEKSQvLFxuXHRycHJvdG9jb2wgPSAvXlxcL1xcLy8sXG5cblx0LyogUHJlZmlsdGVyc1xuXHQgKiAxKSBUaGV5IGFyZSB1c2VmdWwgdG8gaW50cm9kdWNlIGN1c3RvbSBkYXRhVHlwZXMgKHNlZSBhamF4L2pzb25wLmpzIGZvciBhbiBleGFtcGxlKVxuXHQgKiAyKSBUaGVzZSBhcmUgY2FsbGVkOlxuXHQgKiAgICAtIEJFRk9SRSBhc2tpbmcgZm9yIGEgdHJhbnNwb3J0XG5cdCAqICAgIC0gQUZURVIgcGFyYW0gc2VyaWFsaXphdGlvbiAocy5kYXRhIGlzIGEgc3RyaW5nIGlmIHMucHJvY2Vzc0RhdGEgaXMgdHJ1ZSlcblx0ICogMykga2V5IGlzIHRoZSBkYXRhVHlwZVxuXHQgKiA0KSB0aGUgY2F0Y2hhbGwgc3ltYm9sIFwiKlwiIGNhbiBiZSB1c2VkXG5cdCAqIDUpIGV4ZWN1dGlvbiB3aWxsIHN0YXJ0IHdpdGggdHJhbnNwb3J0IGRhdGFUeXBlIGFuZCBUSEVOIGNvbnRpbnVlIGRvd24gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHRwcmVmaWx0ZXJzID0ge30sXG5cblx0LyogVHJhbnNwb3J0cyBiaW5kaW5nc1xuXHQgKiAxKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDIpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogMykgc2VsZWN0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gZ28gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHR0cmFuc3BvcnRzID0ge30sXG5cblx0Ly8gQXZvaWQgY29tbWVudC1wcm9sb2cgY2hhciBzZXF1ZW5jZSAoIzEwMDk4KTsgbXVzdCBhcHBlYXNlIGxpbnQgYW5kIGV2YWRlIGNvbXByZXNzaW9uXG5cdGFsbFR5cGVzID0gXCIqL1wiLmNvbmNhdCggXCIqXCIgKSxcblxuXHQvLyBBbmNob3IgdGFnIGZvciBwYXJzaW5nIHRoZSBkb2N1bWVudCBvcmlnaW5cblx0b3JpZ2luQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblx0b3JpZ2luQW5jaG9yLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXG4vLyBCYXNlIFwiY29uc3RydWN0b3JcIiBmb3IgalF1ZXJ5LmFqYXhQcmVmaWx0ZXIgYW5kIGpRdWVyeS5hamF4VHJhbnNwb3J0XG5mdW5jdGlvbiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHN0cnVjdHVyZSApIHtcblxuXHQvLyBkYXRhVHlwZUV4cHJlc3Npb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIFwiKlwiXG5cdHJldHVybiBmdW5jdGlvbiggZGF0YVR5cGVFeHByZXNzaW9uLCBmdW5jICkge1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVFeHByZXNzaW9uICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZnVuYyA9IGRhdGFUeXBlRXhwcmVzc2lvbjtcblx0XHRcdGRhdGFUeXBlRXhwcmVzc2lvbiA9IFwiKlwiO1xuXHRcdH1cblxuXHRcdHZhciBkYXRhVHlwZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0ZGF0YVR5cGVzID0gZGF0YVR5cGVFeHByZXNzaW9uLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGZ1bmMgKSApIHtcblxuXHRcdFx0Ly8gRm9yIGVhY2ggZGF0YVR5cGUgaW4gdGhlIGRhdGFUeXBlRXhwcmVzc2lvblxuXHRcdFx0d2hpbGUgKCAoIGRhdGFUeXBlID0gZGF0YVR5cGVzWyBpKysgXSApICkge1xuXG5cdFx0XHRcdC8vIFByZXBlbmQgaWYgcmVxdWVzdGVkXG5cdFx0XHRcdGlmICggZGF0YVR5cGVbIDAgXSA9PT0gXCIrXCIgKSB7XG5cdFx0XHRcdFx0ZGF0YVR5cGUgPSBkYXRhVHlwZS5zbGljZSggMSApIHx8IFwiKlwiO1xuXHRcdFx0XHRcdCggc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdICkudW5zaGlmdCggZnVuYyApO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBhcHBlbmRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQoIHN0cnVjdHVyZVsgZGF0YVR5cGUgXSA9IHN0cnVjdHVyZVsgZGF0YVR5cGUgXSB8fCBbXSApLnB1c2goIGZ1bmMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxuLy8gQmFzZSBpbnNwZWN0aW9uIGZ1bmN0aW9uIGZvciBwcmVmaWx0ZXJzIGFuZCB0cmFuc3BvcnRzXG5mdW5jdGlvbiBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlLCBvcHRpb25zLCBvcmlnaW5hbE9wdGlvbnMsIGpxWEhSICkge1xuXG5cdHZhciBpbnNwZWN0ZWQgPSB7fSxcblx0XHRzZWVraW5nVHJhbnNwb3J0ID0gKCBzdHJ1Y3R1cmUgPT09IHRyYW5zcG9ydHMgKTtcblxuXHRmdW5jdGlvbiBpbnNwZWN0KCBkYXRhVHlwZSApIHtcblx0XHR2YXIgc2VsZWN0ZWQ7XG5cdFx0aW5zcGVjdGVkWyBkYXRhVHlwZSBdID0gdHJ1ZTtcblx0XHRqUXVlcnkuZWFjaCggc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdLCBmdW5jdGlvbiggXywgcHJlZmlsdGVyT3JGYWN0b3J5ICkge1xuXHRcdFx0dmFyIGRhdGFUeXBlT3JUcmFuc3BvcnQgPSBwcmVmaWx0ZXJPckZhY3RvcnkoIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKTtcblx0XHRcdGlmICggdHlwZW9mIGRhdGFUeXBlT3JUcmFuc3BvcnQgPT09IFwic3RyaW5nXCIgJiZcblx0XHRcdFx0IXNlZWtpbmdUcmFuc3BvcnQgJiYgIWluc3BlY3RlZFsgZGF0YVR5cGVPclRyYW5zcG9ydCBdICkge1xuXG5cdFx0XHRcdG9wdGlvbnMuZGF0YVR5cGVzLnVuc2hpZnQoIGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdFx0aW5zcGVjdCggZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCBzZWVraW5nVHJhbnNwb3J0ICkge1xuXHRcdFx0XHRyZXR1cm4gISggc2VsZWN0ZWQgPSBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcdHJldHVybiBzZWxlY3RlZDtcblx0fVxuXG5cdHJldHVybiBpbnNwZWN0KCBvcHRpb25zLmRhdGFUeXBlc1sgMCBdICkgfHwgIWluc3BlY3RlZFsgXCIqXCIgXSAmJiBpbnNwZWN0KCBcIipcIiApO1xufVxuXG4vLyBBIHNwZWNpYWwgZXh0ZW5kIGZvciBhamF4IG9wdGlvbnNcbi8vIHRoYXQgdGFrZXMgXCJmbGF0XCIgb3B0aW9ucyAobm90IHRvIGJlIGRlZXAgZXh0ZW5kZWQpXG4vLyBGaXhlcyAjOTg4N1xuZnVuY3Rpb24gYWpheEV4dGVuZCggdGFyZ2V0LCBzcmMgKSB7XG5cdHZhciBrZXksIGRlZXAsXG5cdFx0ZmxhdE9wdGlvbnMgPSBqUXVlcnkuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zIHx8IHt9O1xuXG5cdGZvciAoIGtleSBpbiBzcmMgKSB7XG5cdFx0aWYgKCBzcmNbIGtleSBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHQoIGZsYXRPcHRpb25zWyBrZXkgXSA/IHRhcmdldCA6ICggZGVlcCB8fCAoIGRlZXAgPSB7fSApICkgKVsga2V5IF0gPSBzcmNbIGtleSBdO1xuXHRcdH1cblx0fVxuXHRpZiAoIGRlZXAgKSB7XG5cdFx0alF1ZXJ5LmV4dGVuZCggdHJ1ZSwgdGFyZ2V0LCBkZWVwICk7XG5cdH1cblxuXHRyZXR1cm4gdGFyZ2V0O1xufVxuXG4vKiBIYW5kbGVzIHJlc3BvbnNlcyB0byBhbiBhamF4IHJlcXVlc3Q6XG4gKiAtIGZpbmRzIHRoZSByaWdodCBkYXRhVHlwZSAobWVkaWF0ZXMgYmV0d2VlbiBjb250ZW50LXR5cGUgYW5kIGV4cGVjdGVkIGRhdGFUeXBlKVxuICogLSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG4gKi9cbmZ1bmN0aW9uIGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKSB7XG5cblx0dmFyIGN0LCB0eXBlLCBmaW5hbERhdGFUeXBlLCBmaXJzdERhdGFUeXBlLFxuXHRcdGNvbnRlbnRzID0gcy5jb250ZW50cyxcblx0XHRkYXRhVHlwZXMgPSBzLmRhdGFUeXBlcztcblxuXHQvLyBSZW1vdmUgYXV0byBkYXRhVHlwZSBhbmQgZ2V0IGNvbnRlbnQtdHlwZSBpbiB0aGUgcHJvY2Vzc1xuXHR3aGlsZSAoIGRhdGFUeXBlc1sgMCBdID09PSBcIipcIiApIHtcblx0XHRkYXRhVHlwZXMuc2hpZnQoKTtcblx0XHRpZiAoIGN0ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRjdCA9IHMubWltZVR5cGUgfHwganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiQ29udGVudC1UeXBlXCIgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayBpZiB3ZSdyZSBkZWFsaW5nIHdpdGggYSBrbm93biBjb250ZW50LXR5cGVcblx0aWYgKCBjdCApIHtcblx0XHRmb3IgKCB0eXBlIGluIGNvbnRlbnRzICkge1xuXHRcdFx0aWYgKCBjb250ZW50c1sgdHlwZSBdICYmIGNvbnRlbnRzWyB0eXBlIF0udGVzdCggY3QgKSApIHtcblx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHR5cGUgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSByZXNwb25zZSBmb3IgdGhlIGV4cGVjdGVkIGRhdGFUeXBlXG5cdGlmICggZGF0YVR5cGVzWyAwIF0gaW4gcmVzcG9uc2VzICkge1xuXHRcdGZpbmFsRGF0YVR5cGUgPSBkYXRhVHlwZXNbIDAgXTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIFRyeSBjb252ZXJ0aWJsZSBkYXRhVHlwZXNcblx0XHRmb3IgKCB0eXBlIGluIHJlc3BvbnNlcyApIHtcblx0XHRcdGlmICggIWRhdGFUeXBlc1sgMCBdIHx8IHMuY29udmVydGVyc1sgdHlwZSArIFwiIFwiICsgZGF0YVR5cGVzWyAwIF0gXSApIHtcblx0XHRcdFx0ZmluYWxEYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAhZmlyc3REYXRhVHlwZSApIHtcblx0XHRcdFx0Zmlyc3REYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gT3IganVzdCB1c2UgZmlyc3Qgb25lXG5cdFx0ZmluYWxEYXRhVHlwZSA9IGZpbmFsRGF0YVR5cGUgfHwgZmlyc3REYXRhVHlwZTtcblx0fVxuXG5cdC8vIElmIHdlIGZvdW5kIGEgZGF0YVR5cGVcblx0Ly8gV2UgYWRkIHRoZSBkYXRhVHlwZSB0byB0aGUgbGlzdCBpZiBuZWVkZWRcblx0Ly8gYW5kIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyByZXNwb25zZVxuXHRpZiAoIGZpbmFsRGF0YVR5cGUgKSB7XG5cdFx0aWYgKCBmaW5hbERhdGFUeXBlICE9PSBkYXRhVHlwZXNbIDAgXSApIHtcblx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCBmaW5hbERhdGFUeXBlICk7XG5cdFx0fVxuXHRcdHJldHVybiByZXNwb25zZXNbIGZpbmFsRGF0YVR5cGUgXTtcblx0fVxufVxuXG4vKiBDaGFpbiBjb252ZXJzaW9ucyBnaXZlbiB0aGUgcmVxdWVzdCBhbmQgdGhlIG9yaWdpbmFsIHJlc3BvbnNlXG4gKiBBbHNvIHNldHMgdGhlIHJlc3BvbnNlWFhYIGZpZWxkcyBvbiB0aGUganFYSFIgaW5zdGFuY2VcbiAqL1xuZnVuY3Rpb24gYWpheENvbnZlcnQoIHMsIHJlc3BvbnNlLCBqcVhIUiwgaXNTdWNjZXNzICkge1xuXHR2YXIgY29udjIsIGN1cnJlbnQsIGNvbnYsIHRtcCwgcHJldixcblx0XHRjb252ZXJ0ZXJzID0ge30sXG5cblx0XHQvLyBXb3JrIHdpdGggYSBjb3B5IG9mIGRhdGFUeXBlcyBpbiBjYXNlIHdlIG5lZWQgdG8gbW9kaWZ5IGl0IGZvciBjb252ZXJzaW9uXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXMuc2xpY2UoKTtcblxuXHQvLyBDcmVhdGUgY29udmVydGVycyBtYXAgd2l0aCBsb3dlcmNhc2VkIGtleXNcblx0aWYgKCBkYXRhVHlwZXNbIDEgXSApIHtcblx0XHRmb3IgKCBjb252IGluIHMuY29udmVydGVycyApIHtcblx0XHRcdGNvbnZlcnRlcnNbIGNvbnYudG9Mb3dlckNhc2UoKSBdID0gcy5jb252ZXJ0ZXJzWyBjb252IF07XG5cdFx0fVxuXHR9XG5cblx0Y3VycmVudCA9IGRhdGFUeXBlcy5zaGlmdCgpO1xuXG5cdC8vIENvbnZlcnQgdG8gZWFjaCBzZXF1ZW50aWFsIGRhdGFUeXBlXG5cdHdoaWxlICggY3VycmVudCApIHtcblxuXHRcdGlmICggcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdICkge1xuXHRcdFx0anFYSFJbIHMucmVzcG9uc2VGaWVsZHNbIGN1cnJlbnQgXSBdID0gcmVzcG9uc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgdGhlIGRhdGFGaWx0ZXIgaWYgcHJvdmlkZWRcblx0XHRpZiAoICFwcmV2ICYmIGlzU3VjY2VzcyAmJiBzLmRhdGFGaWx0ZXIgKSB7XG5cdFx0XHRyZXNwb25zZSA9IHMuZGF0YUZpbHRlciggcmVzcG9uc2UsIHMuZGF0YVR5cGUgKTtcblx0XHR9XG5cblx0XHRwcmV2ID0gY3VycmVudDtcblx0XHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0XHRpZiAoIGN1cnJlbnQgKSB7XG5cblx0XHRcdC8vIFRoZXJlJ3Mgb25seSB3b3JrIHRvIGRvIGlmIGN1cnJlbnQgZGF0YVR5cGUgaXMgbm9uLWF1dG9cblx0XHRcdGlmICggY3VycmVudCA9PT0gXCIqXCIgKSB7XG5cblx0XHRcdFx0Y3VycmVudCA9IHByZXY7XG5cblx0XHRcdC8vIENvbnZlcnQgcmVzcG9uc2UgaWYgcHJldiBkYXRhVHlwZSBpcyBub24tYXV0byBhbmQgZGlmZmVycyBmcm9tIGN1cnJlbnRcblx0XHRcdH0gZWxzZSBpZiAoIHByZXYgIT09IFwiKlwiICYmIHByZXYgIT09IGN1cnJlbnQgKSB7XG5cblx0XHRcdFx0Ly8gU2VlayBhIGRpcmVjdCBjb252ZXJ0ZXJcblx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIGN1cnJlbnQgXSB8fCBjb252ZXJ0ZXJzWyBcIiogXCIgKyBjdXJyZW50IF07XG5cblx0XHRcdFx0Ly8gSWYgbm9uZSBmb3VuZCwgc2VlayBhIHBhaXJcblx0XHRcdFx0aWYgKCAhY29udiApIHtcblx0XHRcdFx0XHRmb3IgKCBjb252MiBpbiBjb252ZXJ0ZXJzICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJZiBjb252MiBvdXRwdXRzIGN1cnJlbnRcblx0XHRcdFx0XHRcdHRtcCA9IGNvbnYyLnNwbGl0KCBcIiBcIiApO1xuXHRcdFx0XHRcdFx0aWYgKCB0bXBbIDEgXSA9PT0gY3VycmVudCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBJZiBwcmV2IGNhbiBiZSBjb252ZXJ0ZWQgdG8gYWNjZXB0ZWQgaW5wdXRcblx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIHRtcFsgMCBdIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRjb252ZXJ0ZXJzWyBcIiogXCIgKyB0bXBbIDAgXSBdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDb25kZW5zZSBlcXVpdmFsZW5jZSBjb252ZXJ0ZXJzXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBjb252ID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIGNvbnYyIF07XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPdGhlcndpc2UsIGluc2VydCB0aGUgaW50ZXJtZWRpYXRlIGRhdGFUeXBlXG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udmVydGVyc1sgY29udjIgXSAhPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGN1cnJlbnQgPSB0bXBbIDAgXTtcblx0XHRcdFx0XHRcdFx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCB0bXBbIDEgXSApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFwcGx5IGNvbnZlcnRlciAoaWYgbm90IGFuIGVxdWl2YWxlbmNlKVxuXHRcdFx0XHRpZiAoIGNvbnYgIT09IHRydWUgKSB7XG5cblx0XHRcdFx0XHQvLyBVbmxlc3MgZXJyb3JzIGFyZSBhbGxvd2VkIHRvIGJ1YmJsZSwgY2F0Y2ggYW5kIHJldHVybiB0aGVtXG5cdFx0XHRcdFx0aWYgKCBjb252ICYmIHMudGhyb3dzICkge1xuXHRcdFx0XHRcdFx0cmVzcG9uc2UgPSBjb252KCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdFx0XHRzdGF0ZTogXCJwYXJzZXJlcnJvclwiLFxuXHRcdFx0XHRcdFx0XHRcdGVycm9yOiBjb252ID8gZSA6IFwiTm8gY29udmVyc2lvbiBmcm9tIFwiICsgcHJldiArIFwiIHRvIFwiICsgY3VycmVudFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7IHN0YXRlOiBcInN1Y2Nlc3NcIiwgZGF0YTogcmVzcG9uc2UgfTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIENvdW50ZXIgZm9yIGhvbGRpbmcgdGhlIG51bWJlciBvZiBhY3RpdmUgcXVlcmllc1xuXHRhY3RpdmU6IDAsXG5cblx0Ly8gTGFzdC1Nb2RpZmllZCBoZWFkZXIgY2FjaGUgZm9yIG5leHQgcmVxdWVzdFxuXHRsYXN0TW9kaWZpZWQ6IHt9LFxuXHRldGFnOiB7fSxcblxuXHRhamF4U2V0dGluZ3M6IHtcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYsXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRpc0xvY2FsOiBybG9jYWxQcm90b2NvbC50ZXN0KCBsb2NhdGlvbi5wcm90b2NvbCApLFxuXHRcdGdsb2JhbDogdHJ1ZSxcblx0XHRwcm9jZXNzRGF0YTogdHJ1ZSxcblx0XHRhc3luYzogdHJ1ZSxcblx0XHRjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIixcblxuXHRcdC8qXG5cdFx0dGltZW91dDogMCxcblx0XHRkYXRhOiBudWxsLFxuXHRcdGRhdGFUeXBlOiBudWxsLFxuXHRcdHVzZXJuYW1lOiBudWxsLFxuXHRcdHBhc3N3b3JkOiBudWxsLFxuXHRcdGNhY2hlOiBudWxsLFxuXHRcdHRocm93czogZmFsc2UsXG5cdFx0dHJhZGl0aW9uYWw6IGZhbHNlLFxuXHRcdGhlYWRlcnM6IHt9LFxuXHRcdCovXG5cblx0XHRhY2NlcHRzOiB7XG5cdFx0XHRcIipcIjogYWxsVHlwZXMsXG5cdFx0XHR0ZXh0OiBcInRleHQvcGxhaW5cIixcblx0XHRcdGh0bWw6IFwidGV4dC9odG1sXCIsXG5cdFx0XHR4bWw6IFwiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbFwiLFxuXHRcdFx0anNvbjogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIlxuXHRcdH0sXG5cblx0XHRjb250ZW50czoge1xuXHRcdFx0eG1sOiAvXFxieG1sXFxiLyxcblx0XHRcdGh0bWw6IC9cXGJodG1sLyxcblx0XHRcdGpzb246IC9cXGJqc29uXFxiL1xuXHRcdH0sXG5cblx0XHRyZXNwb25zZUZpZWxkczoge1xuXHRcdFx0eG1sOiBcInJlc3BvbnNlWE1MXCIsXG5cdFx0XHR0ZXh0OiBcInJlc3BvbnNlVGV4dFwiLFxuXHRcdFx0anNvbjogXCJyZXNwb25zZUpTT05cIlxuXHRcdH0sXG5cblx0XHQvLyBEYXRhIGNvbnZlcnRlcnNcblx0XHQvLyBLZXlzIHNlcGFyYXRlIHNvdXJjZSAob3IgY2F0Y2hhbGwgXCIqXCIpIGFuZCBkZXN0aW5hdGlvbiB0eXBlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG5cdFx0Y29udmVydGVyczoge1xuXG5cdFx0XHQvLyBDb252ZXJ0IGFueXRoaW5nIHRvIHRleHRcblx0XHRcdFwiKiB0ZXh0XCI6IFN0cmluZyxcblxuXHRcdFx0Ly8gVGV4dCB0byBodG1sICh0cnVlID0gbm8gdHJhbnNmb3JtYXRpb24pXG5cdFx0XHRcInRleHQgaHRtbFwiOiB0cnVlLFxuXG5cdFx0XHQvLyBFdmFsdWF0ZSB0ZXh0IGFzIGEganNvbiBleHByZXNzaW9uXG5cdFx0XHRcInRleHQganNvblwiOiBKU09OLnBhcnNlLFxuXG5cdFx0XHQvLyBQYXJzZSB0ZXh0IGFzIHhtbFxuXHRcdFx0XCJ0ZXh0IHhtbFwiOiBqUXVlcnkucGFyc2VYTUxcblx0XHR9LFxuXG5cdFx0Ly8gRm9yIG9wdGlvbnMgdGhhdCBzaG91bGRuJ3QgYmUgZGVlcCBleHRlbmRlZDpcblx0XHQvLyB5b3UgY2FuIGFkZCB5b3VyIG93biBjdXN0b20gb3B0aW9ucyBoZXJlIGlmXG5cdFx0Ly8gYW5kIHdoZW4geW91IGNyZWF0ZSBvbmUgdGhhdCBzaG91bGRuJ3QgYmVcblx0XHQvLyBkZWVwIGV4dGVuZGVkIChzZWUgYWpheEV4dGVuZClcblx0XHRmbGF0T3B0aW9uczoge1xuXHRcdFx0dXJsOiB0cnVlLFxuXHRcdFx0Y29udGV4dDogdHJ1ZVxuXHRcdH1cblx0fSxcblxuXHQvLyBDcmVhdGVzIGEgZnVsbCBmbGVkZ2VkIHNldHRpbmdzIG9iamVjdCBpbnRvIHRhcmdldFxuXHQvLyB3aXRoIGJvdGggYWpheFNldHRpbmdzIGFuZCBzZXR0aW5ncyBmaWVsZHMuXG5cdC8vIElmIHRhcmdldCBpcyBvbWl0dGVkLCB3cml0ZXMgaW50byBhamF4U2V0dGluZ3MuXG5cdGFqYXhTZXR1cDogZnVuY3Rpb24oIHRhcmdldCwgc2V0dGluZ3MgKSB7XG5cdFx0cmV0dXJuIHNldHRpbmdzID9cblxuXHRcdFx0Ly8gQnVpbGRpbmcgYSBzZXR0aW5ncyBvYmplY3Rcblx0XHRcdGFqYXhFeHRlbmQoIGFqYXhFeHRlbmQoIHRhcmdldCwgalF1ZXJ5LmFqYXhTZXR0aW5ncyApLCBzZXR0aW5ncyApIDpcblxuXHRcdFx0Ly8gRXh0ZW5kaW5nIGFqYXhTZXR0aW5nc1xuXHRcdFx0YWpheEV4dGVuZCggalF1ZXJ5LmFqYXhTZXR0aW5ncywgdGFyZ2V0ICk7XG5cdH0sXG5cblx0YWpheFByZWZpbHRlcjogYWRkVG9QcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBwcmVmaWx0ZXJzICksXG5cdGFqYXhUcmFuc3BvcnQ6IGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cyApLFxuXG5cdC8vIE1haW4gbWV0aG9kXG5cdGFqYXg6IGZ1bmN0aW9uKCB1cmwsIG9wdGlvbnMgKSB7XG5cblx0XHQvLyBJZiB1cmwgaXMgYW4gb2JqZWN0LCBzaW11bGF0ZSBwcmUtMS41IHNpZ25hdHVyZVxuXHRcdGlmICggdHlwZW9mIHVybCA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdG9wdGlvbnMgPSB1cmw7XG5cdFx0XHR1cmwgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gRm9yY2Ugb3B0aW9ucyB0byBiZSBhbiBvYmplY3Rcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdHZhciB0cmFuc3BvcnQsXG5cblx0XHRcdC8vIFVSTCB3aXRob3V0IGFudGktY2FjaGUgcGFyYW1cblx0XHRcdGNhY2hlVVJMLFxuXG5cdFx0XHQvLyBSZXNwb25zZSBoZWFkZXJzXG5cdFx0XHRyZXNwb25zZUhlYWRlcnNTdHJpbmcsXG5cdFx0XHRyZXNwb25zZUhlYWRlcnMsXG5cblx0XHRcdC8vIHRpbWVvdXQgaGFuZGxlXG5cdFx0XHR0aW1lb3V0VGltZXIsXG5cblx0XHRcdC8vIFVybCBjbGVhbnVwIHZhclxuXHRcdFx0dXJsQW5jaG9yLFxuXG5cdFx0XHQvLyBSZXF1ZXN0IHN0YXRlIChiZWNvbWVzIGZhbHNlIHVwb24gc2VuZCBhbmQgdHJ1ZSB1cG9uIGNvbXBsZXRpb24pXG5cdFx0XHRjb21wbGV0ZWQsXG5cblx0XHRcdC8vIFRvIGtub3cgaWYgZ2xvYmFsIGV2ZW50cyBhcmUgdG8gYmUgZGlzcGF0Y2hlZFxuXHRcdFx0ZmlyZUdsb2JhbHMsXG5cblx0XHRcdC8vIExvb3AgdmFyaWFibGVcblx0XHRcdGksXG5cblx0XHRcdC8vIHVuY2FjaGVkIHBhcnQgb2YgdGhlIHVybFxuXHRcdFx0dW5jYWNoZWQsXG5cblx0XHRcdC8vIENyZWF0ZSB0aGUgZmluYWwgb3B0aW9ucyBvYmplY3Rcblx0XHRcdHMgPSBqUXVlcnkuYWpheFNldHVwKCB7fSwgb3B0aW9ucyApLFxuXG5cdFx0XHQvLyBDYWxsYmFja3MgY29udGV4dFxuXHRcdFx0Y2FsbGJhY2tDb250ZXh0ID0gcy5jb250ZXh0IHx8IHMsXG5cblx0XHRcdC8vIENvbnRleHQgZm9yIGdsb2JhbCBldmVudHMgaXMgY2FsbGJhY2tDb250ZXh0IGlmIGl0IGlzIGEgRE9NIG5vZGUgb3IgalF1ZXJ5IGNvbGxlY3Rpb25cblx0XHRcdGdsb2JhbEV2ZW50Q29udGV4dCA9IHMuY29udGV4dCAmJlxuXHRcdFx0XHQoIGNhbGxiYWNrQ29udGV4dC5ub2RlVHlwZSB8fCBjYWxsYmFja0NvbnRleHQuanF1ZXJ5ICkgP1xuXHRcdFx0XHRcdGpRdWVyeSggY2FsbGJhY2tDb250ZXh0ICkgOlxuXHRcdFx0XHRcdGpRdWVyeS5ldmVudCxcblxuXHRcdFx0Ly8gRGVmZXJyZWRzXG5cdFx0XHRkZWZlcnJlZCA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZCA9IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXG5cdFx0XHQvLyBTdGF0dXMtZGVwZW5kZW50IGNhbGxiYWNrc1xuXHRcdFx0c3RhdHVzQ29kZSA9IHMuc3RhdHVzQ29kZSB8fCB7fSxcblxuXHRcdFx0Ly8gSGVhZGVycyAodGhleSBhcmUgc2VudCBhbGwgYXQgb25jZSlcblx0XHRcdHJlcXVlc3RIZWFkZXJzID0ge30sXG5cdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzID0ge30sXG5cblx0XHRcdC8vIERlZmF1bHQgYWJvcnQgbWVzc2FnZVxuXHRcdFx0c3RyQWJvcnQgPSBcImNhbmNlbGVkXCIsXG5cblx0XHRcdC8vIEZha2UgeGhyXG5cdFx0XHRqcVhIUiA9IHtcblx0XHRcdFx0cmVhZHlTdGF0ZTogMCxcblxuXHRcdFx0XHQvLyBCdWlsZHMgaGVhZGVycyBoYXNodGFibGUgaWYgbmVlZGVkXG5cdFx0XHRcdGdldFJlc3BvbnNlSGVhZGVyOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdFx0XHRcdHZhciBtYXRjaDtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHRcdGlmICggIXJlc3BvbnNlSGVhZGVycyApIHtcblx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzID0ge307XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggKCBtYXRjaCA9IHJoZWFkZXJzLmV4ZWMoIHJlc3BvbnNlSGVhZGVyc1N0cmluZyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzWyBtYXRjaFsgMSBdLnRvTG93ZXJDYXNlKCkgXSA9IG1hdGNoWyAyIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1hdGNoID0gcmVzcG9uc2VIZWFkZXJzWyBrZXkudG9Mb3dlckNhc2UoKSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2ggPT0gbnVsbCA/IG51bGwgOiBtYXRjaDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBSYXcgc3RyaW5nXG5cdFx0XHRcdGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNvbXBsZXRlZCA/IHJlc3BvbnNlSGVhZGVyc1N0cmluZyA6IG51bGw7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gQ2FjaGVzIHRoZSBoZWFkZXJcblx0XHRcdFx0c2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRuYW1lID0gcmVxdWVzdEhlYWRlcnNOYW1lc1sgbmFtZS50b0xvd2VyQ2FzZSgpIF0gPVxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSB8fCBuYW1lO1xuXHRcdFx0XHRcdFx0cmVxdWVzdEhlYWRlcnNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBPdmVycmlkZXMgcmVzcG9uc2UgY29udGVudC10eXBlIGhlYWRlclxuXHRcdFx0XHRvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0cy5taW1lVHlwZSA9IHR5cGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRcdHN0YXR1c0NvZGU6IGZ1bmN0aW9uKCBtYXAgKSB7XG5cdFx0XHRcdFx0dmFyIGNvZGU7XG5cdFx0XHRcdFx0aWYgKCBtYXAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBFeGVjdXRlIHRoZSBhcHByb3ByaWF0ZSBjYWxsYmFja3Ncblx0XHRcdFx0XHRcdFx0anFYSFIuYWx3YXlzKCBtYXBbIGpxWEhSLnN0YXR1cyBdICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdC8vIExhenktYWRkIHRoZSBuZXcgY2FsbGJhY2tzIGluIGEgd2F5IHRoYXQgcHJlc2VydmVzIG9sZCBvbmVzXG5cdFx0XHRcdFx0XHRcdGZvciAoIGNvZGUgaW4gbWFwICkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0NvZGVbIGNvZGUgXSA9IFsgc3RhdHVzQ29kZVsgY29kZSBdLCBtYXBbIGNvZGUgXSBdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIENhbmNlbCB0aGUgcmVxdWVzdFxuXHRcdFx0XHRhYm9ydDogZnVuY3Rpb24oIHN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0dmFyIGZpbmFsVGV4dCA9IHN0YXR1c1RleHQgfHwgc3RyQWJvcnQ7XG5cdFx0XHRcdFx0aWYgKCB0cmFuc3BvcnQgKSB7XG5cdFx0XHRcdFx0XHR0cmFuc3BvcnQuYWJvcnQoIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkb25lKCAwLCBmaW5hbFRleHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdC8vIEF0dGFjaCBkZWZlcnJlZHNcblx0XHRkZWZlcnJlZC5wcm9taXNlKCBqcVhIUiApO1xuXG5cdFx0Ly8gQWRkIHByb3RvY29sIGlmIG5vdCBwcm92aWRlZCAocHJlZmlsdGVycyBtaWdodCBleHBlY3QgaXQpXG5cdFx0Ly8gSGFuZGxlIGZhbHN5IHVybCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0ICgjMTAwOTM6IGNvbnNpc3RlbmN5IHdpdGggb2xkIHNpZ25hdHVyZSlcblx0XHQvLyBXZSBhbHNvIHVzZSB0aGUgdXJsIHBhcmFtZXRlciBpZiBhdmFpbGFibGVcblx0XHRzLnVybCA9ICggKCB1cmwgfHwgcy51cmwgfHwgbG9jYXRpb24uaHJlZiApICsgXCJcIiApXG5cdFx0XHQucmVwbGFjZSggcnByb3RvY29sLCBsb2NhdGlvbi5wcm90b2NvbCArIFwiLy9cIiApO1xuXG5cdFx0Ly8gQWxpYXMgbWV0aG9kIG9wdGlvbiB0byB0eXBlIGFzIHBlciB0aWNrZXQgIzEyMDA0XG5cdFx0cy50eXBlID0gb3B0aW9ucy5tZXRob2QgfHwgb3B0aW9ucy50eXBlIHx8IHMubWV0aG9kIHx8IHMudHlwZTtcblxuXHRcdC8vIEV4dHJhY3QgZGF0YVR5cGVzIGxpc3Rcblx0XHRzLmRhdGFUeXBlcyA9ICggcy5kYXRhVHlwZSB8fCBcIipcIiApLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblxuXHRcdC8vIEEgY3Jvc3MtZG9tYWluIHJlcXVlc3QgaXMgaW4gb3JkZXIgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgb3JpZ2luLlxuXHRcdGlmICggcy5jcm9zc0RvbWFpbiA9PSBudWxsICkge1xuXHRcdFx0dXJsQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHRcdFx0Ly8gSUUgdGhyb3dzIGV4Y2VwdGlvbiBvbiBhY2Nlc3NpbmcgdGhlIGhyZWYgcHJvcGVydHkgaWYgdXJsIGlzIG1hbGZvcm1lZCxcblx0XHRcdC8vIGUuZy4gaHR0cDovL2V4YW1wbGUuY29tOjgweC9cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHVybEFuY2hvci5ocmVmID0gcy51cmw7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEgb25seVxuXHRcdFx0XHQvLyBBbmNob3IncyBob3N0IHByb3BlcnR5IGlzbid0IGNvcnJlY3RseSBzZXQgd2hlbiBzLnVybCBpcyByZWxhdGl2ZVxuXHRcdFx0XHR1cmxBbmNob3IuaHJlZiA9IHVybEFuY2hvci5ocmVmO1xuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gb3JpZ2luQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgb3JpZ2luQW5jaG9yLmhvc3QgIT09XG5cdFx0XHRcdFx0dXJsQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgdXJsQW5jaG9yLmhvc3Q7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhbiBlcnJvciBwYXJzaW5nIHRoZSBVUkwsIGFzc3VtZSBpdCBpcyBjcm9zc0RvbWFpbixcblx0XHRcdFx0Ly8gaXQgY2FuIGJlIHJlamVjdGVkIGJ5IHRoZSB0cmFuc3BvcnQgaWYgaXQgaXMgaW52YWxpZFxuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcblx0XHRpZiAoIHMuZGF0YSAmJiBzLnByb2Nlc3NEYXRhICYmIHR5cGVvZiBzLmRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRzLmRhdGEgPSBqUXVlcnkucGFyYW0oIHMuZGF0YSwgcy50cmFkaXRpb25hbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHByZWZpbHRlcnNcblx0XHRpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGEgcHJlZmlsdGVyLCBzdG9wIHRoZXJlXG5cdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4ganFYSFI7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgY2FuIGZpcmUgZ2xvYmFsIGV2ZW50cyBhcyBvZiBub3cgaWYgYXNrZWQgdG9cblx0XHQvLyBEb24ndCBmaXJlIGV2ZW50cyBpZiBqUXVlcnkuZXZlbnQgaXMgdW5kZWZpbmVkIGluIGFuIEFNRC11c2FnZSBzY2VuYXJpbyAoIzE1MTE4KVxuXHRcdGZpcmVHbG9iYWxzID0galF1ZXJ5LmV2ZW50ICYmIHMuZ2xvYmFsO1xuXG5cdFx0Ly8gV2F0Y2ggZm9yIGEgbmV3IHNldCBvZiByZXF1ZXN0c1xuXHRcdGlmICggZmlyZUdsb2JhbHMgJiYgalF1ZXJ5LmFjdGl2ZSsrID09PSAwICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIFwiYWpheFN0YXJ0XCIgKTtcblx0XHR9XG5cblx0XHQvLyBVcHBlcmNhc2UgdGhlIHR5cGVcblx0XHRzLnR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTtcblxuXHRcdC8vIERldGVybWluZSBpZiByZXF1ZXN0IGhhcyBjb250ZW50XG5cdFx0cy5oYXNDb250ZW50ID0gIXJub0NvbnRlbnQudGVzdCggcy50eXBlICk7XG5cblx0XHQvLyBTYXZlIHRoZSBVUkwgaW4gY2FzZSB3ZSdyZSB0b3lpbmcgd2l0aCB0aGUgSWYtTW9kaWZpZWQtU2luY2Vcblx0XHQvLyBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIgbGF0ZXIgb25cblx0XHQvLyBSZW1vdmUgaGFzaCB0byBzaW1wbGlmeSB1cmwgbWFuaXB1bGF0aW9uXG5cdFx0Y2FjaGVVUkwgPSBzLnVybC5yZXBsYWNlKCByaGFzaCwgXCJcIiApO1xuXG5cdFx0Ly8gTW9yZSBvcHRpb25zIGhhbmRsaW5nIGZvciByZXF1ZXN0cyB3aXRoIG5vIGNvbnRlbnRcblx0XHRpZiAoICFzLmhhc0NvbnRlbnQgKSB7XG5cblx0XHRcdC8vIFJlbWVtYmVyIHRoZSBoYXNoIHNvIHdlIGNhbiBwdXQgaXQgYmFja1xuXHRcdFx0dW5jYWNoZWQgPSBzLnVybC5zbGljZSggY2FjaGVVUkwubGVuZ3RoICk7XG5cblx0XHRcdC8vIElmIGRhdGEgaXMgYXZhaWxhYmxlLCBhcHBlbmQgZGF0YSB0byB1cmxcblx0XHRcdGlmICggcy5kYXRhICkge1xuXHRcdFx0XHRjYWNoZVVSTCArPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgcy5kYXRhO1xuXG5cdFx0XHRcdC8vICM5NjgyOiByZW1vdmUgZGF0YSBzbyB0aGF0IGl0J3Mgbm90IHVzZWQgaW4gYW4gZXZlbnR1YWwgcmV0cnlcblx0XHRcdFx0ZGVsZXRlIHMuZGF0YTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9yIHVwZGF0ZSBhbnRpLWNhY2hlIHBhcmFtIGlmIG5lZWRlZFxuXHRcdFx0aWYgKCBzLmNhY2hlID09PSBmYWxzZSApIHtcblx0XHRcdFx0Y2FjaGVVUkwgPSBjYWNoZVVSTC5yZXBsYWNlKCByYW50aUNhY2hlLCBcIiQxXCIgKTtcblx0XHRcdFx0dW5jYWNoZWQgPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgXCJfPVwiICsgKCBub25jZSsrICkgKyB1bmNhY2hlZDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUHV0IGhhc2ggYW5kIGFudGktY2FjaGUgb24gdGhlIFVSTCB0aGF0IHdpbGwgYmUgcmVxdWVzdGVkIChnaC0xNzMyKVxuXHRcdFx0cy51cmwgPSBjYWNoZVVSTCArIHVuY2FjaGVkO1xuXG5cdFx0Ly8gQ2hhbmdlICclMjAnIHRvICcrJyBpZiB0aGlzIGlzIGVuY29kZWQgZm9ybSBib2R5IGNvbnRlbnQgKGdoLTI2NTgpXG5cdFx0fSBlbHNlIGlmICggcy5kYXRhICYmIHMucHJvY2Vzc0RhdGEgJiZcblx0XHRcdCggcy5jb250ZW50VHlwZSB8fCBcIlwiICkuaW5kZXhPZiggXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiApID09PSAwICkge1xuXHRcdFx0cy5kYXRhID0gcy5kYXRhLnJlcGxhY2UoIHIyMCwgXCIrXCIgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdGhlIElmLU1vZGlmaWVkLVNpbmNlIGFuZC9vciBJZi1Ob25lLU1hdGNoIGhlYWRlciwgaWYgaW4gaWZNb2RpZmllZCBtb2RlLlxuXHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0aWYgKCBqUXVlcnkubGFzdE1vZGlmaWVkWyBjYWNoZVVSTCBdICkge1xuXHRcdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIklmLU1vZGlmaWVkLVNpbmNlXCIsIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKTtcblx0XHRcdH1cblx0XHRcdGlmICggalF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTm9uZS1NYXRjaFwiLCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgY29ycmVjdCBoZWFkZXIsIGlmIGRhdGEgaXMgYmVpbmcgc2VudFxuXHRcdGlmICggcy5kYXRhICYmIHMuaGFzQ29udGVudCAmJiBzLmNvbnRlbnRUeXBlICE9PSBmYWxzZSB8fCBvcHRpb25zLmNvbnRlbnRUeXBlICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJDb250ZW50LVR5cGVcIiwgcy5jb250ZW50VHlwZSApO1xuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgQWNjZXB0cyBoZWFkZXIgZm9yIHRoZSBzZXJ2ZXIsIGRlcGVuZGluZyBvbiB0aGUgZGF0YVR5cGVcblx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKFxuXHRcdFx0XCJBY2NlcHRcIixcblx0XHRcdHMuZGF0YVR5cGVzWyAwIF0gJiYgcy5hY2NlcHRzWyBzLmRhdGFUeXBlc1sgMCBdIF0gP1xuXHRcdFx0XHRzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWyAwIF0gXSArXG5cdFx0XHRcdFx0KCBzLmRhdGFUeXBlc1sgMCBdICE9PSBcIipcIiA/IFwiLCBcIiArIGFsbFR5cGVzICsgXCI7IHE9MC4wMVwiIDogXCJcIiApIDpcblx0XHRcdFx0cy5hY2NlcHRzWyBcIipcIiBdXG5cdFx0KTtcblxuXHRcdC8vIENoZWNrIGZvciBoZWFkZXJzIG9wdGlvblxuXHRcdGZvciAoIGkgaW4gcy5oZWFkZXJzICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggaSwgcy5oZWFkZXJzWyBpIF0gKTtcblx0XHR9XG5cblx0XHQvLyBBbGxvdyBjdXN0b20gaGVhZGVycy9taW1ldHlwZXMgYW5kIGVhcmx5IGFib3J0XG5cdFx0aWYgKCBzLmJlZm9yZVNlbmQgJiZcblx0XHRcdCggcy5iZWZvcmVTZW5kLmNhbGwoIGNhbGxiYWNrQ29udGV4dCwganFYSFIsIHMgKSA9PT0gZmFsc2UgfHwgY29tcGxldGVkICkgKSB7XG5cblx0XHRcdC8vIEFib3J0IGlmIG5vdCBkb25lIGFscmVhZHkgYW5kIHJldHVyblxuXHRcdFx0cmV0dXJuIGpxWEhSLmFib3J0KCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWJvcnRpbmcgaXMgbm8gbG9uZ2VyIGEgY2FuY2VsbGF0aW9uXG5cdFx0c3RyQWJvcnQgPSBcImFib3J0XCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrcyBvbiBkZWZlcnJlZHNcblx0XHRjb21wbGV0ZURlZmVycmVkLmFkZCggcy5jb21wbGV0ZSApO1xuXHRcdGpxWEhSLmRvbmUoIHMuc3VjY2VzcyApO1xuXHRcdGpxWEhSLmZhaWwoIHMuZXJyb3IgKTtcblxuXHRcdC8vIEdldCB0cmFuc3BvcnRcblx0XHR0cmFuc3BvcnQgPSBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIG5vIHRyYW5zcG9ydCwgd2UgYXV0by1hYm9ydFxuXHRcdGlmICggIXRyYW5zcG9ydCApIHtcblx0XHRcdGRvbmUoIC0xLCBcIk5vIFRyYW5zcG9ydFwiICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSAxO1xuXG5cdFx0XHQvLyBTZW5kIGdsb2JhbCBldmVudFxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheFNlbmRcIiwgWyBqcVhIUiwgcyBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGFqYXhTZW5kLCBzdG9wIHRoZXJlXG5cdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0cmV0dXJuIGpxWEhSO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaW1lb3V0XG5cdFx0XHRpZiAoIHMuYXN5bmMgJiYgcy50aW1lb3V0ID4gMCApIHtcblx0XHRcdFx0dGltZW91dFRpbWVyID0gd2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGpxWEhSLmFib3J0KCBcInRpbWVvdXRcIiApO1xuXHRcdFx0XHR9LCBzLnRpbWVvdXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29tcGxldGVkID0gZmFsc2U7XG5cdFx0XHRcdHRyYW5zcG9ydC5zZW5kKCByZXF1ZXN0SGVhZGVycywgZG9uZSApO1xuXHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0Ly8gUmV0aHJvdyBwb3N0LWNvbXBsZXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHR0aHJvdyBlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUHJvcGFnYXRlIG90aGVycyBhcyByZXN1bHRzXG5cdFx0XHRcdGRvbmUoIC0xLCBlICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGJhY2sgZm9yIHdoZW4gZXZlcnl0aGluZyBpcyBkb25lXG5cdFx0ZnVuY3Rpb24gZG9uZSggc3RhdHVzLCBuYXRpdmVTdGF0dXNUZXh0LCByZXNwb25zZXMsIGhlYWRlcnMgKSB7XG5cdFx0XHR2YXIgaXNTdWNjZXNzLCBzdWNjZXNzLCBlcnJvciwgcmVzcG9uc2UsIG1vZGlmaWVkLFxuXHRcdFx0XHRzdGF0dXNUZXh0ID0gbmF0aXZlU3RhdHVzVGV4dDtcblxuXHRcdFx0Ly8gSWdub3JlIHJlcGVhdCBpbnZvY2F0aW9uc1xuXHRcdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gQ2xlYXIgdGltZW91dCBpZiBpdCBleGlzdHNcblx0XHRcdGlmICggdGltZW91dFRpbWVyICkge1xuXHRcdFx0XHR3aW5kb3cuY2xlYXJUaW1lb3V0KCB0aW1lb3V0VGltZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRGVyZWZlcmVuY2UgdHJhbnNwb3J0IGZvciBlYXJseSBnYXJiYWdlIGNvbGxlY3Rpb25cblx0XHRcdC8vIChubyBtYXR0ZXIgaG93IGxvbmcgdGhlIGpxWEhSIG9iamVjdCB3aWxsIGJlIHVzZWQpXG5cdFx0XHR0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHRcdC8vIENhY2hlIHJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyA9IGhlYWRlcnMgfHwgXCJcIjtcblxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGVcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSBzdGF0dXMgPiAwID8gNCA6IDA7XG5cblx0XHRcdC8vIERldGVybWluZSBpZiBzdWNjZXNzZnVsXG5cdFx0XHRpc1N1Y2Nlc3MgPSBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDtcblxuXHRcdFx0Ly8gR2V0IHJlc3BvbnNlIGRhdGFcblx0XHRcdGlmICggcmVzcG9uc2VzICkge1xuXHRcdFx0XHRyZXNwb25zZSA9IGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udmVydCBubyBtYXR0ZXIgd2hhdCAodGhhdCB3YXkgcmVzcG9uc2VYWFggZmllbGRzIGFyZSBhbHdheXMgc2V0KVxuXHRcdFx0cmVzcG9uc2UgPSBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKTtcblxuXHRcdFx0Ly8gSWYgc3VjY2Vzc2Z1bCwgaGFuZGxlIHR5cGUgY2hhaW5pbmdcblx0XHRcdGlmICggaXNTdWNjZXNzICkge1xuXG5cdFx0XHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0XHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiTGFzdC1Nb2RpZmllZFwiICk7XG5cdFx0XHRcdFx0aWYgKCBtb2RpZmllZCApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bW9kaWZpZWQgPSBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJldGFnXCIgKTtcblx0XHRcdFx0XHRpZiAoIG1vZGlmaWVkICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpZiBubyBjb250ZW50XG5cdFx0XHRcdGlmICggc3RhdHVzID09PSAyMDQgfHwgcy50eXBlID09PSBcIkhFQURcIiApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub2NvbnRlbnRcIjtcblxuXHRcdFx0XHQvLyBpZiBub3QgbW9kaWZpZWRcblx0XHRcdFx0fSBlbHNlIGlmICggc3RhdHVzID09PSAzMDQgKSB7XG5cdFx0XHRcdFx0c3RhdHVzVGV4dCA9IFwibm90bW9kaWZpZWRcIjtcblxuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGRhdGEsIGxldCdzIGNvbnZlcnQgaXRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gcmVzcG9uc2Uuc3RhdGU7XG5cdFx0XHRcdFx0c3VjY2VzcyA9IHJlc3BvbnNlLmRhdGE7XG5cdFx0XHRcdFx0ZXJyb3IgPSByZXNwb25zZS5lcnJvcjtcblx0XHRcdFx0XHRpc1N1Y2Nlc3MgPSAhZXJyb3I7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gRXh0cmFjdCBlcnJvciBmcm9tIHN0YXR1c1RleHQgYW5kIG5vcm1hbGl6ZSBmb3Igbm9uLWFib3J0c1xuXHRcdFx0XHRlcnJvciA9IHN0YXR1c1RleHQ7XG5cdFx0XHRcdGlmICggc3RhdHVzIHx8ICFzdGF0dXNUZXh0ICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcImVycm9yXCI7XG5cdFx0XHRcdFx0aWYgKCBzdGF0dXMgPCAwICkge1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGRhdGEgZm9yIHRoZSBmYWtlIHhociBvYmplY3Rcblx0XHRcdGpxWEhSLnN0YXR1cyA9IHN0YXR1cztcblx0XHRcdGpxWEhSLnN0YXR1c1RleHQgPSAoIG5hdGl2ZVN0YXR1c1RleHQgfHwgc3RhdHVzVGV4dCApICsgXCJcIjtcblxuXHRcdFx0Ly8gU3VjY2Vzcy9FcnJvclxuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsgc3VjY2Vzcywgc3RhdHVzVGV4dCwganFYSFIgXSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0LCBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRqcVhIUi5zdGF0dXNDb2RlKCBzdGF0dXNDb2RlICk7XG5cdFx0XHRzdGF0dXNDb2RlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggaXNTdWNjZXNzID8gXCJhamF4U3VjY2Vzc1wiIDogXCJhamF4RXJyb3JcIixcblx0XHRcdFx0XHRbIGpxWEhSLCBzLCBpc1N1Y2Nlc3MgPyBzdWNjZXNzIDogZXJyb3IgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb21wbGV0ZVxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZC5maXJlV2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0IF0gKTtcblxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheENvbXBsZXRlXCIsIFsganFYSFIsIHMgXSApO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSB0aGUgZ2xvYmFsIEFKQVggY291bnRlclxuXHRcdFx0XHRpZiAoICEoIC0talF1ZXJ5LmFjdGl2ZSApICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCBcImFqYXhTdG9wXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBqcVhIUjtcblx0fSxcblxuXHRnZXRKU09OOiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdldCggdXJsLCBkYXRhLCBjYWxsYmFjaywgXCJqc29uXCIgKTtcblx0fSxcblxuXHRnZXRTY3JpcHQ6IGZ1bmN0aW9uKCB1cmwsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIHVuZGVmaW5lZCwgY2FsbGJhY2ssIFwic2NyaXB0XCIgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImdldFwiLCBcInBvc3RcIiBdLCBmdW5jdGlvbiggaSwgbWV0aG9kICkge1xuXHRqUXVlcnlbIG1ldGhvZCBdID0gZnVuY3Rpb24oIHVybCwgZGF0YSwgY2FsbGJhY2ssIHR5cGUgKSB7XG5cblx0XHQvLyBTaGlmdCBhcmd1bWVudHMgaWYgZGF0YSBhcmd1bWVudCB3YXMgb21pdHRlZFxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGRhdGEgKSApIHtcblx0XHRcdHR5cGUgPSB0eXBlIHx8IGNhbGxiYWNrO1xuXHRcdFx0Y2FsbGJhY2sgPSBkYXRhO1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBUaGUgdXJsIGNhbiBiZSBhbiBvcHRpb25zIG9iamVjdCAod2hpY2ggdGhlbiBtdXN0IGhhdmUgLnVybClcblx0XHRyZXR1cm4galF1ZXJ5LmFqYXgoIGpRdWVyeS5leHRlbmQoIHtcblx0XHRcdHVybDogdXJsLFxuXHRcdFx0dHlwZTogbWV0aG9kLFxuXHRcdFx0ZGF0YVR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhOiBkYXRhLFxuXHRcdFx0c3VjY2VzczogY2FsbGJhY2tcblx0XHR9LCBqUXVlcnkuaXNQbGFpbk9iamVjdCggdXJsICkgJiYgdXJsICkgKTtcblx0fTtcbn0gKTtcblxuXG5qUXVlcnkuX2V2YWxVcmwgPSBmdW5jdGlvbiggdXJsICkge1xuXHRyZXR1cm4galF1ZXJ5LmFqYXgoIHtcblx0XHR1cmw6IHVybCxcblxuXHRcdC8vIE1ha2UgdGhpcyBleHBsaWNpdCwgc2luY2UgdXNlciBjYW4gb3ZlcnJpZGUgdGhpcyB0aHJvdWdoIGFqYXhTZXR1cCAoIzExMjY0KVxuXHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0ZGF0YVR5cGU6IFwic2NyaXB0XCIsXG5cdFx0Y2FjaGU6IHRydWUsXG5cdFx0YXN5bmM6IGZhbHNlLFxuXHRcdGdsb2JhbDogZmFsc2UsXG5cdFx0XCJ0aHJvd3NcIjogdHJ1ZVxuXHR9ICk7XG59O1xuXG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0d3JhcEFsbDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIHdyYXA7XG5cblx0XHRpZiAoIHRoaXNbIDAgXSApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdFx0aHRtbCA9IGh0bWwuY2FsbCggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoZSBlbGVtZW50cyB0byB3cmFwIHRoZSB0YXJnZXQgYXJvdW5kXG5cdFx0XHR3cmFwID0galF1ZXJ5KCBodG1sLCB0aGlzWyAwIF0ub3duZXJEb2N1bWVudCApLmVxKCAwICkuY2xvbmUoIHRydWUgKTtcblxuXHRcdFx0aWYgKCB0aGlzWyAwIF0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0d3JhcC5pbnNlcnRCZWZvcmUoIHRoaXNbIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHR3cmFwLm1hcCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBlbGVtID0gdGhpcztcblxuXHRcdFx0XHR3aGlsZSAoIGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQgKSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gZWxlbTtcblx0XHRcdH0gKS5hcHBlbmQoIHRoaXMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwSW5uZXIoIGh0bWwuY2FsbCggdGhpcywgaSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgc2VsZiA9IGpRdWVyeSggdGhpcyApLFxuXHRcdFx0XHRjb250ZW50cyA9IHNlbGYuY29udGVudHMoKTtcblxuXHRcdFx0aWYgKCBjb250ZW50cy5sZW5ndGggKSB7XG5cdFx0XHRcdGNvbnRlbnRzLndyYXBBbGwoIGh0bWwgKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi5hcHBlbmQoIGh0bWwgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0d3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwQWxsKCBpc0Z1bmN0aW9uID8gaHRtbC5jYWxsKCB0aGlzLCBpICkgOiBodG1sICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdHVud3JhcDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHRoaXMucGFyZW50KCBzZWxlY3RvciApLm5vdCggXCJib2R5XCIgKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLnJlcGxhY2VXaXRoKCB0aGlzLmNoaWxkTm9kZXMgKTtcblx0XHR9ICk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gIWpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSggZWxlbSApO1xufTtcbmpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gISEoIGVsZW0ub2Zmc2V0V2lkdGggfHwgZWxlbS5vZmZzZXRIZWlnaHQgfHwgZWxlbS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCApO1xufTtcblxuXG5cblxualF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIgPSBmdW5jdGlvbigpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbmV3IHdpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuXHR9IGNhdGNoICggZSApIHt9XG59O1xuXG52YXIgeGhyU3VjY2Vzc1N0YXR1cyA9IHtcblxuXHRcdC8vIEZpbGUgcHJvdG9jb2wgYWx3YXlzIHlpZWxkcyBzdGF0dXMgY29kZSAwLCBhc3N1bWUgMjAwXG5cdFx0MDogMjAwLFxuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHQvLyAjMTQ1MDogc29tZXRpbWVzIElFIHJldHVybnMgMTIyMyB3aGVuIGl0IHNob3VsZCBiZSAyMDRcblx0XHQxMjIzOiAyMDRcblx0fSxcblx0eGhyU3VwcG9ydGVkID0galF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIoKTtcblxuc3VwcG9ydC5jb3JzID0gISF4aHJTdXBwb3J0ZWQgJiYgKCBcIndpdGhDcmVkZW50aWFsc1wiIGluIHhoclN1cHBvcnRlZCApO1xuc3VwcG9ydC5hamF4ID0geGhyU3VwcG9ydGVkID0gISF4aHJTdXBwb3J0ZWQ7XG5cbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0dmFyIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrO1xuXG5cdC8vIENyb3NzIGRvbWFpbiBvbmx5IGFsbG93ZWQgaWYgc3VwcG9ydGVkIHRocm91Z2ggWE1MSHR0cFJlcXVlc3Rcblx0aWYgKCBzdXBwb3J0LmNvcnMgfHwgeGhyU3VwcG9ydGVkICYmICFvcHRpb25zLmNyb3NzRG9tYWluICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRzZW5kOiBmdW5jdGlvbiggaGVhZGVycywgY29tcGxldGUgKSB7XG5cdFx0XHRcdHZhciBpLFxuXHRcdFx0XHRcdHhociA9IG9wdGlvbnMueGhyKCk7XG5cblx0XHRcdFx0eGhyLm9wZW4oXG5cdFx0XHRcdFx0b3B0aW9ucy50eXBlLFxuXHRcdFx0XHRcdG9wdGlvbnMudXJsLFxuXHRcdFx0XHRcdG9wdGlvbnMuYXN5bmMsXG5cdFx0XHRcdFx0b3B0aW9ucy51c2VybmFtZSxcblx0XHRcdFx0XHRvcHRpb25zLnBhc3N3b3JkXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gQXBwbHkgY3VzdG9tIGZpZWxkcyBpZiBwcm92aWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMueGhyRmllbGRzICkge1xuXHRcdFx0XHRcdGZvciAoIGkgaW4gb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0XHR4aHJbIGkgXSA9IG9wdGlvbnMueGhyRmllbGRzWyBpIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gT3ZlcnJpZGUgbWltZSB0eXBlIGlmIG5lZWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMubWltZVR5cGUgJiYgeGhyLm92ZXJyaWRlTWltZVR5cGUgKSB7XG5cdFx0XHRcdFx0eGhyLm92ZXJyaWRlTWltZVR5cGUoIG9wdGlvbnMubWltZVR5cGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFgtUmVxdWVzdGVkLVdpdGggaGVhZGVyXG5cdFx0XHRcdC8vIEZvciBjcm9zcy1kb21haW4gcmVxdWVzdHMsIHNlZWluZyBhcyBjb25kaXRpb25zIGZvciBhIHByZWZsaWdodCBhcmVcblx0XHRcdFx0Ly8gYWtpbiB0byBhIGppZ3NhdyBwdXp6bGUsIHdlIHNpbXBseSBuZXZlciBzZXQgaXQgdG8gYmUgc3VyZS5cblx0XHRcdFx0Ly8gKGl0IGNhbiBhbHdheXMgYmUgc2V0IG9uIGEgcGVyLXJlcXVlc3QgYmFzaXMgb3IgZXZlbiB1c2luZyBhamF4U2V0dXApXG5cdFx0XHRcdC8vIEZvciBzYW1lLWRvbWFpbiByZXF1ZXN0cywgd29uJ3QgY2hhbmdlIGhlYWRlciBpZiBhbHJlYWR5IHByb3ZpZGVkLlxuXHRcdFx0XHRpZiAoICFvcHRpb25zLmNyb3NzRG9tYWluICYmICFoZWFkZXJzWyBcIlgtUmVxdWVzdGVkLVdpdGhcIiBdICkge1xuXHRcdFx0XHRcdGhlYWRlcnNbIFwiWC1SZXF1ZXN0ZWQtV2l0aFwiIF0gPSBcIlhNTEh0dHBSZXF1ZXN0XCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBTZXQgaGVhZGVyc1xuXHRcdFx0XHRmb3IgKCBpIGluIGhlYWRlcnMgKSB7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoIGksIGhlYWRlcnNbIGkgXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQ2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRjYWxsYmFjayA9IGVycm9yQ2FsbGJhY2sgPSB4aHIub25sb2FkID1cblx0XHRcdFx0XHRcdFx0XHR4aHIub25lcnJvciA9IHhoci5vbmFib3J0ID0geGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSBcImFib3J0XCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0eGhyLmFib3J0KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHR5cGUgPT09IFwiZXJyb3JcIiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gT24gYSBtYW51YWwgbmF0aXZlIGFib3J0LCBJRTkgdGhyb3dzXG5cdFx0XHRcdFx0XHRcdFx0Ly8gZXJyb3JzIG9uIGFueSBwcm9wZXJ0eSBhY2Nlc3MgdGhhdCBpcyBub3QgcmVhZHlTdGF0ZVxuXHRcdFx0XHRcdFx0XHRcdGlmICggdHlwZW9mIHhoci5zdGF0dXMgIT09IFwibnVtYmVyXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggMCwgXCJlcnJvclwiICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKFxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEZpbGU6IHByb3RvY29sIGFsd2F5cyB5aWVsZHMgc3RhdHVzIDA7IHNlZSAjODYwNSwgIzE0MjA3XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXMsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXNUZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZShcblx0XHRcdFx0XHRcdFx0XHRcdHhoclN1Y2Nlc3NTdGF0dXNbIHhoci5zdGF0dXMgXSB8fCB4aHIuc3RhdHVzLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHQsXG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBJRTkgaGFzIG5vIFhIUjIgYnV0IHRocm93cyBvbiBiaW5hcnkgKHRyYWMtMTE0MjYpXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBGb3IgWEhSMiBub24tdGV4dCwgbGV0IHRoZSBjYWxsZXIgaGFuZGxlIGl0IChnaC0yNDk4KVxuXHRcdFx0XHRcdFx0XHRcdFx0KCB4aHIucmVzcG9uc2VUeXBlIHx8IFwidGV4dFwiICkgIT09IFwidGV4dFwiICB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0dHlwZW9mIHhoci5yZXNwb25zZVRleHQgIT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IGJpbmFyeTogeGhyLnJlc3BvbnNlIH0gOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IHRleHQ6IHhoci5yZXNwb25zZVRleHQgfSxcblx0XHRcdFx0XHRcdFx0XHRcdHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKVxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIExpc3RlbiB0byBldmVudHNcblx0XHRcdFx0eGhyLm9ubG9hZCA9IGNhbGxiYWNrKCk7XG5cdFx0XHRcdGVycm9yQ2FsbGJhY2sgPSB4aHIub25lcnJvciA9IGNhbGxiYWNrKCBcImVycm9yXCIgKTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA5IG9ubHlcblx0XHRcdFx0Ly8gVXNlIG9ucmVhZHlzdGF0ZWNoYW5nZSB0byByZXBsYWNlIG9uYWJvcnRcblx0XHRcdFx0Ly8gdG8gaGFuZGxlIHVuY2F1Z2h0IGFib3J0c1xuXHRcdFx0XHRpZiAoIHhoci5vbmFib3J0ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0eGhyLm9uYWJvcnQgPSBlcnJvckNhbGxiYWNrO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgcmVhZHlTdGF0ZSBiZWZvcmUgdGltZW91dCBhcyBpdCBjaGFuZ2VzXG5cdFx0XHRcdFx0XHRpZiAoIHhoci5yZWFkeVN0YXRlID09PSA0ICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIEFsbG93IG9uZXJyb3IgdG8gYmUgY2FsbGVkIGZpcnN0LFxuXHRcdFx0XHRcdFx0XHQvLyBidXQgdGhhdCB3aWxsIG5vdCBoYW5kbGUgYSBuYXRpdmUgYWJvcnRcblx0XHRcdFx0XHRcdFx0Ly8gQWxzbywgc2F2ZSBlcnJvckNhbGxiYWNrIHRvIGEgdmFyaWFibGVcblx0XHRcdFx0XHRcdFx0Ly8gYXMgeGhyLm9uZXJyb3IgY2Fubm90IGJlIGFjY2Vzc2VkXG5cdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JDYWxsYmFjaygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDcmVhdGUgdGhlIGFib3J0IGNhbGxiYWNrXG5cdFx0XHRcdGNhbGxiYWNrID0gY2FsbGJhY2soIFwiYWJvcnRcIiApO1xuXG5cdFx0XHRcdHRyeSB7XG5cblx0XHRcdFx0XHQvLyBEbyBzZW5kIHRoZSByZXF1ZXN0ICh0aGlzIG1heSByYWlzZSBhbiBleGNlcHRpb24pXG5cdFx0XHRcdFx0eGhyLnNlbmQoIG9wdGlvbnMuaGFzQ29udGVudCAmJiBvcHRpb25zLmRhdGEgfHwgbnVsbCApO1xuXHRcdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHRcdC8vICMxNDY4MzogT25seSByZXRocm93IGlmIHRoaXMgaGFzbid0IGJlZW4gbm90aWZpZWQgYXMgYW4gZXJyb3IgeWV0XG5cdFx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRcdHRocm93IGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0gKTtcblxuXG5cblxuLy8gUHJldmVudCBhdXRvLWV4ZWN1dGlvbiBvZiBzY3JpcHRzIHdoZW4gbm8gZXhwbGljaXQgZGF0YVR5cGUgd2FzIHByb3ZpZGVkIChTZWUgZ2gtMjQzMilcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBmdW5jdGlvbiggcyApIHtcblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMuY29udGVudHMuc2NyaXB0ID0gZmFsc2U7XG5cdH1cbn0gKTtcblxuLy8gSW5zdGFsbCBzY3JpcHQgZGF0YVR5cGVcbmpRdWVyeS5hamF4U2V0dXAoIHtcblx0YWNjZXB0czoge1xuXHRcdHNjcmlwdDogXCJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIFwiICtcblx0XHRcdFwiYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0XCJcblx0fSxcblx0Y29udGVudHM6IHtcblx0XHRzY3JpcHQ6IC9cXGIoPzpqYXZhfGVjbWEpc2NyaXB0XFxiL1xuXHR9LFxuXHRjb252ZXJ0ZXJzOiB7XG5cdFx0XCJ0ZXh0IHNjcmlwdFwiOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdGpRdWVyeS5nbG9iYWxFdmFsKCB0ZXh0ICk7XG5cdFx0XHRyZXR1cm4gdGV4dDtcblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSGFuZGxlIGNhY2hlJ3Mgc3BlY2lhbCBjYXNlIGFuZCBjcm9zc0RvbWFpblxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIFwic2NyaXB0XCIsIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzLmNhY2hlID0gZmFsc2U7XG5cdH1cblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMudHlwZSA9IFwiR0VUXCI7XG5cdH1cbn0gKTtcblxuLy8gQmluZCBzY3JpcHQgdGFnIGhhY2sgdHJhbnNwb3J0XG5qUXVlcnkuYWpheFRyYW5zcG9ydCggXCJzY3JpcHRcIiwgZnVuY3Rpb24oIHMgKSB7XG5cblx0Ly8gVGhpcyB0cmFuc3BvcnQgb25seSBkZWFscyB3aXRoIGNyb3NzIGRvbWFpbiByZXF1ZXN0c1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0dmFyIHNjcmlwdCwgY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBfLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0c2NyaXB0ID0galF1ZXJ5KCBcIjxzY3JpcHQ+XCIgKS5wcm9wKCB7XG5cdFx0XHRcdFx0Y2hhcnNldDogcy5zY3JpcHRDaGFyc2V0LFxuXHRcdFx0XHRcdHNyYzogcy51cmxcblx0XHRcdFx0fSApLm9uKFxuXHRcdFx0XHRcdFwibG9hZCBlcnJvclwiLFxuXHRcdFx0XHRcdGNhbGxiYWNrID0gZnVuY3Rpb24oIGV2dCApIHtcblx0XHRcdFx0XHRcdHNjcmlwdC5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdGNhbGxiYWNrID0gbnVsbDtcblx0XHRcdFx0XHRcdGlmICggZXZ0ICkge1xuXHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggZXZ0LnR5cGUgPT09IFwiZXJyb3JcIiA/IDQwNCA6IDIwMCwgZXZ0LnR5cGUgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gVXNlIG5hdGl2ZSBET00gbWFuaXB1bGF0aW9uIHRvIGF2b2lkIG91ciBkb21NYW5pcCBBSkFYIHRyaWNrZXJ5XG5cdFx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdFsgMCBdICk7XG5cdFx0XHR9LFxuXHRcdFx0YWJvcnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBvbGRDYWxsYmFja3MgPSBbXSxcblx0cmpzb25wID0gLyg9KVxcPyg/PSZ8JCl8XFw/XFw/LztcblxuLy8gRGVmYXVsdCBqc29ucCBzZXR0aW5nc1xualF1ZXJ5LmFqYXhTZXR1cCgge1xuXHRqc29ucDogXCJjYWxsYmFja1wiLFxuXHRqc29ucENhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgY2FsbGJhY2sgPSBvbGRDYWxsYmFja3MucG9wKCkgfHwgKCBqUXVlcnkuZXhwYW5kbyArIFwiX1wiICsgKCBub25jZSsrICkgKTtcblx0XHR0aGlzWyBjYWxsYmFjayBdID0gdHJ1ZTtcblx0XHRyZXR1cm4gY2FsbGJhY2s7XG5cdH1cbn0gKTtcblxuLy8gRGV0ZWN0LCBub3JtYWxpemUgb3B0aW9ucyBhbmQgaW5zdGFsbCBjYWxsYmFja3MgZm9yIGpzb25wIHJlcXVlc3RzXG5qUXVlcnkuYWpheFByZWZpbHRlciggXCJqc29uIGpzb25wXCIsIGZ1bmN0aW9uKCBzLCBvcmlnaW5hbFNldHRpbmdzLCBqcVhIUiApIHtcblxuXHR2YXIgY2FsbGJhY2tOYW1lLCBvdmVyd3JpdHRlbiwgcmVzcG9uc2VDb250YWluZXIsXG5cdFx0anNvblByb3AgPSBzLmpzb25wICE9PSBmYWxzZSAmJiAoIHJqc29ucC50ZXN0KCBzLnVybCApID9cblx0XHRcdFwidXJsXCIgOlxuXHRcdFx0dHlwZW9mIHMuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHQoIHMuY29udGVudFR5cGUgfHwgXCJcIiApXG5cdFx0XHRcdFx0LmluZGV4T2YoIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgKSA9PT0gMCAmJlxuXHRcdFx0XHRyanNvbnAudGVzdCggcy5kYXRhICkgJiYgXCJkYXRhXCJcblx0XHQpO1xuXG5cdC8vIEhhbmRsZSBpZmYgdGhlIGV4cGVjdGVkIGRhdGEgdHlwZSBpcyBcImpzb25wXCIgb3Igd2UgaGF2ZSBhIHBhcmFtZXRlciB0byBzZXRcblx0aWYgKCBqc29uUHJvcCB8fCBzLmRhdGFUeXBlc1sgMCBdID09PSBcImpzb25wXCIgKSB7XG5cblx0XHQvLyBHZXQgY2FsbGJhY2sgbmFtZSwgcmVtZW1iZXJpbmcgcHJlZXhpc3RpbmcgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGl0XG5cdFx0Y2FsbGJhY2tOYW1lID0gcy5qc29ucENhbGxiYWNrID0galF1ZXJ5LmlzRnVuY3Rpb24oIHMuanNvbnBDYWxsYmFjayApID9cblx0XHRcdHMuanNvbnBDYWxsYmFjaygpIDpcblx0XHRcdHMuanNvbnBDYWxsYmFjaztcblxuXHRcdC8vIEluc2VydCBjYWxsYmFjayBpbnRvIHVybCBvciBmb3JtIGRhdGFcblx0XHRpZiAoIGpzb25Qcm9wICkge1xuXHRcdFx0c1sganNvblByb3AgXSA9IHNbIGpzb25Qcm9wIF0ucmVwbGFjZSggcmpzb25wLCBcIiQxXCIgKyBjYWxsYmFja05hbWUgKTtcblx0XHR9IGVsc2UgaWYgKCBzLmpzb25wICE9PSBmYWxzZSApIHtcblx0XHRcdHMudXJsICs9ICggcnF1ZXJ5LnRlc3QoIHMudXJsICkgPyBcIiZcIiA6IFwiP1wiICkgKyBzLmpzb25wICsgXCI9XCIgKyBjYWxsYmFja05hbWU7XG5cdFx0fVxuXG5cdFx0Ly8gVXNlIGRhdGEgY29udmVydGVyIHRvIHJldHJpZXZlIGpzb24gYWZ0ZXIgc2NyaXB0IGV4ZWN1dGlvblxuXHRcdHMuY29udmVydGVyc1sgXCJzY3JpcHQganNvblwiIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggIXJlc3BvbnNlQ29udGFpbmVyICkge1xuXHRcdFx0XHRqUXVlcnkuZXJyb3IoIGNhbGxiYWNrTmFtZSArIFwiIHdhcyBub3QgY2FsbGVkXCIgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXNwb25zZUNvbnRhaW5lclsgMCBdO1xuXHRcdH07XG5cblx0XHQvLyBGb3JjZSBqc29uIGRhdGFUeXBlXG5cdFx0cy5kYXRhVHlwZXNbIDAgXSA9IFwianNvblwiO1xuXG5cdFx0Ly8gSW5zdGFsbCBjYWxsYmFja1xuXHRcdG92ZXJ3cml0dGVuID0gd2luZG93WyBjYWxsYmFja05hbWUgXTtcblx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXNwb25zZUNvbnRhaW5lciA9IGFyZ3VtZW50cztcblx0XHR9O1xuXG5cdFx0Ly8gQ2xlYW4tdXAgZnVuY3Rpb24gKGZpcmVzIGFmdGVyIGNvbnZlcnRlcnMpXG5cdFx0anFYSFIuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gSWYgcHJldmlvdXMgdmFsdWUgZGlkbid0IGV4aXN0IC0gcmVtb3ZlIGl0XG5cdFx0XHRpZiAoIG92ZXJ3cml0dGVuID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpRdWVyeSggd2luZG93ICkucmVtb3ZlUHJvcCggY2FsbGJhY2tOYW1lICk7XG5cblx0XHRcdC8vIE90aGVyd2lzZSByZXN0b3JlIHByZWV4aXN0aW5nIHZhbHVlXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gb3ZlcndyaXR0ZW47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNhdmUgYmFjayBhcyBmcmVlXG5cdFx0XHRpZiAoIHNbIGNhbGxiYWNrTmFtZSBdICkge1xuXG5cdFx0XHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHJlLXVzaW5nIHRoZSBvcHRpb25zIGRvZXNuJ3Qgc2NyZXcgdGhpbmdzIGFyb3VuZFxuXHRcdFx0XHRzLmpzb25wQ2FsbGJhY2sgPSBvcmlnaW5hbFNldHRpbmdzLmpzb25wQ2FsbGJhY2s7XG5cblx0XHRcdFx0Ly8gU2F2ZSB0aGUgY2FsbGJhY2sgbmFtZSBmb3IgZnV0dXJlIHVzZVxuXHRcdFx0XHRvbGRDYWxsYmFja3MucHVzaCggY2FsbGJhY2tOYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENhbGwgaWYgaXQgd2FzIGEgZnVuY3Rpb24gYW5kIHdlIGhhdmUgYSByZXNwb25zZVxuXHRcdFx0aWYgKCByZXNwb25zZUNvbnRhaW5lciAmJiBqUXVlcnkuaXNGdW5jdGlvbiggb3ZlcndyaXR0ZW4gKSApIHtcblx0XHRcdFx0b3ZlcndyaXR0ZW4oIHJlc3BvbnNlQ29udGFpbmVyWyAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmVzcG9uc2VDb250YWluZXIgPSBvdmVyd3JpdHRlbiA9IHVuZGVmaW5lZDtcblx0XHR9ICk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBzY3JpcHRcblx0XHRyZXR1cm4gXCJzY3JpcHRcIjtcblx0fVxufSApO1xuXG5cblxuXG4vLyBTdXBwb3J0OiBTYWZhcmkgOCBvbmx5XG4vLyBJbiBTYWZhcmkgOCBkb2N1bWVudHMgY3JlYXRlZCB2aWEgZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50XG4vLyBjb2xsYXBzZSBzaWJsaW5nIGZvcm1zOiB0aGUgc2Vjb25kIG9uZSBiZWNvbWVzIGEgY2hpbGQgb2YgdGhlIGZpcnN0IG9uZS5cbi8vIEJlY2F1c2Ugb2YgdGhhdCwgdGhpcyBzZWN1cml0eSBtZWFzdXJlIGhhcyB0byBiZSBkaXNhYmxlZCBpbiBTYWZhcmkgOC5cbi8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzczMzdcbnN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ID0gKCBmdW5jdGlvbigpIHtcblx0dmFyIGJvZHkgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoIFwiXCIgKS5ib2R5O1xuXHRib2R5LmlubmVySFRNTCA9IFwiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT5cIjtcblx0cmV0dXJuIGJvZHkuY2hpbGROb2Rlcy5sZW5ndGggPT09IDI7XG59ICkoKTtcblxuXG4vLyBBcmd1bWVudCBcImRhdGFcIiBzaG91bGQgYmUgc3RyaW5nIG9mIGh0bWxcbi8vIGNvbnRleHQgKG9wdGlvbmFsKTogSWYgc3BlY2lmaWVkLCB0aGUgZnJhZ21lbnQgd2lsbCBiZSBjcmVhdGVkIGluIHRoaXMgY29udGV4dCxcbi8vIGRlZmF1bHRzIHRvIGRvY3VtZW50XG4vLyBrZWVwU2NyaXB0cyAob3B0aW9uYWwpOiBJZiB0cnVlLCB3aWxsIGluY2x1ZGUgc2NyaXB0cyBwYXNzZWQgaW4gdGhlIGh0bWwgc3RyaW5nXG5qUXVlcnkucGFyc2VIVE1MID0gZnVuY3Rpb24oIGRhdGEsIGNvbnRleHQsIGtlZXBTY3JpcHRzICkge1xuXHRpZiAoIHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBbXTtcblx0fVxuXHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRrZWVwU2NyaXB0cyA9IGNvbnRleHQ7XG5cdFx0Y29udGV4dCA9IGZhbHNlO1xuXHR9XG5cblx0dmFyIGJhc2UsIHBhcnNlZCwgc2NyaXB0cztcblxuXHRpZiAoICFjb250ZXh0ICkge1xuXG5cdFx0Ly8gU3RvcCBzY3JpcHRzIG9yIGlubGluZSBldmVudCBoYW5kbGVycyBmcm9tIGJlaW5nIGV4ZWN1dGVkIGltbWVkaWF0ZWx5XG5cdFx0Ly8gYnkgdXNpbmcgZG9jdW1lbnQuaW1wbGVtZW50YXRpb25cblx0XHRpZiAoIHN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ICkge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCggXCJcIiApO1xuXG5cdFx0XHQvLyBTZXQgdGhlIGJhc2UgaHJlZiBmb3IgdGhlIGNyZWF0ZWQgZG9jdW1lbnRcblx0XHRcdC8vIHNvIGFueSBwYXJzZWQgZWxlbWVudHMgd2l0aCBVUkxzXG5cdFx0XHQvLyBhcmUgYmFzZWQgb24gdGhlIGRvY3VtZW50J3MgVVJMIChnaC0yOTY1KVxuXHRcdFx0YmFzZSA9IGNvbnRleHQuY3JlYXRlRWxlbWVudCggXCJiYXNlXCIgKTtcblx0XHRcdGJhc2UuaHJlZiA9IGRvY3VtZW50LmxvY2F0aW9uLmhyZWY7XG5cdFx0XHRjb250ZXh0LmhlYWQuYXBwZW5kQ2hpbGQoIGJhc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50O1xuXHRcdH1cblx0fVxuXG5cdHBhcnNlZCA9IHJzaW5nbGVUYWcuZXhlYyggZGF0YSApO1xuXHRzY3JpcHRzID0gIWtlZXBTY3JpcHRzICYmIFtdO1xuXG5cdC8vIFNpbmdsZSB0YWdcblx0aWYgKCBwYXJzZWQgKSB7XG5cdFx0cmV0dXJuIFsgY29udGV4dC5jcmVhdGVFbGVtZW50KCBwYXJzZWRbIDEgXSApIF07XG5cdH1cblxuXHRwYXJzZWQgPSBidWlsZEZyYWdtZW50KCBbIGRhdGEgXSwgY29udGV4dCwgc2NyaXB0cyApO1xuXG5cdGlmICggc2NyaXB0cyAmJiBzY3JpcHRzLmxlbmd0aCApIHtcblx0XHRqUXVlcnkoIHNjcmlwdHMgKS5yZW1vdmUoKTtcblx0fVxuXG5cdHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBwYXJzZWQuY2hpbGROb2RlcyApO1xufTtcblxuXG4vKipcbiAqIExvYWQgYSB1cmwgaW50byBhIHBhZ2VcbiAqL1xualF1ZXJ5LmZuLmxvYWQgPSBmdW5jdGlvbiggdXJsLCBwYXJhbXMsIGNhbGxiYWNrICkge1xuXHR2YXIgc2VsZWN0b3IsIHR5cGUsIHJlc3BvbnNlLFxuXHRcdHNlbGYgPSB0aGlzLFxuXHRcdG9mZiA9IHVybC5pbmRleE9mKCBcIiBcIiApO1xuXG5cdGlmICggb2ZmID4gLTEgKSB7XG5cdFx0c2VsZWN0b3IgPSBzdHJpcEFuZENvbGxhcHNlKCB1cmwuc2xpY2UoIG9mZiApICk7XG5cdFx0dXJsID0gdXJsLnNsaWNlKCAwLCBvZmYgKTtcblx0fVxuXG5cdC8vIElmIGl0J3MgYSBmdW5jdGlvblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwYXJhbXMgKSApIHtcblxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2sgPSBwYXJhbXM7XG5cdFx0cGFyYW1zID0gdW5kZWZpbmVkO1xuXG5cdC8vIE90aGVyd2lzZSwgYnVpbGQgYSBwYXJhbSBzdHJpbmdcblx0fSBlbHNlIGlmICggcGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0dHlwZSA9IFwiUE9TVFwiO1xuXHR9XG5cblx0Ly8gSWYgd2UgaGF2ZSBlbGVtZW50cyB0byBtb2RpZnksIG1ha2UgdGhlIHJlcXVlc3Rcblx0aWYgKCBzZWxmLmxlbmd0aCA+IDAgKSB7XG5cdFx0alF1ZXJ5LmFqYXgoIHtcblx0XHRcdHVybDogdXJsLFxuXG5cdFx0XHQvLyBJZiBcInR5cGVcIiB2YXJpYWJsZSBpcyB1bmRlZmluZWQsIHRoZW4gXCJHRVRcIiBtZXRob2Qgd2lsbCBiZSB1c2VkLlxuXHRcdFx0Ly8gTWFrZSB2YWx1ZSBvZiB0aGlzIGZpZWxkIGV4cGxpY2l0IHNpbmNlXG5cdFx0XHQvLyB1c2VyIGNhbiBvdmVycmlkZSBpdCB0aHJvdWdoIGFqYXhTZXR1cCBtZXRob2Rcblx0XHRcdHR5cGU6IHR5cGUgfHwgXCJHRVRcIixcblx0XHRcdGRhdGFUeXBlOiBcImh0bWxcIixcblx0XHRcdGRhdGE6IHBhcmFtc1xuXHRcdH0gKS5kb25lKCBmdW5jdGlvbiggcmVzcG9uc2VUZXh0ICkge1xuXG5cdFx0XHQvLyBTYXZlIHJlc3BvbnNlIGZvciB1c2UgaW4gY29tcGxldGUgY2FsbGJhY2tcblx0XHRcdHJlc3BvbnNlID0gYXJndW1lbnRzO1xuXG5cdFx0XHRzZWxmLmh0bWwoIHNlbGVjdG9yID9cblxuXHRcdFx0XHQvLyBJZiBhIHNlbGVjdG9yIHdhcyBzcGVjaWZpZWQsIGxvY2F0ZSB0aGUgcmlnaHQgZWxlbWVudHMgaW4gYSBkdW1teSBkaXZcblx0XHRcdFx0Ly8gRXhjbHVkZSBzY3JpcHRzIHRvIGF2b2lkIElFICdQZXJtaXNzaW9uIERlbmllZCcgZXJyb3JzXG5cdFx0XHRcdGpRdWVyeSggXCI8ZGl2PlwiICkuYXBwZW5kKCBqUXVlcnkucGFyc2VIVE1MKCByZXNwb25zZVRleHQgKSApLmZpbmQoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSB1c2UgdGhlIGZ1bGwgcmVzdWx0XG5cdFx0XHRcdHJlc3BvbnNlVGV4dCApO1xuXG5cdFx0Ly8gSWYgdGhlIHJlcXVlc3Qgc3VjY2VlZHMsIHRoaXMgZnVuY3Rpb24gZ2V0cyBcImRhdGFcIiwgXCJzdGF0dXNcIiwgXCJqcVhIUlwiXG5cdFx0Ly8gYnV0IHRoZXkgYXJlIGlnbm9yZWQgYmVjYXVzZSByZXNwb25zZSB3YXMgc2V0IGFib3ZlLlxuXHRcdC8vIElmIGl0IGZhaWxzLCB0aGlzIGZ1bmN0aW9uIGdldHMgXCJqcVhIUlwiLCBcInN0YXR1c1wiLCBcImVycm9yXCJcblx0XHR9ICkuYWx3YXlzKCBjYWxsYmFjayAmJiBmdW5jdGlvbigganFYSFIsIHN0YXR1cyApIHtcblx0XHRcdHNlbGYuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNhbGxiYWNrLmFwcGx5KCB0aGlzLCByZXNwb25zZSB8fCBbIGpxWEhSLnJlc3BvbnNlVGV4dCwgc3RhdHVzLCBqcVhIUiBdICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXM7XG59O1xuXG5cblxuXG4vLyBBdHRhY2ggYSBidW5jaCBvZiBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIGNvbW1vbiBBSkFYIGV2ZW50c1xualF1ZXJ5LmVhY2goIFtcblx0XCJhamF4U3RhcnRcIixcblx0XCJhamF4U3RvcFwiLFxuXHRcImFqYXhDb21wbGV0ZVwiLFxuXHRcImFqYXhFcnJvclwiLFxuXHRcImFqYXhTdWNjZXNzXCIsXG5cdFwiYWpheFNlbmRcIlxuXSwgZnVuY3Rpb24oIGksIHR5cGUgKSB7XG5cdGpRdWVyeS5mblsgdHlwZSBdID0gZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlLCBmbiApO1xuXHR9O1xufSApO1xuXG5cblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggalF1ZXJ5LnRpbWVycywgZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiBlbGVtID09PSBmbi5lbGVtO1xuXHR9ICkubGVuZ3RoO1xufTtcblxuXG5cblxualF1ZXJ5Lm9mZnNldCA9IHtcblx0c2V0T2Zmc2V0OiBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgaSApIHtcblx0XHR2YXIgY3VyUG9zaXRpb24sIGN1ckxlZnQsIGN1ckNTU1RvcCwgY3VyVG9wLCBjdXJPZmZzZXQsIGN1ckNTU0xlZnQsIGNhbGN1bGF0ZVBvc2l0aW9uLFxuXHRcdFx0cG9zaXRpb24gPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBvc2l0aW9uXCIgKSxcblx0XHRcdGN1ckVsZW0gPSBqUXVlcnkoIGVsZW0gKSxcblx0XHRcdHByb3BzID0ge307XG5cblx0XHQvLyBTZXQgcG9zaXRpb24gZmlyc3QsIGluLWNhc2UgdG9wL2xlZnQgYXJlIHNldCBldmVuIG9uIHN0YXRpYyBlbGVtXG5cdFx0aWYgKCBwb3NpdGlvbiA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdGVsZW0uc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cdFx0fVxuXG5cdFx0Y3VyT2Zmc2V0ID0gY3VyRWxlbS5vZmZzZXQoKTtcblx0XHRjdXJDU1NUb3AgPSBqUXVlcnkuY3NzKCBlbGVtLCBcInRvcFwiICk7XG5cdFx0Y3VyQ1NTTGVmdCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwibGVmdFwiICk7XG5cdFx0Y2FsY3VsYXRlUG9zaXRpb24gPSAoIHBvc2l0aW9uID09PSBcImFic29sdXRlXCIgfHwgcG9zaXRpb24gPT09IFwiZml4ZWRcIiApICYmXG5cdFx0XHQoIGN1ckNTU1RvcCArIGN1ckNTU0xlZnQgKS5pbmRleE9mKCBcImF1dG9cIiApID4gLTE7XG5cblx0XHQvLyBOZWVkIHRvIGJlIGFibGUgdG8gY2FsY3VsYXRlIHBvc2l0aW9uIGlmIGVpdGhlclxuXHRcdC8vIHRvcCBvciBsZWZ0IGlzIGF1dG8gYW5kIHBvc2l0aW9uIGlzIGVpdGhlciBhYnNvbHV0ZSBvciBmaXhlZFxuXHRcdGlmICggY2FsY3VsYXRlUG9zaXRpb24gKSB7XG5cdFx0XHRjdXJQb3NpdGlvbiA9IGN1ckVsZW0ucG9zaXRpb24oKTtcblx0XHRcdGN1clRvcCA9IGN1clBvc2l0aW9uLnRvcDtcblx0XHRcdGN1ckxlZnQgPSBjdXJQb3NpdGlvbi5sZWZ0O1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1clRvcCA9IHBhcnNlRmxvYXQoIGN1ckNTU1RvcCApIHx8IDA7XG5cdFx0XHRjdXJMZWZ0ID0gcGFyc2VGbG9hdCggY3VyQ1NTTGVmdCApIHx8IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0aW9ucyApICkge1xuXG5cdFx0XHQvLyBVc2UgalF1ZXJ5LmV4dGVuZCBoZXJlIHRvIGFsbG93IG1vZGlmaWNhdGlvbiBvZiBjb29yZGluYXRlcyBhcmd1bWVudCAoZ2gtMTg0OClcblx0XHRcdG9wdGlvbnMgPSBvcHRpb25zLmNhbGwoIGVsZW0sIGksIGpRdWVyeS5leHRlbmQoIHt9LCBjdXJPZmZzZXQgKSApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0aW9ucy50b3AgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLnRvcCA9ICggb3B0aW9ucy50b3AgLSBjdXJPZmZzZXQudG9wICkgKyBjdXJUb3A7XG5cdFx0fVxuXHRcdGlmICggb3B0aW9ucy5sZWZ0ICE9IG51bGwgKSB7XG5cdFx0XHRwcm9wcy5sZWZ0ID0gKCBvcHRpb25zLmxlZnQgLSBjdXJPZmZzZXQubGVmdCApICsgY3VyTGVmdDtcblx0XHR9XG5cblx0XHRpZiAoIFwidXNpbmdcIiBpbiBvcHRpb25zICkge1xuXHRcdFx0b3B0aW9ucy51c2luZy5jYWxsKCBlbGVtLCBwcm9wcyApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1ckVsZW0uY3NzKCBwcm9wcyApO1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRvZmZzZXQ6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdFx0Ly8gUHJlc2VydmUgY2hhaW5pbmcgZm9yIHNldHRlclxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiBvcHRpb25zID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHR0aGlzIDpcblx0XHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0XHRqUXVlcnkub2Zmc2V0LnNldE9mZnNldCggdGhpcywgb3B0aW9ucywgaSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRvYywgZG9jRWxlbSwgcmVjdCwgd2luLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHplcm9zIGZvciBkaXNjb25uZWN0ZWQgYW5kIGhpZGRlbiAoZGlzcGxheTogbm9uZSkgZWxlbWVudHMgKGdoLTIzMTApXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYVxuXHRcdC8vIGRpc2Nvbm5lY3RlZCBub2RlIGluIElFIHRocm93cyBhbiBlcnJvclxuXHRcdGlmICggIWVsZW0uZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblx0XHR9XG5cblx0XHRyZWN0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudDtcblx0XHRkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudDtcblx0XHR3aW4gPSBkb2MuZGVmYXVsdFZpZXc7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiByZWN0LnRvcCArIHdpbi5wYWdlWU9mZnNldCAtIGRvY0VsZW0uY2xpZW50VG9wLFxuXHRcdFx0bGVmdDogcmVjdC5sZWZ0ICsgd2luLnBhZ2VYT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRMZWZ0XG5cdFx0fTtcblx0fSxcblxuXHRwb3NpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCAhdGhpc1sgMCBdICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBvZmZzZXRQYXJlbnQsIG9mZnNldCxcblx0XHRcdGVsZW0gPSB0aGlzWyAwIF0sXG5cdFx0XHRwYXJlbnRPZmZzZXQgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xuXG5cdFx0Ly8gRml4ZWQgZWxlbWVudHMgYXJlIG9mZnNldCBmcm9tIHdpbmRvdyAocGFyZW50T2Zmc2V0ID0ge3RvcDowLCBsZWZ0OiAwfSxcblx0XHQvLyBiZWNhdXNlIGl0IGlzIGl0cyBvbmx5IG9mZnNldCBwYXJlbnRcblx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApID09PSBcImZpeGVkXCIgKSB7XG5cblx0XHRcdC8vIEFzc3VtZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgaXMgdGhlcmUgd2hlbiBjb21wdXRlZCBwb3NpdGlvbiBpcyBmaXhlZFxuXHRcdFx0b2Zmc2V0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIEdldCAqcmVhbCogb2Zmc2V0UGFyZW50XG5cdFx0XHRvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudCgpO1xuXG5cdFx0XHQvLyBHZXQgY29ycmVjdCBvZmZzZXRzXG5cdFx0XHRvZmZzZXQgPSB0aGlzLm9mZnNldCgpO1xuXHRcdFx0aWYgKCAhbm9kZU5hbWUoIG9mZnNldFBhcmVudFsgMCBdLCBcImh0bWxcIiApICkge1xuXHRcdFx0XHRwYXJlbnRPZmZzZXQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBvZmZzZXRQYXJlbnQgYm9yZGVyc1xuXHRcdFx0cGFyZW50T2Zmc2V0ID0ge1xuXHRcdFx0XHR0b3A6IHBhcmVudE9mZnNldC50b3AgKyBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnRbIDAgXSwgXCJib3JkZXJUb3BXaWR0aFwiLCB0cnVlICksXG5cdFx0XHRcdGxlZnQ6IHBhcmVudE9mZnNldC5sZWZ0ICsgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50WyAwIF0sIFwiYm9yZGVyTGVmdFdpZHRoXCIsIHRydWUgKVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHQvLyBTdWJ0cmFjdCBwYXJlbnQgb2Zmc2V0cyBhbmQgZWxlbWVudCBtYXJnaW5zXG5cdFx0cmV0dXJuIHtcblx0XHRcdHRvcDogb2Zmc2V0LnRvcCAtIHBhcmVudE9mZnNldC50b3AgLSBqUXVlcnkuY3NzKCBlbGVtLCBcIm1hcmdpblRvcFwiLCB0cnVlICksXG5cdFx0XHRsZWZ0OiBvZmZzZXQubGVmdCAtIHBhcmVudE9mZnNldC5sZWZ0IC0galF1ZXJ5LmNzcyggZWxlbSwgXCJtYXJnaW5MZWZ0XCIsIHRydWUgKVxuXHRcdH07XG5cdH0sXG5cblx0Ly8gVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gZG9jdW1lbnRFbGVtZW50IGluIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG5cdC8vIDEpIEZvciB0aGUgZWxlbWVudCBpbnNpZGUgdGhlIGlmcmFtZSB3aXRob3V0IG9mZnNldFBhcmVudCwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm5cblx0Ly8gICAgZG9jdW1lbnRFbGVtZW50IG9mIHRoZSBwYXJlbnQgd2luZG93XG5cdC8vIDIpIEZvciB0aGUgaGlkZGVuIG9yIGRldGFjaGVkIGVsZW1lbnRcblx0Ly8gMykgRm9yIGJvZHkgb3IgaHRtbCBlbGVtZW50LCBpLmUuIGluIGNhc2Ugb2YgdGhlIGh0bWwgbm9kZSAtIGl0IHdpbGwgcmV0dXJuIGl0c2VsZlxuXHQvL1xuXHQvLyBidXQgdGhvc2UgZXhjZXB0aW9ucyB3ZXJlIG5ldmVyIHByZXNlbnRlZCBhcyBhIHJlYWwgbGlmZSB1c2UtY2FzZXNcblx0Ly8gYW5kIG1pZ2h0IGJlIGNvbnNpZGVyZWQgYXMgbW9yZSBwcmVmZXJhYmxlIHJlc3VsdHMuXG5cdC8vXG5cdC8vIFRoaXMgbG9naWMsIGhvd2V2ZXIsIGlzIG5vdCBndWFyYW50ZWVkIGFuZCBjYW4gY2hhbmdlIGF0IGFueSBwb2ludCBpbiB0aGUgZnV0dXJlXG5cdG9mZnNldFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudDtcblxuXHRcdFx0d2hpbGUgKCBvZmZzZXRQYXJlbnQgJiYgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50LCBcInBvc2l0aW9uXCIgKSA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdFx0b2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG9mZnNldFBhcmVudCB8fCBkb2N1bWVudEVsZW1lbnQ7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbi8vIENyZWF0ZSBzY3JvbGxMZWZ0IGFuZCBzY3JvbGxUb3AgbWV0aG9kc1xualF1ZXJ5LmVhY2goIHsgc2Nyb2xsTGVmdDogXCJwYWdlWE9mZnNldFwiLCBzY3JvbGxUb3A6IFwicGFnZVlPZmZzZXRcIiB9LCBmdW5jdGlvbiggbWV0aG9kLCBwcm9wICkge1xuXHR2YXIgdG9wID0gXCJwYWdlWU9mZnNldFwiID09PSBwcm9wO1xuXG5cdGpRdWVyeS5mblsgbWV0aG9kIF0gPSBmdW5jdGlvbiggdmFsICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCBtZXRob2QsIHZhbCApIHtcblxuXHRcdFx0Ly8gQ29hbGVzY2UgZG9jdW1lbnRzIGFuZCB3aW5kb3dzXG5cdFx0XHR2YXIgd2luO1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblx0XHRcdFx0d2luID0gZWxlbTtcblx0XHRcdH0gZWxzZSBpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHdpbiA9IGVsZW0uZGVmYXVsdFZpZXc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdmFsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiB3aW4gPyB3aW5bIHByb3AgXSA6IGVsZW1bIG1ldGhvZCBdO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHdpbiApIHtcblx0XHRcdFx0d2luLnNjcm9sbFRvKFxuXHRcdFx0XHRcdCF0b3AgPyB2YWwgOiB3aW4ucGFnZVhPZmZzZXQsXG5cdFx0XHRcdFx0dG9wID8gdmFsIDogd2luLnBhZ2VZT2Zmc2V0XG5cdFx0XHRcdCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVsZW1bIG1ldGhvZCBdID0gdmFsO1xuXHRcdFx0fVxuXHRcdH0sIG1ldGhvZCwgdmFsLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH07XG59ICk7XG5cbi8vIFN1cHBvcnQ6IFNhZmFyaSA8PTcgLSA5LjEsIENocm9tZSA8PTM3IC0gNDlcbi8vIEFkZCB0aGUgdG9wL2xlZnQgY3NzSG9va3MgdXNpbmcgalF1ZXJ5LmZuLnBvc2l0aW9uXG4vLyBXZWJraXQgYnVnOiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkwODRcbi8vIEJsaW5rIGJ1ZzogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NTg5MzQ3XG4vLyBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgcGVyY2VudCB3aGVuIHNwZWNpZmllZCBmb3IgdG9wL2xlZnQvYm90dG9tL3JpZ2h0O1xuLy8gcmF0aGVyIHRoYW4gbWFrZSB0aGUgY3NzIG1vZHVsZSBkZXBlbmQgb24gdGhlIG9mZnNldCBtb2R1bGUsIGp1c3QgY2hlY2sgZm9yIGl0IGhlcmVcbmpRdWVyeS5lYWNoKCBbIFwidG9wXCIsIFwibGVmdFwiIF0sIGZ1bmN0aW9uKCBpLCBwcm9wICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByb3AgXSA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5waXhlbFBvc2l0aW9uLFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGNvbXB1dGVkID0gY3VyQ1NTKCBlbGVtLCBwcm9wICk7XG5cblx0XHRcdFx0Ly8gSWYgY3VyQ1NTIHJldHVybnMgcGVyY2VudGFnZSwgZmFsbGJhY2sgdG8gb2Zmc2V0XG5cdFx0XHRcdHJldHVybiBybnVtbm9ucHgudGVzdCggY29tcHV0ZWQgKSA/XG5cdFx0XHRcdFx0alF1ZXJ5KCBlbGVtICkucG9zaXRpb24oKVsgcHJvcCBdICsgXCJweFwiIDpcblx0XHRcdFx0XHRjb21wdXRlZDtcblx0XHRcdH1cblx0XHR9XG5cdCk7XG59ICk7XG5cblxuLy8gQ3JlYXRlIGlubmVySGVpZ2h0LCBpbm5lcldpZHRoLCBoZWlnaHQsIHdpZHRoLCBvdXRlckhlaWdodCBhbmQgb3V0ZXJXaWR0aCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBIZWlnaHQ6IFwiaGVpZ2h0XCIsIFdpZHRoOiBcIndpZHRoXCIgfSwgZnVuY3Rpb24oIG5hbWUsIHR5cGUgKSB7XG5cdGpRdWVyeS5lYWNoKCB7IHBhZGRpbmc6IFwiaW5uZXJcIiArIG5hbWUsIGNvbnRlbnQ6IHR5cGUsIFwiXCI6IFwib3V0ZXJcIiArIG5hbWUgfSxcblx0XHRmdW5jdGlvbiggZGVmYXVsdEV4dHJhLCBmdW5jTmFtZSApIHtcblxuXHRcdC8vIE1hcmdpbiBpcyBvbmx5IGZvciBvdXRlckhlaWdodCwgb3V0ZXJXaWR0aFxuXHRcdGpRdWVyeS5mblsgZnVuY05hbWUgXSA9IGZ1bmN0aW9uKCBtYXJnaW4sIHZhbHVlICkge1xuXHRcdFx0dmFyIGNoYWluYWJsZSA9IGFyZ3VtZW50cy5sZW5ndGggJiYgKCBkZWZhdWx0RXh0cmEgfHwgdHlwZW9mIG1hcmdpbiAhPT0gXCJib29sZWFuXCIgKSxcblx0XHRcdFx0ZXh0cmEgPSBkZWZhdWx0RXh0cmEgfHwgKCBtYXJnaW4gPT09IHRydWUgfHwgdmFsdWUgPT09IHRydWUgPyBcIm1hcmdpblwiIDogXCJib3JkZXJcIiApO1xuXG5cdFx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgdHlwZSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBkb2M7XG5cblx0XHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vICQoIHdpbmRvdyApLm91dGVyV2lkdGgvSGVpZ2h0IHJldHVybiB3L2ggaW5jbHVkaW5nIHNjcm9sbGJhcnMgKGdoLTE3MjkpXG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmNOYW1lLmluZGV4T2YoIFwib3V0ZXJcIiApID09PSAwID9cblx0XHRcdFx0XHRcdGVsZW1bIFwiaW5uZXJcIiArIG5hbWUgXSA6XG5cdFx0XHRcdFx0XHRlbGVtLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsgXCJjbGllbnRcIiArIG5hbWUgXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEdldCBkb2N1bWVudCB3aWR0aCBvciBoZWlnaHRcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdGRvYyA9IGVsZW0uZG9jdW1lbnRFbGVtZW50O1xuXG5cdFx0XHRcdFx0Ly8gRWl0aGVyIHNjcm9sbFtXaWR0aC9IZWlnaHRdIG9yIG9mZnNldFtXaWR0aC9IZWlnaHRdIG9yIGNsaWVudFtXaWR0aC9IZWlnaHRdLFxuXHRcdFx0XHRcdC8vIHdoaWNoZXZlciBpcyBncmVhdGVzdFxuXHRcdFx0XHRcdHJldHVybiBNYXRoLm1heChcblx0XHRcdFx0XHRcdGVsZW0uYm9keVsgXCJzY3JvbGxcIiArIG5hbWUgXSwgZG9jWyBcInNjcm9sbFwiICsgbmFtZSBdLFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcIm9mZnNldFwiICsgbmFtZSBdLCBkb2NbIFwib2Zmc2V0XCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRkb2NbIFwiY2xpZW50XCIgKyBuYW1lIF1cblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXG5cdFx0XHRcdFx0Ly8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudCwgcmVxdWVzdGluZyBidXQgbm90IGZvcmNpbmcgcGFyc2VGbG9hdFxuXHRcdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIHR5cGUsIGV4dHJhICkgOlxuXG5cdFx0XHRcdFx0Ly8gU2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudFxuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgdHlwZSwgdmFsdWUsIGV4dHJhICk7XG5cdFx0XHR9LCB0eXBlLCBjaGFpbmFibGUgPyBtYXJnaW4gOiB1bmRlZmluZWQsIGNoYWluYWJsZSApO1xuXHRcdH07XG5cdH0gKTtcbn0gKTtcblxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cblx0YmluZDogZnVuY3Rpb24oIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIG51bGwsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuYmluZDogZnVuY3Rpb24oIHR5cGVzLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYoIHR5cGVzLCBudWxsLCBmbiApO1xuXHR9LFxuXG5cdGRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHR1bmRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBmbiApIHtcblxuXHRcdC8vICggbmFtZXNwYWNlICkgb3IgKCBzZWxlY3RvciwgdHlwZXMgWywgZm5dIClcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/XG5cdFx0XHR0aGlzLm9mZiggc2VsZWN0b3IsIFwiKipcIiApIDpcblx0XHRcdHRoaXMub2ZmKCB0eXBlcywgc2VsZWN0b3IgfHwgXCIqKlwiLCBmbiApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5ob2xkUmVhZHkgPSBmdW5jdGlvbiggaG9sZCApIHtcblx0aWYgKCBob2xkICkge1xuXHRcdGpRdWVyeS5yZWFkeVdhaXQrKztcblx0fSBlbHNlIHtcblx0XHRqUXVlcnkucmVhZHkoIHRydWUgKTtcblx0fVxufTtcbmpRdWVyeS5pc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbmpRdWVyeS5wYXJzZUpTT04gPSBKU09OLnBhcnNlO1xualF1ZXJ5Lm5vZGVOYW1lID0gbm9kZU5hbWU7XG5cblxuXG5cbi8vIFJlZ2lzdGVyIGFzIGEgbmFtZWQgQU1EIG1vZHVsZSwgc2luY2UgalF1ZXJ5IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBvdGhlclxuLy8gZmlsZXMgdGhhdCBtYXkgdXNlIGRlZmluZSwgYnV0IG5vdCB2aWEgYSBwcm9wZXIgY29uY2F0ZW5hdGlvbiBzY3JpcHQgdGhhdFxuLy8gdW5kZXJzdGFuZHMgYW5vbnltb3VzIEFNRCBtb2R1bGVzLiBBIG5hbWVkIEFNRCBpcyBzYWZlc3QgYW5kIG1vc3Qgcm9idXN0XG4vLyB3YXkgdG8gcmVnaXN0ZXIuIExvd2VyY2FzZSBqcXVlcnkgaXMgdXNlZCBiZWNhdXNlIEFNRCBtb2R1bGUgbmFtZXMgYXJlXG4vLyBkZXJpdmVkIGZyb20gZmlsZSBuYW1lcywgYW5kIGpRdWVyeSBpcyBub3JtYWxseSBkZWxpdmVyZWQgaW4gYSBsb3dlcmNhc2Vcbi8vIGZpbGUgbmFtZS4gRG8gdGhpcyBhZnRlciBjcmVhdGluZyB0aGUgZ2xvYmFsIHNvIHRoYXQgaWYgYW4gQU1EIG1vZHVsZSB3YW50c1xuLy8gdG8gY2FsbCBub0NvbmZsaWN0IHRvIGhpZGUgdGhpcyB2ZXJzaW9uIG9mIGpRdWVyeSwgaXQgd2lsbCB3b3JrLlxuXG4vLyBOb3RlIHRoYXQgZm9yIG1heGltdW0gcG9ydGFiaWxpdHksIGxpYnJhcmllcyB0aGF0IGFyZSBub3QgalF1ZXJ5IHNob3VsZFxuLy8gZGVjbGFyZSB0aGVtc2VsdmVzIGFzIGFub255bW91cyBtb2R1bGVzLCBhbmQgYXZvaWQgc2V0dGluZyBhIGdsb2JhbCBpZiBhblxuLy8gQU1EIGxvYWRlciBpcyBwcmVzZW50LiBqUXVlcnkgaXMgYSBzcGVjaWFsIGNhc2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcmJ1cmtlL3JlcXVpcmVqcy93aWtpL1VwZGF0aW5nLWV4aXN0aW5nLWxpYnJhcmllcyN3aWtpLWFub25cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKCBcImpxdWVyeVwiLCBbXSwgZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGpRdWVyeTtcblx0fSApO1xufVxuXG5cblxuXG52YXJcblxuXHQvLyBNYXAgb3ZlciBqUXVlcnkgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0X2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksXG5cblx0Ly8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0XyQgPSB3aW5kb3cuJDtcblxualF1ZXJ5Lm5vQ29uZmxpY3QgPSBmdW5jdGlvbiggZGVlcCApIHtcblx0aWYgKCB3aW5kb3cuJCA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy4kID0gXyQ7XG5cdH1cblxuXHRpZiAoIGRlZXAgJiYgd2luZG93LmpRdWVyeSA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5O1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeTtcbn07XG5cbi8vIEV4cG9zZSBqUXVlcnkgYW5kICQgaWRlbnRpZmllcnMsIGV2ZW4gaW4gQU1EXG4vLyAoIzcxMDIjY29tbWVudDoxMCwgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvcHVsbC81NTcpXG4vLyBhbmQgQ29tbW9uSlMgZm9yIGJyb3dzZXIgZW11bGF0b3JzICgjMTM1NjYpXG5pZiAoICFub0dsb2JhbCApIHtcblx0d2luZG93LmpRdWVyeSA9IHdpbmRvdy4kID0galF1ZXJ5O1xufVxuXG5cblxuXG5yZXR1cm4galF1ZXJ5O1xufSApO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvanF1ZXJ5L2Rpc3QvanF1ZXJ5LmpzXG4vLyBtb2R1bGUgaWQgPSAwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIEphdmFzY3JpcHRcblxuaW1wb3J0ICQgZnJvbSAnanF1ZXJ5J1xuaW1wb3J0ICdib290c3RyYXAnO1xuaW1wb3J0ICdib290c3RyYXAtc2VsZWN0JztcbmltcG9ydCAnYm9vdHN0cmFwLXZhbGlkYXRvcic7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQnO1xuXG5cbi8vIENTU1xuXG5pbXBvcnQgJ2Jvb3RzdHJhcC9kaXN0L2Nzcy9ib290c3RyYXAuY3NzJztcbmltcG9ydCAnYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzcyc7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3MnO1xuaW1wb3J0ICcuL3N0eWxlLmNzcydcblxuJChmdW5jdGlvbiAoKSB7XG4gIFxuICAkKFwiI215SW5wdXRcIikub24oXCJrZXl1cFwiLCBmdW5jdGlvbihldmVudE9iamVjdCkge1xuICAgIFxuICAgIHZhciBpbnB1dCwgZmlsdGVyLCB1bCwgbGksIGEsIGk7XG5cbiAgICBpbnB1dCA9IGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQ7XG4gICAgZmlsdGVyID0gaW5wdXQudmFsdWUudG9VcHBlckNhc2UoKTtcbiAgICB1bCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXlVTFwiKTtcbiAgICBsaSA9IHVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdhJyk7XG5cbiAgICAvLyBMb29wIHRocm91Z2ggYWxsIGxpc3QgaXRlbXMsIGFuZCBoaWRlIHRob3NlIHdobyBkb24ndCBtYXRjaCB0aGUgc2VhcmNoIHF1ZXJ5XG4gICAgZm9yIChpID0gMDsgaSA8IGxpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhID0gbGlbaV07IC8vbGlbaV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJhXCIpWzBdO1xuICAgICAgaWYgKGEuaW5uZXJIVE1MLnRvVXBwZXJDYXNlKCkuaW5kZXhPZihmaWx0ZXIpID4gLTEpIHtcblx0bGlbaV0uc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICB9IGVsc2Uge1xuXHRsaVtpXS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICB9XG4gICAgfVxuXG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNoZWNrVXNlcm5hbWVJbnB1dEhhbmRsZXIoZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgaW5wdXRfZWwgPSAkKGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQpO1xuICAgIHZhciBkYXRhID0gSlNPTi5zdHJpbmdpZnkoe1widXNlcm5hbWVcIjogaW5wdXRfZWwudmFsKCl9KTtcbiAgICB2YXIgdXJsID0gYC90ZWFjaGVycy9jaGVja191c2VybmFtZS8ke2lucHV0X2VsLnZhbCgpfWBcbiAgICAgICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHRpZiAocmVzdWx0LmV4aXN0cykge1xuXHQgIGNvbnNvbGUubG9nKFwiVXNlcm5hbWUgZXhpc3RzXCIpO1xuXHR9XG4gICAgICB9LFxuICAgICAgXCJqc29uXCJcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gdXNlcm5hbWVHZW5lcmF0b3IoZXZlbnRPYmplY3QsIGZpcnN0bmFtZSwgc3VybmFtZSkge1xuICAgIHZhciBpbnB1dF9lbCA9ICQoZXZlbnRPYmplY3QuY3VycmVudFRhcmdldCk7XG4gICAgaW5wdXRfZWwudmFsKGZpcnN0bmFtZStcIi5cIitzdXJuYW1lKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlbGV0ZVJlbGF0aW9uSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgXG4gICAgICAkLmFqYXgoe1xuXHR1cmw6IHVybCxcblx0dHlwZTogJ0RFTEVURScsXG5cdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3VsdCkge1xuXHQgIGVsLmNsb3Nlc3QoXCIubGlzdC1ncm91cC1pdGVtXCIpLnJlbW92ZSgpO1xuXHQgIG1vZGFsRWwubW9kYWwoJ2hpZGUnKTtcblx0fVxuICAgICAgfSk7XG4gICAgICBcbiAgICB9KTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZnVuY3Rpb24gZGVsZXRlSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgICBcbiAgICAgICQuYWpheCh7XG5cdHVybDogdXJsLFxuXHR0eXBlOiAnREVMRVRFJyxcblx0c3VjY2VzczogZnVuY3Rpb24ocmVzdWx0KSB7XG5cdCAgbW9kYWxFbC5tb2RhbCgnaGlkZScpO1xuXHQgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKHJlc3VsdC5yZWRpcmVjdF91cmwpO1xuXHR9XG4gICAgICB9KTtcbiAgICAgIFxuICAgIH0pO1xuICAgIFxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgXG4gICQoXCIuYWpheC1wb3N0XCIpLm9uKFwiY2xpY2tcIiwgZnVuY3Rpb24oZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgc2VsZWN0X2VsID0gJChcIiNcIit0aGlzLmRhdGFzZXQuc2VsZWN0KS5maXJzdCgpO1xuICAgIHZhciBsaXN0Z3JvdXBfZWwgPSAkKFwiI1wiK3RoaXMuZGF0YXNldC5saXN0Z3JvdXApLmZpcnN0KCk7XG4gICAgdmFyIHVybCA9IHRoaXMuZGF0YXNldC51cmw7XG4gICAgdmFyIGRhdGEgPSBKU09OLnN0cmluZ2lmeSh7XCJpZHNcIjogc2VsZWN0X2VsLnZhbCgpfSk7XG4gICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHR2YXIgaTtcblx0aWYgKHJlc3VsdC5lbGVtZW50cyAhPSBudWxsKSB7XG5cdCAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5lbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHQgICAgdmFyIG5ld0l0ZW0gPSBgXG5cdFx0PGEgaHJlZj1cIiNcIiBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBjbGVhcmZpeFwiPlxuXHRcdDxzcGFuIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1ib29rXCI+PC9zcGFuPlxuXHRcdCR7cmVzdWx0LmVsZW1lbnRzW2ldLk5hbWV9XG5cdFx0PHNwYW4gY2xhc3M9XCJwdWxsLXJpZ2h0XCI+XG5cdFx0PGJ1dHRvbiBkYXRhLXVybD1cIi8ke3Jlc3VsdC5uYW1lMX0vJHtyZXN1bHQuaWQxfS8ke3Jlc3VsdC5uYW1lMn0vJHtyZXN1bHQuaWQyW2ldfS9kZWxldGVcIiBjbGFzcz1cImJ0biBidG4teHMgYnRuLXdhcm5pbmcga2FybWVuLWFqYXgtZGVsZXRlXCI+XG5cdFx0PHNwYW4gY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXRyYXNoXCI+PC9zcGFuPlxuXHRcdDwvYnV0dG9uPlxuXHQgICAgICA8L3NwYW4+XG5cdCAgICAgIGA7XG5cdCAgICAkKGxpc3Rncm91cF9lbCkuYXBwZW5kKG5ld0l0ZW0pO1xuXHQgICAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblx0ICB9XG5cdH1cbiAgICAgIFxuICAgICAgfSxcbiAgICAgIFwianNvblwiXG4gICAgKTtcblxuICAgIHNlbGVjdF9lbC52YWwoJ2RlZmF1bHQnKTtcbiAgICBzZWxlY3RfZWwuc2VsZWN0cGlja2VyKFwicmVmcmVzaFwiKTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gICAgXG4gIH0pO1xuXG4gICQoXCIua2FybWVuLWFqYXgtZGVsZXRlLXJlbGF0aW9uXCIpLm9uKFwiY2xpY2tcIiwgZGVsZXRlUmVsYXRpb25IYW5kbGVyKTtcbiAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblxufSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAgKiBCb290c3RyYXAgdjQuMS4zIChodHRwczovL2dldGJvb3RzdHJhcC5jb20vKVxuICAqIENvcHlyaWdodCAyMDExLTIwMTggVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCByZXF1aXJlKCdqcXVlcnknKSwgcmVxdWlyZSgncG9wcGVyLmpzJykpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cycsICdqcXVlcnknLCAncG9wcGVyLmpzJ10sIGZhY3RvcnkpIDpcbiAgKGZhY3RvcnkoKGdsb2JhbC5ib290c3RyYXAgPSB7fSksZ2xvYmFsLmpRdWVyeSxnbG9iYWwuUG9wcGVyKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cywkLFBvcHBlcikgeyAndXNlIHN0cmljdCc7XG5cbiAgJCA9ICQgJiYgJC5oYXNPd25Qcm9wZXJ0eSgnZGVmYXVsdCcpID8gJFsnZGVmYXVsdCddIDogJDtcbiAgUG9wcGVyID0gUG9wcGVyICYmIFBvcHBlci5oYXNPd25Qcm9wZXJ0eSgnZGVmYXVsdCcpID8gUG9wcGVyWydkZWZhdWx0J10gOiBQb3BwZXI7XG5cbiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07XG4gICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7XG4gICAgICBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHtcbiAgICBpZiAocHJvdG9Qcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTtcbiAgICBpZiAoc3RhdGljUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7XG4gICAgcmV0dXJuIENvbnN0cnVjdG9yO1xuICB9XG5cbiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnR5KG9iaiwga2V5LCB2YWx1ZSkge1xuICAgIGlmIChrZXkgaW4gb2JqKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgb2JqW2tleV0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gb2JqO1xuICB9XG5cbiAgZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307XG4gICAgICB2YXIgb3duS2V5cyA9IE9iamVjdC5rZXlzKHNvdXJjZSk7XG5cbiAgICAgIGlmICh0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBvd25LZXlzID0gb3duS2V5cy5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzb3VyY2UpLmZpbHRlcihmdW5jdGlvbiAoc3ltKSB7XG4gICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBzeW0pLmVudW1lcmFibGU7XG4gICAgICAgIH0pKTtcbiAgICAgIH1cblxuICAgICAgb3duS2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgX2RlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBzb3VyY2Vba2V5XSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9XG5cbiAgZnVuY3Rpb24gX2luaGVyaXRzTG9vc2Uoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHtcbiAgICBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTtcbiAgICBzdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBzdWJDbGFzcztcbiAgICBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogdXRpbC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICB2YXIgVXRpbCA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogUHJpdmF0ZSBUcmFuc2l0aW9uRW5kIEhlbHBlcnNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgVFJBTlNJVElPTl9FTkQgPSAndHJhbnNpdGlvbmVuZCc7XG4gICAgdmFyIE1BWF9VSUQgPSAxMDAwMDAwO1xuICAgIHZhciBNSUxMSVNFQ09ORFNfTVVMVElQTElFUiA9IDEwMDA7IC8vIFNob3V0b3V0IEFuZ3VzQ3JvbGwgKGh0dHBzOi8vZ29vLmdsL3B4d1FHcClcblxuICAgIGZ1bmN0aW9uIHRvVHlwZShvYmopIHtcbiAgICAgIHJldHVybiB7fS50b1N0cmluZy5jYWxsKG9iaikubWF0Y2goL1xccyhbYS16XSspL2kpWzFdLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U3BlY2lhbFRyYW5zaXRpb25FbmRFdmVudCgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGJpbmRUeXBlOiBUUkFOU0lUSU9OX0VORCxcbiAgICAgICAgZGVsZWdhdGVUeXBlOiBUUkFOU0lUSU9OX0VORCxcbiAgICAgICAgaGFuZGxlOiBmdW5jdGlvbiBoYW5kbGUoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoJCQkMShldmVudC50YXJnZXQpLmlzKHRoaXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gZXZlbnQuaGFuZGxlT2JqLmhhbmRsZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBwcmVmZXItcmVzdC1wYXJhbXNcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmaW5lZFxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyYW5zaXRpb25FbmRFbXVsYXRvcihkdXJhdGlvbikge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICAgICAgJCQkMSh0aGlzKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgfSk7XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgICAgICBVdGlsLnRyaWdnZXJUcmFuc2l0aW9uRW5kKF90aGlzKTtcbiAgICAgICAgfVxuICAgICAgfSwgZHVyYXRpb24pO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0VHJhbnNpdGlvbkVuZFN1cHBvcnQoKSB7XG4gICAgICAkJCQxLmZuLmVtdWxhdGVUcmFuc2l0aW9uRW5kID0gdHJhbnNpdGlvbkVuZEVtdWxhdG9yO1xuICAgICAgJCQkMS5ldmVudC5zcGVjaWFsW1V0aWwuVFJBTlNJVElPTl9FTkRdID0gZ2V0U3BlY2lhbFRyYW5zaXRpb25FbmRFdmVudCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIFB1YmxpYyBVdGlsIEFwaVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgIHZhciBVdGlsID0ge1xuICAgICAgVFJBTlNJVElPTl9FTkQ6ICdic1RyYW5zaXRpb25FbmQnLFxuICAgICAgZ2V0VUlEOiBmdW5jdGlvbiBnZXRVSUQocHJlZml4KSB7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICAgIHByZWZpeCArPSB+fihNYXRoLnJhbmRvbSgpICogTUFYX1VJRCk7IC8vIFwifn5cIiBhY3RzIGxpa2UgYSBmYXN0ZXIgTWF0aC5mbG9vcigpIGhlcmVcbiAgICAgICAgfSB3aGlsZSAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocHJlZml4KSk7XG5cbiAgICAgICAgcmV0dXJuIHByZWZpeDtcbiAgICAgIH0sXG4gICAgICBnZXRTZWxlY3RvckZyb21FbGVtZW50OiBmdW5jdGlvbiBnZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtdGFyZ2V0Jyk7XG5cbiAgICAgICAgaWYgKCFzZWxlY3RvciB8fCBzZWxlY3RvciA9PT0gJyMnKSB7XG4gICAgICAgICAgc2VsZWN0b3IgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnaHJlZicpIHx8ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgPyBzZWxlY3RvciA6IG51bGw7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQ6IGZ1bmN0aW9uIGdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0gLy8gR2V0IHRyYW5zaXRpb24tZHVyYXRpb24gb2YgdGhlIGVsZW1lbnRcblxuXG4gICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSAkJCQxKGVsZW1lbnQpLmNzcygndHJhbnNpdGlvbi1kdXJhdGlvbicpO1xuICAgICAgICB2YXIgZmxvYXRUcmFuc2l0aW9uRHVyYXRpb24gPSBwYXJzZUZsb2F0KHRyYW5zaXRpb25EdXJhdGlvbik7IC8vIFJldHVybiAwIGlmIGVsZW1lbnQgb3IgdHJhbnNpdGlvbiBkdXJhdGlvbiBpcyBub3QgZm91bmRcblxuICAgICAgICBpZiAoIWZsb2F0VHJhbnNpdGlvbkR1cmF0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0gLy8gSWYgbXVsdGlwbGUgZHVyYXRpb25zIGFyZSBkZWZpbmVkLCB0YWtlIHRoZSBmaXJzdFxuXG5cbiAgICAgICAgdHJhbnNpdGlvbkR1cmF0aW9uID0gdHJhbnNpdGlvbkR1cmF0aW9uLnNwbGl0KCcsJylbMF07XG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHRyYW5zaXRpb25EdXJhdGlvbikgKiBNSUxMSVNFQ09ORFNfTVVMVElQTElFUjtcbiAgICAgIH0sXG4gICAgICByZWZsb3c6IGZ1bmN0aW9uIHJlZmxvdyhlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgIH0sXG4gICAgICB0cmlnZ2VyVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gdHJpZ2dlclRyYW5zaXRpb25FbmQoZWxlbWVudCkge1xuICAgICAgICAkJCQxKGVsZW1lbnQpLnRyaWdnZXIoVFJBTlNJVElPTl9FTkQpO1xuICAgICAgfSxcbiAgICAgIC8vIFRPRE86IFJlbW92ZSBpbiB2NVxuICAgICAgc3VwcG9ydHNUcmFuc2l0aW9uRW5kOiBmdW5jdGlvbiBzdXBwb3J0c1RyYW5zaXRpb25FbmQoKSB7XG4gICAgICAgIHJldHVybiBCb29sZWFuKFRSQU5TSVRJT05fRU5EKTtcbiAgICAgIH0sXG4gICAgICBpc0VsZW1lbnQ6IGZ1bmN0aW9uIGlzRWxlbWVudChvYmopIHtcbiAgICAgICAgcmV0dXJuIChvYmpbMF0gfHwgb2JqKS5ub2RlVHlwZTtcbiAgICAgIH0sXG4gICAgICB0eXBlQ2hlY2tDb25maWc6IGZ1bmN0aW9uIHR5cGVDaGVja0NvbmZpZyhjb21wb25lbnROYW1lLCBjb25maWcsIGNvbmZpZ1R5cGVzKSB7XG4gICAgICAgIGZvciAodmFyIHByb3BlcnR5IGluIGNvbmZpZ1R5cGVzKSB7XG4gICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChjb25maWdUeXBlcywgcHJvcGVydHkpKSB7XG4gICAgICAgICAgICB2YXIgZXhwZWN0ZWRUeXBlcyA9IGNvbmZpZ1R5cGVzW3Byb3BlcnR5XTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGNvbmZpZ1twcm9wZXJ0eV07XG4gICAgICAgICAgICB2YXIgdmFsdWVUeXBlID0gdmFsdWUgJiYgVXRpbC5pc0VsZW1lbnQodmFsdWUpID8gJ2VsZW1lbnQnIDogdG9UeXBlKHZhbHVlKTtcblxuICAgICAgICAgICAgaWYgKCFuZXcgUmVnRXhwKGV4cGVjdGVkVHlwZXMpLnRlc3QodmFsdWVUeXBlKSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoY29tcG9uZW50TmFtZS50b1VwcGVyQ2FzZSgpICsgXCI6IFwiICsgKFwiT3B0aW9uIFxcXCJcIiArIHByb3BlcnR5ICsgXCJcXFwiIHByb3ZpZGVkIHR5cGUgXFxcIlwiICsgdmFsdWVUeXBlICsgXCJcXFwiIFwiKSArIChcImJ1dCBleHBlY3RlZCB0eXBlIFxcXCJcIiArIGV4cGVjdGVkVHlwZXMgKyBcIlxcXCIuXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIHNldFRyYW5zaXRpb25FbmRTdXBwb3J0KCk7XG4gICAgcmV0dXJuIFV0aWw7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogYWxlcnQuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIEFsZXJ0ID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdhbGVydCc7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5hbGVydCc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIERJU01JU1M6ICdbZGF0YS1kaXNtaXNzPVwiYWxlcnRcIl0nXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBDTE9TRTogXCJjbG9zZVwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xPU0VEOiBcImNsb3NlZFwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIEFMRVJUOiAnYWxlcnQnLFxuICAgICAgRkFERTogJ2ZhZGUnLFxuICAgICAgU0hPVzogJ3Nob3cnXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgQWxlcnQgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBBbGVydChlbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IEFsZXJ0LnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8uY2xvc2UgPSBmdW5jdGlvbiBjbG9zZShlbGVtZW50KSB7XG4gICAgICAgIHZhciByb290RWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICByb290RWxlbWVudCA9IHRoaXMuX2dldFJvb3RFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGN1c3RvbUV2ZW50ID0gdGhpcy5fdHJpZ2dlckNsb3NlRXZlbnQocm9vdEVsZW1lbnQpO1xuXG4gICAgICAgIGlmIChjdXN0b21FdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3JlbW92ZUVsZW1lbnQocm9vdEVsZW1lbnQpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldFJvb3RFbGVtZW50ID0gZnVuY3Rpb24gX2dldFJvb3RFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICB2YXIgcGFyZW50ID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgcGFyZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgIHBhcmVudCA9ICQkJDEoZWxlbWVudCkuY2xvc2VzdChcIi5cIiArIENsYXNzTmFtZS5BTEVSVClbMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFyZW50O1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl90cmlnZ2VyQ2xvc2VFdmVudCA9IGZ1bmN0aW9uIF90cmlnZ2VyQ2xvc2VFdmVudChlbGVtZW50KSB7XG4gICAgICAgIHZhciBjbG9zZUV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5DTE9TRSk7XG4gICAgICAgICQkJDEoZWxlbWVudCkudHJpZ2dlcihjbG9zZUV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGNsb3NlRXZlbnQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3JlbW92ZUVsZW1lbnQgPSBmdW5jdGlvbiBfcmVtb3ZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgJCQkMShlbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgaWYgKCEkJCQxKGVsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lFbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgICQkJDEoZWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5fZGVzdHJveUVsZW1lbnQoZWxlbWVudCwgZXZlbnQpO1xuICAgICAgICB9KS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9kZXN0cm95RWxlbWVudCA9IGZ1bmN0aW9uIF9kZXN0cm95RWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgICQkJDEoZWxlbWVudCkuZGV0YWNoKCkudHJpZ2dlcihFdmVudC5DTE9TRUQpLnJlbW92ZSgpO1xuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgQWxlcnQuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciAkZWxlbWVudCA9ICQkJDEodGhpcyk7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkZWxlbWVudC5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgZGF0YSA9IG5ldyBBbGVydCh0aGlzKTtcbiAgICAgICAgICAgICRlbGVtZW50LmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjb25maWcgPT09ICdjbG9zZScpIHtcbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSh0aGlzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgQWxlcnQuX2hhbmRsZURpc21pc3MgPSBmdW5jdGlvbiBfaGFuZGxlRGlzbWlzcyhhbGVydEluc3RhbmNlKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYWxlcnRJbnN0YW5jZS5jbG9zZSh0aGlzKTtcbiAgICAgICAgfTtcbiAgICAgIH07XG5cbiAgICAgIF9jcmVhdGVDbGFzcyhBbGVydCwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIEFsZXJ0O1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuRElTTUlTUywgQWxlcnQuX2hhbmRsZURpc21pc3MobmV3IEFsZXJ0KCkpKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBBbGVydC5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBBbGVydDtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gQWxlcnQuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIEFsZXJ0O1xuICB9KCQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IGJ1dHRvbi5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICB2YXIgQnV0dG9uID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdidXR0b24nO1xuICAgIHZhciBWRVJTSU9OID0gJzQuMS4zJztcbiAgICB2YXIgREFUQV9LRVkgPSAnYnMuYnV0dG9uJztcbiAgICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIEFDVElWRTogJ2FjdGl2ZScsXG4gICAgICBCVVRUT046ICdidG4nLFxuICAgICAgRk9DVVM6ICdmb2N1cydcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIERBVEFfVE9HR0xFX0NBUlJPVDogJ1tkYXRhLXRvZ2dsZV49XCJidXR0b25cIl0nLFxuICAgICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJidXR0b25zXCJdJyxcbiAgICAgIElOUFVUOiAnaW5wdXQnLFxuICAgICAgQUNUSVZFOiAnLmFjdGl2ZScsXG4gICAgICBCVVRUT046ICcuYnRuJ1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICAgIEZPQ1VTX0JMVVJfREFUQV9BUEk6IFwiZm9jdXNcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSArIFwiIFwiICsgKFwiYmx1clwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZKVxuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIEJ1dHRvbiA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIEJ1dHRvbihlbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IEJ1dHRvbi5wcm90b3R5cGU7XG5cbiAgICAgIC8vIFB1YmxpY1xuICAgICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAgICAgdmFyIHRyaWdnZXJDaGFuZ2VFdmVudCA9IHRydWU7XG4gICAgICAgIHZhciBhZGRBcmlhUHJlc3NlZCA9IHRydWU7XG4gICAgICAgIHZhciByb290RWxlbWVudCA9ICQkJDEodGhpcy5fZWxlbWVudCkuY2xvc2VzdChTZWxlY3Rvci5EQVRBX1RPR0dMRSlbMF07XG5cbiAgICAgICAgaWYgKHJvb3RFbGVtZW50KSB7XG4gICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLklOUFVUKTtcblxuICAgICAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICAgICAgaWYgKGlucHV0LnR5cGUgPT09ICdyYWRpbycpIHtcbiAgICAgICAgICAgICAgaWYgKGlucHV0LmNoZWNrZWQgJiYgdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ2xhc3NOYW1lLkFDVElWRSkpIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyQ2hhbmdlRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aXZlRWxlbWVudCA9IHJvb3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuQUNUSVZFKTtcblxuICAgICAgICAgICAgICAgIGlmIChhY3RpdmVFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAkJCQxKGFjdGl2ZUVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHJpZ2dlckNoYW5nZUV2ZW50KSB7XG4gICAgICAgICAgICAgIGlmIChpbnB1dC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgfHwgcm9vdEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpIHx8IGlucHV0LmNsYXNzTGlzdC5jb250YWlucygnZGlzYWJsZWQnKSB8fCByb290RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gIXRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgICAgICAkJCQxKGlucHV0KS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgICAgIGFkZEFyaWFQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFkZEFyaWFQcmVzc2VkKSB7XG4gICAgICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtcHJlc3NlZCcsICF0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhDbGFzc05hbWUuQUNUSVZFKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHJpZ2dlckNoYW5nZUV2ZW50KSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIEJ1dHRvbi5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IEJ1dHRvbih0aGlzKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNvbmZpZyA9PT0gJ3RvZ2dsZScpIHtcbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoQnV0dG9uLCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gQnV0dG9uO1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEVfQ0FSUk9ULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB2YXIgYnV0dG9uID0gZXZlbnQudGFyZ2V0O1xuXG4gICAgICBpZiAoISQkJDEoYnV0dG9uKS5oYXNDbGFzcyhDbGFzc05hbWUuQlVUVE9OKSkge1xuICAgICAgICBidXR0b24gPSAkJCQxKGJ1dHRvbikuY2xvc2VzdChTZWxlY3Rvci5CVVRUT04pO1xuICAgICAgfVxuXG4gICAgICBCdXR0b24uX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEoYnV0dG9uKSwgJ3RvZ2dsZScpO1xuICAgIH0pLm9uKEV2ZW50LkZPQ1VTX0JMVVJfREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfVE9HR0xFX0NBUlJPVCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICB2YXIgYnV0dG9uID0gJCQkMShldmVudC50YXJnZXQpLmNsb3Nlc3QoU2VsZWN0b3IuQlVUVE9OKVswXTtcbiAgICAgICQkJDEoYnV0dG9uKS50b2dnbGVDbGFzcyhDbGFzc05hbWUuRk9DVVMsIC9eZm9jdXMoaW4pPyQvLnRlc3QoZXZlbnQudHlwZSkpO1xuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IEJ1dHRvbi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBCdXR0b247XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIEJ1dHRvbi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gQnV0dG9uO1xuICB9KCQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IGNhcm91c2VsLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBDYXJvdXNlbCA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ29uc3RhbnRzXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG4gICAgdmFyIE5BTUUgPSAnY2Fyb3VzZWwnO1xuICAgIHZhciBWRVJTSU9OID0gJzQuMS4zJztcbiAgICB2YXIgREFUQV9LRVkgPSAnYnMuY2Fyb3VzZWwnO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgICB2YXIgQVJST1dfTEVGVF9LRVlDT0RFID0gMzc7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIGxlZnQgYXJyb3cga2V5XG5cbiAgICB2YXIgQVJST1dfUklHSFRfS0VZQ09ERSA9IDM5OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciByaWdodCBhcnJvdyBrZXlcblxuICAgIHZhciBUT1VDSEVWRU5UX0NPTVBBVF9XQUlUID0gNTAwOyAvLyBUaW1lIGZvciBtb3VzZSBjb21wYXQgZXZlbnRzIHRvIGZpcmUgYWZ0ZXIgdG91Y2hcblxuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgaW50ZXJ2YWw6IDUwMDAsXG4gICAgICBrZXlib2FyZDogdHJ1ZSxcbiAgICAgIHNsaWRlOiBmYWxzZSxcbiAgICAgIHBhdXNlOiAnaG92ZXInLFxuICAgICAgd3JhcDogdHJ1ZVxuICAgIH07XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgaW50ZXJ2YWw6ICcobnVtYmVyfGJvb2xlYW4pJyxcbiAgICAgIGtleWJvYXJkOiAnYm9vbGVhbicsXG4gICAgICBzbGlkZTogJyhib29sZWFufHN0cmluZyknLFxuICAgICAgcGF1c2U6ICcoc3RyaW5nfGJvb2xlYW4pJyxcbiAgICAgIHdyYXA6ICdib29sZWFuJ1xuICAgIH07XG4gICAgdmFyIERpcmVjdGlvbiA9IHtcbiAgICAgIE5FWFQ6ICduZXh0JyxcbiAgICAgIFBSRVY6ICdwcmV2JyxcbiAgICAgIExFRlQ6ICdsZWZ0JyxcbiAgICAgIFJJR0hUOiAncmlnaHQnXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBTTElERTogXCJzbGlkZVwiICsgRVZFTlRfS0VZLFxuICAgICAgU0xJRDogXCJzbGlkXCIgKyBFVkVOVF9LRVksXG4gICAgICBLRVlET1dOOiBcImtleWRvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIE1PVVNFRU5URVI6IFwibW91c2VlbnRlclwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VMRUFWRTogXCJtb3VzZWxlYXZlXCIgKyBFVkVOVF9LRVksXG4gICAgICBUT1VDSEVORDogXCJ0b3VjaGVuZFwiICsgRVZFTlRfS0VZLFxuICAgICAgTE9BRF9EQVRBX0FQSTogXCJsb2FkXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gICAgfTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgQ0FST1VTRUw6ICdjYXJvdXNlbCcsXG4gICAgICBBQ1RJVkU6ICdhY3RpdmUnLFxuICAgICAgU0xJREU6ICdzbGlkZScsXG4gICAgICBSSUdIVDogJ2Nhcm91c2VsLWl0ZW0tcmlnaHQnLFxuICAgICAgTEVGVDogJ2Nhcm91c2VsLWl0ZW0tbGVmdCcsXG4gICAgICBORVhUOiAnY2Fyb3VzZWwtaXRlbS1uZXh0JyxcbiAgICAgIFBSRVY6ICdjYXJvdXNlbC1pdGVtLXByZXYnLFxuICAgICAgSVRFTTogJ2Nhcm91c2VsLWl0ZW0nXG4gICAgfTtcbiAgICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgICBBQ1RJVkU6ICcuYWN0aXZlJyxcbiAgICAgIEFDVElWRV9JVEVNOiAnLmFjdGl2ZS5jYXJvdXNlbC1pdGVtJyxcbiAgICAgIElURU06ICcuY2Fyb3VzZWwtaXRlbScsXG4gICAgICBORVhUX1BSRVY6ICcuY2Fyb3VzZWwtaXRlbS1uZXh0LCAuY2Fyb3VzZWwtaXRlbS1wcmV2JyxcbiAgICAgIElORElDQVRPUlM6ICcuY2Fyb3VzZWwtaW5kaWNhdG9ycycsXG4gICAgICBEQVRBX1NMSURFOiAnW2RhdGEtc2xpZGVdLCBbZGF0YS1zbGlkZS10b10nLFxuICAgICAgREFUQV9SSURFOiAnW2RhdGEtcmlkZT1cImNhcm91c2VsXCJdJ1xuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIENhcm91c2VsID1cbiAgICAvKiNfX1BVUkVfXyovXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgZnVuY3Rpb24gQ2Fyb3VzZWwoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICAgIHRoaXMuX2l0ZW1zID0gbnVsbDtcbiAgICAgICAgdGhpcy5faW50ZXJ2YWwgPSBudWxsO1xuICAgICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNQYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMudG91Y2hUaW1lb3V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSAkJCQxKGVsZW1lbnQpWzBdO1xuICAgICAgICB0aGlzLl9pbmRpY2F0b3JzRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5JTkRJQ0FUT1JTKTtcblxuICAgICAgICB0aGlzLl9hZGRFdmVudExpc3RlbmVycygpO1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IENhcm91c2VsLnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8ubmV4dCA9IGZ1bmN0aW9uIG5leHQoKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgICAgdGhpcy5fc2xpZGUoRGlyZWN0aW9uLk5FWFQpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8ubmV4dFdoZW5WaXNpYmxlID0gZnVuY3Rpb24gbmV4dFdoZW5WaXNpYmxlKCkge1xuICAgICAgICAvLyBEb24ndCBjYWxsIG5leHQgd2hlbiB0aGUgcGFnZSBpc24ndCB2aXNpYmxlXG4gICAgICAgIC8vIG9yIHRoZSBjYXJvdXNlbCBvciBpdHMgcGFyZW50IGlzbid0IHZpc2libGVcbiAgICAgICAgaWYgKCFkb2N1bWVudC5oaWRkZW4gJiYgJCQkMSh0aGlzLl9lbGVtZW50KS5pcygnOnZpc2libGUnKSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmNzcygndmlzaWJpbGl0eScpICE9PSAnaGlkZGVuJykge1xuICAgICAgICAgIHRoaXMubmV4dCgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8ucHJldiA9IGZ1bmN0aW9uIHByZXYoKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgICAgdGhpcy5fc2xpZGUoRGlyZWN0aW9uLlBSRVYpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8ucGF1c2UgPSBmdW5jdGlvbiBwYXVzZShldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50KSB7XG4gICAgICAgICAgdGhpcy5faXNQYXVzZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5ORVhUX1BSRVYpKSB7XG4gICAgICAgICAgVXRpbC50cmlnZ2VyVHJhbnNpdGlvbkVuZCh0aGlzLl9lbGVtZW50KTtcbiAgICAgICAgICB0aGlzLmN5Y2xlKHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLl9pbnRlcnZhbCk7XG4gICAgICAgIHRoaXMuX2ludGVydmFsID0gbnVsbDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5jeWNsZSA9IGZ1bmN0aW9uIGN5Y2xlKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgICB0aGlzLl9pc1BhdXNlZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2ludGVydmFsKSB7XG4gICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLl9pbnRlcnZhbCk7XG4gICAgICAgICAgdGhpcy5faW50ZXJ2YWwgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5pbnRlcnZhbCAmJiAhdGhpcy5faXNQYXVzZWQpIHtcbiAgICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IHNldEludGVydmFsKChkb2N1bWVudC52aXNpYmlsaXR5U3RhdGUgPyB0aGlzLm5leHRXaGVuVmlzaWJsZSA6IHRoaXMubmV4dCkuYmluZCh0aGlzKSwgdGhpcy5fY29uZmlnLmludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnRvID0gZnVuY3Rpb24gdG8oaW5kZXgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLkFDVElWRV9JVEVNKTtcblxuICAgICAgICB2YXIgYWN0aXZlSW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgodGhpcy5fYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgaWYgKGluZGV4ID4gdGhpcy5faXRlbXMubGVuZ3RoIC0gMSB8fCBpbmRleCA8IDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbmUoRXZlbnQuU0xJRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzLnRvKGluZGV4KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWN0aXZlSW5kZXggPT09IGluZGV4KSB7XG4gICAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgICAgIHRoaXMuY3ljbGUoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGlyZWN0aW9uID0gaW5kZXggPiBhY3RpdmVJbmRleCA/IERpcmVjdGlvbi5ORVhUIDogRGlyZWN0aW9uLlBSRVY7XG5cbiAgICAgICAgdGhpcy5fc2xpZGUoZGlyZWN0aW9uLCB0aGlzLl9pdGVtc1tpbmRleF0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFVkVOVF9LRVkpO1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICB0aGlzLl9pdGVtcyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2lzUGF1c2VkID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gbnVsbDtcbiAgICAgICAgdGhpcy5fYWN0aXZlRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2luZGljYXRvcnNFbGVtZW50ID0gbnVsbDtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIERlZmF1bHQsIGNvbmZpZyk7XG4gICAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgRGVmYXVsdFR5cGUpO1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9hZGRFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uIF9hZGRFdmVudExpc3RlbmVycygpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5rZXlib2FyZCkge1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuS0VZRE9XTiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMyLl9rZXlkb3duKGV2ZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9jb25maWcucGF1c2UgPT09ICdob3ZlcicpIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50Lk1PVVNFRU5URVIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzMi5wYXVzZShldmVudCk7XG4gICAgICAgICAgfSkub24oRXZlbnQuTU9VU0VMRUFWRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMyLmN5Y2xlKGV2ZW50KTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgIC8vIElmIGl0J3MgYSB0b3VjaC1lbmFibGVkIGRldmljZSwgbW91c2VlbnRlci9sZWF2ZSBhcmUgZmlyZWQgYXNcbiAgICAgICAgICAgIC8vIHBhcnQgb2YgdGhlIG1vdXNlIGNvbXBhdGliaWxpdHkgZXZlbnRzIG9uIGZpcnN0IHRhcCAtIHRoZSBjYXJvdXNlbFxuICAgICAgICAgICAgLy8gd291bGQgc3RvcCBjeWNsaW5nIHVudGlsIHVzZXIgdGFwcGVkIG91dCBvZiBpdDtcbiAgICAgICAgICAgIC8vIGhlcmUsIHdlIGxpc3RlbiBmb3IgdG91Y2hlbmQsIGV4cGxpY2l0bHkgcGF1c2UgdGhlIGNhcm91c2VsXG4gICAgICAgICAgICAvLyAoYXMgaWYgaXQncyB0aGUgc2Vjb25kIHRpbWUgd2UgdGFwIG9uIGl0LCBtb3VzZWVudGVyIGNvbXBhdCBldmVudFxuICAgICAgICAgICAgLy8gaXMgTk9UIGZpcmVkKSBhbmQgYWZ0ZXIgYSB0aW1lb3V0ICh0byBhbGxvdyBmb3IgbW91c2UgY29tcGF0aWJpbGl0eVxuICAgICAgICAgICAgLy8gZXZlbnRzIHRvIGZpcmUpIHdlIGV4cGxpY2l0bHkgcmVzdGFydCBjeWNsaW5nXG4gICAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50LlRPVUNIRU5ELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIF90aGlzMi5wYXVzZSgpO1xuXG4gICAgICAgICAgICAgIGlmIChfdGhpczIudG91Y2hUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KF90aGlzMi50b3VjaFRpbWVvdXQpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgX3RoaXMyLnRvdWNoVGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzMi5jeWNsZShldmVudCk7XG4gICAgICAgICAgICAgIH0sIFRPVUNIRVZFTlRfQ09NUEFUX1dBSVQgKyBfdGhpczIuX2NvbmZpZy5pbnRlcnZhbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fa2V5ZG93biA9IGZ1bmN0aW9uIF9rZXlkb3duKGV2ZW50KSB7XG4gICAgICAgIGlmICgvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAoZXZlbnQud2hpY2gpIHtcbiAgICAgICAgICBjYXNlIEFSUk9XX0xFRlRfS0VZQ09ERTpcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLnByZXYoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSBBUlJPV19SSUdIVF9LRVlDT0RFOlxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMubmV4dCgpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldEl0ZW1JbmRleCA9IGZ1bmN0aW9uIF9nZXRJdGVtSW5kZXgoZWxlbWVudCkge1xuICAgICAgICB0aGlzLl9pdGVtcyA9IGVsZW1lbnQgJiYgZWxlbWVudC5wYXJlbnROb2RlID8gW10uc2xpY2UuY2FsbChlbGVtZW50LnBhcmVudE5vZGUucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5JVEVNKSkgOiBbXTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2l0ZW1zLmluZGV4T2YoZWxlbWVudCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldEl0ZW1CeURpcmVjdGlvbiA9IGZ1bmN0aW9uIF9nZXRJdGVtQnlEaXJlY3Rpb24oZGlyZWN0aW9uLCBhY3RpdmVFbGVtZW50KSB7XG4gICAgICAgIHZhciBpc05leHREaXJlY3Rpb24gPSBkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5ORVhUO1xuICAgICAgICB2YXIgaXNQcmV2RGlyZWN0aW9uID0gZGlyZWN0aW9uID09PSBEaXJlY3Rpb24uUFJFVjtcblxuICAgICAgICB2YXIgYWN0aXZlSW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgoYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgdmFyIGxhc3RJdGVtSW5kZXggPSB0aGlzLl9pdGVtcy5sZW5ndGggLSAxO1xuICAgICAgICB2YXIgaXNHb2luZ1RvV3JhcCA9IGlzUHJldkRpcmVjdGlvbiAmJiBhY3RpdmVJbmRleCA9PT0gMCB8fCBpc05leHREaXJlY3Rpb24gJiYgYWN0aXZlSW5kZXggPT09IGxhc3RJdGVtSW5kZXg7XG5cbiAgICAgICAgaWYgKGlzR29pbmdUb1dyYXAgJiYgIXRoaXMuX2NvbmZpZy53cmFwKSB7XG4gICAgICAgICAgcmV0dXJuIGFjdGl2ZUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGVsdGEgPSBkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5QUkVWID8gLTEgOiAxO1xuICAgICAgICB2YXIgaXRlbUluZGV4ID0gKGFjdGl2ZUluZGV4ICsgZGVsdGEpICUgdGhpcy5faXRlbXMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gaXRlbUluZGV4ID09PSAtMSA/IHRoaXMuX2l0ZW1zW3RoaXMuX2l0ZW1zLmxlbmd0aCAtIDFdIDogdGhpcy5faXRlbXNbaXRlbUluZGV4XTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fdHJpZ2dlclNsaWRlRXZlbnQgPSBmdW5jdGlvbiBfdHJpZ2dlclNsaWRlRXZlbnQocmVsYXRlZFRhcmdldCwgZXZlbnREaXJlY3Rpb25OYW1lKSB7XG4gICAgICAgIHZhciB0YXJnZXRJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleChyZWxhdGVkVGFyZ2V0KTtcblxuICAgICAgICB2YXIgZnJvbUluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5BQ1RJVkVfSVRFTSkpO1xuXG4gICAgICAgIHZhciBzbGlkZUV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TTElERSwge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHJlbGF0ZWRUYXJnZXQsXG4gICAgICAgICAgZGlyZWN0aW9uOiBldmVudERpcmVjdGlvbk5hbWUsXG4gICAgICAgICAgZnJvbTogZnJvbUluZGV4LFxuICAgICAgICAgIHRvOiB0YXJnZXRJbmRleFxuICAgICAgICB9KTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHNsaWRlRXZlbnQpO1xuICAgICAgICByZXR1cm4gc2xpZGVFdmVudDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fc2V0QWN0aXZlSW5kaWNhdG9yRWxlbWVudCA9IGZ1bmN0aW9uIF9zZXRBY3RpdmVJbmRpY2F0b3JFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2luZGljYXRvcnNFbGVtZW50KSB7XG4gICAgICAgICAgdmFyIGluZGljYXRvcnMgPSBbXS5zbGljZS5jYWxsKHRoaXMuX2luZGljYXRvcnNFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuQUNUSVZFKSk7XG4gICAgICAgICAgJCQkMShpbmRpY2F0b3JzKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcblxuICAgICAgICAgIHZhciBuZXh0SW5kaWNhdG9yID0gdGhpcy5faW5kaWNhdG9yc0VsZW1lbnQuY2hpbGRyZW5bdGhpcy5fZ2V0SXRlbUluZGV4KGVsZW1lbnQpXTtcblxuICAgICAgICAgIGlmIChuZXh0SW5kaWNhdG9yKSB7XG4gICAgICAgICAgICAkJCQxKG5leHRJbmRpY2F0b3IpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zbGlkZSA9IGZ1bmN0aW9uIF9zbGlkZShkaXJlY3Rpb24sIGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGFjdGl2ZUVsZW1lbnQgPSB0aGlzLl9lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuQUNUSVZFX0lURU0pO1xuXG4gICAgICAgIHZhciBhY3RpdmVFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgoYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgdmFyIG5leHRFbGVtZW50ID0gZWxlbWVudCB8fCBhY3RpdmVFbGVtZW50ICYmIHRoaXMuX2dldEl0ZW1CeURpcmVjdGlvbihkaXJlY3Rpb24sIGFjdGl2ZUVsZW1lbnQpO1xuXG4gICAgICAgIHZhciBuZXh0RWxlbWVudEluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KG5leHRFbGVtZW50KTtcblxuICAgICAgICB2YXIgaXNDeWNsaW5nID0gQm9vbGVhbih0aGlzLl9pbnRlcnZhbCk7XG4gICAgICAgIHZhciBkaXJlY3Rpb25hbENsYXNzTmFtZTtcbiAgICAgICAgdmFyIG9yZGVyQ2xhc3NOYW1lO1xuICAgICAgICB2YXIgZXZlbnREaXJlY3Rpb25OYW1lO1xuXG4gICAgICAgIGlmIChkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5ORVhUKSB7XG4gICAgICAgICAgZGlyZWN0aW9uYWxDbGFzc05hbWUgPSBDbGFzc05hbWUuTEVGVDtcbiAgICAgICAgICBvcmRlckNsYXNzTmFtZSA9IENsYXNzTmFtZS5ORVhUO1xuICAgICAgICAgIGV2ZW50RGlyZWN0aW9uTmFtZSA9IERpcmVjdGlvbi5MRUZUO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRpcmVjdGlvbmFsQ2xhc3NOYW1lID0gQ2xhc3NOYW1lLlJJR0hUO1xuICAgICAgICAgIG9yZGVyQ2xhc3NOYW1lID0gQ2xhc3NOYW1lLlBSRVY7XG4gICAgICAgICAgZXZlbnREaXJlY3Rpb25OYW1lID0gRGlyZWN0aW9uLlJJR0hUO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5leHRFbGVtZW50ICYmICQkJDEobmV4dEVsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5BQ1RJVkUpKSB7XG4gICAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNsaWRlRXZlbnQgPSB0aGlzLl90cmlnZ2VyU2xpZGVFdmVudChuZXh0RWxlbWVudCwgZXZlbnREaXJlY3Rpb25OYW1lKTtcblxuICAgICAgICBpZiAoc2xpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYWN0aXZlRWxlbWVudCB8fCAhbmV4dEVsZW1lbnQpIHtcbiAgICAgICAgICAvLyBTb21lIHdlaXJkbmVzcyBpcyBoYXBwZW5pbmcsIHNvIHdlIGJhaWxcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSB0cnVlO1xuXG4gICAgICAgIGlmIChpc0N5Y2xpbmcpIHtcbiAgICAgICAgICB0aGlzLnBhdXNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXRBY3RpdmVJbmRpY2F0b3JFbGVtZW50KG5leHRFbGVtZW50KTtcblxuICAgICAgICB2YXIgc2xpZEV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TTElELCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogbmV4dEVsZW1lbnQsXG4gICAgICAgICAgZGlyZWN0aW9uOiBldmVudERpcmVjdGlvbk5hbWUsXG4gICAgICAgICAgZnJvbTogYWN0aXZlRWxlbWVudEluZGV4LFxuICAgICAgICAgIHRvOiBuZXh0RWxlbWVudEluZGV4XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICgkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5TTElERSkpIHtcbiAgICAgICAgICAkJCQxKG5leHRFbGVtZW50KS5hZGRDbGFzcyhvcmRlckNsYXNzTmFtZSk7XG4gICAgICAgICAgVXRpbC5yZWZsb3cobmV4dEVsZW1lbnQpO1xuICAgICAgICAgICQkJDEoYWN0aXZlRWxlbWVudCkuYWRkQ2xhc3MoZGlyZWN0aW9uYWxDbGFzc05hbWUpO1xuICAgICAgICAgICQkJDEobmV4dEVsZW1lbnQpLmFkZENsYXNzKGRpcmVjdGlvbmFsQ2xhc3NOYW1lKTtcbiAgICAgICAgICB2YXIgdHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudChhY3RpdmVFbGVtZW50KTtcbiAgICAgICAgICAkJCQxKGFjdGl2ZUVsZW1lbnQpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkJCQxKG5leHRFbGVtZW50KS5yZW1vdmVDbGFzcyhkaXJlY3Rpb25hbENsYXNzTmFtZSArIFwiIFwiICsgb3JkZXJDbGFzc05hbWUpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFICsgXCIgXCIgKyBvcmRlckNsYXNzTmFtZSArIFwiIFwiICsgZGlyZWN0aW9uYWxDbGFzc05hbWUpO1xuICAgICAgICAgICAgX3RoaXMzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gJCQkMShfdGhpczMuX2VsZW1lbnQpLnRyaWdnZXIoc2xpZEV2ZW50KTtcbiAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgIH0pLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICAkJCQxKG5leHRFbGVtZW50KS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc2xpZEV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0N5Y2xpbmcpIHtcbiAgICAgICAgICB0aGlzLmN5Y2xlKCk7XG4gICAgICAgIH1cbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIENhcm91c2VsLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIERlZmF1bHQsICQkJDEodGhpcykuZGF0YSgpKTtcblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgX2NvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIF9jb25maWcsIGNvbmZpZyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGFjdGlvbiA9IHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnID8gY29uZmlnIDogX2NvbmZpZy5zbGlkZTtcblxuICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgZGF0YSA9IG5ldyBDYXJvdXNlbCh0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBkYXRhLnRvKGNvbmZpZyk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2FjdGlvbl0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgYWN0aW9uICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2FjdGlvbl0oKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKF9jb25maWcuaW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIGRhdGEucGF1c2UoKTtcbiAgICAgICAgICAgIGRhdGEuY3ljbGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgQ2Fyb3VzZWwuX2RhdGFBcGlDbGlja0hhbmRsZXIgPSBmdW5jdGlvbiBfZGF0YUFwaUNsaWNrSGFuZGxlcihldmVudCkge1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQodGhpcyk7XG5cbiAgICAgICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0YXJnZXQgPSAkJCQxKHNlbGVjdG9yKVswXTtcblxuICAgICAgICBpZiAoIXRhcmdldCB8fCAhJCQkMSh0YXJnZXQpLmhhc0NsYXNzKENsYXNzTmFtZS5DQVJPVVNFTCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgJCQkMSh0YXJnZXQpLmRhdGEoKSwgJCQkMSh0aGlzKS5kYXRhKCkpO1xuXG4gICAgICAgIHZhciBzbGlkZUluZGV4ID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2RhdGEtc2xpZGUtdG8nKTtcblxuICAgICAgICBpZiAoc2xpZGVJbmRleCkge1xuICAgICAgICAgIGNvbmZpZy5pbnRlcnZhbCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEodGFyZ2V0KSwgY29uZmlnKTtcblxuICAgICAgICBpZiAoc2xpZGVJbmRleCkge1xuICAgICAgICAgICQkJDEodGFyZ2V0KS5kYXRhKERBVEFfS0VZKS50byhzbGlkZUluZGV4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoQ2Fyb3VzZWwsIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJEZWZhdWx0XCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBDYXJvdXNlbDtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfU0xJREUsIENhcm91c2VsLl9kYXRhQXBpQ2xpY2tIYW5kbGVyKTtcbiAgICAkJCQxKHdpbmRvdykub24oRXZlbnQuTE9BRF9EQVRBX0FQSSwgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGNhcm91c2VscyA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5EQVRBX1JJREUpKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNhcm91c2Vscy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgJGNhcm91c2VsID0gJCQkMShjYXJvdXNlbHNbaV0pO1xuXG4gICAgICAgIENhcm91c2VsLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkY2Fyb3VzZWwsICRjYXJvdXNlbC5kYXRhKCkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IENhcm91c2VsLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IENhcm91c2VsO1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBDYXJvdXNlbC5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ2Fyb3VzZWw7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogY29sbGFwc2UuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIENvbGxhcHNlID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdjb2xsYXBzZSc7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5jb2xsYXBzZSc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgdG9nZ2xlOiB0cnVlLFxuICAgICAgcGFyZW50OiAnJ1xuICAgIH07XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgdG9nZ2xlOiAnYm9vbGVhbicsXG4gICAgICBwYXJlbnQ6ICcoc3RyaW5nfGVsZW1lbnQpJ1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgU0hPVzogXCJzaG93XCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gICAgfTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgU0hPVzogJ3Nob3cnLFxuICAgICAgQ09MTEFQU0U6ICdjb2xsYXBzZScsXG4gICAgICBDT0xMQVBTSU5HOiAnY29sbGFwc2luZycsXG4gICAgICBDT0xMQVBTRUQ6ICdjb2xsYXBzZWQnXG4gICAgfTtcbiAgICB2YXIgRGltZW5zaW9uID0ge1xuICAgICAgV0lEVEg6ICd3aWR0aCcsXG4gICAgICBIRUlHSFQ6ICdoZWlnaHQnXG4gICAgfTtcbiAgICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgICBBQ1RJVkVTOiAnLnNob3csIC5jb2xsYXBzaW5nJyxcbiAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwiY29sbGFwc2VcIl0nXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgQ29sbGFwc2UgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBDb2xsYXBzZShlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy5fdHJpZ2dlckFycmF5ID0gJCQkMS5tYWtlQXJyYXkoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChcIltkYXRhLXRvZ2dsZT1cXFwiY29sbGFwc2VcXFwiXVtocmVmPVxcXCIjXCIgKyBlbGVtZW50LmlkICsgXCJcXFwiXSxcIiArIChcIltkYXRhLXRvZ2dsZT1cXFwiY29sbGFwc2VcXFwiXVtkYXRhLXRhcmdldD1cXFwiI1wiICsgZWxlbWVudC5pZCArIFwiXFxcIl1cIikpKTtcbiAgICAgICAgdmFyIHRvZ2dsZUxpc3QgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuREFUQV9UT0dHTEUpKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gdG9nZ2xlTGlzdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgIHZhciBlbGVtID0gdG9nZ2xlTGlzdFtpXTtcbiAgICAgICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbSk7XG4gICAgICAgICAgdmFyIGZpbHRlckVsZW1lbnQgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKS5maWx0ZXIoZnVuY3Rpb24gKGZvdW5kRWxlbSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvdW5kRWxlbSA9PT0gZWxlbWVudDtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChzZWxlY3RvciAhPT0gbnVsbCAmJiBmaWx0ZXJFbGVtZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdG9yID0gc2VsZWN0b3I7XG5cbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJBcnJheS5wdXNoKGVsZW0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3BhcmVudCA9IHRoaXMuX2NvbmZpZy5wYXJlbnQgPyB0aGlzLl9nZXRQYXJlbnQoKSA6IG51bGw7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb25maWcucGFyZW50KSB7XG4gICAgICAgICAgdGhpcy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKHRoaXMuX2VsZW1lbnQsIHRoaXMuX3RyaWdnZXJBcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLnRvZ2dsZSkge1xuICAgICAgICAgIHRoaXMudG9nZ2xlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICAgIHZhciBfcHJvdG8gPSBDb2xsYXBzZS5wcm90b3R5cGU7XG5cbiAgICAgIC8vIFB1YmxpY1xuICAgICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAgICAgaWYgKCQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFjdGl2ZXM7XG4gICAgICAgIHZhciBhY3RpdmVzRGF0YTtcblxuICAgICAgICBpZiAodGhpcy5fcGFyZW50KSB7XG4gICAgICAgICAgYWN0aXZlcyA9IFtdLnNsaWNlLmNhbGwodGhpcy5fcGFyZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuQUNUSVZFUykpLmZpbHRlcihmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCdkYXRhLXBhcmVudCcpID09PSBfdGhpcy5fY29uZmlnLnBhcmVudDtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChhY3RpdmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgYWN0aXZlcyA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFjdGl2ZXMpIHtcbiAgICAgICAgICBhY3RpdmVzRGF0YSA9ICQkJDEoYWN0aXZlcykubm90KHRoaXMuX3NlbGVjdG9yKS5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICAgIGlmIChhY3RpdmVzRGF0YSAmJiBhY3RpdmVzRGF0YS5faXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YXJ0RXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNIT1cpO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc3RhcnRFdmVudCk7XG5cbiAgICAgICAgaWYgKHN0YXJ0RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWN0aXZlcykge1xuICAgICAgICAgIENvbGxhcHNlLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkJCQxKGFjdGl2ZXMpLm5vdCh0aGlzLl9zZWxlY3RvciksICdoaWRlJyk7XG5cbiAgICAgICAgICBpZiAoIWFjdGl2ZXNEYXRhKSB7XG4gICAgICAgICAgICAkJCQxKGFjdGl2ZXMpLmRhdGEoREFUQV9LRVksIG51bGwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkaW1lbnNpb24gPSB0aGlzLl9nZXREaW1lbnNpb24oKTtcblxuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTRSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNJTkcpO1xuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAwO1xuXG4gICAgICAgIGlmICh0aGlzLl90cmlnZ2VyQXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl90cmlnZ2VyQXJyYXkpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTRUQpLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0VHJhbnNpdGlvbmluZyh0cnVlKTtcblxuICAgICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgICAkJCQxKF90aGlzLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS5hZGRDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAgICAgX3RoaXMuX2VsZW1lbnQuc3R5bGVbZGltZW5zaW9uXSA9ICcnO1xuXG4gICAgICAgICAgX3RoaXMuc2V0VHJhbnNpdGlvbmluZyhmYWxzZSk7XG5cbiAgICAgICAgICAkJCQxKF90aGlzLl9lbGVtZW50KS50cmlnZ2VyKEV2ZW50LlNIT1dOKTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgY2FwaXRhbGl6ZWREaW1lbnNpb24gPSBkaW1lbnNpb25bMF0udG9VcHBlckNhc2UoKSArIGRpbWVuc2lvbi5zbGljZSgxKTtcbiAgICAgICAgdmFyIHNjcm9sbFNpemUgPSBcInNjcm9sbFwiICsgY2FwaXRhbGl6ZWREaW1lbnNpb247XG4gICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gdGhpcy5fZWxlbWVudFtzY3JvbGxTaXplXSArIFwicHhcIjtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5oaWRlID0gZnVuY3Rpb24gaGlkZSgpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzVHJhbnNpdGlvbmluZyB8fCAhJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3RhcnRFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuSElERSk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzdGFydEV2ZW50KTtcblxuICAgICAgICBpZiAoc3RhcnRFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkaW1lbnNpb24gPSB0aGlzLl9nZXREaW1lbnNpb24oKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSB0aGlzLl9lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpW2RpbWVuc2lvbl0gKyBcInB4XCI7XG4gICAgICAgIFV0aWwucmVmbG93KHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLmFkZENsYXNzKENsYXNzTmFtZS5DT0xMQVBTSU5HKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0UpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcbiAgICAgICAgdmFyIHRyaWdnZXJBcnJheUxlbmd0aCA9IHRoaXMuX3RyaWdnZXJBcnJheS5sZW5ndGg7XG5cbiAgICAgICAgaWYgKHRyaWdnZXJBcnJheUxlbmd0aCA+IDApIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyaWdnZXJBcnJheUxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJpZ2dlciA9IHRoaXMuX3RyaWdnZXJBcnJheVtpXTtcbiAgICAgICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0cmlnZ2VyKTtcblxuICAgICAgICAgICAgaWYgKHNlbGVjdG9yICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgIHZhciAkZWxlbSA9ICQkJDEoW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSkpO1xuXG4gICAgICAgICAgICAgIGlmICghJGVsZW0uaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgICAgICAgJCQkMSh0cmlnZ2VyKS5hZGRDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0VEKS5hdHRyKCdhcmlhLWV4cGFuZGVkJywgZmFsc2UpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRUcmFuc2l0aW9uaW5nKHRydWUpO1xuXG4gICAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICAgIF90aGlzMi5zZXRUcmFuc2l0aW9uaW5nKGZhbHNlKTtcblxuICAgICAgICAgICQkJDEoX3RoaXMyLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS50cmlnZ2VyKEV2ZW50LkhJRERFTik7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gJyc7XG4gICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5zZXRUcmFuc2l0aW9uaW5nID0gZnVuY3Rpb24gc2V0VHJhbnNpdGlvbmluZyhpc1RyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gaXNUcmFuc2l0aW9uaW5nO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICB0aGlzLl9jb25maWcgPSBudWxsO1xuICAgICAgICB0aGlzLl9wYXJlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fdHJpZ2dlckFycmF5ID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gbnVsbDtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIERlZmF1bHQsIGNvbmZpZyk7XG4gICAgICAgIGNvbmZpZy50b2dnbGUgPSBCb29sZWFuKGNvbmZpZy50b2dnbGUpOyAvLyBDb2VyY2Ugc3RyaW5nIHZhbHVlc1xuXG4gICAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgRGVmYXVsdFR5cGUpO1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXREaW1lbnNpb24gPSBmdW5jdGlvbiBfZ2V0RGltZW5zaW9uKCkge1xuICAgICAgICB2YXIgaGFzV2lkdGggPSAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKERpbWVuc2lvbi5XSURUSCk7XG4gICAgICAgIHJldHVybiBoYXNXaWR0aCA/IERpbWVuc2lvbi5XSURUSCA6IERpbWVuc2lvbi5IRUlHSFQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldFBhcmVudCA9IGZ1bmN0aW9uIF9nZXRQYXJlbnQoKSB7XG4gICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgIHZhciBwYXJlbnQgPSBudWxsO1xuXG4gICAgICAgIGlmIChVdGlsLmlzRWxlbWVudCh0aGlzLl9jb25maWcucGFyZW50KSkge1xuICAgICAgICAgIHBhcmVudCA9IHRoaXMuX2NvbmZpZy5wYXJlbnQ7IC8vIEl0J3MgYSBqUXVlcnkgb2JqZWN0XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX2NvbmZpZy5wYXJlbnQuanF1ZXJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcGFyZW50ID0gdGhpcy5fY29uZmlnLnBhcmVudFswXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGFyZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLl9jb25maWcucGFyZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZWxlY3RvciA9IFwiW2RhdGEtdG9nZ2xlPVxcXCJjb2xsYXBzZVxcXCJdW2RhdGEtcGFyZW50PVxcXCJcIiArIHRoaXMuX2NvbmZpZy5wYXJlbnQgKyBcIlxcXCJdXCI7XG4gICAgICAgIHZhciBjaGlsZHJlbiA9IFtdLnNsaWNlLmNhbGwocGFyZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcbiAgICAgICAgJCQkMShjaGlsZHJlbikuZWFjaChmdW5jdGlvbiAoaSwgZWxlbWVudCkge1xuICAgICAgICAgIF90aGlzMy5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzKENvbGxhcHNlLl9nZXRUYXJnZXRGcm9tRWxlbWVudChlbGVtZW50KSwgW2VsZW1lbnRdKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBwYXJlbnQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2FkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyA9IGZ1bmN0aW9uIF9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoZWxlbWVudCwgdHJpZ2dlckFycmF5KSB7XG4gICAgICAgIGlmIChlbGVtZW50KSB7XG4gICAgICAgICAgdmFyIGlzT3BlbiA9ICQkJDEoZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgICAgaWYgKHRyaWdnZXJBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAgICQkJDEodHJpZ2dlckFycmF5KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0VELCAhaXNPcGVuKS5hdHRyKCdhcmlhLWV4cGFuZGVkJywgaXNPcGVuKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIENvbGxhcHNlLl9nZXRUYXJnZXRGcm9tRWxlbWVudCA9IGZ1bmN0aW9uIF9nZXRUYXJnZXRGcm9tRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdG9yID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcikgOiBudWxsO1xuICAgICAgfTtcblxuICAgICAgQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciAkdGhpcyA9ICQkJDEodGhpcyk7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkdGhpcy5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICAgIHZhciBfY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgRGVmYXVsdCwgJHRoaXMuZGF0YSgpLCB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyAmJiBjb25maWcgPyBjb25maWcgOiB7fSk7XG5cbiAgICAgICAgICBpZiAoIWRhdGEgJiYgX2NvbmZpZy50b2dnbGUgJiYgL3Nob3d8aGlkZS8udGVzdChjb25maWcpKSB7XG4gICAgICAgICAgICBfY29uZmlnLnRvZ2dsZSA9IGZhbHNlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgZGF0YSA9IG5ldyBDb2xsYXBzZSh0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICR0aGlzLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKENvbGxhcHNlLCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gQ29sbGFwc2U7XG4gICAgfSgpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAvLyBwcmV2ZW50RGVmYXVsdCBvbmx5IGZvciA8YT4gZWxlbWVudHMgKHdoaWNoIGNoYW5nZSB0aGUgVVJMKSBub3QgaW5zaWRlIHRoZSBjb2xsYXBzaWJsZSBlbGVtZW50XG4gICAgICBpZiAoZXZlbnQuY3VycmVudFRhcmdldC50YWdOYW1lID09PSAnQScpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgdmFyICR0cmlnZ2VyID0gJCQkMSh0aGlzKTtcbiAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0aGlzKTtcbiAgICAgIHZhciBzZWxlY3RvcnMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKTtcbiAgICAgICQkJDEoc2VsZWN0b3JzKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0YXJnZXQgPSAkJCQxKHRoaXMpO1xuICAgICAgICB2YXIgZGF0YSA9ICR0YXJnZXQuZGF0YShEQVRBX0tFWSk7XG4gICAgICAgIHZhciBjb25maWcgPSBkYXRhID8gJ3RvZ2dsZScgOiAkdHJpZ2dlci5kYXRhKCk7XG5cbiAgICAgICAgQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZS5jYWxsKCR0YXJnZXQsIGNvbmZpZyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBDb2xsYXBzZTtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIENvbGxhcHNlO1xuICB9KCQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IGRyb3Bkb3duLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBEcm9wZG93biA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ29uc3RhbnRzXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG4gICAgdmFyIE5BTUUgPSAnZHJvcGRvd24nO1xuICAgIHZhciBWRVJTSU9OID0gJzQuMS4zJztcbiAgICB2YXIgREFUQV9LRVkgPSAnYnMuZHJvcGRvd24nO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgICB2YXIgRVNDQVBFX0tFWUNPREUgPSAyNzsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgRXNjYXBlIChFc2MpIGtleVxuXG4gICAgdmFyIFNQQUNFX0tFWUNPREUgPSAzMjsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3Igc3BhY2Uga2V5XG5cbiAgICB2YXIgVEFCX0tFWUNPREUgPSA5OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciB0YWIga2V5XG5cbiAgICB2YXIgQVJST1dfVVBfS0VZQ09ERSA9IDM4OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciB1cCBhcnJvdyBrZXlcblxuICAgIHZhciBBUlJPV19ET1dOX0tFWUNPREUgPSA0MDsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgZG93biBhcnJvdyBrZXlcblxuICAgIHZhciBSSUdIVF9NT1VTRV9CVVRUT05fV0hJQ0ggPSAzOyAvLyBNb3VzZUV2ZW50LndoaWNoIHZhbHVlIGZvciB0aGUgcmlnaHQgYnV0dG9uIChhc3N1bWluZyBhIHJpZ2h0LWhhbmRlZCBtb3VzZSlcblxuICAgIHZhciBSRUdFWFBfS0VZRE9XTiA9IG5ldyBSZWdFeHAoQVJST1dfVVBfS0VZQ09ERSArIFwifFwiICsgQVJST1dfRE9XTl9LRVlDT0RFICsgXCJ8XCIgKyBFU0NBUEVfS0VZQ09ERSk7XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDSzogXCJjbGlja1wiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICAgIEtFWURPV05fREFUQV9BUEk6IFwia2V5ZG93blwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZLFxuICAgICAgS0VZVVBfREFUQV9BUEk6IFwia2V5dXBcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIERJU0FCTEVEOiAnZGlzYWJsZWQnLFxuICAgICAgU0hPVzogJ3Nob3cnLFxuICAgICAgRFJPUFVQOiAnZHJvcHVwJyxcbiAgICAgIERST1BSSUdIVDogJ2Ryb3ByaWdodCcsXG4gICAgICBEUk9QTEVGVDogJ2Ryb3BsZWZ0JyxcbiAgICAgIE1FTlVSSUdIVDogJ2Ryb3Bkb3duLW1lbnUtcmlnaHQnLFxuICAgICAgTUVOVUxFRlQ6ICdkcm9wZG93bi1tZW51LWxlZnQnLFxuICAgICAgUE9TSVRJT05fU1RBVElDOiAncG9zaXRpb24tc3RhdGljJ1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJkcm9wZG93blwiXScsXG4gICAgICBGT1JNX0NISUxEOiAnLmRyb3Bkb3duIGZvcm0nLFxuICAgICAgTUVOVTogJy5kcm9wZG93bi1tZW51JyxcbiAgICAgIE5BVkJBUl9OQVY6ICcubmF2YmFyLW5hdicsXG4gICAgICBWSVNJQkxFX0lURU1TOiAnLmRyb3Bkb3duLW1lbnUgLmRyb3Bkb3duLWl0ZW06bm90KC5kaXNhYmxlZCk6bm90KDpkaXNhYmxlZCknXG4gICAgfTtcbiAgICB2YXIgQXR0YWNobWVudE1hcCA9IHtcbiAgICAgIFRPUDogJ3RvcC1zdGFydCcsXG4gICAgICBUT1BFTkQ6ICd0b3AtZW5kJyxcbiAgICAgIEJPVFRPTTogJ2JvdHRvbS1zdGFydCcsXG4gICAgICBCT1RUT01FTkQ6ICdib3R0b20tZW5kJyxcbiAgICAgIFJJR0hUOiAncmlnaHQtc3RhcnQnLFxuICAgICAgUklHSFRFTkQ6ICdyaWdodC1lbmQnLFxuICAgICAgTEVGVDogJ2xlZnQtc3RhcnQnLFxuICAgICAgTEVGVEVORDogJ2xlZnQtZW5kJ1xuICAgIH07XG4gICAgdmFyIERlZmF1bHQgPSB7XG4gICAgICBvZmZzZXQ6IDAsXG4gICAgICBmbGlwOiB0cnVlLFxuICAgICAgYm91bmRhcnk6ICdzY3JvbGxQYXJlbnQnLFxuICAgICAgcmVmZXJlbmNlOiAndG9nZ2xlJyxcbiAgICAgIGRpc3BsYXk6ICdkeW5hbWljJ1xuICAgIH07XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgb2Zmc2V0OiAnKG51bWJlcnxzdHJpbmd8ZnVuY3Rpb24pJyxcbiAgICAgIGZsaXA6ICdib29sZWFuJyxcbiAgICAgIGJvdW5kYXJ5OiAnKHN0cmluZ3xlbGVtZW50KScsXG4gICAgICByZWZlcmVuY2U6ICcoc3RyaW5nfGVsZW1lbnQpJyxcbiAgICAgIGRpc3BsYXk6ICdzdHJpbmcnXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgRHJvcGRvd24gPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBEcm9wZG93bihlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuX3BvcHBlciA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLl9tZW51ID0gdGhpcy5fZ2V0TWVudUVsZW1lbnQoKTtcbiAgICAgICAgdGhpcy5faW5OYXZiYXIgPSB0aGlzLl9kZXRlY3ROYXZiYXIoKTtcblxuICAgICAgICB0aGlzLl9hZGRFdmVudExpc3RlbmVycygpO1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IERyb3Bkb3duLnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgICBpZiAodGhpcy5fZWxlbWVudC5kaXNhYmxlZCB8fCAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5ESVNBQkxFRCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcGFyZW50ID0gRHJvcGRvd24uX2dldFBhcmVudEZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICAgIHZhciBpc0FjdGl2ZSA9ICQkJDEodGhpcy5fbWVudSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIERyb3Bkb3duLl9jbGVhck1lbnVzKCk7XG5cbiAgICAgICAgaWYgKGlzQWN0aXZlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlbGF0ZWRUYXJnZXQgPSB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogdGhpcy5fZWxlbWVudFxuICAgICAgICB9O1xuICAgICAgICB2YXIgc2hvd0V2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XLCByZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgJCQkMShwYXJlbnQpLnRyaWdnZXIoc2hvd0V2ZW50KTtcblxuICAgICAgICBpZiAoc2hvd0V2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IC8vIERpc2FibGUgdG90YWxseSBQb3BwZXIuanMgZm9yIERyb3Bkb3duIGluIE5hdmJhclxuXG5cbiAgICAgICAgaWYgKCF0aGlzLl9pbk5hdmJhcikge1xuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIENoZWNrIGZvciBQb3BwZXIgZGVwZW5kZW5jeVxuICAgICAgICAgICAqIFBvcHBlciAtIGh0dHBzOi8vcG9wcGVyLmpzLm9yZ1xuICAgICAgICAgICAqL1xuICAgICAgICAgIGlmICh0eXBlb2YgUG9wcGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQm9vdHN0cmFwIGRyb3Bkb3duIHJlcXVpcmUgUG9wcGVyLmpzIChodHRwczovL3BvcHBlci5qcy5vcmcpJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHJlZmVyZW5jZUVsZW1lbnQgPSB0aGlzLl9lbGVtZW50O1xuXG4gICAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5yZWZlcmVuY2UgPT09ICdwYXJlbnQnKSB7XG4gICAgICAgICAgICByZWZlcmVuY2VFbGVtZW50ID0gcGFyZW50O1xuICAgICAgICAgIH0gZWxzZSBpZiAoVXRpbC5pc0VsZW1lbnQodGhpcy5fY29uZmlnLnJlZmVyZW5jZSkpIHtcbiAgICAgICAgICAgIHJlZmVyZW5jZUVsZW1lbnQgPSB0aGlzLl9jb25maWcucmVmZXJlbmNlOyAvLyBDaGVjayBpZiBpdCdzIGpRdWVyeSBlbGVtZW50XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fY29uZmlnLnJlZmVyZW5jZS5qcXVlcnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHJlZmVyZW5jZUVsZW1lbnQgPSB0aGlzLl9jb25maWcucmVmZXJlbmNlWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gLy8gSWYgYm91bmRhcnkgaXMgbm90IGBzY3JvbGxQYXJlbnRgLCB0aGVuIHNldCBwb3NpdGlvbiB0byBgc3RhdGljYFxuICAgICAgICAgIC8vIHRvIGFsbG93IHRoZSBtZW51IHRvIFwiZXNjYXBlXCIgdGhlIHNjcm9sbCBwYXJlbnQncyBib3VuZGFyaWVzXG4gICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2lzc3Vlcy8yNDI1MVxuXG5cbiAgICAgICAgICBpZiAodGhpcy5fY29uZmlnLmJvdW5kYXJ5ICE9PSAnc2Nyb2xsUGFyZW50Jykge1xuICAgICAgICAgICAgJCQkMShwYXJlbnQpLmFkZENsYXNzKENsYXNzTmFtZS5QT1NJVElPTl9TVEFUSUMpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX3BvcHBlciA9IG5ldyBQb3BwZXIocmVmZXJlbmNlRWxlbWVudCwgdGhpcy5fbWVudSwgdGhpcy5fZ2V0UG9wcGVyQ29uZmlnKCkpO1xuICAgICAgICB9IC8vIElmIHRoaXMgaXMgYSB0b3VjaC1lbmFibGVkIGRldmljZSB3ZSBhZGQgZXh0cmFcbiAgICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB0byB0aGUgYm9keSdzIGltbWVkaWF0ZSBjaGlsZHJlbjtcbiAgICAgICAgLy8gb25seSBuZWVkZWQgYmVjYXVzZSBvZiBicm9rZW4gZXZlbnQgZGVsZWdhdGlvbiBvbiBpT1NcbiAgICAgICAgLy8gaHR0cHM6Ly93d3cucXVpcmtzbW9kZS5vcmcvYmxvZy9hcmNoaXZlcy8yMDE0LzAyL21vdXNlX2V2ZW50X2J1Yi5odG1sXG5cblxuICAgICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmICQkJDEocGFyZW50KS5jbG9zZXN0KFNlbGVjdG9yLk5BVkJBUl9OQVYpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuY2hpbGRyZW4oKS5vbignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuZm9jdXMoKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuXG4gICAgICAgICQkJDEodGhpcy5fbWVudSkudG9nZ2xlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuICAgICAgICAkJCQxKHBhcmVudCkudG9nZ2xlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpLnRyaWdnZXIoJCQkMS5FdmVudChFdmVudC5TSE9XTiwgcmVsYXRlZFRhcmdldCkpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFVkVOVF9LRVkpO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fbWVudSA9IG51bGw7XG5cbiAgICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMuX3BvcHBlci5kZXN0cm95KCk7XG5cbiAgICAgICAgICB0aGlzLl9wb3BwZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8udXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKCkge1xuICAgICAgICB0aGlzLl9pbk5hdmJhciA9IHRoaXMuX2RldGVjdE5hdmJhcigpO1xuXG4gICAgICAgIGlmICh0aGlzLl9wb3BwZXIgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLl9wb3BwZXIuc2NoZWR1bGVVcGRhdGUoKTtcbiAgICAgICAgfVxuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fYWRkRXZlbnRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBfYWRkRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5DTElDSywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICAgIF90aGlzLnRvZ2dsZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0Q29uZmlnID0gZnVuY3Rpb24gX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0LCAkJCQxKHRoaXMuX2VsZW1lbnQpLmRhdGEoKSwgY29uZmlnKTtcbiAgICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRUeXBlKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0TWVudUVsZW1lbnQgPSBmdW5jdGlvbiBfZ2V0TWVudUVsZW1lbnQoKSB7XG4gICAgICAgIGlmICghdGhpcy5fbWVudSkge1xuICAgICAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG5cbiAgICAgICAgICBpZiAocGFyZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9tZW51ID0gcGFyZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuTUVOVSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX21lbnU7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldFBsYWNlbWVudCA9IGZ1bmN0aW9uIF9nZXRQbGFjZW1lbnQoKSB7XG4gICAgICAgIHZhciAkcGFyZW50RHJvcGRvd24gPSAkJCQxKHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZSk7XG4gICAgICAgIHZhciBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLkJPVFRPTTsgLy8gSGFuZGxlIGRyb3B1cFxuXG4gICAgICAgIGlmICgkcGFyZW50RHJvcGRvd24uaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BVUCkpIHtcbiAgICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLlRPUDtcblxuICAgICAgICAgIGlmICgkJCQxKHRoaXMuX21lbnUpLmhhc0NsYXNzKENsYXNzTmFtZS5NRU5VUklHSFQpKSB7XG4gICAgICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLlRPUEVORDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoJHBhcmVudERyb3Bkb3duLmhhc0NsYXNzKENsYXNzTmFtZS5EUk9QUklHSFQpKSB7XG4gICAgICAgICAgcGxhY2VtZW50ID0gQXR0YWNobWVudE1hcC5SSUdIVDtcbiAgICAgICAgfSBlbHNlIGlmICgkcGFyZW50RHJvcGRvd24uaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BMRUZUKSkge1xuICAgICAgICAgIHBsYWNlbWVudCA9IEF0dGFjaG1lbnRNYXAuTEVGVDtcbiAgICAgICAgfSBlbHNlIGlmICgkJCQxKHRoaXMuX21lbnUpLmhhc0NsYXNzKENsYXNzTmFtZS5NRU5VUklHSFQpKSB7XG4gICAgICAgICAgcGxhY2VtZW50ID0gQXR0YWNobWVudE1hcC5CT1RUT01FTkQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGxhY2VtZW50O1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9kZXRlY3ROYXZiYXIgPSBmdW5jdGlvbiBfZGV0ZWN0TmF2YmFyKCkge1xuICAgICAgICByZXR1cm4gJCQkMSh0aGlzLl9lbGVtZW50KS5jbG9zZXN0KCcubmF2YmFyJykubGVuZ3RoID4gMDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0UG9wcGVyQ29uZmlnID0gZnVuY3Rpb24gX2dldFBvcHBlckNvbmZpZygpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgdmFyIG9mZnNldENvbmYgPSB7fTtcblxuICAgICAgICBpZiAodHlwZW9mIHRoaXMuX2NvbmZpZy5vZmZzZXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICBvZmZzZXRDb25mLmZuID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEub2Zmc2V0cyA9IF9vYmplY3RTcHJlYWQoe30sIGRhdGEub2Zmc2V0cywgX3RoaXMyLl9jb25maWcub2Zmc2V0KGRhdGEub2Zmc2V0cykgfHwge30pO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvZmZzZXRDb25mLm9mZnNldCA9IHRoaXMuX2NvbmZpZy5vZmZzZXQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9wcGVyQ29uZmlnID0ge1xuICAgICAgICAgIHBsYWNlbWVudDogdGhpcy5fZ2V0UGxhY2VtZW50KCksXG4gICAgICAgICAgbW9kaWZpZXJzOiB7XG4gICAgICAgICAgICBvZmZzZXQ6IG9mZnNldENvbmYsXG4gICAgICAgICAgICBmbGlwOiB7XG4gICAgICAgICAgICAgIGVuYWJsZWQ6IHRoaXMuX2NvbmZpZy5mbGlwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJldmVudE92ZXJmbG93OiB7XG4gICAgICAgICAgICAgIGJvdW5kYXJpZXNFbGVtZW50OiB0aGlzLl9jb25maWcuYm91bmRhcnlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IC8vIERpc2FibGUgUG9wcGVyLmpzIGlmIHdlIGhhdmUgYSBzdGF0aWMgZGlzcGxheVxuXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5kaXNwbGF5ID09PSAnc3RhdGljJykge1xuICAgICAgICAgIHBvcHBlckNvbmZpZy5tb2RpZmllcnMuYXBwbHlTdHlsZSA9IHtcbiAgICAgICAgICAgIGVuYWJsZWQ6IGZhbHNlXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb3BwZXJDb25maWc7XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBEcm9wZG93bi5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgdmFyIF9jb25maWcgPSB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IG51bGw7XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgRHJvcGRvd24odGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgRHJvcGRvd24uX2NsZWFyTWVudXMgPSBmdW5jdGlvbiBfY2xlYXJNZW51cyhldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQgJiYgKGV2ZW50LndoaWNoID09PSBSSUdIVF9NT1VTRV9CVVRUT05fV0hJQ0ggfHwgZXZlbnQudHlwZSA9PT0gJ2tleXVwJyAmJiBldmVudC53aGljaCAhPT0gVEFCX0tFWUNPREUpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRvZ2dsZXMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuREFUQV9UT0dHTEUpKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gdG9nZ2xlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodG9nZ2xlc1tpXSk7XG5cbiAgICAgICAgICB2YXIgY29udGV4dCA9ICQkJDEodG9nZ2xlc1tpXSkuZGF0YShEQVRBX0tFWSk7XG4gICAgICAgICAgdmFyIHJlbGF0ZWRUYXJnZXQgPSB7XG4gICAgICAgICAgICByZWxhdGVkVGFyZ2V0OiB0b2dnbGVzW2ldXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmIChldmVudCAmJiBldmVudC50eXBlID09PSAnY2xpY2snKSB7XG4gICAgICAgICAgICByZWxhdGVkVGFyZ2V0LmNsaWNrRXZlbnQgPSBldmVudDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBkcm9wZG93bk1lbnUgPSBjb250ZXh0Ll9tZW51O1xuXG4gICAgICAgICAgaWYgKCEkJCQxKHBhcmVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZXZlbnQgJiYgKGV2ZW50LnR5cGUgPT09ICdjbGljaycgJiYgL2lucHV0fHRleHRhcmVhL2kudGVzdChldmVudC50YXJnZXQudGFnTmFtZSkgfHwgZXZlbnQudHlwZSA9PT0gJ2tleXVwJyAmJiBldmVudC53aGljaCA9PT0gVEFCX0tFWUNPREUpICYmICQkJDEuY29udGFpbnMocGFyZW50LCBldmVudC50YXJnZXQpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgaGlkZUV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5ISURFLCByZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgICAkJCQxKHBhcmVudCkudHJpZ2dlcihoaWRlRXZlbnQpO1xuXG4gICAgICAgICAgaWYgKGhpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfSAvLyBJZiB0aGlzIGlzIGEgdG91Y2gtZW5hYmxlZCBkZXZpY2Ugd2UgcmVtb3ZlIHRoZSBleHRyYVxuICAgICAgICAgIC8vIGVtcHR5IG1vdXNlb3ZlciBsaXN0ZW5lcnMgd2UgYWRkZWQgZm9yIGlPUyBzdXBwb3J0XG5cblxuICAgICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuY2hpbGRyZW4oKS5vZmYoJ21vdXNlb3ZlcicsIG51bGwsICQkJDEubm9vcCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdG9nZ2xlc1tpXS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAkJCQxKGRyb3Bkb3duTWVudSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuICAgICAgICAgICQkJDEocGFyZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVykudHJpZ2dlcigkJCQxLkV2ZW50KEV2ZW50LkhJRERFTiwgcmVsYXRlZFRhcmdldCkpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQgPSBmdW5jdGlvbiBfZ2V0UGFyZW50RnJvbUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICB2YXIgcGFyZW50O1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgcGFyZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFyZW50IHx8IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICAgIH07IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5cblxuICAgICAgRHJvcGRvd24uX2RhdGFBcGlLZXlkb3duSGFuZGxlciA9IGZ1bmN0aW9uIF9kYXRhQXBpS2V5ZG93bkhhbmRsZXIoZXZlbnQpIHtcbiAgICAgICAgLy8gSWYgbm90IGlucHV0L3RleHRhcmVhOlxuICAgICAgICAvLyAgLSBBbmQgbm90IGEga2V5IGluIFJFR0VYUF9LRVlET1dOID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgICAgLy8gSWYgaW5wdXQvdGV4dGFyZWE6XG4gICAgICAgIC8vICAtIElmIHNwYWNlIGtleSA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICAgIC8vICAtIElmIGtleSBpcyBvdGhlciB0aGFuIGVzY2FwZVxuICAgICAgICAvLyAgICAtIElmIGtleSBpcyBub3QgdXAgb3IgZG93biA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICAgIC8vICAgIC0gSWYgdHJpZ2dlciBpbnNpZGUgdGhlIG1lbnUgPT4gbm90IGEgZHJvcGRvd24gY29tbWFuZFxuICAgICAgICBpZiAoL2lucHV0fHRleHRhcmVhL2kudGVzdChldmVudC50YXJnZXQudGFnTmFtZSkgPyBldmVudC53aGljaCA9PT0gU1BBQ0VfS0VZQ09ERSB8fCBldmVudC53aGljaCAhPT0gRVNDQVBFX0tFWUNPREUgJiYgKGV2ZW50LndoaWNoICE9PSBBUlJPV19ET1dOX0tFWUNPREUgJiYgZXZlbnQud2hpY2ggIT09IEFSUk9XX1VQX0tFWUNPREUgfHwgJCQkMShldmVudC50YXJnZXQpLmNsb3Nlc3QoU2VsZWN0b3IuTUVOVSkubGVuZ3RoKSA6ICFSRUdFWFBfS0VZRE9XTi50ZXN0KGV2ZW50LndoaWNoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkIHx8ICQkJDEodGhpcykuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRJU0FCTEVEKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcyk7XG5cbiAgICAgICAgdmFyIGlzQWN0aXZlID0gJCQkMShwYXJlbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgICBpZiAoIWlzQWN0aXZlICYmIChldmVudC53aGljaCAhPT0gRVNDQVBFX0tFWUNPREUgfHwgZXZlbnQud2hpY2ggIT09IFNQQUNFX0tFWUNPREUpIHx8IGlzQWN0aXZlICYmIChldmVudC53aGljaCA9PT0gRVNDQVBFX0tFWUNPREUgfHwgZXZlbnQud2hpY2ggPT09IFNQQUNFX0tFWUNPREUpKSB7XG4gICAgICAgICAgaWYgKGV2ZW50LndoaWNoID09PSBFU0NBUEVfS0VZQ09ERSkge1xuICAgICAgICAgICAgdmFyIHRvZ2dsZSA9IHBhcmVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLkRBVEFfVE9HR0xFKTtcbiAgICAgICAgICAgICQkJDEodG9nZ2xlKS50cmlnZ2VyKCdmb2N1cycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICQkJDEodGhpcykudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaXRlbXMgPSBbXS5zbGljZS5jYWxsKHBhcmVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLlZJU0lCTEVfSVRFTVMpKTtcblxuICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluZGV4ID0gaXRlbXMuaW5kZXhPZihldmVudC50YXJnZXQpO1xuXG4gICAgICAgIGlmIChldmVudC53aGljaCA9PT0gQVJST1dfVVBfS0VZQ09ERSAmJiBpbmRleCA+IDApIHtcbiAgICAgICAgICAvLyBVcFxuICAgICAgICAgIGluZGV4LS07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQud2hpY2ggPT09IEFSUk9XX0RPV05fS0VZQ09ERSAmJiBpbmRleCA8IGl0ZW1zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAvLyBEb3duXG4gICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgICBpbmRleCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpdGVtc1tpbmRleF0uZm9jdXMoKTtcbiAgICAgIH07XG5cbiAgICAgIF9jcmVhdGVDbGFzcyhEcm9wZG93biwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRUeXBlXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gRHJvcGRvd247XG4gICAgfSgpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LktFWURPV05fREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfVE9HR0xFLCBEcm9wZG93bi5fZGF0YUFwaUtleWRvd25IYW5kbGVyKS5vbihFdmVudC5LRVlET1dOX0RBVEFfQVBJLCBTZWxlY3Rvci5NRU5VLCBEcm9wZG93bi5fZGF0YUFwaUtleWRvd25IYW5kbGVyKS5vbihFdmVudC5DTElDS19EQVRBX0FQSSArIFwiIFwiICsgRXZlbnQuS0VZVVBfREFUQV9BUEksIERyb3Bkb3duLl9jbGVhck1lbnVzKS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICBEcm9wZG93bi5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMSh0aGlzKSwgJ3RvZ2dsZScpO1xuICAgIH0pLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5GT1JNX0NISUxELCBmdW5jdGlvbiAoZSkge1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBEcm9wZG93bi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBEcm9wZG93bjtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gRHJvcGRvd24uX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIERyb3Bkb3duO1xuICB9KCQsIFBvcHBlcik7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogbW9kYWwuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIE1vZGFsID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdtb2RhbCc7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5tb2RhbCc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBFU0NBUEVfS0VZQ09ERSA9IDI3OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciBFc2NhcGUgKEVzYykga2V5XG5cbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgIGJhY2tkcm9wOiB0cnVlLFxuICAgICAga2V5Ym9hcmQ6IHRydWUsXG4gICAgICBmb2N1czogdHJ1ZSxcbiAgICAgIHNob3c6IHRydWVcbiAgICB9O1xuICAgIHZhciBEZWZhdWx0VHlwZSA9IHtcbiAgICAgIGJhY2tkcm9wOiAnKGJvb2xlYW58c3RyaW5nKScsXG4gICAgICBrZXlib2FyZDogJ2Jvb2xlYW4nLFxuICAgICAgZm9jdXM6ICdib29sZWFuJyxcbiAgICAgIHNob3c6ICdib29sZWFuJ1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgICBGT0NVU0lOOiBcImZvY3VzaW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFJFU0laRTogXCJyZXNpemVcIiArIEVWRU5UX0tFWSxcbiAgICAgIENMSUNLX0RJU01JU1M6IFwiY2xpY2suZGlzbWlzc1wiICsgRVZFTlRfS0VZLFxuICAgICAgS0VZRE9XTl9ESVNNSVNTOiBcImtleWRvd24uZGlzbWlzc1wiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VVUF9ESVNNSVNTOiBcIm1vdXNldXAuZGlzbWlzc1wiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VET1dOX0RJU01JU1M6IFwibW91c2Vkb3duLmRpc21pc3NcIiArIEVWRU5UX0tFWSxcbiAgICAgIENMSUNLX0RBVEFfQVBJOiBcImNsaWNrXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVlcbiAgICB9O1xuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBTQ1JPTExCQVJfTUVBU1VSRVI6ICdtb2RhbC1zY3JvbGxiYXItbWVhc3VyZScsXG4gICAgICBCQUNLRFJPUDogJ21vZGFsLWJhY2tkcm9wJyxcbiAgICAgIE9QRU46ICdtb2RhbC1vcGVuJyxcbiAgICAgIEZBREU6ICdmYWRlJyxcbiAgICAgIFNIT1c6ICdzaG93J1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgRElBTE9HOiAnLm1vZGFsLWRpYWxvZycsXG4gICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cIm1vZGFsXCJdJyxcbiAgICAgIERBVEFfRElTTUlTUzogJ1tkYXRhLWRpc21pc3M9XCJtb2RhbFwiXScsXG4gICAgICBGSVhFRF9DT05URU5UOiAnLmZpeGVkLXRvcCwgLmZpeGVkLWJvdHRvbSwgLmlzLWZpeGVkLCAuc3RpY2t5LXRvcCcsXG4gICAgICBTVElDS1lfQ09OVEVOVDogJy5zdGlja3ktdG9wJ1xuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIE1vZGFsID1cbiAgICAvKiNfX1BVUkVfXyovXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgZnVuY3Rpb24gTW9kYWwoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5fZGlhbG9nID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLkRJQUxPRyk7XG4gICAgICAgIHRoaXMuX2JhY2tkcm9wID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNTaG93biA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9pZ25vcmVCYWNrZHJvcENsaWNrID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX3Njcm9sbGJhcldpZHRoID0gMDtcbiAgICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICAgIHZhciBfcHJvdG8gPSBNb2RhbC5wcm90b3R5cGU7XG5cbiAgICAgIC8vIFB1YmxpY1xuICAgICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZShyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1Nob3duID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3cocmVsYXRlZFRhcmdldCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uc2hvdyA9IGZ1bmN0aW9uIHNob3cocmVsYXRlZFRhcmdldCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9pc1RyYW5zaXRpb25pbmcgfHwgdGhpcy5faXNTaG93bikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hvd0V2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldFxuICAgICAgICB9KTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHNob3dFdmVudCk7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzU2hvd24gfHwgc2hvd0V2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faXNTaG93biA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5fY2hlY2tTY3JvbGxiYXIoKTtcblxuICAgICAgICB0aGlzLl9zZXRTY3JvbGxiYXIoKTtcblxuICAgICAgICB0aGlzLl9hZGp1c3REaWFsb2coKTtcblxuICAgICAgICAkJCQxKGRvY3VtZW50LmJvZHkpLmFkZENsYXNzKENsYXNzTmFtZS5PUEVOKTtcblxuICAgICAgICB0aGlzLl9zZXRFc2NhcGVFdmVudCgpO1xuXG4gICAgICAgIHRoaXMuX3NldFJlc2l6ZUV2ZW50KCk7XG5cbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5DTElDS19ESVNNSVNTLCBTZWxlY3Rvci5EQVRBX0RJU01JU1MsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5oaWRlKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgICQkJDEodGhpcy5fZGlhbG9nKS5vbihFdmVudC5NT1VTRURPV05fRElTTUlTUywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLm9uZShFdmVudC5NT1VTRVVQX0RJU01JU1MsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKCQkJDEoZXZlbnQudGFyZ2V0KS5pcyhfdGhpcy5fZWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgX3RoaXMuX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLl9zaG93QmFja2Ryb3AoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5fc2hvd0VsZW1lbnQocmVsYXRlZFRhcmdldCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmhpZGUgPSBmdW5jdGlvbiBoaWRlKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8ICF0aGlzLl9pc1Nob3duKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGhpZGVFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuSElERSk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihoaWRlRXZlbnQpO1xuXG4gICAgICAgIGlmICghdGhpcy5faXNTaG93biB8fCBoaWRlRXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICAgIHZhciB0cmFuc2l0aW9uID0gJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSk7XG5cbiAgICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2V0RXNjYXBlRXZlbnQoKTtcblxuICAgICAgICB0aGlzLl9zZXRSZXNpemVFdmVudCgpO1xuXG4gICAgICAgICQkJDEoZG9jdW1lbnQpLm9mZihFdmVudC5GT0NVU0lOKTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub2ZmKEV2ZW50LkNMSUNLX0RJU01JU1MpO1xuICAgICAgICAkJCQxKHRoaXMuX2RpYWxvZykub2ZmKEV2ZW50Lk1PVVNFRE9XTl9ESVNNSVNTKTtcblxuICAgICAgICBpZiAodHJhbnNpdGlvbikge1xuICAgICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzMi5faGlkZU1vZGFsKGV2ZW50KTtcbiAgICAgICAgICB9KS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX2hpZGVNb2RhbCgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgICQkJDEod2luZG93LCBkb2N1bWVudCwgdGhpcy5fZWxlbWVudCwgdGhpcy5fYmFja2Ryb3ApLm9mZihFVkVOVF9LRVkpO1xuICAgICAgICB0aGlzLl9jb25maWcgPSBudWxsO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZGlhbG9nID0gbnVsbDtcbiAgICAgICAgdGhpcy5fYmFja2Ryb3AgPSBudWxsO1xuICAgICAgICB0aGlzLl9pc1Nob3duID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcgPSBudWxsO1xuICAgICAgICB0aGlzLl9pZ25vcmVCYWNrZHJvcENsaWNrID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyV2lkdGggPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmhhbmRsZVVwZGF0ZSA9IGZ1bmN0aW9uIGhhbmRsZVVwZGF0ZSgpIHtcbiAgICAgICAgdGhpcy5fYWRqdXN0RGlhbG9nKCk7XG4gICAgICB9OyAvLyBQcml2YXRlXG5cblxuICAgICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgICBjb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCBEZWZhdWx0LCBjb25maWcpO1xuICAgICAgICBVdGlsLnR5cGVDaGVja0NvbmZpZyhOQU1FLCBjb25maWcsIERlZmF1bHRUeXBlKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fc2hvd0VsZW1lbnQgPSBmdW5jdGlvbiBfc2hvd0VsZW1lbnQocmVsYXRlZFRhcmdldCkge1xuICAgICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgICB2YXIgdHJhbnNpdGlvbiA9ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpO1xuXG4gICAgICAgIGlmICghdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlIHx8IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZS5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREUpIHtcbiAgICAgICAgICAvLyBEb24ndCBtb3ZlIG1vZGFsJ3MgRE9NIHBvc2l0aW9uXG4gICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0aGlzLl9lbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJyk7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zY3JvbGxUb3AgPSAwO1xuXG4gICAgICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICAgICAgVXRpbC5yZWZsb3codGhpcy5fZWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLmFkZENsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmZvY3VzKSB7XG4gICAgICAgICAgdGhpcy5fZW5mb3JjZUZvY3VzKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hvd25FdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPV04sIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiByZWxhdGVkVGFyZ2V0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciB0cmFuc2l0aW9uQ29tcGxldGUgPSBmdW5jdGlvbiB0cmFuc2l0aW9uQ29tcGxldGUoKSB7XG4gICAgICAgICAgaWYgKF90aGlzMy5fY29uZmlnLmZvY3VzKSB7XG4gICAgICAgICAgICBfdGhpczMuX2VsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBfdGhpczMuX2lzVHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICQkJDEoX3RoaXMzLl9lbGVtZW50KS50cmlnZ2VyKHNob3duRXZlbnQpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG4gICAgICAgICAgJCQkMSh0aGlzLl9kaWFsb2cpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCB0cmFuc2l0aW9uQ29tcGxldGUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJhbnNpdGlvbkNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZW5mb3JjZUZvY3VzID0gZnVuY3Rpb24gX2VuZm9yY2VGb2N1cygpIHtcbiAgICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgICAgJCQkMShkb2N1bWVudCkub2ZmKEV2ZW50LkZPQ1VTSU4pIC8vIEd1YXJkIGFnYWluc3QgaW5maW5pdGUgZm9jdXMgbG9vcFxuICAgICAgICAub24oRXZlbnQuRk9DVVNJTiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgaWYgKGRvY3VtZW50ICE9PSBldmVudC50YXJnZXQgJiYgX3RoaXM0Ll9lbGVtZW50ICE9PSBldmVudC50YXJnZXQgJiYgJCQkMShfdGhpczQuX2VsZW1lbnQpLmhhcyhldmVudC50YXJnZXQpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgX3RoaXM0Ll9lbGVtZW50LmZvY3VzKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fc2V0RXNjYXBlRXZlbnQgPSBmdW5jdGlvbiBfc2V0RXNjYXBlRXZlbnQoKSB7XG4gICAgICAgIHZhciBfdGhpczUgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9pc1Nob3duICYmIHRoaXMuX2NvbmZpZy5rZXlib2FyZCkge1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuS0VZRE9XTl9ESVNNSVNTLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC53aGljaCA9PT0gRVNDQVBFX0tFWUNPREUpIHtcbiAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgICBfdGhpczUuaGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLl9pc1Nob3duKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vZmYoRXZlbnQuS0VZRE9XTl9ESVNNSVNTKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zZXRSZXNpemVFdmVudCA9IGZ1bmN0aW9uIF9zZXRSZXNpemVFdmVudCgpIHtcbiAgICAgICAgdmFyIF90aGlzNiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgICAkJCQxKHdpbmRvdykub24oRXZlbnQuUkVTSVpFLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczYuaGFuZGxlVXBkYXRlKGV2ZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAkJCQxKHdpbmRvdykub2ZmKEV2ZW50LlJFU0laRSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5faGlkZU1vZGFsID0gZnVuY3Rpb24gX2hpZGVNb2RhbCgpIHtcbiAgICAgICAgdmFyIF90aGlzNyA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsIHRydWUpO1xuXG4gICAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX3Nob3dCYWNrZHJvcChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuT1BFTik7XG5cbiAgICAgICAgICBfdGhpczcuX3Jlc2V0QWRqdXN0bWVudHMoKTtcblxuICAgICAgICAgIF90aGlzNy5fcmVzZXRTY3JvbGxiYXIoKTtcblxuICAgICAgICAgICQkJDEoX3RoaXM3Ll9lbGVtZW50KS50cmlnZ2VyKEV2ZW50LkhJRERFTik7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9yZW1vdmVCYWNrZHJvcCA9IGZ1bmN0aW9uIF9yZW1vdmVCYWNrZHJvcCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2JhY2tkcm9wKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkucmVtb3ZlKCk7XG4gICAgICAgICAgdGhpcy5fYmFja2Ryb3AgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3Nob3dCYWNrZHJvcCA9IGZ1bmN0aW9uIF9zaG93QmFja2Ryb3AoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzOCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGFuaW1hdGUgPSAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSA/IENsYXNzTmFtZS5GQURFIDogJyc7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzU2hvd24gJiYgdGhpcy5fY29uZmlnLmJhY2tkcm9wKSB7XG4gICAgICAgICAgdGhpcy5fYmFja2Ryb3AgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICB0aGlzLl9iYWNrZHJvcC5jbGFzc05hbWUgPSBDbGFzc05hbWUuQkFDS0RST1A7XG5cbiAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgdGhpcy5fYmFja2Ryb3AuY2xhc3NMaXN0LmFkZChhbmltYXRlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5hcHBlbmRUbyhkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RJU01JU1MsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKF90aGlzOC5faWdub3JlQmFja2Ryb3BDbGljaykge1xuICAgICAgICAgICAgICBfdGhpczguX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZXZlbnQudGFyZ2V0ICE9PSBldmVudC5jdXJyZW50VGFyZ2V0KSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKF90aGlzOC5fY29uZmlnLmJhY2tkcm9wID09PSAnc3RhdGljJykge1xuICAgICAgICAgICAgICBfdGhpczguX2VsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIF90aGlzOC5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgVXRpbC5yZWZsb3codGhpcy5fYmFja2Ryb3ApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICQkJDEodGhpcy5fYmFja2Ryb3ApLmFkZENsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWFuaW1hdGUpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGJhY2tkcm9wVHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCh0aGlzLl9iYWNrZHJvcCk7XG4gICAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNhbGxiYWNrKS5lbXVsYXRlVHJhbnNpdGlvbkVuZChiYWNrZHJvcFRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lzU2hvd24gJiYgdGhpcy5fYmFja2Ryb3ApIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgICB2YXIgY2FsbGJhY2tSZW1vdmUgPSBmdW5jdGlvbiBjYWxsYmFja1JlbW92ZSgpIHtcbiAgICAgICAgICAgIF90aGlzOC5fcmVtb3ZlQmFja2Ryb3AoKTtcblxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmICgkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICAgICAgdmFyIF9iYWNrZHJvcFRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGhpcy5fYmFja2Ryb3ApO1xuXG4gICAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY2FsbGJhY2tSZW1vdmUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKF9iYWNrZHJvcFRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrUmVtb3ZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTsgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgLy8gdGhlIGZvbGxvd2luZyBtZXRob2RzIGFyZSB1c2VkIHRvIGhhbmRsZSBvdmVyZmxvd2luZyBtb2RhbHNcbiAgICAgIC8vIHRvZG8gKGZhdCk6IHRoZXNlIHNob3VsZCBwcm9iYWJseSBiZSByZWZhY3RvcmVkIG91dCBvZiBtb2RhbC5qc1xuICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbiAgICAgIF9wcm90by5fYWRqdXN0RGlhbG9nID0gZnVuY3Rpb24gX2FkanVzdERpYWxvZygpIHtcbiAgICAgICAgdmFyIGlzTW9kYWxPdmVyZmxvd2luZyA9IHRoaXMuX2VsZW1lbnQuc2Nyb2xsSGVpZ2h0ID4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodDtcblxuICAgICAgICBpZiAoIXRoaXMuX2lzQm9keU92ZXJmbG93aW5nICYmIGlzTW9kYWxPdmVyZmxvd2luZykge1xuICAgICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ0xlZnQgPSB0aGlzLl9zY3JvbGxiYXJXaWR0aCArIFwicHhcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyAmJiAhaXNNb2RhbE92ZXJmbG93aW5nKSB7XG4gICAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nUmlnaHQgPSB0aGlzLl9zY3JvbGxiYXJXaWR0aCArIFwicHhcIjtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9yZXNldEFkanVzdG1lbnRzID0gZnVuY3Rpb24gX3Jlc2V0QWRqdXN0bWVudHMoKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ0xlZnQgPSAnJztcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nUmlnaHQgPSAnJztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fY2hlY2tTY3JvbGxiYXIgPSBmdW5jdGlvbiBfY2hlY2tTY3JvbGxiYXIoKSB7XG4gICAgICAgIHZhciByZWN0ID0gZG9jdW1lbnQuYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcgPSByZWN0LmxlZnQgKyByZWN0LnJpZ2h0IDwgd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgIHRoaXMuX3Njcm9sbGJhcldpZHRoID0gdGhpcy5fZ2V0U2Nyb2xsYmFyV2lkdGgoKTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fc2V0U2Nyb2xsYmFyID0gZnVuY3Rpb24gX3NldFNjcm9sbGJhcigpIHtcbiAgICAgICAgdmFyIF90aGlzOSA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzQm9keU92ZXJmbG93aW5nKSB7XG4gICAgICAgICAgLy8gTm90ZTogRE9NTm9kZS5zdHlsZS5wYWRkaW5nUmlnaHQgcmV0dXJucyB0aGUgYWN0dWFsIHZhbHVlIG9yICcnIGlmIG5vdCBzZXRcbiAgICAgICAgICAvLyAgIHdoaWxlICQoRE9NTm9kZSkuY3NzKCdwYWRkaW5nLXJpZ2h0JykgcmV0dXJucyB0aGUgY2FsY3VsYXRlZCB2YWx1ZSBvciAwIGlmIG5vdCBzZXRcbiAgICAgICAgICB2YXIgZml4ZWRDb250ZW50ID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLkZJWEVEX0NPTlRFTlQpKTtcbiAgICAgICAgICB2YXIgc3RpY2t5Q29udGVudCA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5TVElDS1lfQ09OVEVOVCkpOyAvLyBBZGp1c3QgZml4ZWQgY29udGVudCBwYWRkaW5nXG5cbiAgICAgICAgICAkJCQxKGZpeGVkQ29udGVudCkuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcbiAgICAgICAgICAgIHZhciBhY3R1YWxQYWRkaW5nID0gZWxlbWVudC5zdHlsZS5wYWRkaW5nUmlnaHQ7XG4gICAgICAgICAgICB2YXIgY2FsY3VsYXRlZFBhZGRpbmcgPSAkJCQxKGVsZW1lbnQpLmNzcygncGFkZGluZy1yaWdodCcpO1xuICAgICAgICAgICAgJCQkMShlbGVtZW50KS5kYXRhKCdwYWRkaW5nLXJpZ2h0JywgYWN0dWFsUGFkZGluZykuY3NzKCdwYWRkaW5nLXJpZ2h0JywgcGFyc2VGbG9hdChjYWxjdWxhdGVkUGFkZGluZykgKyBfdGhpczkuX3Njcm9sbGJhcldpZHRoICsgXCJweFwiKTtcbiAgICAgICAgICB9KTsgLy8gQWRqdXN0IHN0aWNreSBjb250ZW50IG1hcmdpblxuXG4gICAgICAgICAgJCQkMShzdGlja3lDb250ZW50KS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGFjdHVhbE1hcmdpbiA9IGVsZW1lbnQuc3R5bGUubWFyZ2luUmlnaHQ7XG4gICAgICAgICAgICB2YXIgY2FsY3VsYXRlZE1hcmdpbiA9ICQkJDEoZWxlbWVudCkuY3NzKCdtYXJnaW4tcmlnaHQnKTtcbiAgICAgICAgICAgICQkJDEoZWxlbWVudCkuZGF0YSgnbWFyZ2luLXJpZ2h0JywgYWN0dWFsTWFyZ2luKS5jc3MoJ21hcmdpbi1yaWdodCcsIHBhcnNlRmxvYXQoY2FsY3VsYXRlZE1hcmdpbikgLSBfdGhpczkuX3Njcm9sbGJhcldpZHRoICsgXCJweFwiKTtcbiAgICAgICAgICB9KTsgLy8gQWRqdXN0IGJvZHkgcGFkZGluZ1xuXG4gICAgICAgICAgdmFyIGFjdHVhbFBhZGRpbmcgPSBkb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmdSaWdodDtcbiAgICAgICAgICB2YXIgY2FsY3VsYXRlZFBhZGRpbmcgPSAkJCQxKGRvY3VtZW50LmJvZHkpLmNzcygncGFkZGluZy1yaWdodCcpO1xuICAgICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuZGF0YSgncGFkZGluZy1yaWdodCcsIGFjdHVhbFBhZGRpbmcpLmNzcygncGFkZGluZy1yaWdodCcsIHBhcnNlRmxvYXQoY2FsY3VsYXRlZFBhZGRpbmcpICsgdGhpcy5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3Jlc2V0U2Nyb2xsYmFyID0gZnVuY3Rpb24gX3Jlc2V0U2Nyb2xsYmFyKCkge1xuICAgICAgICAvLyBSZXN0b3JlIGZpeGVkIGNvbnRlbnQgcGFkZGluZ1xuICAgICAgICB2YXIgZml4ZWRDb250ZW50ID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLkZJWEVEX0NPTlRFTlQpKTtcbiAgICAgICAgJCQkMShmaXhlZENvbnRlbnQpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgdmFyIHBhZGRpbmcgPSAkJCQxKGVsZW1lbnQpLmRhdGEoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgICAkJCQxKGVsZW1lbnQpLnJlbW92ZURhdGEoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgICBlbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9IHBhZGRpbmcgPyBwYWRkaW5nIDogJyc7XG4gICAgICAgIH0pOyAvLyBSZXN0b3JlIHN0aWNreSBjb250ZW50XG5cbiAgICAgICAgdmFyIGVsZW1lbnRzID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFwiXCIgKyBTZWxlY3Rvci5TVElDS1lfQ09OVEVOVCkpO1xuICAgICAgICAkJCQxKGVsZW1lbnRzKS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgIHZhciBtYXJnaW4gPSAkJCQxKGVsZW1lbnQpLmRhdGEoJ21hcmdpbi1yaWdodCcpO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBtYXJnaW4gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAkJCQxKGVsZW1lbnQpLmNzcygnbWFyZ2luLXJpZ2h0JywgbWFyZ2luKS5yZW1vdmVEYXRhKCdtYXJnaW4tcmlnaHQnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pOyAvLyBSZXN0b3JlIGJvZHkgcGFkZGluZ1xuXG4gICAgICAgIHZhciBwYWRkaW5nID0gJCQkMShkb2N1bWVudC5ib2R5KS5kYXRhKCdwYWRkaW5nLXJpZ2h0Jyk7XG4gICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkucmVtb3ZlRGF0YSgncGFkZGluZy1yaWdodCcpO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmdSaWdodCA9IHBhZGRpbmcgPyBwYWRkaW5nIDogJyc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldFNjcm9sbGJhcldpZHRoID0gZnVuY3Rpb24gX2dldFNjcm9sbGJhcldpZHRoKCkge1xuICAgICAgICAvLyB0aHggZC53YWxzaFxuICAgICAgICB2YXIgc2Nyb2xsRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHNjcm9sbERpdi5jbGFzc05hbWUgPSBDbGFzc05hbWUuU0NST0xMQkFSX01FQVNVUkVSO1xuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHNjcm9sbERpdik7XG4gICAgICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHNjcm9sbERpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCAtIHNjcm9sbERpdi5jbGllbnRXaWR0aDtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzY3JvbGxEaXYpO1xuICAgICAgICByZXR1cm4gc2Nyb2xsYmFyV2lkdGg7XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBNb2RhbC5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcsIHJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgdmFyIF9jb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCBEZWZhdWx0LCAkJCQxKHRoaXMpLmRhdGEoKSwgdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IE1vZGFsKHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICAgJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gbWV0aG9kIG5hbWVkIFxcXCJcIiArIGNvbmZpZyArIFwiXFxcIlwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGF0YVtjb25maWddKHJlbGF0ZWRUYXJnZXQpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoX2NvbmZpZy5zaG93KSB7XG4gICAgICAgICAgICBkYXRhLnNob3cocmVsYXRlZFRhcmdldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIF9jcmVhdGVDbGFzcyhNb2RhbCwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIE1vZGFsO1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgdmFyIF90aGlzMTAgPSB0aGlzO1xuXG4gICAgICB2YXIgdGFyZ2V0O1xuICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRoaXMpO1xuXG4gICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgICB9XG5cbiAgICAgIHZhciBjb25maWcgPSAkJCQxKHRhcmdldCkuZGF0YShEQVRBX0tFWSkgPyAndG9nZ2xlJyA6IF9vYmplY3RTcHJlYWQoe30sICQkJDEodGFyZ2V0KS5kYXRhKCksICQkJDEodGhpcykuZGF0YSgpKTtcblxuICAgICAgaWYgKHRoaXMudGFnTmFtZSA9PT0gJ0EnIHx8IHRoaXMudGFnTmFtZSA9PT0gJ0FSRUEnKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIHZhciAkdGFyZ2V0ID0gJCQkMSh0YXJnZXQpLm9uZShFdmVudC5TSE9XLCBmdW5jdGlvbiAoc2hvd0V2ZW50KSB7XG4gICAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICAvLyBPbmx5IHJlZ2lzdGVyIGZvY3VzIHJlc3RvcmVyIGlmIG1vZGFsIHdpbGwgYWN0dWFsbHkgZ2V0IHNob3duXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgJHRhcmdldC5vbmUoRXZlbnQuSElEREVOLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKCQkJDEoX3RoaXMxMCkuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgIF90aGlzMTAuZm9jdXMoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIE1vZGFsLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkJCQxKHRhcmdldCksIGNvbmZpZywgdGhpcyk7XG4gICAgfSk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgICAkJCQxLmZuW05BTUVdID0gTW9kYWwuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gTW9kYWw7XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIE1vZGFsLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBNb2RhbDtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiB0b29sdGlwLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBUb29sdGlwID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICd0b29sdGlwJztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLnRvb2x0aXAnO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBDTEFTU19QUkVGSVggPSAnYnMtdG9vbHRpcCc7XG4gICAgdmFyIEJTQ0xTX1BSRUZJWF9SRUdFWCA9IG5ldyBSZWdFeHAoXCIoXnxcXFxccylcIiArIENMQVNTX1BSRUZJWCArIFwiXFxcXFMrXCIsICdnJyk7XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgYW5pbWF0aW9uOiAnYm9vbGVhbicsXG4gICAgICB0ZW1wbGF0ZTogJ3N0cmluZycsXG4gICAgICB0aXRsZTogJyhzdHJpbmd8ZWxlbWVudHxmdW5jdGlvbiknLFxuICAgICAgdHJpZ2dlcjogJ3N0cmluZycsXG4gICAgICBkZWxheTogJyhudW1iZXJ8b2JqZWN0KScsXG4gICAgICBodG1sOiAnYm9vbGVhbicsXG4gICAgICBzZWxlY3RvcjogJyhzdHJpbmd8Ym9vbGVhbiknLFxuICAgICAgcGxhY2VtZW50OiAnKHN0cmluZ3xmdW5jdGlvbiknLFxuICAgICAgb2Zmc2V0OiAnKG51bWJlcnxzdHJpbmcpJyxcbiAgICAgIGNvbnRhaW5lcjogJyhzdHJpbmd8ZWxlbWVudHxib29sZWFuKScsXG4gICAgICBmYWxsYmFja1BsYWNlbWVudDogJyhzdHJpbmd8YXJyYXkpJyxcbiAgICAgIGJvdW5kYXJ5OiAnKHN0cmluZ3xlbGVtZW50KSdcbiAgICB9O1xuICAgIHZhciBBdHRhY2htZW50TWFwID0ge1xuICAgICAgQVVUTzogJ2F1dG8nLFxuICAgICAgVE9QOiAndG9wJyxcbiAgICAgIFJJR0hUOiAncmlnaHQnLFxuICAgICAgQk9UVE9NOiAnYm90dG9tJyxcbiAgICAgIExFRlQ6ICdsZWZ0J1xuICAgIH07XG4gICAgdmFyIERlZmF1bHQgPSB7XG4gICAgICBhbmltYXRpb246IHRydWUsXG4gICAgICB0ZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJ0b29sdGlwXCIgcm9sZT1cInRvb2x0aXBcIj4nICsgJzxkaXYgY2xhc3M9XCJhcnJvd1wiPjwvZGl2PicgKyAnPGRpdiBjbGFzcz1cInRvb2x0aXAtaW5uZXJcIj48L2Rpdj48L2Rpdj4nLFxuICAgICAgdHJpZ2dlcjogJ2hvdmVyIGZvY3VzJyxcbiAgICAgIHRpdGxlOiAnJyxcbiAgICAgIGRlbGF5OiAwLFxuICAgICAgaHRtbDogZmFsc2UsXG4gICAgICBzZWxlY3RvcjogZmFsc2UsXG4gICAgICBwbGFjZW1lbnQ6ICd0b3AnLFxuICAgICAgb2Zmc2V0OiAwLFxuICAgICAgY29udGFpbmVyOiBmYWxzZSxcbiAgICAgIGZhbGxiYWNrUGxhY2VtZW50OiAnZmxpcCcsXG4gICAgICBib3VuZGFyeTogJ3Njcm9sbFBhcmVudCdcbiAgICB9O1xuICAgIHZhciBIb3ZlclN0YXRlID0ge1xuICAgICAgU0hPVzogJ3Nob3cnLFxuICAgICAgT1VUOiAnb3V0J1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgICBJTlNFUlRFRDogXCJpbnNlcnRlZFwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0s6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSxcbiAgICAgIEZPQ1VTSU46IFwiZm9jdXNpblwiICsgRVZFTlRfS0VZLFxuICAgICAgRk9DVVNPVVQ6IFwiZm9jdXNvdXRcIiArIEVWRU5UX0tFWSxcbiAgICAgIE1PVVNFRU5URVI6IFwibW91c2VlbnRlclwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VMRUFWRTogXCJtb3VzZWxlYXZlXCIgKyBFVkVOVF9LRVlcbiAgICB9O1xuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBGQURFOiAnZmFkZScsXG4gICAgICBTSE9XOiAnc2hvdydcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIFRPT0xUSVA6ICcudG9vbHRpcCcsXG4gICAgICBUT09MVElQX0lOTkVSOiAnLnRvb2x0aXAtaW5uZXInLFxuICAgICAgQVJST1c6ICcuYXJyb3cnXG4gICAgfTtcbiAgICB2YXIgVHJpZ2dlciA9IHtcbiAgICAgIEhPVkVSOiAnaG92ZXInLFxuICAgICAgRk9DVVM6ICdmb2N1cycsXG4gICAgICBDTElDSzogJ2NsaWNrJyxcbiAgICAgIE1BTlVBTDogJ21hbnVhbCdcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBUb29sdGlwID1cbiAgICAvKiNfX1BVUkVfXyovXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgZnVuY3Rpb24gVG9vbHRpcChlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrIGZvciBQb3BwZXIgZGVwZW5kZW5jeVxuICAgICAgICAgKiBQb3BwZXIgLSBodHRwczovL3BvcHBlci5qcy5vcmdcbiAgICAgICAgICovXG4gICAgICAgIGlmICh0eXBlb2YgUG9wcGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Jvb3RzdHJhcCB0b29sdGlwcyByZXF1aXJlIFBvcHBlci5qcyAoaHR0cHM6Ly9wb3BwZXIuanMub3JnKScpO1xuICAgICAgICB9IC8vIHByaXZhdGVcblxuXG4gICAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX3RpbWVvdXQgPSAwO1xuICAgICAgICB0aGlzLl9ob3ZlclN0YXRlID0gJyc7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRyaWdnZXIgPSB7fTtcbiAgICAgICAgdGhpcy5fcG9wcGVyID0gbnVsbDsgLy8gUHJvdGVjdGVkXG5cbiAgICAgICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy50aXAgPSBudWxsO1xuXG4gICAgICAgIHRoaXMuX3NldExpc3RlbmVycygpO1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IFRvb2x0aXAucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by5lbmFibGUgPSBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IHRydWU7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzYWJsZSA9IGZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gICAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnRvZ2dsZUVuYWJsZWQgPSBmdW5jdGlvbiB0b2dnbGVFbmFibGVkKCkge1xuICAgICAgICB0aGlzLl9pc0VuYWJsZWQgPSAhdGhpcy5faXNFbmFibGVkO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZShldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgIHZhciBkYXRhS2V5ID0gdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTtcbiAgICAgICAgICB2YXIgY29udGV4dCA9ICQkJDEoZXZlbnQuY3VycmVudFRhcmdldCkuZGF0YShkYXRhS2V5KTtcblxuICAgICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgICAgY29udGV4dCA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKGV2ZW50LmN1cnJlbnRUYXJnZXQsIHRoaXMuX2dldERlbGVnYXRlQ29uZmlnKCkpO1xuICAgICAgICAgICAgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXksIGNvbnRleHQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnRleHQuX2FjdGl2ZVRyaWdnZXIuY2xpY2sgPSAhY29udGV4dC5fYWN0aXZlVHJpZ2dlci5jbGljaztcblxuICAgICAgICAgIGlmIChjb250ZXh0Ll9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkpIHtcbiAgICAgICAgICAgIGNvbnRleHQuX2VudGVyKG51bGwsIGNvbnRleHQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250ZXh0Ll9sZWF2ZShudWxsLCBjb250ZXh0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSkge1xuICAgICAgICAgICAgdGhpcy5fbGVhdmUobnVsbCwgdGhpcyk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl9lbnRlcihudWxsLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fdGltZW91dCk7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLmVsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVkpO1xuICAgICAgICAkJCQxKHRoaXMuZWxlbWVudCkub2ZmKHRoaXMuY29uc3RydWN0b3IuRVZFTlRfS0VZKTtcbiAgICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLmNsb3Nlc3QoJy5tb2RhbCcpLm9mZignaGlkZS5icy5tb2RhbCcpO1xuXG4gICAgICAgIGlmICh0aGlzLnRpcCkge1xuICAgICAgICAgICQkJDEodGhpcy50aXApLnJlbW92ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faXNFbmFibGVkID0gbnVsbDtcbiAgICAgICAgdGhpcy5fdGltZW91dCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2hvdmVyU3RhdGUgPSBudWxsO1xuICAgICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyID0gbnVsbDtcblxuICAgICAgICBpZiAodGhpcy5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5fcG9wcGVyLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3BvcHBlciA9IG51bGw7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuY29uZmlnID0gbnVsbDtcbiAgICAgICAgdGhpcy50aXAgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNob3cgPSBmdW5jdGlvbiBzaG93KCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICgkJCQxKHRoaXMuZWxlbWVudCkuY3NzKCdkaXNwbGF5JykgPT09ICdub25lJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHVzZSBzaG93IG9uIHZpc2libGUgZWxlbWVudHMnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzaG93RXZlbnQgPSAkJCQxLkV2ZW50KHRoaXMuY29uc3RydWN0b3IuRXZlbnQuU0hPVyk7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNXaXRoQ29udGVudCgpICYmIHRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgICAgICQkJDEodGhpcy5lbGVtZW50KS50cmlnZ2VyKHNob3dFdmVudCk7XG4gICAgICAgICAgdmFyIGlzSW5UaGVEb20gPSAkJCQxLmNvbnRhaW5zKHRoaXMuZWxlbWVudC5vd25lckRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy5lbGVtZW50KTtcblxuICAgICAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgIWlzSW5UaGVEb20pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdGlwID0gdGhpcy5nZXRUaXBFbGVtZW50KCk7XG4gICAgICAgICAgdmFyIHRpcElkID0gVXRpbC5nZXRVSUQodGhpcy5jb25zdHJ1Y3Rvci5OQU1FKTtcbiAgICAgICAgICB0aXAuc2V0QXR0cmlidXRlKCdpZCcsIHRpcElkKTtcbiAgICAgICAgICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWRlc2NyaWJlZGJ5JywgdGlwSWQpO1xuICAgICAgICAgIHRoaXMuc2V0Q29udGVudCgpO1xuXG4gICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmFuaW1hdGlvbikge1xuICAgICAgICAgICAgJCQkMSh0aXApLmFkZENsYXNzKENsYXNzTmFtZS5GQURFKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcGxhY2VtZW50ID0gdHlwZW9mIHRoaXMuY29uZmlnLnBsYWNlbWVudCA9PT0gJ2Z1bmN0aW9uJyA/IHRoaXMuY29uZmlnLnBsYWNlbWVudC5jYWxsKHRoaXMsIHRpcCwgdGhpcy5lbGVtZW50KSA6IHRoaXMuY29uZmlnLnBsYWNlbWVudDtcblxuICAgICAgICAgIHZhciBhdHRhY2htZW50ID0gdGhpcy5fZ2V0QXR0YWNobWVudChwbGFjZW1lbnQpO1xuXG4gICAgICAgICAgdGhpcy5hZGRBdHRhY2htZW50Q2xhc3MoYXR0YWNobWVudCk7XG4gICAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuY29uZmlnLmNvbnRhaW5lciA9PT0gZmFsc2UgPyBkb2N1bWVudC5ib2R5IDogJCQkMShkb2N1bWVudCkuZmluZCh0aGlzLmNvbmZpZy5jb250YWluZXIpO1xuICAgICAgICAgICQkJDEodGlwKS5kYXRhKHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVksIHRoaXMpO1xuXG4gICAgICAgICAgaWYgKCEkJCQxLmNvbnRhaW5zKHRoaXMuZWxlbWVudC5vd25lckRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgdGhpcy50aXApKSB7XG4gICAgICAgICAgICAkJCQxKHRpcCkuYXBwZW5kVG8oY29udGFpbmVyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAkJCQxKHRoaXMuZWxlbWVudCkudHJpZ2dlcih0aGlzLmNvbnN0cnVjdG9yLkV2ZW50LklOU0VSVEVEKTtcbiAgICAgICAgICB0aGlzLl9wb3BwZXIgPSBuZXcgUG9wcGVyKHRoaXMuZWxlbWVudCwgdGlwLCB7XG4gICAgICAgICAgICBwbGFjZW1lbnQ6IGF0dGFjaG1lbnQsXG4gICAgICAgICAgICBtb2RpZmllcnM6IHtcbiAgICAgICAgICAgICAgb2Zmc2V0OiB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0OiB0aGlzLmNvbmZpZy5vZmZzZXRcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZmxpcDoge1xuICAgICAgICAgICAgICAgIGJlaGF2aW9yOiB0aGlzLmNvbmZpZy5mYWxsYmFja1BsYWNlbWVudFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBhcnJvdzoge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IFNlbGVjdG9yLkFSUk9XXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHByZXZlbnRPdmVyZmxvdzoge1xuICAgICAgICAgICAgICAgIGJvdW5kYXJpZXNFbGVtZW50OiB0aGlzLmNvbmZpZy5ib3VuZGFyeVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25DcmVhdGU6IGZ1bmN0aW9uIG9uQ3JlYXRlKGRhdGEpIHtcbiAgICAgICAgICAgICAgaWYgKGRhdGEub3JpZ2luYWxQbGFjZW1lbnQgIT09IGRhdGEucGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2hhbmRsZVBvcHBlclBsYWNlbWVudENoYW5nZShkYXRhKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uVXBkYXRlOiBmdW5jdGlvbiBvblVwZGF0ZShkYXRhKSB7XG4gICAgICAgICAgICAgIF90aGlzLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UoZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJCQkMSh0aXApLmFkZENsYXNzKENsYXNzTmFtZS5TSE9XKTsgLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIGFkZCBleHRyYVxuICAgICAgICAgIC8vIGVtcHR5IG1vdXNlb3ZlciBsaXN0ZW5lcnMgdG8gdGhlIGJvZHkncyBpbW1lZGlhdGUgY2hpbGRyZW47XG4gICAgICAgICAgLy8gb25seSBuZWVkZWQgYmVjYXVzZSBvZiBicm9rZW4gZXZlbnQgZGVsZWdhdGlvbiBvbiBpT1NcbiAgICAgICAgICAvLyBodHRwczovL3d3dy5xdWlya3Ntb2RlLm9yZy9ibG9nL2FyY2hpdmVzLzIwMTQvMDIvbW91c2VfZXZlbnRfYnViLmh0bWxcblxuICAgICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuY2hpbGRyZW4oKS5vbignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuYW5pbWF0aW9uKSB7XG4gICAgICAgICAgICAgIF90aGlzLl9maXhUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwcmV2SG92ZXJTdGF0ZSA9IF90aGlzLl9ob3ZlclN0YXRlO1xuICAgICAgICAgICAgX3RoaXMuX2hvdmVyU3RhdGUgPSBudWxsO1xuICAgICAgICAgICAgJCQkMShfdGhpcy5lbGVtZW50KS50cmlnZ2VyKF90aGlzLmNvbnN0cnVjdG9yLkV2ZW50LlNIT1dOKTtcblxuICAgICAgICAgICAgaWYgKHByZXZIb3ZlclN0YXRlID09PSBIb3ZlclN0YXRlLk9VVCkge1xuICAgICAgICAgICAgICBfdGhpcy5fbGVhdmUobnVsbCwgX3RoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBpZiAoJCQkMSh0aGlzLnRpcCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCh0aGlzLnRpcCk7XG4gICAgICAgICAgICAkJCQxKHRoaXMudGlwKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY29tcGxldGUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uaGlkZSA9IGZ1bmN0aW9uIGhpZGUoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgdmFyIHRpcCA9IHRoaXMuZ2V0VGlwRWxlbWVudCgpO1xuICAgICAgICB2YXIgaGlkZUV2ZW50ID0gJCQkMS5FdmVudCh0aGlzLmNvbnN0cnVjdG9yLkV2ZW50LkhJREUpO1xuXG4gICAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICAgIGlmIChfdGhpczIuX2hvdmVyU3RhdGUgIT09IEhvdmVyU3RhdGUuU0hPVyAmJiB0aXAucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgdGlwLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGlwKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBfdGhpczIuX2NsZWFuVGlwQ2xhc3MoKTtcblxuICAgICAgICAgIF90aGlzMi5lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScpO1xuXG4gICAgICAgICAgJCQkMShfdGhpczIuZWxlbWVudCkudHJpZ2dlcihfdGhpczIuY29uc3RydWN0b3IuRXZlbnQuSElEREVOKTtcblxuICAgICAgICAgIGlmIChfdGhpczIuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgX3RoaXMyLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLnRyaWdnZXIoaGlkZUV2ZW50KTtcblxuICAgICAgICBpZiAoaGlkZUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aXApLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTsgLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIHJlbW92ZSB0aGUgZXh0cmFcbiAgICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB3ZSBhZGRlZCBmb3IgaU9TIHN1cHBvcnRcblxuICAgICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5jaGlsZHJlbigpLm9mZignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2FjdGl2ZVRyaWdnZXJbVHJpZ2dlci5DTElDS10gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlcltUcmlnZ2VyLkZPQ1VTXSA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyW1RyaWdnZXIuSE9WRVJdID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCQkJDEodGhpcy50aXApLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRpcCk7XG4gICAgICAgICAgJCQkMSh0aXApLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5faG92ZXJTdGF0ZSA9ICcnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMuX3BvcHBlci5zY2hlZHVsZVVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9OyAvLyBQcm90ZWN0ZWRcblxuXG4gICAgICBfcHJvdG8uaXNXaXRoQ29udGVudCA9IGZ1bmN0aW9uIGlzV2l0aENvbnRlbnQoKSB7XG4gICAgICAgIHJldHVybiBCb29sZWFuKHRoaXMuZ2V0VGl0bGUoKSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uYWRkQXR0YWNobWVudENsYXNzID0gZnVuY3Rpb24gYWRkQXR0YWNobWVudENsYXNzKGF0dGFjaG1lbnQpIHtcbiAgICAgICAgJCQkMSh0aGlzLmdldFRpcEVsZW1lbnQoKSkuYWRkQ2xhc3MoQ0xBU1NfUFJFRklYICsgXCItXCIgKyBhdHRhY2htZW50KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5nZXRUaXBFbGVtZW50ID0gZnVuY3Rpb24gZ2V0VGlwRWxlbWVudCgpIHtcbiAgICAgICAgdGhpcy50aXAgPSB0aGlzLnRpcCB8fCAkJCQxKHRoaXMuY29uZmlnLnRlbXBsYXRlKVswXTtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlwO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNldENvbnRlbnQgPSBmdW5jdGlvbiBzZXRDb250ZW50KCkge1xuICAgICAgICB2YXIgdGlwID0gdGhpcy5nZXRUaXBFbGVtZW50KCk7XG4gICAgICAgIHRoaXMuc2V0RWxlbWVudENvbnRlbnQoJCQkMSh0aXAucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5UT09MVElQX0lOTkVSKSksIHRoaXMuZ2V0VGl0bGUoKSk7XG4gICAgICAgICQkJDEodGlwKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuRkFERSArIFwiIFwiICsgQ2xhc3NOYW1lLlNIT1cpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNldEVsZW1lbnRDb250ZW50ID0gZnVuY3Rpb24gc2V0RWxlbWVudENvbnRlbnQoJGVsZW1lbnQsIGNvbnRlbnQpIHtcbiAgICAgICAgdmFyIGh0bWwgPSB0aGlzLmNvbmZpZy5odG1sO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gJ29iamVjdCcgJiYgKGNvbnRlbnQubm9kZVR5cGUgfHwgY29udGVudC5qcXVlcnkpKSB7XG4gICAgICAgICAgLy8gQ29udGVudCBpcyBhIERPTSBub2RlIG9yIGEgalF1ZXJ5XG4gICAgICAgICAgaWYgKGh0bWwpIHtcbiAgICAgICAgICAgIGlmICghJCQkMShjb250ZW50KS5wYXJlbnQoKS5pcygkZWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgJGVsZW1lbnQuZW1wdHkoKS5hcHBlbmQoY29udGVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICRlbGVtZW50LnRleHQoJCQkMShjb250ZW50KS50ZXh0KCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAkZWxlbWVudFtodG1sID8gJ2h0bWwnIDogJ3RleHQnXShjb250ZW50KTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmdldFRpdGxlID0gZnVuY3Rpb24gZ2V0VGl0bGUoKSB7XG4gICAgICAgIHZhciB0aXRsZSA9IHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtb3JpZ2luYWwtdGl0bGUnKTtcblxuICAgICAgICBpZiAoIXRpdGxlKSB7XG4gICAgICAgICAgdGl0bGUgPSB0eXBlb2YgdGhpcy5jb25maWcudGl0bGUgPT09ICdmdW5jdGlvbicgPyB0aGlzLmNvbmZpZy50aXRsZS5jYWxsKHRoaXMuZWxlbWVudCkgOiB0aGlzLmNvbmZpZy50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aXRsZTtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldEF0dGFjaG1lbnQgPSBmdW5jdGlvbiBfZ2V0QXR0YWNobWVudChwbGFjZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIEF0dGFjaG1lbnRNYXBbcGxhY2VtZW50LnRvVXBwZXJDYXNlKCldO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBfc2V0TGlzdGVuZXJzKCkge1xuICAgICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgICB2YXIgdHJpZ2dlcnMgPSB0aGlzLmNvbmZpZy50cmlnZ2VyLnNwbGl0KCcgJyk7XG4gICAgICAgIHRyaWdnZXJzLmZvckVhY2goZnVuY3Rpb24gKHRyaWdnZXIpIHtcbiAgICAgICAgICBpZiAodHJpZ2dlciA9PT0gJ2NsaWNrJykge1xuICAgICAgICAgICAgJCQkMShfdGhpczMuZWxlbWVudCkub24oX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50LkNMSUNLLCBfdGhpczMuY29uZmlnLnNlbGVjdG9yLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIF90aGlzMy50b2dnbGUoZXZlbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0cmlnZ2VyICE9PSBUcmlnZ2VyLk1BTlVBTCkge1xuICAgICAgICAgICAgdmFyIGV2ZW50SW4gPSB0cmlnZ2VyID09PSBUcmlnZ2VyLkhPVkVSID8gX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50Lk1PVVNFRU5URVIgOiBfdGhpczMuY29uc3RydWN0b3IuRXZlbnQuRk9DVVNJTjtcbiAgICAgICAgICAgIHZhciBldmVudE91dCA9IHRyaWdnZXIgPT09IFRyaWdnZXIuSE9WRVIgPyBfdGhpczMuY29uc3RydWN0b3IuRXZlbnQuTU9VU0VMRUFWRSA6IF90aGlzMy5jb25zdHJ1Y3Rvci5FdmVudC5GT0NVU09VVDtcbiAgICAgICAgICAgICQkJDEoX3RoaXMzLmVsZW1lbnQpLm9uKGV2ZW50SW4sIF90aGlzMy5jb25maWcuc2VsZWN0b3IsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICByZXR1cm4gX3RoaXMzLl9lbnRlcihldmVudCk7XG4gICAgICAgICAgICB9KS5vbihldmVudE91dCwgX3RoaXMzLmNvbmZpZy5zZWxlY3RvciwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgIHJldHVybiBfdGhpczMuX2xlYXZlKGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICQkJDEoX3RoaXMzLmVsZW1lbnQpLmNsb3Nlc3QoJy5tb2RhbCcpLm9uKCdoaWRlLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzMy5oaWRlKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5zZWxlY3Rvcikge1xuICAgICAgICAgIHRoaXMuY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgdGhpcy5jb25maWcsIHtcbiAgICAgICAgICAgIHRyaWdnZXI6ICdtYW51YWwnLFxuICAgICAgICAgICAgc2VsZWN0b3I6ICcnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fZml4VGl0bGUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9maXhUaXRsZSA9IGZ1bmN0aW9uIF9maXhUaXRsZSgpIHtcbiAgICAgICAgdmFyIHRpdGxlVHlwZSA9IHR5cGVvZiB0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLW9yaWdpbmFsLXRpdGxlJyk7XG5cbiAgICAgICAgaWYgKHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykgfHwgdGl0bGVUeXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtb3JpZ2luYWwtdGl0bGUnLCB0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCd0aXRsZScpIHx8ICcnKTtcbiAgICAgICAgICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCd0aXRsZScsICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9lbnRlciA9IGZ1bmN0aW9uIF9lbnRlcihldmVudCwgY29udGV4dCkge1xuICAgICAgICB2YXIgZGF0YUtleSA9IHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVk7XG4gICAgICAgIGNvbnRleHQgPSBjb250ZXh0IHx8ICQkJDEoZXZlbnQuY3VycmVudFRhcmdldCkuZGF0YShkYXRhS2V5KTtcblxuICAgICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgICBjb250ZXh0ID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZXZlbnQuY3VycmVudFRhcmdldCwgdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSk7XG4gICAgICAgICAgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXksIGNvbnRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgY29udGV4dC5fYWN0aXZlVHJpZ2dlcltldmVudC50eXBlID09PSAnZm9jdXNpbicgPyBUcmlnZ2VyLkZPQ1VTIDogVHJpZ2dlci5IT1ZFUl0gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCQkJDEoY29udGV4dC5nZXRUaXBFbGVtZW50KCkpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSB8fCBjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIb3ZlclN0YXRlLlNIT1cpIHtcbiAgICAgICAgICBjb250ZXh0Ll9ob3ZlclN0YXRlID0gSG92ZXJTdGF0ZS5TSE9XO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsZWFyVGltZW91dChjb250ZXh0Ll90aW1lb3V0KTtcbiAgICAgICAgY29udGV4dC5faG92ZXJTdGF0ZSA9IEhvdmVyU3RhdGUuU0hPVztcblxuICAgICAgICBpZiAoIWNvbnRleHQuY29uZmlnLmRlbGF5IHx8ICFjb250ZXh0LmNvbmZpZy5kZWxheS5zaG93KSB7XG4gICAgICAgICAgY29udGV4dC5zaG93KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5fdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIb3ZlclN0YXRlLlNIT1cpIHtcbiAgICAgICAgICAgIGNvbnRleHQuc2hvdygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgY29udGV4dC5jb25maWcuZGVsYXkuc2hvdyk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2xlYXZlID0gZnVuY3Rpb24gX2xlYXZlKGV2ZW50LCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBkYXRhS2V5ID0gdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTtcbiAgICAgICAgY29udGV4dCA9IGNvbnRleHQgfHwgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXkpO1xuXG4gICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgIGNvbnRleHQgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihldmVudC5jdXJyZW50VGFyZ2V0LCB0aGlzLl9nZXREZWxlZ2F0ZUNvbmZpZygpKTtcbiAgICAgICAgICAkJCQxKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmRhdGEoZGF0YUtleSwgY29udGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICBjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyW2V2ZW50LnR5cGUgPT09ICdmb2N1c291dCcgPyBUcmlnZ2VyLkZPQ1VTIDogVHJpZ2dlci5IT1ZFUl0gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb250ZXh0Ll9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjbGVhclRpbWVvdXQoY29udGV4dC5fdGltZW91dCk7XG4gICAgICAgIGNvbnRleHQuX2hvdmVyU3RhdGUgPSBIb3ZlclN0YXRlLk9VVDtcblxuICAgICAgICBpZiAoIWNvbnRleHQuY29uZmlnLmRlbGF5IHx8ICFjb250ZXh0LmNvbmZpZy5kZWxheS5oaWRlKSB7XG4gICAgICAgICAgY29udGV4dC5oaWRlKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5fdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIb3ZlclN0YXRlLk9VVCkge1xuICAgICAgICAgICAgY29udGV4dC5oaWRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCBjb250ZXh0LmNvbmZpZy5kZWxheS5oaWRlKTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5faXNXaXRoQWN0aXZlVHJpZ2dlciA9IGZ1bmN0aW9uIF9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkge1xuICAgICAgICBmb3IgKHZhciB0cmlnZ2VyIGluIHRoaXMuX2FjdGl2ZVRyaWdnZXIpIHtcbiAgICAgICAgICBpZiAodGhpcy5fYWN0aXZlVHJpZ2dlclt0cmlnZ2VyXSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgICBjb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHQsICQkJDEodGhpcy5lbGVtZW50KS5kYXRhKCksIHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZyA/IGNvbmZpZyA6IHt9KTtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZy5kZWxheSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb25maWcuZGVsYXkgPSB7XG4gICAgICAgICAgICBzaG93OiBjb25maWcuZGVsYXksXG4gICAgICAgICAgICBoaWRlOiBjb25maWcuZGVsYXlcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcudGl0bGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgY29uZmlnLnRpdGxlID0gY29uZmlnLnRpdGxlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZy5jb250ZW50ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGNvbmZpZy5jb250ZW50ID0gY29uZmlnLmNvbnRlbnQudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSk7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldERlbGVnYXRlQ29uZmlnID0gZnVuY3Rpb24gX2dldERlbGVnYXRlQ29uZmlnKCkge1xuICAgICAgICB2YXIgY29uZmlnID0ge307XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnKSB7XG4gICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuY29uZmlnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0W2tleV0gIT09IHRoaXMuY29uZmlnW2tleV0pIHtcbiAgICAgICAgICAgICAgY29uZmlnW2tleV0gPSB0aGlzLmNvbmZpZ1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2NsZWFuVGlwQ2xhc3MgPSBmdW5jdGlvbiBfY2xlYW5UaXBDbGFzcygpIHtcbiAgICAgICAgdmFyICR0aXAgPSAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKTtcbiAgICAgICAgdmFyIHRhYkNsYXNzID0gJHRpcC5hdHRyKCdjbGFzcycpLm1hdGNoKEJTQ0xTX1BSRUZJWF9SRUdFWCk7XG5cbiAgICAgICAgaWYgKHRhYkNsYXNzICE9PSBudWxsICYmIHRhYkNsYXNzLmxlbmd0aCkge1xuICAgICAgICAgICR0aXAucmVtb3ZlQ2xhc3ModGFiQ2xhc3Muam9pbignJykpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2hhbmRsZVBvcHBlclBsYWNlbWVudENoYW5nZSA9IGZ1bmN0aW9uIF9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UocG9wcGVyRGF0YSkge1xuICAgICAgICB2YXIgcG9wcGVySW5zdGFuY2UgPSBwb3BwZXJEYXRhLmluc3RhbmNlO1xuICAgICAgICB0aGlzLnRpcCA9IHBvcHBlckluc3RhbmNlLnBvcHBlcjtcblxuICAgICAgICB0aGlzLl9jbGVhblRpcENsYXNzKCk7XG5cbiAgICAgICAgdGhpcy5hZGRBdHRhY2htZW50Q2xhc3ModGhpcy5fZ2V0QXR0YWNobWVudChwb3BwZXJEYXRhLnBsYWNlbWVudCkpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9maXhUcmFuc2l0aW9uID0gZnVuY3Rpb24gX2ZpeFRyYW5zaXRpb24oKSB7XG4gICAgICAgIHZhciB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcbiAgICAgICAgdmFyIGluaXRDb25maWdBbmltYXRpb24gPSB0aGlzLmNvbmZpZy5hbmltYXRpb247XG5cbiAgICAgICAgaWYgKHRpcC5nZXRBdHRyaWJ1dGUoJ3gtcGxhY2VtZW50JykgIT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRpcCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkZBREUpO1xuICAgICAgICB0aGlzLmNvbmZpZy5hbmltYXRpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICB0aGlzLmNvbmZpZy5hbmltYXRpb24gPSBpbml0Q29uZmlnQW5pbWF0aW9uO1xuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgVG9vbHRpcC5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgdmFyIF9jb25maWcgPSB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyAmJiBjb25maWc7XG5cbiAgICAgICAgICBpZiAoIWRhdGEgJiYgL2Rpc3Bvc2V8aGlkZS8udGVzdChjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IFRvb2x0aXAodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKFRvb2x0aXAsIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJEZWZhdWx0XCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJOQU1FXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBOQU1FO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJEQVRBX0tFWVwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gREFUQV9LRVk7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkV2ZW50XCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBFdmVudDtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRVZFTlRfS0VZXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBFVkVOVF9LRVk7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRUeXBlXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gVG9vbHRpcDtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEuZm5bTkFNRV0gPSBUb29sdGlwLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IFRvb2x0aXA7XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIFRvb2x0aXAuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFRvb2x0aXA7XG4gIH0oJCwgUG9wcGVyKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBwb3BvdmVyLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBQb3BvdmVyID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdwb3BvdmVyJztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLnBvcG92ZXInO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBDTEFTU19QUkVGSVggPSAnYnMtcG9wb3Zlcic7XG4gICAgdmFyIEJTQ0xTX1BSRUZJWF9SRUdFWCA9IG5ldyBSZWdFeHAoXCIoXnxcXFxccylcIiArIENMQVNTX1BSRUZJWCArIFwiXFxcXFMrXCIsICdnJyk7XG5cbiAgICB2YXIgRGVmYXVsdCA9IF9vYmplY3RTcHJlYWQoe30sIFRvb2x0aXAuRGVmYXVsdCwge1xuICAgICAgcGxhY2VtZW50OiAncmlnaHQnLFxuICAgICAgdHJpZ2dlcjogJ2NsaWNrJyxcbiAgICAgIGNvbnRlbnQ6ICcnLFxuICAgICAgdGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwicG9wb3ZlclwiIHJvbGU9XCJ0b29sdGlwXCI+JyArICc8ZGl2IGNsYXNzPVwiYXJyb3dcIj48L2Rpdj4nICsgJzxoMyBjbGFzcz1cInBvcG92ZXItaGVhZGVyXCI+PC9oMz4nICsgJzxkaXYgY2xhc3M9XCJwb3BvdmVyLWJvZHlcIj48L2Rpdj48L2Rpdj4nXG4gICAgfSk7XG5cbiAgICB2YXIgRGVmYXVsdFR5cGUgPSBfb2JqZWN0U3ByZWFkKHt9LCBUb29sdGlwLkRlZmF1bHRUeXBlLCB7XG4gICAgICBjb250ZW50OiAnKHN0cmluZ3xlbGVtZW50fGZ1bmN0aW9uKSdcbiAgICB9KTtcblxuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBGQURFOiAnZmFkZScsXG4gICAgICBTSE9XOiAnc2hvdydcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIFRJVExFOiAnLnBvcG92ZXItaGVhZGVyJyxcbiAgICAgIENPTlRFTlQ6ICcucG9wb3Zlci1ib2R5J1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgICBJTlNFUlRFRDogXCJpbnNlcnRlZFwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0s6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSxcbiAgICAgIEZPQ1VTSU46IFwiZm9jdXNpblwiICsgRVZFTlRfS0VZLFxuICAgICAgRk9DVVNPVVQ6IFwiZm9jdXNvdXRcIiArIEVWRU5UX0tFWSxcbiAgICAgIE1PVVNFRU5URVI6IFwibW91c2VlbnRlclwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VMRUFWRTogXCJtb3VzZWxlYXZlXCIgKyBFVkVOVF9LRVlcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBQb3BvdmVyID1cbiAgICAvKiNfX1BVUkVfXyovXG4gICAgZnVuY3Rpb24gKF9Ub29sdGlwKSB7XG4gICAgICBfaW5oZXJpdHNMb29zZShQb3BvdmVyLCBfVG9vbHRpcCk7XG5cbiAgICAgIGZ1bmN0aW9uIFBvcG92ZXIoKSB7XG4gICAgICAgIHJldHVybiBfVG9vbHRpcC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICB9XG5cbiAgICAgIHZhciBfcHJvdG8gPSBQb3BvdmVyLnByb3RvdHlwZTtcblxuICAgICAgLy8gT3ZlcnJpZGVzXG4gICAgICBfcHJvdG8uaXNXaXRoQ29udGVudCA9IGZ1bmN0aW9uIGlzV2l0aENvbnRlbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFRpdGxlKCkgfHwgdGhpcy5fZ2V0Q29udGVudCgpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmFkZEF0dGFjaG1lbnRDbGFzcyA9IGZ1bmN0aW9uIGFkZEF0dGFjaG1lbnRDbGFzcyhhdHRhY2htZW50KSB7XG4gICAgICAgICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpLmFkZENsYXNzKENMQVNTX1BSRUZJWCArIFwiLVwiICsgYXR0YWNobWVudCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZ2V0VGlwRWxlbWVudCA9IGZ1bmN0aW9uIGdldFRpcEVsZW1lbnQoKSB7XG4gICAgICAgIHRoaXMudGlwID0gdGhpcy50aXAgfHwgJCQkMSh0aGlzLmNvbmZpZy50ZW1wbGF0ZSlbMF07XG4gICAgICAgIHJldHVybiB0aGlzLnRpcDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5zZXRDb250ZW50ID0gZnVuY3Rpb24gc2V0Q29udGVudCgpIHtcbiAgICAgICAgdmFyICR0aXAgPSAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKTsgLy8gV2UgdXNlIGFwcGVuZCBmb3IgaHRtbCBvYmplY3RzIHRvIG1haW50YWluIGpzIGV2ZW50c1xuXG4gICAgICAgIHRoaXMuc2V0RWxlbWVudENvbnRlbnQoJHRpcC5maW5kKFNlbGVjdG9yLlRJVExFKSwgdGhpcy5nZXRUaXRsZSgpKTtcblxuICAgICAgICB2YXIgY29udGVudCA9IHRoaXMuX2dldENvbnRlbnQoKTtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICBjb250ZW50ID0gY29udGVudC5jYWxsKHRoaXMuZWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldEVsZW1lbnRDb250ZW50KCR0aXAuZmluZChTZWxlY3Rvci5DT05URU5UKSwgY29udGVudCk7XG4gICAgICAgICR0aXAucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkZBREUgKyBcIiBcIiArIENsYXNzTmFtZS5TSE9XKTtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldENvbnRlbnQgPSBmdW5jdGlvbiBfZ2V0Q29udGVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtY29udGVudCcpIHx8IHRoaXMuY29uZmlnLmNvbnRlbnQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2NsZWFuVGlwQ2xhc3MgPSBmdW5jdGlvbiBfY2xlYW5UaXBDbGFzcygpIHtcbiAgICAgICAgdmFyICR0aXAgPSAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKTtcbiAgICAgICAgdmFyIHRhYkNsYXNzID0gJHRpcC5hdHRyKCdjbGFzcycpLm1hdGNoKEJTQ0xTX1BSRUZJWF9SRUdFWCk7XG5cbiAgICAgICAgaWYgKHRhYkNsYXNzICE9PSBudWxsICYmIHRhYkNsYXNzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAkdGlwLnJlbW92ZUNsYXNzKHRhYkNsYXNzLmpvaW4oJycpKTtcbiAgICAgICAgfVxuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgUG9wb3Zlci5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgdmFyIF9jb25maWcgPSB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IG51bGw7XG5cbiAgICAgICAgICBpZiAoIWRhdGEgJiYgL2Rlc3Ryb3l8aGlkZS8udGVzdChjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IFBvcG92ZXIodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKFBvcG92ZXIsIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICAgIC8vIEdldHRlcnNcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIk5BTUVcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIE5BTUU7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRBVEFfS0VZXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEQVRBX0tFWTtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRXZlbnRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJFVkVOVF9LRVlcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFR5cGVcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHRUeXBlO1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBQb3BvdmVyO1xuICAgIH0oVG9vbHRpcCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEuZm5bTkFNRV0gPSBQb3BvdmVyLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IFBvcG92ZXI7XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIFBvcG92ZXIuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFBvcG92ZXI7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogc2Nyb2xsc3B5LmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBTY3JvbGxTcHkgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ3Njcm9sbHNweSc7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5zY3JvbGxzcHknO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgIG9mZnNldDogMTAsXG4gICAgICBtZXRob2Q6ICdhdXRvJyxcbiAgICAgIHRhcmdldDogJydcbiAgICB9O1xuICAgIHZhciBEZWZhdWx0VHlwZSA9IHtcbiAgICAgIG9mZnNldDogJ251bWJlcicsXG4gICAgICBtZXRob2Q6ICdzdHJpbmcnLFxuICAgICAgdGFyZ2V0OiAnKHN0cmluZ3xlbGVtZW50KSdcbiAgICB9O1xuICAgIHZhciBFdmVudCA9IHtcbiAgICAgIEFDVElWQVRFOiBcImFjdGl2YXRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBTQ1JPTEw6IFwic2Nyb2xsXCIgKyBFVkVOVF9LRVksXG4gICAgICBMT0FEX0RBVEFfQVBJOiBcImxvYWRcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIERST1BET1dOX0lURU06ICdkcm9wZG93bi1pdGVtJyxcbiAgICAgIERST1BET1dOX01FTlU6ICdkcm9wZG93bi1tZW51JyxcbiAgICAgIEFDVElWRTogJ2FjdGl2ZSdcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIERBVEFfU1BZOiAnW2RhdGEtc3B5PVwic2Nyb2xsXCJdJyxcbiAgICAgIEFDVElWRTogJy5hY3RpdmUnLFxuICAgICAgTkFWX0xJU1RfR1JPVVA6ICcubmF2LCAubGlzdC1ncm91cCcsXG4gICAgICBOQVZfTElOS1M6ICcubmF2LWxpbmsnLFxuICAgICAgTkFWX0lURU1TOiAnLm5hdi1pdGVtJyxcbiAgICAgIExJU1RfSVRFTVM6ICcubGlzdC1ncm91cC1pdGVtJyxcbiAgICAgIERST1BET1dOOiAnLmRyb3Bkb3duJyxcbiAgICAgIERST1BET1dOX0lURU1TOiAnLmRyb3Bkb3duLWl0ZW0nLFxuICAgICAgRFJPUERPV05fVE9HR0xFOiAnLmRyb3Bkb3duLXRvZ2dsZSdcbiAgICB9O1xuICAgIHZhciBPZmZzZXRNZXRob2QgPSB7XG4gICAgICBPRkZTRVQ6ICdvZmZzZXQnLFxuICAgICAgUE9TSVRJT046ICdwb3NpdGlvbidcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBTY3JvbGxTcHkgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBTY3JvbGxTcHkoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuX3Njcm9sbEVsZW1lbnQgPSBlbGVtZW50LnRhZ05hbWUgPT09ICdCT0RZJyA/IHdpbmRvdyA6IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLl9zZWxlY3RvciA9IHRoaXMuX2NvbmZpZy50YXJnZXQgKyBcIiBcIiArIFNlbGVjdG9yLk5BVl9MSU5LUyArIFwiLFwiICsgKHRoaXMuX2NvbmZpZy50YXJnZXQgKyBcIiBcIiArIFNlbGVjdG9yLkxJU1RfSVRFTVMgKyBcIixcIikgKyAodGhpcy5fY29uZmlnLnRhcmdldCArIFwiIFwiICsgU2VsZWN0b3IuRFJPUERPV05fSVRFTVMpO1xuICAgICAgICB0aGlzLl9vZmZzZXRzID0gW107XG4gICAgICAgIHRoaXMuX3RhcmdldHMgPSBbXTtcbiAgICAgICAgdGhpcy5fYWN0aXZlVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2Nyb2xsSGVpZ2h0ID0gMDtcbiAgICAgICAgJCQkMSh0aGlzLl9zY3JvbGxFbGVtZW50KS5vbihFdmVudC5TQ1JPTEwsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIHJldHVybiBfdGhpcy5fcHJvY2VzcyhldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJlZnJlc2goKTtcblxuICAgICAgICB0aGlzLl9wcm9jZXNzKCk7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gU2Nyb2xsU3B5LnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8ucmVmcmVzaCA9IGZ1bmN0aW9uIHJlZnJlc2goKSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIHZhciBhdXRvTWV0aG9kID0gdGhpcy5fc2Nyb2xsRWxlbWVudCA9PT0gdGhpcy5fc2Nyb2xsRWxlbWVudC53aW5kb3cgPyBPZmZzZXRNZXRob2QuT0ZGU0VUIDogT2Zmc2V0TWV0aG9kLlBPU0lUSU9OO1xuICAgICAgICB2YXIgb2Zmc2V0TWV0aG9kID0gdGhpcy5fY29uZmlnLm1ldGhvZCA9PT0gJ2F1dG8nID8gYXV0b01ldGhvZCA6IHRoaXMuX2NvbmZpZy5tZXRob2Q7XG4gICAgICAgIHZhciBvZmZzZXRCYXNlID0gb2Zmc2V0TWV0aG9kID09PSBPZmZzZXRNZXRob2QuUE9TSVRJT04gPyB0aGlzLl9nZXRTY3JvbGxUb3AoKSA6IDA7XG4gICAgICAgIHRoaXMuX29mZnNldHMgPSBbXTtcbiAgICAgICAgdGhpcy5fdGFyZ2V0cyA9IFtdO1xuICAgICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSB0aGlzLl9nZXRTY3JvbGxIZWlnaHQoKTtcbiAgICAgICAgdmFyIHRhcmdldHMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5fc2VsZWN0b3IpKTtcbiAgICAgICAgdGFyZ2V0cy5tYXAoZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgdGFyZ2V0O1xuICAgICAgICAgIHZhciB0YXJnZXRTZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtZW50KTtcblxuICAgICAgICAgIGlmICh0YXJnZXRTZWxlY3Rvcikge1xuICAgICAgICAgICAgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0YXJnZXRTZWxlY3Rvcik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldEJDUiA9IHRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgaWYgKHRhcmdldEJDUi53aWR0aCB8fCB0YXJnZXRCQ1IuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgIC8vIFRPRE8gKGZhdCk6IHJlbW92ZSBza2V0Y2ggcmVsaWFuY2Ugb24galF1ZXJ5IHBvc2l0aW9uL29mZnNldFxuICAgICAgICAgICAgICByZXR1cm4gWyQkJDEodGFyZ2V0KVtvZmZzZXRNZXRob2RdKCkudG9wICsgb2Zmc2V0QmFzZSwgdGFyZ2V0U2VsZWN0b3JdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9KS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgICAgfSkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgIHJldHVybiBhWzBdIC0gYlswXTtcbiAgICAgICAgfSkuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgIF90aGlzMi5fb2Zmc2V0cy5wdXNoKGl0ZW1bMF0pO1xuXG4gICAgICAgICAgX3RoaXMyLl90YXJnZXRzLnB1c2goaXRlbVsxXSk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgICAkJCQxKHRoaXMuX3Njcm9sbEVsZW1lbnQpLm9mZihFVkVOVF9LRVkpO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2Nyb2xsRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IG51bGw7XG4gICAgICAgIHRoaXMuX3NlbGVjdG9yID0gbnVsbDtcbiAgICAgICAgdGhpcy5fb2Zmc2V0cyA9IG51bGw7XG4gICAgICAgIHRoaXMuX3RhcmdldHMgPSBudWxsO1xuICAgICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSBudWxsO1xuICAgICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSBudWxsO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0Q29uZmlnID0gZnVuY3Rpb24gX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgRGVmYXVsdCwgdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnLnRhcmdldCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB2YXIgaWQgPSAkJCQxKGNvbmZpZy50YXJnZXQpLmF0dHIoJ2lkJyk7XG5cbiAgICAgICAgICBpZiAoIWlkKSB7XG4gICAgICAgICAgICBpZCA9IFV0aWwuZ2V0VUlEKE5BTUUpO1xuICAgICAgICAgICAgJCQkMShjb25maWcudGFyZ2V0KS5hdHRyKCdpZCcsIGlkKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25maWcudGFyZ2V0ID0gXCIjXCIgKyBpZDtcbiAgICAgICAgfVxuXG4gICAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgRGVmYXVsdFR5cGUpO1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiBfZ2V0U2Nyb2xsVG9wKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudCA9PT0gd2luZG93ID8gdGhpcy5fc2Nyb2xsRWxlbWVudC5wYWdlWU9mZnNldCA6IHRoaXMuX3Njcm9sbEVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRTY3JvbGxIZWlnaHQgPSBmdW5jdGlvbiBfZ2V0U2Nyb2xsSGVpZ2h0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudC5zY3JvbGxIZWlnaHQgfHwgTWF0aC5tYXgoZG9jdW1lbnQuYm9keS5zY3JvbGxIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRPZmZzZXRIZWlnaHQgPSBmdW5jdGlvbiBfZ2V0T2Zmc2V0SGVpZ2h0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudCA9PT0gd2luZG93ID8gd2luZG93LmlubmVySGVpZ2h0IDogdGhpcy5fc2Nyb2xsRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3Byb2Nlc3MgPSBmdW5jdGlvbiBfcHJvY2VzcygpIHtcbiAgICAgICAgdmFyIHNjcm9sbFRvcCA9IHRoaXMuX2dldFNjcm9sbFRvcCgpICsgdGhpcy5fY29uZmlnLm9mZnNldDtcblxuICAgICAgICB2YXIgc2Nyb2xsSGVpZ2h0ID0gdGhpcy5fZ2V0U2Nyb2xsSGVpZ2h0KCk7XG5cbiAgICAgICAgdmFyIG1heFNjcm9sbCA9IHRoaXMuX2NvbmZpZy5vZmZzZXQgKyBzY3JvbGxIZWlnaHQgLSB0aGlzLl9nZXRPZmZzZXRIZWlnaHQoKTtcblxuICAgICAgICBpZiAodGhpcy5fc2Nyb2xsSGVpZ2h0ICE9PSBzY3JvbGxIZWlnaHQpIHtcbiAgICAgICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY3JvbGxUb3AgPj0gbWF4U2Nyb2xsKSB7XG4gICAgICAgICAgdmFyIHRhcmdldCA9IHRoaXMuX3RhcmdldHNbdGhpcy5fdGFyZ2V0cy5sZW5ndGggLSAxXTtcblxuICAgICAgICAgIGlmICh0aGlzLl9hY3RpdmVUYXJnZXQgIT09IHRhcmdldCkge1xuICAgICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGFyZ2V0KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fYWN0aXZlVGFyZ2V0ICYmIHNjcm9sbFRvcCA8IHRoaXMuX29mZnNldHNbMF0gJiYgdGhpcy5fb2Zmc2V0c1swXSA+IDApIHtcbiAgICAgICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSBudWxsO1xuXG4gICAgICAgICAgdGhpcy5fY2xlYXIoKTtcblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBvZmZzZXRMZW5ndGggPSB0aGlzLl9vZmZzZXRzLmxlbmd0aDtcblxuICAgICAgICBmb3IgKHZhciBpID0gb2Zmc2V0TGVuZ3RoOyBpLS07KSB7XG4gICAgICAgICAgdmFyIGlzQWN0aXZlVGFyZ2V0ID0gdGhpcy5fYWN0aXZlVGFyZ2V0ICE9PSB0aGlzLl90YXJnZXRzW2ldICYmIHNjcm9sbFRvcCA+PSB0aGlzLl9vZmZzZXRzW2ldICYmICh0eXBlb2YgdGhpcy5fb2Zmc2V0c1tpICsgMV0gPT09ICd1bmRlZmluZWQnIHx8IHNjcm9sbFRvcCA8IHRoaXMuX29mZnNldHNbaSArIDFdKTtcblxuICAgICAgICAgIGlmIChpc0FjdGl2ZVRhcmdldCkge1xuICAgICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGhpcy5fdGFyZ2V0c1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2FjdGl2YXRlID0gZnVuY3Rpb24gX2FjdGl2YXRlKHRhcmdldCkge1xuICAgICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSB0YXJnZXQ7XG5cbiAgICAgICAgdGhpcy5fY2xlYXIoKTtcblxuICAgICAgICB2YXIgcXVlcmllcyA9IHRoaXMuX3NlbGVjdG9yLnNwbGl0KCcsJyk7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBhcnJvdy1ib2R5LXN0eWxlXG5cblxuICAgICAgICBxdWVyaWVzID0gcXVlcmllcy5tYXAoZnVuY3Rpb24gKHNlbGVjdG9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGVjdG9yICsgXCJbZGF0YS10YXJnZXQ9XFxcIlwiICsgdGFyZ2V0ICsgXCJcXFwiXSxcIiArIChzZWxlY3RvciArIFwiW2hyZWY9XFxcIlwiICsgdGFyZ2V0ICsgXCJcXFwiXVwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciAkbGluayA9ICQkJDEoW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHF1ZXJpZXMuam9pbignLCcpKSkpO1xuXG4gICAgICAgIGlmICgkbGluay5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUERPV05fSVRFTSkpIHtcbiAgICAgICAgICAkbGluay5jbG9zZXN0KFNlbGVjdG9yLkRST1BET1dOKS5maW5kKFNlbGVjdG9yLkRST1BET1dOX1RPR0dMRSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgJGxpbmsuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU2V0IHRyaWdnZXJlZCBsaW5rIGFzIGFjdGl2ZVxuICAgICAgICAgICRsaW5rLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpOyAvLyBTZXQgdHJpZ2dlcmVkIGxpbmtzIHBhcmVudHMgYXMgYWN0aXZlXG4gICAgICAgICAgLy8gV2l0aCBib3RoIDx1bD4gYW5kIDxuYXY+IG1hcmt1cCBhIHBhcmVudCBpcyB0aGUgcHJldmlvdXMgc2libGluZyBvZiBhbnkgbmF2IGFuY2VzdG9yXG5cbiAgICAgICAgICAkbGluay5wYXJlbnRzKFNlbGVjdG9yLk5BVl9MSVNUX0dST1VQKS5wcmV2KFNlbGVjdG9yLk5BVl9MSU5LUyArIFwiLCBcIiArIFNlbGVjdG9yLkxJU1RfSVRFTVMpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpOyAvLyBIYW5kbGUgc3BlY2lhbCBjYXNlIHdoZW4gLm5hdi1saW5rIGlzIGluc2lkZSAubmF2LWl0ZW1cblxuICAgICAgICAgICRsaW5rLnBhcmVudHMoU2VsZWN0b3IuTkFWX0xJU1RfR1JPVVApLnByZXYoU2VsZWN0b3IuTkFWX0lURU1TKS5jaGlsZHJlbihTZWxlY3Rvci5OQVZfTElOS1MpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aGlzLl9zY3JvbGxFbGVtZW50KS50cmlnZ2VyKEV2ZW50LkFDVElWQVRFLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogdGFyZ2V0XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9jbGVhciA9IGZ1bmN0aW9uIF9jbGVhcigpIHtcbiAgICAgICAgdmFyIG5vZGVzID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHRoaXMuX3NlbGVjdG9yKSk7XG4gICAgICAgICQkJDEobm9kZXMpLmZpbHRlcihTZWxlY3Rvci5BQ1RJVkUpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgU2Nyb2xsU3B5Ll9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZztcblxuICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgZGF0YSA9IG5ldyBTY3JvbGxTcHkodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKFNjcm9sbFNweSwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIFNjcm9sbFNweTtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMSh3aW5kb3cpLm9uKEV2ZW50LkxPQURfREFUQV9BUEksIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBzY3JvbGxTcHlzID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLkRBVEFfU1BZKSk7XG4gICAgICB2YXIgc2Nyb2xsU3B5c0xlbmd0aCA9IHNjcm9sbFNweXMubGVuZ3RoO1xuXG4gICAgICBmb3IgKHZhciBpID0gc2Nyb2xsU3B5c0xlbmd0aDsgaS0tOykge1xuICAgICAgICB2YXIgJHNweSA9ICQkJDEoc2Nyb2xsU3B5c1tpXSk7XG5cbiAgICAgICAgU2Nyb2xsU3B5Ll9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkc3B5LCAkc3B5LmRhdGEoKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgICAkJCQxLmZuW05BTUVdID0gU2Nyb2xsU3B5Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IFNjcm9sbFNweTtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gU2Nyb2xsU3B5Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBTY3JvbGxTcHk7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogdGFiLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBUYWIgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ3RhYic7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy50YWInO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIENMSUNLX0RBVEFfQVBJOiBcImNsaWNrXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVlcbiAgICB9O1xuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBEUk9QRE9XTl9NRU5VOiAnZHJvcGRvd24tbWVudScsXG4gICAgICBBQ1RJVkU6ICdhY3RpdmUnLFxuICAgICAgRElTQUJMRUQ6ICdkaXNhYmxlZCcsXG4gICAgICBGQURFOiAnZmFkZScsXG4gICAgICBTSE9XOiAnc2hvdydcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIERST1BET1dOOiAnLmRyb3Bkb3duJyxcbiAgICAgIE5BVl9MSVNUX0dST1VQOiAnLm5hdiwgLmxpc3QtZ3JvdXAnLFxuICAgICAgQUNUSVZFOiAnLmFjdGl2ZScsXG4gICAgICBBQ1RJVkVfVUw6ICc+IGxpID4gLmFjdGl2ZScsXG4gICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cInRhYlwiXSwgW2RhdGEtdG9nZ2xlPVwicGlsbFwiXSwgW2RhdGEtdG9nZ2xlPVwibGlzdFwiXScsXG4gICAgICBEUk9QRE9XTl9UT0dHTEU6ICcuZHJvcGRvd24tdG9nZ2xlJyxcbiAgICAgIERST1BET1dOX0FDVElWRV9DSElMRDogJz4gLmRyb3Bkb3duLW1lbnUgLmFjdGl2ZSdcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBUYWIgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBUYWIoZWxlbWVudCkge1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICAgIHZhciBfcHJvdG8gPSBUYWIucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5fZWxlbWVudC5wYXJlbnROb2RlICYmIHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgJiYgJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuQUNUSVZFKSB8fCAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5ESVNBQkxFRCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGFyZ2V0O1xuICAgICAgICB2YXIgcHJldmlvdXM7XG4gICAgICAgIHZhciBsaXN0RWxlbWVudCA9ICQkJDEodGhpcy5fZWxlbWVudCkuY2xvc2VzdChTZWxlY3Rvci5OQVZfTElTVF9HUk9VUClbMF07XG4gICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0aGlzLl9lbGVtZW50KTtcblxuICAgICAgICBpZiAobGlzdEVsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgaXRlbVNlbGVjdG9yID0gbGlzdEVsZW1lbnQubm9kZU5hbWUgPT09ICdVTCcgPyBTZWxlY3Rvci5BQ1RJVkVfVUwgOiBTZWxlY3Rvci5BQ1RJVkU7XG4gICAgICAgICAgcHJldmlvdXMgPSAkJCQxLm1ha2VBcnJheSgkJCQxKGxpc3RFbGVtZW50KS5maW5kKGl0ZW1TZWxlY3RvcikpO1xuICAgICAgICAgIHByZXZpb3VzID0gcHJldmlvdXNbcHJldmlvdXMubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaGlkZUV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5ISURFLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogdGhpcy5fZWxlbWVudFxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHNob3dFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPVywge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHByZXZpb3VzXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICQkJDEocHJldmlvdXMpLnRyaWdnZXIoaGlkZUV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzaG93RXZlbnQpO1xuXG4gICAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgaGlkZUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgICAgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9hY3RpdmF0ZSh0aGlzLl9lbGVtZW50LCBsaXN0RWxlbWVudCk7XG5cbiAgICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgICAgICAgdmFyIGhpZGRlbkV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5ISURERU4sIHtcbiAgICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IF90aGlzLl9lbGVtZW50XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdmFyIHNob3duRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNIT1dOLCB7XG4gICAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBwcmV2aW91c1xuICAgICAgICAgIH0pO1xuICAgICAgICAgICQkJDEocHJldmlvdXMpLnRyaWdnZXIoaGlkZGVuRXZlbnQpO1xuICAgICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc2hvd25FdmVudCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgIHRoaXMuX2FjdGl2YXRlKHRhcmdldCwgdGFyZ2V0LnBhcmVudE5vZGUsIGNvbXBsZXRlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fYWN0aXZhdGUgPSBmdW5jdGlvbiBfYWN0aXZhdGUoZWxlbWVudCwgY29udGFpbmVyLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICB2YXIgYWN0aXZlRWxlbWVudHM7XG5cbiAgICAgICAgaWYgKGNvbnRhaW5lci5ub2RlTmFtZSA9PT0gJ1VMJykge1xuICAgICAgICAgIGFjdGl2ZUVsZW1lbnRzID0gJCQkMShjb250YWluZXIpLmZpbmQoU2VsZWN0b3IuQUNUSVZFX1VMKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhY3RpdmVFbGVtZW50cyA9ICQkJDEoY29udGFpbmVyKS5jaGlsZHJlbihTZWxlY3Rvci5BQ1RJVkUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFjdGl2ZSA9IGFjdGl2ZUVsZW1lbnRzWzBdO1xuICAgICAgICB2YXIgaXNUcmFuc2l0aW9uaW5nID0gY2FsbGJhY2sgJiYgYWN0aXZlICYmICQkJDEoYWN0aXZlKS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSk7XG5cbiAgICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMi5fdHJhbnNpdGlvbkNvbXBsZXRlKGVsZW1lbnQsIGFjdGl2ZSwgY2FsbGJhY2spO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChhY3RpdmUgJiYgaXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQoYWN0aXZlKTtcbiAgICAgICAgICAkJCQxKGFjdGl2ZSkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNvbXBsZXRlKS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fdHJhbnNpdGlvbkNvbXBsZXRlID0gZnVuY3Rpb24gX3RyYW5zaXRpb25Db21wbGV0ZShlbGVtZW50LCBhY3RpdmUsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChhY3RpdmUpIHtcbiAgICAgICAgICAkJCQxKGFjdGl2ZSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cgKyBcIiBcIiArIENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgIHZhciBkcm9wZG93bkNoaWxkID0gJCQkMShhY3RpdmUucGFyZW50Tm9kZSkuZmluZChTZWxlY3Rvci5EUk9QRE9XTl9BQ1RJVkVfQ0hJTEQpWzBdO1xuXG4gICAgICAgICAgaWYgKGRyb3Bkb3duQ2hpbGQpIHtcbiAgICAgICAgICAgICQkJDEoZHJvcGRvd25DaGlsZCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGFjdGl2ZS5nZXRBdHRyaWJ1dGUoJ3JvbGUnKSA9PT0gJ3RhYicpIHtcbiAgICAgICAgICAgIGFjdGl2ZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtc2VsZWN0ZWQnLCBmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgJCQkMShlbGVtZW50KS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcblxuICAgICAgICBpZiAoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3JvbGUnKSA9PT0gJ3RhYicpIHtcbiAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgVXRpbC5yZWZsb3coZWxlbWVudCk7XG4gICAgICAgICQkJDEoZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIGlmIChlbGVtZW50LnBhcmVudE5vZGUgJiYgJCQkMShlbGVtZW50LnBhcmVudE5vZGUpLmhhc0NsYXNzKENsYXNzTmFtZS5EUk9QRE9XTl9NRU5VKSkge1xuICAgICAgICAgIHZhciBkcm9wZG93bkVsZW1lbnQgPSAkJCQxKGVsZW1lbnQpLmNsb3Nlc3QoU2VsZWN0b3IuRFJPUERPV04pWzBdO1xuXG4gICAgICAgICAgaWYgKGRyb3Bkb3duRWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGRyb3Bkb3duVG9nZ2xlTGlzdCA9IFtdLnNsaWNlLmNhbGwoZHJvcGRvd25FbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuRFJPUERPV05fVE9HR0xFKSk7XG4gICAgICAgICAgICAkJCQxKGRyb3Bkb3duVG9nZ2xlTGlzdCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIFRhYi5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJCQkMSh0aGlzKTtcbiAgICAgICAgICB2YXIgZGF0YSA9ICR0aGlzLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IFRhYih0aGlzKTtcbiAgICAgICAgICAgICR0aGlzLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKFRhYiwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIFRhYjtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfVE9HR0xFLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIFRhYi5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMSh0aGlzKSwgJ3Nob3cnKTtcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBUYWIuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gVGFiO1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBUYWIuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFRhYjtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBpbmRleC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAoZnVuY3Rpb24gKCQkJDEpIHtcbiAgICBpZiAodHlwZW9mICQkJDEgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb290c3RyYXBcXCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgalF1ZXJ5LiBqUXVlcnkgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgQm9vdHN0cmFwXFwncyBKYXZhU2NyaXB0LicpO1xuICAgIH1cblxuICAgIHZhciB2ZXJzaW9uID0gJCQkMS5mbi5qcXVlcnkuc3BsaXQoJyAnKVswXS5zcGxpdCgnLicpO1xuICAgIHZhciBtaW5NYWpvciA9IDE7XG4gICAgdmFyIGx0TWFqb3IgPSAyO1xuICAgIHZhciBtaW5NaW5vciA9IDk7XG4gICAgdmFyIG1pblBhdGNoID0gMTtcbiAgICB2YXIgbWF4TWFqb3IgPSA0O1xuXG4gICAgaWYgKHZlcnNpb25bMF0gPCBsdE1ham9yICYmIHZlcnNpb25bMV0gPCBtaW5NaW5vciB8fCB2ZXJzaW9uWzBdID09PSBtaW5NYWpvciAmJiB2ZXJzaW9uWzFdID09PSBtaW5NaW5vciAmJiB2ZXJzaW9uWzJdIDwgbWluUGF0Y2ggfHwgdmVyc2lvblswXSA+PSBtYXhNYWpvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb290c3RyYXBcXCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgYXQgbGVhc3QgalF1ZXJ5IHYxLjkuMSBidXQgbGVzcyB0aGFuIHY0LjAuMCcpO1xuICAgIH1cbiAgfSkoJCk7XG5cbiAgZXhwb3J0cy5VdGlsID0gVXRpbDtcbiAgZXhwb3J0cy5BbGVydCA9IEFsZXJ0O1xuICBleHBvcnRzLkJ1dHRvbiA9IEJ1dHRvbjtcbiAgZXhwb3J0cy5DYXJvdXNlbCA9IENhcm91c2VsO1xuICBleHBvcnRzLkNvbGxhcHNlID0gQ29sbGFwc2U7XG4gIGV4cG9ydHMuRHJvcGRvd24gPSBEcm9wZG93bjtcbiAgZXhwb3J0cy5Nb2RhbCA9IE1vZGFsO1xuICBleHBvcnRzLlBvcG92ZXIgPSBQb3BvdmVyO1xuICBleHBvcnRzLlNjcm9sbHNweSA9IFNjcm9sbFNweTtcbiAgZXhwb3J0cy5UYWIgPSBUYWI7XG4gIGV4cG9ydHMuVG9vbHRpcCA9IFRvb2x0aXA7XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWJvb3RzdHJhcC5qcy5tYXBcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2pzL2Jvb3RzdHJhcC5qc1xuLy8gbW9kdWxlIGlkID0gMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiohXG4gKiBAZmlsZU92ZXJ2aWV3IEtpY2thc3MgbGlicmFyeSB0byBjcmVhdGUgYW5kIHBsYWNlIHBvcHBlcnMgbmVhciB0aGVpciByZWZlcmVuY2UgZWxlbWVudHMuXG4gKiBAdmVyc2lvbiAxLjE0LjRcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYgRmVkZXJpY28gWml2b2xvIGFuZCBjb250cmlidXRvcnNcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gKiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gKiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gKiBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiAqIFNPRlRXQVJFLlxuICovXG52YXIgaXNCcm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJztcblxudmFyIGxvbmdlclRpbWVvdXRCcm93c2VycyA9IFsnRWRnZScsICdUcmlkZW50JywgJ0ZpcmVmb3gnXTtcbnZhciB0aW1lb3V0RHVyYXRpb24gPSAwO1xuZm9yICh2YXIgaSA9IDA7IGkgPCBsb25nZXJUaW1lb3V0QnJvd3NlcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgaWYgKGlzQnJvd3NlciAmJiBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YobG9uZ2VyVGltZW91dEJyb3dzZXJzW2ldKSA+PSAwKSB7XG4gICAgdGltZW91dER1cmF0aW9uID0gMTtcbiAgICBicmVhaztcbiAgfVxufVxuXG5mdW5jdGlvbiBtaWNyb3Rhc2tEZWJvdW5jZShmbikge1xuICB2YXIgY2FsbGVkID0gZmFsc2U7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGNhbGxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsZWQgPSB0cnVlO1xuICAgIHdpbmRvdy5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxlZCA9IGZhbHNlO1xuICAgICAgZm4oKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdGFza0RlYm91bmNlKGZuKSB7XG4gIHZhciBzY2hlZHVsZWQgPSBmYWxzZTtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXNjaGVkdWxlZCkge1xuICAgICAgc2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBzY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgZm4oKTtcbiAgICAgIH0sIHRpbWVvdXREdXJhdGlvbik7XG4gICAgfVxuICB9O1xufVxuXG52YXIgc3VwcG9ydHNNaWNyb1Rhc2tzID0gaXNCcm93c2VyICYmIHdpbmRvdy5Qcm9taXNlO1xuXG4vKipcbiogQ3JlYXRlIGEgZGVib3VuY2VkIHZlcnNpb24gb2YgYSBtZXRob2QsIHRoYXQncyBhc3luY2hyb25vdXNseSBkZWZlcnJlZFxuKiBidXQgY2FsbGVkIGluIHRoZSBtaW5pbXVtIHRpbWUgcG9zc2libGUuXG4qXG4qIEBtZXRob2RcbiogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuKiBAYXJndW1lbnQge0Z1bmN0aW9ufSBmblxuKiBAcmV0dXJucyB7RnVuY3Rpb259XG4qL1xudmFyIGRlYm91bmNlID0gc3VwcG9ydHNNaWNyb1Rhc2tzID8gbWljcm90YXNrRGVib3VuY2UgOiB0YXNrRGVib3VuY2U7XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGdpdmVuIHZhcmlhYmxlIGlzIGEgZnVuY3Rpb25cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7QW55fSBmdW5jdGlvblRvQ2hlY2sgLSB2YXJpYWJsZSB0byBjaGVja1xuICogQHJldHVybnMge0Jvb2xlYW59IGFuc3dlciB0bzogaXMgYSBmdW5jdGlvbj9cbiAqL1xuZnVuY3Rpb24gaXNGdW5jdGlvbihmdW5jdGlvblRvQ2hlY2spIHtcbiAgdmFyIGdldFR5cGUgPSB7fTtcbiAgcmV0dXJuIGZ1bmN0aW9uVG9DaGVjayAmJiBnZXRUeXBlLnRvU3RyaW5nLmNhbGwoZnVuY3Rpb25Ub0NoZWNrKSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuLyoqXG4gKiBHZXQgQ1NTIGNvbXB1dGVkIHByb3BlcnR5IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VlbWVudH0gZWxlbWVudFxuICogQGFyZ3VtZW50IHtTdHJpbmd9IHByb3BlcnR5XG4gKi9cbmZ1bmN0aW9uIGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShlbGVtZW50LCBwcm9wZXJ0eSkge1xuICBpZiAoZWxlbWVudC5ub2RlVHlwZSAhPT0gMSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICAvLyBOT1RFOiAxIERPTSBhY2Nlc3MgaGVyZVxuICB2YXIgY3NzID0gZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50LCBudWxsKTtcbiAgcmV0dXJuIHByb3BlcnR5ID8gY3NzW3Byb3BlcnR5XSA6IGNzcztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwYXJlbnROb2RlIG9yIHRoZSBob3N0IG9mIHRoZSBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gZ2V0UGFyZW50Tm9kZShlbGVtZW50KSB7XG4gIGlmIChlbGVtZW50Lm5vZGVOYW1lID09PSAnSFRNTCcpIHtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuICByZXR1cm4gZWxlbWVudC5wYXJlbnROb2RlIHx8IGVsZW1lbnQuaG9zdDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzY3JvbGxpbmcgcGFyZW50IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBzY3JvbGwgcGFyZW50XG4gKi9cbmZ1bmN0aW9uIGdldFNjcm9sbFBhcmVudChlbGVtZW50KSB7XG4gIC8vIFJldHVybiBib2R5LCBgZ2V0U2Nyb2xsYCB3aWxsIHRha2UgY2FyZSB0byBnZXQgdGhlIGNvcnJlY3QgYHNjcm9sbFRvcGAgZnJvbSBpdFxuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuYm9keTtcbiAgfVxuXG4gIHN3aXRjaCAoZWxlbWVudC5ub2RlTmFtZSkge1xuICAgIGNhc2UgJ0hUTUwnOlxuICAgIGNhc2UgJ0JPRFknOlxuICAgICAgcmV0dXJuIGVsZW1lbnQub3duZXJEb2N1bWVudC5ib2R5O1xuICAgIGNhc2UgJyNkb2N1bWVudCc6XG4gICAgICByZXR1cm4gZWxlbWVudC5ib2R5O1xuICB9XG5cbiAgLy8gRmlyZWZveCB3YW50IHVzIHRvIGNoZWNrIGAteGAgYW5kIGAteWAgdmFyaWF0aW9ucyBhcyB3ZWxsXG5cbiAgdmFyIF9nZXRTdHlsZUNvbXB1dGVkUHJvcCA9IGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShlbGVtZW50KSxcbiAgICAgIG92ZXJmbG93ID0gX2dldFN0eWxlQ29tcHV0ZWRQcm9wLm92ZXJmbG93LFxuICAgICAgb3ZlcmZsb3dYID0gX2dldFN0eWxlQ29tcHV0ZWRQcm9wLm92ZXJmbG93WCxcbiAgICAgIG92ZXJmbG93WSA9IF9nZXRTdHlsZUNvbXB1dGVkUHJvcC5vdmVyZmxvd1k7XG5cbiAgaWYgKC8oYXV0b3xzY3JvbGx8b3ZlcmxheSkvLnRlc3Qob3ZlcmZsb3cgKyBvdmVyZmxvd1kgKyBvdmVyZmxvd1gpKSB7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICByZXR1cm4gZ2V0U2Nyb2xsUGFyZW50KGdldFBhcmVudE5vZGUoZWxlbWVudCkpO1xufVxuXG52YXIgaXNJRTExID0gaXNCcm93c2VyICYmICEhKHdpbmRvdy5NU0lucHV0TWV0aG9kQ29udGV4dCAmJiBkb2N1bWVudC5kb2N1bWVudE1vZGUpO1xudmFyIGlzSUUxMCA9IGlzQnJvd3NlciAmJiAvTVNJRSAxMC8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcblxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIHRoZSBicm93c2VyIGlzIEludGVybmV0IEV4cGxvcmVyXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge051bWJlcn0gdmVyc2lvbiB0byBjaGVja1xuICogQHJldHVybnMge0Jvb2xlYW59IGlzSUVcbiAqL1xuZnVuY3Rpb24gaXNJRSh2ZXJzaW9uKSB7XG4gIGlmICh2ZXJzaW9uID09PSAxMSkge1xuICAgIHJldHVybiBpc0lFMTE7XG4gIH1cbiAgaWYgKHZlcnNpb24gPT09IDEwKSB7XG4gICAgcmV0dXJuIGlzSUUxMDtcbiAgfVxuICByZXR1cm4gaXNJRTExIHx8IGlzSUUxMDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBvZmZzZXQgcGFyZW50IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBvZmZzZXQgcGFyZW50XG4gKi9cbmZ1bmN0aW9uIGdldE9mZnNldFBhcmVudChlbGVtZW50KSB7XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIH1cblxuICB2YXIgbm9PZmZzZXRQYXJlbnQgPSBpc0lFKDEwKSA/IGRvY3VtZW50LmJvZHkgOiBudWxsO1xuXG4gIC8vIE5PVEU6IDEgRE9NIGFjY2VzcyBoZXJlXG4gIHZhciBvZmZzZXRQYXJlbnQgPSBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgLy8gU2tpcCBoaWRkZW4gZWxlbWVudHMgd2hpY2ggZG9uJ3QgaGF2ZSBhbiBvZmZzZXRQYXJlbnRcbiAgd2hpbGUgKG9mZnNldFBhcmVudCA9PT0gbm9PZmZzZXRQYXJlbnQgJiYgZWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmcpIHtcbiAgICBvZmZzZXRQYXJlbnQgPSAoZWxlbWVudCA9IGVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nKS5vZmZzZXRQYXJlbnQ7XG4gIH1cblxuICB2YXIgbm9kZU5hbWUgPSBvZmZzZXRQYXJlbnQgJiYgb2Zmc2V0UGFyZW50Lm5vZGVOYW1lO1xuXG4gIGlmICghbm9kZU5hbWUgfHwgbm9kZU5hbWUgPT09ICdCT0RZJyB8fCBub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgcmV0dXJuIGVsZW1lbnQgPyBlbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IDogZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB9XG5cbiAgLy8gLm9mZnNldFBhcmVudCB3aWxsIHJldHVybiB0aGUgY2xvc2VzdCBURCBvciBUQUJMRSBpbiBjYXNlXG4gIC8vIG5vIG9mZnNldFBhcmVudCBpcyBwcmVzZW50LCBJIGhhdGUgdGhpcyBqb2IuLi5cbiAgaWYgKFsnVEQnLCAnVEFCTEUnXS5pbmRleE9mKG9mZnNldFBhcmVudC5ub2RlTmFtZSkgIT09IC0xICYmIGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShvZmZzZXRQYXJlbnQsICdwb3NpdGlvbicpID09PSAnc3RhdGljJykge1xuICAgIHJldHVybiBnZXRPZmZzZXRQYXJlbnQob2Zmc2V0UGFyZW50KTtcbiAgfVxuXG4gIHJldHVybiBvZmZzZXRQYXJlbnQ7XG59XG5cbmZ1bmN0aW9uIGlzT2Zmc2V0Q29udGFpbmVyKGVsZW1lbnQpIHtcbiAgdmFyIG5vZGVOYW1lID0gZWxlbWVudC5ub2RlTmFtZTtcblxuICBpZiAobm9kZU5hbWUgPT09ICdCT0RZJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gbm9kZU5hbWUgPT09ICdIVE1MJyB8fCBnZXRPZmZzZXRQYXJlbnQoZWxlbWVudC5maXJzdEVsZW1lbnRDaGlsZCkgPT09IGVsZW1lbnQ7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIHJvb3Qgbm9kZSAoZG9jdW1lbnQsIHNoYWRvd0RPTSByb290KSBvZiB0aGUgZ2l2ZW4gZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBub2RlXG4gKiBAcmV0dXJucyB7RWxlbWVudH0gcm9vdCBub2RlXG4gKi9cbmZ1bmN0aW9uIGdldFJvb3Qobm9kZSkge1xuICBpZiAobm9kZS5wYXJlbnROb2RlICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIGdldFJvb3Qobm9kZS5wYXJlbnROb2RlKTtcbiAgfVxuXG4gIHJldHVybiBub2RlO1xufVxuXG4vKipcbiAqIEZpbmRzIHRoZSBvZmZzZXQgcGFyZW50IGNvbW1vbiB0byB0aGUgdHdvIHByb3ZpZGVkIG5vZGVzXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnQxXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnQyXG4gKiBAcmV0dXJucyB7RWxlbWVudH0gY29tbW9uIG9mZnNldCBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gZmluZENvbW1vbk9mZnNldFBhcmVudChlbGVtZW50MSwgZWxlbWVudDIpIHtcbiAgLy8gVGhpcyBjaGVjayBpcyBuZWVkZWQgdG8gYXZvaWQgZXJyb3JzIGluIGNhc2Ugb25lIG9mIHRoZSBlbGVtZW50cyBpc24ndCBkZWZpbmVkIGZvciBhbnkgcmVhc29uXG4gIGlmICghZWxlbWVudDEgfHwgIWVsZW1lbnQxLm5vZGVUeXBlIHx8ICFlbGVtZW50MiB8fCAhZWxlbWVudDIubm9kZVR5cGUpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB9XG5cbiAgLy8gSGVyZSB3ZSBtYWtlIHN1cmUgdG8gZ2l2ZSBhcyBcInN0YXJ0XCIgdGhlIGVsZW1lbnQgdGhhdCBjb21lcyBmaXJzdCBpbiB0aGUgRE9NXG4gIHZhciBvcmRlciA9IGVsZW1lbnQxLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGVsZW1lbnQyKSAmIE5vZGUuRE9DVU1FTlRfUE9TSVRJT05fRk9MTE9XSU5HO1xuICB2YXIgc3RhcnQgPSBvcmRlciA/IGVsZW1lbnQxIDogZWxlbWVudDI7XG4gIHZhciBlbmQgPSBvcmRlciA/IGVsZW1lbnQyIDogZWxlbWVudDE7XG5cbiAgLy8gR2V0IGNvbW1vbiBhbmNlc3RvciBjb250YWluZXJcbiAgdmFyIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgcmFuZ2Uuc2V0U3RhcnQoc3RhcnQsIDApO1xuICByYW5nZS5zZXRFbmQoZW5kLCAwKTtcbiAgdmFyIGNvbW1vbkFuY2VzdG9yQ29udGFpbmVyID0gcmFuZ2UuY29tbW9uQW5jZXN0b3JDb250YWluZXI7XG5cbiAgLy8gQm90aCBub2RlcyBhcmUgaW5zaWRlICNkb2N1bWVudFxuXG4gIGlmIChlbGVtZW50MSAhPT0gY29tbW9uQW5jZXN0b3JDb250YWluZXIgJiYgZWxlbWVudDIgIT09IGNvbW1vbkFuY2VzdG9yQ29udGFpbmVyIHx8IHN0YXJ0LmNvbnRhaW5zKGVuZCkpIHtcbiAgICBpZiAoaXNPZmZzZXRDb250YWluZXIoY29tbW9uQW5jZXN0b3JDb250YWluZXIpKSB7XG4gICAgICByZXR1cm4gY29tbW9uQW5jZXN0b3JDb250YWluZXI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldE9mZnNldFBhcmVudChjb21tb25BbmNlc3RvckNvbnRhaW5lcik7XG4gIH1cblxuICAvLyBvbmUgb2YgdGhlIG5vZGVzIGlzIGluc2lkZSBzaGFkb3dET00sIGZpbmQgd2hpY2ggb25lXG4gIHZhciBlbGVtZW50MXJvb3QgPSBnZXRSb290KGVsZW1lbnQxKTtcbiAgaWYgKGVsZW1lbnQxcm9vdC5ob3N0KSB7XG4gICAgcmV0dXJuIGZpbmRDb21tb25PZmZzZXRQYXJlbnQoZWxlbWVudDFyb290Lmhvc3QsIGVsZW1lbnQyKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmluZENvbW1vbk9mZnNldFBhcmVudChlbGVtZW50MSwgZ2V0Um9vdChlbGVtZW50MikuaG9zdCk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBzY3JvbGwgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQgaW4gdGhlIGdpdmVuIHNpZGUgKHRvcCBhbmQgbGVmdClcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQGFyZ3VtZW50IHtTdHJpbmd9IHNpZGUgYHRvcGAgb3IgYGxlZnRgXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBhbW91bnQgb2Ygc2Nyb2xsZWQgcGl4ZWxzXG4gKi9cbmZ1bmN0aW9uIGdldFNjcm9sbChlbGVtZW50KSB7XG4gIHZhciBzaWRlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAndG9wJztcblxuICB2YXIgdXBwZXJTaWRlID0gc2lkZSA9PT0gJ3RvcCcgPyAnc2Nyb2xsVG9wJyA6ICdzY3JvbGxMZWZ0JztcbiAgdmFyIG5vZGVOYW1lID0gZWxlbWVudC5ub2RlTmFtZTtcblxuICBpZiAobm9kZU5hbWUgPT09ICdCT0RZJyB8fCBub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgdmFyIGh0bWwgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIHZhciBzY3JvbGxpbmdFbGVtZW50ID0gZWxlbWVudC5vd25lckRvY3VtZW50LnNjcm9sbGluZ0VsZW1lbnQgfHwgaHRtbDtcbiAgICByZXR1cm4gc2Nyb2xsaW5nRWxlbWVudFt1cHBlclNpZGVdO1xuICB9XG5cbiAgcmV0dXJuIGVsZW1lbnRbdXBwZXJTaWRlXTtcbn1cblxuLypcbiAqIFN1bSBvciBzdWJ0cmFjdCB0aGUgZWxlbWVudCBzY3JvbGwgdmFsdWVzIChsZWZ0IGFuZCB0b3ApIGZyb20gYSBnaXZlbiByZWN0IG9iamVjdFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtPYmplY3R9IHJlY3QgLSBSZWN0IG9iamVjdCB5b3Ugd2FudCB0byBjaGFuZ2VcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnQgLSBUaGUgZWxlbWVudCBmcm9tIHRoZSBmdW5jdGlvbiByZWFkcyB0aGUgc2Nyb2xsIHZhbHVlc1xuICogQHBhcmFtIHtCb29sZWFufSBzdWJ0cmFjdCAtIHNldCB0byB0cnVlIGlmIHlvdSB3YW50IHRvIHN1YnRyYWN0IHRoZSBzY3JvbGwgdmFsdWVzXG4gKiBAcmV0dXJuIHtPYmplY3R9IHJlY3QgLSBUaGUgbW9kaWZpZXIgcmVjdCBvYmplY3RcbiAqL1xuZnVuY3Rpb24gaW5jbHVkZVNjcm9sbChyZWN0LCBlbGVtZW50KSB7XG4gIHZhciBzdWJ0cmFjdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7XG5cbiAgdmFyIHNjcm9sbFRvcCA9IGdldFNjcm9sbChlbGVtZW50LCAndG9wJyk7XG4gIHZhciBzY3JvbGxMZWZ0ID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICdsZWZ0Jyk7XG4gIHZhciBtb2RpZmllciA9IHN1YnRyYWN0ID8gLTEgOiAxO1xuICByZWN0LnRvcCArPSBzY3JvbGxUb3AgKiBtb2RpZmllcjtcbiAgcmVjdC5ib3R0b20gKz0gc2Nyb2xsVG9wICogbW9kaWZpZXI7XG4gIHJlY3QubGVmdCArPSBzY3JvbGxMZWZ0ICogbW9kaWZpZXI7XG4gIHJlY3QucmlnaHQgKz0gc2Nyb2xsTGVmdCAqIG1vZGlmaWVyO1xuICByZXR1cm4gcmVjdDtcbn1cblxuLypcbiAqIEhlbHBlciB0byBkZXRlY3QgYm9yZGVycyBvZiBhIGdpdmVuIGVsZW1lbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7Q1NTU3R5bGVEZWNsYXJhdGlvbn0gc3R5bGVzXG4gKiBSZXN1bHQgb2YgYGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eWAgb24gdGhlIGdpdmVuIGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBheGlzIC0gYHhgIG9yIGB5YFxuICogQHJldHVybiB7bnVtYmVyfSBib3JkZXJzIC0gVGhlIGJvcmRlcnMgc2l6ZSBvZiB0aGUgZ2l2ZW4gYXhpc1xuICovXG5cbmZ1bmN0aW9uIGdldEJvcmRlcnNTaXplKHN0eWxlcywgYXhpcykge1xuICB2YXIgc2lkZUEgPSBheGlzID09PSAneCcgPyAnTGVmdCcgOiAnVG9wJztcbiAgdmFyIHNpZGVCID0gc2lkZUEgPT09ICdMZWZ0JyA/ICdSaWdodCcgOiAnQm90dG9tJztcblxuICByZXR1cm4gcGFyc2VGbG9hdChzdHlsZXNbJ2JvcmRlcicgKyBzaWRlQSArICdXaWR0aCddLCAxMCkgKyBwYXJzZUZsb2F0KHN0eWxlc1snYm9yZGVyJyArIHNpZGVCICsgJ1dpZHRoJ10sIDEwKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2l6ZShheGlzLCBib2R5LCBodG1sLCBjb21wdXRlZFN0eWxlKSB7XG4gIHJldHVybiBNYXRoLm1heChib2R5WydvZmZzZXQnICsgYXhpc10sIGJvZHlbJ3Njcm9sbCcgKyBheGlzXSwgaHRtbFsnY2xpZW50JyArIGF4aXNdLCBodG1sWydvZmZzZXQnICsgYXhpc10sIGh0bWxbJ3Njcm9sbCcgKyBheGlzXSwgaXNJRSgxMCkgPyBwYXJzZUludChodG1sWydvZmZzZXQnICsgYXhpc10pICsgcGFyc2VJbnQoY29tcHV0ZWRTdHlsZVsnbWFyZ2luJyArIChheGlzID09PSAnSGVpZ2h0JyA/ICdUb3AnIDogJ0xlZnQnKV0pICsgcGFyc2VJbnQoY29tcHV0ZWRTdHlsZVsnbWFyZ2luJyArIChheGlzID09PSAnSGVpZ2h0JyA/ICdCb3R0b20nIDogJ1JpZ2h0JyldKSA6IDApO1xufVxuXG5mdW5jdGlvbiBnZXRXaW5kb3dTaXplcyhkb2N1bWVudCkge1xuICB2YXIgYm9keSA9IGRvY3VtZW50LmJvZHk7XG4gIHZhciBodG1sID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB2YXIgY29tcHV0ZWRTdHlsZSA9IGlzSUUoMTApICYmIGdldENvbXB1dGVkU3R5bGUoaHRtbCk7XG5cbiAgcmV0dXJuIHtcbiAgICBoZWlnaHQ6IGdldFNpemUoJ0hlaWdodCcsIGJvZHksIGh0bWwsIGNvbXB1dGVkU3R5bGUpLFxuICAgIHdpZHRoOiBnZXRTaXplKCdXaWR0aCcsIGJvZHksIGh0bWwsIGNvbXB1dGVkU3R5bGUpXG4gIH07XG59XG5cbnZhciBjbGFzc0NhbGxDaGVjayA9IGZ1bmN0aW9uIChpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpO1xuICB9XG59O1xuXG52YXIgY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07XG4gICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7XG4gICAgICBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7XG4gICAgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTtcbiAgICBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH07XG59KCk7XG5cblxuXG5cblxudmFyIGRlZmluZVByb3BlcnR5ID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG9iaikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgb2JqW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59O1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldO1xuXG4gICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHtcbiAgICAgICAgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufTtcblxuLyoqXG4gKiBHaXZlbiBlbGVtZW50IG9mZnNldHMsIGdlbmVyYXRlIGFuIG91dHB1dCBzaW1pbGFyIHRvIGdldEJvdW5kaW5nQ2xpZW50UmVjdFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IG9mZnNldHNcbiAqIEByZXR1cm5zIHtPYmplY3R9IENsaWVudFJlY3QgbGlrZSBvdXRwdXRcbiAqL1xuZnVuY3Rpb24gZ2V0Q2xpZW50UmVjdChvZmZzZXRzKSB7XG4gIHJldHVybiBfZXh0ZW5kcyh7fSwgb2Zmc2V0cywge1xuICAgIHJpZ2h0OiBvZmZzZXRzLmxlZnQgKyBvZmZzZXRzLndpZHRoLFxuICAgIGJvdHRvbTogb2Zmc2V0cy50b3AgKyBvZmZzZXRzLmhlaWdodFxuICB9KTtcbn1cblxuLyoqXG4gKiBHZXQgYm91bmRpbmcgY2xpZW50IHJlY3Qgb2YgZ2l2ZW4gZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7T2JqZWN0fSBjbGllbnQgcmVjdFxuICovXG5mdW5jdGlvbiBnZXRCb3VuZGluZ0NsaWVudFJlY3QoZWxlbWVudCkge1xuICB2YXIgcmVjdCA9IHt9O1xuXG4gIC8vIElFMTAgMTAgRklYOiBQbGVhc2UsIGRvbid0IGFzaywgdGhlIGVsZW1lbnQgaXNuJ3RcbiAgLy8gY29uc2lkZXJlZCBpbiBET00gaW4gc29tZSBjaXJjdW1zdGFuY2VzLi4uXG4gIC8vIFRoaXMgaXNuJ3QgcmVwcm9kdWNpYmxlIGluIElFMTAgY29tcGF0aWJpbGl0eSBtb2RlIG9mIElFMTFcbiAgdHJ5IHtcbiAgICBpZiAoaXNJRSgxMCkpIHtcbiAgICAgIHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgdmFyIHNjcm9sbFRvcCA9IGdldFNjcm9sbChlbGVtZW50LCAndG9wJyk7XG4gICAgICB2YXIgc2Nyb2xsTGVmdCA9IGdldFNjcm9sbChlbGVtZW50LCAnbGVmdCcpO1xuICAgICAgcmVjdC50b3AgKz0gc2Nyb2xsVG9wO1xuICAgICAgcmVjdC5sZWZ0ICs9IHNjcm9sbExlZnQ7XG4gICAgICByZWN0LmJvdHRvbSArPSBzY3JvbGxUb3A7XG4gICAgICByZWN0LnJpZ2h0ICs9IHNjcm9sbExlZnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge31cblxuICB2YXIgcmVzdWx0ID0ge1xuICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICB0b3A6IHJlY3QudG9wLFxuICAgIHdpZHRoOiByZWN0LnJpZ2h0IC0gcmVjdC5sZWZ0LFxuICAgIGhlaWdodDogcmVjdC5ib3R0b20gLSByZWN0LnRvcFxuICB9O1xuXG4gIC8vIHN1YnRyYWN0IHNjcm9sbGJhciBzaXplIGZyb20gc2l6ZXNcbiAgdmFyIHNpemVzID0gZWxlbWVudC5ub2RlTmFtZSA9PT0gJ0hUTUwnID8gZ2V0V2luZG93U2l6ZXMoZWxlbWVudC5vd25lckRvY3VtZW50KSA6IHt9O1xuICB2YXIgd2lkdGggPSBzaXplcy53aWR0aCB8fCBlbGVtZW50LmNsaWVudFdpZHRoIHx8IHJlc3VsdC5yaWdodCAtIHJlc3VsdC5sZWZ0O1xuICB2YXIgaGVpZ2h0ID0gc2l6ZXMuaGVpZ2h0IHx8IGVsZW1lbnQuY2xpZW50SGVpZ2h0IHx8IHJlc3VsdC5ib3R0b20gLSByZXN1bHQudG9wO1xuXG4gIHZhciBob3JpelNjcm9sbGJhciA9IGVsZW1lbnQub2Zmc2V0V2lkdGggLSB3aWR0aDtcbiAgdmFyIHZlcnRTY3JvbGxiYXIgPSBlbGVtZW50Lm9mZnNldEhlaWdodCAtIGhlaWdodDtcblxuICAvLyBpZiBhbiBoeXBvdGhldGljYWwgc2Nyb2xsYmFyIGlzIGRldGVjdGVkLCB3ZSBtdXN0IGJlIHN1cmUgaXQncyBub3QgYSBgYm9yZGVyYFxuICAvLyB3ZSBtYWtlIHRoaXMgY2hlY2sgY29uZGl0aW9uYWwgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnNcbiAgaWYgKGhvcml6U2Nyb2xsYmFyIHx8IHZlcnRTY3JvbGxiYXIpIHtcbiAgICB2YXIgc3R5bGVzID0gZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQpO1xuICAgIGhvcml6U2Nyb2xsYmFyIC09IGdldEJvcmRlcnNTaXplKHN0eWxlcywgJ3gnKTtcbiAgICB2ZXJ0U2Nyb2xsYmFyIC09IGdldEJvcmRlcnNTaXplKHN0eWxlcywgJ3knKTtcblxuICAgIHJlc3VsdC53aWR0aCAtPSBob3JpelNjcm9sbGJhcjtcbiAgICByZXN1bHQuaGVpZ2h0IC09IHZlcnRTY3JvbGxiYXI7XG4gIH1cblxuICByZXR1cm4gZ2V0Q2xpZW50UmVjdChyZXN1bHQpO1xufVxuXG5mdW5jdGlvbiBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoY2hpbGRyZW4sIHBhcmVudCkge1xuICB2YXIgZml4ZWRQb3NpdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7XG5cbiAgdmFyIGlzSUUxMCA9IGlzSUUoMTApO1xuICB2YXIgaXNIVE1MID0gcGFyZW50Lm5vZGVOYW1lID09PSAnSFRNTCc7XG4gIHZhciBjaGlsZHJlblJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QoY2hpbGRyZW4pO1xuICB2YXIgcGFyZW50UmVjdCA9IGdldEJvdW5kaW5nQ2xpZW50UmVjdChwYXJlbnQpO1xuICB2YXIgc2Nyb2xsUGFyZW50ID0gZ2V0U2Nyb2xsUGFyZW50KGNoaWxkcmVuKTtcblxuICB2YXIgc3R5bGVzID0gZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KHBhcmVudCk7XG4gIHZhciBib3JkZXJUb3BXaWR0aCA9IHBhcnNlRmxvYXQoc3R5bGVzLmJvcmRlclRvcFdpZHRoLCAxMCk7XG4gIHZhciBib3JkZXJMZWZ0V2lkdGggPSBwYXJzZUZsb2F0KHN0eWxlcy5ib3JkZXJMZWZ0V2lkdGgsIDEwKTtcblxuICAvLyBJbiBjYXNlcyB3aGVyZSB0aGUgcGFyZW50IGlzIGZpeGVkLCB3ZSBtdXN0IGlnbm9yZSBuZWdhdGl2ZSBzY3JvbGwgaW4gb2Zmc2V0IGNhbGNcbiAgaWYgKGZpeGVkUG9zaXRpb24gJiYgaXNIVE1MKSB7XG4gICAgcGFyZW50UmVjdC50b3AgPSBNYXRoLm1heChwYXJlbnRSZWN0LnRvcCwgMCk7XG4gICAgcGFyZW50UmVjdC5sZWZ0ID0gTWF0aC5tYXgocGFyZW50UmVjdC5sZWZ0LCAwKTtcbiAgfVxuICB2YXIgb2Zmc2V0cyA9IGdldENsaWVudFJlY3Qoe1xuICAgIHRvcDogY2hpbGRyZW5SZWN0LnRvcCAtIHBhcmVudFJlY3QudG9wIC0gYm9yZGVyVG9wV2lkdGgsXG4gICAgbGVmdDogY2hpbGRyZW5SZWN0LmxlZnQgLSBwYXJlbnRSZWN0LmxlZnQgLSBib3JkZXJMZWZ0V2lkdGgsXG4gICAgd2lkdGg6IGNoaWxkcmVuUmVjdC53aWR0aCxcbiAgICBoZWlnaHQ6IGNoaWxkcmVuUmVjdC5oZWlnaHRcbiAgfSk7XG4gIG9mZnNldHMubWFyZ2luVG9wID0gMDtcbiAgb2Zmc2V0cy5tYXJnaW5MZWZ0ID0gMDtcblxuICAvLyBTdWJ0cmFjdCBtYXJnaW5zIG9mIGRvY3VtZW50RWxlbWVudCBpbiBjYXNlIGl0J3MgYmVpbmcgdXNlZCBhcyBwYXJlbnRcbiAgLy8gd2UgZG8gdGhpcyBvbmx5IG9uIEhUTUwgYmVjYXVzZSBpdCdzIHRoZSBvbmx5IGVsZW1lbnQgdGhhdCBiZWhhdmVzXG4gIC8vIGRpZmZlcmVudGx5IHdoZW4gbWFyZ2lucyBhcmUgYXBwbGllZCB0byBpdC4gVGhlIG1hcmdpbnMgYXJlIGluY2x1ZGVkIGluXG4gIC8vIHRoZSBib3ggb2YgdGhlIGRvY3VtZW50RWxlbWVudCwgaW4gdGhlIG90aGVyIGNhc2VzIG5vdC5cbiAgaWYgKCFpc0lFMTAgJiYgaXNIVE1MKSB7XG4gICAgdmFyIG1hcmdpblRvcCA9IHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpblRvcCwgMTApO1xuICAgIHZhciBtYXJnaW5MZWZ0ID0gcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luTGVmdCwgMTApO1xuXG4gICAgb2Zmc2V0cy50b3AgLT0gYm9yZGVyVG9wV2lkdGggLSBtYXJnaW5Ub3A7XG4gICAgb2Zmc2V0cy5ib3R0b20gLT0gYm9yZGVyVG9wV2lkdGggLSBtYXJnaW5Ub3A7XG4gICAgb2Zmc2V0cy5sZWZ0IC09IGJvcmRlckxlZnRXaWR0aCAtIG1hcmdpbkxlZnQ7XG4gICAgb2Zmc2V0cy5yaWdodCAtPSBib3JkZXJMZWZ0V2lkdGggLSBtYXJnaW5MZWZ0O1xuXG4gICAgLy8gQXR0YWNoIG1hcmdpblRvcCBhbmQgbWFyZ2luTGVmdCBiZWNhdXNlIGluIHNvbWUgY2lyY3Vtc3RhbmNlcyB3ZSBtYXkgbmVlZCB0aGVtXG4gICAgb2Zmc2V0cy5tYXJnaW5Ub3AgPSBtYXJnaW5Ub3A7XG4gICAgb2Zmc2V0cy5tYXJnaW5MZWZ0ID0gbWFyZ2luTGVmdDtcbiAgfVxuXG4gIGlmIChpc0lFMTAgJiYgIWZpeGVkUG9zaXRpb24gPyBwYXJlbnQuY29udGFpbnMoc2Nyb2xsUGFyZW50KSA6IHBhcmVudCA9PT0gc2Nyb2xsUGFyZW50ICYmIHNjcm9sbFBhcmVudC5ub2RlTmFtZSAhPT0gJ0JPRFknKSB7XG4gICAgb2Zmc2V0cyA9IGluY2x1ZGVTY3JvbGwob2Zmc2V0cywgcGFyZW50KTtcbiAgfVxuXG4gIHJldHVybiBvZmZzZXRzO1xufVxuXG5mdW5jdGlvbiBnZXRWaWV3cG9ydE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJ0Yml0cmFyeU5vZGUoZWxlbWVudCkge1xuICB2YXIgZXhjbHVkZVNjcm9sbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7XG5cbiAgdmFyIGh0bWwgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB2YXIgcmVsYXRpdmVPZmZzZXQgPSBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoZWxlbWVudCwgaHRtbCk7XG4gIHZhciB3aWR0aCA9IE1hdGgubWF4KGh0bWwuY2xpZW50V2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIHx8IDApO1xuICB2YXIgaGVpZ2h0ID0gTWF0aC5tYXgoaHRtbC5jbGllbnRIZWlnaHQsIHdpbmRvdy5pbm5lckhlaWdodCB8fCAwKTtcblxuICB2YXIgc2Nyb2xsVG9wID0gIWV4Y2x1ZGVTY3JvbGwgPyBnZXRTY3JvbGwoaHRtbCkgOiAwO1xuICB2YXIgc2Nyb2xsTGVmdCA9ICFleGNsdWRlU2Nyb2xsID8gZ2V0U2Nyb2xsKGh0bWwsICdsZWZ0JykgOiAwO1xuXG4gIHZhciBvZmZzZXQgPSB7XG4gICAgdG9wOiBzY3JvbGxUb3AgLSByZWxhdGl2ZU9mZnNldC50b3AgKyByZWxhdGl2ZU9mZnNldC5tYXJnaW5Ub3AsXG4gICAgbGVmdDogc2Nyb2xsTGVmdCAtIHJlbGF0aXZlT2Zmc2V0LmxlZnQgKyByZWxhdGl2ZU9mZnNldC5tYXJnaW5MZWZ0LFxuICAgIHdpZHRoOiB3aWR0aCxcbiAgICBoZWlnaHQ6IGhlaWdodFxuICB9O1xuXG4gIHJldHVybiBnZXRDbGllbnRSZWN0KG9mZnNldCk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaXMgZml4ZWQgb3IgaXMgaW5zaWRlIGEgZml4ZWQgcGFyZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gY3VzdG9tQ29udGFpbmVyXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gYW5zd2VyIHRvIFwiaXNGaXhlZD9cIlxuICovXG5mdW5jdGlvbiBpc0ZpeGVkKGVsZW1lbnQpIHtcbiAgdmFyIG5vZGVOYW1lID0gZWxlbWVudC5ub2RlTmFtZTtcbiAgaWYgKG5vZGVOYW1lID09PSAnQk9EWScgfHwgbm9kZU5hbWUgPT09ICdIVE1MJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQsICdwb3NpdGlvbicpID09PSAnZml4ZWQnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGlzRml4ZWQoZ2V0UGFyZW50Tm9kZShlbGVtZW50KSk7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIGZpcnN0IHBhcmVudCBvZiBhbiBlbGVtZW50IHRoYXQgaGFzIGEgdHJhbnNmb3JtZWQgcHJvcGVydHkgZGVmaW5lZFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJucyB7RWxlbWVudH0gZmlyc3QgdHJhbnNmb3JtZWQgcGFyZW50IG9yIGRvY3VtZW50RWxlbWVudFxuICovXG5cbmZ1bmN0aW9uIGdldEZpeGVkUG9zaXRpb25PZmZzZXRQYXJlbnQoZWxlbWVudCkge1xuICAvLyBUaGlzIGNoZWNrIGlzIG5lZWRlZCB0byBhdm9pZCBlcnJvcnMgaW4gY2FzZSBvbmUgb2YgdGhlIGVsZW1lbnRzIGlzbid0IGRlZmluZWQgZm9yIGFueSByZWFzb25cbiAgaWYgKCFlbGVtZW50IHx8ICFlbGVtZW50LnBhcmVudEVsZW1lbnQgfHwgaXNJRSgpKSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgfVxuICB2YXIgZWwgPSBlbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gIHdoaWxlIChlbCAmJiBnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkoZWwsICd0cmFuc2Zvcm0nKSA9PT0gJ25vbmUnKSB7XG4gICAgZWwgPSBlbC5wYXJlbnRFbGVtZW50O1xuICB9XG4gIHJldHVybiBlbCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG59XG5cbi8qKlxuICogQ29tcHV0ZWQgdGhlIGJvdW5kYXJpZXMgbGltaXRzIGFuZCByZXR1cm4gdGhlbVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByZWZlcmVuY2VcbiAqIEBwYXJhbSB7bnVtYmVyfSBwYWRkaW5nXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBib3VuZGFyaWVzRWxlbWVudCAtIEVsZW1lbnQgdXNlZCB0byBkZWZpbmUgdGhlIGJvdW5kYXJpZXNcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gZml4ZWRQb3NpdGlvbiAtIElzIGluIGZpeGVkIHBvc2l0aW9uIG1vZGVcbiAqIEByZXR1cm5zIHtPYmplY3R9IENvb3JkaW5hdGVzIG9mIHRoZSBib3VuZGFyaWVzXG4gKi9cbmZ1bmN0aW9uIGdldEJvdW5kYXJpZXMocG9wcGVyLCByZWZlcmVuY2UsIHBhZGRpbmcsIGJvdW5kYXJpZXNFbGVtZW50KSB7XG4gIHZhciBmaXhlZFBvc2l0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiBmYWxzZTtcblxuICAvLyBOT1RFOiAxIERPTSBhY2Nlc3MgaGVyZVxuXG4gIHZhciBib3VuZGFyaWVzID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcbiAgdmFyIG9mZnNldFBhcmVudCA9IGZpeGVkUG9zaXRpb24gPyBnZXRGaXhlZFBvc2l0aW9uT2Zmc2V0UGFyZW50KHBvcHBlcikgOiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KHBvcHBlciwgcmVmZXJlbmNlKTtcblxuICAvLyBIYW5kbGUgdmlld3BvcnQgY2FzZVxuICBpZiAoYm91bmRhcmllc0VsZW1lbnQgPT09ICd2aWV3cG9ydCcpIHtcbiAgICBib3VuZGFyaWVzID0gZ2V0Vmlld3BvcnRPZmZzZXRSZWN0UmVsYXRpdmVUb0FydGJpdHJhcnlOb2RlKG9mZnNldFBhcmVudCwgZml4ZWRQb3NpdGlvbik7XG4gIH0gZWxzZSB7XG4gICAgLy8gSGFuZGxlIG90aGVyIGNhc2VzIGJhc2VkIG9uIERPTSBlbGVtZW50IHVzZWQgYXMgYm91bmRhcmllc1xuICAgIHZhciBib3VuZGFyaWVzTm9kZSA9IHZvaWQgMDtcbiAgICBpZiAoYm91bmRhcmllc0VsZW1lbnQgPT09ICdzY3JvbGxQYXJlbnQnKSB7XG4gICAgICBib3VuZGFyaWVzTm9kZSA9IGdldFNjcm9sbFBhcmVudChnZXRQYXJlbnROb2RlKHJlZmVyZW5jZSkpO1xuICAgICAgaWYgKGJvdW5kYXJpZXNOb2RlLm5vZGVOYW1lID09PSAnQk9EWScpIHtcbiAgICAgICAgYm91bmRhcmllc05vZGUgPSBwb3BwZXIub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChib3VuZGFyaWVzRWxlbWVudCA9PT0gJ3dpbmRvdycpIHtcbiAgICAgIGJvdW5kYXJpZXNOb2RlID0gcG9wcGVyLm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICBib3VuZGFyaWVzTm9kZSA9IGJvdW5kYXJpZXNFbGVtZW50O1xuICAgIH1cblxuICAgIHZhciBvZmZzZXRzID0gZ2V0T2Zmc2V0UmVjdFJlbGF0aXZlVG9BcmJpdHJhcnlOb2RlKGJvdW5kYXJpZXNOb2RlLCBvZmZzZXRQYXJlbnQsIGZpeGVkUG9zaXRpb24pO1xuXG4gICAgLy8gSW4gY2FzZSBvZiBIVE1MLCB3ZSBuZWVkIGEgZGlmZmVyZW50IGNvbXB1dGF0aW9uXG4gICAgaWYgKGJvdW5kYXJpZXNOb2RlLm5vZGVOYW1lID09PSAnSFRNTCcgJiYgIWlzRml4ZWQob2Zmc2V0UGFyZW50KSkge1xuICAgICAgdmFyIF9nZXRXaW5kb3dTaXplcyA9IGdldFdpbmRvd1NpemVzKHBvcHBlci5vd25lckRvY3VtZW50KSxcbiAgICAgICAgICBoZWlnaHQgPSBfZ2V0V2luZG93U2l6ZXMuaGVpZ2h0LFxuICAgICAgICAgIHdpZHRoID0gX2dldFdpbmRvd1NpemVzLndpZHRoO1xuXG4gICAgICBib3VuZGFyaWVzLnRvcCArPSBvZmZzZXRzLnRvcCAtIG9mZnNldHMubWFyZ2luVG9wO1xuICAgICAgYm91bmRhcmllcy5ib3R0b20gPSBoZWlnaHQgKyBvZmZzZXRzLnRvcDtcbiAgICAgIGJvdW5kYXJpZXMubGVmdCArPSBvZmZzZXRzLmxlZnQgLSBvZmZzZXRzLm1hcmdpbkxlZnQ7XG4gICAgICBib3VuZGFyaWVzLnJpZ2h0ID0gd2lkdGggKyBvZmZzZXRzLmxlZnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGZvciBhbGwgdGhlIG90aGVyIERPTSBlbGVtZW50cywgdGhpcyBvbmUgaXMgZ29vZFxuICAgICAgYm91bmRhcmllcyA9IG9mZnNldHM7XG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIHBhZGRpbmdzXG4gIHBhZGRpbmcgPSBwYWRkaW5nIHx8IDA7XG4gIHZhciBpc1BhZGRpbmdOdW1iZXIgPSB0eXBlb2YgcGFkZGluZyA9PT0gJ251bWJlcic7XG4gIGJvdW5kYXJpZXMubGVmdCArPSBpc1BhZGRpbmdOdW1iZXIgPyBwYWRkaW5nIDogcGFkZGluZy5sZWZ0IHx8IDA7XG4gIGJvdW5kYXJpZXMudG9wICs9IGlzUGFkZGluZ051bWJlciA/IHBhZGRpbmcgOiBwYWRkaW5nLnRvcCB8fCAwO1xuICBib3VuZGFyaWVzLnJpZ2h0IC09IGlzUGFkZGluZ051bWJlciA/IHBhZGRpbmcgOiBwYWRkaW5nLnJpZ2h0IHx8IDA7XG4gIGJvdW5kYXJpZXMuYm90dG9tIC09IGlzUGFkZGluZ051bWJlciA/IHBhZGRpbmcgOiBwYWRkaW5nLmJvdHRvbSB8fCAwO1xuXG4gIHJldHVybiBib3VuZGFyaWVzO1xufVxuXG5mdW5jdGlvbiBnZXRBcmVhKF9yZWYpIHtcbiAgdmFyIHdpZHRoID0gX3JlZi53aWR0aCxcbiAgICAgIGhlaWdodCA9IF9yZWYuaGVpZ2h0O1xuXG4gIHJldHVybiB3aWR0aCAqIGhlaWdodDtcbn1cblxuLyoqXG4gKiBVdGlsaXR5IHVzZWQgdG8gdHJhbnNmb3JtIHRoZSBgYXV0b2AgcGxhY2VtZW50IHRvIHRoZSBwbGFjZW1lbnQgd2l0aCBtb3JlXG4gKiBhdmFpbGFibGUgc3BhY2UuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBjb21wdXRlQXV0b1BsYWNlbWVudChwbGFjZW1lbnQsIHJlZlJlY3QsIHBvcHBlciwgcmVmZXJlbmNlLCBib3VuZGFyaWVzRWxlbWVudCkge1xuICB2YXIgcGFkZGluZyA9IGFyZ3VtZW50cy5sZW5ndGggPiA1ICYmIGFyZ3VtZW50c1s1XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzVdIDogMDtcblxuICBpZiAocGxhY2VtZW50LmluZGV4T2YoJ2F1dG8nKSA9PT0gLTEpIHtcbiAgICByZXR1cm4gcGxhY2VtZW50O1xuICB9XG5cbiAgdmFyIGJvdW5kYXJpZXMgPSBnZXRCb3VuZGFyaWVzKHBvcHBlciwgcmVmZXJlbmNlLCBwYWRkaW5nLCBib3VuZGFyaWVzRWxlbWVudCk7XG5cbiAgdmFyIHJlY3RzID0ge1xuICAgIHRvcDoge1xuICAgICAgd2lkdGg6IGJvdW5kYXJpZXMud2lkdGgsXG4gICAgICBoZWlnaHQ6IHJlZlJlY3QudG9wIC0gYm91bmRhcmllcy50b3BcbiAgICB9LFxuICAgIHJpZ2h0OiB7XG4gICAgICB3aWR0aDogYm91bmRhcmllcy5yaWdodCAtIHJlZlJlY3QucmlnaHQsXG4gICAgICBoZWlnaHQ6IGJvdW5kYXJpZXMuaGVpZ2h0XG4gICAgfSxcbiAgICBib3R0b206IHtcbiAgICAgIHdpZHRoOiBib3VuZGFyaWVzLndpZHRoLFxuICAgICAgaGVpZ2h0OiBib3VuZGFyaWVzLmJvdHRvbSAtIHJlZlJlY3QuYm90dG9tXG4gICAgfSxcbiAgICBsZWZ0OiB7XG4gICAgICB3aWR0aDogcmVmUmVjdC5sZWZ0IC0gYm91bmRhcmllcy5sZWZ0LFxuICAgICAgaGVpZ2h0OiBib3VuZGFyaWVzLmhlaWdodFxuICAgIH1cbiAgfTtcblxuICB2YXIgc29ydGVkQXJlYXMgPSBPYmplY3Qua2V5cyhyZWN0cykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gX2V4dGVuZHMoe1xuICAgICAga2V5OiBrZXlcbiAgICB9LCByZWN0c1trZXldLCB7XG4gICAgICBhcmVhOiBnZXRBcmVhKHJlY3RzW2tleV0pXG4gICAgfSk7XG4gIH0pLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gYi5hcmVhIC0gYS5hcmVhO1xuICB9KTtcblxuICB2YXIgZmlsdGVyZWRBcmVhcyA9IHNvcnRlZEFyZWFzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjIpIHtcbiAgICB2YXIgd2lkdGggPSBfcmVmMi53aWR0aCxcbiAgICAgICAgaGVpZ2h0ID0gX3JlZjIuaGVpZ2h0O1xuICAgIHJldHVybiB3aWR0aCA+PSBwb3BwZXIuY2xpZW50V2lkdGggJiYgaGVpZ2h0ID49IHBvcHBlci5jbGllbnRIZWlnaHQ7XG4gIH0pO1xuXG4gIHZhciBjb21wdXRlZFBsYWNlbWVudCA9IGZpbHRlcmVkQXJlYXMubGVuZ3RoID4gMCA/IGZpbHRlcmVkQXJlYXNbMF0ua2V5IDogc29ydGVkQXJlYXNbMF0ua2V5O1xuXG4gIHZhciB2YXJpYXRpb24gPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVsxXTtcblxuICByZXR1cm4gY29tcHV0ZWRQbGFjZW1lbnQgKyAodmFyaWF0aW9uID8gJy0nICsgdmFyaWF0aW9uIDogJycpO1xufVxuXG4vKipcbiAqIEdldCBvZmZzZXRzIHRvIHRoZSByZWZlcmVuY2UgZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHBvcHBlciAtIHRoZSBwb3BwZXIgZWxlbWVudFxuICogQHBhcmFtIHtFbGVtZW50fSByZWZlcmVuY2UgLSB0aGUgcmVmZXJlbmNlIGVsZW1lbnQgKHRoZSBwb3BwZXIgd2lsbCBiZSByZWxhdGl2ZSB0byB0aGlzKVxuICogQHBhcmFtIHtFbGVtZW50fSBmaXhlZFBvc2l0aW9uIC0gaXMgaW4gZml4ZWQgcG9zaXRpb24gbW9kZVxuICogQHJldHVybnMge09iamVjdH0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG9mZnNldHMgd2hpY2ggd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXJcbiAqL1xuZnVuY3Rpb24gZ2V0UmVmZXJlbmNlT2Zmc2V0cyhzdGF0ZSwgcG9wcGVyLCByZWZlcmVuY2UpIHtcbiAgdmFyIGZpeGVkUG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IG51bGw7XG5cbiAgdmFyIGNvbW1vbk9mZnNldFBhcmVudCA9IGZpeGVkUG9zaXRpb24gPyBnZXRGaXhlZFBvc2l0aW9uT2Zmc2V0UGFyZW50KHBvcHBlcikgOiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KHBvcHBlciwgcmVmZXJlbmNlKTtcbiAgcmV0dXJuIGdldE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJiaXRyYXJ5Tm9kZShyZWZlcmVuY2UsIGNvbW1vbk9mZnNldFBhcmVudCwgZml4ZWRQb3NpdGlvbik7XG59XG5cbi8qKlxuICogR2V0IHRoZSBvdXRlciBzaXplcyBvZiB0aGUgZ2l2ZW4gZWxlbWVudCAob2Zmc2V0IHNpemUgKyBtYXJnaW5zKVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBvYmplY3QgY29udGFpbmluZyB3aWR0aCBhbmQgaGVpZ2h0IHByb3BlcnRpZXNcbiAqL1xuZnVuY3Rpb24gZ2V0T3V0ZXJTaXplcyhlbGVtZW50KSB7XG4gIHZhciBzdHlsZXMgPSBnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xuICB2YXIgeCA9IHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpblRvcCkgKyBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5Cb3R0b20pO1xuICB2YXIgeSA9IHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpbkxlZnQpICsgcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luUmlnaHQpO1xuICB2YXIgcmVzdWx0ID0ge1xuICAgIHdpZHRoOiBlbGVtZW50Lm9mZnNldFdpZHRoICsgeSxcbiAgICBoZWlnaHQ6IGVsZW1lbnQub2Zmc2V0SGVpZ2h0ICsgeFxuICB9O1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIEdldCB0aGUgb3Bwb3NpdGUgcGxhY2VtZW50IG9mIHRoZSBnaXZlbiBvbmVcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBwbGFjZW1lbnRcbiAqIEByZXR1cm5zIHtTdHJpbmd9IGZsaXBwZWQgcGxhY2VtZW50XG4gKi9cbmZ1bmN0aW9uIGdldE9wcG9zaXRlUGxhY2VtZW50KHBsYWNlbWVudCkge1xuICB2YXIgaGFzaCA9IHsgbGVmdDogJ3JpZ2h0JywgcmlnaHQ6ICdsZWZ0JywgYm90dG9tOiAndG9wJywgdG9wOiAnYm90dG9tJyB9O1xuICByZXR1cm4gcGxhY2VtZW50LnJlcGxhY2UoL2xlZnR8cmlnaHR8Ym90dG9tfHRvcC9nLCBmdW5jdGlvbiAobWF0Y2hlZCkge1xuICAgIHJldHVybiBoYXNoW21hdGNoZWRdO1xuICB9KTtcbn1cblxuLyoqXG4gKiBHZXQgb2Zmc2V0cyB0byB0aGUgcG9wcGVyXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge09iamVjdH0gcG9zaXRpb24gLSBDU1MgcG9zaXRpb24gdGhlIFBvcHBlciB3aWxsIGdldCBhcHBsaWVkXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwb3BwZXIgLSB0aGUgcG9wcGVyIGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSByZWZlcmVuY2VPZmZzZXRzIC0gdGhlIHJlZmVyZW5jZSBvZmZzZXRzICh0aGUgcG9wcGVyIHdpbGwgYmUgcmVsYXRpdmUgdG8gdGhpcylcbiAqIEBwYXJhbSB7U3RyaW5nfSBwbGFjZW1lbnQgLSBvbmUgb2YgdGhlIHZhbGlkIHBsYWNlbWVudCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwb3BwZXJPZmZzZXRzIC0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG9mZnNldHMgd2hpY2ggd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXJcbiAqL1xuZnVuY3Rpb24gZ2V0UG9wcGVyT2Zmc2V0cyhwb3BwZXIsIHJlZmVyZW5jZU9mZnNldHMsIHBsYWNlbWVudCkge1xuICBwbGFjZW1lbnQgPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcblxuICAvLyBHZXQgcG9wcGVyIG5vZGUgc2l6ZXNcbiAgdmFyIHBvcHBlclJlY3QgPSBnZXRPdXRlclNpemVzKHBvcHBlcik7XG5cbiAgLy8gQWRkIHBvc2l0aW9uLCB3aWR0aCBhbmQgaGVpZ2h0IHRvIG91ciBvZmZzZXRzIG9iamVjdFxuICB2YXIgcG9wcGVyT2Zmc2V0cyA9IHtcbiAgICB3aWR0aDogcG9wcGVyUmVjdC53aWR0aCxcbiAgICBoZWlnaHQ6IHBvcHBlclJlY3QuaGVpZ2h0XG4gIH07XG5cbiAgLy8gZGVwZW5kaW5nIGJ5IHRoZSBwb3BwZXIgcGxhY2VtZW50IHdlIGhhdmUgdG8gY29tcHV0ZSBpdHMgb2Zmc2V0cyBzbGlnaHRseSBkaWZmZXJlbnRseVxuICB2YXIgaXNIb3JpeiA9IFsncmlnaHQnLCAnbGVmdCddLmluZGV4T2YocGxhY2VtZW50KSAhPT0gLTE7XG4gIHZhciBtYWluU2lkZSA9IGlzSG9yaXogPyAndG9wJyA6ICdsZWZ0JztcbiAgdmFyIHNlY29uZGFyeVNpZGUgPSBpc0hvcml6ID8gJ2xlZnQnIDogJ3RvcCc7XG4gIHZhciBtZWFzdXJlbWVudCA9IGlzSG9yaXogPyAnaGVpZ2h0JyA6ICd3aWR0aCc7XG4gIHZhciBzZWNvbmRhcnlNZWFzdXJlbWVudCA9ICFpc0hvcml6ID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuXG4gIHBvcHBlck9mZnNldHNbbWFpblNpZGVdID0gcmVmZXJlbmNlT2Zmc2V0c1ttYWluU2lkZV0gKyByZWZlcmVuY2VPZmZzZXRzW21lYXN1cmVtZW50XSAvIDIgLSBwb3BwZXJSZWN0W21lYXN1cmVtZW50XSAvIDI7XG4gIGlmIChwbGFjZW1lbnQgPT09IHNlY29uZGFyeVNpZGUpIHtcbiAgICBwb3BwZXJPZmZzZXRzW3NlY29uZGFyeVNpZGVdID0gcmVmZXJlbmNlT2Zmc2V0c1tzZWNvbmRhcnlTaWRlXSAtIHBvcHBlclJlY3Rbc2Vjb25kYXJ5TWVhc3VyZW1lbnRdO1xuICB9IGVsc2Uge1xuICAgIHBvcHBlck9mZnNldHNbc2Vjb25kYXJ5U2lkZV0gPSByZWZlcmVuY2VPZmZzZXRzW2dldE9wcG9zaXRlUGxhY2VtZW50KHNlY29uZGFyeVNpZGUpXTtcbiAgfVxuXG4gIHJldHVybiBwb3BwZXJPZmZzZXRzO1xufVxuXG4vKipcbiAqIE1pbWljcyB0aGUgYGZpbmRgIG1ldGhvZCBvZiBBcnJheVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtBcnJheX0gYXJyXG4gKiBAYXJndW1lbnQgcHJvcFxuICogQGFyZ3VtZW50IHZhbHVlXG4gKiBAcmV0dXJucyBpbmRleCBvciAtMVxuICovXG5mdW5jdGlvbiBmaW5kKGFyciwgY2hlY2spIHtcbiAgLy8gdXNlIG5hdGl2ZSBmaW5kIGlmIHN1cHBvcnRlZFxuICBpZiAoQXJyYXkucHJvdG90eXBlLmZpbmQpIHtcbiAgICByZXR1cm4gYXJyLmZpbmQoY2hlY2spO1xuICB9XG5cbiAgLy8gdXNlIGBmaWx0ZXJgIHRvIG9idGFpbiB0aGUgc2FtZSBiZWhhdmlvciBvZiBgZmluZGBcbiAgcmV0dXJuIGFyci5maWx0ZXIoY2hlY2spWzBdO1xufVxuXG4vKipcbiAqIFJldHVybiB0aGUgaW5kZXggb2YgdGhlIG1hdGNoaW5nIG9iamVjdFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtBcnJheX0gYXJyXG4gKiBAYXJndW1lbnQgcHJvcFxuICogQGFyZ3VtZW50IHZhbHVlXG4gKiBAcmV0dXJucyBpbmRleCBvciAtMVxuICovXG5mdW5jdGlvbiBmaW5kSW5kZXgoYXJyLCBwcm9wLCB2YWx1ZSkge1xuICAvLyB1c2UgbmF0aXZlIGZpbmRJbmRleCBpZiBzdXBwb3J0ZWRcbiAgaWYgKEFycmF5LnByb3RvdHlwZS5maW5kSW5kZXgpIHtcbiAgICByZXR1cm4gYXJyLmZpbmRJbmRleChmdW5jdGlvbiAoY3VyKSB7XG4gICAgICByZXR1cm4gY3VyW3Byb3BdID09PSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIHVzZSBgZmluZGAgKyBgaW5kZXhPZmAgaWYgYGZpbmRJbmRleGAgaXNuJ3Qgc3VwcG9ydGVkXG4gIHZhciBtYXRjaCA9IGZpbmQoYXJyLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIG9ialtwcm9wXSA9PT0gdmFsdWU7XG4gIH0pO1xuICByZXR1cm4gYXJyLmluZGV4T2YobWF0Y2gpO1xufVxuXG4vKipcbiAqIExvb3AgdHJvdWdoIHRoZSBsaXN0IG9mIG1vZGlmaWVycyBhbmQgcnVuIHRoZW0gaW4gb3JkZXIsXG4gKiBlYWNoIG9mIHRoZW0gd2lsbCB0aGVuIGVkaXQgdGhlIGRhdGEgb2JqZWN0LlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtkYXRhT2JqZWN0fSBkYXRhXG4gKiBAcGFyYW0ge0FycmF5fSBtb2RpZmllcnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBlbmRzIC0gT3B0aW9uYWwgbW9kaWZpZXIgbmFtZSB1c2VkIGFzIHN0b3BwZXJcbiAqIEByZXR1cm5zIHtkYXRhT2JqZWN0fVxuICovXG5mdW5jdGlvbiBydW5Nb2RpZmllcnMobW9kaWZpZXJzLCBkYXRhLCBlbmRzKSB7XG4gIHZhciBtb2RpZmllcnNUb1J1biA9IGVuZHMgPT09IHVuZGVmaW5lZCA/IG1vZGlmaWVycyA6IG1vZGlmaWVycy5zbGljZSgwLCBmaW5kSW5kZXgobW9kaWZpZXJzLCAnbmFtZScsIGVuZHMpKTtcblxuICBtb2RpZmllcnNUb1J1bi5mb3JFYWNoKGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgIGlmIChtb2RpZmllclsnZnVuY3Rpb24nXSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICAgIGNvbnNvbGUud2FybignYG1vZGlmaWVyLmZ1bmN0aW9uYCBpcyBkZXByZWNhdGVkLCB1c2UgYG1vZGlmaWVyLmZuYCEnKTtcbiAgICB9XG4gICAgdmFyIGZuID0gbW9kaWZpZXJbJ2Z1bmN0aW9uJ10gfHwgbW9kaWZpZXIuZm47IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZG90LW5vdGF0aW9uXG4gICAgaWYgKG1vZGlmaWVyLmVuYWJsZWQgJiYgaXNGdW5jdGlvbihmbikpIHtcbiAgICAgIC8vIEFkZCBwcm9wZXJ0aWVzIHRvIG9mZnNldHMgdG8gbWFrZSB0aGVtIGEgY29tcGxldGUgY2xpZW50UmVjdCBvYmplY3RcbiAgICAgIC8vIHdlIGRvIHRoaXMgYmVmb3JlIGVhY2ggbW9kaWZpZXIgdG8gbWFrZSBzdXJlIHRoZSBwcmV2aW91cyBvbmUgZG9lc24ndFxuICAgICAgLy8gbWVzcyB3aXRoIHRoZXNlIHZhbHVlc1xuICAgICAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldENsaWVudFJlY3QoZGF0YS5vZmZzZXRzLnBvcHBlcik7XG4gICAgICBkYXRhLm9mZnNldHMucmVmZXJlbmNlID0gZ2V0Q2xpZW50UmVjdChkYXRhLm9mZnNldHMucmVmZXJlbmNlKTtcblxuICAgICAgZGF0YSA9IGZuKGRhdGEsIG1vZGlmaWVyKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIFVwZGF0ZXMgdGhlIHBvc2l0aW9uIG9mIHRoZSBwb3BwZXIsIGNvbXB1dGluZyB0aGUgbmV3IG9mZnNldHMgYW5kIGFwcGx5aW5nXG4gKiB0aGUgbmV3IHN0eWxlLjxiciAvPlxuICogUHJlZmVyIGBzY2hlZHVsZVVwZGF0ZWAgb3ZlciBgdXBkYXRlYCBiZWNhdXNlIG9mIHBlcmZvcm1hbmNlIHJlYXNvbnMuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZSgpIHtcbiAgLy8gaWYgcG9wcGVyIGlzIGRlc3Ryb3llZCwgZG9uJ3QgcGVyZm9ybSBhbnkgZnVydGhlciB1cGRhdGVcbiAgaWYgKHRoaXMuc3RhdGUuaXNEZXN0cm95ZWQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgZGF0YSA9IHtcbiAgICBpbnN0YW5jZTogdGhpcyxcbiAgICBzdHlsZXM6IHt9LFxuICAgIGFycm93U3R5bGVzOiB7fSxcbiAgICBhdHRyaWJ1dGVzOiB7fSxcbiAgICBmbGlwcGVkOiBmYWxzZSxcbiAgICBvZmZzZXRzOiB7fVxuICB9O1xuXG4gIC8vIGNvbXB1dGUgcmVmZXJlbmNlIGVsZW1lbnQgb2Zmc2V0c1xuICBkYXRhLm9mZnNldHMucmVmZXJlbmNlID0gZ2V0UmVmZXJlbmNlT2Zmc2V0cyh0aGlzLnN0YXRlLCB0aGlzLnBvcHBlciwgdGhpcy5yZWZlcmVuY2UsIHRoaXMub3B0aW9ucy5wb3NpdGlvbkZpeGVkKTtcblxuICAvLyBjb21wdXRlIGF1dG8gcGxhY2VtZW50LCBzdG9yZSBwbGFjZW1lbnQgaW5zaWRlIHRoZSBkYXRhIG9iamVjdCxcbiAgLy8gbW9kaWZpZXJzIHdpbGwgYmUgYWJsZSB0byBlZGl0IGBwbGFjZW1lbnRgIGlmIG5lZWRlZFxuICAvLyBhbmQgcmVmZXIgdG8gb3JpZ2luYWxQbGFjZW1lbnQgdG8ga25vdyB0aGUgb3JpZ2luYWwgdmFsdWVcbiAgZGF0YS5wbGFjZW1lbnQgPSBjb21wdXRlQXV0b1BsYWNlbWVudCh0aGlzLm9wdGlvbnMucGxhY2VtZW50LCBkYXRhLm9mZnNldHMucmVmZXJlbmNlLCB0aGlzLnBvcHBlciwgdGhpcy5yZWZlcmVuY2UsIHRoaXMub3B0aW9ucy5tb2RpZmllcnMuZmxpcC5ib3VuZGFyaWVzRWxlbWVudCwgdGhpcy5vcHRpb25zLm1vZGlmaWVycy5mbGlwLnBhZGRpbmcpO1xuXG4gIC8vIHN0b3JlIHRoZSBjb21wdXRlZCBwbGFjZW1lbnQgaW5zaWRlIGBvcmlnaW5hbFBsYWNlbWVudGBcbiAgZGF0YS5vcmlnaW5hbFBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50O1xuXG4gIGRhdGEucG9zaXRpb25GaXhlZCA9IHRoaXMub3B0aW9ucy5wb3NpdGlvbkZpeGVkO1xuXG4gIC8vIGNvbXB1dGUgdGhlIHBvcHBlciBvZmZzZXRzXG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBnZXRQb3BwZXJPZmZzZXRzKHRoaXMucG9wcGVyLCBkYXRhLm9mZnNldHMucmVmZXJlbmNlLCBkYXRhLnBsYWNlbWVudCk7XG5cbiAgZGF0YS5vZmZzZXRzLnBvcHBlci5wb3NpdGlvbiA9IHRoaXMub3B0aW9ucy5wb3NpdGlvbkZpeGVkID8gJ2ZpeGVkJyA6ICdhYnNvbHV0ZSc7XG5cbiAgLy8gcnVuIHRoZSBtb2RpZmllcnNcbiAgZGF0YSA9IHJ1bk1vZGlmaWVycyh0aGlzLm1vZGlmaWVycywgZGF0YSk7XG5cbiAgLy8gdGhlIGZpcnN0IGB1cGRhdGVgIHdpbGwgY2FsbCBgb25DcmVhdGVgIGNhbGxiYWNrXG4gIC8vIHRoZSBvdGhlciBvbmVzIHdpbGwgY2FsbCBgb25VcGRhdGVgIGNhbGxiYWNrXG4gIGlmICghdGhpcy5zdGF0ZS5pc0NyZWF0ZWQpIHtcbiAgICB0aGlzLnN0YXRlLmlzQ3JlYXRlZCA9IHRydWU7XG4gICAgdGhpcy5vcHRpb25zLm9uQ3JlYXRlKGRhdGEpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMub3B0aW9ucy5vblVwZGF0ZShkYXRhKTtcbiAgfVxufVxuXG4vKipcbiAqIEhlbHBlciB1c2VkIHRvIGtub3cgaWYgdGhlIGdpdmVuIG1vZGlmaWVyIGlzIGVuYWJsZWQuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNNb2RpZmllckVuYWJsZWQobW9kaWZpZXJzLCBtb2RpZmllck5hbWUpIHtcbiAgcmV0dXJuIG1vZGlmaWVycy5zb21lKGZ1bmN0aW9uIChfcmVmKSB7XG4gICAgdmFyIG5hbWUgPSBfcmVmLm5hbWUsXG4gICAgICAgIGVuYWJsZWQgPSBfcmVmLmVuYWJsZWQ7XG4gICAgcmV0dXJuIGVuYWJsZWQgJiYgbmFtZSA9PT0gbW9kaWZpZXJOYW1lO1xuICB9KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHByZWZpeGVkIHN1cHBvcnRlZCBwcm9wZXJ0eSBuYW1lXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge1N0cmluZ30gcHJvcGVydHkgKGNhbWVsQ2FzZSlcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHByZWZpeGVkIHByb3BlcnR5IChjYW1lbENhc2Ugb3IgUGFzY2FsQ2FzZSwgZGVwZW5kaW5nIG9uIHRoZSB2ZW5kb3IgcHJlZml4KVxuICovXG5mdW5jdGlvbiBnZXRTdXBwb3J0ZWRQcm9wZXJ0eU5hbWUocHJvcGVydHkpIHtcbiAgdmFyIHByZWZpeGVzID0gW2ZhbHNlLCAnbXMnLCAnV2Via2l0JywgJ01veicsICdPJ107XG4gIHZhciB1cHBlclByb3AgPSBwcm9wZXJ0eS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHByb3BlcnR5LnNsaWNlKDEpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcHJlZml4ID0gcHJlZml4ZXNbaV07XG4gICAgdmFyIHRvQ2hlY2sgPSBwcmVmaXggPyAnJyArIHByZWZpeCArIHVwcGVyUHJvcCA6IHByb3BlcnR5O1xuICAgIGlmICh0eXBlb2YgZG9jdW1lbnQuYm9keS5zdHlsZVt0b0NoZWNrXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiB0b0NoZWNrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBEZXN0cm95cyB0aGUgcG9wcGVyLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG5mdW5jdGlvbiBkZXN0cm95KCkge1xuICB0aGlzLnN0YXRlLmlzRGVzdHJveWVkID0gdHJ1ZTtcblxuICAvLyB0b3VjaCBET00gb25seSBpZiBgYXBwbHlTdHlsZWAgbW9kaWZpZXIgaXMgZW5hYmxlZFxuICBpZiAoaXNNb2RpZmllckVuYWJsZWQodGhpcy5tb2RpZmllcnMsICdhcHBseVN0eWxlJykpIHtcbiAgICB0aGlzLnBvcHBlci5yZW1vdmVBdHRyaWJ1dGUoJ3gtcGxhY2VtZW50Jyk7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGUucG9zaXRpb24gPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZS50b3AgPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZS5sZWZ0ID0gJyc7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGUucmlnaHQgPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZS5ib3R0b20gPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZS53aWxsQ2hhbmdlID0gJyc7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGVbZ2V0U3VwcG9ydGVkUHJvcGVydHlOYW1lKCd0cmFuc2Zvcm0nKV0gPSAnJztcbiAgfVxuXG4gIHRoaXMuZGlzYWJsZUV2ZW50TGlzdGVuZXJzKCk7XG5cbiAgLy8gcmVtb3ZlIHRoZSBwb3BwZXIgaWYgdXNlciBleHBsaWNpdHkgYXNrZWQgZm9yIHRoZSBkZWxldGlvbiBvbiBkZXN0cm95XG4gIC8vIGRvIG5vdCB1c2UgYHJlbW92ZWAgYmVjYXVzZSBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBpdFxuICBpZiAodGhpcy5vcHRpb25zLnJlbW92ZU9uRGVzdHJveSkge1xuICAgIHRoaXMucG9wcGVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5wb3BwZXIpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufVxuXG4vKipcbiAqIEdldCB0aGUgd2luZG93IGFzc29jaWF0ZWQgd2l0aCB0aGUgZWxlbWVudFxuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJucyB7V2luZG93fVxuICovXG5mdW5jdGlvbiBnZXRXaW5kb3coZWxlbWVudCkge1xuICB2YXIgb3duZXJEb2N1bWVudCA9IGVsZW1lbnQub3duZXJEb2N1bWVudDtcbiAgcmV0dXJuIG93bmVyRG9jdW1lbnQgPyBvd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IDogd2luZG93O1xufVxuXG5mdW5jdGlvbiBhdHRhY2hUb1Njcm9sbFBhcmVudHMoc2Nyb2xsUGFyZW50LCBldmVudCwgY2FsbGJhY2ssIHNjcm9sbFBhcmVudHMpIHtcbiAgdmFyIGlzQm9keSA9IHNjcm9sbFBhcmVudC5ub2RlTmFtZSA9PT0gJ0JPRFknO1xuICB2YXIgdGFyZ2V0ID0gaXNCb2R5ID8gc2Nyb2xsUGFyZW50Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgOiBzY3JvbGxQYXJlbnQ7XG4gIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBjYWxsYmFjaywgeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4gIGlmICghaXNCb2R5KSB7XG4gICAgYXR0YWNoVG9TY3JvbGxQYXJlbnRzKGdldFNjcm9sbFBhcmVudCh0YXJnZXQucGFyZW50Tm9kZSksIGV2ZW50LCBjYWxsYmFjaywgc2Nyb2xsUGFyZW50cyk7XG4gIH1cbiAgc2Nyb2xsUGFyZW50cy5wdXNoKHRhcmdldCk7XG59XG5cbi8qKlxuICogU2V0dXAgbmVlZGVkIGV2ZW50IGxpc3RlbmVycyB1c2VkIHRvIHVwZGF0ZSB0aGUgcG9wcGVyIHBvc2l0aW9uXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBzZXR1cEV2ZW50TGlzdGVuZXJzKHJlZmVyZW5jZSwgb3B0aW9ucywgc3RhdGUsIHVwZGF0ZUJvdW5kKSB7XG4gIC8vIFJlc2l6ZSBldmVudCBsaXN0ZW5lciBvbiB3aW5kb3dcbiAgc3RhdGUudXBkYXRlQm91bmQgPSB1cGRhdGVCb3VuZDtcbiAgZ2V0V2luZG93KHJlZmVyZW5jZSkuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgc3RhdGUudXBkYXRlQm91bmQsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcblxuICAvLyBTY3JvbGwgZXZlbnQgbGlzdGVuZXIgb24gc2Nyb2xsIHBhcmVudHNcbiAgdmFyIHNjcm9sbEVsZW1lbnQgPSBnZXRTY3JvbGxQYXJlbnQocmVmZXJlbmNlKTtcbiAgYXR0YWNoVG9TY3JvbGxQYXJlbnRzKHNjcm9sbEVsZW1lbnQsICdzY3JvbGwnLCBzdGF0ZS51cGRhdGVCb3VuZCwgc3RhdGUuc2Nyb2xsUGFyZW50cyk7XG4gIHN0YXRlLnNjcm9sbEVsZW1lbnQgPSBzY3JvbGxFbGVtZW50O1xuICBzdGF0ZS5ldmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qKlxuICogSXQgd2lsbCBhZGQgcmVzaXplL3Njcm9sbCBldmVudHMgYW5kIHN0YXJ0IHJlY2FsY3VsYXRpbmdcbiAqIHBvc2l0aW9uIG9mIHRoZSBwb3BwZXIgZWxlbWVudCB3aGVuIHRoZXkgYXJlIHRyaWdnZXJlZC5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXJcbiAqL1xuZnVuY3Rpb24gZW5hYmxlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gIGlmICghdGhpcy5zdGF0ZS5ldmVudHNFbmFibGVkKSB7XG4gICAgdGhpcy5zdGF0ZSA9IHNldHVwRXZlbnRMaXN0ZW5lcnModGhpcy5yZWZlcmVuY2UsIHRoaXMub3B0aW9ucywgdGhpcy5zdGF0ZSwgdGhpcy5zY2hlZHVsZVVwZGF0ZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmUgZXZlbnQgbGlzdGVuZXJzIHVzZWQgdG8gdXBkYXRlIHRoZSBwb3BwZXIgcG9zaXRpb25cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXJzKHJlZmVyZW5jZSwgc3RhdGUpIHtcbiAgLy8gUmVtb3ZlIHJlc2l6ZSBldmVudCBsaXN0ZW5lciBvbiB3aW5kb3dcbiAgZ2V0V2luZG93KHJlZmVyZW5jZSkucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgc3RhdGUudXBkYXRlQm91bmQpO1xuXG4gIC8vIFJlbW92ZSBzY3JvbGwgZXZlbnQgbGlzdGVuZXIgb24gc2Nyb2xsIHBhcmVudHNcbiAgc3RhdGUuc2Nyb2xsUGFyZW50cy5mb3JFYWNoKGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3RhdGUudXBkYXRlQm91bmQpO1xuICB9KTtcblxuICAvLyBSZXNldCBzdGF0ZVxuICBzdGF0ZS51cGRhdGVCb3VuZCA9IG51bGw7XG4gIHN0YXRlLnNjcm9sbFBhcmVudHMgPSBbXTtcbiAgc3RhdGUuc2Nyb2xsRWxlbWVudCA9IG51bGw7XG4gIHN0YXRlLmV2ZW50c0VuYWJsZWQgPSBmYWxzZTtcbiAgcmV0dXJuIHN0YXRlO1xufVxuXG4vKipcbiAqIEl0IHdpbGwgcmVtb3ZlIHJlc2l6ZS9zY3JvbGwgZXZlbnRzIGFuZCB3b24ndCByZWNhbGN1bGF0ZSBwb3BwZXIgcG9zaXRpb25cbiAqIHdoZW4gdGhleSBhcmUgdHJpZ2dlcmVkLiBJdCBhbHNvIHdvbid0IHRyaWdnZXIgYG9uVXBkYXRlYCBjYWxsYmFjayBhbnltb3JlLFxuICogdW5sZXNzIHlvdSBjYWxsIGB1cGRhdGVgIG1ldGhvZCBtYW51YWxseS5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXJcbiAqL1xuZnVuY3Rpb24gZGlzYWJsZUV2ZW50TGlzdGVuZXJzKCkge1xuICBpZiAodGhpcy5zdGF0ZS5ldmVudHNFbmFibGVkKSB7XG4gICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5zY2hlZHVsZVVwZGF0ZSk7XG4gICAgdGhpcy5zdGF0ZSA9IHJlbW92ZUV2ZW50TGlzdGVuZXJzKHRoaXMucmVmZXJlbmNlLCB0aGlzLnN0YXRlKTtcbiAgfVxufVxuXG4vKipcbiAqIFRlbGxzIGlmIGEgZ2l2ZW4gaW5wdXQgaXMgYSBudW1iZXJcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7Kn0gaW5wdXQgdG8gY2hlY2tcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzTnVtZXJpYyhuKSB7XG4gIHJldHVybiBuICE9PSAnJyAmJiAhaXNOYU4ocGFyc2VGbG9hdChuKSkgJiYgaXNGaW5pdGUobik7XG59XG5cbi8qKlxuICogU2V0IHRoZSBzdHlsZSB0byB0aGUgZ2l2ZW4gcG9wcGVyXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnQgLSBFbGVtZW50IHRvIGFwcGx5IHRoZSBzdHlsZSB0b1xuICogQGFyZ3VtZW50IHtPYmplY3R9IHN0eWxlc1xuICogT2JqZWN0IHdpdGggYSBsaXN0IG9mIHByb3BlcnRpZXMgYW5kIHZhbHVlcyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnRcbiAqL1xuZnVuY3Rpb24gc2V0U3R5bGVzKGVsZW1lbnQsIHN0eWxlcykge1xuICBPYmplY3Qua2V5cyhzdHlsZXMpLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHtcbiAgICB2YXIgdW5pdCA9ICcnO1xuICAgIC8vIGFkZCB1bml0IGlmIHRoZSB2YWx1ZSBpcyBudW1lcmljIGFuZCBpcyBvbmUgb2YgdGhlIGZvbGxvd2luZ1xuICAgIGlmIChbJ3dpZHRoJywgJ2hlaWdodCcsICd0b3AnLCAncmlnaHQnLCAnYm90dG9tJywgJ2xlZnQnXS5pbmRleE9mKHByb3ApICE9PSAtMSAmJiBpc051bWVyaWMoc3R5bGVzW3Byb3BdKSkge1xuICAgICAgdW5pdCA9ICdweCc7XG4gICAgfVxuICAgIGVsZW1lbnQuc3R5bGVbcHJvcF0gPSBzdHlsZXNbcHJvcF0gKyB1bml0O1xuICB9KTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIGF0dHJpYnV0ZXMgdG8gdGhlIGdpdmVuIHBvcHBlclxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50IC0gRWxlbWVudCB0byBhcHBseSB0aGUgYXR0cmlidXRlcyB0b1xuICogQGFyZ3VtZW50IHtPYmplY3R9IHN0eWxlc1xuICogT2JqZWN0IHdpdGggYSBsaXN0IG9mIHByb3BlcnRpZXMgYW5kIHZhbHVlcyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIGVsZW1lbnRcbiAqL1xuZnVuY3Rpb24gc2V0QXR0cmlidXRlcyhlbGVtZW50LCBhdHRyaWJ1dGVzKSB7XG4gIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpLmZvckVhY2goZnVuY3Rpb24gKHByb3ApIHtcbiAgICB2YXIgdmFsdWUgPSBhdHRyaWJ1dGVzW3Byb3BdO1xuICAgIGlmICh2YWx1ZSAhPT0gZmFsc2UpIHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKHByb3AsIGF0dHJpYnV0ZXNbcHJvcF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShwcm9wKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEuc3R5bGVzIC0gTGlzdCBvZiBzdHlsZSBwcm9wZXJ0aWVzIC0gdmFsdWVzIHRvIGFwcGx5IHRvIHBvcHBlciBlbGVtZW50XG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YS5hdHRyaWJ1dGVzIC0gTGlzdCBvZiBhdHRyaWJ1dGUgcHJvcGVydGllcyAtIHZhbHVlcyB0byBhcHBseSB0byBwb3BwZXIgZWxlbWVudFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIHNhbWUgZGF0YSBvYmplY3RcbiAqL1xuZnVuY3Rpb24gYXBwbHlTdHlsZShkYXRhKSB7XG4gIC8vIGFueSBwcm9wZXJ0eSBwcmVzZW50IGluIGBkYXRhLnN0eWxlc2Agd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIsXG4gIC8vIGluIHRoaXMgd2F5IHdlIGNhbiBtYWtlIHRoZSAzcmQgcGFydHkgbW9kaWZpZXJzIGFkZCBjdXN0b20gc3R5bGVzIHRvIGl0XG4gIC8vIEJlIGF3YXJlLCBtb2RpZmllcnMgY291bGQgb3ZlcnJpZGUgdGhlIHByb3BlcnRpZXMgZGVmaW5lZCBpbiB0aGUgcHJldmlvdXNcbiAgLy8gbGluZXMgb2YgdGhpcyBtb2RpZmllciFcbiAgc2V0U3R5bGVzKGRhdGEuaW5zdGFuY2UucG9wcGVyLCBkYXRhLnN0eWxlcyk7XG5cbiAgLy8gYW55IHByb3BlcnR5IHByZXNlbnQgaW4gYGRhdGEuYXR0cmlidXRlc2Agd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIsXG4gIC8vIHRoZXkgd2lsbCBiZSBzZXQgYXMgSFRNTCBhdHRyaWJ1dGVzIG9mIHRoZSBlbGVtZW50XG4gIHNldEF0dHJpYnV0ZXMoZGF0YS5pbnN0YW5jZS5wb3BwZXIsIGRhdGEuYXR0cmlidXRlcyk7XG5cbiAgLy8gaWYgYXJyb3dFbGVtZW50IGlzIGRlZmluZWQgYW5kIGFycm93U3R5bGVzIGhhcyBzb21lIHByb3BlcnRpZXNcbiAgaWYgKGRhdGEuYXJyb3dFbGVtZW50ICYmIE9iamVjdC5rZXlzKGRhdGEuYXJyb3dTdHlsZXMpLmxlbmd0aCkge1xuICAgIHNldFN0eWxlcyhkYXRhLmFycm93RWxlbWVudCwgZGF0YS5hcnJvd1N0eWxlcyk7XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIHgtcGxhY2VtZW50IGF0dHJpYnV0ZSBiZWZvcmUgZXZlcnl0aGluZyBlbHNlIGJlY2F1c2UgaXQgY291bGQgYmUgdXNlZFxuICogdG8gYWRkIG1hcmdpbnMgdG8gdGhlIHBvcHBlciBtYXJnaW5zIG5lZWRzIHRvIGJlIGNhbGN1bGF0ZWQgdG8gZ2V0IHRoZVxuICogY29ycmVjdCBwb3BwZXIgb2Zmc2V0cy5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIubW9kaWZpZXJzXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByZWZlcmVuY2UgLSBUaGUgcmVmZXJlbmNlIGVsZW1lbnQgdXNlZCB0byBwb3NpdGlvbiB0aGUgcG9wcGVyXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwb3BwZXIgLSBUaGUgSFRNTCBlbGVtZW50IHVzZWQgYXMgcG9wcGVyXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFBvcHBlci5qcyBvcHRpb25zXG4gKi9cbmZ1bmN0aW9uIGFwcGx5U3R5bGVPbkxvYWQocmVmZXJlbmNlLCBwb3BwZXIsIG9wdGlvbnMsIG1vZGlmaWVyT3B0aW9ucywgc3RhdGUpIHtcbiAgLy8gY29tcHV0ZSByZWZlcmVuY2UgZWxlbWVudCBvZmZzZXRzXG4gIHZhciByZWZlcmVuY2VPZmZzZXRzID0gZ2V0UmVmZXJlbmNlT2Zmc2V0cyhzdGF0ZSwgcG9wcGVyLCByZWZlcmVuY2UsIG9wdGlvbnMucG9zaXRpb25GaXhlZCk7XG5cbiAgLy8gY29tcHV0ZSBhdXRvIHBsYWNlbWVudCwgc3RvcmUgcGxhY2VtZW50IGluc2lkZSB0aGUgZGF0YSBvYmplY3QsXG4gIC8vIG1vZGlmaWVycyB3aWxsIGJlIGFibGUgdG8gZWRpdCBgcGxhY2VtZW50YCBpZiBuZWVkZWRcbiAgLy8gYW5kIHJlZmVyIHRvIG9yaWdpbmFsUGxhY2VtZW50IHRvIGtub3cgdGhlIG9yaWdpbmFsIHZhbHVlXG4gIHZhciBwbGFjZW1lbnQgPSBjb21wdXRlQXV0b1BsYWNlbWVudChvcHRpb25zLnBsYWNlbWVudCwgcmVmZXJlbmNlT2Zmc2V0cywgcG9wcGVyLCByZWZlcmVuY2UsIG9wdGlvbnMubW9kaWZpZXJzLmZsaXAuYm91bmRhcmllc0VsZW1lbnQsIG9wdGlvbnMubW9kaWZpZXJzLmZsaXAucGFkZGluZyk7XG5cbiAgcG9wcGVyLnNldEF0dHJpYnV0ZSgneC1wbGFjZW1lbnQnLCBwbGFjZW1lbnQpO1xuXG4gIC8vIEFwcGx5IGBwb3NpdGlvbmAgdG8gcG9wcGVyIGJlZm9yZSBhbnl0aGluZyBlbHNlIGJlY2F1c2VcbiAgLy8gd2l0aG91dCB0aGUgcG9zaXRpb24gYXBwbGllZCB3ZSBjYW4ndCBndWFyYW50ZWUgY29ycmVjdCBjb21wdXRhdGlvbnNcbiAgc2V0U3R5bGVzKHBvcHBlciwgeyBwb3NpdGlvbjogb3B0aW9ucy5wb3NpdGlvbkZpeGVkID8gJ2ZpeGVkJyA6ICdhYnNvbHV0ZScgfSk7XG5cbiAgcmV0dXJuIG9wdGlvbnM7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGNvbXB1dGVTdHlsZShkYXRhLCBvcHRpb25zKSB7XG4gIHZhciB4ID0gb3B0aW9ucy54LFxuICAgICAgeSA9IG9wdGlvbnMueTtcbiAgdmFyIHBvcHBlciA9IGRhdGEub2Zmc2V0cy5wb3BwZXI7XG5cbiAgLy8gUmVtb3ZlIHRoaXMgbGVnYWN5IHN1cHBvcnQgaW4gUG9wcGVyLmpzIHYyXG5cbiAgdmFyIGxlZ2FjeUdwdUFjY2VsZXJhdGlvbk9wdGlvbiA9IGZpbmQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsIGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgIHJldHVybiBtb2RpZmllci5uYW1lID09PSAnYXBwbHlTdHlsZSc7XG4gIH0pLmdwdUFjY2VsZXJhdGlvbjtcbiAgaWYgKGxlZ2FjeUdwdUFjY2VsZXJhdGlvbk9wdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc29sZS53YXJuKCdXQVJOSU5HOiBgZ3B1QWNjZWxlcmF0aW9uYCBvcHRpb24gbW92ZWQgdG8gYGNvbXB1dGVTdHlsZWAgbW9kaWZpZXIgYW5kIHdpbGwgbm90IGJlIHN1cHBvcnRlZCBpbiBmdXR1cmUgdmVyc2lvbnMgb2YgUG9wcGVyLmpzIScpO1xuICB9XG4gIHZhciBncHVBY2NlbGVyYXRpb24gPSBsZWdhY3lHcHVBY2NlbGVyYXRpb25PcHRpb24gIT09IHVuZGVmaW5lZCA/IGxlZ2FjeUdwdUFjY2VsZXJhdGlvbk9wdGlvbiA6IG9wdGlvbnMuZ3B1QWNjZWxlcmF0aW9uO1xuXG4gIHZhciBvZmZzZXRQYXJlbnQgPSBnZXRPZmZzZXRQYXJlbnQoZGF0YS5pbnN0YW5jZS5wb3BwZXIpO1xuICB2YXIgb2Zmc2V0UGFyZW50UmVjdCA9IGdldEJvdW5kaW5nQ2xpZW50UmVjdChvZmZzZXRQYXJlbnQpO1xuXG4gIC8vIFN0eWxlc1xuICB2YXIgc3R5bGVzID0ge1xuICAgIHBvc2l0aW9uOiBwb3BwZXIucG9zaXRpb25cbiAgfTtcblxuICAvLyBBdm9pZCBibHVycnkgdGV4dCBieSB1c2luZyBmdWxsIHBpeGVsIGludGVnZXJzLlxuICAvLyBGb3IgcGl4ZWwtcGVyZmVjdCBwb3NpdGlvbmluZywgdG9wL2JvdHRvbSBwcmVmZXJzIHJvdW5kZWRcbiAgLy8gdmFsdWVzLCB3aGlsZSBsZWZ0L3JpZ2h0IHByZWZlcnMgZmxvb3JlZCB2YWx1ZXMuXG4gIHZhciBvZmZzZXRzID0ge1xuICAgIGxlZnQ6IE1hdGguZmxvb3IocG9wcGVyLmxlZnQpLFxuICAgIHRvcDogTWF0aC5yb3VuZChwb3BwZXIudG9wKSxcbiAgICBib3R0b206IE1hdGgucm91bmQocG9wcGVyLmJvdHRvbSksXG4gICAgcmlnaHQ6IE1hdGguZmxvb3IocG9wcGVyLnJpZ2h0KVxuICB9O1xuXG4gIHZhciBzaWRlQSA9IHggPT09ICdib3R0b20nID8gJ3RvcCcgOiAnYm90dG9tJztcbiAgdmFyIHNpZGVCID0geSA9PT0gJ3JpZ2h0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG5cbiAgLy8gaWYgZ3B1QWNjZWxlcmF0aW9uIGlzIHNldCB0byBgdHJ1ZWAgYW5kIHRyYW5zZm9ybSBpcyBzdXBwb3J0ZWQsXG4gIC8vICB3ZSB1c2UgYHRyYW5zbGF0ZTNkYCB0byBhcHBseSB0aGUgcG9zaXRpb24gdG8gdGhlIHBvcHBlciB3ZVxuICAvLyBhdXRvbWF0aWNhbGx5IHVzZSB0aGUgc3VwcG9ydGVkIHByZWZpeGVkIHZlcnNpb24gaWYgbmVlZGVkXG4gIHZhciBwcmVmaXhlZFByb3BlcnR5ID0gZ2V0U3VwcG9ydGVkUHJvcGVydHlOYW1lKCd0cmFuc2Zvcm0nKTtcblxuICAvLyBub3csIGxldCdzIG1ha2UgYSBzdGVwIGJhY2sgYW5kIGxvb2sgYXQgdGhpcyBjb2RlIGNsb3NlbHkgKHd0Zj8pXG4gIC8vIElmIHRoZSBjb250ZW50IG9mIHRoZSBwb3BwZXIgZ3Jvd3Mgb25jZSBpdCdzIGJlZW4gcG9zaXRpb25lZCwgaXRcbiAgLy8gbWF5IGhhcHBlbiB0aGF0IHRoZSBwb3BwZXIgZ2V0cyBtaXNwbGFjZWQgYmVjYXVzZSBvZiB0aGUgbmV3IGNvbnRlbnRcbiAgLy8gb3ZlcmZsb3dpbmcgaXRzIHJlZmVyZW5jZSBlbGVtZW50XG4gIC8vIFRvIGF2b2lkIHRoaXMgcHJvYmxlbSwgd2UgcHJvdmlkZSB0d28gb3B0aW9ucyAoeCBhbmQgeSksIHdoaWNoIGFsbG93XG4gIC8vIHRoZSBjb25zdW1lciB0byBkZWZpbmUgdGhlIG9mZnNldCBvcmlnaW4uXG4gIC8vIElmIHdlIHBvc2l0aW9uIGEgcG9wcGVyIG9uIHRvcCBvZiBhIHJlZmVyZW5jZSBlbGVtZW50LCB3ZSBjYW4gc2V0XG4gIC8vIGB4YCB0byBgdG9wYCB0byBtYWtlIHRoZSBwb3BwZXIgZ3JvdyB0b3dhcmRzIGl0cyB0b3AgaW5zdGVhZCBvZlxuICAvLyBpdHMgYm90dG9tLlxuICB2YXIgbGVmdCA9IHZvaWQgMCxcbiAgICAgIHRvcCA9IHZvaWQgMDtcbiAgaWYgKHNpZGVBID09PSAnYm90dG9tJykge1xuICAgIC8vIHdoZW4gb2Zmc2V0UGFyZW50IGlzIDxodG1sPiB0aGUgcG9zaXRpb25pbmcgaXMgcmVsYXRpdmUgdG8gdGhlIGJvdHRvbSBvZiB0aGUgc2NyZWVuIChleGNsdWRpbmcgdGhlIHNjcm9sbGJhcilcbiAgICAvLyBhbmQgbm90IHRoZSBib3R0b20gb2YgdGhlIGh0bWwgZWxlbWVudFxuICAgIGlmIChvZmZzZXRQYXJlbnQubm9kZU5hbWUgPT09ICdIVE1MJykge1xuICAgICAgdG9wID0gLW9mZnNldFBhcmVudC5jbGllbnRIZWlnaHQgKyBvZmZzZXRzLmJvdHRvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgdG9wID0gLW9mZnNldFBhcmVudFJlY3QuaGVpZ2h0ICsgb2Zmc2V0cy5ib3R0b207XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRvcCA9IG9mZnNldHMudG9wO1xuICB9XG4gIGlmIChzaWRlQiA9PT0gJ3JpZ2h0Jykge1xuICAgIGlmIChvZmZzZXRQYXJlbnQubm9kZU5hbWUgPT09ICdIVE1MJykge1xuICAgICAgbGVmdCA9IC1vZmZzZXRQYXJlbnQuY2xpZW50V2lkdGggKyBvZmZzZXRzLnJpZ2h0O1xuICAgIH0gZWxzZSB7XG4gICAgICBsZWZ0ID0gLW9mZnNldFBhcmVudFJlY3Qud2lkdGggKyBvZmZzZXRzLnJpZ2h0O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZWZ0ID0gb2Zmc2V0cy5sZWZ0O1xuICB9XG4gIGlmIChncHVBY2NlbGVyYXRpb24gJiYgcHJlZml4ZWRQcm9wZXJ0eSkge1xuICAgIHN0eWxlc1twcmVmaXhlZFByb3BlcnR5XSA9ICd0cmFuc2xhdGUzZCgnICsgbGVmdCArICdweCwgJyArIHRvcCArICdweCwgMCknO1xuICAgIHN0eWxlc1tzaWRlQV0gPSAwO1xuICAgIHN0eWxlc1tzaWRlQl0gPSAwO1xuICAgIHN0eWxlcy53aWxsQ2hhbmdlID0gJ3RyYW5zZm9ybSc7XG4gIH0gZWxzZSB7XG4gICAgLy8gb3Rod2VyaXNlLCB3ZSB1c2UgdGhlIHN0YW5kYXJkIGB0b3BgLCBgbGVmdGAsIGBib3R0b21gIGFuZCBgcmlnaHRgIHByb3BlcnRpZXNcbiAgICB2YXIgaW52ZXJ0VG9wID0gc2lkZUEgPT09ICdib3R0b20nID8gLTEgOiAxO1xuICAgIHZhciBpbnZlcnRMZWZ0ID0gc2lkZUIgPT09ICdyaWdodCcgPyAtMSA6IDE7XG4gICAgc3R5bGVzW3NpZGVBXSA9IHRvcCAqIGludmVydFRvcDtcbiAgICBzdHlsZXNbc2lkZUJdID0gbGVmdCAqIGludmVydExlZnQ7XG4gICAgc3R5bGVzLndpbGxDaGFuZ2UgPSBzaWRlQSArICcsICcgKyBzaWRlQjtcbiAgfVxuXG4gIC8vIEF0dHJpYnV0ZXNcbiAgdmFyIGF0dHJpYnV0ZXMgPSB7XG4gICAgJ3gtcGxhY2VtZW50JzogZGF0YS5wbGFjZW1lbnRcbiAgfTtcblxuICAvLyBVcGRhdGUgYGRhdGFgIGF0dHJpYnV0ZXMsIHN0eWxlcyBhbmQgYXJyb3dTdHlsZXNcbiAgZGF0YS5hdHRyaWJ1dGVzID0gX2V4dGVuZHMoe30sIGF0dHJpYnV0ZXMsIGRhdGEuYXR0cmlidXRlcyk7XG4gIGRhdGEuc3R5bGVzID0gX2V4dGVuZHMoe30sIHN0eWxlcywgZGF0YS5zdHlsZXMpO1xuICBkYXRhLmFycm93U3R5bGVzID0gX2V4dGVuZHMoe30sIGRhdGEub2Zmc2V0cy5hcnJvdywgZGF0YS5hcnJvd1N0eWxlcyk7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogSGVscGVyIHVzZWQgdG8ga25vdyBpZiB0aGUgZ2l2ZW4gbW9kaWZpZXIgZGVwZW5kcyBmcm9tIGFub3RoZXIgb25lLjxiciAvPlxuICogSXQgY2hlY2tzIGlmIHRoZSBuZWVkZWQgbW9kaWZpZXIgaXMgbGlzdGVkIGFuZCBlbmFibGVkLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtBcnJheX0gbW9kaWZpZXJzIC0gbGlzdCBvZiBtb2RpZmllcnNcbiAqIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0aW5nTmFtZSAtIG5hbWUgb2YgcmVxdWVzdGluZyBtb2RpZmllclxuICogQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RlZE5hbWUgLSBuYW1lIG9mIHJlcXVlc3RlZCBtb2RpZmllclxuICogQHJldHVybnMge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzTW9kaWZpZXJSZXF1aXJlZChtb2RpZmllcnMsIHJlcXVlc3RpbmdOYW1lLCByZXF1ZXN0ZWROYW1lKSB7XG4gIHZhciByZXF1ZXN0aW5nID0gZmluZChtb2RpZmllcnMsIGZ1bmN0aW9uIChfcmVmKSB7XG4gICAgdmFyIG5hbWUgPSBfcmVmLm5hbWU7XG4gICAgcmV0dXJuIG5hbWUgPT09IHJlcXVlc3RpbmdOYW1lO1xuICB9KTtcblxuICB2YXIgaXNSZXF1aXJlZCA9ICEhcmVxdWVzdGluZyAmJiBtb2RpZmllcnMuc29tZShmdW5jdGlvbiAobW9kaWZpZXIpIHtcbiAgICByZXR1cm4gbW9kaWZpZXIubmFtZSA9PT0gcmVxdWVzdGVkTmFtZSAmJiBtb2RpZmllci5lbmFibGVkICYmIG1vZGlmaWVyLm9yZGVyIDwgcmVxdWVzdGluZy5vcmRlcjtcbiAgfSk7XG5cbiAgaWYgKCFpc1JlcXVpcmVkKSB7XG4gICAgdmFyIF9yZXF1ZXN0aW5nID0gJ2AnICsgcmVxdWVzdGluZ05hbWUgKyAnYCc7XG4gICAgdmFyIHJlcXVlc3RlZCA9ICdgJyArIHJlcXVlc3RlZE5hbWUgKyAnYCc7XG4gICAgY29uc29sZS53YXJuKHJlcXVlc3RlZCArICcgbW9kaWZpZXIgaXMgcmVxdWlyZWQgYnkgJyArIF9yZXF1ZXN0aW5nICsgJyBtb2RpZmllciBpbiBvcmRlciB0byB3b3JrLCBiZSBzdXJlIHRvIGluY2x1ZGUgaXQgYmVmb3JlICcgKyBfcmVxdWVzdGluZyArICchJyk7XG4gIH1cbiAgcmV0dXJuIGlzUmVxdWlyZWQ7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBhcnJvdyhkYXRhLCBvcHRpb25zKSB7XG4gIHZhciBfZGF0YSRvZmZzZXRzJGFycm93O1xuXG4gIC8vIGFycm93IGRlcGVuZHMgb24ga2VlcFRvZ2V0aGVyIGluIG9yZGVyIHRvIHdvcmtcbiAgaWYgKCFpc01vZGlmaWVyUmVxdWlyZWQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsICdhcnJvdycsICdrZWVwVG9nZXRoZXInKSkge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgdmFyIGFycm93RWxlbWVudCA9IG9wdGlvbnMuZWxlbWVudDtcblxuICAvLyBpZiBhcnJvd0VsZW1lbnQgaXMgYSBzdHJpbmcsIHN1cHBvc2UgaXQncyBhIENTUyBzZWxlY3RvclxuICBpZiAodHlwZW9mIGFycm93RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICBhcnJvd0VsZW1lbnQgPSBkYXRhLmluc3RhbmNlLnBvcHBlci5xdWVyeVNlbGVjdG9yKGFycm93RWxlbWVudCk7XG5cbiAgICAvLyBpZiBhcnJvd0VsZW1lbnQgaXMgbm90IGZvdW5kLCBkb24ndCBydW4gdGhlIG1vZGlmaWVyXG4gICAgaWYgKCFhcnJvd0VsZW1lbnQpIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBpZiB0aGUgYXJyb3dFbGVtZW50IGlzbid0IGEgcXVlcnkgc2VsZWN0b3Igd2UgbXVzdCBjaGVjayB0aGF0IHRoZVxuICAgIC8vIHByb3ZpZGVkIERPTSBub2RlIGlzIGNoaWxkIG9mIGl0cyBwb3BwZXIgbm9kZVxuICAgIGlmICghZGF0YS5pbnN0YW5jZS5wb3BwZXIuY29udGFpbnMoYXJyb3dFbGVtZW50KSkge1xuICAgICAgY29uc29sZS53YXJuKCdXQVJOSU5HOiBgYXJyb3cuZWxlbWVudGAgbXVzdCBiZSBjaGlsZCBvZiBpdHMgcG9wcGVyIGVsZW1lbnQhJyk7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gIH1cblxuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgdmFyIF9kYXRhJG9mZnNldHMgPSBkYXRhLm9mZnNldHMsXG4gICAgICBwb3BwZXIgPSBfZGF0YSRvZmZzZXRzLnBvcHBlcixcbiAgICAgIHJlZmVyZW5jZSA9IF9kYXRhJG9mZnNldHMucmVmZXJlbmNlO1xuXG4gIHZhciBpc1ZlcnRpY2FsID0gWydsZWZ0JywgJ3JpZ2h0J10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcblxuICB2YXIgbGVuID0gaXNWZXJ0aWNhbCA/ICdoZWlnaHQnIDogJ3dpZHRoJztcbiAgdmFyIHNpZGVDYXBpdGFsaXplZCA9IGlzVmVydGljYWwgPyAnVG9wJyA6ICdMZWZ0JztcbiAgdmFyIHNpZGUgPSBzaWRlQ2FwaXRhbGl6ZWQudG9Mb3dlckNhc2UoKTtcbiAgdmFyIGFsdFNpZGUgPSBpc1ZlcnRpY2FsID8gJ2xlZnQnIDogJ3RvcCc7XG4gIHZhciBvcFNpZGUgPSBpc1ZlcnRpY2FsID8gJ2JvdHRvbScgOiAncmlnaHQnO1xuICB2YXIgYXJyb3dFbGVtZW50U2l6ZSA9IGdldE91dGVyU2l6ZXMoYXJyb3dFbGVtZW50KVtsZW5dO1xuXG4gIC8vXG4gIC8vIGV4dGVuZHMga2VlcFRvZ2V0aGVyIGJlaGF2aW9yIG1ha2luZyBzdXJlIHRoZSBwb3BwZXIgYW5kIGl0c1xuICAvLyByZWZlcmVuY2UgaGF2ZSBlbm91Z2ggcGl4ZWxzIGluIGNvbmp1bmN0aW9uXG4gIC8vXG5cbiAgLy8gdG9wL2xlZnQgc2lkZVxuICBpZiAocmVmZXJlbmNlW29wU2lkZV0gLSBhcnJvd0VsZW1lbnRTaXplIDwgcG9wcGVyW3NpZGVdKSB7XG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlcltzaWRlXSAtPSBwb3BwZXJbc2lkZV0gLSAocmVmZXJlbmNlW29wU2lkZV0gLSBhcnJvd0VsZW1lbnRTaXplKTtcbiAgfVxuICAvLyBib3R0b20vcmlnaHQgc2lkZVxuICBpZiAocmVmZXJlbmNlW3NpZGVdICsgYXJyb3dFbGVtZW50U2l6ZSA+IHBvcHBlcltvcFNpZGVdKSB7XG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlcltzaWRlXSArPSByZWZlcmVuY2Vbc2lkZV0gKyBhcnJvd0VsZW1lbnRTaXplIC0gcG9wcGVyW29wU2lkZV07XG4gIH1cbiAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldENsaWVudFJlY3QoZGF0YS5vZmZzZXRzLnBvcHBlcik7XG5cbiAgLy8gY29tcHV0ZSBjZW50ZXIgb2YgdGhlIHBvcHBlclxuICB2YXIgY2VudGVyID0gcmVmZXJlbmNlW3NpZGVdICsgcmVmZXJlbmNlW2xlbl0gLyAyIC0gYXJyb3dFbGVtZW50U2l6ZSAvIDI7XG5cbiAgLy8gQ29tcHV0ZSB0aGUgc2lkZVZhbHVlIHVzaW5nIHRoZSB1cGRhdGVkIHBvcHBlciBvZmZzZXRzXG4gIC8vIHRha2UgcG9wcGVyIG1hcmdpbiBpbiBhY2NvdW50IGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSB0aGlzIGluZm8gYXZhaWxhYmxlXG4gIHZhciBjc3MgPSBnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkoZGF0YS5pbnN0YW5jZS5wb3BwZXIpO1xuICB2YXIgcG9wcGVyTWFyZ2luU2lkZSA9IHBhcnNlRmxvYXQoY3NzWydtYXJnaW4nICsgc2lkZUNhcGl0YWxpemVkXSwgMTApO1xuICB2YXIgcG9wcGVyQm9yZGVyU2lkZSA9IHBhcnNlRmxvYXQoY3NzWydib3JkZXInICsgc2lkZUNhcGl0YWxpemVkICsgJ1dpZHRoJ10sIDEwKTtcbiAgdmFyIHNpZGVWYWx1ZSA9IGNlbnRlciAtIGRhdGEub2Zmc2V0cy5wb3BwZXJbc2lkZV0gLSBwb3BwZXJNYXJnaW5TaWRlIC0gcG9wcGVyQm9yZGVyU2lkZTtcblxuICAvLyBwcmV2ZW50IGFycm93RWxlbWVudCBmcm9tIGJlaW5nIHBsYWNlZCBub3QgY29udGlndW91c2x5IHRvIGl0cyBwb3BwZXJcbiAgc2lkZVZhbHVlID0gTWF0aC5tYXgoTWF0aC5taW4ocG9wcGVyW2xlbl0gLSBhcnJvd0VsZW1lbnRTaXplLCBzaWRlVmFsdWUpLCAwKTtcblxuICBkYXRhLmFycm93RWxlbWVudCA9IGFycm93RWxlbWVudDtcbiAgZGF0YS5vZmZzZXRzLmFycm93ID0gKF9kYXRhJG9mZnNldHMkYXJyb3cgPSB7fSwgZGVmaW5lUHJvcGVydHkoX2RhdGEkb2Zmc2V0cyRhcnJvdywgc2lkZSwgTWF0aC5yb3VuZChzaWRlVmFsdWUpKSwgZGVmaW5lUHJvcGVydHkoX2RhdGEkb2Zmc2V0cyRhcnJvdywgYWx0U2lkZSwgJycpLCBfZGF0YSRvZmZzZXRzJGFycm93KTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG9wcG9zaXRlIHBsYWNlbWVudCB2YXJpYXRpb24gb2YgdGhlIGdpdmVuIG9uZVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IHBsYWNlbWVudCB2YXJpYXRpb25cbiAqIEByZXR1cm5zIHtTdHJpbmd9IGZsaXBwZWQgcGxhY2VtZW50IHZhcmlhdGlvblxuICovXG5mdW5jdGlvbiBnZXRPcHBvc2l0ZVZhcmlhdGlvbih2YXJpYXRpb24pIHtcbiAgaWYgKHZhcmlhdGlvbiA9PT0gJ2VuZCcpIHtcbiAgICByZXR1cm4gJ3N0YXJ0JztcbiAgfSBlbHNlIGlmICh2YXJpYXRpb24gPT09ICdzdGFydCcpIHtcbiAgICByZXR1cm4gJ2VuZCc7XG4gIH1cbiAgcmV0dXJuIHZhcmlhdGlvbjtcbn1cblxuLyoqXG4gKiBMaXN0IG9mIGFjY2VwdGVkIHBsYWNlbWVudHMgdG8gdXNlIGFzIHZhbHVlcyBvZiB0aGUgYHBsYWNlbWVudGAgb3B0aW9uLjxiciAvPlxuICogVmFsaWQgcGxhY2VtZW50cyBhcmU6XG4gKiAtIGBhdXRvYFxuICogLSBgdG9wYFxuICogLSBgcmlnaHRgXG4gKiAtIGBib3R0b21gXG4gKiAtIGBsZWZ0YFxuICpcbiAqIEVhY2ggcGxhY2VtZW50IGNhbiBoYXZlIGEgdmFyaWF0aW9uIGZyb20gdGhpcyBsaXN0OlxuICogLSBgLXN0YXJ0YFxuICogLSBgLWVuZGBcbiAqXG4gKiBWYXJpYXRpb25zIGFyZSBpbnRlcnByZXRlZCBlYXNpbHkgaWYgeW91IHRoaW5rIG9mIHRoZW0gYXMgdGhlIGxlZnQgdG8gcmlnaHRcbiAqIHdyaXR0ZW4gbGFuZ3VhZ2VzLiBIb3Jpem9udGFsbHkgKGB0b3BgIGFuZCBgYm90dG9tYCksIGBzdGFydGAgaXMgbGVmdCBhbmQgYGVuZGBcbiAqIGlzIHJpZ2h0LjxiciAvPlxuICogVmVydGljYWxseSAoYGxlZnRgIGFuZCBgcmlnaHRgKSwgYHN0YXJ0YCBpcyB0b3AgYW5kIGBlbmRgIGlzIGJvdHRvbS5cbiAqXG4gKiBTb21lIHZhbGlkIGV4YW1wbGVzIGFyZTpcbiAqIC0gYHRvcC1lbmRgIChvbiB0b3Agb2YgcmVmZXJlbmNlLCByaWdodCBhbGlnbmVkKVxuICogLSBgcmlnaHQtc3RhcnRgIChvbiByaWdodCBvZiByZWZlcmVuY2UsIHRvcCBhbGlnbmVkKVxuICogLSBgYm90dG9tYCAob24gYm90dG9tLCBjZW50ZXJlZClcbiAqIC0gYGF1dG8tZW5kYCAob24gdGhlIHNpZGUgd2l0aCBtb3JlIHNwYWNlIGF2YWlsYWJsZSwgYWxpZ25tZW50IGRlcGVuZHMgYnkgcGxhY2VtZW50KVxuICpcbiAqIEBzdGF0aWNcbiAqIEB0eXBlIHtBcnJheX1cbiAqIEBlbnVtIHtTdHJpbmd9XG4gKiBAcmVhZG9ubHlcbiAqIEBtZXRob2QgcGxhY2VtZW50c1xuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG52YXIgcGxhY2VtZW50cyA9IFsnYXV0by1zdGFydCcsICdhdXRvJywgJ2F1dG8tZW5kJywgJ3RvcC1zdGFydCcsICd0b3AnLCAndG9wLWVuZCcsICdyaWdodC1zdGFydCcsICdyaWdodCcsICdyaWdodC1lbmQnLCAnYm90dG9tLWVuZCcsICdib3R0b20nLCAnYm90dG9tLXN0YXJ0JywgJ2xlZnQtZW5kJywgJ2xlZnQnLCAnbGVmdC1zdGFydCddO1xuXG4vLyBHZXQgcmlkIG9mIGBhdXRvYCBgYXV0by1zdGFydGAgYW5kIGBhdXRvLWVuZGBcbnZhciB2YWxpZFBsYWNlbWVudHMgPSBwbGFjZW1lbnRzLnNsaWNlKDMpO1xuXG4vKipcbiAqIEdpdmVuIGFuIGluaXRpYWwgcGxhY2VtZW50LCByZXR1cm5zIGFsbCB0aGUgc3Vic2VxdWVudCBwbGFjZW1lbnRzXG4gKiBjbG9ja3dpc2UgKG9yIGNvdW50ZXItY2xvY2t3aXNlKS5cbiAqXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge1N0cmluZ30gcGxhY2VtZW50IC0gQSB2YWxpZCBwbGFjZW1lbnQgKGl0IGFjY2VwdHMgdmFyaWF0aW9ucylcbiAqIEBhcmd1bWVudCB7Qm9vbGVhbn0gY291bnRlciAtIFNldCB0byB0cnVlIHRvIHdhbGsgdGhlIHBsYWNlbWVudHMgY291bnRlcmNsb2Nrd2lzZVxuICogQHJldHVybnMge0FycmF5fSBwbGFjZW1lbnRzIGluY2x1ZGluZyB0aGVpciB2YXJpYXRpb25zXG4gKi9cbmZ1bmN0aW9uIGNsb2Nrd2lzZShwbGFjZW1lbnQpIHtcbiAgdmFyIGNvdW50ZXIgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuXG4gIHZhciBpbmRleCA9IHZhbGlkUGxhY2VtZW50cy5pbmRleE9mKHBsYWNlbWVudCk7XG4gIHZhciBhcnIgPSB2YWxpZFBsYWNlbWVudHMuc2xpY2UoaW5kZXggKyAxKS5jb25jYXQodmFsaWRQbGFjZW1lbnRzLnNsaWNlKDAsIGluZGV4KSk7XG4gIHJldHVybiBjb3VudGVyID8gYXJyLnJldmVyc2UoKSA6IGFycjtcbn1cblxudmFyIEJFSEFWSU9SUyA9IHtcbiAgRkxJUDogJ2ZsaXAnLFxuICBDTE9DS1dJU0U6ICdjbG9ja3dpc2UnLFxuICBDT1VOVEVSQ0xPQ0tXSVNFOiAnY291bnRlcmNsb2Nrd2lzZSdcbn07XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBmbGlwKGRhdGEsIG9wdGlvbnMpIHtcbiAgLy8gaWYgYGlubmVyYCBtb2RpZmllciBpcyBlbmFibGVkLCB3ZSBjYW4ndCB1c2UgdGhlIGBmbGlwYCBtb2RpZmllclxuICBpZiAoaXNNb2RpZmllckVuYWJsZWQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsICdpbm5lcicpKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICBpZiAoZGF0YS5mbGlwcGVkICYmIGRhdGEucGxhY2VtZW50ID09PSBkYXRhLm9yaWdpbmFsUGxhY2VtZW50KSB7XG4gICAgLy8gc2VlbXMgbGlrZSBmbGlwIGlzIHRyeWluZyB0byBsb29wLCBwcm9iYWJseSB0aGVyZSdzIG5vdCBlbm91Z2ggc3BhY2Ugb24gYW55IG9mIHRoZSBmbGlwcGFibGUgc2lkZXNcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIHZhciBib3VuZGFyaWVzID0gZ2V0Qm91bmRhcmllcyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5pbnN0YW5jZS5yZWZlcmVuY2UsIG9wdGlvbnMucGFkZGluZywgb3B0aW9ucy5ib3VuZGFyaWVzRWxlbWVudCwgZGF0YS5wb3NpdGlvbkZpeGVkKTtcblxuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgdmFyIHBsYWNlbWVudE9wcG9zaXRlID0gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocGxhY2VtZW50KTtcbiAgdmFyIHZhcmlhdGlvbiA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMV0gfHwgJyc7XG5cbiAgdmFyIGZsaXBPcmRlciA9IFtdO1xuXG4gIHN3aXRjaCAob3B0aW9ucy5iZWhhdmlvcikge1xuICAgIGNhc2UgQkVIQVZJT1JTLkZMSVA6XG4gICAgICBmbGlwT3JkZXIgPSBbcGxhY2VtZW50LCBwbGFjZW1lbnRPcHBvc2l0ZV07XG4gICAgICBicmVhaztcbiAgICBjYXNlIEJFSEFWSU9SUy5DTE9DS1dJU0U6XG4gICAgICBmbGlwT3JkZXIgPSBjbG9ja3dpc2UocGxhY2VtZW50KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQkVIQVZJT1JTLkNPVU5URVJDTE9DS1dJU0U6XG4gICAgICBmbGlwT3JkZXIgPSBjbG9ja3dpc2UocGxhY2VtZW50LCB0cnVlKTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBmbGlwT3JkZXIgPSBvcHRpb25zLmJlaGF2aW9yO1xuICB9XG5cbiAgZmxpcE9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHN0ZXAsIGluZGV4KSB7XG4gICAgaWYgKHBsYWNlbWVudCAhPT0gc3RlcCB8fCBmbGlwT3JkZXIubGVuZ3RoID09PSBpbmRleCArIDEpIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gICAgcGxhY2VtZW50T3Bwb3NpdGUgPSBnZXRPcHBvc2l0ZVBsYWNlbWVudChwbGFjZW1lbnQpO1xuXG4gICAgdmFyIHBvcHBlck9mZnNldHMgPSBkYXRhLm9mZnNldHMucG9wcGVyO1xuICAgIHZhciByZWZPZmZzZXRzID0gZGF0YS5vZmZzZXRzLnJlZmVyZW5jZTtcblxuICAgIC8vIHVzaW5nIGZsb29yIGJlY2F1c2UgdGhlIHJlZmVyZW5jZSBvZmZzZXRzIG1heSBjb250YWluIGRlY2ltYWxzIHdlIGFyZSBub3QgZ29pbmcgdG8gY29uc2lkZXIgaGVyZVxuICAgIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gICAgdmFyIG92ZXJsYXBzUmVmID0gcGxhY2VtZW50ID09PSAnbGVmdCcgJiYgZmxvb3IocG9wcGVyT2Zmc2V0cy5yaWdodCkgPiBmbG9vcihyZWZPZmZzZXRzLmxlZnQpIHx8IHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLmxlZnQpIDwgZmxvb3IocmVmT2Zmc2V0cy5yaWdodCkgfHwgcGxhY2VtZW50ID09PSAndG9wJyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLmJvdHRvbSkgPiBmbG9vcihyZWZPZmZzZXRzLnRvcCkgfHwgcGxhY2VtZW50ID09PSAnYm90dG9tJyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLnRvcCkgPCBmbG9vcihyZWZPZmZzZXRzLmJvdHRvbSk7XG5cbiAgICB2YXIgb3ZlcmZsb3dzTGVmdCA9IGZsb29yKHBvcHBlck9mZnNldHMubGVmdCkgPCBmbG9vcihib3VuZGFyaWVzLmxlZnQpO1xuICAgIHZhciBvdmVyZmxvd3NSaWdodCA9IGZsb29yKHBvcHBlck9mZnNldHMucmlnaHQpID4gZmxvb3IoYm91bmRhcmllcy5yaWdodCk7XG4gICAgdmFyIG92ZXJmbG93c1RvcCA9IGZsb29yKHBvcHBlck9mZnNldHMudG9wKSA8IGZsb29yKGJvdW5kYXJpZXMudG9wKTtcbiAgICB2YXIgb3ZlcmZsb3dzQm90dG9tID0gZmxvb3IocG9wcGVyT2Zmc2V0cy5ib3R0b20pID4gZmxvb3IoYm91bmRhcmllcy5ib3R0b20pO1xuXG4gICAgdmFyIG92ZXJmbG93c0JvdW5kYXJpZXMgPSBwbGFjZW1lbnQgPT09ICdsZWZ0JyAmJiBvdmVyZmxvd3NMZWZ0IHx8IHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyAmJiBvdmVyZmxvd3NSaWdodCB8fCBwbGFjZW1lbnQgPT09ICd0b3AnICYmIG92ZXJmbG93c1RvcCB8fCBwbGFjZW1lbnQgPT09ICdib3R0b20nICYmIG92ZXJmbG93c0JvdHRvbTtcblxuICAgIC8vIGZsaXAgdGhlIHZhcmlhdGlvbiBpZiByZXF1aXJlZFxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcbiAgICB2YXIgZmxpcHBlZFZhcmlhdGlvbiA9ICEhb3B0aW9ucy5mbGlwVmFyaWF0aW9ucyAmJiAoaXNWZXJ0aWNhbCAmJiB2YXJpYXRpb24gPT09ICdzdGFydCcgJiYgb3ZlcmZsb3dzTGVmdCB8fCBpc1ZlcnRpY2FsICYmIHZhcmlhdGlvbiA9PT0gJ2VuZCcgJiYgb3ZlcmZsb3dzUmlnaHQgfHwgIWlzVmVydGljYWwgJiYgdmFyaWF0aW9uID09PSAnc3RhcnQnICYmIG92ZXJmbG93c1RvcCB8fCAhaXNWZXJ0aWNhbCAmJiB2YXJpYXRpb24gPT09ICdlbmQnICYmIG92ZXJmbG93c0JvdHRvbSk7XG5cbiAgICBpZiAob3ZlcmxhcHNSZWYgfHwgb3ZlcmZsb3dzQm91bmRhcmllcyB8fCBmbGlwcGVkVmFyaWF0aW9uKSB7XG4gICAgICAvLyB0aGlzIGJvb2xlYW4gdG8gZGV0ZWN0IGFueSBmbGlwIGxvb3BcbiAgICAgIGRhdGEuZmxpcHBlZCA9IHRydWU7XG5cbiAgICAgIGlmIChvdmVybGFwc1JlZiB8fCBvdmVyZmxvd3NCb3VuZGFyaWVzKSB7XG4gICAgICAgIHBsYWNlbWVudCA9IGZsaXBPcmRlcltpbmRleCArIDFdO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmxpcHBlZFZhcmlhdGlvbikge1xuICAgICAgICB2YXJpYXRpb24gPSBnZXRPcHBvc2l0ZVZhcmlhdGlvbih2YXJpYXRpb24pO1xuICAgICAgfVxuXG4gICAgICBkYXRhLnBsYWNlbWVudCA9IHBsYWNlbWVudCArICh2YXJpYXRpb24gPyAnLScgKyB2YXJpYXRpb24gOiAnJyk7XG5cbiAgICAgIC8vIHRoaXMgb2JqZWN0IGNvbnRhaW5zIGBwb3NpdGlvbmAsIHdlIHdhbnQgdG8gcHJlc2VydmUgaXQgYWxvbmcgd2l0aFxuICAgICAgLy8gYW55IGFkZGl0aW9uYWwgcHJvcGVydHkgd2UgbWF5IGFkZCBpbiB0aGUgZnV0dXJlXG4gICAgICBkYXRhLm9mZnNldHMucG9wcGVyID0gX2V4dGVuZHMoe30sIGRhdGEub2Zmc2V0cy5wb3BwZXIsIGdldFBvcHBlck9mZnNldHMoZGF0YS5pbnN0YW5jZS5wb3BwZXIsIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UsIGRhdGEucGxhY2VtZW50KSk7XG5cbiAgICAgIGRhdGEgPSBydW5Nb2RpZmllcnMoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsIGRhdGEsICdmbGlwJyk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBrZWVwVG9nZXRoZXIoZGF0YSkge1xuICB2YXIgX2RhdGEkb2Zmc2V0cyA9IGRhdGEub2Zmc2V0cyxcbiAgICAgIHBvcHBlciA9IF9kYXRhJG9mZnNldHMucG9wcGVyLFxuICAgICAgcmVmZXJlbmNlID0gX2RhdGEkb2Zmc2V0cy5yZWZlcmVuY2U7XG5cbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gIHZhciBpc1ZlcnRpY2FsID0gWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcbiAgdmFyIHNpZGUgPSBpc1ZlcnRpY2FsID8gJ3JpZ2h0JyA6ICdib3R0b20nO1xuICB2YXIgb3BTaWRlID0gaXNWZXJ0aWNhbCA/ICdsZWZ0JyA6ICd0b3AnO1xuICB2YXIgbWVhc3VyZW1lbnQgPSBpc1ZlcnRpY2FsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuXG4gIGlmIChwb3BwZXJbc2lkZV0gPCBmbG9vcihyZWZlcmVuY2Vbb3BTaWRlXSkpIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW29wU2lkZV0gPSBmbG9vcihyZWZlcmVuY2Vbb3BTaWRlXSkgLSBwb3BwZXJbbWVhc3VyZW1lbnRdO1xuICB9XG4gIGlmIChwb3BwZXJbb3BTaWRlXSA+IGZsb29yKHJlZmVyZW5jZVtzaWRlXSkpIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW29wU2lkZV0gPSBmbG9vcihyZWZlcmVuY2Vbc2lkZV0pO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgY29udGFpbmluZyB2YWx1ZSArIHVuaXQgaW50byBhIHB4IHZhbHVlIG51bWJlclxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2Yge21vZGlmaWVyc35vZmZzZXR9XG4gKiBAcHJpdmF0ZVxuICogQGFyZ3VtZW50IHtTdHJpbmd9IHN0ciAtIFZhbHVlICsgdW5pdCBzdHJpbmdcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBtZWFzdXJlbWVudCAtIGBoZWlnaHRgIG9yIGB3aWR0aGBcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBwb3BwZXJPZmZzZXRzXG4gKiBAYXJndW1lbnQge09iamVjdH0gcmVmZXJlbmNlT2Zmc2V0c1xuICogQHJldHVybnMge051bWJlcnxTdHJpbmd9XG4gKiBWYWx1ZSBpbiBwaXhlbHMsIG9yIG9yaWdpbmFsIHN0cmluZyBpZiBubyB2YWx1ZXMgd2VyZSBleHRyYWN0ZWRcbiAqL1xuZnVuY3Rpb24gdG9WYWx1ZShzdHIsIG1lYXN1cmVtZW50LCBwb3BwZXJPZmZzZXRzLCByZWZlcmVuY2VPZmZzZXRzKSB7XG4gIC8vIHNlcGFyYXRlIHZhbHVlIGZyb20gdW5pdFxuICB2YXIgc3BsaXQgPSBzdHIubWF0Y2goLygoPzpcXC18XFwrKT9cXGQqXFwuP1xcZCopKC4qKS8pO1xuICB2YXIgdmFsdWUgPSArc3BsaXRbMV07XG4gIHZhciB1bml0ID0gc3BsaXRbMl07XG5cbiAgLy8gSWYgaXQncyBub3QgYSBudW1iZXIgaXQncyBhbiBvcGVyYXRvciwgSSBndWVzc1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxuXG4gIGlmICh1bml0LmluZGV4T2YoJyUnKSA9PT0gMCkge1xuICAgIHZhciBlbGVtZW50ID0gdm9pZCAwO1xuICAgIHN3aXRjaCAodW5pdCkge1xuICAgICAgY2FzZSAnJXAnOlxuICAgICAgICBlbGVtZW50ID0gcG9wcGVyT2Zmc2V0cztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICclJzpcbiAgICAgIGNhc2UgJyVyJzpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGVsZW1lbnQgPSByZWZlcmVuY2VPZmZzZXRzO1xuICAgIH1cblxuICAgIHZhciByZWN0ID0gZ2V0Q2xpZW50UmVjdChlbGVtZW50KTtcbiAgICByZXR1cm4gcmVjdFttZWFzdXJlbWVudF0gLyAxMDAgKiB2YWx1ZTtcbiAgfSBlbHNlIGlmICh1bml0ID09PSAndmgnIHx8IHVuaXQgPT09ICd2dycpIHtcbiAgICAvLyBpZiBpcyBhIHZoIG9yIHZ3LCB3ZSBjYWxjdWxhdGUgdGhlIHNpemUgYmFzZWQgb24gdGhlIHZpZXdwb3J0XG4gICAgdmFyIHNpemUgPSB2b2lkIDA7XG4gICAgaWYgKHVuaXQgPT09ICd2aCcpIHtcbiAgICAgIHNpemUgPSBNYXRoLm1heChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0LCB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNpemUgPSBNYXRoLm1heChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIHx8IDApO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZSAvIDEwMCAqIHZhbHVlO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIGlzIGFuIGV4cGxpY2l0IHBpeGVsIHVuaXQsIHdlIGdldCByaWQgb2YgdGhlIHVuaXQgYW5kIGtlZXAgdGhlIHZhbHVlXG4gICAgLy8gaWYgaXMgYW4gaW1wbGljaXQgdW5pdCwgaXQncyBweCwgYW5kIHdlIHJldHVybiBqdXN0IHRoZSB2YWx1ZVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlIGFuIGBvZmZzZXRgIHN0cmluZyB0byBleHRyYXBvbGF0ZSBgeGAgYW5kIGB5YCBudW1lcmljIG9mZnNldHMuXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiB7bW9kaWZpZXJzfm9mZnNldH1cbiAqIEBwcml2YXRlXG4gKiBAYXJndW1lbnQge1N0cmluZ30gb2Zmc2V0XG4gKiBAYXJndW1lbnQge09iamVjdH0gcG9wcGVyT2Zmc2V0c1xuICogQGFyZ3VtZW50IHtPYmplY3R9IHJlZmVyZW5jZU9mZnNldHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBiYXNlUGxhY2VtZW50XG4gKiBAcmV0dXJucyB7QXJyYXl9IGEgdHdvIGNlbGxzIGFycmF5IHdpdGggeCBhbmQgeSBvZmZzZXRzIGluIG51bWJlcnNcbiAqL1xuZnVuY3Rpb24gcGFyc2VPZmZzZXQob2Zmc2V0LCBwb3BwZXJPZmZzZXRzLCByZWZlcmVuY2VPZmZzZXRzLCBiYXNlUGxhY2VtZW50KSB7XG4gIHZhciBvZmZzZXRzID0gWzAsIDBdO1xuXG4gIC8vIFVzZSBoZWlnaHQgaWYgcGxhY2VtZW50IGlzIGxlZnQgb3IgcmlnaHQgYW5kIGluZGV4IGlzIDAgb3RoZXJ3aXNlIHVzZSB3aWR0aFxuICAvLyBpbiB0aGlzIHdheSB0aGUgZmlyc3Qgb2Zmc2V0IHdpbGwgdXNlIGFuIGF4aXMgYW5kIHRoZSBzZWNvbmQgb25lXG4gIC8vIHdpbGwgdXNlIHRoZSBvdGhlciBvbmVcbiAgdmFyIHVzZUhlaWdodCA9IFsncmlnaHQnLCAnbGVmdCddLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgIT09IC0xO1xuXG4gIC8vIFNwbGl0IHRoZSBvZmZzZXQgc3RyaW5nIHRvIG9idGFpbiBhIGxpc3Qgb2YgdmFsdWVzIGFuZCBvcGVyYW5kc1xuICAvLyBUaGUgcmVnZXggYWRkcmVzc2VzIHZhbHVlcyB3aXRoIHRoZSBwbHVzIG9yIG1pbnVzIHNpZ24gaW4gZnJvbnQgKCsxMCwgLTIwLCBldGMpXG4gIHZhciBmcmFnbWVudHMgPSBvZmZzZXQuc3BsaXQoLyhcXCt8XFwtKS8pLm1hcChmdW5jdGlvbiAoZnJhZykge1xuICAgIHJldHVybiBmcmFnLnRyaW0oKTtcbiAgfSk7XG5cbiAgLy8gRGV0ZWN0IGlmIHRoZSBvZmZzZXQgc3RyaW5nIGNvbnRhaW5zIGEgcGFpciBvZiB2YWx1ZXMgb3IgYSBzaW5nbGUgb25lXG4gIC8vIHRoZXkgY291bGQgYmUgc2VwYXJhdGVkIGJ5IGNvbW1hIG9yIHNwYWNlXG4gIHZhciBkaXZpZGVyID0gZnJhZ21lbnRzLmluZGV4T2YoZmluZChmcmFnbWVudHMsIGZ1bmN0aW9uIChmcmFnKSB7XG4gICAgcmV0dXJuIGZyYWcuc2VhcmNoKC8sfFxccy8pICE9PSAtMTtcbiAgfSkpO1xuXG4gIGlmIChmcmFnbWVudHNbZGl2aWRlcl0gJiYgZnJhZ21lbnRzW2RpdmlkZXJdLmluZGV4T2YoJywnKSA9PT0gLTEpIHtcbiAgICBjb25zb2xlLndhcm4oJ09mZnNldHMgc2VwYXJhdGVkIGJ5IHdoaXRlIHNwYWNlKHMpIGFyZSBkZXByZWNhdGVkLCB1c2UgYSBjb21tYSAoLCkgaW5zdGVhZC4nKTtcbiAgfVxuXG4gIC8vIElmIGRpdmlkZXIgaXMgZm91bmQsIHdlIGRpdmlkZSB0aGUgbGlzdCBvZiB2YWx1ZXMgYW5kIG9wZXJhbmRzIHRvIGRpdmlkZVxuICAvLyB0aGVtIGJ5IG9mc2V0IFggYW5kIFkuXG4gIHZhciBzcGxpdFJlZ2V4ID0gL1xccyosXFxzKnxcXHMrLztcbiAgdmFyIG9wcyA9IGRpdmlkZXIgIT09IC0xID8gW2ZyYWdtZW50cy5zbGljZSgwLCBkaXZpZGVyKS5jb25jYXQoW2ZyYWdtZW50c1tkaXZpZGVyXS5zcGxpdChzcGxpdFJlZ2V4KVswXV0pLCBbZnJhZ21lbnRzW2RpdmlkZXJdLnNwbGl0KHNwbGl0UmVnZXgpWzFdXS5jb25jYXQoZnJhZ21lbnRzLnNsaWNlKGRpdmlkZXIgKyAxKSldIDogW2ZyYWdtZW50c107XG5cbiAgLy8gQ29udmVydCB0aGUgdmFsdWVzIHdpdGggdW5pdHMgdG8gYWJzb2x1dGUgcGl4ZWxzIHRvIGFsbG93IG91ciBjb21wdXRhdGlvbnNcbiAgb3BzID0gb3BzLm1hcChmdW5jdGlvbiAob3AsIGluZGV4KSB7XG4gICAgLy8gTW9zdCBvZiB0aGUgdW5pdHMgcmVseSBvbiB0aGUgb3JpZW50YXRpb24gb2YgdGhlIHBvcHBlclxuICAgIHZhciBtZWFzdXJlbWVudCA9IChpbmRleCA9PT0gMSA/ICF1c2VIZWlnaHQgOiB1c2VIZWlnaHQpID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICAgIHZhciBtZXJnZVdpdGhQcmV2aW91cyA9IGZhbHNlO1xuICAgIHJldHVybiBvcFxuICAgIC8vIFRoaXMgYWdncmVnYXRlcyBhbnkgYCtgIG9yIGAtYCBzaWduIHRoYXQgYXJlbid0IGNvbnNpZGVyZWQgb3BlcmF0b3JzXG4gICAgLy8gZS5nLjogMTAgKyArNSA9PiBbMTAsICssICs1XVxuICAgIC5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIGlmIChhW2EubGVuZ3RoIC0gMV0gPT09ICcnICYmIFsnKycsICctJ10uaW5kZXhPZihiKSAhPT0gLTEpIHtcbiAgICAgICAgYVthLmxlbmd0aCAtIDFdID0gYjtcbiAgICAgICAgbWVyZ2VXaXRoUHJldmlvdXMgPSB0cnVlO1xuICAgICAgICByZXR1cm4gYTtcbiAgICAgIH0gZWxzZSBpZiAobWVyZ2VXaXRoUHJldmlvdXMpIHtcbiAgICAgICAgYVthLmxlbmd0aCAtIDFdICs9IGI7XG4gICAgICAgIG1lcmdlV2l0aFByZXZpb3VzID0gZmFsc2U7XG4gICAgICAgIHJldHVybiBhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGEuY29uY2F0KGIpO1xuICAgICAgfVxuICAgIH0sIFtdKVxuICAgIC8vIEhlcmUgd2UgY29udmVydCB0aGUgc3RyaW5nIHZhbHVlcyBpbnRvIG51bWJlciB2YWx1ZXMgKGluIHB4KVxuICAgIC5tYXAoZnVuY3Rpb24gKHN0cikge1xuICAgICAgcmV0dXJuIHRvVmFsdWUoc3RyLCBtZWFzdXJlbWVudCwgcG9wcGVyT2Zmc2V0cywgcmVmZXJlbmNlT2Zmc2V0cyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIExvb3AgdHJvdWdoIHRoZSBvZmZzZXRzIGFycmF5cyBhbmQgZXhlY3V0ZSB0aGUgb3BlcmF0aW9uc1xuICBvcHMuZm9yRWFjaChmdW5jdGlvbiAob3AsIGluZGV4KSB7XG4gICAgb3AuZm9yRWFjaChmdW5jdGlvbiAoZnJhZywgaW5kZXgyKSB7XG4gICAgICBpZiAoaXNOdW1lcmljKGZyYWcpKSB7XG4gICAgICAgIG9mZnNldHNbaW5kZXhdICs9IGZyYWcgKiAob3BbaW5kZXgyIC0gMV0gPT09ICctJyA/IC0xIDogMSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2Zmc2V0cztcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAYXJndW1lbnQge051bWJlcnxTdHJpbmd9IG9wdGlvbnMub2Zmc2V0PTBcbiAqIFRoZSBvZmZzZXQgdmFsdWUgYXMgZGVzY3JpYmVkIGluIHRoZSBtb2RpZmllciBkZXNjcmlwdGlvblxuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBvZmZzZXQoZGF0YSwgX3JlZikge1xuICB2YXIgb2Zmc2V0ID0gX3JlZi5vZmZzZXQ7XG4gIHZhciBwbGFjZW1lbnQgPSBkYXRhLnBsYWNlbWVudCxcbiAgICAgIF9kYXRhJG9mZnNldHMgPSBkYXRhLm9mZnNldHMsXG4gICAgICBwb3BwZXIgPSBfZGF0YSRvZmZzZXRzLnBvcHBlcixcbiAgICAgIHJlZmVyZW5jZSA9IF9kYXRhJG9mZnNldHMucmVmZXJlbmNlO1xuXG4gIHZhciBiYXNlUGxhY2VtZW50ID0gcGxhY2VtZW50LnNwbGl0KCctJylbMF07XG5cbiAgdmFyIG9mZnNldHMgPSB2b2lkIDA7XG4gIGlmIChpc051bWVyaWMoK29mZnNldCkpIHtcbiAgICBvZmZzZXRzID0gWytvZmZzZXQsIDBdO1xuICB9IGVsc2Uge1xuICAgIG9mZnNldHMgPSBwYXJzZU9mZnNldChvZmZzZXQsIHBvcHBlciwgcmVmZXJlbmNlLCBiYXNlUGxhY2VtZW50KTtcbiAgfVxuXG4gIGlmIChiYXNlUGxhY2VtZW50ID09PSAnbGVmdCcpIHtcbiAgICBwb3BwZXIudG9wICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLmxlZnQgLT0gb2Zmc2V0c1sxXTtcbiAgfSBlbHNlIGlmIChiYXNlUGxhY2VtZW50ID09PSAncmlnaHQnKSB7XG4gICAgcG9wcGVyLnRvcCArPSBvZmZzZXRzWzBdO1xuICAgIHBvcHBlci5sZWZ0ICs9IG9mZnNldHNbMV07XG4gIH0gZWxzZSBpZiAoYmFzZVBsYWNlbWVudCA9PT0gJ3RvcCcpIHtcbiAgICBwb3BwZXIubGVmdCArPSBvZmZzZXRzWzBdO1xuICAgIHBvcHBlci50b3AgLT0gb2Zmc2V0c1sxXTtcbiAgfSBlbHNlIGlmIChiYXNlUGxhY2VtZW50ID09PSAnYm90dG9tJykge1xuICAgIHBvcHBlci5sZWZ0ICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLnRvcCArPSBvZmZzZXRzWzFdO1xuICB9XG5cbiAgZGF0YS5wb3BwZXIgPSBwb3BwZXI7XG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBwcmV2ZW50T3ZlcmZsb3coZGF0YSwgb3B0aW9ucykge1xuICB2YXIgYm91bmRhcmllc0VsZW1lbnQgPSBvcHRpb25zLmJvdW5kYXJpZXNFbGVtZW50IHx8IGdldE9mZnNldFBhcmVudChkYXRhLmluc3RhbmNlLnBvcHBlcik7XG5cbiAgLy8gSWYgb2Zmc2V0UGFyZW50IGlzIHRoZSByZWZlcmVuY2UgZWxlbWVudCwgd2UgcmVhbGx5IHdhbnQgdG9cbiAgLy8gZ28gb25lIHN0ZXAgdXAgYW5kIHVzZSB0aGUgbmV4dCBvZmZzZXRQYXJlbnQgYXMgcmVmZXJlbmNlIHRvXG4gIC8vIGF2b2lkIHRvIG1ha2UgdGhpcyBtb2RpZmllciBjb21wbGV0ZWx5IHVzZWxlc3MgYW5kIGxvb2sgbGlrZSBicm9rZW5cbiAgaWYgKGRhdGEuaW5zdGFuY2UucmVmZXJlbmNlID09PSBib3VuZGFyaWVzRWxlbWVudCkge1xuICAgIGJvdW5kYXJpZXNFbGVtZW50ID0gZ2V0T2Zmc2V0UGFyZW50KGJvdW5kYXJpZXNFbGVtZW50KTtcbiAgfVxuXG4gIC8vIE5PVEU6IERPTSBhY2Nlc3MgaGVyZVxuICAvLyByZXNldHMgdGhlIHBvcHBlcidzIHBvc2l0aW9uIHNvIHRoYXQgdGhlIGRvY3VtZW50IHNpemUgY2FuIGJlIGNhbGN1bGF0ZWQgZXhjbHVkaW5nXG4gIC8vIHRoZSBzaXplIG9mIHRoZSBwb3BwZXIgZWxlbWVudCBpdHNlbGZcbiAgdmFyIHRyYW5zZm9ybVByb3AgPSBnZXRTdXBwb3J0ZWRQcm9wZXJ0eU5hbWUoJ3RyYW5zZm9ybScpO1xuICB2YXIgcG9wcGVyU3R5bGVzID0gZGF0YS5pbnN0YW5jZS5wb3BwZXIuc3R5bGU7IC8vIGFzc2lnbm1lbnQgdG8gaGVscCBtaW5pZmljYXRpb25cbiAgdmFyIHRvcCA9IHBvcHBlclN0eWxlcy50b3AsXG4gICAgICBsZWZ0ID0gcG9wcGVyU3R5bGVzLmxlZnQsXG4gICAgICB0cmFuc2Zvcm0gPSBwb3BwZXJTdHlsZXNbdHJhbnNmb3JtUHJvcF07XG5cbiAgcG9wcGVyU3R5bGVzLnRvcCA9ICcnO1xuICBwb3BwZXJTdHlsZXMubGVmdCA9ICcnO1xuICBwb3BwZXJTdHlsZXNbdHJhbnNmb3JtUHJvcF0gPSAnJztcblxuICB2YXIgYm91bmRhcmllcyA9IGdldEJvdW5kYXJpZXMoZGF0YS5pbnN0YW5jZS5wb3BwZXIsIGRhdGEuaW5zdGFuY2UucmVmZXJlbmNlLCBvcHRpb25zLnBhZGRpbmcsIGJvdW5kYXJpZXNFbGVtZW50LCBkYXRhLnBvc2l0aW9uRml4ZWQpO1xuXG4gIC8vIE5PVEU6IERPTSBhY2Nlc3MgaGVyZVxuICAvLyByZXN0b3JlcyB0aGUgb3JpZ2luYWwgc3R5bGUgcHJvcGVydGllcyBhZnRlciB0aGUgb2Zmc2V0cyBoYXZlIGJlZW4gY29tcHV0ZWRcbiAgcG9wcGVyU3R5bGVzLnRvcCA9IHRvcDtcbiAgcG9wcGVyU3R5bGVzLmxlZnQgPSBsZWZ0O1xuICBwb3BwZXJTdHlsZXNbdHJhbnNmb3JtUHJvcF0gPSB0cmFuc2Zvcm07XG5cbiAgb3B0aW9ucy5ib3VuZGFyaWVzID0gYm91bmRhcmllcztcblxuICB2YXIgb3JkZXIgPSBvcHRpb25zLnByaW9yaXR5O1xuICB2YXIgcG9wcGVyID0gZGF0YS5vZmZzZXRzLnBvcHBlcjtcblxuICB2YXIgY2hlY2sgPSB7XG4gICAgcHJpbWFyeTogZnVuY3Rpb24gcHJpbWFyeShwbGFjZW1lbnQpIHtcbiAgICAgIHZhciB2YWx1ZSA9IHBvcHBlcltwbGFjZW1lbnRdO1xuICAgICAgaWYgKHBvcHBlcltwbGFjZW1lbnRdIDwgYm91bmRhcmllc1twbGFjZW1lbnRdICYmICFvcHRpb25zLmVzY2FwZVdpdGhSZWZlcmVuY2UpIHtcbiAgICAgICAgdmFsdWUgPSBNYXRoLm1heChwb3BwZXJbcGxhY2VtZW50XSwgYm91bmRhcmllc1twbGFjZW1lbnRdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkZWZpbmVQcm9wZXJ0eSh7fSwgcGxhY2VtZW50LCB2YWx1ZSk7XG4gICAgfSxcbiAgICBzZWNvbmRhcnk6IGZ1bmN0aW9uIHNlY29uZGFyeShwbGFjZW1lbnQpIHtcbiAgICAgIHZhciBtYWluU2lkZSA9IHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyA/ICdsZWZ0JyA6ICd0b3AnO1xuICAgICAgdmFyIHZhbHVlID0gcG9wcGVyW21haW5TaWRlXTtcbiAgICAgIGlmIChwb3BwZXJbcGxhY2VtZW50XSA+IGJvdW5kYXJpZXNbcGxhY2VtZW50XSAmJiAhb3B0aW9ucy5lc2NhcGVXaXRoUmVmZXJlbmNlKSB7XG4gICAgICAgIHZhbHVlID0gTWF0aC5taW4ocG9wcGVyW21haW5TaWRlXSwgYm91bmRhcmllc1twbGFjZW1lbnRdIC0gKHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyA/IHBvcHBlci53aWR0aCA6IHBvcHBlci5oZWlnaHQpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkZWZpbmVQcm9wZXJ0eSh7fSwgbWFpblNpZGUsIHZhbHVlKTtcbiAgICB9XG4gIH07XG5cbiAgb3JkZXIuZm9yRWFjaChmdW5jdGlvbiAocGxhY2VtZW50KSB7XG4gICAgdmFyIHNpZGUgPSBbJ2xlZnQnLCAndG9wJ10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMSA/ICdwcmltYXJ5JyA6ICdzZWNvbmRhcnknO1xuICAgIHBvcHBlciA9IF9leHRlbmRzKHt9LCBwb3BwZXIsIGNoZWNrW3NpZGVdKHBsYWNlbWVudCkpO1xuICB9KTtcblxuICBkYXRhLm9mZnNldHMucG9wcGVyID0gcG9wcGVyO1xuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBzaGlmdChkYXRhKSB7XG4gIHZhciBwbGFjZW1lbnQgPSBkYXRhLnBsYWNlbWVudDtcbiAgdmFyIGJhc2VQbGFjZW1lbnQgPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgdmFyIHNoaWZ0dmFyaWF0aW9uID0gcGxhY2VtZW50LnNwbGl0KCctJylbMV07XG5cbiAgLy8gaWYgc2hpZnQgc2hpZnR2YXJpYXRpb24gaXMgc3BlY2lmaWVkLCBydW4gdGhlIG1vZGlmaWVyXG4gIGlmIChzaGlmdHZhcmlhdGlvbikge1xuICAgIHZhciBfZGF0YSRvZmZzZXRzID0gZGF0YS5vZmZzZXRzLFxuICAgICAgICByZWZlcmVuY2UgPSBfZGF0YSRvZmZzZXRzLnJlZmVyZW5jZSxcbiAgICAgICAgcG9wcGVyID0gX2RhdGEkb2Zmc2V0cy5wb3BwZXI7XG5cbiAgICB2YXIgaXNWZXJ0aWNhbCA9IFsnYm90dG9tJywgJ3RvcCddLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgIT09IC0xO1xuICAgIHZhciBzaWRlID0gaXNWZXJ0aWNhbCA/ICdsZWZ0JyA6ICd0b3AnO1xuICAgIHZhciBtZWFzdXJlbWVudCA9IGlzVmVydGljYWwgPyAnd2lkdGgnIDogJ2hlaWdodCc7XG5cbiAgICB2YXIgc2hpZnRPZmZzZXRzID0ge1xuICAgICAgc3RhcnQ6IGRlZmluZVByb3BlcnR5KHt9LCBzaWRlLCByZWZlcmVuY2Vbc2lkZV0pLFxuICAgICAgZW5kOiBkZWZpbmVQcm9wZXJ0eSh7fSwgc2lkZSwgcmVmZXJlbmNlW3NpZGVdICsgcmVmZXJlbmNlW21lYXN1cmVtZW50XSAtIHBvcHBlclttZWFzdXJlbWVudF0pXG4gICAgfTtcblxuICAgIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBfZXh0ZW5kcyh7fSwgcG9wcGVyLCBzaGlmdE9mZnNldHNbc2hpZnR2YXJpYXRpb25dKTtcbiAgfVxuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IHVwZGF0ZSBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gaGlkZShkYXRhKSB7XG4gIGlmICghaXNNb2RpZmllclJlcXVpcmVkKGRhdGEuaW5zdGFuY2UubW9kaWZpZXJzLCAnaGlkZScsICdwcmV2ZW50T3ZlcmZsb3cnKSkge1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgdmFyIHJlZlJlY3QgPSBkYXRhLm9mZnNldHMucmVmZXJlbmNlO1xuICB2YXIgYm91bmQgPSBmaW5kKGRhdGEuaW5zdGFuY2UubW9kaWZpZXJzLCBmdW5jdGlvbiAobW9kaWZpZXIpIHtcbiAgICByZXR1cm4gbW9kaWZpZXIubmFtZSA9PT0gJ3ByZXZlbnRPdmVyZmxvdyc7XG4gIH0pLmJvdW5kYXJpZXM7XG5cbiAgaWYgKHJlZlJlY3QuYm90dG9tIDwgYm91bmQudG9wIHx8IHJlZlJlY3QubGVmdCA+IGJvdW5kLnJpZ2h0IHx8IHJlZlJlY3QudG9wID4gYm91bmQuYm90dG9tIHx8IHJlZlJlY3QucmlnaHQgPCBib3VuZC5sZWZ0KSB7XG4gICAgLy8gQXZvaWQgdW5uZWNlc3NhcnkgRE9NIGFjY2VzcyBpZiB2aXNpYmlsaXR5IGhhc24ndCBjaGFuZ2VkXG4gICAgaWYgKGRhdGEuaGlkZSA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgZGF0YS5oaWRlID0gdHJ1ZTtcbiAgICBkYXRhLmF0dHJpYnV0ZXNbJ3gtb3V0LW9mLWJvdW5kYXJpZXMnXSA9ICcnO1xuICB9IGVsc2Uge1xuICAgIC8vIEF2b2lkIHVubmVjZXNzYXJ5IERPTSBhY2Nlc3MgaWYgdmlzaWJpbGl0eSBoYXNuJ3QgY2hhbmdlZFxuICAgIGlmIChkYXRhLmhpZGUgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICBkYXRhLmhpZGUgPSBmYWxzZTtcbiAgICBkYXRhLmF0dHJpYnV0ZXNbJ3gtb3V0LW9mLWJvdW5kYXJpZXMnXSA9IGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGlubmVyKGRhdGEpIHtcbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50O1xuICB2YXIgYmFzZVBsYWNlbWVudCA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB2YXIgX2RhdGEkb2Zmc2V0cyA9IGRhdGEub2Zmc2V0cyxcbiAgICAgIHBvcHBlciA9IF9kYXRhJG9mZnNldHMucG9wcGVyLFxuICAgICAgcmVmZXJlbmNlID0gX2RhdGEkb2Zmc2V0cy5yZWZlcmVuY2U7XG5cbiAgdmFyIGlzSG9yaXogPSBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGJhc2VQbGFjZW1lbnQpICE9PSAtMTtcblxuICB2YXIgc3VidHJhY3RMZW5ndGggPSBbJ3RvcCcsICdsZWZ0J10uaW5kZXhPZihiYXNlUGxhY2VtZW50KSA9PT0gLTE7XG5cbiAgcG9wcGVyW2lzSG9yaXogPyAnbGVmdCcgOiAndG9wJ10gPSByZWZlcmVuY2VbYmFzZVBsYWNlbWVudF0gLSAoc3VidHJhY3RMZW5ndGggPyBwb3BwZXJbaXNIb3JpeiA/ICd3aWR0aCcgOiAnaGVpZ2h0J10gOiAwKTtcblxuICBkYXRhLnBsYWNlbWVudCA9IGdldE9wcG9zaXRlUGxhY2VtZW50KHBsYWNlbWVudCk7XG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBnZXRDbGllbnRSZWN0KHBvcHBlcik7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogTW9kaWZpZXIgZnVuY3Rpb24sIGVhY2ggbW9kaWZpZXIgY2FuIGhhdmUgYSBmdW5jdGlvbiBvZiB0aGlzIHR5cGUgYXNzaWduZWRcbiAqIHRvIGl0cyBgZm5gIHByb3BlcnR5LjxiciAvPlxuICogVGhlc2UgZnVuY3Rpb25zIHdpbGwgYmUgY2FsbGVkIG9uIGVhY2ggdXBkYXRlLCB0aGlzIG1lYW5zIHRoYXQgeW91IG11c3RcbiAqIG1ha2Ugc3VyZSB0aGV5IGFyZSBwZXJmb3JtYW50IGVub3VnaCB0byBhdm9pZCBwZXJmb3JtYW5jZSBib3R0bGVuZWNrcy5cbiAqXG4gKiBAZnVuY3Rpb24gTW9kaWZpZXJGblxuICogQGFyZ3VtZW50IHtkYXRhT2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtkYXRhT2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cblxuLyoqXG4gKiBNb2RpZmllcnMgYXJlIHBsdWdpbnMgdXNlZCB0byBhbHRlciB0aGUgYmVoYXZpb3Igb2YgeW91ciBwb3BwZXJzLjxiciAvPlxuICogUG9wcGVyLmpzIHVzZXMgYSBzZXQgb2YgOSBtb2RpZmllcnMgdG8gcHJvdmlkZSBhbGwgdGhlIGJhc2ljIGZ1bmN0aW9uYWxpdGllc1xuICogbmVlZGVkIGJ5IHRoZSBsaWJyYXJ5LlxuICpcbiAqIFVzdWFsbHkgeW91IGRvbid0IHdhbnQgdG8gb3ZlcnJpZGUgdGhlIGBvcmRlcmAsIGBmbmAgYW5kIGBvbkxvYWRgIHByb3BzLlxuICogQWxsIHRoZSBvdGhlciBwcm9wZXJ0aWVzIGFyZSBjb25maWd1cmF0aW9ucyB0aGF0IGNvdWxkIGJlIHR3ZWFrZWQuXG4gKiBAbmFtZXNwYWNlIG1vZGlmaWVyc1xuICovXG52YXIgbW9kaWZpZXJzID0ge1xuICAvKipcbiAgICogTW9kaWZpZXIgdXNlZCB0byBzaGlmdCB0aGUgcG9wcGVyIG9uIHRoZSBzdGFydCBvciBlbmQgb2YgaXRzIHJlZmVyZW5jZVxuICAgKiBlbGVtZW50LjxiciAvPlxuICAgKiBJdCB3aWxsIHJlYWQgdGhlIHZhcmlhdGlvbiBvZiB0aGUgYHBsYWNlbWVudGAgcHJvcGVydHkuPGJyIC8+XG4gICAqIEl0IGNhbiBiZSBvbmUgZWl0aGVyIGAtZW5kYCBvciBgLXN0YXJ0YC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIHNoaWZ0OiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTEwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogMTAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogc2hpZnRcbiAgfSxcblxuICAvKipcbiAgICogVGhlIGBvZmZzZXRgIG1vZGlmaWVyIGNhbiBzaGlmdCB5b3VyIHBvcHBlciBvbiBib3RoIGl0cyBheGlzLlxuICAgKlxuICAgKiBJdCBhY2NlcHRzIHRoZSBmb2xsb3dpbmcgdW5pdHM6XG4gICAqIC0gYHB4YCBvciB1bml0LWxlc3MsIGludGVycHJldGVkIGFzIHBpeGVsc1xuICAgKiAtIGAlYCBvciBgJXJgLCBwZXJjZW50YWdlIHJlbGF0aXZlIHRvIHRoZSBsZW5ndGggb2YgdGhlIHJlZmVyZW5jZSBlbGVtZW50XG4gICAqIC0gYCVwYCwgcGVyY2VudGFnZSByZWxhdGl2ZSB0byB0aGUgbGVuZ3RoIG9mIHRoZSBwb3BwZXIgZWxlbWVudFxuICAgKiAtIGB2d2AsIENTUyB2aWV3cG9ydCB3aWR0aCB1bml0XG4gICAqIC0gYHZoYCwgQ1NTIHZpZXdwb3J0IGhlaWdodCB1bml0XG4gICAqXG4gICAqIEZvciBsZW5ndGggaXMgaW50ZW5kZWQgdGhlIG1haW4gYXhpcyByZWxhdGl2ZSB0byB0aGUgcGxhY2VtZW50IG9mIHRoZSBwb3BwZXIuPGJyIC8+XG4gICAqIFRoaXMgbWVhbnMgdGhhdCBpZiB0aGUgcGxhY2VtZW50IGlzIGB0b3BgIG9yIGBib3R0b21gLCB0aGUgbGVuZ3RoIHdpbGwgYmUgdGhlXG4gICAqIGB3aWR0aGAuIEluIGNhc2Ugb2YgYGxlZnRgIG9yIGByaWdodGAsIGl0IHdpbGwgYmUgdGhlIGBoZWlnaHRgLlxuICAgKlxuICAgKiBZb3UgY2FuIHByb3ZpZGUgYSBzaW5nbGUgdmFsdWUgKGFzIGBOdW1iZXJgIG9yIGBTdHJpbmdgKSwgb3IgYSBwYWlyIG9mIHZhbHVlc1xuICAgKiBhcyBgU3RyaW5nYCBkaXZpZGVkIGJ5IGEgY29tbWEgb3Igb25lIChvciBtb3JlKSB3aGl0ZSBzcGFjZXMuPGJyIC8+XG4gICAqIFRoZSBsYXR0ZXIgaXMgYSBkZXByZWNhdGVkIG1ldGhvZCBiZWNhdXNlIGl0IGxlYWRzIHRvIGNvbmZ1c2lvbiBhbmQgd2lsbCBiZVxuICAgKiByZW1vdmVkIGluIHYyLjxiciAvPlxuICAgKiBBZGRpdGlvbmFsbHksIGl0IGFjY2VwdHMgYWRkaXRpb25zIGFuZCBzdWJ0cmFjdGlvbnMgYmV0d2VlbiBkaWZmZXJlbnQgdW5pdHMuXG4gICAqIE5vdGUgdGhhdCBtdWx0aXBsaWNhdGlvbnMgYW5kIGRpdmlzaW9ucyBhcmVuJ3Qgc3VwcG9ydGVkLlxuICAgKlxuICAgKiBWYWxpZCBleGFtcGxlcyBhcmU6XG4gICAqIGBgYFxuICAgKiAxMFxuICAgKiAnMTAlJ1xuICAgKiAnMTAsIDEwJ1xuICAgKiAnMTAlLCAxMCdcbiAgICogJzEwICsgMTAlJ1xuICAgKiAnMTAgLSA1dmggKyAzJSdcbiAgICogJy0xMHB4ICsgNXZoLCA1cHggLSA2JSdcbiAgICogYGBgXG4gICAqID4gKipOQioqOiBJZiB5b3UgZGVzaXJlIHRvIGFwcGx5IG9mZnNldHMgdG8geW91ciBwb3BwZXJzIGluIGEgd2F5IHRoYXQgbWF5IG1ha2UgdGhlbSBvdmVybGFwXG4gICAqID4gd2l0aCB0aGVpciByZWZlcmVuY2UgZWxlbWVudCwgdW5mb3J0dW5hdGVseSwgeW91IHdpbGwgaGF2ZSB0byBkaXNhYmxlIHRoZSBgZmxpcGAgbW9kaWZpZXIuXG4gICAqID4gWW91IGNhbiByZWFkIG1vcmUgb24gdGhpcyBhdCB0aGlzIFtpc3N1ZV0oaHR0cHM6Ly9naXRodWIuY29tL0ZlelZyYXN0YS9wb3BwZXIuanMvaXNzdWVzLzM3MykuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBvZmZzZXQ6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9MjAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiAyMDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBvZmZzZXQsXG4gICAgLyoqIEBwcm9wIHtOdW1iZXJ8U3RyaW5nfSBvZmZzZXQ9MFxuICAgICAqIFRoZSBvZmZzZXQgdmFsdWUgYXMgZGVzY3JpYmVkIGluIHRoZSBtb2RpZmllciBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIG9mZnNldDogMFxuICB9LFxuXG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIHByZXZlbnQgdGhlIHBvcHBlciBmcm9tIGJlaW5nIHBvc2l0aW9uZWQgb3V0c2lkZSB0aGUgYm91bmRhcnkuXG4gICAqXG4gICAqIEEgc2NlbmFyaW8gZXhpc3RzIHdoZXJlIHRoZSByZWZlcmVuY2UgaXRzZWxmIGlzIG5vdCB3aXRoaW4gdGhlIGJvdW5kYXJpZXMuPGJyIC8+XG4gICAqIFdlIGNhbiBzYXkgaXQgaGFzIFwiZXNjYXBlZCB0aGUgYm91bmRhcmllc1wiIOKAlCBvciBqdXN0IFwiZXNjYXBlZFwiLjxiciAvPlxuICAgKiBJbiB0aGlzIGNhc2Ugd2UgbmVlZCB0byBkZWNpZGUgd2hldGhlciB0aGUgcG9wcGVyIHNob3VsZCBlaXRoZXI6XG4gICAqXG4gICAqIC0gZGV0YWNoIGZyb20gdGhlIHJlZmVyZW5jZSBhbmQgcmVtYWluIFwidHJhcHBlZFwiIGluIHRoZSBib3VuZGFyaWVzLCBvclxuICAgKiAtIGlmIGl0IHNob3VsZCBpZ25vcmUgdGhlIGJvdW5kYXJ5IGFuZCBcImVzY2FwZSB3aXRoIGl0cyByZWZlcmVuY2VcIlxuICAgKlxuICAgKiBXaGVuIGBlc2NhcGVXaXRoUmVmZXJlbmNlYCBpcyBzZXQgdG9gdHJ1ZWAgYW5kIHJlZmVyZW5jZSBpcyBjb21wbGV0ZWx5XG4gICAqIG91dHNpZGUgaXRzIGJvdW5kYXJpZXMsIHRoZSBwb3BwZXIgd2lsbCBvdmVyZmxvdyAob3IgY29tcGxldGVseSBsZWF2ZSlcbiAgICogdGhlIGJvdW5kYXJpZXMgaW4gb3JkZXIgdG8gcmVtYWluIGF0dGFjaGVkIHRvIHRoZSBlZGdlIG9mIHRoZSByZWZlcmVuY2UuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBwcmV2ZW50T3ZlcmZsb3c6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9MzAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiAzMDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBwcmV2ZW50T3ZlcmZsb3csXG4gICAgLyoqXG4gICAgICogQHByb3Age0FycmF5fSBbcHJpb3JpdHk9WydsZWZ0JywncmlnaHQnLCd0b3AnLCdib3R0b20nXV1cbiAgICAgKiBQb3BwZXIgd2lsbCB0cnkgdG8gcHJldmVudCBvdmVyZmxvdyBmb2xsb3dpbmcgdGhlc2UgcHJpb3JpdGllcyBieSBkZWZhdWx0LFxuICAgICAqIHRoZW4sIGl0IGNvdWxkIG92ZXJmbG93IG9uIHRoZSBsZWZ0IGFuZCBvbiB0b3Agb2YgdGhlIGBib3VuZGFyaWVzRWxlbWVudGBcbiAgICAgKi9cbiAgICBwcmlvcml0eTogWydsZWZ0JywgJ3JpZ2h0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7bnVtYmVyfSBwYWRkaW5nPTVcbiAgICAgKiBBbW91bnQgb2YgcGl4ZWwgdXNlZCB0byBkZWZpbmUgYSBtaW5pbXVtIGRpc3RhbmNlIGJldHdlZW4gdGhlIGJvdW5kYXJpZXNcbiAgICAgKiBhbmQgdGhlIHBvcHBlci4gVGhpcyBtYWtlcyBzdXJlIHRoZSBwb3BwZXIgYWx3YXlzIGhhcyBhIGxpdHRsZSBwYWRkaW5nXG4gICAgICogYmV0d2VlbiB0aGUgZWRnZXMgb2YgaXRzIGNvbnRhaW5lclxuICAgICAqL1xuICAgIHBhZGRpbmc6IDUsXG4gICAgLyoqXG4gICAgICogQHByb3Age1N0cmluZ3xIVE1MRWxlbWVudH0gYm91bmRhcmllc0VsZW1lbnQ9J3Njcm9sbFBhcmVudCdcbiAgICAgKiBCb3VuZGFyaWVzIHVzZWQgYnkgdGhlIG1vZGlmaWVyLiBDYW4gYmUgYHNjcm9sbFBhcmVudGAsIGB3aW5kb3dgLFxuICAgICAqIGB2aWV3cG9ydGAgb3IgYW55IERPTSBlbGVtZW50LlxuICAgICAqL1xuICAgIGJvdW5kYXJpZXNFbGVtZW50OiAnc2Nyb2xsUGFyZW50J1xuICB9LFxuXG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIG1ha2Ugc3VyZSB0aGUgcmVmZXJlbmNlIGFuZCBpdHMgcG9wcGVyIHN0YXkgbmVhciBlYWNoIG90aGVyXG4gICAqIHdpdGhvdXQgbGVhdmluZyBhbnkgZ2FwIGJldHdlZW4gdGhlIHR3by4gRXNwZWNpYWxseSB1c2VmdWwgd2hlbiB0aGUgYXJyb3cgaXNcbiAgICogZW5hYmxlZCBhbmQgeW91IHdhbnQgdG8gZW5zdXJlIHRoYXQgaXQgcG9pbnRzIHRvIGl0cyByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogSXQgY2FyZXMgb25seSBhYm91dCB0aGUgZmlyc3QgYXhpcy4gWW91IGNhbiBzdGlsbCBoYXZlIHBvcHBlcnMgd2l0aCBtYXJnaW5cbiAgICogYmV0d2VlbiB0aGUgcG9wcGVyIGFuZCBpdHMgcmVmZXJlbmNlIGVsZW1lbnQuXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBrZWVwVG9nZXRoZXI6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9NDAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA0MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBrZWVwVG9nZXRoZXJcbiAgfSxcblxuICAvKipcbiAgICogVGhpcyBtb2RpZmllciBpcyB1c2VkIHRvIG1vdmUgdGhlIGBhcnJvd0VsZW1lbnRgIG9mIHRoZSBwb3BwZXIgdG8gbWFrZVxuICAgKiBzdXJlIGl0IGlzIHBvc2l0aW9uZWQgYmV0d2VlbiB0aGUgcmVmZXJlbmNlIGVsZW1lbnQgYW5kIGl0cyBwb3BwZXIgZWxlbWVudC5cbiAgICogSXQgd2lsbCByZWFkIHRoZSBvdXRlciBzaXplIG9mIHRoZSBgYXJyb3dFbGVtZW50YCBub2RlIHRvIGRldGVjdCBob3cgbWFueVxuICAgKiBwaXhlbHMgb2YgY29uanVuY3Rpb24gYXJlIG5lZWRlZC5cbiAgICpcbiAgICogSXQgaGFzIG5vIGVmZmVjdCBpZiBubyBgYXJyb3dFbGVtZW50YCBpcyBwcm92aWRlZC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGFycm93OiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTUwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogNTAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogYXJyb3csXG4gICAgLyoqIEBwcm9wIHtTdHJpbmd8SFRNTEVsZW1lbnR9IGVsZW1lbnQ9J1t4LWFycm93XScgLSBTZWxlY3RvciBvciBub2RlIHVzZWQgYXMgYXJyb3cgKi9cbiAgICBlbGVtZW50OiAnW3gtYXJyb3ddJ1xuICB9LFxuXG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIGZsaXAgdGhlIHBvcHBlcidzIHBsYWNlbWVudCB3aGVuIGl0IHN0YXJ0cyB0byBvdmVybGFwIGl0c1xuICAgKiByZWZlcmVuY2UgZWxlbWVudC5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBwcmV2ZW50T3ZlcmZsb3dgIG1vZGlmaWVyIGJlZm9yZSBpdCBpbiBvcmRlciB0byB3b3JrLlxuICAgKlxuICAgKiAqKk5PVEU6KiogdGhpcyBtb2RpZmllciB3aWxsIGludGVycnVwdCB0aGUgY3VycmVudCB1cGRhdGUgY3ljbGUgYW5kIHdpbGxcbiAgICogcmVzdGFydCBpdCBpZiBpdCBkZXRlY3RzIHRoZSBuZWVkIHRvIGZsaXAgdGhlIHBsYWNlbWVudC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGZsaXA6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9NjAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA2MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBmbGlwLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtTdHJpbmd8QXJyYXl9IGJlaGF2aW9yPSdmbGlwJ1xuICAgICAqIFRoZSBiZWhhdmlvciB1c2VkIHRvIGNoYW5nZSB0aGUgcG9wcGVyJ3MgcGxhY2VtZW50LiBJdCBjYW4gYmUgb25lIG9mXG4gICAgICogYGZsaXBgLCBgY2xvY2t3aXNlYCwgYGNvdW50ZXJjbG9ja3dpc2VgIG9yIGFuIGFycmF5IHdpdGggYSBsaXN0IG9mIHZhbGlkXG4gICAgICogcGxhY2VtZW50cyAod2l0aCBvcHRpb25hbCB2YXJpYXRpb25zKVxuICAgICAqL1xuICAgIGJlaGF2aW9yOiAnZmxpcCcsXG4gICAgLyoqXG4gICAgICogQHByb3Age251bWJlcn0gcGFkZGluZz01XG4gICAgICogVGhlIHBvcHBlciB3aWxsIGZsaXAgaWYgaXQgaGl0cyB0aGUgZWRnZXMgb2YgdGhlIGBib3VuZGFyaWVzRWxlbWVudGBcbiAgICAgKi9cbiAgICBwYWRkaW5nOiA1LFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtTdHJpbmd8SFRNTEVsZW1lbnR9IGJvdW5kYXJpZXNFbGVtZW50PSd2aWV3cG9ydCdcbiAgICAgKiBUaGUgZWxlbWVudCB3aGljaCB3aWxsIGRlZmluZSB0aGUgYm91bmRhcmllcyBvZiB0aGUgcG9wcGVyIHBvc2l0aW9uLlxuICAgICAqIFRoZSBwb3BwZXIgd2lsbCBuZXZlciBiZSBwbGFjZWQgb3V0c2lkZSBvZiB0aGUgZGVmaW5lZCBib3VuZGFyaWVzXG4gICAgICogKGV4Y2VwdCBpZiBga2VlcFRvZ2V0aGVyYCBpcyBlbmFibGVkKVxuICAgICAqL1xuICAgIGJvdW5kYXJpZXNFbGVtZW50OiAndmlld3BvcnQnXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gbWFrZSB0aGUgcG9wcGVyIGZsb3cgdG93YXJkIHRoZSBpbm5lciBvZiB0aGUgcmVmZXJlbmNlIGVsZW1lbnQuXG4gICAqIEJ5IGRlZmF1bHQsIHdoZW4gdGhpcyBtb2RpZmllciBpcyBkaXNhYmxlZCwgdGhlIHBvcHBlciB3aWxsIGJlIHBsYWNlZCBvdXRzaWRlXG4gICAqIHRoZSByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGlubmVyOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTcwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogNzAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD1mYWxzZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogZmFsc2UsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBpbm5lclxuICB9LFxuXG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIGhpZGUgdGhlIHBvcHBlciB3aGVuIGl0cyByZWZlcmVuY2UgZWxlbWVudCBpcyBvdXRzaWRlIG9mIHRoZVxuICAgKiBwb3BwZXIgYm91bmRhcmllcy4gSXQgd2lsbCBzZXQgYSBgeC1vdXQtb2YtYm91bmRhcmllc2AgYXR0cmlidXRlIHdoaWNoIGNhblxuICAgKiBiZSB1c2VkIHRvIGhpZGUgd2l0aCBhIENTUyBzZWxlY3RvciB0aGUgcG9wcGVyIHdoZW4gaXRzIHJlZmVyZW5jZSBpc1xuICAgKiBvdXQgb2YgYm91bmRhcmllcy5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBwcmV2ZW50T3ZlcmZsb3dgIG1vZGlmaWVyIGJlZm9yZSBpdCBpbiBvcmRlciB0byB3b3JrLlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgaGlkZToge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj04MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDgwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGhpZGVcbiAgfSxcblxuICAvKipcbiAgICogQ29tcHV0ZXMgdGhlIHN0eWxlIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIgZWxlbWVudCB0byBnZXRzXG4gICAqIHByb3Blcmx5IHBvc2l0aW9uZWQuXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGlzIG1vZGlmaWVyIHdpbGwgbm90IHRvdWNoIHRoZSBET00sIGl0IGp1c3QgcHJlcGFyZXMgdGhlIHN0eWxlc1xuICAgKiBzbyB0aGF0IGBhcHBseVN0eWxlYCBtb2RpZmllciBjYW4gYXBwbHkgaXQuIFRoaXMgc2VwYXJhdGlvbiBpcyB1c2VmdWxcbiAgICogaW4gY2FzZSB5b3UgbmVlZCB0byByZXBsYWNlIGBhcHBseVN0eWxlYCB3aXRoIGEgY3VzdG9tIGltcGxlbWVudGF0aW9uLlxuICAgKlxuICAgKiBUaGlzIG1vZGlmaWVyIGhhcyBgODUwYCBhcyBgb3JkZXJgIHZhbHVlIHRvIG1haW50YWluIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICogd2l0aCBwcmV2aW91cyB2ZXJzaW9ucyBvZiBQb3BwZXIuanMuIEV4cGVjdCB0aGUgbW9kaWZpZXJzIG9yZGVyaW5nIG1ldGhvZFxuICAgKiB0byBjaGFuZ2UgaW4gZnV0dXJlIG1ham9yIHZlcnNpb25zIG9mIHRoZSBsaWJyYXJ5LlxuICAgKlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgY29tcHV0ZVN0eWxlOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTg1MCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogODUwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogY29tcHV0ZVN0eWxlLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtCb29sZWFufSBncHVBY2NlbGVyYXRpb249dHJ1ZVxuICAgICAqIElmIHRydWUsIGl0IHVzZXMgdGhlIENTUyAzRCB0cmFuc2Zvcm1hdGlvbiB0byBwb3NpdGlvbiB0aGUgcG9wcGVyLlxuICAgICAqIE90aGVyd2lzZSwgaXQgd2lsbCB1c2UgdGhlIGB0b3BgIGFuZCBgbGVmdGAgcHJvcGVydGllc1xuICAgICAqL1xuICAgIGdwdUFjY2VsZXJhdGlvbjogdHJ1ZSxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7c3RyaW5nfSBbeD0nYm90dG9tJ11cbiAgICAgKiBXaGVyZSB0byBhbmNob3IgdGhlIFggYXhpcyAoYGJvdHRvbWAgb3IgYHRvcGApLiBBS0EgWCBvZmZzZXQgb3JpZ2luLlxuICAgICAqIENoYW5nZSB0aGlzIGlmIHlvdXIgcG9wcGVyIHNob3VsZCBncm93IGluIGEgZGlyZWN0aW9uIGRpZmZlcmVudCBmcm9tIGBib3R0b21gXG4gICAgICovXG4gICAgeDogJ2JvdHRvbScsXG4gICAgLyoqXG4gICAgICogQHByb3Age3N0cmluZ30gW3g9J2xlZnQnXVxuICAgICAqIFdoZXJlIHRvIGFuY2hvciB0aGUgWSBheGlzIChgbGVmdGAgb3IgYHJpZ2h0YCkuIEFLQSBZIG9mZnNldCBvcmlnaW4uXG4gICAgICogQ2hhbmdlIHRoaXMgaWYgeW91ciBwb3BwZXIgc2hvdWxkIGdyb3cgaW4gYSBkaXJlY3Rpb24gZGlmZmVyZW50IGZyb20gYHJpZ2h0YFxuICAgICAqL1xuICAgIHk6ICdyaWdodCdcbiAgfSxcblxuICAvKipcbiAgICogQXBwbGllcyB0aGUgY29tcHV0ZWQgc3R5bGVzIHRvIHRoZSBwb3BwZXIgZWxlbWVudC5cbiAgICpcbiAgICogQWxsIHRoZSBET00gbWFuaXB1bGF0aW9ucyBhcmUgbGltaXRlZCB0byB0aGlzIG1vZGlmaWVyLiBUaGlzIGlzIHVzZWZ1bCBpbiBjYXNlXG4gICAqIHlvdSB3YW50IHRvIGludGVncmF0ZSBQb3BwZXIuanMgaW5zaWRlIGEgZnJhbWV3b3JrIG9yIHZpZXcgbGlicmFyeSBhbmQgeW91XG4gICAqIHdhbnQgdG8gZGVsZWdhdGUgYWxsIHRoZSBET00gbWFuaXB1bGF0aW9ucyB0byBpdC5cbiAgICpcbiAgICogTm90ZSB0aGF0IGlmIHlvdSBkaXNhYmxlIHRoaXMgbW9kaWZpZXIsIHlvdSBtdXN0IG1ha2Ugc3VyZSB0aGUgcG9wcGVyIGVsZW1lbnRcbiAgICogaGFzIGl0cyBwb3NpdGlvbiBzZXQgdG8gYGFic29sdXRlYCBiZWZvcmUgUG9wcGVyLmpzIGNhbiBkbyBpdHMgd29yayFcbiAgICpcbiAgICogSnVzdCBkaXNhYmxlIHRoaXMgbW9kaWZpZXIgYW5kIGRlZmluZSB5b3VyIG93biB0byBhY2hpZXZlIHRoZSBkZXNpcmVkIGVmZmVjdC5cbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGFwcGx5U3R5bGU6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9OTAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA5MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBhcHBseVN0eWxlLFxuICAgIC8qKiBAcHJvcCB7RnVuY3Rpb259ICovXG4gICAgb25Mb2FkOiBhcHBseVN0eWxlT25Mb2FkLFxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS4xMC4wLCB0aGUgcHJvcGVydHkgbW92ZWQgdG8gYGNvbXB1dGVTdHlsZWAgbW9kaWZpZXJcbiAgICAgKiBAcHJvcCB7Qm9vbGVhbn0gZ3B1QWNjZWxlcmF0aW9uPXRydWVcbiAgICAgKiBJZiB0cnVlLCBpdCB1c2VzIHRoZSBDU1MgM0QgdHJhbnNmb3JtYXRpb24gdG8gcG9zaXRpb24gdGhlIHBvcHBlci5cbiAgICAgKiBPdGhlcndpc2UsIGl0IHdpbGwgdXNlIHRoZSBgdG9wYCBhbmQgYGxlZnRgIHByb3BlcnRpZXNcbiAgICAgKi9cbiAgICBncHVBY2NlbGVyYXRpb246IHVuZGVmaW5lZFxuICB9XG59O1xuXG4vKipcbiAqIFRoZSBgZGF0YU9iamVjdGAgaXMgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYWxsIHRoZSBpbmZvcm1hdGlvbiB1c2VkIGJ5IFBvcHBlci5qcy5cbiAqIFRoaXMgb2JqZWN0IGlzIHBhc3NlZCB0byBtb2RpZmllcnMgYW5kIHRvIHRoZSBgb25DcmVhdGVgIGFuZCBgb25VcGRhdGVgIGNhbGxiYWNrcy5cbiAqIEBuYW1lIGRhdGFPYmplY3RcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLmluc3RhbmNlIFRoZSBQb3BwZXIuanMgaW5zdGFuY2VcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkYXRhLnBsYWNlbWVudCBQbGFjZW1lbnQgYXBwbGllZCB0byBwb3BwZXJcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkYXRhLm9yaWdpbmFsUGxhY2VtZW50IFBsYWNlbWVudCBvcmlnaW5hbGx5IGRlZmluZWQgb24gaW5pdFxuICogQHByb3BlcnR5IHtCb29sZWFufSBkYXRhLmZsaXBwZWQgVHJ1ZSBpZiBwb3BwZXIgaGFzIGJlZW4gZmxpcHBlZCBieSBmbGlwIG1vZGlmaWVyXG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IGRhdGEuaGlkZSBUcnVlIGlmIHRoZSByZWZlcmVuY2UgZWxlbWVudCBpcyBvdXQgb2YgYm91bmRhcmllcywgdXNlZnVsIHRvIGtub3cgd2hlbiB0byBoaWRlIHRoZSBwb3BwZXJcbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR9IGRhdGEuYXJyb3dFbGVtZW50IE5vZGUgdXNlZCBhcyBhcnJvdyBieSBhcnJvdyBtb2RpZmllclxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuc3R5bGVzIEFueSBDU1MgcHJvcGVydHkgZGVmaW5lZCBoZXJlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLiBJdCBleHBlY3RzIHRoZSBKYXZhU2NyaXB0IG5vbWVuY2xhdHVyZSAoZWcuIGBtYXJnaW5Cb3R0b21gKVxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuYXJyb3dTdHlsZXMgQW55IENTUyBwcm9wZXJ0eSBkZWZpbmVkIGhlcmUgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIgYXJyb3cuIEl0IGV4cGVjdHMgdGhlIEphdmFTY3JpcHQgbm9tZW5jbGF0dXJlIChlZy4gYG1hcmdpbkJvdHRvbWApXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5ib3VuZGFyaWVzIE9mZnNldHMgb2YgdGhlIHBvcHBlciBib3VuZGFyaWVzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5vZmZzZXRzIFRoZSBtZWFzdXJlbWVudHMgb2YgcG9wcGVyLCByZWZlcmVuY2UgYW5kIGFycm93IGVsZW1lbnRzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5vZmZzZXRzLnBvcHBlciBgdG9wYCwgYGxlZnRgLCBgd2lkdGhgLCBgaGVpZ2h0YCB2YWx1ZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLm9mZnNldHMucmVmZXJlbmNlIGB0b3BgLCBgbGVmdGAsIGB3aWR0aGAsIGBoZWlnaHRgIHZhbHVlc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEub2Zmc2V0cy5hcnJvd10gYHRvcGAgYW5kIGBsZWZ0YCBvZmZzZXRzLCBvbmx5IG9uZSBvZiB0aGVtIHdpbGwgYmUgZGlmZmVyZW50IGZyb20gMFxuICovXG5cbi8qKlxuICogRGVmYXVsdCBvcHRpb25zIHByb3ZpZGVkIHRvIFBvcHBlci5qcyBjb25zdHJ1Y3Rvci48YnIgLz5cbiAqIFRoZXNlIGNhbiBiZSBvdmVycmlkZGVuIHVzaW5nIHRoZSBgb3B0aW9uc2AgYXJndW1lbnQgb2YgUG9wcGVyLmpzLjxiciAvPlxuICogVG8gb3ZlcnJpZGUgYW4gb3B0aW9uLCBzaW1wbHkgcGFzcyBhbiBvYmplY3Qgd2l0aCB0aGUgc2FtZVxuICogc3RydWN0dXJlIG9mIHRoZSBgb3B0aW9uc2Agb2JqZWN0LCBhcyB0aGUgM3JkIGFyZ3VtZW50LiBGb3IgZXhhbXBsZTpcbiAqIGBgYFxuICogbmV3IFBvcHBlcihyZWYsIHBvcCwge1xuICogICBtb2RpZmllcnM6IHtcbiAqICAgICBwcmV2ZW50T3ZlcmZsb3c6IHsgZW5hYmxlZDogZmFsc2UgfVxuICogICB9XG4gKiB9KVxuICogYGBgXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHN0YXRpY1xuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG52YXIgRGVmYXVsdHMgPSB7XG4gIC8qKlxuICAgKiBQb3BwZXIncyBwbGFjZW1lbnQuXG4gICAqIEBwcm9wIHtQb3BwZXIucGxhY2VtZW50c30gcGxhY2VtZW50PSdib3R0b20nXG4gICAqL1xuICBwbGFjZW1lbnQ6ICdib3R0b20nLFxuXG4gIC8qKlxuICAgKiBTZXQgdGhpcyB0byB0cnVlIGlmIHlvdSB3YW50IHBvcHBlciB0byBwb3NpdGlvbiBpdCBzZWxmIGluICdmaXhlZCcgbW9kZVxuICAgKiBAcHJvcCB7Qm9vbGVhbn0gcG9zaXRpb25GaXhlZD1mYWxzZVxuICAgKi9cbiAgcG9zaXRpb25GaXhlZDogZmFsc2UsXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgZXZlbnRzIChyZXNpemUsIHNjcm9sbCkgYXJlIGluaXRpYWxseSBlbmFibGVkLlxuICAgKiBAcHJvcCB7Qm9vbGVhbn0gZXZlbnRzRW5hYmxlZD10cnVlXG4gICAqL1xuICBldmVudHNFbmFibGVkOiB0cnVlLFxuXG4gIC8qKlxuICAgKiBTZXQgdG8gdHJ1ZSBpZiB5b3Ugd2FudCB0byBhdXRvbWF0aWNhbGx5IHJlbW92ZSB0aGUgcG9wcGVyIHdoZW5cbiAgICogeW91IGNhbGwgdGhlIGBkZXN0cm95YCBtZXRob2QuXG4gICAqIEBwcm9wIHtCb29sZWFufSByZW1vdmVPbkRlc3Ryb3k9ZmFsc2VcbiAgICovXG4gIHJlbW92ZU9uRGVzdHJveTogZmFsc2UsXG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGNhbGxlZCB3aGVuIHRoZSBwb3BwZXIgaXMgY3JlYXRlZC48YnIgLz5cbiAgICogQnkgZGVmYXVsdCwgaXQgaXMgc2V0IHRvIG5vLW9wLjxiciAvPlxuICAgKiBBY2Nlc3MgUG9wcGVyLmpzIGluc3RhbmNlIHdpdGggYGRhdGEuaW5zdGFuY2VgLlxuICAgKiBAcHJvcCB7b25DcmVhdGV9XG4gICAqL1xuICBvbkNyZWF0ZTogZnVuY3Rpb24gb25DcmVhdGUoKSB7fSxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHBvcHBlciBpcyB1cGRhdGVkLiBUaGlzIGNhbGxiYWNrIGlzIG5vdCBjYWxsZWRcbiAgICogb24gdGhlIGluaXRpYWxpemF0aW9uL2NyZWF0aW9uIG9mIHRoZSBwb3BwZXIsIGJ1dCBvbmx5IG9uIHN1YnNlcXVlbnRcbiAgICogdXBkYXRlcy48YnIgLz5cbiAgICogQnkgZGVmYXVsdCwgaXQgaXMgc2V0IHRvIG5vLW9wLjxiciAvPlxuICAgKiBBY2Nlc3MgUG9wcGVyLmpzIGluc3RhbmNlIHdpdGggYGRhdGEuaW5zdGFuY2VgLlxuICAgKiBAcHJvcCB7b25VcGRhdGV9XG4gICAqL1xuICBvblVwZGF0ZTogZnVuY3Rpb24gb25VcGRhdGUoKSB7fSxcblxuICAvKipcbiAgICogTGlzdCBvZiBtb2RpZmllcnMgdXNlZCB0byBtb2RpZnkgdGhlIG9mZnNldHMgYmVmb3JlIHRoZXkgYXJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlci5cbiAgICogVGhleSBwcm92aWRlIG1vc3Qgb2YgdGhlIGZ1bmN0aW9uYWxpdGllcyBvZiBQb3BwZXIuanMuXG4gICAqIEBwcm9wIHttb2RpZmllcnN9XG4gICAqL1xuICBtb2RpZmllcnM6IG1vZGlmaWVyc1xufTtcblxuLyoqXG4gKiBAY2FsbGJhY2sgb25DcmVhdGVcbiAqIEBwYXJhbSB7ZGF0YU9iamVjdH0gZGF0YVxuICovXG5cbi8qKlxuICogQGNhbGxiYWNrIG9uVXBkYXRlXG4gKiBAcGFyYW0ge2RhdGFPYmplY3R9IGRhdGFcbiAqL1xuXG4vLyBVdGlsc1xuLy8gTWV0aG9kc1xudmFyIFBvcHBlciA9IGZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUG9wcGVyLmpzIGluc3RhbmNlLlxuICAgKiBAY2xhc3MgUG9wcGVyXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8cmVmZXJlbmNlT2JqZWN0fSByZWZlcmVuY2UgLSBUaGUgcmVmZXJlbmNlIGVsZW1lbnQgdXNlZCB0byBwb3NpdGlvbiB0aGUgcG9wcGVyXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHBvcHBlciAtIFRoZSBIVE1MIGVsZW1lbnQgdXNlZCBhcyB0aGUgcG9wcGVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gWW91ciBjdXN0b20gb3B0aW9ucyB0byBvdmVycmlkZSB0aGUgb25lcyBkZWZpbmVkIGluIFtEZWZhdWx0c10oI2RlZmF1bHRzKVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IGluc3RhbmNlIC0gVGhlIGdlbmVyYXRlZCBQb3BwZXIuanMgaW5zdGFuY2VcbiAgICovXG4gIGZ1bmN0aW9uIFBvcHBlcihyZWZlcmVuY2UsIHBvcHBlcikge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDoge307XG4gICAgY2xhc3NDYWxsQ2hlY2sodGhpcywgUG9wcGVyKTtcblxuICAgIHRoaXMuc2NoZWR1bGVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKF90aGlzLnVwZGF0ZSk7XG4gICAgfTtcblxuICAgIC8vIG1ha2UgdXBkYXRlKCkgZGVib3VuY2VkLCBzbyB0aGF0IGl0IG9ubHkgcnVucyBhdCBtb3N0IG9uY2UtcGVyLXRpY2tcbiAgICB0aGlzLnVwZGF0ZSA9IGRlYm91bmNlKHRoaXMudXBkYXRlLmJpbmQodGhpcykpO1xuXG4gICAgLy8gd2l0aCB7fSB3ZSBjcmVhdGUgYSBuZXcgb2JqZWN0IHdpdGggdGhlIG9wdGlvbnMgaW5zaWRlIGl0XG4gICAgdGhpcy5vcHRpb25zID0gX2V4dGVuZHMoe30sIFBvcHBlci5EZWZhdWx0cywgb3B0aW9ucyk7XG5cbiAgICAvLyBpbml0IHN0YXRlXG4gICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgIGlzRGVzdHJveWVkOiBmYWxzZSxcbiAgICAgIGlzQ3JlYXRlZDogZmFsc2UsXG4gICAgICBzY3JvbGxQYXJlbnRzOiBbXVxuICAgIH07XG5cbiAgICAvLyBnZXQgcmVmZXJlbmNlIGFuZCBwb3BwZXIgZWxlbWVudHMgKGFsbG93IGpRdWVyeSB3cmFwcGVycylcbiAgICB0aGlzLnJlZmVyZW5jZSA9IHJlZmVyZW5jZSAmJiByZWZlcmVuY2UuanF1ZXJ5ID8gcmVmZXJlbmNlWzBdIDogcmVmZXJlbmNlO1xuICAgIHRoaXMucG9wcGVyID0gcG9wcGVyICYmIHBvcHBlci5qcXVlcnkgPyBwb3BwZXJbMF0gOiBwb3BwZXI7XG5cbiAgICAvLyBEZWVwIG1lcmdlIG1vZGlmaWVycyBvcHRpb25zXG4gICAgdGhpcy5vcHRpb25zLm1vZGlmaWVycyA9IHt9O1xuICAgIE9iamVjdC5rZXlzKF9leHRlbmRzKHt9LCBQb3BwZXIuRGVmYXVsdHMubW9kaWZpZXJzLCBvcHRpb25zLm1vZGlmaWVycykpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgIF90aGlzLm9wdGlvbnMubW9kaWZpZXJzW25hbWVdID0gX2V4dGVuZHMoe30sIFBvcHBlci5EZWZhdWx0cy5tb2RpZmllcnNbbmFtZV0gfHwge30sIG9wdGlvbnMubW9kaWZpZXJzID8gb3B0aW9ucy5tb2RpZmllcnNbbmFtZV0gOiB7fSk7XG4gICAgfSk7XG5cbiAgICAvLyBSZWZhY3RvcmluZyBtb2RpZmllcnMnIGxpc3QgKE9iamVjdCA9PiBBcnJheSlcbiAgICB0aGlzLm1vZGlmaWVycyA9IE9iamVjdC5rZXlzKHRoaXMub3B0aW9ucy5tb2RpZmllcnMpLm1hcChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgcmV0dXJuIF9leHRlbmRzKHtcbiAgICAgICAgbmFtZTogbmFtZVxuICAgICAgfSwgX3RoaXMub3B0aW9ucy5tb2RpZmllcnNbbmFtZV0pO1xuICAgIH0pXG4gICAgLy8gc29ydCB0aGUgbW9kaWZpZXJzIGJ5IG9yZGVyXG4gICAgLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiBhLm9yZGVyIC0gYi5vcmRlcjtcbiAgICB9KTtcblxuICAgIC8vIG1vZGlmaWVycyBoYXZlIHRoZSBhYmlsaXR5IHRvIGV4ZWN1dGUgYXJiaXRyYXJ5IGNvZGUgd2hlbiBQb3BwZXIuanMgZ2V0IGluaXRlZFxuICAgIC8vIHN1Y2ggY29kZSBpcyBleGVjdXRlZCBpbiB0aGUgc2FtZSBvcmRlciBvZiBpdHMgbW9kaWZpZXJcbiAgICAvLyB0aGV5IGNvdWxkIGFkZCBuZXcgcHJvcGVydGllcyB0byB0aGVpciBvcHRpb25zIGNvbmZpZ3VyYXRpb25cbiAgICAvLyBCRSBBV0FSRTogZG9uJ3QgYWRkIG9wdGlvbnMgdG8gYG9wdGlvbnMubW9kaWZpZXJzLm5hbWVgIGJ1dCB0byBgbW9kaWZpZXJPcHRpb25zYCFcbiAgICB0aGlzLm1vZGlmaWVycy5mb3JFYWNoKGZ1bmN0aW9uIChtb2RpZmllck9wdGlvbnMpIHtcbiAgICAgIGlmIChtb2RpZmllck9wdGlvbnMuZW5hYmxlZCAmJiBpc0Z1bmN0aW9uKG1vZGlmaWVyT3B0aW9ucy5vbkxvYWQpKSB7XG4gICAgICAgIG1vZGlmaWVyT3B0aW9ucy5vbkxvYWQoX3RoaXMucmVmZXJlbmNlLCBfdGhpcy5wb3BwZXIsIF90aGlzLm9wdGlvbnMsIG1vZGlmaWVyT3B0aW9ucywgX3RoaXMuc3RhdGUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gZmlyZSB0aGUgZmlyc3QgdXBkYXRlIHRvIHBvc2l0aW9uIHRoZSBwb3BwZXIgaW4gdGhlIHJpZ2h0IHBsYWNlXG4gICAgdGhpcy51cGRhdGUoKTtcblxuICAgIHZhciBldmVudHNFbmFibGVkID0gdGhpcy5vcHRpb25zLmV2ZW50c0VuYWJsZWQ7XG4gICAgaWYgKGV2ZW50c0VuYWJsZWQpIHtcbiAgICAgIC8vIHNldHVwIGV2ZW50IGxpc3RlbmVycywgdGhleSB3aWxsIHRha2UgY2FyZSBvZiB1cGRhdGUgdGhlIHBvc2l0aW9uIGluIHNwZWNpZmljIHNpdHVhdGlvbnNcbiAgICAgIHRoaXMuZW5hYmxlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICB9XG5cbiAgICB0aGlzLnN0YXRlLmV2ZW50c0VuYWJsZWQgPSBldmVudHNFbmFibGVkO1xuICB9XG5cbiAgLy8gV2UgY2FuJ3QgdXNlIGNsYXNzIHByb3BlcnRpZXMgYmVjYXVzZSB0aGV5IGRvbid0IGdldCBsaXN0ZWQgaW4gdGhlXG4gIC8vIGNsYXNzIHByb3RvdHlwZSBhbmQgYnJlYWsgc3R1ZmYgbGlrZSBTaW5vbiBzdHVic1xuXG5cbiAgY3JlYXRlQ2xhc3MoUG9wcGVyLCBbe1xuICAgIGtleTogJ3VwZGF0ZScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZSQkMSgpIHtcbiAgICAgIHJldHVybiB1cGRhdGUuY2FsbCh0aGlzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdkZXN0cm95JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZGVzdHJveSQkMSgpIHtcbiAgICAgIHJldHVybiBkZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZW5hYmxlRXZlbnRMaXN0ZW5lcnMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBlbmFibGVFdmVudExpc3RlbmVycyQkMSgpIHtcbiAgICAgIHJldHVybiBlbmFibGVFdmVudExpc3RlbmVycy5jYWxsKHRoaXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2Rpc2FibGVFdmVudExpc3RlbmVycycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRpc2FibGVFdmVudExpc3RlbmVycyQkMSgpIHtcbiAgICAgIHJldHVybiBkaXNhYmxlRXZlbnRMaXN0ZW5lcnMuY2FsbCh0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY2hlZHVsZXMgYW4gdXBkYXRlLiBJdCB3aWxsIHJ1biBvbiB0aGUgbmV4dCBVSSB1cGRhdGUgYXZhaWxhYmxlLlxuICAgICAqIEBtZXRob2Qgc2NoZWR1bGVVcGRhdGVcbiAgICAgKiBAbWVtYmVyb2YgUG9wcGVyXG4gICAgICovXG5cblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgdXRpbGl0aWVzIHVzZWZ1bCB3aGVuIHdyaXRpbmcgY3VzdG9tIG1vZGlmaWVycy5cbiAgICAgKiBTdGFydGluZyBmcm9tIHZlcnNpb24gMS43LCB0aGlzIG1ldGhvZCBpcyBhdmFpbGFibGUgb25seSBpZiB5b3VcbiAgICAgKiBpbmNsdWRlIGBwb3BwZXItdXRpbHMuanNgIGJlZm9yZSBgcG9wcGVyLmpzYC5cbiAgICAgKlxuICAgICAqICoqREVQUkVDQVRJT04qKjogVGhpcyB3YXkgdG8gYWNjZXNzIFBvcHBlclV0aWxzIGlzIGRlcHJlY2F0ZWRcbiAgICAgKiBhbmQgd2lsbCBiZSByZW1vdmVkIGluIHYyISBVc2UgdGhlIFBvcHBlclV0aWxzIG1vZHVsZSBkaXJlY3RseSBpbnN0ZWFkLlxuICAgICAqIER1ZSB0byB0aGUgaGlnaCBpbnN0YWJpbGl0eSBvZiB0aGUgbWV0aG9kcyBjb250YWluZWQgaW4gVXRpbHMsIHdlIGNhbid0XG4gICAgICogZ3VhcmFudGVlIHRoZW0gdG8gZm9sbG93IHNlbXZlci4gVXNlIHRoZW0gYXQgeW91ciBvd24gcmlzayFcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS44XG4gICAgICogQG1lbWJlciBVdGlsc1xuICAgICAqIEBtZW1iZXJvZiBQb3BwZXJcbiAgICAgKi9cblxuICB9XSk7XG4gIHJldHVybiBQb3BwZXI7XG59KCk7XG5cbi8qKlxuICogVGhlIGByZWZlcmVuY2VPYmplY3RgIGlzIGFuIG9iamVjdCB0aGF0IHByb3ZpZGVzIGFuIGludGVyZmFjZSBjb21wYXRpYmxlIHdpdGggUG9wcGVyLmpzXG4gKiBhbmQgbGV0cyB5b3UgdXNlIGl0IGFzIHJlcGxhY2VtZW50IG9mIGEgcmVhbCBET00gbm9kZS48YnIgLz5cbiAqIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIHBvc2l0aW9uIGEgcG9wcGVyIHJlbGF0aXZlbHkgdG8gYSBzZXQgb2YgY29vcmRpbmF0ZXNcbiAqIGluIGNhc2UgeW91IGRvbid0IGhhdmUgYSBET00gbm9kZSB0byB1c2UgYXMgcmVmZXJlbmNlLlxuICpcbiAqIGBgYFxuICogbmV3IFBvcHBlcihyZWZlcmVuY2VPYmplY3QsIHBvcHBlck5vZGUpO1xuICogYGBgXG4gKlxuICogTkI6IFRoaXMgZmVhdHVyZSBpc24ndCBzdXBwb3J0ZWQgaW4gSW50ZXJuZXQgRXhwbG9yZXIgMTAuXG4gKiBAbmFtZSByZWZlcmVuY2VPYmplY3RcbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb259IGRhdGEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG4gKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIHNldCBvZiBjb29yZGluYXRlcyBjb21wYXRpYmxlIHdpdGggdGhlIG5hdGl2ZSBgZ2V0Qm91bmRpbmdDbGllbnRSZWN0YCBtZXRob2QuXG4gKiBAcHJvcGVydHkge251bWJlcn0gZGF0YS5jbGllbnRXaWR0aFxuICogQW4gRVM2IGdldHRlciB0aGF0IHdpbGwgcmV0dXJuIHRoZSB3aWR0aCBvZiB0aGUgdmlydHVhbCByZWZlcmVuY2UgZWxlbWVudC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkYXRhLmNsaWVudEhlaWdodFxuICogQW4gRVM2IGdldHRlciB0aGF0IHdpbGwgcmV0dXJuIHRoZSBoZWlnaHQgb2YgdGhlIHZpcnR1YWwgcmVmZXJlbmNlIGVsZW1lbnQuXG4gKi9cblxuXG5Qb3BwZXIuVXRpbHMgPSAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiBnbG9iYWwpLlBvcHBlclV0aWxzO1xuUG9wcGVyLnBsYWNlbWVudHMgPSBwbGFjZW1lbnRzO1xuUG9wcGVyLkRlZmF1bHRzID0gRGVmYXVsdHM7XG5cbmV4cG9ydCBkZWZhdWx0IFBvcHBlcjtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXBvcHBlci5qcy5tYXBcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL3BvcHBlci5qcy9kaXN0L2VzbS9wb3BwZXIuanNcbi8vIG1vZHVsZSBpZCA9IDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwidmFyIGc7XHJcblxyXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxyXG5nID0gKGZ1bmN0aW9uKCkge1xyXG5cdHJldHVybiB0aGlzO1xyXG59KSgpO1xyXG5cclxudHJ5IHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcclxuXHRnID0gZyB8fCBGdW5jdGlvbihcInJldHVybiB0aGlzXCIpKCkgfHwgKDEsZXZhbCkoXCJ0aGlzXCIpO1xyXG59IGNhdGNoKGUpIHtcclxuXHQvLyBUaGlzIHdvcmtzIGlmIHRoZSB3aW5kb3cgcmVmZXJlbmNlIGlzIGF2YWlsYWJsZVxyXG5cdGlmKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpXHJcblx0XHRnID0gd2luZG93O1xyXG59XHJcblxyXG4vLyBnIGNhbiBzdGlsbCBiZSB1bmRlZmluZWQsIGJ1dCBub3RoaW5nIHRvIGRvIGFib3V0IGl0Li4uXHJcbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXHJcbi8vIGVhc2llciB0byBoYW5kbGUgdGhpcyBjYXNlLiBpZighZ2xvYmFsKSB7IC4uLn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZztcclxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxyXG4gKiBCb290c3RyYXAtc2VsZWN0IHYxLjEyLjQgKGh0dHA6Ly9zaWx2aW9tb3JldG8uZ2l0aHViLmlvL2Jvb3RzdHJhcC1zZWxlY3QpXHJcbiAqXHJcbiAqIENvcHlyaWdodCAyMDEzLTIwMTcgYm9vdHN0cmFwLXNlbGVjdFxyXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS9zaWx2aW9tb3JldG8vYm9vdHN0cmFwLXNlbGVjdC9ibG9iL21hc3Rlci9MSUNFTlNFKVxyXG4gKi9cclxuXHJcbihmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHVubGVzcyBhbWRNb2R1bGVJZCBpcyBzZXRcbiAgICBkZWZpbmUoW1wianF1ZXJ5XCJdLCBmdW5jdGlvbiAoYTApIHtcbiAgICAgIHJldHVybiAoZmFjdG9yeShhMCkpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgLy8gTm9kZS4gRG9lcyBub3Qgd29yayB3aXRoIHN0cmljdCBDb21tb25KUywgYnV0XG4gICAgLy8gb25seSBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB0aGF0IHN1cHBvcnQgbW9kdWxlLmV4cG9ydHMsXG4gICAgLy8gbGlrZSBOb2RlLlxuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwianF1ZXJ5XCIpKTtcbiAgfSBlbHNlIHtcbiAgICBmYWN0b3J5KHJvb3RbXCJqUXVlcnlcIl0pO1xuICB9XG59KHRoaXMsIGZ1bmN0aW9uIChqUXVlcnkpIHtcblxuKGZ1bmN0aW9uICgkKSB7XHJcbiAgJ3VzZSBzdHJpY3QnO1xyXG5cclxuICAvLzxlZGl0b3ItZm9sZCBkZXNjPVwiU2hpbXNcIj5cclxuICBpZiAoIVN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMpIHtcclxuICAgIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICd1c2Ugc3RyaWN0JzsgLy8gbmVlZGVkIHRvIHN1cHBvcnQgYGFwcGx5YC9gY2FsbGAgd2l0aCBgdW5kZWZpbmVkYC9gbnVsbGBcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIGluZGV4T2YgPSAnJy5pbmRleE9mO1xyXG4gICAgICB2YXIgaW5jbHVkZXMgPSBmdW5jdGlvbiAoc2VhcmNoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHRoaXMpO1xyXG4gICAgICAgIGlmIChzZWFyY2ggJiYgdG9TdHJpbmcuY2FsbChzZWFyY2gpID09ICdbb2JqZWN0IFJlZ0V4cF0nKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xyXG4gICAgICAgIHZhciBzZWFyY2hTdHJpbmcgPSBTdHJpbmcoc2VhcmNoKTtcclxuICAgICAgICB2YXIgc2VhcmNoTGVuZ3RoID0gc2VhcmNoU3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgcG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBgVG9JbnRlZ2VyYFxyXG4gICAgICAgIHZhciBwb3MgPSBwb3NpdGlvbiA/IE51bWJlcihwb3NpdGlvbikgOiAwO1xyXG4gICAgICAgIGlmIChwb3MgIT0gcG9zKSB7IC8vIGJldHRlciBgaXNOYU5gXHJcbiAgICAgICAgICBwb3MgPSAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBNYXRoLm1pbihNYXRoLm1heChwb3MsIDApLCBzdHJpbmdMZW5ndGgpO1xyXG4gICAgICAgIC8vIEF2b2lkIHRoZSBgaW5kZXhPZmAgY2FsbCBpZiBubyBtYXRjaCBpcyBwb3NzaWJsZVxyXG4gICAgICAgIGlmIChzZWFyY2hMZW5ndGggKyBzdGFydCA+IHN0cmluZ0xlbmd0aCkge1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaW5kZXhPZi5jYWxsKHN0cmluZywgc2VhcmNoU3RyaW5nLCBwb3MpICE9IC0xO1xyXG4gICAgICB9O1xyXG4gICAgICBpZiAoZGVmaW5lUHJvcGVydHkpIHtcclxuICAgICAgICBkZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAnaW5jbHVkZXMnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBpbmNsdWRlcyxcclxuICAgICAgICAgICdjb25maWd1cmFibGUnOiB0cnVlLFxyXG4gICAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIFN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMgPSBpbmNsdWRlcztcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoKSB7XHJcbiAgICAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAndXNlIHN0cmljdCc7IC8vIG5lZWRlZCB0byBzdXBwb3J0IGBhcHBseWAvYGNhbGxgIHdpdGggYHVuZGVmaW5lZGAvYG51bGxgXHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBzdGFydHNXaXRoID0gZnVuY3Rpb24gKHNlYXJjaCkge1xyXG4gICAgICAgIGlmICh0aGlzID09IG51bGwpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0cmluZyA9IFN0cmluZyh0aGlzKTtcclxuICAgICAgICBpZiAoc2VhcmNoICYmIHRvU3RyaW5nLmNhbGwoc2VhcmNoKSA9PSAnW29iamVjdCBSZWdFeHBdJykge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgc2VhcmNoU3RyaW5nID0gU3RyaW5nKHNlYXJjaCk7XHJcbiAgICAgICAgdmFyIHNlYXJjaExlbmd0aCA9IHNlYXJjaFN0cmluZy5sZW5ndGg7XHJcbiAgICAgICAgdmFyIHBvc2l0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgLy8gYFRvSW50ZWdlcmBcclxuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPyBOdW1iZXIocG9zaXRpb24pIDogMDtcclxuICAgICAgICBpZiAocG9zICE9IHBvcykgeyAvLyBiZXR0ZXIgYGlzTmFOYFxyXG4gICAgICAgICAgcG9zID0gMDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5taW4oTWF0aC5tYXgocG9zLCAwKSwgc3RyaW5nTGVuZ3RoKTtcclxuICAgICAgICAvLyBBdm9pZCB0aGUgYGluZGV4T2ZgIGNhbGwgaWYgbm8gbWF0Y2ggaXMgcG9zc2libGVcclxuICAgICAgICBpZiAoc2VhcmNoTGVuZ3RoICsgc3RhcnQgPiBzdHJpbmdMZW5ndGgpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGluZGV4ID0gLTE7XHJcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzZWFyY2hMZW5ndGgpIHtcclxuICAgICAgICAgIGlmIChzdHJpbmcuY2hhckNvZGVBdChzdGFydCArIGluZGV4KSAhPSBzZWFyY2hTdHJpbmcuY2hhckNvZGVBdChpbmRleCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfTtcclxuICAgICAgaWYgKGRlZmluZVByb3BlcnR5KSB7XHJcbiAgICAgICAgZGVmaW5lUHJvcGVydHkoU3RyaW5nLnByb3RvdHlwZSwgJ3N0YXJ0c1dpdGgnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBzdGFydHNXaXRoLFxyXG4gICAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXHJcbiAgICAgICAgICAnd3JpdGFibGUnOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghT2JqZWN0LmtleXMpIHtcclxuICAgIE9iamVjdC5rZXlzID0gZnVuY3Rpb24gKFxyXG4gICAgICBvLCAvLyBvYmplY3RcclxuICAgICAgaywgLy8ga2V5XHJcbiAgICAgIHIgIC8vIHJlc3VsdCBhcnJheVxyXG4gICAgICApe1xyXG4gICAgICAvLyBpbml0aWFsaXplIG9iamVjdCBhbmQgcmVzdWx0XHJcbiAgICAgIHI9W107XHJcbiAgICAgIC8vIGl0ZXJhdGUgb3ZlciBvYmplY3Qga2V5c1xyXG4gICAgICBmb3IgKGsgaW4gbylcclxuICAgICAgICAgIC8vIGZpbGwgcmVzdWx0IGFycmF5IHdpdGggbm9uLXByb3RvdHlwaWNhbCBrZXlzXHJcbiAgICAgICAgci5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspICYmIHIucHVzaChrKTtcclxuICAgICAgLy8gcmV0dXJuIHJlc3VsdFxyXG4gICAgICByZXR1cm4gcjtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBzZXQgZGF0YS1zZWxlY3RlZCBvbiBzZWxlY3QgZWxlbWVudCBpZiB0aGUgdmFsdWUgaGFzIGJlZW4gcHJvZ3JhbW1hdGljYWxseSBzZWxlY3RlZFxyXG4gIC8vIHByaW9yIHRvIGluaXRpYWxpemF0aW9uIG9mIGJvb3RzdHJhcC1zZWxlY3RcclxuICAvLyAqIGNvbnNpZGVyIHJlbW92aW5nIG9yIHJlcGxhY2luZyBhbiBhbHRlcm5hdGl2ZSBtZXRob2QgKlxyXG4gIHZhciB2YWxIb29rcyA9IHtcclxuICAgIHVzZURlZmF1bHQ6IGZhbHNlLFxyXG4gICAgX3NldDogJC52YWxIb29rcy5zZWxlY3Quc2V0XHJcbiAgfTtcclxuXHJcbiAgJC52YWxIb29rcy5zZWxlY3Quc2V0ID0gZnVuY3Rpb24oZWxlbSwgdmFsdWUpIHtcclxuICAgIGlmICh2YWx1ZSAmJiAhdmFsSG9va3MudXNlRGVmYXVsdCkgJChlbGVtKS5kYXRhKCdzZWxlY3RlZCcsIHRydWUpO1xyXG5cclxuICAgIHJldHVybiB2YWxIb29rcy5fc2V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgfTtcclxuXHJcbiAgdmFyIGNoYW5nZWRfYXJndW1lbnRzID0gbnVsbDtcclxuXHJcbiAgdmFyIEV2ZW50SXNTdXBwb3J0ZWQgPSAoZnVuY3Rpb24oKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBuZXcgRXZlbnQoJ2NoYW5nZScpO1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH0pKCk7XHJcblxyXG4gICQuZm4udHJpZ2dlck5hdGl2ZSA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgIHZhciBlbCA9IHRoaXNbMF0sXHJcbiAgICAgICAgZXZlbnQ7XHJcblxyXG4gICAgaWYgKGVsLmRpc3BhdGNoRXZlbnQpIHsgLy8gZm9yIG1vZGVybiBicm93c2VycyAmIElFOStcclxuICAgICAgaWYgKEV2ZW50SXNTdXBwb3J0ZWQpIHtcclxuICAgICAgICAvLyBGb3IgbW9kZXJuIGJyb3dzZXJzXHJcbiAgICAgICAgZXZlbnQgPSBuZXcgRXZlbnQoZXZlbnROYW1lLCB7XHJcbiAgICAgICAgICBidWJibGVzOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gRm9yIElFIHNpbmNlIGl0IGRvZXNuJ3Qgc3VwcG9ydCBFdmVudCBjb25zdHJ1Y3RvclxyXG4gICAgICAgIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XHJcbiAgICAgICAgZXZlbnQuaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgZmFsc2UpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBlbC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcclxuICAgIH0gZWxzZSBpZiAoZWwuZmlyZUV2ZW50KSB7IC8vIGZvciBJRThcclxuICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudE9iamVjdCgpO1xyXG4gICAgICBldmVudC5ldmVudFR5cGUgPSBldmVudE5hbWU7XHJcbiAgICAgIGVsLmZpcmVFdmVudCgnb24nICsgZXZlbnROYW1lLCBldmVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBmYWxsIGJhY2sgdG8galF1ZXJ5LnRyaWdnZXJcclxuICAgICAgdGhpcy50cmlnZ2VyKGV2ZW50TmFtZSk7XHJcbiAgICB9XHJcbiAgfTtcclxuICAvLzwvZWRpdG9yLWZvbGQ+XHJcblxyXG4gIC8vIENhc2UgaW5zZW5zaXRpdmUgY29udGFpbnMgc2VhcmNoXHJcbiAgJC5leHByLnBzZXVkb3MuaWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suaW5jbHVkZXMobWV0YVszXS50b1VwcGVyQ2FzZSgpKTtcclxuICB9O1xyXG5cclxuICAvLyBDYXNlIGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5pYmVnaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suc3RhcnRzV2l0aChtZXRhWzNdLnRvVXBwZXJDYXNlKCkpO1xyXG4gIH07XHJcblxyXG4gIC8vIENhc2UgYW5kIGFjY2VudCBpbnNlbnNpdGl2ZSBjb250YWlucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmouZGF0YSgnbm9ybWFsaXplZFRleHQnKSB8fCAkb2JqLnRleHQoKSkudG9TdHJpbmcoKS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgcmV0dXJuIGhheXN0YWNrLmluY2x1ZGVzKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ2FzZSBhbmQgYWNjZW50IGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWJlZ2lucyA9IGZ1bmN0aW9uIChvYmosIGluZGV4LCBtZXRhKSB7XHJcbiAgICB2YXIgJG9iaiA9ICQob2JqKS5maW5kKCdhJyk7XHJcbiAgICB2YXIgaGF5c3RhY2sgPSAoJG9iai5kYXRhKCd0b2tlbnMnKSB8fCAkb2JqLmRhdGEoJ25vcm1hbGl6ZWRUZXh0JykgfHwgJG9iai50ZXh0KCkpLnRvU3RyaW5nKCkudG9VcHBlckNhc2UoKTtcclxuICAgIHJldHVybiBoYXlzdGFjay5zdGFydHNXaXRoKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFsbCBkaWF0cmljcyBmcm9tIHRoZSBnaXZlbiB0ZXh0LlxyXG4gICAqIEBhY2Nlc3MgcHJpdmF0ZVxyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0XHJcbiAgICogQHJldHVybnMge1N0cmluZ31cclxuICAgKi9cclxuICBmdW5jdGlvbiBub3JtYWxpemVUb0Jhc2UodGV4dCkge1xyXG4gICAgdmFyIHJFeHBzID0gW1xyXG4gICAgICB7cmU6IC9bXFx4QzAtXFx4QzZdL2csIGNoOiBcIkFcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhFMC1cXHhFNl0vZywgY2g6IFwiYVwifSxcclxuICAgICAge3JlOiAvW1xceEM4LVxceENCXS9nLCBjaDogXCJFXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RTgtXFx4RUJdL2csIGNoOiBcImVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDQy1cXHhDRl0vZywgY2g6IFwiSVwifSxcclxuICAgICAge3JlOiAvW1xceEVDLVxceEVGXS9nLCBjaDogXCJpXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RDItXFx4RDZdL2csIGNoOiBcIk9cIn0sXHJcbiAgICAgIHtyZTogL1tcXHhGMi1cXHhGNl0vZywgY2g6IFwib1wifSxcclxuICAgICAge3JlOiAvW1xceEQ5LVxceERDXS9nLCBjaDogXCJVXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjktXFx4RkNdL2csIGNoOiBcInVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDNy1cXHhFN10vZywgY2g6IFwiY1wifSxcclxuICAgICAge3JlOiAvW1xceEQxXS9nLCBjaDogXCJOXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjFdL2csIGNoOiBcIm5cIn1cclxuICAgIF07XHJcbiAgICAkLmVhY2gockV4cHMsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGV4dCA9IHRleHQgPyB0ZXh0LnJlcGxhY2UodGhpcy5yZSwgdGhpcy5jaCkgOiAnJztcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHRleHQ7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gTGlzdCBvZiBIVE1MIGVudGl0aWVzIGZvciBlc2NhcGluZy5cclxuICB2YXIgZXNjYXBlTWFwID0ge1xyXG4gICAgJyYnOiAnJmFtcDsnLFxyXG4gICAgJzwnOiAnJmx0OycsXHJcbiAgICAnPic6ICcmZ3Q7JyxcclxuICAgICdcIic6ICcmcXVvdDsnLFxyXG4gICAgXCInXCI6ICcmI3gyNzsnLFxyXG4gICAgJ2AnOiAnJiN4NjA7J1xyXG4gIH07XHJcbiAgXHJcbiAgdmFyIHVuZXNjYXBlTWFwID0ge1xyXG4gICAgJyZhbXA7JzogJyYnLFxyXG4gICAgJyZsdDsnOiAnPCcsXHJcbiAgICAnJmd0Oyc6ICc+JyxcclxuICAgICcmcXVvdDsnOiAnXCInLFxyXG4gICAgJyYjeDI3Oyc6IFwiJ1wiLFxyXG4gICAgJyYjeDYwOyc6ICdgJ1xyXG4gIH07XHJcblxyXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cclxuICB2YXIgY3JlYXRlRXNjYXBlciA9IGZ1bmN0aW9uKG1hcCkge1xyXG4gICAgdmFyIGVzY2FwZXIgPSBmdW5jdGlvbihtYXRjaCkge1xyXG4gICAgICByZXR1cm4gbWFwW21hdGNoXTtcclxuICAgIH07XHJcbiAgICAvLyBSZWdleGVzIGZvciBpZGVudGlmeWluZyBhIGtleSB0aGF0IG5lZWRzIHRvIGJlIGVzY2FwZWQuXHJcbiAgICB2YXIgc291cmNlID0gJyg/OicgKyBPYmplY3Qua2V5cyhtYXApLmpvaW4oJ3wnKSArICcpJztcclxuICAgIHZhciB0ZXN0UmVnZXhwID0gUmVnRXhwKHNvdXJjZSk7XHJcbiAgICB2YXIgcmVwbGFjZVJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UsICdnJyk7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XHJcbiAgICAgIHN0cmluZyA9IHN0cmluZyA9PSBudWxsID8gJycgOiAnJyArIHN0cmluZztcclxuICAgICAgcmV0dXJuIHRlc3RSZWdleHAudGVzdChzdHJpbmcpID8gc3RyaW5nLnJlcGxhY2UocmVwbGFjZVJlZ2V4cCwgZXNjYXBlcikgOiBzdHJpbmc7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIHZhciBodG1sRXNjYXBlID0gY3JlYXRlRXNjYXBlcihlc2NhcGVNYXApO1xyXG4gIHZhciBodG1sVW5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKHVuZXNjYXBlTWFwKTtcclxuXHJcbiAgdmFyIFNlbGVjdHBpY2tlciA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XHJcbiAgICAvLyBib290c3RyYXAtc2VsZWN0IGhhcyBiZWVuIGluaXRpYWxpemVkIC0gcmV2ZXJ0IHZhbEhvb2tzLnNlbGVjdC5zZXQgYmFjayB0byBpdHMgb3JpZ2luYWwgZnVuY3Rpb25cclxuICAgIGlmICghdmFsSG9va3MudXNlRGVmYXVsdCkge1xyXG4gICAgICAkLnZhbEhvb2tzLnNlbGVjdC5zZXQgPSB2YWxIb29rcy5fc2V0O1xyXG4gICAgICB2YWxIb29rcy51c2VEZWZhdWx0ID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLiRlbGVtZW50ID0gJChlbGVtZW50KTtcclxuICAgIHRoaXMuJG5ld0VsZW1lbnQgPSBudWxsO1xyXG4gICAgdGhpcy4kYnV0dG9uID0gbnVsbDtcclxuICAgIHRoaXMuJG1lbnUgPSBudWxsO1xyXG4gICAgdGhpcy4kbGlzID0gbnVsbDtcclxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XHJcblxyXG4gICAgLy8gSWYgd2UgaGF2ZSBubyB0aXRsZSB5ZXQsIHRyeSB0byBwdWxsIGl0IGZyb20gdGhlIGh0bWwgdGl0bGUgYXR0cmlidXRlIChqUXVlcnkgZG9lc250JyBwaWNrIGl0IHVwIGFzIGl0J3Mgbm90IGFcclxuICAgIC8vIGRhdGEtYXR0cmlidXRlKVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PT0gbnVsbCkge1xyXG4gICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9ybWF0IHdpbmRvdyBwYWRkaW5nXHJcbiAgICB2YXIgd2luUGFkID0gdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmc7XHJcbiAgICBpZiAodHlwZW9mIHdpblBhZCA9PT0gJ251bWJlcicpIHtcclxuICAgICAgdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmcgPSBbd2luUGFkLCB3aW5QYWQsIHdpblBhZCwgd2luUGFkXTtcclxuICAgIH1cclxuXHJcbiAgICAvL0V4cG9zZSBwdWJsaWMgbWV0aG9kc1xyXG4gICAgdGhpcy52YWwgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnZhbDtcclxuICAgIHRoaXMucmVuZGVyID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW5kZXI7XHJcbiAgICB0aGlzLnJlZnJlc2ggPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnJlZnJlc2g7XHJcbiAgICB0aGlzLnNldFN0eWxlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZXRTdHlsZTtcclxuICAgIHRoaXMuc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZWxlY3RBbGw7XHJcbiAgICB0aGlzLmRlc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5kZXNlbGVjdEFsbDtcclxuICAgIHRoaXMuZGVzdHJveSA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUuZGVzdHJveTtcclxuICAgIHRoaXMucmVtb3ZlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW1vdmU7XHJcbiAgICB0aGlzLnNob3cgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnNob3c7XHJcbiAgICB0aGlzLmhpZGUgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLmhpZGU7XHJcblxyXG4gICAgdGhpcy5pbml0KCk7XHJcbiAgfTtcclxuXHJcbiAgU2VsZWN0cGlja2VyLlZFUlNJT04gPSAnMS4xMi40JztcclxuXHJcbiAgLy8gcGFydCBvZiB0aGlzIGlzIGR1cGxpY2F0ZWQgaW4gaTE4bi9kZWZhdWx0cy1lbl9VUy5qcy4gTWFrZSBzdXJlIHRvIHVwZGF0ZSBib3RoLlxyXG4gIFNlbGVjdHBpY2tlci5ERUZBVUxUUyA9IHtcclxuICAgIG5vbmVTZWxlY3RlZFRleHQ6ICdOb3RoaW5nIHNlbGVjdGVkJyxcclxuICAgIG5vbmVSZXN1bHRzVGV4dDogJ05vIHJlc3VsdHMgbWF0Y2hlZCB7MH0nLFxyXG4gICAgY291bnRTZWxlY3RlZFRleHQ6IGZ1bmN0aW9uIChudW1TZWxlY3RlZCwgbnVtVG90YWwpIHtcclxuICAgICAgcmV0dXJuIChudW1TZWxlY3RlZCA9PSAxKSA/IFwiezB9IGl0ZW0gc2VsZWN0ZWRcIiA6IFwiezB9IGl0ZW1zIHNlbGVjdGVkXCI7XHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uc1RleHQ6IGZ1bmN0aW9uIChudW1BbGwsIG51bUdyb3VwKSB7XHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgKG51bUFsbCA9PSAxKSA/ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbSBtYXgpJyA6ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbXMgbWF4KScsXHJcbiAgICAgICAgKG51bUdyb3VwID09IDEpID8gJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtIG1heCknIDogJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtcyBtYXgpJ1xyXG4gICAgICBdO1xyXG4gICAgfSxcclxuICAgIHNlbGVjdEFsbFRleHQ6ICdTZWxlY3QgQWxsJyxcclxuICAgIGRlc2VsZWN0QWxsVGV4dDogJ0Rlc2VsZWN0IEFsbCcsXHJcbiAgICBkb25lQnV0dG9uOiBmYWxzZSxcclxuICAgIGRvbmVCdXR0b25UZXh0OiAnQ2xvc2UnLFxyXG4gICAgbXVsdGlwbGVTZXBhcmF0b3I6ICcsICcsXHJcbiAgICBzdHlsZUJhc2U6ICdidG4nLFxyXG4gICAgc3R5bGU6ICdidG4tZGVmYXVsdCcsXHJcbiAgICBzaXplOiAnYXV0bycsXHJcbiAgICB0aXRsZTogbnVsbCxcclxuICAgIHNlbGVjdGVkVGV4dEZvcm1hdDogJ3ZhbHVlcycsXHJcbiAgICB3aWR0aDogZmFsc2UsXHJcbiAgICBjb250YWluZXI6IGZhbHNlLFxyXG4gICAgaGlkZURpc2FibGVkOiBmYWxzZSxcclxuICAgIHNob3dTdWJ0ZXh0OiBmYWxzZSxcclxuICAgIHNob3dJY29uOiB0cnVlLFxyXG4gICAgc2hvd0NvbnRlbnQ6IHRydWUsXHJcbiAgICBkcm9wdXBBdXRvOiB0cnVlLFxyXG4gICAgaGVhZGVyOiBmYWxzZSxcclxuICAgIGxpdmVTZWFyY2g6IGZhbHNlLFxyXG4gICAgbGl2ZVNlYXJjaFBsYWNlaG9sZGVyOiBudWxsLFxyXG4gICAgbGl2ZVNlYXJjaE5vcm1hbGl6ZTogZmFsc2UsXHJcbiAgICBsaXZlU2VhcmNoU3R5bGU6ICdjb250YWlucycsXHJcbiAgICBhY3Rpb25zQm94OiBmYWxzZSxcclxuICAgIGljb25CYXNlOiAnZ2x5cGhpY29uJyxcclxuICAgIHRpY2tJY29uOiAnZ2x5cGhpY29uLW9rJyxcclxuICAgIHNob3dUaWNrOiBmYWxzZSxcclxuICAgIHRlbXBsYXRlOiB7XHJcbiAgICAgIGNhcmV0OiAnPHNwYW4gY2xhc3M9XCJjYXJldFwiPjwvc3Bhbj4nXHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uczogZmFsc2UsXHJcbiAgICBtb2JpbGU6IGZhbHNlLFxyXG4gICAgc2VsZWN0T25UYWI6IGZhbHNlLFxyXG4gICAgZHJvcGRvd25BbGlnblJpZ2h0OiBmYWxzZSxcclxuICAgIHdpbmRvd1BhZGRpbmc6IDBcclxuICB9O1xyXG5cclxuICBTZWxlY3RwaWNrZXIucHJvdG90eXBlID0ge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yOiBTZWxlY3RwaWNrZXIsXHJcblxyXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICBpZCA9IHRoaXMuJGVsZW1lbnQuYXR0cignaWQnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4nKTtcclxuXHJcbiAgICAgIC8vIHN0b3JlIG9yaWdpbmFsSW5kZXggKGtleSkgYW5kIG5ld0luZGV4ICh2YWx1ZSkgaW4gdGhpcy5saU9iaiBmb3IgZmFzdCBhY2Nlc3NpYmlsaXR5XHJcbiAgICAgIC8vIGFsbG93cyB1cyB0byBkbyB0aGlzLiRsaXMuZXEodGhhdC5saU9ialtpbmRleF0pIGluc3RlYWQgb2YgdGhpcy4kbGlzLmZpbHRlcignW2RhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCJdJylcclxuICAgICAgdGhpcy5saU9iaiA9IHt9O1xyXG4gICAgICB0aGlzLm11bHRpcGxlID0gdGhpcy4kZWxlbWVudC5wcm9wKCdtdWx0aXBsZScpO1xyXG4gICAgICB0aGlzLmF1dG9mb2N1cyA9IHRoaXMuJGVsZW1lbnQucHJvcCgnYXV0b2ZvY3VzJyk7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpZXcoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudFxyXG4gICAgICAgIC5hZnRlcih0aGlzLiRuZXdFbGVtZW50KVxyXG4gICAgICAgIC5hcHBlbmRUbyh0aGlzLiRuZXdFbGVtZW50KTtcclxuICAgICAgdGhpcy4kYnV0dG9uID0gdGhpcy4kbmV3RWxlbWVudC5jaGlsZHJlbignYnV0dG9uJyk7XHJcbiAgICAgIHRoaXMuJG1lbnUgPSB0aGlzLiRuZXdFbGVtZW50LmNoaWxkcmVuKCcuZHJvcGRvd24tbWVudScpO1xyXG4gICAgICB0aGlzLiRtZW51SW5uZXIgPSB0aGlzLiRtZW51LmNoaWxkcmVuKCcuaW5uZXInKTtcclxuICAgICAgdGhpcy4kc2VhcmNoYm94ID0gdGhpcy4kbWVudS5maW5kKCdpbnB1dCcpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmVDbGFzcygnYnMtc2VsZWN0LWhpZGRlbicpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09IHRydWUpIHRoaXMuJG1lbnUuYWRkQ2xhc3MoJ2Ryb3Bkb3duLW1lbnUtcmlnaHQnKTtcclxuXHJcbiAgICAgIGlmICh0eXBlb2YgaWQgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ2RhdGEtaWQnLCBpZCk7XHJcbiAgICAgICAgJCgnbGFiZWxbZm9yPVwiJyArIGlkICsgJ1wiXScpLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMuY2xpY2tMaXN0ZW5lcigpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmxpdmVTZWFyY2gpIHRoaXMubGl2ZVNlYXJjaExpc3RlbmVyKCk7XHJcbiAgICAgIHRoaXMucmVuZGVyKCk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmNvbnRhaW5lcikgdGhpcy5zZWxlY3RQb3NpdGlvbigpO1xyXG4gICAgICB0aGlzLiRtZW51LmRhdGEoJ3RoaXMnLCB0aGlzKTtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5kYXRhKCd0aGlzJywgdGhpcyk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMubW9iaWxlKSB0aGlzLm1vYmlsZSgpO1xyXG5cclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5vbih7XHJcbiAgICAgICAgJ2hpZGUuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2hpZGUuYnMuc2VsZWN0JywgZSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAnaGlkZGVuLmJzLmRyb3Bkb3duJzogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignaGlkZGVuLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgJ3Nob3cuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKTtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignc2hvdy5icy5zZWxlY3QnLCBlKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgICdzaG93bi5icy5kcm9wZG93bic6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ3Nob3duLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAodGhhdC4kZWxlbWVudFswXS5oYXNBdHRyaWJ1dGUoJ3JlcXVpcmVkJykpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50Lm9uKCdpbnZhbGlkJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLmFkZENsYXNzKCdicy1pbnZhbGlkJyk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kZWxlbWVudC5vbih7XHJcbiAgICAgICAgICAgICdmb2N1cy5icy5zZWxlY3QnOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC5vZmYoJ2ZvY3VzLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAnc2hvd24uYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnRcclxuICAgICAgICAgICAgICAgIC52YWwodGhhdC4kZWxlbWVudC52YWwoKSkgLy8gc2V0IHRoZSB2YWx1ZSB0byBoaWRlIHRoZSB2YWxpZGF0aW9uIG1lc3NhZ2UgaW4gQ2hyb21lIHdoZW4gbWVudSBpcyBvcGVuZWRcclxuICAgICAgICAgICAgICAgIC5vZmYoJ3Nob3duLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAncmVuZGVyZWQuYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIC8vIGlmIHNlbGVjdCBpcyBubyBsb25nZXIgaW52YWxpZCwgcmVtb3ZlIHRoZSBicy1pbnZhbGlkIGNsYXNzXHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMudmFsaWRpdHkudmFsaWQpIHRoYXQuJGJ1dHRvbi5yZW1vdmVDbGFzcygnYnMtaW52YWxpZCcpO1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQub2ZmKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLm9uKCdibHVyLmJzLnNlbGVjdCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB0aGF0LiRlbGVtZW50LmZvY3VzKCkuYmx1cigpO1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24ub2ZmKCdibHVyLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbG9hZGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlRHJvcGRvd246IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gT3B0aW9uc1xyXG4gICAgICAvLyBJZiB3ZSBhcmUgbXVsdGlwbGUgb3Igc2hvd1RpY2sgb3B0aW9uIGlzIHNldCwgdGhlbiBhZGQgdGhlIHNob3ctdGljayBjbGFzc1xyXG4gICAgICB2YXIgc2hvd1RpY2sgPSAodGhpcy5tdWx0aXBsZSB8fCB0aGlzLm9wdGlvbnMuc2hvd1RpY2spID8gJyBzaG93LXRpY2snIDogJycsXHJcbiAgICAgICAgICBpbnB1dEdyb3VwID0gdGhpcy4kZWxlbWVudC5wYXJlbnQoKS5oYXNDbGFzcygnaW5wdXQtZ3JvdXAnKSA/ICcgaW5wdXQtZ3JvdXAtYnRuJyA6ICcnLFxyXG4gICAgICAgICAgYXV0b2ZvY3VzID0gdGhpcy5hdXRvZm9jdXMgPyAnIGF1dG9mb2N1cycgOiAnJztcclxuICAgICAgLy8gRWxlbWVudHNcclxuICAgICAgdmFyIGhlYWRlciA9IHRoaXMub3B0aW9ucy5oZWFkZXIgPyAnPGRpdiBjbGFzcz1cInBvcG92ZXItdGl0bGVcIj48YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNsb3NlXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvYnV0dG9uPicgKyB0aGlzLm9wdGlvbnMuaGVhZGVyICsgJzwvZGl2PicgOiAnJztcclxuICAgICAgdmFyIHNlYXJjaGJveCA9IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoID9cclxuICAgICAgJzxkaXYgY2xhc3M9XCJicy1zZWFyY2hib3hcIj4nICtcclxuICAgICAgJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCInICtcclxuICAgICAgKG51bGwgPT09IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoUGxhY2Vob2xkZXIgPyAnJyA6ICcgcGxhY2Vob2xkZXI9XCInICsgaHRtbEVzY2FwZSh0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaFBsYWNlaG9sZGVyKSArICdcIicpICsgJyByb2xlPVwidGV4dGJveFwiIGFyaWEtbGFiZWw9XCJTZWFyY2hcIj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBhY3Rpb25zYm94ID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuYWN0aW9uc0JveCA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtYWN0aW9uc2JveFwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tZ3JvdXAtc20gYnRuLWJsb2NrXCI+JyArXHJcbiAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImFjdGlvbnMtYnRuIGJzLXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5zZWxlY3RBbGxUZXh0ICtcclxuICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJhY3Rpb25zLWJ0biBicy1kZXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5kZXNlbGVjdEFsbFRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkb25lYnV0dG9uID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvbiA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtZG9uZWJ1dHRvblwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tYmxvY2tcIj4nICtcclxuICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tZGVmYXVsdFwiPicgK1xyXG4gICAgICB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvblRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkcm9wID1cclxuICAgICAgICAgICc8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIGJvb3RzdHJhcC1zZWxlY3QnICsgc2hvd1RpY2sgKyBpbnB1dEdyb3VwICsgJ1wiPicgK1xyXG4gICAgICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiJyArIHRoaXMub3B0aW9ucy5zdHlsZUJhc2UgKyAnIGRyb3Bkb3duLXRvZ2dsZVwiIGRhdGEtdG9nZ2xlPVwiZHJvcGRvd25cIicgKyBhdXRvZm9jdXMgKyAnIHJvbGU9XCJidXR0b25cIj4nICtcclxuICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZpbHRlci1vcHRpb24gcHVsbC1sZWZ0XCI+PC9zcGFuPiZuYnNwOycgK1xyXG4gICAgICAgICAgJzxzcGFuIGNsYXNzPVwiYnMtY2FyZXRcIj4nICtcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy50ZW1wbGF0ZS5jYXJldCArXHJcbiAgICAgICAgICAnPC9zcGFuPicgK1xyXG4gICAgICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAgICAgJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51IG9wZW5cIiByb2xlPVwiY29tYm9ib3hcIj4nICtcclxuICAgICAgICAgIGhlYWRlciArXHJcbiAgICAgICAgICBzZWFyY2hib3ggK1xyXG4gICAgICAgICAgYWN0aW9uc2JveCArXHJcbiAgICAgICAgICAnPHVsIGNsYXNzPVwiZHJvcGRvd24tbWVudSBpbm5lclwiIHJvbGU9XCJsaXN0Ym94XCIgYXJpYS1leHBhbmRlZD1cImZhbHNlXCI+JyArXHJcbiAgICAgICAgICAnPC91bD4nICtcclxuICAgICAgICAgIGRvbmVidXR0b24gK1xyXG4gICAgICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAgICAgJzwvZGl2Pic7XHJcblxyXG4gICAgICByZXR1cm4gJChkcm9wKTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlVmlldzogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgJGRyb3AgPSB0aGlzLmNyZWF0ZURyb3Bkb3duKCksXHJcbiAgICAgICAgICBsaSA9IHRoaXMuY3JlYXRlTGkoKTtcclxuXHJcbiAgICAgICRkcm9wLmZpbmQoJ3VsJylbMF0uaW5uZXJIVE1MID0gbGk7XHJcbiAgICAgIHJldHVybiAkZHJvcDtcclxuICAgIH0sXHJcblxyXG4gICAgcmVsb2FkTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gcmVidWlsZFxyXG4gICAgICB2YXIgbGkgPSB0aGlzLmNyZWF0ZUxpKCk7XHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lclswXS5pbm5lckhUTUwgPSBsaTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgX2xpID0gW10sXHJcbiAgICAgICAgICBvcHRJRCA9IDAsXHJcbiAgICAgICAgICB0aXRsZU9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgbGlJbmRleCA9IC0xOyAvLyBpbmNyZW1lbnQgbGlJbmRleCB3aGVuZXZlciBhIG5ldyA8bGk+IGVsZW1lbnQgaXMgY3JlYXRlZCB0byBlbnN1cmUgbGlPYmogaXMgY29ycmVjdFxyXG5cclxuICAgICAgLy8gSGVscGVyIGZ1bmN0aW9uc1xyXG4gICAgICAvKipcclxuICAgICAgICogQHBhcmFtIGNvbnRlbnRcclxuICAgICAgICogQHBhcmFtIFtpbmRleF1cclxuICAgICAgICogQHBhcmFtIFtjbGFzc2VzXVxyXG4gICAgICAgKiBAcGFyYW0gW29wdGdyb3VwXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlTEkgPSBmdW5jdGlvbiAoY29udGVudCwgaW5kZXgsIGNsYXNzZXMsIG9wdGdyb3VwKSB7XHJcbiAgICAgICAgcmV0dXJuICc8bGknICtcclxuICAgICAgICAgICAgKCh0eXBlb2YgY2xhc3NlcyAhPT0gJ3VuZGVmaW5lZCcgJiYgJycgIT09IGNsYXNzZXMpID8gJyBjbGFzcz1cIicgKyBjbGFzc2VzICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICgodHlwZW9mIGluZGV4ICE9PSAndW5kZWZpbmVkJyAmJiBudWxsICE9PSBpbmRleCkgPyAnIGRhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKCh0eXBlb2Ygb3B0Z3JvdXAgIT09ICd1bmRlZmluZWQnICYmIG51bGwgIT09IG9wdGdyb3VwKSA/ICdkYXRhLW9wdGdyb3VwPVwiJyArIG9wdGdyb3VwICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICc+JyArIGNvbnRlbnQgKyAnPC9saT4nO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgLyoqXHJcbiAgICAgICAqIEBwYXJhbSB0ZXh0XHJcbiAgICAgICAqIEBwYXJhbSBbY2xhc3Nlc11cclxuICAgICAgICogQHBhcmFtIFtpbmxpbmVdXHJcbiAgICAgICAqIEBwYXJhbSBbdG9rZW5zXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlQSA9IGZ1bmN0aW9uICh0ZXh0LCBjbGFzc2VzLCBpbmxpbmUsIHRva2Vucykge1xyXG4gICAgICAgIHJldHVybiAnPGEgdGFiaW5kZXg9XCIwXCInICtcclxuICAgICAgICAgICAgKHR5cGVvZiBjbGFzc2VzICE9PSAndW5kZWZpbmVkJyA/ICcgY2xhc3M9XCInICsgY2xhc3NlcyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAoaW5saW5lID8gJyBzdHlsZT1cIicgKyBpbmxpbmUgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplID8gJyBkYXRhLW5vcm1hbGl6ZWQtdGV4dD1cIicgKyBub3JtYWxpemVUb0Jhc2UoaHRtbEVzY2FwZSgkKHRleHQpLmh0bWwoKSkpICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICh0eXBlb2YgdG9rZW5zICE9PSAndW5kZWZpbmVkJyB8fCB0b2tlbnMgIT09IG51bGwgPyAnIGRhdGEtdG9rZW5zPVwiJyArIHRva2VucyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAnIHJvbGU9XCJvcHRpb25cIj4nICsgdGV4dCArXHJcbiAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyB0aGF0Lm9wdGlvbnMudGlja0ljb24gKyAnIGNoZWNrLW1hcmtcIj48L3NwYW4+JyArXHJcbiAgICAgICAgICAgICc8L2E+JztcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMudGl0bGUgJiYgIXRoaXMubXVsdGlwbGUpIHtcclxuICAgICAgICAvLyB0aGlzIG9wdGlvbiBkb2Vzbid0IGNyZWF0ZSBhIG5ldyA8bGk+IGVsZW1lbnQsIGJ1dCBkb2VzIGFkZCBhIG5ldyBvcHRpb24sIHNvIGxpSW5kZXggaXMgZGVjcmVhc2VkXHJcbiAgICAgICAgLy8gc2luY2UgbGlPYmogaXMgcmVjYWxjdWxhdGVkIG9uIGV2ZXJ5IHJlZnJlc2gsIGxpSW5kZXggbmVlZHMgdG8gYmUgZGVjcmVhc2VkIGV2ZW4gaWYgdGhlIHRpdGxlT3B0aW9uIGlzIGFscmVhZHkgYXBwZW5kZWRcclxuICAgICAgICBsaUluZGV4LS07XHJcblxyXG4gICAgICAgIGlmICghdGhpcy4kZWxlbWVudC5maW5kKCcuYnMtdGl0bGUtb3B0aW9uJykubGVuZ3RoKSB7XHJcbiAgICAgICAgICAvLyBVc2UgbmF0aXZlIEpTIHRvIHByZXBlbmQgb3B0aW9uIChmYXN0ZXIpXHJcbiAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuJGVsZW1lbnRbMF07XHJcbiAgICAgICAgICB0aXRsZU9wdGlvbi5jbGFzc05hbWUgPSAnYnMtdGl0bGUtb3B0aW9uJztcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLmlubmVySFRNTCA9IHRoaXMub3B0aW9ucy50aXRsZTtcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLnZhbHVlID0gJyc7XHJcbiAgICAgICAgICBlbGVtZW50Lmluc2VydEJlZm9yZSh0aXRsZU9wdGlvbiwgZWxlbWVudC5maXJzdENoaWxkKTtcclxuICAgICAgICAgIC8vIENoZWNrIGlmIHNlbGVjdGVkIG9yIGRhdGEtc2VsZWN0ZWQgYXR0cmlidXRlIGlzIGFscmVhZHkgc2V0IG9uIGFuIG9wdGlvbi4gSWYgbm90LCBzZWxlY3QgdGhlIHRpdGxlT3B0aW9uIG9wdGlvbi5cclxuICAgICAgICAgIC8vIHRoZSBzZWxlY3RlZCBpdGVtIG1heSBoYXZlIGJlZW4gY2hhbmdlZCBieSB1c2VyIG9yIHByb2dyYW1tYXRpY2FsbHkgYmVmb3JlIHRoZSBib290c3RyYXAgc2VsZWN0IHBsdWdpbiBydW5zLFxyXG4gICAgICAgICAgLy8gaWYgc28sIHRoZSBzZWxlY3Qgd2lsbCBoYXZlIHRoZSBkYXRhLXNlbGVjdGVkIGF0dHJpYnV0ZVxyXG4gICAgICAgICAgdmFyICRvcHQgPSAkKGVsZW1lbnQub3B0aW9uc1tlbGVtZW50LnNlbGVjdGVkSW5kZXhdKTtcclxuICAgICAgICAgIGlmICgkb3B0LmF0dHIoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCAmJiB0aGlzLiRlbGVtZW50LmRhdGEoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aXRsZU9wdGlvbi5zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgJHNlbGVjdE9wdGlvbnMuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBsaUluZGV4Kys7XHJcblxyXG4gICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygnYnMtdGl0bGUtb3B0aW9uJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gR2V0IHRoZSBjbGFzcyBhbmQgdGV4dCBmb3IgdGhlIG9wdGlvblxyXG4gICAgICAgIHZhciBvcHRpb25DbGFzcyA9IHRoaXMuY2xhc3NOYW1lIHx8ICcnLFxyXG4gICAgICAgICAgICBpbmxpbmUgPSBodG1sRXNjYXBlKHRoaXMuc3R5bGUuY3NzVGV4dCksXHJcbiAgICAgICAgICAgIHRleHQgPSAkdGhpcy5kYXRhKCdjb250ZW50JykgPyAkdGhpcy5kYXRhKCdjb250ZW50JykgOiAkdGhpcy5odG1sKCksXHJcbiAgICAgICAgICAgIHRva2VucyA9ICR0aGlzLmRhdGEoJ3Rva2VucycpID8gJHRoaXMuZGF0YSgndG9rZW5zJykgOiBudWxsLFxyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gdHlwZW9mICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkdGhpcy5kYXRhKCdzdWJ0ZXh0JykgKyAnPC9zbWFsbD4nIDogJycsXHJcbiAgICAgICAgICAgIGljb24gPSB0eXBlb2YgJHRoaXMuZGF0YSgnaWNvbicpICE9PSAndW5kZWZpbmVkJyA/ICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9zcGFuPiAnIDogJycsXHJcbiAgICAgICAgICAgICRwYXJlbnQgPSAkdGhpcy5wYXJlbnQoKSxcclxuICAgICAgICAgICAgaXNPcHRncm91cCA9ICRwYXJlbnRbMF0udGFnTmFtZSA9PT0gJ09QVEdST1VQJyxcclxuICAgICAgICAgICAgaXNPcHRncm91cERpc2FibGVkID0gaXNPcHRncm91cCAmJiAkcGFyZW50WzBdLmRpc2FibGVkLFxyXG4gICAgICAgICAgICBpc0Rpc2FibGVkID0gdGhpcy5kaXNhYmxlZCB8fCBpc09wdGdyb3VwRGlzYWJsZWQsXHJcbiAgICAgICAgICAgIHByZXZIaWRkZW5JbmRleDtcclxuXHJcbiAgICAgICAgaWYgKGljb24gIT09ICcnICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgIGljb24gPSAnPHNwYW4+JyArIGljb24gKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAoaXNEaXNhYmxlZCAmJiAhaXNPcHRncm91cCB8fCBpc09wdGdyb3VwRGlzYWJsZWQpKSB7XHJcbiAgICAgICAgICAvLyBzZXQgcHJldkhpZGRlbkluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBoaWRkZW4gb3B0aW9uIGluIGEgZ3JvdXAgb2YgaGlkZGVuIG9wdGlvbnNcclxuICAgICAgICAgIC8vIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IGEgZGl2aWRlciBzaG91bGQgYmUgcGxhY2VkIGFmdGVyIGFuIG9wdGdyb3VwIGlmIHRoZXJlIGFyZVxyXG4gICAgICAgICAgLy8gaGlkZGVuIG9wdGlvbnMgYmV0d2VlbiB0aGUgb3B0Z3JvdXAgYW5kIHRoZSBmaXJzdCB2aXNpYmxlIG9wdGlvblxyXG4gICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcbiAgICAgICAgICAkdGhpcy5uZXh0KCkuZGF0YSgncHJldkhpZGRlbkluZGV4JywgKHByZXZIaWRkZW5JbmRleCAhPT0gdW5kZWZpbmVkID8gcHJldkhpZGRlbkluZGV4IDogaW5kZXgpKTtcclxuXHJcbiAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoISR0aGlzLmRhdGEoJ2NvbnRlbnQnKSkge1xyXG4gICAgICAgICAgLy8gUHJlcGVuZCBhbnkgaWNvbiBhbmQgYXBwZW5kIGFueSBzdWJ0ZXh0IHRvIHRoZSBtYWluIHRleHQuXHJcbiAgICAgICAgICB0ZXh0ID0gaWNvbiArICc8c3BhbiBjbGFzcz1cInRleHRcIj4nICsgdGV4dCArIHN1YnRleHQgKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaXNPcHRncm91cCAmJiAkdGhpcy5kYXRhKCdkaXZpZGVyJykgIT09IHRydWUpIHtcclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuaGlkZURpc2FibGVkICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgaWYgKCRwYXJlbnQuZGF0YSgnYWxsT3B0aW9uc0Rpc2FibGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIHZhciAkb3B0aW9ucyA9ICRwYXJlbnQuY2hpbGRyZW4oKTtcclxuICAgICAgICAgICAgICAkcGFyZW50LmRhdGEoJ2FsbE9wdGlvbnNEaXNhYmxlZCcsICRvcHRpb25zLmZpbHRlcignOmRpc2FibGVkJykubGVuZ3RoID09PSAkb3B0aW9ucy5sZW5ndGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5kYXRhKCdhbGxPcHRpb25zRGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgICAgIGxpSW5kZXgtLTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB2YXIgb3B0R3JvdXBDbGFzcyA9ICcgJyArICRwYXJlbnRbMF0uY2xhc3NOYW1lIHx8ICcnO1xyXG5cclxuICAgICAgICAgIGlmICgkdGhpcy5pbmRleCgpID09PSAwKSB7IC8vIElzIGl0IHRoZSBmaXJzdCBvcHRpb24gb2YgdGhlIG9wdGdyb3VwP1xyXG4gICAgICAgICAgICBvcHRJRCArPSAxO1xyXG5cclxuICAgICAgICAgICAgLy8gR2V0IHRoZSBvcHQgZ3JvdXAgbGFiZWxcclxuICAgICAgICAgICAgdmFyIGxhYmVsID0gJHBhcmVudFswXS5sYWJlbCxcclxuICAgICAgICAgICAgICAgIGxhYmVsU3VidGV4dCA9IHR5cGVvZiAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPicgOiAnJyxcclxuICAgICAgICAgICAgICAgIGxhYmVsSWNvbiA9ICRwYXJlbnQuZGF0YSgnaWNvbicpID8gJzxzcGFuIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArICRwYXJlbnQuZGF0YSgnaWNvbicpICsgJ1wiPjwvc3Bhbj4gJyA6ICcnO1xyXG5cclxuICAgICAgICAgICAgbGFiZWwgPSBsYWJlbEljb24gKyAnPHNwYW4gY2xhc3M9XCJ0ZXh0XCI+JyArIGh0bWxFc2NhcGUobGFiZWwpICsgbGFiZWxTdWJ0ZXh0ICsgJzwvc3Bhbj4nO1xyXG5cclxuICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAwICYmIF9saS5sZW5ndGggPiAwKSB7IC8vIElzIGl0IE5PVCB0aGUgZmlyc3Qgb3B0aW9uIG9mIHRoZSBzZWxlY3QgJiYgYXJlIHRoZXJlIGVsZW1lbnRzIGluIHRoZSBkcm9wZG93bj9cclxuICAgICAgICAgICAgICBsaUluZGV4Kys7XHJcbiAgICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGlJbmRleCsrO1xyXG4gICAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGxhYmVsLCBudWxsLCAnZHJvcGRvd24taGVhZGVyJyArIG9wdEdyb3VwQ2xhc3MsIG9wdElEKSk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCAnb3B0ICcgKyBvcHRpb25DbGFzcyArIG9wdEdyb3VwQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICcnLCBvcHRJRCkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuZGF0YSgnZGl2aWRlcicpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKCcnLCBpbmRleCwgJ2RpdmlkZXInKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdoaWRkZW4nKSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgLy8gc2V0IHByZXZIaWRkZW5JbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgaGlkZGVuIG9wdGlvbiBpbiBhIGdyb3VwIG9mIGhpZGRlbiBvcHRpb25zXHJcbiAgICAgICAgICAvLyB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCBhIGRpdmlkZXIgc2hvdWxkIGJlIHBsYWNlZCBhZnRlciBhbiBvcHRncm91cCBpZiB0aGVyZSBhcmVcclxuICAgICAgICAgIC8vIGhpZGRlbiBvcHRpb25zIGJldHdlZW4gdGhlIG9wdGdyb3VwIGFuZCB0aGUgZmlyc3QgdmlzaWJsZSBvcHRpb25cclxuICAgICAgICAgIHByZXZIaWRkZW5JbmRleCA9ICR0aGlzLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcpO1xyXG4gICAgICAgICAgJHRoaXMubmV4dCgpLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcsIChwcmV2SGlkZGVuSW5kZXggIT09IHVuZGVmaW5lZCA/IHByZXZIaWRkZW5JbmRleCA6IGluZGV4KSk7XHJcblxyXG4gICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSShnZW5lcmF0ZUEodGV4dCwgb3B0aW9uQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICdoaWRkZW4gaXMtaGlkZGVuJykpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB2YXIgc2hvd0RpdmlkZXIgPSB0aGlzLnByZXZpb3VzRWxlbWVudFNpYmxpbmcgJiYgdGhpcy5wcmV2aW91c0VsZW1lbnRTaWJsaW5nLnRhZ05hbWUgPT09ICdPUFRHUk9VUCc7XHJcblxyXG4gICAgICAgICAgLy8gaWYgcHJldmlvdXMgZWxlbWVudCBpcyBub3QgYW4gb3B0Z3JvdXAgYW5kIGhpZGVEaXNhYmxlZCBpcyB0cnVlXHJcbiAgICAgICAgICBpZiAoIXNob3dEaXZpZGVyICYmIHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcblxyXG4gICAgICAgICAgICBpZiAocHJldkhpZGRlbkluZGV4ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAvLyBzZWxlY3QgdGhlIGVsZW1lbnQgKipiZWZvcmUqKiB0aGUgZmlyc3QgaGlkZGVuIGVsZW1lbnQgaW4gdGhlIGdyb3VwXHJcbiAgICAgICAgICAgICAgdmFyIHByZXZIaWRkZW4gPSAkc2VsZWN0T3B0aW9ucy5lcShwcmV2SGlkZGVuSW5kZXgpWzBdLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XHJcbiAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgaWYgKHByZXZIaWRkZW4gJiYgcHJldkhpZGRlbi50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmICFwcmV2SGlkZGVuLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICBzaG93RGl2aWRlciA9IHRydWU7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHNob3dEaXZpZGVyKSB7XHJcbiAgICAgICAgICAgIGxpSW5kZXgrKztcclxuICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCBvcHRpb25DbGFzcywgaW5saW5lLCB0b2tlbnMpLCBpbmRleCkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC5saU9ialtpbmRleF0gPSBsaUluZGV4O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vSWYgd2UgYXJlIG5vdCBtdWx0aXBsZSwgd2UgZG9uJ3QgaGF2ZSBhIHNlbGVjdGVkIGl0ZW0sIGFuZCB3ZSBkb24ndCBoYXZlIGEgdGl0bGUsIHNlbGVjdCB0aGUgZmlyc3QgZWxlbWVudCBzbyBzb21ldGhpbmcgaXMgc2V0IGluIHRoZSBidXR0b25cclxuICAgICAgaWYgKCF0aGlzLm11bHRpcGxlICYmIHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykubGVuZ3RoID09PSAwICYmICF0aGlzLm9wdGlvbnMudGl0bGUpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLmVxKDApLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSkuYXR0cignc2VsZWN0ZWQnLCAnc2VsZWN0ZWQnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIF9saS5qb2luKCcnKTtcclxuICAgIH0sXHJcblxyXG4gICAgZmluZExpczogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kbGlzID09IG51bGwpIHRoaXMuJGxpcyA9IHRoaXMuJG1lbnUuZmluZCgnbGknKTtcclxuICAgICAgcmV0dXJuIHRoaXMuJGxpcztcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3VwZGF0ZUxpXSBkZWZhdWx0cyB0byB0cnVlXHJcbiAgICAgKi9cclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKHVwZGF0ZUxpKSB7XHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgIG5vdERpc2FibGVkLFxyXG4gICAgICAgICAgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgLy9VcGRhdGUgdGhlIExJIHRvIG1hdGNoIHRoZSBTRUxFQ1RcclxuICAgICAgaWYgKHVwZGF0ZUxpICE9PSBmYWxzZSkge1xyXG4gICAgICAgICRzZWxlY3RPcHRpb25zLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XHJcbiAgICAgICAgICB2YXIgJGxpcyA9IHRoYXQuZmluZExpcygpLmVxKHRoYXQubGlPYmpbaW5kZXhdKTtcclxuXHJcbiAgICAgICAgICB0aGF0LnNldERpc2FibGVkKGluZGV4LCB0aGlzLmRpc2FibGVkIHx8IHRoaXMucGFyZW50Tm9kZS50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmIHRoaXMucGFyZW50Tm9kZS5kaXNhYmxlZCwgJGxpcyk7XHJcbiAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGluZGV4LCB0aGlzLnNlbGVjdGVkLCAkbGlzKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy50b2dnbGVQbGFjZWhvbGRlcigpO1xyXG5cclxuICAgICAgdGhpcy50YWJJbmRleCgpO1xyXG5cclxuICAgICAgdmFyIHNlbGVjdGVkSXRlbXMgPSAkc2VsZWN0T3B0aW9ucy5tYXAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkKSB7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLnBhcmVudE5vZGUudGFnTmFtZSA9PT0gJ09QVEdST1VQJyAmJiB0aGlzLnBhcmVudE5vZGUuZGlzYWJsZWQpKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICAgICBpY29uID0gJHRoaXMuZGF0YSgnaWNvbicpICYmIHRoYXQub3B0aW9ucy5zaG93SWNvbiA/ICc8aSBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9pPiAnIDogJycsXHJcbiAgICAgICAgICAgICAgc3VidGV4dDtcclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLnNob3dTdWJ0ZXh0ICYmICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAmJiAhdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JyArICR0aGlzLmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPic7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyc7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAodHlwZW9mICR0aGlzLmF0dHIoJ3RpdGxlJykgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5hdHRyKCd0aXRsZScpO1xyXG4gICAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdjb250ZW50JykgJiYgdGhhdC5vcHRpb25zLnNob3dDb250ZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5kYXRhKCdjb250ZW50JykudG9TdHJpbmcoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpY29uICsgJHRoaXMuaHRtbCgpICsgc3VidGV4dDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pLnRvQXJyYXkoKTtcclxuXHJcbiAgICAgIC8vRml4ZXMgaXNzdWUgaW4gSUUxMCBvY2N1cnJpbmcgd2hlbiBubyBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZCBhbmQgYXQgbGVhc3Qgb25lIG9wdGlvbiBpcyBkaXNhYmxlZFxyXG4gICAgICAvL0NvbnZlcnQgYWxsIHRoZSB2YWx1ZXMgaW50byBhIGNvbW1hIGRlbGltaXRlZCBzdHJpbmdcclxuICAgICAgdmFyIHRpdGxlID0gIXRoaXMubXVsdGlwbGUgPyBzZWxlY3RlZEl0ZW1zWzBdIDogc2VsZWN0ZWRJdGVtcy5qb2luKHRoaXMub3B0aW9ucy5tdWx0aXBsZVNlcGFyYXRvcik7XHJcblxyXG4gICAgICAvL0lmIHRoaXMgaXMgbXVsdGkgc2VsZWN0LCBhbmQgdGhlIHNlbGVjdFRleHQgdHlwZSBpcyBjb3VudCwgdGhlIHNob3cgMSBvZiAyIHNlbGVjdGVkIGV0Yy4uXHJcbiAgICAgIGlmICh0aGlzLm11bHRpcGxlICYmIHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuaW5kZXhPZignY291bnQnKSA+IC0xKSB7XHJcbiAgICAgICAgdmFyIG1heCA9IHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuc3BsaXQoJz4nKTtcclxuICAgICAgICBpZiAoKG1heC5sZW5ndGggPiAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID4gbWF4WzFdKSB8fCAobWF4Lmxlbmd0aCA9PSAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID49IDIpKSB7XHJcbiAgICAgICAgICBub3REaXNhYmxlZCA9IHRoaXMub3B0aW9ucy5oaWRlRGlzYWJsZWQgPyAnLCBbZGlzYWJsZWRdJyA6ICcnO1xyXG4gICAgICAgICAgdmFyIHRvdGFsQ291bnQgPSAkc2VsZWN0T3B0aW9ucy5ub3QoJ1tkYXRhLWRpdmlkZXI9XCJ0cnVlXCJdLCBbZGF0YS1oaWRkZW49XCJ0cnVlXCJdJyArIG5vdERpc2FibGVkKS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgdHI4blRleHQgPSAodHlwZW9mIHRoaXMub3B0aW9ucy5jb3VudFNlbGVjdGVkVGV4dCA9PT0gJ2Z1bmN0aW9uJykgPyB0aGlzLm9wdGlvbnMuY291bnRTZWxlY3RlZFRleHQoc2VsZWN0ZWRJdGVtcy5sZW5ndGgsIHRvdGFsQ291bnQpIDogdGhpcy5vcHRpb25zLmNvdW50U2VsZWN0ZWRUZXh0O1xyXG4gICAgICAgICAgdGl0bGUgPSB0cjhuVGV4dC5yZXBsYWNlKCd7MH0nLCBzZWxlY3RlZEl0ZW1zLmxlbmd0aC50b1N0cmluZygpKS5yZXBsYWNlKCd7MX0nLCB0b3RhbENvdW50LnRvU3RyaW5nKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2VsZWN0ZWRUZXh0Rm9ybWF0ID09ICdzdGF0aWMnKSB7XHJcbiAgICAgICAgdGl0bGUgPSB0aGlzLm9wdGlvbnMudGl0bGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vSWYgd2UgZG9udCBoYXZlIGEgdGl0bGUsIHRoZW4gdXNlIHRoZSBkZWZhdWx0LCBvciBpZiBub3RoaW5nIGlzIHNldCBhdCBhbGwsIHVzZSB0aGUgbm90IHNlbGVjdGVkIHRleHRcclxuICAgICAgaWYgKCF0aXRsZSkge1xyXG4gICAgICAgIHRpdGxlID0gdHlwZW9mIHRoaXMub3B0aW9ucy50aXRsZSAhPT0gJ3VuZGVmaW5lZCcgPyB0aGlzLm9wdGlvbnMudGl0bGUgOiB0aGlzLm9wdGlvbnMubm9uZVNlbGVjdGVkVGV4dDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy9zdHJpcCBhbGwgSFRNTCB0YWdzIGFuZCB0cmltIHRoZSByZXN1bHQsIHRoZW4gdW5lc2NhcGUgYW55IGVzY2FwZWQgdGFnc1xyXG4gICAgICB0aGlzLiRidXR0b24uYXR0cigndGl0bGUnLCBodG1sVW5lc2NhcGUoJC50cmltKHRpdGxlLnJlcGxhY2UoLzxbXj5dKj4/L2csICcnKSkpKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLmNoaWxkcmVuKCcuZmlsdGVyLW9wdGlvbicpLmh0bWwodGl0bGUpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3N0eWxlXVxyXG4gICAgICogQHBhcmFtIFtzdGF0dXNdXHJcbiAgICAgKi9cclxuICAgIHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUsIHN0YXR1cykge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5hdHRyKCdjbGFzcycpKSB7XHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5hZGRDbGFzcyh0aGlzLiRlbGVtZW50LmF0dHIoJ2NsYXNzJykucmVwbGFjZSgvc2VsZWN0cGlja2VyfG1vYmlsZS1kZXZpY2V8YnMtc2VsZWN0LWhpZGRlbnx2YWxpZGF0ZVxcWy4qXFxdL2dpLCAnJykpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgYnV0dG9uQ2xhc3MgPSBzdHlsZSA/IHN0eWxlIDogdGhpcy5vcHRpb25zLnN0eWxlO1xyXG5cclxuICAgICAgaWYgKHN0YXR1cyA9PSAnYWRkJykge1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcyhidXR0b25DbGFzcyk7XHJcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID09ICdyZW1vdmUnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLnJlbW92ZUNsYXNzKGJ1dHRvbkNsYXNzKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLiRidXR0b24ucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLnN0eWxlKTtcclxuICAgICAgICB0aGlzLiRidXR0b24uYWRkQ2xhc3MoYnV0dG9uQ2xhc3MpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGxpSGVpZ2h0OiBmdW5jdGlvbiAocmVmcmVzaCkge1xyXG4gICAgICBpZiAoIXJlZnJlc2ggJiYgKHRoaXMub3B0aW9ucy5zaXplID09PSBmYWxzZSB8fCB0aGlzLnNpemVJbmZvKSkgcmV0dXJuO1xyXG5cclxuICAgICAgdmFyIG5ld0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnVJbm5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3VsJyksXHJcbiAgICAgICAgICBkaXZpZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGxpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyksXHJcbiAgICAgICAgICB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLFxyXG4gICAgICAgICAgaGVhZGVyID0gdGhpcy5vcHRpb25zLmhlYWRlciAmJiB0aGlzLiRtZW51LmZpbmQoJy5wb3BvdmVyLXRpdGxlJykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLnBvcG92ZXItdGl0bGUnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgc2VhcmNoID0gdGhpcy5vcHRpb25zLmxpdmVTZWFyY2ggPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSA6IG51bGwsXHJcbiAgICAgICAgICBhY3Rpb25zID0gdGhpcy5vcHRpb25zLmFjdGlvbnNCb3ggJiYgdGhpcy5tdWx0aXBsZSAmJiB0aGlzLiRtZW51LmZpbmQoJy5icy1hY3Rpb25zYm94JykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLmJzLWFjdGlvbnNib3gnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbiA9IHRoaXMub3B0aW9ucy5kb25lQnV0dG9uICYmIHRoaXMubXVsdGlwbGUgJiYgdGhpcy4kbWVudS5maW5kKCcuYnMtZG9uZWJ1dHRvbicpLmxlbmd0aCA+IDAgPyB0aGlzLiRtZW51LmZpbmQoJy5icy1kb25lYnV0dG9uJylbMF0uY2xvbmVOb2RlKHRydWUpIDogbnVsbDtcclxuXHJcbiAgICAgIHRleHQuY2xhc3NOYW1lID0gJ3RleHQnO1xyXG4gICAgICBuZXdFbGVtZW50LmNsYXNzTmFtZSA9IHRoaXMuJG1lbnVbMF0ucGFyZW50Tm9kZS5jbGFzc05hbWUgKyAnIG9wZW4nO1xyXG4gICAgICBtZW51LmNsYXNzTmFtZSA9ICdkcm9wZG93bi1tZW51IG9wZW4nO1xyXG4gICAgICBtZW51SW5uZXIuY2xhc3NOYW1lID0gJ2Ryb3Bkb3duLW1lbnUgaW5uZXInO1xyXG4gICAgICBkaXZpZGVyLmNsYXNzTmFtZSA9ICdkaXZpZGVyJztcclxuXHJcbiAgICAgIHRleHQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJ0lubmVyIHRleHQnKSk7XHJcbiAgICAgIGEuYXBwZW5kQ2hpbGQodGV4dCk7XHJcbiAgICAgIGxpLmFwcGVuZENoaWxkKGEpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQobGkpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQoZGl2aWRlcik7XHJcbiAgICAgIGlmIChoZWFkZXIpIG1lbnUuYXBwZW5kQ2hpbGQoaGVhZGVyKTtcclxuICAgICAgaWYgKHNlYXJjaCkge1xyXG4gICAgICAgIHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcbiAgICAgICAgc2VhcmNoLmNsYXNzTmFtZSA9ICdicy1zZWFyY2hib3gnO1xyXG4gICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICdmb3JtLWNvbnRyb2wnO1xyXG4gICAgICAgIHNlYXJjaC5hcHBlbmRDaGlsZChpbnB1dCk7XHJcbiAgICAgICAgbWVudS5hcHBlbmRDaGlsZChzZWFyY2gpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChhY3Rpb25zKSBtZW51LmFwcGVuZENoaWxkKGFjdGlvbnMpO1xyXG4gICAgICBtZW51LmFwcGVuZENoaWxkKG1lbnVJbm5lcik7XHJcbiAgICAgIGlmIChkb25lQnV0dG9uKSBtZW51LmFwcGVuZENoaWxkKGRvbmVCdXR0b24pO1xyXG4gICAgICBuZXdFbGVtZW50LmFwcGVuZENoaWxkKG1lbnUpO1xyXG5cclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgIHZhciBsaUhlaWdodCA9IGEub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gaGVhZGVyID8gaGVhZGVyLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSBzZWFyY2ggPyBzZWFyY2gub2Zmc2V0SGVpZ2h0IDogMCxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSBhY3Rpb25zID8gYWN0aW9ucy5vZmZzZXRIZWlnaHQgOiAwLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbkhlaWdodCA9IGRvbmVCdXR0b24gPyBkb25lQnV0dG9uLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBkaXZpZGVySGVpZ2h0ID0gJChkaXZpZGVyKS5vdXRlckhlaWdodCh0cnVlKSxcclxuICAgICAgICAgIC8vIGZhbGwgYmFjayB0byBqUXVlcnkgaWYgZ2V0Q29tcHV0ZWRTdHlsZSBpcyBub3Qgc3VwcG9ydGVkXHJcbiAgICAgICAgICBtZW51U3R5bGUgPSB0eXBlb2YgZ2V0Q29tcHV0ZWRTdHlsZSA9PT0gJ2Z1bmN0aW9uJyA/IGdldENvbXB1dGVkU3R5bGUobWVudSkgOiBmYWxzZSxcclxuICAgICAgICAgICRtZW51ID0gbWVudVN0eWxlID8gbnVsbCA6ICQobWVudSksXHJcbiAgICAgICAgICBtZW51UGFkZGluZyA9IHtcclxuICAgICAgICAgICAgdmVydDogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdUb3AgOiAkbWVudS5jc3MoJ3BhZGRpbmdUb3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUucGFkZGluZ0JvdHRvbSA6ICRtZW51LmNzcygncGFkZGluZ0JvdHRvbScpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJUb3BXaWR0aCA6ICRtZW51LmNzcygnYm9yZGVyVG9wV2lkdGgnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUuYm9yZGVyQm90dG9tV2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckJvdHRvbVdpZHRoJykpLFxyXG4gICAgICAgICAgICBob3JpejogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdMZWZ0IDogJG1lbnUuY3NzKCdwYWRkaW5nTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5wYWRkaW5nUmlnaHQgOiAkbWVudS5jc3MoJ3BhZGRpbmdSaWdodCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJMZWZ0V2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJSaWdodFdpZHRoIDogJG1lbnUuY3NzKCdib3JkZXJSaWdodFdpZHRoJykpXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9ICB7XHJcbiAgICAgICAgICAgIHZlcnQ6IG1lbnVQYWRkaW5nLnZlcnQgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luVG9wIDogJG1lbnUuY3NzKCdtYXJnaW5Ub3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luQm90dG9tIDogJG1lbnUuY3NzKCdtYXJnaW5Cb3R0b20nKSkgKyAyLFxyXG4gICAgICAgICAgICBob3JpejogbWVudVBhZGRpbmcuaG9yaXogK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luTGVmdCA6ICRtZW51LmNzcygnbWFyZ2luTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5SaWdodCA6ICRtZW51LmNzcygnbWFyZ2luUmlnaHQnKSkgKyAyXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgdGhpcy5zaXplSW5mbyA9IHtcclxuICAgICAgICBsaUhlaWdodDogbGlIZWlnaHQsXHJcbiAgICAgICAgaGVhZGVySGVpZ2h0OiBoZWFkZXJIZWlnaHQsXHJcbiAgICAgICAgc2VhcmNoSGVpZ2h0OiBzZWFyY2hIZWlnaHQsXHJcbiAgICAgICAgYWN0aW9uc0hlaWdodDogYWN0aW9uc0hlaWdodCxcclxuICAgICAgICBkb25lQnV0dG9uSGVpZ2h0OiBkb25lQnV0dG9uSGVpZ2h0LFxyXG4gICAgICAgIGRpdmlkZXJIZWlnaHQ6IGRpdmlkZXJIZWlnaHQsXHJcbiAgICAgICAgbWVudVBhZGRpbmc6IG1lbnVQYWRkaW5nLFxyXG4gICAgICAgIG1lbnVFeHRyYXM6IG1lbnVFeHRyYXNcclxuICAgICAgfTtcclxuICAgIH0sXHJcblxyXG4gICAgc2V0U2l6ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLmZpbmRMaXMoKTtcclxuICAgICAgdGhpcy5saUhlaWdodCgpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5oZWFkZXIpIHRoaXMuJG1lbnUuY3NzKCdwYWRkaW5nLXRvcCcsIDApO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnNpemUgPT09IGZhbHNlKSByZXR1cm47XHJcblxyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkbWVudSA9IHRoaXMuJG1lbnUsXHJcbiAgICAgICAgICAkbWVudUlubmVyID0gdGhpcy4kbWVudUlubmVyLFxyXG4gICAgICAgICAgJHdpbmRvdyA9ICQod2luZG93KSxcclxuICAgICAgICAgIHNlbGVjdEhlaWdodCA9IHRoaXMuJG5ld0VsZW1lbnRbMF0ub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgc2VsZWN0V2lkdGggPSB0aGlzLiRuZXdFbGVtZW50WzBdLm9mZnNldFdpZHRoLFxyXG4gICAgICAgICAgbGlIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydsaUhlaWdodCddLFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snaGVhZGVySGVpZ2h0J10sXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydzZWFyY2hIZWlnaHQnXSxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydhY3Rpb25zSGVpZ2h0J10sXHJcbiAgICAgICAgICBkb25lQnV0dG9uSGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZG9uZUJ1dHRvbkhlaWdodCddLFxyXG4gICAgICAgICAgZGl2SGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZGl2aWRlckhlaWdodCddLFxyXG4gICAgICAgICAgbWVudVBhZGRpbmcgPSB0aGlzLnNpemVJbmZvWydtZW51UGFkZGluZyddLFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9IHRoaXMuc2l6ZUluZm9bJ21lbnVFeHRyYXMnXSxcclxuICAgICAgICAgIG5vdERpc2FibGVkID0gdGhpcy5vcHRpb25zLmhpZGVEaXNhYmxlZCA/ICcuZGlzYWJsZWQnIDogJycsXHJcbiAgICAgICAgICBtZW51SGVpZ2h0LFxyXG4gICAgICAgICAgbWVudVdpZHRoLFxyXG4gICAgICAgICAgZ2V0SGVpZ2h0LFxyXG4gICAgICAgICAgZ2V0V2lkdGgsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRCb3QsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0LFxyXG4gICAgICAgICAgc2VsZWN0T2Zmc2V0UmlnaHQsXHJcbiAgICAgICAgICBnZXRQb3MgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgdmFyIHBvcyA9IHRoYXQuJG5ld0VsZW1lbnQub2Zmc2V0KCksXHJcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyID0gJCh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSxcclxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclBvcztcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyICYmICEkY29udGFpbmVyLmlzKCdib2R5JykpIHtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MgPSAkY29udGFpbmVyLm9mZnNldCgpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy50b3AgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlclRvcFdpZHRoJykpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy5sZWZ0ICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJMZWZ0V2lkdGgnKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdmFyIHdpblBhZCA9IHRoYXQub3B0aW9ucy53aW5kb3dQYWRkaW5nO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgPSBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCAtICR3aW5kb3cuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldEJvdCA9ICR3aW5kb3cuaGVpZ2h0KCkgLSBzZWxlY3RPZmZzZXRUb3AgLSBzZWxlY3RIZWlnaHQgLSBjb250YWluZXJQb3MudG9wIC0gd2luUGFkWzJdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0ID0gcG9zLmxlZnQgLSBjb250YWluZXJQb3MubGVmdCAtICR3aW5kb3cuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRSaWdodCA9ICR3aW5kb3cud2lkdGgoKSAtIHNlbGVjdE9mZnNldExlZnQgLSBzZWxlY3RXaWR0aCAtIGNvbnRhaW5lclBvcy5sZWZ0IC0gd2luUGFkWzFdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgLT0gd2luUGFkWzBdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0IC09IHdpblBhZFszXTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICBnZXRQb3MoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSA9PT0gJ2F1dG8nKSB7XHJcbiAgICAgICAgdmFyIGdldFNpemUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB2YXIgbWluSGVpZ2h0LFxyXG4gICAgICAgICAgICAgIGhhc0NsYXNzID0gZnVuY3Rpb24gKGNsYXNzTmFtZSwgaW5jbHVkZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluY2x1ZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChlbGVtZW50LmNsYXNzTGlzdCA/IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSkgOiAkKGVsZW1lbnQpLmhhc0NsYXNzKGNsYXNzTmFtZSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhKGVsZW1lbnQuY2xhc3NMaXN0ID8gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSA6ICQoZWxlbWVudCkuaGFzQ2xhc3MoY2xhc3NOYW1lKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgIGxpcyA9IHRoYXQuJG1lbnVJbm5lclswXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbGknKSxcclxuICAgICAgICAgICAgICBsaXNWaXNpYmxlID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXMsIGhhc0NsYXNzKCdoaWRkZW4nLCBmYWxzZSkpIDogdGhhdC4kbGlzLm5vdCgnLmhpZGRlbicpLFxyXG4gICAgICAgICAgICAgIG9wdEdyb3VwID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXNWaXNpYmxlLCBoYXNDbGFzcygnZHJvcGRvd24taGVhZGVyJywgdHJ1ZSkpIDogbGlzVmlzaWJsZS5maWx0ZXIoJy5kcm9wZG93bi1oZWFkZXInKTtcclxuXHJcbiAgICAgICAgICBnZXRQb3MoKTtcclxuICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRCb3QgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICBtZW51V2lkdGggPSBzZWxlY3RPZmZzZXRSaWdodCAtIG1lbnVFeHRyYXMuaG9yaXo7XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgICBnZXRIZWlnaHQgPSAkbWVudS5kYXRhKCdoZWlnaHQnKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJG1lbnUuZGF0YSgnd2lkdGgnKSkgJG1lbnUuZGF0YSgnd2lkdGgnLCAkbWVudS53aWR0aCgpKTtcclxuICAgICAgICAgICAgZ2V0V2lkdGggPSAkbWVudS5kYXRhKCd3aWR0aCcpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuaGVpZ2h0KCk7XHJcbiAgICAgICAgICAgIGdldFdpZHRoID0gJG1lbnUud2lkdGgoKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmRyb3B1cEF1dG8pIHtcclxuICAgICAgICAgICAgdGhhdC4kbmV3RWxlbWVudC50b2dnbGVDbGFzcygnZHJvcHVwJywgc2VsZWN0T2Zmc2V0VG9wID4gc2VsZWN0T2Zmc2V0Qm90ICYmIChtZW51SGVpZ2h0IC0gbWVudUV4dHJhcy52ZXJ0KSA8IGdldEhlaWdodCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2Ryb3B1cCcpKSB7XHJcbiAgICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRUb3AgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09ICdhdXRvJykge1xyXG4gICAgICAgICAgICAkbWVudS50b2dnbGVDbGFzcygnZHJvcGRvd24tbWVudS1yaWdodCcsIHNlbGVjdE9mZnNldExlZnQgPiBzZWxlY3RPZmZzZXRSaWdodCAmJiAobWVudVdpZHRoIC0gbWVudUV4dHJhcy5ob3JpeikgPCAoZ2V0V2lkdGggLSBzZWxlY3RXaWR0aCkpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICgobGlzVmlzaWJsZS5sZW5ndGggKyBvcHRHcm91cC5sZW5ndGgpID4gMykge1xyXG4gICAgICAgICAgICBtaW5IZWlnaHQgPSBsaUhlaWdodCAqIDMgKyBtZW51RXh0cmFzLnZlcnQgLSAyO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbWluSGVpZ2h0ID0gMDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cnOiAnaGlkZGVuJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBtaW5IZWlnaHQgKyBoZWFkZXJIZWlnaHQgKyBzZWFyY2hIZWlnaHQgKyBhY3Rpb25zSGVpZ2h0ICsgZG9uZUJ1dHRvbkhlaWdodCArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgLSBoZWFkZXJIZWlnaHQgLSBzZWFyY2hIZWlnaHQgLSBhY3Rpb25zSGVpZ2h0IC0gZG9uZUJ1dHRvbkhlaWdodCAtIG1lbnVQYWRkaW5nLnZlcnQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBNYXRoLm1heChtaW5IZWlnaHQgLSBtZW51UGFkZGluZy52ZXJ0LCAwKSArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgZ2V0U2l6ZSgpO1xyXG4gICAgICAgIHRoaXMuJHNlYXJjaGJveC5vZmYoJ2lucHV0LmdldFNpemUgcHJvcGVydHljaGFuZ2UuZ2V0U2l6ZScpLm9uKCdpbnB1dC5nZXRTaXplIHByb3BlcnR5Y2hhbmdlLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgICAkd2luZG93Lm9mZigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnKS5vbigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSAmJiB0aGlzLm9wdGlvbnMuc2l6ZSAhPSAnYXV0bycgJiYgdGhpcy4kbGlzLm5vdChub3REaXNhYmxlZCkubGVuZ3RoID4gdGhpcy5vcHRpb25zLnNpemUpIHtcclxuICAgICAgICB2YXIgb3B0SW5kZXggPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlcicpLm5vdChub3REaXNhYmxlZCkuY2hpbGRyZW4oKS5zbGljZSgwLCB0aGlzLm9wdGlvbnMuc2l6ZSkubGFzdCgpLnBhcmVudCgpLmluZGV4KCksXHJcbiAgICAgICAgICAgIGRpdkxlbmd0aCA9IHRoaXMuJGxpcy5zbGljZSgwLCBvcHRJbmRleCArIDEpLmZpbHRlcignLmRpdmlkZXInKS5sZW5ndGg7XHJcbiAgICAgICAgbWVudUhlaWdodCA9IGxpSGVpZ2h0ICogdGhpcy5vcHRpb25zLnNpemUgKyBkaXZMZW5ndGggKiBkaXZIZWlnaHQgKyBtZW51UGFkZGluZy52ZXJ0O1xyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmNvbnRhaW5lcikge1xyXG4gICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuZGF0YSgnaGVpZ2h0Jyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGdldEhlaWdodCA9ICRtZW51LmhlaWdodCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wdXBBdXRvKSB7XHJcbiAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1VudXNlZEFzc2lnbm1lbnRcclxuICAgICAgICAgIHRoaXMuJG5ld0VsZW1lbnQudG9nZ2xlQ2xhc3MoJ2Ryb3B1cCcsIHNlbGVjdE9mZnNldFRvcCA+IHNlbGVjdE9mZnNldEJvdCAmJiAobWVudUhlaWdodCAtIG1lbnVFeHRyYXMudmVydCkgPCBnZXRIZWlnaHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0ICsgaGVhZGVySGVpZ2h0ICsgc2VhcmNoSGVpZ2h0ICsgYWN0aW9uc0hlaWdodCArIGRvbmVCdXR0b25IZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgJ292ZXJmbG93JzogJ2hpZGRlbicsXHJcbiAgICAgICAgICAnbWluLWhlaWdodCc6ICcnXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0IC0gbWVudVBhZGRpbmcudmVydCArICdweCcsXHJcbiAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICdtaW4taGVpZ2h0JzogJydcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZXRXaWR0aDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnYXV0bycpIHtcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJzAnKTtcclxuXHJcbiAgICAgICAgLy8gR2V0IGNvcnJlY3Qgd2lkdGggaWYgZWxlbWVudCBpcyBoaWRkZW5cclxuICAgICAgICB2YXIgJHNlbGVjdENsb25lID0gdGhpcy4kbWVudS5wYXJlbnQoKS5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JyksXHJcbiAgICAgICAgICAgICRzZWxlY3RDbG9uZTIgPSB0aGlzLm9wdGlvbnMuY29udGFpbmVyID8gdGhpcy4kbmV3RWxlbWVudC5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JykgOiAkc2VsZWN0Q2xvbmUsXHJcbiAgICAgICAgICAgIHVsV2lkdGggPSAkc2VsZWN0Q2xvbmUuY2hpbGRyZW4oJy5kcm9wZG93bi1tZW51Jykub3V0ZXJXaWR0aCgpLFxyXG4gICAgICAgICAgICBidG5XaWR0aCA9ICRzZWxlY3RDbG9uZTIuY3NzKCd3aWR0aCcsICdhdXRvJykuY2hpbGRyZW4oJ2J1dHRvbicpLm91dGVyV2lkdGgoKTtcclxuXHJcbiAgICAgICAgJHNlbGVjdENsb25lLnJlbW92ZSgpO1xyXG4gICAgICAgICRzZWxlY3RDbG9uZTIucmVtb3ZlKCk7XHJcblxyXG4gICAgICAgIC8vIFNldCB3aWR0aCB0byB3aGF0ZXZlcidzIGxhcmdlciwgYnV0dG9uIHRpdGxlIG9yIGxvbmdlc3Qgb3B0aW9uXHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5jc3MoJ3dpZHRoJywgTWF0aC5tYXgodWxXaWR0aCwgYnRuV2lkdGgpICsgJ3B4Jyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnZml0Jykge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJykuYWRkQ2xhc3MoJ2ZpdC13aWR0aCcpO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy53aWR0aCkge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCB0aGlzLm9wdGlvbnMud2lkdGgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoL3dpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJyk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gUmVtb3ZlIGZpdC13aWR0aCBjbGFzcyBpZiB3aWR0aCBpcyBjaGFuZ2VkIHByb2dyYW1tYXRpY2FsbHlcclxuICAgICAgaWYgKHRoaXMuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2ZpdC13aWR0aCcpICYmIHRoaXMub3B0aW9ucy53aWR0aCAhPT0gJ2ZpdCcpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdmaXQtd2lkdGgnKTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRic0NvbnRhaW5lciA9ICQoJzxkaXYgY2xhc3M9XCJicy1jb250YWluZXJcIiAvPicpO1xyXG5cclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGNvbnRhaW5lciA9ICQodGhpcy5vcHRpb25zLmNvbnRhaW5lciksXHJcbiAgICAgICAgICBwb3MsXHJcbiAgICAgICAgICBjb250YWluZXJQb3MsXHJcbiAgICAgICAgICBhY3R1YWxIZWlnaHQsXHJcbiAgICAgICAgICBnZXRQbGFjZW1lbnQgPSBmdW5jdGlvbiAoJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgdGhhdC4kYnNDb250YWluZXIuYWRkQ2xhc3MoJGVsZW1lbnQuYXR0cignY2xhc3MnKS5yZXBsYWNlKC9mb3JtLWNvbnRyb2x8Zml0LXdpZHRoL2dpLCAnJykpLnRvZ2dsZUNsYXNzKCdkcm9wdXAnLCAkZWxlbWVudC5oYXNDbGFzcygnZHJvcHVwJykpO1xyXG4gICAgICAgICAgICBwb3MgPSAkZWxlbWVudC5vZmZzZXQoKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJGNvbnRhaW5lci5pcygnYm9keScpKSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0gJGNvbnRhaW5lci5vZmZzZXQoKTtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MudG9wICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJUb3BXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zLmxlZnQgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcyA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGFjdHVhbEhlaWdodCA9ICRlbGVtZW50Lmhhc0NsYXNzKCdkcm9wdXAnKSA/IDAgOiAkZWxlbWVudFswXS5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICd0b3AnOiBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCArIGFjdHVhbEhlaWdodCxcclxuICAgICAgICAgICAgICAnbGVmdCc6IHBvcy5sZWZ0IC0gY29udGFpbmVyUG9zLmxlZnQsXHJcbiAgICAgICAgICAgICAgJ3dpZHRoJzogJGVsZW1lbnRbMF0ub2Zmc2V0V2lkdGhcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9O1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBpZiAodGhhdC5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGdldFBsYWNlbWVudCh0aGF0LiRuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgICAgdGhhdC4kYnNDb250YWluZXJcclxuICAgICAgICAgIC5hcHBlbmRUbyh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKVxyXG4gICAgICAgICAgLnRvZ2dsZUNsYXNzKCdvcGVuJywgISR0aGlzLmhhc0NsYXNzKCdvcGVuJykpXHJcbiAgICAgICAgICAuYXBwZW5kKHRoYXQuJG1lbnUpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgICQod2luZG93KS5vbigncmVzaXplIHNjcm9sbCcsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBnZXRQbGFjZW1lbnQodGhhdC4kbmV3RWxlbWVudCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignaGlkZS5icy5zZWxlY3QnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5kYXRhKCdoZWlnaHQnLCB0aGF0LiRtZW51LmhlaWdodCgpKTtcclxuICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5kZXRhY2goKTtcclxuICAgICAgfSk7XHJcbiAgICB9LFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBvcHRpb24gdGhhdCBpcyBiZWluZyBjaGFuZ2VkXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNlbGVjdGVkIC0gdHJ1ZSBpZiB0aGUgb3B0aW9uIGlzIGJlaW5nIHNlbGVjdGVkLCBmYWxzZSBpZiBiZWluZyBkZXNlbGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge0pRdWVyeX0gJGxpcyAtIHRoZSAnbGknIGVsZW1lbnQgdGhhdCBpcyBiZWluZyBtb2RpZmllZFxyXG4gICAgICovXHJcbiAgICBzZXRTZWxlY3RlZDogZnVuY3Rpb24gKGluZGV4LCBzZWxlY3RlZCwgJGxpcykge1xyXG4gICAgICBpZiAoISRsaXMpIHtcclxuICAgICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7IC8vIGNoZWNrIGlmIHNldFNlbGVjdGVkIGlzIGJlaW5nIGNhbGxlZCBieSBjaGFuZ2luZyB0aGUgdmFsdWUgb2YgdGhlIHNlbGVjdFxyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICRsaXMudG9nZ2xlQ2xhc3MoJ3NlbGVjdGVkJywgc2VsZWN0ZWQpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgc2VsZWN0ZWQpO1xyXG4gICAgfSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgb3B0aW9uIHRoYXQgaXMgYmVpbmcgZGlzYWJsZWRcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlzYWJsZWQgLSB0cnVlIGlmIHRoZSBvcHRpb24gaXMgYmVpbmcgZGlzYWJsZWQsIGZhbHNlIGlmIGJlaW5nIGVuYWJsZWRcclxuICAgICAqIEBwYXJhbSB7SlF1ZXJ5fSAkbGlzIC0gdGhlICdsaScgZWxlbWVudCB0aGF0IGlzIGJlaW5nIG1vZGlmaWVkXHJcbiAgICAgKi9cclxuICAgIHNldERpc2FibGVkOiBmdW5jdGlvbiAoaW5kZXgsIGRpc2FibGVkLCAkbGlzKSB7XHJcbiAgICAgIGlmICghJGxpcykge1xyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChkaXNhYmxlZCkge1xyXG4gICAgICAgICRsaXMuYWRkQ2xhc3MoJ2Rpc2FibGVkJykuY2hpbGRyZW4oJ2EnKS5hdHRyKCdocmVmJywgJyMnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgJGxpcy5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5jaGlsZHJlbignYScpLnJlbW92ZUF0dHIoJ2hyZWYnKS5hdHRyKCd0YWJpbmRleCcsIDApLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCBmYWxzZSk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgaXNEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy4kZWxlbWVudFswXS5kaXNhYmxlZDtcclxuICAgIH0sXHJcblxyXG4gICAgY2hlY2tEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcblxyXG4gICAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgZmFsc2UpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5hdHRyKCd0YWJpbmRleCcpID09IC0xICYmICF0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JykpIHtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVBdHRyKCd0YWJpbmRleCcpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gIXRoYXQuaXNEaXNhYmxlZCgpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgdG9nZ2xlUGxhY2Vob2xkZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHZhbHVlID0gdGhpcy4kZWxlbWVudC52YWwoKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLnRvZ2dsZUNsYXNzKCdicy1wbGFjZWhvbGRlcicsIHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnJyB8fCAodmFsdWUuY29uc3RydWN0b3IgPT09IEFycmF5ICYmIHZhbHVlLmxlbmd0aCA9PT0gMCkpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0YWJJbmRleDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpICE9PSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RhYmluZGV4JykgJiYgXHJcbiAgICAgICAgKHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gLTk4ICYmIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gJy05OCcpKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcsIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSk7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ3RhYmluZGV4JywgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcsIC05OCk7XHJcbiAgICB9LFxyXG5cclxuICAgIGNsaWNrTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGRvY3VtZW50ID0gJChkb2N1bWVudCk7XHJcblxyXG4gICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24ub24oJ2tleXVwJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAoLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgJiYgJGRvY3VtZW50LmRhdGEoJ3NwYWNlU2VsZWN0JykpIHtcclxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC5zZXRTaXplKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignc2hvd24uYnMuc2VsZWN0JywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmxpdmVTZWFyY2ggJiYgIXRoYXQubXVsdGlwbGUpIHtcclxuICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQgYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmICghdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgdmFyIHNlbGVjdGVkSW5kZXggPSB0aGF0LmxpT2JqW3RoYXQuJGVsZW1lbnRbMF0uc2VsZWN0ZWRJbmRleF07XHJcblxyXG4gICAgICAgICAgaWYgKHR5cGVvZiBzZWxlY3RlZEluZGV4ICE9PSAnbnVtYmVyJyB8fCB0aGF0Lm9wdGlvbnMuc2l6ZSA9PT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAvLyBzY3JvbGwgdG8gc2VsZWN0ZWQgb3B0aW9uXHJcbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gdGhhdC4kbGlzLmVxKHNlbGVjdGVkSW5kZXgpWzBdLm9mZnNldFRvcCAtIHRoYXQuJG1lbnVJbm5lclswXS5vZmZzZXRUb3A7XHJcbiAgICAgICAgICBvZmZzZXQgPSBvZmZzZXQgLSB0aGF0LiRtZW51SW5uZXJbMF0ub2Zmc2V0SGVpZ2h0LzIgKyB0aGF0LnNpemVJbmZvLmxpSGVpZ2h0LzI7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXJbMF0uc2Nyb2xsVG9wID0gb2Zmc2V0O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJ2xpIGEnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAgIGNsaWNrZWRJbmRleCA9ICR0aGlzLnBhcmVudCgpLmRhdGEoJ29yaWdpbmFsSW5kZXgnKSxcclxuICAgICAgICAgICAgcHJldlZhbHVlID0gdGhhdC4kZWxlbWVudC52YWwoKSxcclxuICAgICAgICAgICAgcHJldkluZGV4ID0gdGhhdC4kZWxlbWVudC5wcm9wKCdzZWxlY3RlZEluZGV4JyksXHJcbiAgICAgICAgICAgIHRyaWdnZXJDaGFuZ2UgPSB0cnVlO1xyXG5cclxuICAgICAgICAvLyBEb24ndCBjbG9zZSBvbiBtdWx0aSBjaG9pY2UgbWVudVxyXG4gICAgICAgIGlmICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zICE9PSAxKSB7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgICAgICAvL0Rvbid0IHJ1biBpZiB3ZSBoYXZlIGJlZW4gZGlzYWJsZWRcclxuICAgICAgICBpZiAoIXRoYXQuaXNEaXNhYmxlZCgpICYmICEkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdmFyICRvcHRpb25zID0gdGhhdC4kZWxlbWVudC5maW5kKCdvcHRpb24nKSxcclxuICAgICAgICAgICAgICAkb3B0aW9uID0gJG9wdGlvbnMuZXEoY2xpY2tlZEluZGV4KSxcclxuICAgICAgICAgICAgICBzdGF0ZSA9ICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSxcclxuICAgICAgICAgICAgICAkb3B0Z3JvdXAgPSAkb3B0aW9uLnBhcmVudCgnb3B0Z3JvdXAnKSxcclxuICAgICAgICAgICAgICBtYXhPcHRpb25zID0gdGhhdC5vcHRpb25zLm1heE9wdGlvbnMsXHJcbiAgICAgICAgICAgICAgbWF4T3B0aW9uc0dycCA9ICRvcHRncm91cC5kYXRhKCdtYXhPcHRpb25zJykgfHwgZmFsc2U7XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlKSB7IC8vIERlc2VsZWN0IGFsbCBvdGhlcnMgaWYgbm90IG11bHRpIHNlbGVjdCBib3hcclxuICAgICAgICAgICAgJG9wdGlvbnMucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCcpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgdHJ1ZSk7XHJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBUb2dnbGUgdGhlIG9uZSB3ZSBoYXZlIGNob3NlbiBpZiB3ZSBhcmUgbXVsdGkgc2VsZWN0LlxyXG4gICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgIXN0YXRlKTtcclxuICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsICFzdGF0ZSk7XHJcbiAgICAgICAgICAgICR0aGlzLmJsdXIoKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChtYXhPcHRpb25zICE9PSBmYWxzZSB8fCBtYXhPcHRpb25zR3JwICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgIHZhciBtYXhSZWFjaGVkID0gbWF4T3B0aW9ucyA8ICRvcHRpb25zLmZpbHRlcignOnNlbGVjdGVkJykubGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICBtYXhSZWFjaGVkR3JwID0gbWF4T3B0aW9uc0dycCA8ICRvcHRncm91cC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5sZW5ndGg7XHJcblxyXG4gICAgICAgICAgICAgIGlmICgobWF4T3B0aW9ucyAmJiBtYXhSZWFjaGVkKSB8fCAobWF4T3B0aW9uc0dycCAmJiBtYXhSZWFjaGVkR3JwKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4T3B0aW9ucyA9PSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb25zLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXhPcHRpb25zR3JwICYmIG1heE9wdGlvbnNHcnAgPT0gMSkge1xyXG4gICAgICAgICAgICAgICAgICAkb3B0Z3JvdXAuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgdmFyIG9wdGdyb3VwSUQgPSAkdGhpcy5wYXJlbnQoKS5kYXRhKCdvcHRncm91cCcpO1xyXG4gICAgICAgICAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnW2RhdGEtb3B0Z3JvdXA9XCInICsgb3B0Z3JvdXBJRCArICdcIl0nKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgdmFyIG1heE9wdGlvbnNUZXh0ID0gdHlwZW9mIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zVGV4dCA9PT0gJ3N0cmluZycgPyBbdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LCB0aGF0Lm9wdGlvbnMubWF4T3B0aW9uc1RleHRdIDogdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4T3B0aW9uc0FyciA9IHR5cGVvZiBtYXhPcHRpb25zVGV4dCA9PT0gJ2Z1bmN0aW9uJyA/IG1heE9wdGlvbnNUZXh0KG1heE9wdGlvbnMsIG1heE9wdGlvbnNHcnApIDogbWF4T3B0aW9uc1RleHQsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhPcHRpb25zQXJyWzBdLnJlcGxhY2UoJ3tufScsIG1heE9wdGlvbnMpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4VHh0R3JwID0gbWF4T3B0aW9uc0FyclsxXS5yZXBsYWNlKCd7bn0nLCBtYXhPcHRpb25zR3JwKSxcclxuICAgICAgICAgICAgICAgICAgICAgICRub3RpZnkgPSAkKCc8ZGl2IGNsYXNzPVwibm90aWZ5XCI+PC9kaXY+Jyk7XHJcbiAgICAgICAgICAgICAgICAgIC8vIElmIHt2YXJ9IGlzIHNldCBpbiBhcnJheSwgcmVwbGFjZSBpdFxyXG4gICAgICAgICAgICAgICAgICAvKiogQGRlcHJlY2F0ZWQgKi9cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNBcnJbMl0pIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhUeHQucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnMgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHRHcnAgPSBtYXhUeHRHcnAucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnNHcnAgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnUuYXBwZW5kKCRub3RpZnkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4UmVhY2hlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNHcnAgJiYgbWF4UmVhY2hlZEdycCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dEdycCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZEdycC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgfSwgMTApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgJG5vdGlmeS5kZWxheSg3NTApLmZhZGVPdXQoMzAwLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5yZW1vdmUoKTtcclxuICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlIHx8ICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zID09PSAxKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gVHJpZ2dlciBzZWxlY3QgJ2NoYW5nZSdcclxuICAgICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlKSB7XHJcbiAgICAgICAgICAgIGlmICgocHJldlZhbHVlICE9IHRoYXQuJGVsZW1lbnQudmFsKCkgJiYgdGhhdC5tdWx0aXBsZSkgfHwgKHByZXZJbmRleCAhPSB0aGF0LiRlbGVtZW50LnByb3AoJ3NlbGVjdGVkSW5kZXgnKSAmJiAhdGhhdC5tdWx0aXBsZSkpIHtcclxuICAgICAgICAgICAgICAvLyAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJykgaXMgY3VycmVudCBvcHRpb24gc3RhdGUgKHNlbGVjdGVkL3Vuc2VsZWN0ZWQpLiBzdGF0ZSBpcyBwcmV2aW91cyBvcHRpb24gc3RhdGUuXHJcbiAgICAgICAgICAgICAgY2hhbmdlZF9hcmd1bWVudHMgPSBbY2xpY2tlZEluZGV4LCAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJyksIHN0YXRlXTtcclxuICAgICAgICAgICAgICB0aGF0LiRlbGVtZW50XHJcbiAgICAgICAgICAgICAgICAudHJpZ2dlck5hdGl2ZSgnY2hhbmdlJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnbGkuZGlzYWJsZWQgYSwgLnBvcG92ZXItdGl0bGUsIC5wb3BvdmVyLXRpdGxlIDpub3QoLmNsb3NlKScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgaWYgKGUuY3VycmVudFRhcmdldCA9PSB0aGlzKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoICYmICEkKGUudGFyZ2V0KS5oYXNDbGFzcygnY2xvc2UnKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJy5kaXZpZGVyLCAuZHJvcGRvd24taGVhZGVyJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLnBvcG92ZXItdGl0bGUgLmNsb3NlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGJ1dHRvbi5jbGljaygpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJHNlYXJjaGJveC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLmFjdGlvbnMtYnRuJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcygnYnMtc2VsZWN0LWFsbCcpKSB7XHJcbiAgICAgICAgICB0aGF0LnNlbGVjdEFsbCgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LmRlc2VsZWN0QWxsKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuY2hhbmdlKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LnJlbmRlcihmYWxzZSk7XHJcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdjaGFuZ2VkLmJzLnNlbGVjdCcsIGNoYW5nZWRfYXJndW1lbnRzKTtcclxuICAgICAgICBjaGFuZ2VkX2FyZ3VtZW50cyA9IG51bGw7XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBsaXZlU2VhcmNoTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJG5vX3Jlc3VsdHMgPSAkKCc8bGkgY2xhc3M9XCJuby1yZXN1bHRzXCI+PC9saT4nKTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2suZHJvcGRvd24uZGF0YS1hcGknLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgaWYgKCEhdGhhdC4kc2VhcmNoYm94LnZhbCgpKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3gudmFsKCcnKTtcclxuICAgICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICBpZiAoISEkbm9fcmVzdWx0cy5wYXJlbnQoKS5sZW5ndGgpICRub19yZXN1bHRzLnJlbW92ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIXRoYXQubXVsdGlwbGUpIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5hZGRDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICB9LCAxMCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kc2VhcmNoYm94Lm9uKCdjbGljay5kcm9wZG93bi5kYXRhLWFwaSBmb2N1cy5kcm9wZG93bi5kYXRhLWFwaSB0b3VjaGVuZC5kcm9wZG93bi5kYXRhLWFwaScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRzZWFyY2hib3gub24oJ2lucHV0IHByb3BlcnR5Y2hhbmdlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgdGhhdC4kbGlzLmZpbHRlcignLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAkbm9fcmVzdWx0cy5yZW1vdmUoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoYXQuJHNlYXJjaGJveC52YWwoKSkge1xyXG4gICAgICAgICAgdmFyICRzZWFyY2hCYXNlID0gdGhhdC4kbGlzLm5vdCgnLmlzLWhpZGRlbiwgLmRpdmlkZXIsIC5kcm9wZG93bi1oZWFkZXInKSxcclxuICAgICAgICAgICAgICAkaGlkZUl0ZW1zO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplKSB7XHJcbiAgICAgICAgICAgICRoaWRlSXRlbXMgPSAkc2VhcmNoQmFzZS5ub3QoJzphJyArIHRoYXQuX3NlYXJjaFN0eWxlKCkgKyAnKFwiJyArIG5vcm1hbGl6ZVRvQmFzZSh0aGF0LiRzZWFyY2hib3gudmFsKCkpICsgJ1wiKScpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcyA9ICRzZWFyY2hCYXNlLm5vdCgnOicgKyB0aGF0Ll9zZWFyY2hTdHlsZSgpICsgJyhcIicgKyB0aGF0LiRzZWFyY2hib3gudmFsKCkgKyAnXCIpJyk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCRoaWRlSXRlbXMubGVuZ3RoID09PSAkc2VhcmNoQmFzZS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgJG5vX3Jlc3VsdHMuaHRtbCh0aGF0Lm9wdGlvbnMubm9uZVJlc3VsdHNUZXh0LnJlcGxhY2UoJ3swfScsICdcIicgKyBodG1sRXNjYXBlKHRoYXQuJHNlYXJjaGJveC52YWwoKSkgKyAnXCInKSk7XHJcbiAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5hcHBlbmQoJG5vX3Jlc3VsdHMpO1xyXG4gICAgICAgICAgICB0aGF0LiRsaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcy5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICB2YXIgJGxpc1Zpc2libGUgPSB0aGF0LiRsaXMubm90KCcuaGlkZGVuJyksXHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXY7XHJcblxyXG4gICAgICAgICAgICAvLyBoaWRlIGRpdmlkZXIgaWYgZmlyc3Qgb3IgbGFzdCB2aXNpYmxlLCBvciBpZiBmb2xsb3dlZCBieSBhbm90aGVyIGRpdmlkZXJcclxuICAgICAgICAgICAgJGxpc1Zpc2libGUuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICAgICAgICBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2RpdmlkZXInKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZERpdiA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICR0aGlzLmFkZENsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICAgICAgICAgICRmb3VuZERpdiA9ICR0aGlzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLWhlYWRlcicpICYmICRsaXNWaXNpYmxlLmVxKGluZGV4ICsgMSkuZGF0YSgnb3B0Z3JvdXAnKSAhPT0gJHRoaXMuZGF0YSgnb3B0Z3JvdXAnKSkge1xyXG4gICAgICAgICAgICAgICAgJHRoaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXYgPSBudWxsO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICAkc2VhcmNoQmFzZS5ub3QoJy5oaWRkZW4nKS5maXJzdCgpLmFkZENsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLnNjcm9sbFRvcCgwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBfc2VhcmNoU3R5bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHN0eWxlcyA9IHtcclxuICAgICAgICBiZWdpbnM6ICdpYmVnaW5zJyxcclxuICAgICAgICBzdGFydHNXaXRoOiAnaWJlZ2lucydcclxuICAgICAgfTtcclxuXHJcbiAgICAgIHJldHVybiBzdHlsZXNbdGhpcy5vcHRpb25zLmxpdmVTZWFyY2hTdHlsZV0gfHwgJ2ljb250YWlucyc7XHJcbiAgICB9LFxyXG5cclxuICAgIHZhbDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC52YWwodmFsdWUpO1xyXG4gICAgICAgIHRoaXMucmVuZGVyKCk7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50LnZhbCgpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGNoYW5nZUFsbDogZnVuY3Rpb24gKHN0YXR1cykge1xyXG4gICAgICBpZiAoIXRoaXMubXVsdGlwbGUpIHJldHVybjtcclxuICAgICAgaWYgKHR5cGVvZiBzdGF0dXMgPT09ICd1bmRlZmluZWQnKSBzdGF0dXMgPSB0cnVlO1xyXG5cclxuICAgICAgdGhpcy5maW5kTGlzKCk7XHJcblxyXG4gICAgICB2YXIgJG9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgJGxpc1Zpc2libGUgPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlciwgLmRyb3Bkb3duLWhlYWRlciwgLmRpc2FibGVkLCAuaGlkZGVuJyksXHJcbiAgICAgICAgICBsaXNWaXNMZW4gPSAkbGlzVmlzaWJsZS5sZW5ndGgsXHJcbiAgICAgICAgICBzZWxlY3RlZE9wdGlvbnMgPSBbXTtcclxuICAgICAgICAgIFxyXG4gICAgICBpZiAoc3RhdHVzKSB7XHJcbiAgICAgICAgaWYgKCRsaXNWaXNpYmxlLmZpbHRlcignLnNlbGVjdGVkJykubGVuZ3RoID09PSAkbGlzVmlzaWJsZS5sZW5ndGgpIHJldHVybjtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAoJGxpc1Zpc2libGUuZmlsdGVyKCcuc2VsZWN0ZWQnKS5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICAgICAgXHJcbiAgICAgICRsaXNWaXNpYmxlLnRvZ2dsZUNsYXNzKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc1Zpc0xlbjsgaSsrKSB7XHJcbiAgICAgICAgdmFyIG9yaWdJbmRleCA9ICRsaXNWaXNpYmxlW2ldLmdldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC1pbmRleCcpO1xyXG4gICAgICAgIHNlbGVjdGVkT3B0aW9uc1tzZWxlY3RlZE9wdGlvbnMubGVuZ3RoXSA9ICRvcHRpb25zLmVxKG9yaWdJbmRleClbMF07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICQoc2VsZWN0ZWRPcHRpb25zKS5wcm9wKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICB0aGlzLnJlbmRlcihmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50XHJcbiAgICAgICAgLnRyaWdnZXJOYXRpdmUoJ2NoYW5nZScpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RBbGw6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY2hhbmdlQWxsKHRydWUpO1xyXG4gICAgfSxcclxuXHJcbiAgICBkZXNlbGVjdEFsbDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5jaGFuZ2VBbGwoZmFsc2UpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0b2dnbGU6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcclxuXHJcbiAgICAgIGlmIChlKSBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLnRyaWdnZXIoJ2NsaWNrJyk7XHJcbiAgICB9LFxyXG5cclxuICAgIGtleWRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuaXMoJ2lucHV0JykgPyAkdGhpcy5wYXJlbnQoKS5wYXJlbnQoKSA6ICR0aGlzLnBhcmVudCgpLFxyXG4gICAgICAgICAgJGl0ZW1zLFxyXG4gICAgICAgICAgdGhhdCA9ICRwYXJlbnQuZGF0YSgndGhpcycpLFxyXG4gICAgICAgICAgaW5kZXgsXHJcbiAgICAgICAgICBwcmV2SW5kZXgsXHJcbiAgICAgICAgICBpc0FjdGl2ZSxcclxuICAgICAgICAgIHNlbGVjdG9yID0gJzpub3QoLmRpc2FibGVkLCAuaGlkZGVuLCAuZHJvcGRvd24taGVhZGVyLCAuZGl2aWRlciknLFxyXG4gICAgICAgICAga2V5Q29kZU1hcCA9IHtcclxuICAgICAgICAgICAgMzI6ICcgJyxcclxuICAgICAgICAgICAgNDg6ICcwJyxcclxuICAgICAgICAgICAgNDk6ICcxJyxcclxuICAgICAgICAgICAgNTA6ICcyJyxcclxuICAgICAgICAgICAgNTE6ICczJyxcclxuICAgICAgICAgICAgNTI6ICc0JyxcclxuICAgICAgICAgICAgNTM6ICc1JyxcclxuICAgICAgICAgICAgNTQ6ICc2JyxcclxuICAgICAgICAgICAgNTU6ICc3JyxcclxuICAgICAgICAgICAgNTY6ICc4JyxcclxuICAgICAgICAgICAgNTc6ICc5JyxcclxuICAgICAgICAgICAgNTk6ICc7JyxcclxuICAgICAgICAgICAgNjU6ICdhJyxcclxuICAgICAgICAgICAgNjY6ICdiJyxcclxuICAgICAgICAgICAgNjc6ICdjJyxcclxuICAgICAgICAgICAgNjg6ICdkJyxcclxuICAgICAgICAgICAgNjk6ICdlJyxcclxuICAgICAgICAgICAgNzA6ICdmJyxcclxuICAgICAgICAgICAgNzE6ICdnJyxcclxuICAgICAgICAgICAgNzI6ICdoJyxcclxuICAgICAgICAgICAgNzM6ICdpJyxcclxuICAgICAgICAgICAgNzQ6ICdqJyxcclxuICAgICAgICAgICAgNzU6ICdrJyxcclxuICAgICAgICAgICAgNzY6ICdsJyxcclxuICAgICAgICAgICAgNzc6ICdtJyxcclxuICAgICAgICAgICAgNzg6ICduJyxcclxuICAgICAgICAgICAgNzk6ICdvJyxcclxuICAgICAgICAgICAgODA6ICdwJyxcclxuICAgICAgICAgICAgODE6ICdxJyxcclxuICAgICAgICAgICAgODI6ICdyJyxcclxuICAgICAgICAgICAgODM6ICdzJyxcclxuICAgICAgICAgICAgODQ6ICd0JyxcclxuICAgICAgICAgICAgODU6ICd1JyxcclxuICAgICAgICAgICAgODY6ICd2JyxcclxuICAgICAgICAgICAgODc6ICd3JyxcclxuICAgICAgICAgICAgODg6ICd4JyxcclxuICAgICAgICAgICAgODk6ICd5JyxcclxuICAgICAgICAgICAgOTA6ICd6JyxcclxuICAgICAgICAgICAgOTY6ICcwJyxcclxuICAgICAgICAgICAgOTc6ICcxJyxcclxuICAgICAgICAgICAgOTg6ICcyJyxcclxuICAgICAgICAgICAgOTk6ICczJyxcclxuICAgICAgICAgICAgMTAwOiAnNCcsXHJcbiAgICAgICAgICAgIDEwMTogJzUnLFxyXG4gICAgICAgICAgICAxMDI6ICc2JyxcclxuICAgICAgICAgICAgMTAzOiAnNycsXHJcbiAgICAgICAgICAgIDEwNDogJzgnLFxyXG4gICAgICAgICAgICAxMDU6ICc5J1xyXG4gICAgICAgICAgfTtcclxuXHJcblxyXG4gICAgICBpc0FjdGl2ZSA9IHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ29wZW4nKTtcclxuXHJcbiAgICAgIGlmICghaXNBY3RpdmUgJiYgKGUua2V5Q29kZSA+PSA0OCAmJiBlLmtleUNvZGUgPD0gNTcgfHwgZS5rZXlDb2RlID49IDk2ICYmIGUua2V5Q29kZSA8PSAxMDUgfHwgZS5rZXlDb2RlID49IDY1ICYmIGUua2V5Q29kZSA8PSA5MCkpIHtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgIHRoYXQuc2V0U2l6ZSgpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5hZGRDbGFzcygnb3BlbicpO1xyXG4gICAgICAgICAgaXNBY3RpdmUgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24udHJpZ2dlcignY2xpY2snKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICBpZiAoLyheOSR8MjcpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmIGlzQWN0aXZlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmNsaWNrKCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICgvKDM4fDQwKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgIGlmICghJGl0ZW1zLmxlbmd0aCkgcmV0dXJuO1xyXG5cclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICBpbmRleCA9ICRpdGVtcy5pbmRleCgkaXRlbXMuZmluZCgnYScpLmZpbHRlcignOmZvY3VzJykucGFyZW50KCkpO1xyXG5cdCAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaW5kZXggPSAkaXRlbXMuaW5kZXgoJGl0ZW1zLmZpbHRlcignLmFjdGl2ZScpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHByZXZJbmRleCA9IHRoYXQuJG1lbnVJbm5lci5kYXRhKCdwcmV2SW5kZXgnKTtcclxuXHJcbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAzOCkge1xyXG4gICAgICAgICAgaWYgKCh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCB8fCBpbmRleCA9PSBwcmV2SW5kZXgpICYmIGluZGV4ICE9IC0xKSBpbmRleC0tO1xyXG4gICAgICAgICAgaWYgKGluZGV4IDwgMCkgaW5kZXggKz0gJGl0ZW1zLmxlbmd0aDtcclxuICAgICAgICB9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSA0MCkge1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoIHx8IGluZGV4ID09IHByZXZJbmRleCkgaW5kZXgrKztcclxuICAgICAgICAgIGluZGV4ID0gaW5kZXggJSAkaXRlbXMubGVuZ3RoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmRhdGEoJ3ByZXZJbmRleCcsIGluZGV4KTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgJGl0ZW1zLmVxKGluZGV4KS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIGlmICghJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLXRvZ2dsZScpKSB7XHJcbiAgICAgICAgICAgICRpdGVtcy5yZW1vdmVDbGFzcygnYWN0aXZlJykuZXEoaW5kZXgpLmFkZENsYXNzKCdhY3RpdmUnKS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICR0aGlzLmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfSBlbHNlIGlmICghJHRoaXMuaXMoJ2lucHV0JykpIHtcclxuICAgICAgICB2YXIga2V5SW5kZXggPSBbXSxcclxuICAgICAgICAgICAgY291bnQsXHJcbiAgICAgICAgICAgIHByZXZLZXk7XHJcblxyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgICRpdGVtcy5lYWNoKGZ1bmN0aW9uIChpKSB7XHJcbiAgICAgICAgICBpZiAoJC50cmltKCQodGhpcykuY2hpbGRyZW4oJ2EnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpID09IGtleUNvZGVNYXBbZS5rZXlDb2RlXSkge1xyXG4gICAgICAgICAgICBrZXlJbmRleC5wdXNoKGkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBjb3VudCA9ICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50Jyk7XHJcbiAgICAgICAgY291bnQrKztcclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIGNvdW50KTtcclxuXHJcbiAgICAgICAgcHJldktleSA9ICQudHJpbSgkKCc6Zm9jdXMnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpO1xyXG5cclxuICAgICAgICBpZiAocHJldktleSAhPSBrZXlDb2RlTWFwW2Uua2V5Q29kZV0pIHtcclxuICAgICAgICAgIGNvdW50ID0gMTtcclxuICAgICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgY291bnQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoY291bnQgPj0ga2V5SW5kZXgubGVuZ3RoKSB7XHJcbiAgICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICAgICAgaWYgKGNvdW50ID4ga2V5SW5kZXgubGVuZ3RoKSBjb3VudCA9IDE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAkaXRlbXMuZXEoa2V5SW5kZXhbY291bnQgLSAxXSkuY2hpbGRyZW4oJ2EnKS5mb2N1cygpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZWxlY3QgZm9jdXNlZCBvcHRpb24gaWYgXCJFbnRlclwiLCBcIlNwYWNlYmFyXCIgb3IgXCJUYWJcIiAod2hlbiBzZWxlY3RPblRhYiBpcyB0cnVlKSBhcmUgcHJlc3NlZCBpbnNpZGUgdGhlIG1lbnUuXHJcbiAgICAgIGlmICgoLygxM3wzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgfHwgKC8oXjkkKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiB0aGF0Lm9wdGlvbnMuc2VsZWN0T25UYWIpKSAmJiBpc0FjdGl2ZSkge1xyXG4gICAgICAgIGlmICghLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkpIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICB2YXIgZWxlbSA9ICQoJzpmb2N1cycpO1xyXG4gICAgICAgICAgZWxlbS5jbGljaygpO1xyXG4gICAgICAgICAgLy8gQnJpbmcgYmFjayBmb2N1cyBmb3IgbXVsdGlzZWxlY3RzXHJcbiAgICAgICAgICBlbGVtLmZvY3VzKCk7XHJcbiAgICAgICAgICAvLyBQcmV2ZW50IHNjcmVlbiBmcm9tIHNjcm9sbGluZyBpZiB0aGUgdXNlciBoaXQgdGhlIHNwYWNlYmFyXHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAvLyBGaXhlcyBzcGFjZWJhciBzZWxlY3Rpb24gb2YgZHJvcGRvd24gaXRlbXMgaW4gRkYgJiBJRVxyXG4gICAgICAgICAgJChkb2N1bWVudCkuZGF0YSgnc3BhY2VTZWxlY3QnLCB0cnVlKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCEvKDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUgYScpLmNsaWNrKCk7XHJcbiAgICAgICAgICAkdGhpcy5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoKC8oXjkkfDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiBpc0FjdGl2ZSAmJiAodGhhdC5tdWx0aXBsZSB8fCB0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkpIHx8ICgvKDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiAhaXNBY3RpdmUpKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5yZW1vdmVDbGFzcygnb3BlbicpO1xyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSB0aGF0LiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdvcGVuJyk7XHJcbiAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgbW9iaWxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ21vYmlsZS1kZXZpY2UnKTtcclxuICAgIH0sXHJcblxyXG4gICAgcmVmcmVzaDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRsaXMgPSBudWxsO1xyXG4gICAgICB0aGlzLmxpT2JqID0ge307XHJcbiAgICAgIHRoaXMucmVsb2FkTGkoKTtcclxuICAgICAgdGhpcy5yZW5kZXIoKTtcclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMubGlIZWlnaHQodHJ1ZSk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy4kbGlzKSB0aGlzLiRzZWFyY2hib3gudHJpZ2dlcigncHJvcGVydHljaGFuZ2UnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcigncmVmcmVzaGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgfSxcclxuXHJcbiAgICBoaWRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuaGlkZSgpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzaG93OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuc2hvdygpO1xyXG4gICAgfSxcclxuXHJcbiAgICByZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmUoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmUoKTtcclxuICAgIH0sXHJcblxyXG4gICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50LmJlZm9yZSh0aGlzLiRlbGVtZW50KS5yZW1vdmUoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLiRic0NvbnRhaW5lcikge1xyXG4gICAgICAgIHRoaXMuJGJzQ29udGFpbmVyLnJlbW92ZSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuJG1lbnUucmVtb3ZlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnRcclxuICAgICAgICAub2ZmKCcuYnMuc2VsZWN0JylcclxuICAgICAgICAucmVtb3ZlRGF0YSgnc2VsZWN0cGlja2VyJylcclxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4gc2VsZWN0cGlja2VyJyk7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIFBMVUdJTiBERUZJTklUSU9OXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xyXG4gICAgLy8gZ2V0IHRoZSBhcmdzIG9mIHRoZSBvdXRlciBmdW5jdGlvbi4uXHJcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcclxuICAgIC8vIFRoZSBhcmd1bWVudHMgb2YgdGhlIGZ1bmN0aW9uIGFyZSBleHBsaWNpdGx5IHJlLWRlZmluZWQgZnJvbSB0aGUgYXJndW1lbnQgbGlzdCwgYmVjYXVzZSB0aGUgc2hpZnQgY2F1c2VzIHRoZW1cclxuICAgIC8vIHRvIGdldCBsb3N0L2NvcnJ1cHRlZCBpbiBhbmRyb2lkIDIuMyBhbmQgSUU5ICM3MTUgIzc3NVxyXG4gICAgdmFyIF9vcHRpb24gPSBvcHRpb247XHJcblxyXG4gICAgW10uc2hpZnQuYXBwbHkoYXJncyk7XHJcblxyXG4gICAgdmFyIHZhbHVlO1xyXG4gICAgdmFyIGNoYWluID0gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcclxuICAgICAgaWYgKCR0aGlzLmlzKCdzZWxlY3QnKSkge1xyXG4gICAgICAgIHZhciBkYXRhID0gJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJyksXHJcbiAgICAgICAgICAgIG9wdGlvbnMgPSB0eXBlb2YgX29wdGlvbiA9PSAnb2JqZWN0JyAmJiBfb3B0aW9uO1xyXG5cclxuICAgICAgICBpZiAoIWRhdGEpIHtcclxuICAgICAgICAgIHZhciBjb25maWcgPSAkLmV4dGVuZCh7fSwgU2VsZWN0cGlja2VyLkRFRkFVTFRTLCAkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyB8fCB7fSwgJHRoaXMuZGF0YSgpLCBvcHRpb25zKTtcclxuICAgICAgICAgIGNvbmZpZy50ZW1wbGF0ZSA9ICQuZXh0ZW5kKHt9LCBTZWxlY3RwaWNrZXIuREVGQVVMVFMudGVtcGxhdGUsICgkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyA/ICQuZm4uc2VsZWN0cGlja2VyLmRlZmF1bHRzLnRlbXBsYXRlIDoge30pLCAkdGhpcy5kYXRhKCkudGVtcGxhdGUsIG9wdGlvbnMudGVtcGxhdGUpO1xyXG4gICAgICAgICAgJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJywgKGRhdGEgPSBuZXcgU2VsZWN0cGlja2VyKHRoaXMsIGNvbmZpZykpKTtcclxuICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMpIHtcclxuICAgICAgICAgIGZvciAodmFyIGkgaW4gb3B0aW9ucykge1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG4gICAgICAgICAgICAgIGRhdGEub3B0aW9uc1tpXSA9IG9wdGlvbnNbaV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YgX29wdGlvbiA9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgaWYgKGRhdGFbX29wdGlvbl0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGFbX29wdGlvbl0uYXBwbHkoZGF0YSwgYXJncyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGEub3B0aW9uc1tfb3B0aW9uXTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkQXNzaWdubWVudFxyXG4gICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gY2hhaW47XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgb2xkID0gJC5mbi5zZWxlY3RwaWNrZXI7XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIgPSBQbHVnaW47XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIuQ29uc3RydWN0b3IgPSBTZWxlY3RwaWNrZXI7XHJcblxyXG4gIC8vIFNFTEVDVFBJQ0tFUiBOTyBDT05GTElDVFxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gICQuZm4uc2VsZWN0cGlja2VyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAkLmZuLnNlbGVjdHBpY2tlciA9IG9sZDtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH07XHJcblxyXG4gICQoZG9jdW1lbnQpXHJcbiAgICAgIC5kYXRhKCdrZXljb3VudCcsIDApXHJcbiAgICAgIC5vbigna2V5ZG93bi5icy5zZWxlY3QnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgU2VsZWN0cGlja2VyLnByb3RvdHlwZS5rZXlkb3duKVxyXG4gICAgICAub24oJ2ZvY3VzaW4ubW9kYWwnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIERBVEEtQVBJXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XHJcbiAgJCh3aW5kb3cpLm9uKCdsb2FkLmJzLnNlbGVjdC5kYXRhLWFwaScsIGZ1bmN0aW9uICgpIHtcclxuICAgICQoJy5zZWxlY3RwaWNrZXInKS5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICRzZWxlY3RwaWNrZXIgPSAkKHRoaXMpO1xyXG4gICAgICBQbHVnaW4uY2FsbCgkc2VsZWN0cGlja2VyLCAkc2VsZWN0cGlja2VyLmRhdGEoKSk7XHJcbiAgICB9KVxyXG4gIH0pO1xyXG59KShqUXVlcnkpO1xyXG5cblxufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2pzL2Jvb3RzdHJhcC1zZWxlY3QuanNcbi8vIG1vZHVsZSBpZCA9IDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXAgKHBsdWdpbik6IHZhbGlkYXRvci5qcyB2MC4xMS45XG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNiBDaW5hIFNhZmZhcnkuXG4gKiBNYWRlIGJ5IEAxMDAwaHogaW4gdGhlIHN0eWxlIG9mIEJvb3RzdHJhcCAzIGVyYSBAZmF0XG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbiAqIFRIRSBTT0ZUV0FSRS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVkFMSURBVE9SIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBnZXRWYWx1ZSgkZWwpIHtcbiAgICByZXR1cm4gJGVsLmlzKCdbdHlwZT1cImNoZWNrYm94XCJdJykgPyAkZWwucHJvcCgnY2hlY2tlZCcpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDpcbiAgICAgICAgICAgJGVsLmlzKCdbdHlwZT1cInJhZGlvXCJdJykgICAgPyAhISQoJ1tuYW1lPVwiJyArICRlbC5hdHRyKCduYW1lJykgKyAnXCJdOmNoZWNrZWQnKS5sZW5ndGggOlxuICAgICAgICAgICAkZWwuaXMoJ3NlbGVjdFttdWx0aXBsZV0nKSAgPyAoJGVsLnZhbCgpIHx8IFtdKS5sZW5ndGggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGVsLnZhbCgpXG4gIH1cblxuICB2YXIgVmFsaWRhdG9yID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgICAgPSBvcHRpb25zXG4gICAgdGhpcy52YWxpZGF0b3JzID0gJC5leHRlbmQoe30sIFZhbGlkYXRvci5WQUxJREFUT1JTLCBvcHRpb25zLmN1c3RvbSlcbiAgICB0aGlzLiRlbGVtZW50ICAgPSAkKGVsZW1lbnQpXG4gICAgdGhpcy4kYnRuICAgICAgID0gJCgnYnV0dG9uW3R5cGU9XCJzdWJtaXRcIl0sIGlucHV0W3R5cGU9XCJzdWJtaXRcIl0nKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcignW2Zvcm09XCInICsgdGhpcy4kZWxlbWVudC5hdHRyKCdpZCcpICsgJ1wiXScpXG4gICAgICAgICAgICAgICAgICAgICAgICAuYWRkKHRoaXMuJGVsZW1lbnQuZmluZCgnaW5wdXRbdHlwZT1cInN1Ym1pdFwiXSwgYnV0dG9uW3R5cGU9XCJzdWJtaXRcIl0nKSlcblxuICAgIHRoaXMudXBkYXRlKClcblxuICAgIHRoaXMuJGVsZW1lbnQub24oJ2lucHV0LmJzLnZhbGlkYXRvciBjaGFuZ2UuYnMudmFsaWRhdG9yIGZvY3Vzb3V0LmJzLnZhbGlkYXRvcicsICQucHJveHkodGhpcy5vbklucHV0LCB0aGlzKSlcbiAgICB0aGlzLiRlbGVtZW50Lm9uKCdzdWJtaXQuYnMudmFsaWRhdG9yJywgJC5wcm94eSh0aGlzLm9uU3VibWl0LCB0aGlzKSlcbiAgICB0aGlzLiRlbGVtZW50Lm9uKCdyZXNldC5icy52YWxpZGF0b3InLCAkLnByb3h5KHRoaXMucmVzZXQsIHRoaXMpKVxuXG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCdbZGF0YS1tYXRjaF0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyAgPSAkKHRoaXMpXG4gICAgICB2YXIgdGFyZ2V0ID0gJHRoaXMuYXR0cignZGF0YS1tYXRjaCcpXG5cbiAgICAgICQodGFyZ2V0KS5vbignaW5wdXQuYnMudmFsaWRhdG9yJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgZ2V0VmFsdWUoJHRoaXMpICYmICR0aGlzLnRyaWdnZXIoJ2lucHV0LmJzLnZhbGlkYXRvcicpXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICAvLyBydW4gdmFsaWRhdG9ycyBmb3IgZmllbGRzIHdpdGggdmFsdWVzLCBidXQgZG9uJ3QgY2xvYmJlciBzZXJ2ZXItc2lkZSBlcnJvcnNcbiAgICB0aGlzLiRpbnB1dHMuZmlsdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBnZXRWYWx1ZSgkKHRoaXMpKSAmJiAhJCh0aGlzKS5jbG9zZXN0KCcuaGFzLWVycm9yJykubGVuZ3RoXG4gICAgfSkudHJpZ2dlcignZm9jdXNvdXQnKVxuXG4gICAgdGhpcy4kZWxlbWVudC5hdHRyKCdub3ZhbGlkYXRlJywgdHJ1ZSkgLy8gZGlzYWJsZSBhdXRvbWF0aWMgbmF0aXZlIHZhbGlkYXRpb25cbiAgfVxuXG4gIFZhbGlkYXRvci5WRVJTSU9OID0gJzAuMTEuOSdcblxuICBWYWxpZGF0b3IuSU5QVVRfU0VMRUNUT1IgPSAnOmlucHV0Om5vdChbdHlwZT1cImhpZGRlblwiXSwgW3R5cGU9XCJzdWJtaXRcIl0sIFt0eXBlPVwicmVzZXRcIl0sIGJ1dHRvbiknXG5cbiAgVmFsaWRhdG9yLkZPQ1VTX09GRlNFVCA9IDIwXG5cbiAgVmFsaWRhdG9yLkRFRkFVTFRTID0ge1xuICAgIGRlbGF5OiA1MDAsXG4gICAgaHRtbDogZmFsc2UsXG4gICAgZGlzYWJsZTogdHJ1ZSxcbiAgICBmb2N1czogdHJ1ZSxcbiAgICBjdXN0b206IHt9LFxuICAgIGVycm9yczoge1xuICAgICAgbWF0Y2g6ICdEb2VzIG5vdCBtYXRjaCcsXG4gICAgICBtaW5sZW5ndGg6ICdOb3QgbG9uZyBlbm91Z2gnXG4gICAgfSxcbiAgICBmZWVkYmFjazoge1xuICAgICAgc3VjY2VzczogJ2dseXBoaWNvbi1vaycsXG4gICAgICBlcnJvcjogJ2dseXBoaWNvbi1yZW1vdmUnXG4gICAgfVxuICB9XG5cbiAgVmFsaWRhdG9yLlZBTElEQVRPUlMgPSB7XG4gICAgJ25hdGl2ZSc6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgIHZhciBlbCA9ICRlbFswXVxuICAgICAgaWYgKGVsLmNoZWNrVmFsaWRpdHkpIHtcbiAgICAgICAgcmV0dXJuICFlbC5jaGVja1ZhbGlkaXR5KCkgJiYgIWVsLnZhbGlkaXR5LnZhbGlkICYmIChlbC52YWxpZGF0aW9uTWVzc2FnZSB8fCBcImVycm9yIVwiKVxuICAgICAgfVxuICAgIH0sXG4gICAgJ21hdGNoJzogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgdmFyIHRhcmdldCA9ICRlbC5hdHRyKCdkYXRhLW1hdGNoJylcbiAgICAgIHJldHVybiAkZWwudmFsKCkgIT09ICQodGFyZ2V0KS52YWwoKSAmJiBWYWxpZGF0b3IuREVGQVVMVFMuZXJyb3JzLm1hdGNoXG4gICAgfSxcbiAgICAnbWlubGVuZ3RoJzogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgdmFyIG1pbmxlbmd0aCA9ICRlbC5hdHRyKCdkYXRhLW1pbmxlbmd0aCcpXG4gICAgICByZXR1cm4gJGVsLnZhbCgpLmxlbmd0aCA8IG1pbmxlbmd0aCAmJiBWYWxpZGF0b3IuREVGQVVMVFMuZXJyb3JzLm1pbmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpc1xuXG4gICAgdGhpcy4kaW5wdXRzID0gdGhpcy4kZWxlbWVudC5maW5kKFZhbGlkYXRvci5JTlBVVF9TRUxFQ1RPUilcbiAgICAgIC5hZGQodGhpcy4kZWxlbWVudC5maW5kKCdbZGF0YS12YWxpZGF0ZT1cInRydWVcIl0nKSlcbiAgICAgIC5ub3QodGhpcy4kZWxlbWVudC5maW5kKCdbZGF0YS12YWxpZGF0ZT1cImZhbHNlXCJdJylcbiAgICAgICAgLmVhY2goZnVuY3Rpb24gKCkgeyBzZWxmLmNsZWFyRXJyb3JzKCQodGhpcykpIH0pXG4gICAgICApXG5cbiAgICB0aGlzLnRvZ2dsZVN1Ym1pdCgpXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5vbklucHV0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgc2VsZiAgICAgICAgPSB0aGlzXG4gICAgdmFyICRlbCAgICAgICAgID0gJChlLnRhcmdldClcbiAgICB2YXIgZGVmZXJFcnJvcnMgPSBlLnR5cGUgIT09ICdmb2N1c291dCdcblxuICAgIGlmICghdGhpcy4kaW5wdXRzLmlzKCRlbCkpIHJldHVyblxuXG4gICAgdGhpcy52YWxpZGF0ZUlucHV0KCRlbCwgZGVmZXJFcnJvcnMpLmRvbmUoZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi50b2dnbGVTdWJtaXQoKVxuICAgIH0pXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnZhbGlkYXRlSW5wdXQgPSBmdW5jdGlvbiAoJGVsLCBkZWZlckVycm9ycykge1xuICAgIHZhciB2YWx1ZSAgICAgID0gZ2V0VmFsdWUoJGVsKVxuICAgIHZhciBwcmV2RXJyb3JzID0gJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5lcnJvcnMnKVxuXG4gICAgaWYgKCRlbC5pcygnW3R5cGU9XCJyYWRpb1wiXScpKSAkZWwgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ2lucHV0W25hbWU9XCInICsgJGVsLmF0dHIoJ25hbWUnKSArICdcIl0nKVxuXG4gICAgdmFyIGUgPSAkLkV2ZW50KCd2YWxpZGF0ZS5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdfSlcbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcbiAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB2YXIgc2VsZiA9IHRoaXNcblxuICAgIHJldHVybiB0aGlzLnJ1blZhbGlkYXRvcnMoJGVsKS5kb25lKGZ1bmN0aW9uIChlcnJvcnMpIHtcbiAgICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJywgZXJyb3JzKVxuXG4gICAgICBlcnJvcnMubGVuZ3RoXG4gICAgICAgID8gZGVmZXJFcnJvcnMgPyBzZWxmLmRlZmVyKCRlbCwgc2VsZi5zaG93RXJyb3JzKSA6IHNlbGYuc2hvd0Vycm9ycygkZWwpXG4gICAgICAgIDogc2VsZi5jbGVhckVycm9ycygkZWwpXG5cbiAgICAgIGlmICghcHJldkVycm9ycyB8fCBlcnJvcnMudG9TdHJpbmcoKSAhPT0gcHJldkVycm9ycy50b1N0cmluZygpKSB7XG4gICAgICAgIGUgPSBlcnJvcnMubGVuZ3RoXG4gICAgICAgICAgPyAkLkV2ZW50KCdpbnZhbGlkLmJzLnZhbGlkYXRvcicsIHtyZWxhdGVkVGFyZ2V0OiAkZWxbMF0sIGRldGFpbDogZXJyb3JzfSlcbiAgICAgICAgICA6ICQuRXZlbnQoJ3ZhbGlkLmJzLnZhbGlkYXRvcicsIHtyZWxhdGVkVGFyZ2V0OiAkZWxbMF0sIGRldGFpbDogcHJldkVycm9yc30pXG5cbiAgICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKGUpXG4gICAgICB9XG5cbiAgICAgIHNlbGYudG9nZ2xlU3VibWl0KClcblxuICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKCQuRXZlbnQoJ3ZhbGlkYXRlZC5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdfSkpXG4gICAgfSlcbiAgfVxuXG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5ydW5WYWxpZGF0b3JzID0gZnVuY3Rpb24gKCRlbCkge1xuICAgIHZhciBlcnJvcnMgICA9IFtdXG4gICAgdmFyIGRlZmVycmVkID0gJC5EZWZlcnJlZCgpXG5cbiAgICAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmRlZmVycmVkJykgJiYgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCcpLnJlamVjdCgpXG4gICAgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCcsIGRlZmVycmVkKVxuXG4gICAgZnVuY3Rpb24gZ2V0VmFsaWRhdG9yU3BlY2lmaWNFcnJvcihrZXkpIHtcbiAgICAgIHJldHVybiAkZWwuYXR0cignZGF0YS0nICsga2V5ICsgJy1lcnJvcicpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VmFsaWRpdHlTdGF0ZUVycm9yKCkge1xuICAgICAgdmFyIHZhbGlkaXR5ID0gJGVsWzBdLnZhbGlkaXR5XG4gICAgICByZXR1cm4gdmFsaWRpdHkudHlwZU1pc21hdGNoICAgID8gJGVsLmF0dHIoJ2RhdGEtdHlwZS1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkucGF0dGVybk1pc21hdGNoID8gJGVsLmF0dHIoJ2RhdGEtcGF0dGVybi1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkuc3RlcE1pc21hdGNoICAgID8gJGVsLmF0dHIoJ2RhdGEtc3RlcC1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkucmFuZ2VPdmVyZmxvdyAgID8gJGVsLmF0dHIoJ2RhdGEtbWF4LWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS5yYW5nZVVuZGVyZmxvdyAgPyAkZWwuYXR0cignZGF0YS1taW4tZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnZhbHVlTWlzc2luZyAgICA/ICRlbC5hdHRyKCdkYXRhLXJlcXVpcmVkLWVycm9yJylcbiAgICAgICAgICAgOiAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWxsXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0R2VuZXJpY0Vycm9yKCkge1xuICAgICAgcmV0dXJuICRlbC5hdHRyKCdkYXRhLWVycm9yJylcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRFcnJvck1lc3NhZ2Uoa2V5KSB7XG4gICAgICByZXR1cm4gZ2V0VmFsaWRhdG9yU3BlY2lmaWNFcnJvcihrZXkpXG4gICAgICAgICAgfHwgZ2V0VmFsaWRpdHlTdGF0ZUVycm9yKClcbiAgICAgICAgICB8fCBnZXRHZW5lcmljRXJyb3IoKVxuICAgIH1cblxuICAgICQuZWFjaCh0aGlzLnZhbGlkYXRvcnMsICQucHJveHkoZnVuY3Rpb24gKGtleSwgdmFsaWRhdG9yKSB7XG4gICAgICB2YXIgZXJyb3IgPSBudWxsXG4gICAgICBpZiAoKGdldFZhbHVlKCRlbCkgfHwgJGVsLmF0dHIoJ3JlcXVpcmVkJykpICYmXG4gICAgICAgICAgKCRlbC5hdHRyKCdkYXRhLScgKyBrZXkpICE9PSB1bmRlZmluZWQgfHwga2V5ID09ICduYXRpdmUnKSAmJlxuICAgICAgICAgIChlcnJvciA9IHZhbGlkYXRvci5jYWxsKHRoaXMsICRlbCkpKSB7XG4gICAgICAgICBlcnJvciA9IGdldEVycm9yTWVzc2FnZShrZXkpIHx8IGVycm9yXG4gICAgICAgICF+ZXJyb3JzLmluZGV4T2YoZXJyb3IpICYmIGVycm9ycy5wdXNoKGVycm9yKVxuICAgICAgfVxuICAgIH0sIHRoaXMpKVxuXG4gICAgaWYgKCFlcnJvcnMubGVuZ3RoICYmIGdldFZhbHVlKCRlbCkgJiYgJGVsLmF0dHIoJ2RhdGEtcmVtb3RlJykpIHtcbiAgICAgIHRoaXMuZGVmZXIoJGVsLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkYXRhID0ge31cbiAgICAgICAgZGF0YVskZWwuYXR0cignbmFtZScpXSA9IGdldFZhbHVlKCRlbClcbiAgICAgICAgJC5nZXQoJGVsLmF0dHIoJ2RhdGEtcmVtb3RlJyksIGRhdGEpXG4gICAgICAgICAgLmZhaWwoZnVuY3Rpb24gKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvcikgeyBlcnJvcnMucHVzaChnZXRFcnJvck1lc3NhZ2UoJ3JlbW90ZScpIHx8IGVycm9yKSB9KVxuICAgICAgICAgIC5hbHdheXMoZnVuY3Rpb24gKCkgeyBkZWZlcnJlZC5yZXNvbHZlKGVycm9ycyl9KVxuICAgICAgfSlcbiAgICB9IGVsc2UgZGVmZXJyZWQucmVzb2x2ZShlcnJvcnMpXG5cbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZSgpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpc1xuXG4gICAgJC53aGVuKHRoaXMuJGlucHV0cy5tYXAoZnVuY3Rpb24gKGVsKSB7XG4gICAgICByZXR1cm4gc2VsZi52YWxpZGF0ZUlucHV0KCQodGhpcyksIGZhbHNlKVxuICAgIH0pKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYudG9nZ2xlU3VibWl0KClcbiAgICAgIHNlbGYuZm9jdXNFcnJvcigpXG4gICAgfSlcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmZvY3VzRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZm9jdXMpIHJldHVyblxuXG4gICAgdmFyICRpbnB1dCA9IHRoaXMuJGVsZW1lbnQuZmluZChcIi5oYXMtZXJyb3I6Zmlyc3QgOmlucHV0XCIpXG4gICAgaWYgKCRpbnB1dC5sZW5ndGggPT09IDApIHJldHVyblxuXG4gICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoe3Njcm9sbFRvcDogJGlucHV0Lm9mZnNldCgpLnRvcCAtIFZhbGlkYXRvci5GT0NVU19PRkZTRVR9LCAyNTApXG4gICAgJGlucHV0LmZvY3VzKClcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuc2hvd0Vycm9ycyA9IGZ1bmN0aW9uICgkZWwpIHtcbiAgICB2YXIgbWV0aG9kID0gdGhpcy5vcHRpb25zLmh0bWwgPyAnaHRtbCcgOiAndGV4dCdcbiAgICB2YXIgZXJyb3JzID0gJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5lcnJvcnMnKVxuICAgIHZhciAkZ3JvdXAgPSAkZWwuY2xvc2VzdCgnLmZvcm0tZ3JvdXAnKVxuICAgIHZhciAkYmxvY2sgPSAkZ3JvdXAuZmluZCgnLmhlbHAtYmxvY2sud2l0aC1lcnJvcnMnKVxuICAgIHZhciAkZmVlZGJhY2sgPSAkZ3JvdXAuZmluZCgnLmZvcm0tY29udHJvbC1mZWVkYmFjaycpXG5cbiAgICBpZiAoIWVycm9ycy5sZW5ndGgpIHJldHVyblxuXG4gICAgZXJyb3JzID0gJCgnPHVsLz4nKVxuICAgICAgLmFkZENsYXNzKCdsaXN0LXVuc3R5bGVkJylcbiAgICAgIC5hcHBlbmQoJC5tYXAoZXJyb3JzLCBmdW5jdGlvbiAoZXJyb3IpIHsgcmV0dXJuICQoJzxsaS8+JylbbWV0aG9kXShlcnJvcikgfSkpXG5cbiAgICAkYmxvY2suZGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpID09PSB1bmRlZmluZWQgJiYgJGJsb2NrLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnLCAkYmxvY2suaHRtbCgpKVxuICAgICRibG9jay5lbXB0eSgpLmFwcGVuZChlcnJvcnMpXG4gICAgJGdyb3VwLmFkZENsYXNzKCdoYXMtZXJyb3IgaGFzLWRhbmdlcicpXG5cbiAgICAkZ3JvdXAuaGFzQ2xhc3MoJ2hhcy1mZWVkYmFjaycpXG4gICAgICAmJiAkZmVlZGJhY2sucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG4gICAgICAmJiAkZmVlZGJhY2suYWRkQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLmVycm9yKVxuICAgICAgJiYgJGdyb3VwLnJlbW92ZUNsYXNzKCdoYXMtc3VjY2VzcycpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmNsZWFyRXJyb3JzID0gZnVuY3Rpb24gKCRlbCkge1xuICAgIHZhciAkZ3JvdXAgPSAkZWwuY2xvc2VzdCgnLmZvcm0tZ3JvdXAnKVxuICAgIHZhciAkYmxvY2sgPSAkZ3JvdXAuZmluZCgnLmhlbHAtYmxvY2sud2l0aC1lcnJvcnMnKVxuICAgIHZhciAkZmVlZGJhY2sgPSAkZ3JvdXAuZmluZCgnLmZvcm0tY29udHJvbC1mZWVkYmFjaycpXG5cbiAgICAkYmxvY2suaHRtbCgkYmxvY2suZGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpKVxuICAgICRncm91cC5yZW1vdmVDbGFzcygnaGFzLWVycm9yIGhhcy1kYW5nZXIgaGFzLXN1Y2Nlc3MnKVxuXG4gICAgJGdyb3VwLmhhc0NsYXNzKCdoYXMtZmVlZGJhY2snKVxuICAgICAgJiYgJGZlZWRiYWNrLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5lcnJvcilcbiAgICAgICYmICRmZWVkYmFjay5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suc3VjY2VzcylcbiAgICAgICYmIGdldFZhbHVlKCRlbClcbiAgICAgICYmICRmZWVkYmFjay5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suc3VjY2VzcylcbiAgICAgICYmICRncm91cC5hZGRDbGFzcygnaGFzLXN1Y2Nlc3MnKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5oYXNFcnJvcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gZmllbGRFcnJvcnMoKSB7XG4gICAgICByZXR1cm4gISEoJCh0aGlzKS5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJykgfHwgW10pLmxlbmd0aFxuICAgIH1cblxuICAgIHJldHVybiAhIXRoaXMuJGlucHV0cy5maWx0ZXIoZmllbGRFcnJvcnMpLmxlbmd0aFxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5pc0luY29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gZmllbGRJbmNvbXBsZXRlKCkge1xuICAgICAgdmFyIHZhbHVlID0gZ2V0VmFsdWUoJCh0aGlzKSlcbiAgICAgIHJldHVybiAhKHR5cGVvZiB2YWx1ZSA9PSBcInN0cmluZ1wiID8gJC50cmltKHZhbHVlKSA6IHZhbHVlKVxuICAgIH1cblxuICAgIHJldHVybiAhIXRoaXMuJGlucHV0cy5maWx0ZXIoJ1tyZXF1aXJlZF0nKS5maWx0ZXIoZmllbGRJbmNvbXBsZXRlKS5sZW5ndGhcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUub25TdWJtaXQgPSBmdW5jdGlvbiAoZSkge1xuICAgIHRoaXMudmFsaWRhdGUoKVxuICAgIGlmICh0aGlzLmlzSW5jb21wbGV0ZSgpIHx8IHRoaXMuaGFzRXJyb3JzKCkpIGUucHJldmVudERlZmF1bHQoKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS50b2dnbGVTdWJtaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZGlzYWJsZSkgcmV0dXJuXG4gICAgdGhpcy4kYnRuLnRvZ2dsZUNsYXNzKCdkaXNhYmxlZCcsIHRoaXMuaXNJbmNvbXBsZXRlKCkgfHwgdGhpcy5oYXNFcnJvcnMoKSlcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuZGVmZXIgPSBmdW5jdGlvbiAoJGVsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gJC5wcm94eShjYWxsYmFjaywgdGhpcywgJGVsKVxuICAgIGlmICghdGhpcy5vcHRpb25zLmRlbGF5KSByZXR1cm4gY2FsbGJhY2soKVxuICAgIHdpbmRvdy5jbGVhclRpbWVvdXQoJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci50aW1lb3V0JykpXG4gICAgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci50aW1lb3V0Jywgd2luZG93LnNldFRpbWVvdXQoY2FsbGJhY2ssIHRoaXMub3B0aW9ucy5kZWxheSkpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnLmZvcm0tY29udHJvbC1mZWVkYmFjaycpXG4gICAgICAucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLmVycm9yKVxuICAgICAgLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5zdWNjZXNzKVxuXG4gICAgdGhpcy4kaW5wdXRzXG4gICAgICAucmVtb3ZlRGF0YShbJ2JzLnZhbGlkYXRvci5lcnJvcnMnLCAnYnMudmFsaWRhdG9yLmRlZmVycmVkJ10pXG4gICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcylcbiAgICAgICAgdmFyIHRpbWVvdXQgPSAkdGhpcy5kYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcpXG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGltZW91dCkgJiYgJHRoaXMucmVtb3ZlRGF0YSgnYnMudmFsaWRhdG9yLnRpbWVvdXQnKVxuICAgICAgfSlcblxuICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnLmhlbHAtYmxvY2sud2l0aC1lcnJvcnMnKVxuICAgICAgLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICAgIHZhciBvcmlnaW5hbENvbnRlbnQgPSAkdGhpcy5kYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JylcblxuICAgICAgICAkdGhpc1xuICAgICAgICAgIC5yZW1vdmVEYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JylcbiAgICAgICAgICAuaHRtbChvcmlnaW5hbENvbnRlbnQpXG4gICAgICB9KVxuXG4gICAgdGhpcy4kYnRuLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpXG5cbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJy5oYXMtZXJyb3IsIC5oYXMtZGFuZ2VyLCAuaGFzLXN1Y2Nlc3MnKS5yZW1vdmVDbGFzcygnaGFzLWVycm9yIGhhcy1kYW5nZXIgaGFzLXN1Y2Nlc3MnKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnJlc2V0KClcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIC5yZW1vdmVBdHRyKCdub3ZhbGlkYXRlJylcbiAgICAgIC5yZW1vdmVEYXRhKCdicy52YWxpZGF0b3InKVxuICAgICAgLm9mZignLmJzLnZhbGlkYXRvcicpXG5cbiAgICB0aGlzLiRpbnB1dHNcbiAgICAgIC5vZmYoJy5icy52YWxpZGF0b3InKVxuXG4gICAgdGhpcy5vcHRpb25zICAgID0gbnVsbFxuICAgIHRoaXMudmFsaWRhdG9ycyA9IG51bGxcbiAgICB0aGlzLiRlbGVtZW50ICAgPSBudWxsXG4gICAgdGhpcy4kYnRuICAgICAgID0gbnVsbFxuICAgIHRoaXMuJGlucHV0cyAgICA9IG51bGxcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvLyBWQUxJREFUT1IgUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sIFZhbGlkYXRvci5ERUZBVUxUUywgJHRoaXMuZGF0YSgpLCB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvbilcbiAgICAgIHZhciBkYXRhICAgID0gJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yJylcblxuICAgICAgaWYgKCFkYXRhICYmIG9wdGlvbiA9PSAnZGVzdHJveScpIHJldHVyblxuICAgICAgaWYgKCFkYXRhKSAkdGhpcy5kYXRhKCdicy52YWxpZGF0b3InLCAoZGF0YSA9IG5ldyBWYWxpZGF0b3IodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLnZhbGlkYXRvclxuXG4gICQuZm4udmFsaWRhdG9yICAgICAgICAgICAgID0gUGx1Z2luXG4gICQuZm4udmFsaWRhdG9yLkNvbnN0cnVjdG9yID0gVmFsaWRhdG9yXG5cblxuICAvLyBWQUxJREFUT1IgTk8gQ09ORkxJQ1RcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi52YWxpZGF0b3Iubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkLmZuLnZhbGlkYXRvciA9IG9sZFxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuXG4gIC8vIFZBTElEQVRPUiBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PT09PT1cblxuICAkKHdpbmRvdykub24oJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgJCgnZm9ybVtkYXRhLXRvZ2dsZT1cInZhbGlkYXRvclwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICRmb3JtID0gJCh0aGlzKVxuICAgICAgUGx1Z2luLmNhbGwoJGZvcm0sICRmb3JtLmRhdGEoKSlcbiAgICB9KVxuICB9KVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtdmFsaWRhdG9yL2pzL3ZhbGlkYXRvci5qc1xuLy8gbW9kdWxlIGlkID0gNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAqIGJvb3RzdHJhcC1maWxlaW5wdXQgdjQuNC4yXG4gKiBodHRwOi8vcGx1Z2lucy5rcmFqZWUuY29tL2ZpbGUtaW5wdXRcbiAqXG4gKiBBdXRob3I6IEthcnRpayBWaXN3ZXN3YXJhblxuICogQ29weXJpZ2h0OiAyMDE0IC0gMjAxNywgS2FydGlrIFZpc3dlc3dhcmFuLCBLcmFqZWUuY29tXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEJTRCAzLUNsYXVzZVxuICogaHR0cHM6Ly9naXRodWIuY29tL2thcnRpay12L2Jvb3RzdHJhcC1maWxlaW5wdXQvYmxvYi9tYXN0ZXIvTElDRU5TRS5tZFxuICovXG4oZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAvL25vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgIC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cbiAgICAgICAgZGVmaW5lKFsnanF1ZXJ5J10sIGZhY3RvcnkpOyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICB9IGVsc2UgeyAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICAgICAgLy8gTm9kZS9Db21tb25KU1xuICAgICAgICAgICAgLy8gbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZSgnanF1ZXJ5JykpOyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEJyb3dzZXIgZ2xvYmFsc1xuICAgICAgICAgICAgZmFjdG9yeSh3aW5kb3cualF1ZXJ5KTtcbiAgICAgICAgfVxuICAgIH1cbn0oZnVuY3Rpb24gKCQpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICQuZm4uZmlsZWlucHV0TG9jYWxlcyA9IHt9O1xuICAgICQuZm4uZmlsZWlucHV0VGhlbWVzID0ge307XG5cbiAgICBTdHJpbmcucHJvdG90eXBlLnNldFRva2VucyA9IGZ1bmN0aW9uIChyZXBsYWNlUGFpcnMpIHtcbiAgICAgICAgdmFyIHN0ciA9IHRoaXMudG9TdHJpbmcoKSwga2V5LCByZTtcbiAgICAgICAgZm9yIChrZXkgaW4gcmVwbGFjZVBhaXJzKSB7XG4gICAgICAgICAgICBpZiAocmVwbGFjZVBhaXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICByZSA9IG5ldyBSZWdFeHAoXCJcXHtcIiArIGtleSArIFwiXFx9XCIsIFwiZ1wiKTtcbiAgICAgICAgICAgICAgICBzdHIgPSBzdHIucmVwbGFjZShyZSwgcmVwbGFjZVBhaXJzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfTtcblxuICAgIHZhciAkaCwgRmlsZUlucHV0O1xuXG4gICAgLy8gZmlsZWlucHV0IGhlbHBlciBvYmplY3QgZm9yIGFsbCBnbG9iYWwgdmFyaWFibGVzIGFuZCBpbnRlcm5hbCBoZWxwZXIgbWV0aG9kc1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgJGggPSB7XG4gICAgICAgIEZSQU1FUzogJy5rdi1wcmV2aWV3LXRodW1iJyxcbiAgICAgICAgU09SVF9DU1M6ICdmaWxlLXNvcnRhYmxlJyxcbiAgICAgICAgU1RZTEVfU0VUVElORzogJ3N0eWxlPVwid2lkdGg6e3dpZHRofTtoZWlnaHQ6e2hlaWdodH07XCInLFxuICAgICAgICBPQkpFQ1RfUEFSQU1TOiAnPHBhcmFtIG5hbWU9XCJjb250cm9sbGVyXCIgdmFsdWU9XCJ0cnVlXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYWxsb3dGdWxsU2NyZWVuXCIgdmFsdWU9XCJ0cnVlXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYWxsb3dTY3JpcHRBY2Nlc3NcIiB2YWx1ZT1cImFsd2F5c1wiIC8+XFxuJyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cImF1dG9QbGF5XCIgdmFsdWU9XCJmYWxzZVwiIC8+XFxuJyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cImF1dG9TdGFydFwiIHZhbHVlPVwiZmFsc2VcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJxdWFsaXR5XCIgdmFsdWU9XCJoaWdoXCIgLz5cXG4nLFxuICAgICAgICBERUZBVUxUX1BSRVZJRVc6ICc8ZGl2IGNsYXNzPVwiZmlsZS1wcmV2aWV3LW90aGVyXCI+XFxuJyArXG4gICAgICAgICc8c3BhbiBjbGFzcz1cIntwcmV2aWV3RmlsZUljb25DbGFzc31cIj57cHJldmlld0ZpbGVJY29ufTwvc3Bhbj5cXG4nICtcbiAgICAgICAgJzwvZGl2PicsXG4gICAgICAgIE1PREFMX0lEOiAna3ZGaWxlaW5wdXRNb2RhbCcsXG4gICAgICAgIE1PREFMX0VWRU5UUzogWydzaG93JywgJ3Nob3duJywgJ2hpZGUnLCAnaGlkZGVuJywgJ2xvYWRlZCddLFxuICAgICAgICBvYmpVcmw6IHdpbmRvdy5VUkwgfHwgd2luZG93LndlYmtpdFVSTCxcbiAgICAgICAgY29tcGFyZTogZnVuY3Rpb24gKGlucHV0LCBzdHIsIGV4YWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgIT09IHVuZGVmaW5lZCAmJiAoZXhhY3QgPyBpbnB1dCA9PT0gc3RyIDogaW5wdXQubWF0Y2goc3RyKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGlzSUU6IGZ1bmN0aW9uICh2ZXIpIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIGZvciBJRSB2ZXJzaW9ucyA8IDExXG4gICAgICAgICAgICBpZiAobmF2aWdhdG9yLmFwcE5hbWUgIT09ICdNaWNyb3NvZnQgSW50ZXJuZXQgRXhwbG9yZXInKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHZlciA9PT0gMTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cCgnbXNpZVxcXFxzJyArIHZlciwgJ2knKS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiksIHN0YXR1cztcbiAgICAgICAgICAgIGRpdi5pbm5lckhUTUwgPSBcIjwhLS1baWYgSUUgXCIgKyB2ZXIgKyBcIl0+IDxpPjwvaT4gPCFbZW5kaWZdLS0+XCI7XG4gICAgICAgICAgICBzdGF0dXMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJpXCIpLmxlbmd0aDtcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICAgICAgICAgIGRpdi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpdik7XG4gICAgICAgICAgICByZXR1cm4gc3RhdHVzO1xuICAgICAgICB9LFxuICAgICAgICBpbml0TW9kYWw6IGZ1bmN0aW9uICgkbW9kYWwpIHtcbiAgICAgICAgICAgIHZhciAkYm9keSA9ICQoJ2JvZHknKTtcbiAgICAgICAgICAgIGlmICgkYm9keS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkbW9kYWwuYXBwZW5kVG8oJGJvZHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBpc0VtcHR5OiBmdW5jdGlvbiAodmFsdWUsIHRyaW0pIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsIHx8IHZhbHVlLmxlbmd0aCA9PT0gMCB8fCAodHJpbSAmJiAkLnRyaW0odmFsdWUpID09PSAnJyk7XG4gICAgICAgIH0sXG4gICAgICAgIGlzQXJyYXk6IGZ1bmN0aW9uIChhKSB7XG4gICAgICAgICAgICByZXR1cm4gQXJyYXkuaXNBcnJheShhKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYSkgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gICAgICAgIH0sXG4gICAgICAgIGlmU2V0OiBmdW5jdGlvbiAobmVlZGxlLCBoYXlzdGFjaywgZGVmKSB7XG4gICAgICAgICAgICBkZWYgPSBkZWYgfHwgJyc7XG4gICAgICAgICAgICByZXR1cm4gKGhheXN0YWNrICYmIHR5cGVvZiBoYXlzdGFjayA9PT0gJ29iamVjdCcgJiYgbmVlZGxlIGluIGhheXN0YWNrKSA/IGhheXN0YWNrW25lZWRsZV0gOiBkZWY7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFuQXJyYXk6IGZ1bmN0aW9uIChhcnIpIHtcbiAgICAgICAgICAgIGlmICghKGFyciBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIGFyciA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFyci5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGUgIT09IHVuZGVmaW5lZCAmJiBlICE9PSBudWxsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBzcGxpY2VBcnJheTogZnVuY3Rpb24gKGFyciwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBpLCBqID0gMCwgb3V0ID0gW107XG4gICAgICAgICAgICBpZiAoIShhcnIgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtqXSA9IGFycltpXTtcbiAgICAgICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIGdldE51bTogZnVuY3Rpb24gKG51bSwgZGVmKSB7XG4gICAgICAgICAgICBkZWYgPSBkZWYgfHwgMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbnVtID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbnVtID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgbnVtID0gcGFyc2VGbG9hdChudW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGlzTmFOKG51bSkgPyBkZWYgOiBudW07XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0ZpbGVBUElTdXBwb3J0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gISEod2luZG93LkZpbGUgJiYgd2luZG93LkZpbGVSZWFkZXIpO1xuICAgICAgICB9LFxuICAgICAgICBoYXNEcmFnRHJvcFN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRpdi5kcmFnZ2FibGUgKi9cbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRpdi5vbmRyYWdzdGFydCAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZGl2Lm9uZHJvcCAqL1xuICAgICAgICAgICAgcmV0dXJuICEkaC5pc0lFKDkpICYmXG4gICAgICAgICAgICAgICAgKGRpdi5kcmFnZ2FibGUgIT09IHVuZGVmaW5lZCB8fCAoZGl2Lm9uZHJhZ3N0YXJ0ICE9PSB1bmRlZmluZWQgJiYgZGl2Lm9uZHJvcCAhPT0gdW5kZWZpbmVkKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0ZpbGVVcGxvYWRTdXBwb3J0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJGguaGFzRmlsZUFQSVN1cHBvcnQoKSAmJiB3aW5kb3cuRm9ybURhdGE7XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0Jsb2JTdXBwb3J0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhIXdpbmRvdy5CbG9iICYmIEJvb2xlYW4obmV3IEJsb2IoKSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBoYXNBcnJheUJ1ZmZlclZpZXdTdXBwb3J0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvYihbbmV3IFVpbnQ4QXJyYXkoMTAwKV0pLnNpemUgPT09IDEwMDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGRhdGFVUkkyQmxvYjogZnVuY3Rpb24gKGRhdGFVUkkpIHtcbiAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgICAgICAgICB2YXIgQmxvYkJ1aWxkZXIgPSB3aW5kb3cuQmxvYkJ1aWxkZXIgfHwgd2luZG93LldlYktpdEJsb2JCdWlsZGVyIHx8IHdpbmRvdy5Nb3pCbG9iQnVpbGRlciB8fFxuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuTVNCbG9iQnVpbGRlciwgY2FuQmxvYiA9ICRoLmhhc0Jsb2JTdXBwb3J0KCksIGJ5dGVTdHIsIGFycmF5QnVmZmVyLCBpbnRBcnJheSwgaSwgbWltZVN0ciwgYmIsXG4gICAgICAgICAgICAgICAgY2FuUHJvY2VlZCA9IChjYW5CbG9iIHx8IEJsb2JCdWlsZGVyKSAmJiB3aW5kb3cuYXRvYiAmJiB3aW5kb3cuQXJyYXlCdWZmZXIgJiYgd2luZG93LlVpbnQ4QXJyYXk7XG4gICAgICAgICAgICBpZiAoIWNhblByb2NlZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkYXRhVVJJLnNwbGl0KCcsJylbMF0uaW5kZXhPZignYmFzZTY0JykgPj0gMCkge1xuICAgICAgICAgICAgICAgIGJ5dGVTdHIgPSBhdG9iKGRhdGFVUkkuc3BsaXQoJywnKVsxXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ5dGVTdHIgPSBkZWNvZGVVUklDb21wb25lbnQoZGF0YVVSSS5zcGxpdCgnLCcpWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFycmF5QnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVTdHIubGVuZ3RoKTtcbiAgICAgICAgICAgIGludEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGJ5dGVTdHIubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICBpbnRBcnJheVtpXSA9IGJ5dGVTdHIuY2hhckNvZGVBdChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pbWVTdHIgPSBkYXRhVVJJLnNwbGl0KCcsJylbMF0uc3BsaXQoJzonKVsxXS5zcGxpdCgnOycpWzBdO1xuICAgICAgICAgICAgaWYgKGNhbkJsb2IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJsb2IoWyRoLmhhc0FycmF5QnVmZmVyVmlld1N1cHBvcnQoKSA/IGludEFycmF5IDogYXJyYXlCdWZmZXJdLCB7dHlwZTogbWltZVN0cn0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYmIgPSBuZXcgQmxvYkJ1aWxkZXIoKTtcbiAgICAgICAgICAgIGJiLmFwcGVuZChhcnJheUJ1ZmZlcik7XG4gICAgICAgICAgICByZXR1cm4gYmIuZ2V0QmxvYihtaW1lU3RyKTtcbiAgICAgICAgfSxcbiAgICAgICAgYWRkQ3NzOiBmdW5jdGlvbiAoJGVsLCBjc3MpIHtcbiAgICAgICAgICAgICRlbC5yZW1vdmVDbGFzcyhjc3MpLmFkZENsYXNzKGNzcyk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldEVsZW1lbnQ6IGZ1bmN0aW9uIChvcHRpb25zLCBwYXJhbSwgdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAoJGguaXNFbXB0eShvcHRpb25zKSB8fCAkaC5pc0VtcHR5KG9wdGlvbnNbcGFyYW1dKSkgPyB2YWx1ZSA6ICQob3B0aW9uc1twYXJhbV0pO1xuICAgICAgICB9LFxuICAgICAgICB1bmlxSWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpICsgKE1hdGgucmFuZG9tKCkgKiAxMDApKTtcbiAgICAgICAgfSxcbiAgICAgICAgaHRtbEVuY29kZTogZnVuY3Rpb24gKHN0cikge1xuICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLycvZywgJyZhcG9zOycpO1xuICAgICAgICB9LFxuICAgICAgICByZXBsYWNlVGFnczogZnVuY3Rpb24gKHN0ciwgdGFncykge1xuICAgICAgICAgICAgdmFyIG91dCA9IHN0cjtcbiAgICAgICAgICAgIGlmICghdGFncykge1xuICAgICAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmVhY2godGFncywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvdXQgPSBvdXQuc3BsaXQoa2V5KS5qb2luKHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSxcbiAgICAgICAgY2xlYW5NZW1vcnk6IGZ1bmN0aW9uICgkdGh1bWIpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gJHRodW1iLmlzKCdpbWcnKSA/ICR0aHVtYi5hdHRyKCdzcmMnKSA6ICR0aHVtYi5maW5kKCdzb3VyY2UnKS5hdHRyKCdzcmMnKTtcbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlICRoLm9ialVybC5yZXZva2VPYmplY3RVUkwgKi9cbiAgICAgICAgICAgICRoLm9ialVybC5yZXZva2VPYmplY3RVUkwoZGF0YSk7XG4gICAgICAgIH0sXG4gICAgICAgIGZpbmRGaWxlTmFtZTogZnVuY3Rpb24gKGZpbGVQYXRoKSB7XG4gICAgICAgICAgICB2YXIgc2VwSW5kZXggPSBmaWxlUGF0aC5sYXN0SW5kZXhPZignLycpO1xuICAgICAgICAgICAgaWYgKHNlcEluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHNlcEluZGV4ID0gZmlsZVBhdGgubGFzdEluZGV4T2YoJ1xcXFwnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmaWxlUGF0aC5zcGxpdChmaWxlUGF0aC5zdWJzdHJpbmcoc2VwSW5kZXgsIHNlcEluZGV4ICsgMSkpLnBvcCgpO1xuICAgICAgICB9LFxuICAgICAgICBjaGVja0Z1bGxTY3JlZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgICAgICAgICByZXR1cm4gZG9jdW1lbnQuZnVsbHNjcmVlbkVsZW1lbnQgfHwgZG9jdW1lbnQubW96RnVsbFNjcmVlbkVsZW1lbnQgfHwgZG9jdW1lbnQud2Via2l0RnVsbHNjcmVlbkVsZW1lbnQgfHxcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5tc0Z1bGxzY3JlZW5FbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICB0b2dnbGVGdWxsU2NyZWVuOiBmdW5jdGlvbiAobWF4aW1pemUpIHtcbiAgICAgICAgICAgIHZhciBkb2MgPSBkb2N1bWVudCwgZGUgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICAgICAgaWYgKGRlICYmIG1heGltaXplICYmICEkaC5jaGVja0Z1bGxTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50LnJlcXVlc3RGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubXNSZXF1ZXN0RnVsbHNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50Lm1velJlcXVlc3RGdWxsU2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQud2Via2l0UmVxdWVzdEZ1bGxzY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBFbGVtZW50LkFMTE9XX0tFWUJPQVJEX0lOUFVUICovXG4gICAgICAgICAgICAgICAgaWYgKGRlLnJlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlLnJlcXVlc3RGdWxsc2NyZWVuKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkZS5tc1JlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlLm1zUmVxdWVzdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlLm1velJlcXVlc3RGdWxsU2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlLm1velJlcXVlc3RGdWxsU2NyZWVuKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkZS53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkZS53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbihFbGVtZW50LkFMTE9XX0tFWUJPQVJEX0lOUFVUKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50LmV4aXRGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubXNFeGl0RnVsbHNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50Lm1vekNhbmNlbEZ1bGxTY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC53ZWJraXRFeGl0RnVsbHNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIGlmIChkb2MuZXhpdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jLmV4aXRGdWxsc2NyZWVuKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkb2MubXNFeGl0RnVsbHNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2MubXNFeGl0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jLm1vekNhbmNlbEZ1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jLm1vekNhbmNlbEZ1bGxTY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRvYy53ZWJraXRFeGl0RnVsbHNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2Mud2Via2l0RXhpdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1vdmVBcnJheTogZnVuY3Rpb24gKGFyciwgb2xkSW5kZXgsIG5ld0luZGV4KSB7XG4gICAgICAgICAgICBpZiAobmV3SW5kZXggPj0gYXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciBrID0gbmV3SW5kZXggLSBhcnIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHdoaWxlICgoay0tKSArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJyLnB1c2godW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhcnIuc3BsaWNlKG5ld0luZGV4LCAwLCBhcnIuc3BsaWNlKG9sZEluZGV4LCAxKVswXSk7XG4gICAgICAgICAgICByZXR1cm4gYXJyO1xuICAgICAgICB9LFxuICAgICAgICBjbGVhblpvb21DYWNoZTogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgICAgICAgdmFyICRjYWNoZSA9ICRlbC5jbG9zZXN0KCcua3Ytem9vbS1jYWNoZS10aGVtZScpO1xuICAgICAgICAgICAgaWYgKCEkY2FjaGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGNhY2hlID0gJGVsLmNsb3Nlc3QoJy5rdi16b29tLWNhY2hlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkY2FjaGUucmVtb3ZlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldE9yaWVudGF0aW9uOiBmdW5jdGlvbiAoYnVmZmVyLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNjYW5uZXIgPSBuZXcgRGF0YVZpZXcoYnVmZmVyKSwgaWR4ID0gMCwgdmFsdWUgPSAxLCAvLyBOb24tcm90YXRlZCBpcyB0aGUgZGVmYXVsdFxuICAgICAgICAgICAgICAgIG1heEJ5dGVzLCB1SW50MTYsIGV4aWZMZW5ndGg7XG4gICAgICAgICAgICBpZiAoc2Nhbm5lci5nZXRVaW50MTYoaWR4KSAhPT0gMHhGRkQ4IHx8IGJ1ZmZlci5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBub3QgYSBwcm9wZXIgSlBFR1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDI7XG4gICAgICAgICAgICBtYXhCeXRlcyA9IHNjYW5uZXIuYnl0ZUxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpZHggPCBtYXhCeXRlcyAtIDIpIHtcbiAgICAgICAgICAgICAgICB1SW50MTYgPSBzY2FubmVyLmdldFVpbnQxNihpZHgpO1xuICAgICAgICAgICAgICAgIGlkeCArPSAyO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodUludDE2KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMHhGRkUxOiAvLyBTdGFydCBvZiBFWElGXG4gICAgICAgICAgICAgICAgICAgICAgICBleGlmTGVuZ3RoID0gc2Nhbm5lci5nZXRVaW50MTYoaWR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEJ5dGVzID0gZXhpZkxlbmd0aCAtIGlkeDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCArPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMHgwMTEyOiAvLyBPcmllbnRhdGlvbiB0YWdcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gc2Nhbm5lci5nZXRVaW50MTYoaWR4ICsgNiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qnl0ZXMgPSAwOyAvLyBTdG9wIHNjYW5uaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHZhbGlkYXRlT3JpZW50YXRpb246IGZ1bmN0aW9uIChmaWxlLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKCF3aW5kb3cuRmlsZVJlYWRlciB8fCAhd2luZG93LkRhdGFWaWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBza2lwIG9yaWVudGF0aW9uIGlmIHByZS1yZXF1aXNpdGUgbGlicmFyaWVzIG5vdCBzdXBwb3J0ZWQgYnkgYnJvd3NlclxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCksIGJ1ZmZlcjtcbiAgICAgICAgICAgIHJlYWRlci5vbmxvYWRlbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgYnVmZmVyID0gcmVhZGVyLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAkaC5zZXRPcmllbnRhdGlvbihidWZmZXIsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoZmlsZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFkanVzdE9yaWVudGVkSW1hZ2U6IGZ1bmN0aW9uICgkaW1nLCBpc1pvb20pIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXRDb250VG9wLCBvZmZzZXRUb3AsIG5ld1RvcDtcbiAgICAgICAgICAgIGlmICghJGltZy5oYXNDbGFzcygnaXMtcG9ydHJhaXQtZ3Q0JykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNab29tKSB7XG4gICAgICAgICAgICAgICAgJGltZy5jc3Moe3dpZHRoOiAkaW1nLnBhcmVudCgpLmhlaWdodCgpfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkaW1nLmNzcyh7aGVpZ2h0OiAnYXV0bycsIHdpZHRoOiAkaW1nLmhlaWdodCgpfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvZmZzZXRDb250VG9wID0gJGltZy5wYXJlbnQoKS5vZmZzZXQoKS50b3A7XG4gICAgICAgICAgICBvZmZzZXRUb3AgPSAkaW1nLm9mZnNldCgpLnRvcDtcbiAgICAgICAgICAgIG5ld1RvcCA9IG9mZnNldENvbnRUb3AgLSBvZmZzZXRUb3A7XG4gICAgICAgICAgICAkaW1nLmNzcygnbWFyZ2luLXRvcCcsIG5ld1RvcCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbGVJbnB1dCA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgc2VsZi4kZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgICAgIGlmICghc2VsZi5fdmFsaWRhdGUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHNlbGYuaXNQcmV2aWV3YWJsZSA9ICRoLmhhc0ZpbGVBUElTdXBwb3J0KCk7XG4gICAgICAgIHNlbGYuaXNJRTkgPSAkaC5pc0lFKDkpO1xuICAgICAgICBzZWxmLmlzSUUxMCA9ICRoLmlzSUUoMTApO1xuICAgICAgICBpZiAoc2VsZi5pc1ByZXZpZXdhYmxlIHx8IHNlbGYuaXNJRTkpIHtcbiAgICAgICAgICAgIHNlbGYuX2luaXQob3B0aW9ucyk7XG4gICAgICAgICAgICBzZWxmLl9saXN0ZW4oKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZpbGUtbG9hZGluZycpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvL25vaW5zcGVjdGlvbiBKU1VudXNlZEdsb2JhbFN5bWJvbHNcbiAgICBGaWxlSW5wdXQucHJvdG90eXBlID0ge1xuICAgICAgICBjb25zdHJ1Y3RvcjogRmlsZUlucHV0LFxuICAgICAgICBfY2xlYW51cDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5yZWFkZXIgPSBudWxsO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IHt9O1xuICAgICAgICAgICAgc2VsZi51cGxvYWRDb3VudCA9IDA7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1cyA9IHt9O1xuICAgICAgICAgICAgc2VsZi51cGxvYWRMb2cgPSBbXTtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkQXN5bmNDb3VudCA9IDA7XG4gICAgICAgICAgICBzZWxmLmxvYWRlZEltYWdlcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi50b3RhbEltYWdlc0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYuYWpheFJlcXVlc3RzID0gW107XG4gICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgIHNlbGYuZmlsZUlucHV0Q2xlYXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzUHJldmlld2FibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnNob3dQcmV2aWV3ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuY2FuY2VsbGluZyA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kZWxlbWVudCwgJGNvbnQsIHQsIHRtcDtcbiAgICAgICAgICAgIHNlbGYub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgICAgICAkLmVhY2gob3B0aW9ucywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdtaW5GaWxlQ291bnQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtYXhGaWxlQ291bnQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtaW5GaWxlU2l6ZSc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21heEZpbGVTaXplJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4RmlsZVByZXZpZXdTaXplJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVzaXplSW1hZ2VRdWFsaXR5JzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVzaXplSWZTaXplTW9yZVRoYW4nOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdwcm9ncmVzc1VwbG9hZFRocmVzaG9sZCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2luaXRpYWxQcmV2aWV3Q291bnQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICd6b29tTW9kYWxIZWlnaHQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtaW5JbWFnZUhlaWdodCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21heEltYWdlSGVpZ2h0JzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWluSW1hZ2VXaWR0aCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21heEltYWdlV2lkdGgnOlxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZltrZXldID0gJGguZ2V0TnVtKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZltrZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChzZWxmLnJ0bCkgeyAvLyBzd2FwIGJ1dHRvbnMgZm9yIHJ0bFxuICAgICAgICAgICAgICAgIHRtcCA9IHNlbGYucHJldmlld1pvb21CdXR0b25JY29ucy5wcmV2O1xuICAgICAgICAgICAgICAgIHNlbGYucHJldmlld1pvb21CdXR0b25JY29ucy5wcmV2ID0gc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLm5leHQ7XG4gICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLm5leHQgPSB0bXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9jbGVhbnVwKCk7XG4gICAgICAgICAgICBzZWxmLiRmb3JtID0gJGVsLmNsb3Nlc3QoJ2Zvcm0nKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRUZW1wbGF0ZURlZmF1bHRzKCk7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZEZpbGVBdHRyID0gISRoLmlzRW1wdHkoJGVsLmF0dHIoJ25hbWUnKSkgPyAkZWwuYXR0cignbmFtZScpIDogJ2ZpbGVfZGF0YSc7XG4gICAgICAgICAgICB0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ3Byb2dyZXNzJyk7XG4gICAgICAgICAgICBzZWxmLnByb2dyZXNzVGVtcGxhdGUgPSB0LnJlcGxhY2UoJ3tjbGFzc30nLCBzZWxmLnByb2dyZXNzQ2xhc3MpO1xuICAgICAgICAgICAgc2VsZi5wcm9ncmVzc0NvbXBsZXRlVGVtcGxhdGUgPSB0LnJlcGxhY2UoJ3tjbGFzc30nLCBzZWxmLnByb2dyZXNzQ29tcGxldGVDbGFzcyk7XG4gICAgICAgICAgICBzZWxmLnByb2dyZXNzRXJyb3JUZW1wbGF0ZSA9IHQucmVwbGFjZSgne2NsYXNzfScsIHNlbGYucHJvZ3Jlc3NFcnJvckNsYXNzKTtcbiAgICAgICAgICAgIHNlbGYuZHJvcFpvbmVFbmFibGVkID0gJGguaGFzRHJhZ0Ryb3BTdXBwb3J0KCkgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQ7XG4gICAgICAgICAgICBzZWxmLmlzRGlzYWJsZWQgPSAkZWwuYXR0cignZGlzYWJsZWQnKSB8fCAkZWwuYXR0cigncmVhZG9ubHknKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAkZWwuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuaXNVcGxvYWRhYmxlID0gJGguaGFzRmlsZVVwbG9hZFN1cHBvcnQoKSAmJiAhJGguaXNFbXB0eShzZWxmLnVwbG9hZFVybCk7XG4gICAgICAgICAgICBzZWxmLmlzQ2xpY2thYmxlID0gc2VsZi5icm93c2VPblpvbmVDbGljayAmJiBzZWxmLnNob3dQcmV2aWV3ICYmXG4gICAgICAgICAgICAgICAgKHNlbGYuaXNVcGxvYWRhYmxlICYmIHNlbGYuZHJvcFpvbmVFbmFibGVkIHx8ICEkaC5pc0VtcHR5KHNlbGYuZGVmYXVsdFByZXZpZXdDb250ZW50KSk7XG4gICAgICAgICAgICBzZWxmLnNsdWcgPSB0eXBlb2Ygb3B0aW9ucy5zbHVnQ2FsbGJhY2sgPT09IFwiZnVuY3Rpb25cIiA/IG9wdGlvbnMuc2x1Z0NhbGxiYWNrIDogc2VsZi5fc2x1Z0RlZmF1bHQ7XG4gICAgICAgICAgICBzZWxmLm1haW5UZW1wbGF0ZSA9IHNlbGYuc2hvd0NhcHRpb24gPyBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnbWFpbjEnKSA6IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdtYWluMicpO1xuICAgICAgICAgICAgc2VsZi5jYXB0aW9uVGVtcGxhdGUgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnY2FwdGlvbicpO1xuICAgICAgICAgICAgc2VsZi5wcmV2aWV3R2VuZXJpY1RlbXBsYXRlID0gc2VsZi5fZ2V0UHJldmlld1RlbXBsYXRlKCdnZW5lcmljJyk7XG4gICAgICAgICAgICBpZiAoc2VsZi5yZXNpemVJbWFnZSAmJiAoc2VsZi5tYXhJbWFnZVdpZHRoIHx8IHNlbGYubWF4SW1hZ2VIZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pbWFnZUNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgICAgIHNlbGYuaW1hZ2VDYW52YXNDb250ZXh0ID0gc2VsZi5pbWFnZUNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoJGVsLmF0dHIoJ2lkJykpKSB7XG4gICAgICAgICAgICAgICAgJGVsLmF0dHIoJ2lkJywgJGgudW5pcUlkKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5uYW1lc3BhY2UgPSAnLmZpbGVpbnB1dF8nICsgJGVsLmF0dHIoJ2lkJykucmVwbGFjZSgvLS9nLCAnXycpO1xuICAgICAgICAgICAgaWYgKHNlbGYuJGNvbnRhaW5lciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyID0gc2VsZi5fY3JlYXRlQ29udGFpbmVyKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX3JlZnJlc2hDb250YWluZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRjb250ID0gc2VsZi4kY29udGFpbmVyO1xuICAgICAgICAgICAgc2VsZi4kZHJvcFpvbmUgPSAkY29udC5maW5kKCcuZmlsZS1kcm9wLXpvbmUnKTtcbiAgICAgICAgICAgIHNlbGYuJHByb2dyZXNzID0gJGNvbnQuZmluZCgnLmt2LXVwbG9hZC1wcm9ncmVzcycpO1xuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkID0gJGNvbnQuZmluZCgnLmZpbGVpbnB1dC11cGxvYWQnKTtcbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbENhcHRpb25Db250YWluZXInLCAkY29udC5maW5kKCcuZmlsZS1jYXB0aW9uJykpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbiA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsQ2FwdGlvblRleHQnLCAkY29udC5maW5kKCcuZmlsZS1jYXB0aW9uLW5hbWUnKSk7XG4gICAgICAgICAgICBzZWxmLiRwcmV2aWV3Q29udGFpbmVyID0gJGguZ2V0RWxlbWVudChvcHRpb25zLCAnZWxQcmV2aWV3Q29udGFpbmVyJywgJGNvbnQuZmluZCgnLmZpbGUtcHJldmlldycpKTtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbFByZXZpZXdJbWFnZScsICRjb250LmZpbmQoJy5maWxlLXByZXZpZXctdGh1bWJuYWlscycpKTtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXdTdGF0dXMgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbFByZXZpZXdTdGF0dXMnLCAkY29udC5maW5kKCcuZmlsZS1wcmV2aWV3LXN0YXR1cycpKTtcbiAgICAgICAgICAgIHNlbGYuJGVycm9yQ29udGFpbmVyID0gJGguZ2V0RWxlbWVudChvcHRpb25zLCAnZWxFcnJvckNvbnRhaW5lcicsXG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlld0NvbnRhaW5lci5maW5kKCcua3YtZmlsZWlucHV0LWVycm9yJykpO1xuICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KHNlbGYubXNnRXJyb3JDbGFzcykpIHtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kZXJyb3JDb250YWluZXIsIHNlbGYubXNnRXJyb3JDbGFzcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRlcnJvckNvbnRhaW5lci5oaWRlKCk7XG4gICAgICAgICAgICBzZWxmLnByZXZpZXdJbml0SWQgPSBcInByZXZpZXctXCIgKyAkaC51bmlxSWQoKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3Q2FjaGUoKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3KHRydWUpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRGaWxlRHJvcFpvbmVUaXRsZSgpO1xuICAgICAgICAgICAgJGVsLnJlbW92ZUNsYXNzKCdmaWxlLWxvYWRpbmcnKTtcbiAgICAgICAgICAgIGlmICgkZWwuYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgIHNlbGYuZGlzYWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faW5pdFpvb20oKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmhpZGVUaHVtYm5haWxDb250ZW50KSB7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJHByZXZpZXcsICdoaWRlLWNvbnRlbnQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRUZW1wbGF0ZURlZmF1bHRzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHRNYWluMSwgdE1haW4yLCB0UHJldmlldywgdEZpbGVJY29uLCB0Q2xvc2UsIHRDYXB0aW9uLCB0QnRuRGVmYXVsdCwgdEJ0bkxpbmssIHRCdG5Ccm93c2UsXG4gICAgICAgICAgICAgICAgdE1vZGFsTWFpbiwgdE1vZGFsLCB0UHJvZ3Jlc3MsIHRTaXplLCB0Rm9vdGVyLCB0QWN0aW9ucywgdEFjdGlvbkRlbGV0ZSwgdEFjdGlvblVwbG9hZCwgdEFjdGlvblpvb20sXG4gICAgICAgICAgICAgICAgdEFjdGlvbkRyYWcsIHRJbmRpY2F0b3IsIHRUYWdCZWYsIHRUYWdCZWYxLCB0VGFnQmVmMiwgdFRhZ0FmdCwgdEdlbmVyaWMsIHRIdG1sLCB0SW1hZ2UsIHRUZXh0LCB0VmlkZW8sXG4gICAgICAgICAgICAgICAgdEF1ZGlvLCB0Rmxhc2gsIHRPYmplY3QsIHRQZGYsIHRPdGhlciwgdFpvb21DYWNoZSwgdkRlZmF1bHREaW07XG4gICAgICAgICAgICB0TWFpbjEgPSAne3ByZXZpZXd9XFxuJyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJrdi11cGxvYWQtcHJvZ3Jlc3MgaGlkZVwiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAge2NsYXNzfVwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICB7Y2FwdGlvbn1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwLWJ0blwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAge3JlbW92ZX1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgIHtjYW5jZWx9XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICB7dXBsb2FkfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAge2Jyb3dzZX1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICB0TWFpbjIgPSAne3ByZXZpZXd9XFxuPGRpdiBjbGFzcz1cImt2LXVwbG9hZC1wcm9ncmVzcyBoaWRlXCI+PC9kaXY+XFxue3JlbW92ZX1cXG57Y2FuY2VsfVxcbnt1cGxvYWR9XFxue2Jyb3dzZX1cXG4nO1xuICAgICAgICAgICAgdFByZXZpZXcgPSAnPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldyB7Y2xhc3N9XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICB7Y2xvc2V9JyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwie2Ryb3BDbGFzc31cIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLXByZXZpZXctdGh1bWJuYWlsc1wiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiY2xlYXJmaXhcIj48L2Rpdj4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLXByZXZpZXctc3RhdHVzIHRleHQtY2VudGVyIHRleHQtc3VjY2Vzc1wiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImt2LWZpbGVpbnB1dC1lcnJvclwiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICB0Q2xvc2UgPSAnPGRpdiBjbGFzcz1cImNsb3NlIGZpbGVpbnB1dC1yZW1vdmVcIj4mdGltZXM7PC9kaXY+XFxuJztcbiAgICAgICAgICAgIHRGaWxlSWNvbiA9ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tZmlsZSBrdi1jYXB0aW9uLWljb25cIj48L2k+JztcbiAgICAgICAgICAgIHRDYXB0aW9uID0gJzxkaXYgdGFiaW5kZXg9XCI1MDBcIiBjbGFzcz1cImZvcm0tY29udHJvbCBmaWxlLWNhcHRpb24ge2NsYXNzfVwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICA8ZGl2IGNsYXNzPVwiZmlsZS1jYXB0aW9uLW5hbWVcIj48L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+XFxuJztcbiAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEh0bWxVbmtub3duQXR0cmlidXRlXG4gICAgICAgICAgICB0QnRuRGVmYXVsdCA9ICc8YnV0dG9uIHR5cGU9XCJ7dHlwZX1cIiB0YWJpbmRleD1cIjUwMFwiIHRpdGxlPVwie3RpdGxlfVwiIGNsYXNzPVwie2Nzc31cIiAnICtcbiAgICAgICAgICAgICAgICAne3N0YXR1c30+e2ljb259IHtsYWJlbH08L2J1dHRvbj4nO1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSHRtbFVua25vd25BdHRyaWJ1dGVcbiAgICAgICAgICAgIHRCdG5MaW5rID0gJzxhIGhyZWY9XCJ7aHJlZn1cIiB0YWJpbmRleD1cIjUwMFwiIHRpdGxlPVwie3RpdGxlfVwiIGNsYXNzPVwie2Nzc31cIiB7c3RhdHVzfT57aWNvbn0ge2xhYmVsfTwvYT4nO1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSHRtbFVua25vd25BdHRyaWJ1dGVcbiAgICAgICAgICAgIHRCdG5Ccm93c2UgPSAnPGRpdiB0YWJpbmRleD1cIjUwMFwiIGNsYXNzPVwie2Nzc31cIiB7c3RhdHVzfT57aWNvbn0ge2xhYmVsfTwvZGl2Pic7XG4gICAgICAgICAgICB0TW9kYWxNYWluID0gJzxkaXYgaWQ9XCInICsgJGguTU9EQUxfSUQgKyAnXCIgY2xhc3M9XCJmaWxlLXpvb20tZGlhbG9nIG1vZGFsIGZhZGVcIiAnICtcbiAgICAgICAgICAgICAgICAndGFiaW5kZXg9XCItMVwiIGFyaWEtbGFiZWxsZWRieT1cIicgKyAkaC5NT0RBTF9JRCArICdMYWJlbFwiPjwvZGl2Pic7XG4gICAgICAgICAgICB0TW9kYWwgPSAnPGRpdiBjbGFzcz1cIm1vZGFsLWRpYWxvZyBtb2RhbC1sZ3tydGx9XCIgcm9sZT1cImRvY3VtZW50XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgPGRpdiBjbGFzcz1cIm1vZGFsLWNvbnRlbnRcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1oZWFkZXJcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgPGRpdiBjbGFzcz1cImt2LXpvb20tYWN0aW9ucyBwdWxsLXJpZ2h0XCI+e3RvZ2dsZWhlYWRlcn17ZnVsbHNjcmVlbn17Ym9yZGVybGVzc317Y2xvc2V9PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgIDxoMyBjbGFzcz1cIm1vZGFsLXRpdGxlXCI+e2hlYWRpbmd9IDxzbWFsbD48c3BhbiBjbGFzcz1cImt2LXpvb20tdGl0bGVcIj48L3NwYW4+PC9zbWFsbD48L2gzPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwibW9kYWwtYm9keVwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICA8ZGl2IGNsYXNzPVwiZmxvYXRpbmctYnV0dG9uc1wiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICA8ZGl2IGNsYXNzPVwia3Ytem9vbS1ib2R5IGZpbGUtem9vbS1jb250ZW50IHt6b29tRnJhbWVDbGFzc31cIj48L2Rpdj5cXG4nICsgJ3twcmV2fSB7bmV4dH1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgIDwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdFByb2dyZXNzID0gJzxkaXYgY2xhc3M9XCJwcm9ncmVzc1wiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIntjbGFzc31cIiByb2xlPVwicHJvZ3Jlc3NiYXJcIicgK1xuICAgICAgICAgICAgICAgICcgYXJpYS12YWx1ZW5vdz1cIntwZXJjZW50fVwiIGFyaWEtdmFsdWVtaW49XCIwXCIgYXJpYS12YWx1ZW1heD1cIjEwMFwiIHN0eWxlPVwid2lkdGg6e3BlcmNlbnR9JTtcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgICB7c3RhdHVzfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgIDwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICAgICAgdFNpemUgPSAnIDxzYW1wPih7c2l6ZVRleHR9KTwvc2FtcD4nO1xuICAgICAgICAgICAgdEZvb3RlciA9ICc8ZGl2IGNsYXNzPVwiZmlsZS10aHVtYm5haWwtZm9vdGVyXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiZmlsZS1mb290ZXItY2FwdGlvblwiIHRpdGxlPVwie2NhcHRpb259XCI+e2NhcHRpb259PGJyPntzaXplfTwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAge3Byb2dyZXNzfSB7aW5kaWNhdG9yfSB7YWN0aW9uc31cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgICAgIHRBY3Rpb25zID0gJ3tkcmFnfVxcbicgK1xuICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPVwiZmlsZS1hY3Rpb25zXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwiZmlsZS1mb290ZXItYnV0dG9uc1wiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAgIHt1cGxvYWR9IHtkZWxldGV9IHt6b29tfSB7b3RoZXJ9JyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSHRtbFVua25vd25BdHRyaWJ1dGVcbiAgICAgICAgICAgIHRBY3Rpb25EZWxldGUgPSAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrdi1maWxlLXJlbW92ZSB7cmVtb3ZlQ2xhc3N9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3RpdGxlPVwie3JlbW92ZVRpdGxlfVwiIHtkYXRhVXJsfXtkYXRhS2V5fT57cmVtb3ZlSWNvbn08L2J1dHRvbj5cXG4nO1xuICAgICAgICAgICAgdEFjdGlvblVwbG9hZCA9ICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImt2LWZpbGUtdXBsb2FkIHt1cGxvYWRDbGFzc31cIiB0aXRsZT1cInt1cGxvYWRUaXRsZX1cIj4nICtcbiAgICAgICAgICAgICAgICAne3VwbG9hZEljb259PC9idXR0b24+JztcbiAgICAgICAgICAgIHRBY3Rpb25ab29tID0gJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwia3YtZmlsZS16b29tIHt6b29tQ2xhc3N9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3RpdGxlPVwie3pvb21UaXRsZX1cIj57em9vbUljb259PC9idXR0b24+JztcbiAgICAgICAgICAgIHRBY3Rpb25EcmFnID0gJzxzcGFuIGNsYXNzPVwiZmlsZS1kcmFnLWhhbmRsZSB7ZHJhZ0NsYXNzfVwiIHRpdGxlPVwie2RyYWdUaXRsZX1cIj57ZHJhZ0ljb259PC9zcGFuPic7XG4gICAgICAgICAgICB0SW5kaWNhdG9yID0gJzxkaXYgY2xhc3M9XCJmaWxlLXVwbG9hZC1pbmRpY2F0b3JcIiB0aXRsZT1cIntpbmRpY2F0b3JUaXRsZX1cIj57aW5kaWNhdG9yfTwvZGl2Pic7XG4gICAgICAgICAgICB0VGFnQmVmID0gJzxkaXYgY2xhc3M9XCJmaWxlLXByZXZpZXctZnJhbWUge2ZyYW1lQ2xhc3N9XCIgaWQ9XCJ7cHJldmlld0lkfVwiIGRhdGEtZmlsZWluZGV4PVwie2ZpbGVpbmRleH1cIicgK1xuICAgICAgICAgICAgICAgICcgZGF0YS10ZW1wbGF0ZT1cInt0ZW1wbGF0ZX1cIic7XG4gICAgICAgICAgICB0VGFnQmVmMSA9IHRUYWdCZWYgKyAnPjxkaXYgY2xhc3M9XCJrdi1maWxlLWNvbnRlbnRcIj5cXG4nO1xuICAgICAgICAgICAgdFRhZ0JlZjIgPSB0VGFnQmVmICsgJyB0aXRsZT1cIntjYXB0aW9ufVwiPjxkaXYgY2xhc3M9XCJrdi1maWxlLWNvbnRlbnRcIj5cXG4nO1xuICAgICAgICAgICAgdFRhZ0FmdCA9ICc8L2Rpdj57Zm9vdGVyfVxcbjwvZGl2Plxcbic7XG4gICAgICAgICAgICB0R2VuZXJpYyA9ICd7Y29udGVudH1cXG4nO1xuICAgICAgICAgICAgdEh0bWwgPSAnPGRpdiBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLXByZXZpZXctaHRtbFwiIHRpdGxlPVwie2NhcHRpb259XCIgJyArICRoLlNUWUxFX1NFVFRJTkcgK1xuICAgICAgICAgICAgICAgICc+e2RhdGF9PC9kaXY+XFxuJztcbiAgICAgICAgICAgIHRJbWFnZSA9ICc8aW1nIHNyYz1cIntkYXRhfVwiIGNsYXNzPVwiZmlsZS1wcmV2aWV3LWltYWdlIGt2LXByZXZpZXctZGF0YVwiIHRpdGxlPVwie2NhcHRpb259XCIgYWx0PVwie2NhcHRpb259XCIgJyArXG4gICAgICAgICAgICAgICAgJGguU1RZTEVfU0VUVElORyArICc+XFxuJztcbiAgICAgICAgICAgIHRUZXh0ID0gJzx0ZXh0YXJlYSBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLXByZXZpZXctdGV4dFwiIHRpdGxlPVwie2NhcHRpb259XCIgcmVhZG9ubHkgJyArXG4gICAgICAgICAgICAgICAgJGguU1RZTEVfU0VUVElORyArICc+e2RhdGF9PC90ZXh0YXJlYT5cXG4nO1xuICAgICAgICAgICAgdFZpZGVvID0gJzx2aWRlbyBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLXByZXZpZXctdmlkZW9cIiB3aWR0aD1cInt3aWR0aH1cIiAnICtcbiAgICAgICAgICAgICAgICAnaGVpZ2h0PVwie2hlaWdodH1cIiBjb250cm9scz5cXG4nICsgJzxzb3VyY2Ugc3JjPVwie2RhdGF9XCIgdHlwZT1cInt0eXBlfVwiPlxcbicgKyAkaC5ERUZBVUxUX1BSRVZJRVcgK1xuICAgICAgICAgICAgICAgICdcXG48L3ZpZGVvPlxcbic7XG4gICAgICAgICAgICB0QXVkaW8gPSAnPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy1hdWRpb1wiPjxhdWRpbyBjbGFzcz1cImt2LXByZXZpZXctZGF0YVwiIGNvbnRyb2xzPlxcbjxzb3VyY2Ugc3JjPVwie2RhdGF9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3R5cGU9XCJ7dHlwZX1cIj5cXG4nICsgJGguREVGQVVMVF9QUkVWSUVXICsgJ1xcbjwvYXVkaW8+PC9kaXY+XFxuJztcbiAgICAgICAgICAgIHRGbGFzaCA9ICc8b2JqZWN0IGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtb2JqZWN0XCIgdHlwZT1cImFwcGxpY2F0aW9uL3gtc2hvY2t3YXZlLWZsYXNoXCIgJyArXG4gICAgICAgICAgICAgICAgJ3dpZHRoPVwie3dpZHRofVwiIGhlaWdodD1cIntoZWlnaHR9XCIgZGF0YT1cIntkYXRhfVwiPlxcbicgKyAkaC5PQkpFQ1RfUEFSQU1TICsgJyAnICsgJGguREVGQVVMVF9QUkVWSUVXICtcbiAgICAgICAgICAgICAgICAnXFxuPC9vYmplY3Q+XFxuJztcbiAgICAgICAgICAgIHRPYmplY3QgPSAnPG9iamVjdCBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLW9iamVjdCB7dHlwZUNzc31cIiBkYXRhPVwie2RhdGF9XCIgdHlwZT1cInt0eXBlfVwiICcgK1xuICAgICAgICAgICAgICAgICd3aWR0aD1cInt3aWR0aH1cIiBoZWlnaHQ9XCJ7aGVpZ2h0fVwiPlxcbicgKyAnPHBhcmFtIG5hbWU9XCJtb3ZpZVwiIHZhbHVlPVwie2NhcHRpb259XCIgLz5cXG4nICtcbiAgICAgICAgICAgICAgICAkaC5PQkpFQ1RfUEFSQU1TICsgJyAnICsgJGguREVGQVVMVF9QUkVWSUVXICsgJ1xcbjwvb2JqZWN0Plxcbic7XG4gICAgICAgICAgICB0UGRmID0gJzxlbWJlZCBjbGFzcz1cImt2LXByZXZpZXctZGF0YVwiIHNyYz1cIntkYXRhfVwiICcgK1xuICAgICAgICAgICAgICAgICd3aWR0aD1cInt3aWR0aH1cIiBoZWlnaHQ9XCJ7aGVpZ2h0fVwiIHR5cGU9XCJhcHBsaWNhdGlvbi9wZGZcIj5cXG4nO1xuICAgICAgICAgICAgdE90aGVyID0gJzxkaXYgY2xhc3M9XCJrdi1wcmV2aWV3LWRhdGEgZmlsZS1wcmV2aWV3LW90aGVyLWZyYW1lXCI+XFxuJyArICRoLkRFRkFVTFRfUFJFVklFVyArICdcXG48L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdFpvb21DYWNoZSA9ICc8ZGl2IGNsYXNzPVwia3Ytem9vbS1jYWNoZVwiIHN0eWxlPVwiZGlzcGxheTpub25lXCI+e3pvb21Db250ZW50fTwvZGl2Pic7XG4gICAgICAgICAgICB2RGVmYXVsdERpbSA9IHt3aWR0aDogXCIxMDAlXCIsIGhlaWdodDogXCIxMDAlXCIsICdtaW4taGVpZ2h0JzogXCI0ODBweFwifTtcbiAgICAgICAgICAgIHNlbGYuZGVmYXVsdHMgPSB7XG4gICAgICAgICAgICAgICAgbGF5b3V0VGVtcGxhdGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIG1haW4xOiB0TWFpbjEsXG4gICAgICAgICAgICAgICAgICAgIG1haW4yOiB0TWFpbjIsXG4gICAgICAgICAgICAgICAgICAgIHByZXZpZXc6IHRQcmV2aWV3LFxuICAgICAgICAgICAgICAgICAgICBjbG9zZTogdENsb3NlLFxuICAgICAgICAgICAgICAgICAgICBmaWxlSWNvbjogdEZpbGVJY29uLFxuICAgICAgICAgICAgICAgICAgICBjYXB0aW9uOiB0Q2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgbW9kYWxNYWluOiB0TW9kYWxNYWluLFxuICAgICAgICAgICAgICAgICAgICBtb2RhbDogdE1vZGFsLFxuICAgICAgICAgICAgICAgICAgICBwcm9ncmVzczogdFByb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICBzaXplOiB0U2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgZm9vdGVyOiB0Rm9vdGVyLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3I6IHRJbmRpY2F0b3IsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnM6IHRBY3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25EZWxldGU6IHRBY3Rpb25EZWxldGUsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvblVwbG9hZDogdEFjdGlvblVwbG9hZCxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uWm9vbTogdEFjdGlvblpvb20sXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbkRyYWc6IHRBY3Rpb25EcmFnLFxuICAgICAgICAgICAgICAgICAgICBidG5EZWZhdWx0OiB0QnRuRGVmYXVsdCxcbiAgICAgICAgICAgICAgICAgICAgYnRuTGluazogdEJ0bkxpbmssXG4gICAgICAgICAgICAgICAgICAgIGJ0bkJyb3dzZTogdEJ0bkJyb3dzZSxcbiAgICAgICAgICAgICAgICAgICAgem9vbUNhY2hlOiB0Wm9vbUNhY2hlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcmV2aWV3TWFya3VwVGFnczoge1xuICAgICAgICAgICAgICAgICAgICB0YWdCZWZvcmUxOiB0VGFnQmVmMSxcbiAgICAgICAgICAgICAgICAgICAgdGFnQmVmb3JlMjogdFRhZ0JlZjIsXG4gICAgICAgICAgICAgICAgICAgIHRhZ0FmdGVyOiB0VGFnQWZ0XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcmV2aWV3Q29udGVudFRlbXBsYXRlczoge1xuICAgICAgICAgICAgICAgICAgICBnZW5lcmljOiB0R2VuZXJpYyxcbiAgICAgICAgICAgICAgICAgICAgaHRtbDogdEh0bWwsXG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiB0SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHRUZXh0LFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogdFZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBhdWRpbzogdEF1ZGlvLFxuICAgICAgICAgICAgICAgICAgICBmbGFzaDogdEZsYXNoLFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IHRPYmplY3QsXG4gICAgICAgICAgICAgICAgICAgIHBkZjogdFBkZixcbiAgICAgICAgICAgICAgICAgICAgb3RoZXI6IHRPdGhlclxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWxsb3dlZFByZXZpZXdUeXBlczogWydpbWFnZScsICdodG1sJywgJ3RleHQnLCAndmlkZW8nLCAnYXVkaW8nLCAnZmxhc2gnLCAncGRmJywgJ29iamVjdCddLFxuICAgICAgICAgICAgICAgIHByZXZpZXdUZW1wbGF0ZXM6IHt9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdTZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZToge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjE2MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBodG1sOiB7d2lkdGg6IFwiMjEzcHhcIiwgaGVpZ2h0OiBcIjE2MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICB0ZXh0OiB7d2lkdGg6IFwiMjEzcHhcIiwgaGVpZ2h0OiBcIjE2MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21heC13aWR0aCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW86IHt3aWR0aDogXCIxMDAlXCIsIGhlaWdodDogXCIzMHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBmbGFzaDoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21heC13aWR0aCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB7aGVpZ2h0OiBcIjEwMCVcIn0sXG4gICAgICAgICAgICAgICAgICAgIHBkZjoge3dpZHRoOiBcIjE2MHB4XCIsIGhlaWdodDogXCIxNjBweFwifSxcbiAgICAgICAgICAgICAgICAgICAgb3RoZXI6IHt3aWR0aDogXCIxNjBweFwiLCBoZWlnaHQ6IFwiMTYwcHhcIn1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdab29tU2V0dGluZ3M6IHtcbiAgICAgICAgICAgICAgICAgICAgaW1hZ2U6IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCJhdXRvXCIsICdtYXgtd2lkdGgnOiBcIjEwMCVcIiwgJ21heC1oZWlnaHQnOiBcIjEwMCVcIn0sXG4gICAgICAgICAgICAgICAgICAgIGh0bWw6IHZEZWZhdWx0RGltLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0OiB2RGVmYXVsdERpbSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCIxMDAlXCIsICdtYXgtd2lkdGgnOiBcIjEwMCVcIn0sXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB7d2lkdGg6IFwiMTAwJVwiLCBoZWlnaHQ6IFwiMzBweFwifSxcbiAgICAgICAgICAgICAgICAgICAgZmxhc2g6IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCI0ODBweFwifSxcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTAwJVwiLCAnbWF4LXdpZHRoJzogXCIxMDAlXCIsICdtaW4taGVpZ2h0JzogXCI0ODBweFwifSxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiB2RGVmYXVsdERpbSxcbiAgICAgICAgICAgICAgICAgICAgb3RoZXI6IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCIxMDAlXCIsICdtaW4taGVpZ2h0JzogXCI0ODBweFwifVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmlsZVR5cGVTZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZTogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICdpbWFnZS4qJykgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLihnaWZ8cG5nfGpwZT9nKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGh0bWw6IGZ1bmN0aW9uICh2VHlwZSwgdk5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkaC5jb21wYXJlKHZUeXBlLCAndGV4dC9odG1sJykgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLihodG18aHRtbCkkL2kpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ3RleHQuKicpIHx8ICRoLmNvbXBhcmUodk5hbWUsIC9cXC4oeG1sfGphdmFzY3JpcHQpJC9pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmNvbXBhcmUodk5hbWUsIC9cXC4odHh0fG1kfGNzdnxuZm98aW5pfGpzb258cGhwfGpzfGNzcykkL2kpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICd2aWRlby4qJykgJiYgKCRoLmNvbXBhcmUodlR5cGUsIC8ob2dnfG1wNHxtcD9nfG1vdnx3ZWJtfDNncCkkL2kpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguY29tcGFyZSh2TmFtZSwgL1xcLihvZz98bXA0fHdlYm18bXA/Z3xtb3Z8M2dwKSQvaSkpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBhdWRpbzogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICdhdWRpby4qJykgJiYgKCRoLmNvbXBhcmUodk5hbWUsIC8ob2dnfG1wM3xtcD9nfHdhdikkL2kpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguY29tcGFyZSh2TmFtZSwgL1xcLihvZz98bXAzfG1wP2d8d2F2KSQvaSkpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBmbGFzaDogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICdhcHBsaWNhdGlvbi94LXNob2Nrd2F2ZS1mbGFzaCcsIHRydWUpIHx8ICRoLmNvbXBhcmUodk5hbWUsIC9cXC4oc3dmKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHBkZjogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICdhcHBsaWNhdGlvbi9wZGYnLCB0cnVlKSB8fCAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKHBkZikkL2kpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZpbGVBY3Rpb25TZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICBzaG93UmVtb3ZlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBzaG93VXBsb2FkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBzaG93Wm9vbTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgc2hvd0RyYWc6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZUljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJhc2ggdGV4dC1kYW5nZXJcIj48L2k+JyxcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlQ2xhc3M6ICdidG4gYnRuLXhzIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlVGl0bGU6ICdSZW1vdmUgZmlsZScsXG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZEljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdXBsb2FkIHRleHQtaW5mb1wiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICB1cGxvYWRDbGFzczogJ2J0biBidG4teHMgYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICB1cGxvYWRUaXRsZTogJ1VwbG9hZCBmaWxlJyxcbiAgICAgICAgICAgICAgICAgICAgem9vbUljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tem9vbS1pblwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICB6b29tQ2xhc3M6ICdidG4gYnRuLXhzIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgICAgICAgICAgICAgem9vbVRpdGxlOiAnVmlldyBEZXRhaWxzJyxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ0ljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tbWVudS1oYW1idXJnZXJcIj48L2k+JyxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ0NsYXNzOiAndGV4dC1pbmZvJyxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1RpdGxlOiAnTW92ZSAvIFJlYXJyYW5nZScsXG4gICAgICAgICAgICAgICAgICAgIGRyYWdTZXR0aW5nczoge30sXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvck5ldzogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1oYW5kLWRvd24gdGV4dC13YXJuaW5nXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvclN1Y2Nlc3M6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tb2stc2lnbiB0ZXh0LXN1Y2Nlc3NcIj48L2k+JyxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yRXJyb3I6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tZXhjbGFtYXRpb24tc2lnbiB0ZXh0LWRhbmdlclwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JMb2FkaW5nOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWhhbmQtdXAgdGV4dC1tdXRlZFwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JOZXdUaXRsZTogJ05vdCB1cGxvYWRlZCB5ZXQnLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JTdWNjZXNzVGl0bGU6ICdVcGxvYWRlZCcsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvckVycm9yVGl0bGU6ICdVcGxvYWQgRXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JMb2FkaW5nVGl0bGU6ICdVcGxvYWRpbmcgLi4uJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAkLmVhY2goc2VsZi5kZWZhdWx0cywgZnVuY3Rpb24gKGtleSwgc2V0dGluZykge1xuICAgICAgICAgICAgICAgIGlmIChrZXkgPT09ICdhbGxvd2VkUHJldmlld1R5cGVzJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWxsb3dlZFByZXZpZXdUeXBlcyA9IHNldHRpbmc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmW2tleV0gPSAkLmV4dGVuZCh0cnVlLCB7fSwgc2V0dGluZywgc2VsZltrZXldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdUZW1wbGF0ZXMoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRQcmV2aWV3VGVtcGxhdGVzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNmZyA9IHNlbGYuZGVmYXVsdHMsIHRhZ3MgPSBzZWxmLnByZXZpZXdNYXJrdXBUYWdzLCB0YWdCZWYsIHRhZ0FmdCA9IHRhZ3MudGFnQWZ0ZXI7XG4gICAgICAgICAgICAkLmVhY2goY2ZnLnByZXZpZXdDb250ZW50VGVtcGxhdGVzLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KHNlbGYucHJldmlld1RlbXBsYXRlc1trZXldKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdCZWYgPSB0YWdzLnRhZ0JlZm9yZTI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgPT09ICdnZW5lcmljJyB8fCBrZXkgPT09ICdpbWFnZScgfHwga2V5ID09PSAnaHRtbCcgfHwga2V5ID09PSAndGV4dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ0JlZiA9IHRhZ3MudGFnQmVmb3JlMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdUZW1wbGF0ZXNba2V5XSA9IHRhZ0JlZiArIHZhbHVlICsgdGFnQWZ0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXdDYWNoZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUgPSB7XG4gICAgICAgICAgICAgICAgZGF0YToge30sXG4gICAgICAgICAgICAgICAgaW5pdDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29udGVudCA9IHNlbGYuaW5pdGlhbFByZXZpZXc7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb250ZW50Lmxlbmd0aCA+IDAgJiYgISRoLmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNwbGl0KHNlbGYuaW5pdGlhbFByZXZpZXdEZWxpbWl0ZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBjb250ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlnOiBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFnczogc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFnc1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmV0Y2g6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYucHJldmlld0NhY2hlLmRhdGEuY29udGVudC5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuICE9PSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNvdW50OiBmdW5jdGlvbiAoYWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhIXNlbGYucHJldmlld0NhY2hlLmRhdGEgJiYgISFzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbnRlbnQgP1xuICAgICAgICAgICAgICAgICAgICAgICAgKGFsbCA/IHNlbGYucHJldmlld0NhY2hlLmRhdGEuY29udGVudC5sZW5ndGggOiBzZWxmLnByZXZpZXdDYWNoZS5mZXRjaCgpLmxlbmd0aCkgOiAwO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoaSwgaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW5kID0gJ2luaXRfJyArIGksIGRhdGEgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLCBjb25maWcgPSBkYXRhLmNvbmZpZ1tpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBkYXRhLmNvbnRlbnRbaV0sIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArICctJyArIGluZCwgb3V0LCAkdG1wLCBjYXQsIGZ0cixcbiAgICAgICAgICAgICAgICAgICAgICAgIGZuYW1lLCBmdHlwZSwgZnJhbWVDbGFzcywgYXNEYXRhID0gJGguaWZTZXQoJ3ByZXZpZXdBc0RhdGEnLCBjb25maWcsIHNlbGYuaW5pdGlhbFByZXZpZXdBc0RhdGEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VUZW1wbGF0ZSA9IGZ1bmN0aW9uIChjYXQsIGRhdCwgZm4sIGZ0LCBpZCwgZnRyLCBpbmQsIGZjLCB0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmMgPSAnIGZpbGUtcHJldmlldy1pbml0aWFsICcgKyAkaC5TT1JUX0NTUyArIChmYyA/ICcgJyArIGZjIDogJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLl9nZW5lcmF0ZVByZXZpZXdUZW1wbGF0ZShjYXQsIGRhdCwgZm4sIGZ0LCBpZCwgZmFsc2UsIG51bGwsIGZjLCBmdHIsIGluZCwgdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpc0Rpc2FibGVkID0gaXNEaXNhYmxlZCA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGlzRGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgIGNhdCA9ICRoLmlmU2V0KCd0eXBlJywgY29uZmlnLCBzZWxmLmluaXRpYWxQcmV2aWV3RmlsZVR5cGUgfHwgJ2dlbmVyaWMnKTtcbiAgICAgICAgICAgICAgICAgICAgZm5hbWUgPSAkaC5pZlNldCgnZmlsZW5hbWUnLCBjb25maWcsICRoLmlmU2V0KCdjYXB0aW9uJywgY29uZmlnKSk7XG4gICAgICAgICAgICAgICAgICAgIGZ0eXBlID0gJGguaWZTZXQoJ2ZpbGV0eXBlJywgY29uZmlnLCBjYXQpO1xuICAgICAgICAgICAgICAgICAgICBmdHIgPSBzZWxmLnByZXZpZXdDYWNoZS5mb290ZXIoaSwgaXNEaXNhYmxlZCwgKGNvbmZpZyAmJiBjb25maWcuc2l6ZSB8fCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lQ2xhc3MgPSAkaC5pZlNldCgnZnJhbWVDbGFzcycsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhc0RhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IHBhcnNlVGVtcGxhdGUoY2F0LCBjb250ZW50LCBmbmFtZSwgZnR5cGUsIHByZXZpZXdJZCwgZnRyLCBpbmQsIGZyYW1lQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gcGFyc2VUZW1wbGF0ZSgnZ2VuZXJpYycsIGNvbnRlbnQsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBmdHIsIGluZCwgZnJhbWVDbGFzcywgY2F0KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXRUb2tlbnMoeydjb250ZW50JzogZGF0YS5jb250ZW50W2ldfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEudGFncy5sZW5ndGggJiYgZGF0YS50YWdzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSAkaC5yZXBsYWNlVGFncyhvdXQsIGRhdGEudGFnc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgY29uZmlnLmZyYW1lQXR0ciAqL1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoY29uZmlnKSAmJiAhJGguaXNFbXB0eShjb25maWcuZnJhbWVBdHRyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRtcCA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwob3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0bXAuZmluZCgnLmZpbGUtcHJldmlldy1pbml0aWFsJykuYXR0cihjb25maWcuZnJhbWVBdHRyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9ICR0bXAuaHRtbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRtcC5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWRkOiBmdW5jdGlvbiAoY29udGVudCwgY29uZmlnLCB0YWdzLCBhcHBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLCBpbmRleDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkaC5pc0FycmF5KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gY29udGVudC5zcGxpdChzZWxmLmluaXRpYWxQcmV2aWV3RGVsaW1pdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYXBwZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGRhdGEuY29udGVudC5wdXNoKGNvbnRlbnQpIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29uZmlnW2luZGV4XSA9IGNvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFnc1tpbmRleF0gPSB0YWdzO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBjb250ZW50Lmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQgPSBjb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWcgPSBjb25maWc7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3MgPSB0YWdzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uIChjb250ZW50LCBjb25maWcsIHRhZ3MsIGFwcGVuZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGksIGNoaztcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb250ZW50IHx8ICFjb250ZW50Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghJGguaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3BsaXQoc2VsZi5pbml0aWFsUHJldmlld0RlbGltaXRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2hrID0gY29udGVudC5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuICE9PSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGsubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuY29udGVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5jb25maWcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWcgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS50YWdzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFncyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb250ZW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRlbnRbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb250ZW50LnB1c2goY29udGVudFtpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbmZpZy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb25maWdbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWcucHVzaChjb25maWdbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhZ3NbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzLnB1c2godGFnc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb250ZW50ID0gY29udGVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29uZmlnID0gY29uZmlnO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzID0gdGFncztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhID0gZGF0YTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHVuc2V0OiBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoayA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghY2hrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoayA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbmZpZyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS50YWdzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50W2luZGV4XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEuY29uZmlnW2luZGV4XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEudGFnc1tpbmRleF0gPSBudWxsO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb3V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBodG1sID0gJycsIGNhcHRpb24sIGxlbiA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KHRydWUpLCBpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge2NvbnRlbnQ6ICcnLCBjYXB0aW9uOiAnJ307XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodG1sICs9IHNlbGYucHJldmlld0NhY2hlLmdldChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQoc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7Y29udGVudDogaHRtbCwgY2FwdGlvbjogY2FwdGlvbn07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmb290ZXI6IGZ1bmN0aW9uIChpLCBpc0Rpc2FibGVkLCBzaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmNvbmZpZyB8fCBkYXRhLmNvbmZpZy5sZW5ndGggPT09IDAgfHwgJGguaXNFbXB0eShkYXRhLmNvbmZpZ1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpc0Rpc2FibGVkID0gaXNEaXNhYmxlZCA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGlzRGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb25maWcgPSBkYXRhLmNvbmZpZ1tpXSwgY2FwdGlvbiA9ICRoLmlmU2V0KCdjYXB0aW9uJywgY29uZmlnKSwgYWN0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gJGguaWZTZXQoJ3dpZHRoJywgY29uZmlnLCAnYXV0bycpLCB1cmwgPSAkaC5pZlNldCgndXJsJywgY29uZmlnLCBmYWxzZSksXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXkgPSAkaC5pZlNldCgna2V5JywgY29uZmlnLCBudWxsKSwgZnMgPSBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRQcmV2aWV3U2hvd0RlbCA9IHNlbGYuaW5pdGlhbFByZXZpZXdTaG93RGVsZXRlIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0RlbCA9ICRoLmlmU2V0KCdzaG93RGVsZXRlJywgY29uZmlnLCAkaC5pZlNldCgnc2hvd0RlbGV0ZScsIGZzLCBpbml0UHJldmlld1Nob3dEZWwpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dab29tID0gJGguaWZTZXQoJ3Nob3dab29tJywgY29uZmlnLCAkaC5pZlNldCgnc2hvd1pvb20nLCBmcywgdHJ1ZSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0RyYWcgPSAkaC5pZlNldCgnc2hvd0RyYWcnLCBjb25maWcsICRoLmlmU2V0KCdzaG93RHJhZycsIGZzLCB0cnVlKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZCA9ICh1cmwgPT09IGZhbHNlKSAmJiBpc0Rpc2FibGVkO1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb25zID0gc2VsZi5fcmVuZGVyRmlsZUFjdGlvbnMoZmFsc2UsIHNob3dEZWwsIHNob3dab29tLCBzaG93RHJhZywgZGlzYWJsZWQsIHVybCwga2V5LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdmb290ZXInKS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3Byb2dyZXNzJzogc2VsZi5fcmVuZGVyVGh1bWJQcm9ncmVzcygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2FjdGlvbnMnOiBhY3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2NhcHRpb24nOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBzZWxmLl9nZXRTaXplKHNpemUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAnaW5kaWNhdG9yJzogJydcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmluaXQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2hhbmRsZXI6IGZ1bmN0aW9uICgkZWwsIGV2ZW50LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBucyA9IHNlbGYubmFtZXNwYWNlLCBldiA9IGV2ZW50LnNwbGl0KCcgJykuam9pbihucyArICcgJykgKyBucztcbiAgICAgICAgICAgIGlmICghJGVsIHx8ICEkZWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVsLm9mZihldikub24oZXYsIGNhbGxiYWNrKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2xvZzogZnVuY3Rpb24gKG1zZykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpZCA9IHNlbGYuJGVsZW1lbnQuYXR0cignaWQnKTtcbiAgICAgICAgICAgIGlmIChpZCkge1xuICAgICAgICAgICAgICAgIG1zZyA9ICdcIicgKyBpZCArICdcIjogJyArIG1zZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygd2luZG93LmNvbnNvbGUubG9nICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmNvbnNvbGUubG9nKG1zZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdpbmRvdy5hbGVydChtc2cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgc3RhdHVzID0gc2VsZi4kZWxlbWVudC5hdHRyKCd0eXBlJykgPT09ICdmaWxlJztcbiAgICAgICAgICAgIGlmICghc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbG9nKCdUaGUgaW5wdXQgXCJ0eXBlXCIgbXVzdCBiZSBzZXQgdG8gXCJmaWxlXCIgZm9yIGluaXRpYWxpemluZyB0aGUgXCJib290c3RyYXAtZmlsZWlucHV0XCIgcGx1Z2luLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0YXR1cztcbiAgICAgICAgfSxcbiAgICAgICAgX2Vycm9yc0V4aXN0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnI7XG4gICAgICAgICAgICBpZiAoc2VsZi4kZXJyb3JDb250YWluZXIuZmluZCgnbGknKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRlcnIgPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKS5odG1sKHNlbGYuJGVycm9yQ29udGFpbmVyLmh0bWwoKSk7XG4gICAgICAgICAgICAkZXJyLmZpbmQoJ3NwYW4ua3YtZXJyb3ItY2xvc2UnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICRlcnIuZmluZCgndWwnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybiAkLnRyaW0oJGVyci50ZXh0KCkpLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbiAgICAgICAgfSxcbiAgICAgICAgX2Vycm9ySGFuZGxlcjogZnVuY3Rpb24gKGV2dCwgY2FwdGlvbikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBlcnIgPSBldnQudGFyZ2V0LmVycm9yLCBzaG93RXJyb3IgPSBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0Vycm9yKG1zZy5yZXBsYWNlKCd7bmFtZX0nLCBjYXB0aW9uKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZXJyLk5PVF9GT1VORF9FUlIgKi9cbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGVyci5TRUNVUklUWV9FUlIgKi9cbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGVyci5OT1RfUkVBREFCTEVfRVJSICovXG4gICAgICAgICAgICBpZiAoZXJyLmNvZGUgPT09IGVyci5OT1RfRk9VTkRfRVJSKSB7XG4gICAgICAgICAgICAgICAgc2hvd0Vycm9yKHNlbGYubXNnRmlsZU5vdEZvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyLmNvZGUgPT09IGVyci5TRUNVUklUWV9FUlIpIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlU2VjdXJlZCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGVyci5jb2RlID09PSBlcnIuTk9UX1JFQURBQkxFX0VSUikge1xuICAgICAgICAgICAgICAgIHNob3dFcnJvcihzZWxmLm1zZ0ZpbGVOb3RSZWFkYWJsZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGVyci5jb2RlID09PSBlcnIuQUJPUlRfRVJSKSB7XG4gICAgICAgICAgICAgICAgc2hvd0Vycm9yKHNlbGYubXNnRmlsZVByZXZpZXdBYm9ydGVkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2hvd0Vycm9yKHNlbGYubXNnRmlsZVByZXZpZXdFcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9hZGRFcnJvcjogZnVuY3Rpb24gKG1zZykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lcjtcbiAgICAgICAgICAgIGlmIChtc2cgJiYgJGVycm9yLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICRlcnJvci5odG1sKHNlbGYuZXJyb3JDbG9zZUJ1dHRvbiArIG1zZyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZXJyb3IuZmluZCgnLmt2LWVycm9yLWNsb3NlJyksICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJGVycm9yLmZhZGVPdXQoJ3Nsb3cnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3Jlc2V0RXJyb3JzOiBmdW5jdGlvbiAoZmFkZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lcjtcbiAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdoYXMtZXJyb3InKTtcbiAgICAgICAgICAgICRlcnJvci5odG1sKCcnKTtcbiAgICAgICAgICAgIGlmIChmYWRlKSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmZhZGVPdXQoJ3Nsb3cnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3Nob3dGb2xkZXJFcnJvcjogZnVuY3Rpb24gKGZvbGRlcnMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVycm9yID0gc2VsZi4kZXJyb3JDb250YWluZXIsIG1zZztcbiAgICAgICAgICAgIGlmICghZm9sZGVycykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnRm9sZGVyc05vdEFsbG93ZWQucmVwbGFjZSgne259JywgZm9sZGVycyk7XG4gICAgICAgICAgICBzZWxmLl9hZGRFcnJvcihtc2cpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgJGVycm9yLmZhZGVJbig4MDApO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVmb2xkZXJlcnJvcicsIFtmb2xkZXJzLCBtc2ddKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3Nob3dVcGxvYWRFcnJvcjogZnVuY3Rpb24gKG1zZywgcGFyYW1zLCBldmVudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lciwgZXYgPSBldmVudCB8fCAnZmlsZXVwbG9hZGVycm9yJywgZSA9IHBhcmFtcyAmJiBwYXJhbXMuaWQgP1xuICAgICAgICAgICAgJzxsaSBkYXRhLWZpbGUtaWQ9XCInICsgcGFyYW1zLmlkICsgJ1wiPicgKyBtc2cgKyAnPC9saT4nIDogJzxsaT4nICsgbXNnICsgJzwvbGk+JztcbiAgICAgICAgICAgIGlmICgkZXJyb3IuZmluZCgndWwnKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9hZGRFcnJvcignPHVsPicgKyBlICsgJzwvdWw+Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICRlcnJvci5maW5kKCd1bCcpLmFwcGVuZChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRlcnJvci5mYWRlSW4oODAwKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKGV2LCBbcGFyYW1zLCBtc2ddKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS1pbnB1dC1uZXcnKTtcbiAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRjb250YWluZXIsICdoYXMtZXJyb3InKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfc2hvd0Vycm9yOiBmdW5jdGlvbiAobXNnLCBwYXJhbXMsIGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyLCBldiA9IGV2ZW50IHx8ICdmaWxlZXJyb3InO1xuICAgICAgICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgICAgICAgICAgcGFyYW1zLnJlYWRlciA9IHNlbGYucmVhZGVyO1xuICAgICAgICAgICAgc2VsZi5fYWRkRXJyb3IobXNnKTtcbiAgICAgICAgICAgICRlcnJvci5mYWRlSW4oODAwKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKGV2LCBbcGFyYW1zLCBtc2ddKTtcbiAgICAgICAgICAgIGlmICghc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgX25vRmlsZXNFcnJvcjogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsYWJlbCA9IHNlbGYubWluRmlsZUNvdW50ID4gMSA/IHNlbGYuZmlsZVBsdXJhbCA6IHNlbGYuZmlsZVNpbmdsZSxcbiAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ZpbGVzVG9vTGVzcy5yZXBsYWNlKCd7bn0nLCBzZWxmLm1pbkZpbGVDb3VudCkucmVwbGFjZSgne2ZpbGVzfScsIGxhYmVsKSxcbiAgICAgICAgICAgICAgICAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lcjtcbiAgICAgICAgICAgIHNlbGYuX2FkZEVycm9yKG1zZyk7XG4gICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMoMCk7XG4gICAgICAgICAgICAkZXJyb3IuZmFkZUluKDgwMCk7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWVycm9yJywgW3BhcmFtcywgbXNnXSk7XG4gICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2hhcy1lcnJvcicpO1xuICAgICAgICB9LFxuICAgICAgICBfcGFyc2VFcnJvcjogZnVuY3Rpb24gKG9wZXJhdGlvbiwganFYSFIsIGVycm9yVGhyb3duLCBmaWxlTmFtZSkge1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UganFYSFIucmVzcG9uc2VKU09OICovXG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGVyck1zZyA9ICQudHJpbShlcnJvclRocm93biArICcnKSwgZG90ID0gZXJyTXNnLnNsaWNlKC0xKSA9PT0gJy4nID8gJycgOiAnLicsXG4gICAgICAgICAgICAgICAgdGV4dCA9IGpxWEhSLnJlc3BvbnNlSlNPTiAhPT0gdW5kZWZpbmVkICYmIGpxWEhSLnJlc3BvbnNlSlNPTi5lcnJvciAhPT0gdW5kZWZpbmVkID9cbiAgICAgICAgICAgICAgICAgICAganFYSFIucmVzcG9uc2VKU09OLmVycm9yIDoganFYSFIucmVzcG9uc2VUZXh0O1xuICAgICAgICAgICAgaWYgKHNlbGYuY2FuY2VsbGluZyAmJiBzZWxmLm1zZ1VwbG9hZEFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLm1zZ1VwbG9hZEFib3J0ZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93QWpheEVycm9yRGV0YWlscyAmJiB0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGV4dCA9ICQudHJpbSh0ZXh0LnJlcGxhY2UoL1xcblxccypcXG4vZywgJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dC5sZW5ndGggPiAwID8gJzxwcmU+JyArIHRleHQgKyAnPC9wcmU+JyA6ICcnO1xuICAgICAgICAgICAgICAgIGVyck1zZyArPSBkb3QgKyB0ZXh0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlcnJNc2cgKz0gZG90O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVyck1zZyA9PT0gZG90KSB7XG4gICAgICAgICAgICAgICAgZXJyTXNnID0gc2VsZi5tc2dBamF4RXJyb3IucmVwbGFjZSgne29wZXJhdGlvbn0nLCBvcGVyYXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5jYW5jZWxsaW5nID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZmlsZU5hbWUgPyAnPGI+JyArIGZpbGVOYW1lICsgJzogPC9iPicgKyBlcnJNc2cgOiBlcnJNc2c7XG4gICAgICAgIH0sXG4gICAgICAgIF9wYXJzZUZpbGVUeXBlOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpc1ZhbGlkLCB2VHlwZSwgY2F0LCBpLCB0eXBlcyA9IHNlbGYuYWxsb3dlZFByZXZpZXdUeXBlcyB8fCBbXTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0eXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNhdCA9IHR5cGVzW2ldO1xuICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBzZWxmLmZpbGVUeXBlU2V0dGluZ3NbY2F0XTtcbiAgICAgICAgICAgICAgICB2VHlwZSA9IGlzVmFsaWQoZmlsZS50eXBlLCBmaWxlLm5hbWUpID8gY2F0IDogJyc7XG4gICAgICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KHZUeXBlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdlR5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICdvdGhlcic7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRQcmV2aWV3SWNvbjogZnVuY3Rpb24gKGZuYW1lKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGV4dCwgb3V0ID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChmbmFtZSAmJiBmbmFtZS5pbmRleE9mKCcuJykgPiAtMSkge1xuICAgICAgICAgICAgICAgIGV4dCA9IGZuYW1lLnNwbGl0KCcuJykucG9wKCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYucHJldmlld0ZpbGVJY29uU2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5nc1tleHRdIHx8IHNlbGYucHJldmlld0ZpbGVJY29uU2V0dGluZ3NbZXh0LnRvTG93ZXJDYXNlKCldIHx8IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzZWxmLnByZXZpZXdGaWxlRXh0U2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgJC5lYWNoKHNlbGYucHJldmlld0ZpbGVFeHRTZXR0aW5ncywgZnVuY3Rpb24gKGtleSwgZnVuYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYucHJldmlld0ZpbGVJY29uU2V0dGluZ3Nba2V5XSAmJiBmdW5jKGV4dCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLnByZXZpZXdGaWxlSWNvblNldHRpbmdzW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gVW5uZWNlc3NhcnlSZXR1cm5TdGF0ZW1lbnRKU1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSxcbiAgICAgICAgX3BhcnNlRmlsZVByZXZpZXdJY29uOiBmdW5jdGlvbiAoY29udGVudCwgZm5hbWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaWNuID0gc2VsZi5fZ2V0UHJldmlld0ljb24oZm5hbWUpIHx8IHNlbGYucHJldmlld0ZpbGVJY29uLCBvdXQgPSBjb250ZW50O1xuICAgICAgICAgICAgaWYgKG91dC5pbmRleE9mKCd7cHJldmlld0ZpbGVJY29ufScpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBvdXQgPSBvdXQuc2V0VG9rZW5zKHsncHJldmlld0ZpbGVJY29uQ2xhc3MnOiBzZWxmLnByZXZpZXdGaWxlSWNvbkNsYXNzLCAncHJldmlld0ZpbGVJY29uJzogaWNufSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBfcmFpc2U6IGZ1bmN0aW9uIChldmVudCwgcGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGUgPSAkLkV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChwYXJhbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcihlLCBwYXJhbXMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRlbGVtZW50LnRyaWdnZXIoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSB8fCBlLnJlc3VsdCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gaWdub3JlIHRoZXNlIGV2ZW50c1xuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGViYXRjaHVwbG9hZGNvbXBsZXRlJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlYmF0Y2h1cGxvYWRzdWNjZXNzJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxldXBsb2FkZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVjbGVhcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWNsZWFyZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVyZXNldCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlZm9sZGVyZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGV1cGxvYWRlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWJhdGNodXBsb2FkZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVkZWxldGVlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWN1c3RvbWVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlc3VjY2Vzc3JlbW92ZSc6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIC8vIHJlY2VpdmUgZGF0YSByZXNwb25zZSB2aWEgYGZpbGVjdXN0b21lcnJvcmAgZXZlbnRgXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLmFqYXhBYm9ydGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmFqYXhBYm9ydGVkID0gZS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgX2xpc3RlbkZ1bGxTY3JlZW46IGZ1bmN0aW9uIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJG1vZGFsID0gc2VsZi4kbW9kYWwsICRidG5GdWxsLCAkYnRuQm9yZDtcbiAgICAgICAgICAgIGlmICghJG1vZGFsIHx8ICEkbW9kYWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGJ0bkZ1bGwgPSAkbW9kYWwgJiYgJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpO1xuICAgICAgICAgICAgJGJ0bkJvcmQgPSAkbW9kYWwgJiYgJG1vZGFsLmZpbmQoJy5idG4tYm9yZGVybGVzcycpO1xuICAgICAgICAgICAgaWYgKCEkYnRuRnVsbC5sZW5ndGggfHwgISRidG5Cb3JkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRidG5GdWxsLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgICRidG5Cb3JkLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgIGlmIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAkYnRuRnVsbC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJGJ0bkJvcmQuYWRkQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICd0cnVlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJG1vZGFsLmhhc0NsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbWF4aW1pemVab29tRGlhbG9nKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChpc0Z1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fbWF4aW1pemVab29tRGlhbG9nKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJGJ0bkJvcmQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2xpc3RlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50LCAkZm9ybSA9IHNlbGYuJGZvcm0sICRjb250ID0gc2VsZi4kY29udGFpbmVyLCBmdWxsU2NyZWVuRXZlbnRzO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZWwsICdjaGFuZ2UnLCAkLnByb3h5KHNlbGYuX2NoYW5nZSwgc2VsZikpO1xuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd0Jyb3dzZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoc2VsZi4kYnRuRmlsZSwgJ2NsaWNrJywgJC5wcm94eShzZWxmLl9icm93c2UsIHNlbGYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGNvbnQuZmluZCgnLmZpbGVpbnB1dC1yZW1vdmU6bm90KFtkaXNhYmxlZF0pJyksICdjbGljaycsICQucHJveHkoc2VsZi5jbGVhciwgc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkY29udC5maW5kKCcuZmlsZWlucHV0LWNhbmNlbCcpLCAnY2xpY2snLCAkLnByb3h5KHNlbGYuY2FuY2VsLCBzZWxmKSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0RHJhZ0Ryb3AoKTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGZvcm0sICdyZXNldCcsICQucHJveHkoc2VsZi5yZXNldCwgc2VsZikpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGZvcm0sICdzdWJtaXQnLCAkLnByb3h5KHNlbGYuX3N1Ym1pdEZvcm0sIHNlbGYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtdXBsb2FkJyksICdjbGljaycsICQucHJveHkoc2VsZi5fdXBsb2FkQ2xpY2ssIHNlbGYpKTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJCh3aW5kb3cpLCAncmVzaXplJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2xpc3RlbkZ1bGxTY3JlZW4oc2NyZWVuLndpZHRoID09PSB3aW5kb3cuaW5uZXJXaWR0aCAmJiBzY3JlZW4uaGVpZ2h0ID09PSB3aW5kb3cuaW5uZXJIZWlnaHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmdWxsU2NyZWVuRXZlbnRzID0gJ3dlYmtpdGZ1bGxzY3JlZW5jaGFuZ2UgbW96ZnVsbHNjcmVlbmNoYW5nZSBmdWxsc2NyZWVuY2hhbmdlIE1TRnVsbHNjcmVlbkNoYW5nZSc7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCQoZG9jdW1lbnQpLCBmdWxsU2NyZWVuRXZlbnRzLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbGlzdGVuRnVsbFNjcmVlbigkaC5jaGVja0Z1bGxTY3JlZW4oKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRDbGlja2FibGUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRDbGlja2FibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHpvbmU7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNDbGlja2FibGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkem9uZSA9IHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi4kZHJvcFpvbmUgOiBzZWxmLiRwcmV2aWV3LmZpbmQoJy5maWxlLWRlZmF1bHQtcHJldmlldycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKCR6b25lLCAnY2xpY2thYmxlJyk7XG4gICAgICAgICAgICAkem9uZS5hdHRyKCd0YWJpbmRleCcsIC0xKTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHpvbmUsICdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0YXIgPSAkKGUudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICBpZiAoISR0YXIucGFyZW50cygnLmZpbGUtcHJldmlldy10aHVtYm5haWxzJykubGVuZ3RoIHx8ICR0YXIucGFyZW50cygnLmZpbGUtZGVmYXVsdC1wcmV2aWV3JykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICAgICAgJHpvbmUuYmx1cigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdERyYWdEcm9wOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICR6b25lID0gc2VsZi4kZHJvcFpvbmU7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQgJiYgc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHpvbmUsICdkcmFnZW50ZXIgZHJhZ292ZXInLCAkLnByb3h5KHNlbGYuX3pvbmVEcmFnRW50ZXIsIHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCR6b25lLCAnZHJhZ2xlYXZlJywgJC5wcm94eShzZWxmLl96b25lRHJhZ0xlYXZlLCBzZWxmKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkem9uZSwgJ2Ryb3AnLCAkLnByb3h5KHNlbGYuX3pvbmVEcm9wLCBzZWxmKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkKGRvY3VtZW50KSwgJ2RyYWdlbnRlciBkcmFnb3ZlciBkcm9wJywgc2VsZi5fem9uZURyYWdEcm9wSW5pdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF96b25lRHJhZ0Ryb3BJbml0OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcmFnRW50ZXI6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGhhc0ZpbGVzID0gJC5pbkFycmF5KCdGaWxlcycsIGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIudHlwZXMpID4gLTE7XG4gICAgICAgICAgICBzZWxmLl96b25lRHJhZ0Ryb3BJbml0KGUpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCB8fCAhaGFzRmlsZXMpIHtcbiAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmVmZmVjdEFsbG93ZWQgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ25vbmUnO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRkcm9wWm9uZSwgJ2ZpbGUtaGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcmFnTGVhdmU6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl96b25lRHJhZ0Ryb3BJbml0KGUpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGRyb3Bab25lLnJlbW92ZUNsYXNzKCdmaWxlLWhpZ2hsaWdodGVkJyk7XG4gICAgICAgIH0sXG4gICAgICAgIF96b25lRHJvcDogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIgKi9cbiAgICAgICAgICAgIGlmIChzZWxmLmlzRGlzYWJsZWQgfHwgJGguaXNFbXB0eShlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2NoYW5nZShlLCAnZHJhZ2Ryb3AnKTtcbiAgICAgICAgICAgIHNlbGYuJGRyb3Bab25lLnJlbW92ZUNsYXNzKCdmaWxlLWhpZ2hsaWdodGVkJyk7XG4gICAgICAgIH0sXG4gICAgICAgIF91cGxvYWRDbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGJ0biA9IHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LXVwbG9hZCcpLCAkZm9ybSxcbiAgICAgICAgICAgICAgICBpc0VuYWJsZWQgPSAhJGJ0bi5oYXNDbGFzcygnZGlzYWJsZWQnKSAmJiAkaC5pc0VtcHR5KCRidG4uYXR0cignZGlzYWJsZWQnKSk7XG4gICAgICAgICAgICBpZiAoZSAmJiBlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQgJiYgJGJ0bi5hdHRyKCd0eXBlJykgIT09ICdzdWJtaXQnKSB7XG4gICAgICAgICAgICAgICAgICAgICRmb3JtID0gJGJ0bi5jbG9zZXN0KCdmb3JtJyk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGRvd25ncmFkZSB0byBub3JtYWwgZm9ybSBzdWJtaXQgaWYgcG9zc2libGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRmb3JtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGZvcm0udHJpZ2dlcignc3VibWl0Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBpZiAoaXNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3N1Ym1pdEZvcm06IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9pc0ZpbGVTZWxlY3Rpb25WYWxpZCgpICYmICFzZWxmLl9hYm9ydCh7fSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jbGVhclByZXZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHAgPSBzZWxmLiRwcmV2aWV3LFxuICAgICAgICAgICAgICAgICR0aHVtYnMgPSBzZWxmLnNob3dVcGxvYWRlZFRodW1icyA/IHNlbGYuZ2V0RnJhbWVzKCc6bm90KC5maWxlLXByZXZpZXctc3VjY2VzcyknKSA6IHNlbGYuZ2V0RnJhbWVzKCk7XG4gICAgICAgICAgICAkdGh1bWJzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZSgkcC5maW5kKCcjem9vbS0nICsgJHRodW1iLmF0dHIoJ2lkJykpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmdldEZyYW1lcygpLmxlbmd0aCB8fCAhc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0VXBsb2FkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl92YWxpZGF0ZURlZmF1bHRQcmV2aWV3KCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0U29ydGFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kcHJldmlldywgc2V0dGluZ3MsIHNlbGVjdG9yID0gJy4nICsgJGguU09SVF9DU1M7XG4gICAgICAgICAgICBpZiAoIXdpbmRvdy5LdlNvcnRhYmxlIHx8ICRlbC5maW5kKHNlbGVjdG9yKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1VudXNlZEdsb2JhbFN5bWJvbHNcbiAgICAgICAgICAgIHNldHRpbmdzID0ge1xuICAgICAgICAgICAgICAgIGhhbmRsZTogJy5kcmFnLWhhbmRsZS1pbml0JyxcbiAgICAgICAgICAgICAgICBkYXRhSWRBdHRyOiAnZGF0YS1wcmV2aWV3LWlkJyxcbiAgICAgICAgICAgICAgICBzY3JvbGw6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGRyYWdnYWJsZTogc2VsZWN0b3IsXG4gICAgICAgICAgICAgICAgb25Tb3J0OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb2xkSW5kZXggPSBlLm9sZEluZGV4LCBuZXdJbmRleCA9IGUubmV3SW5kZXgsIGtleSwgJGZyYW1lO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gJGgubW92ZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXcsIG9sZEluZGV4LCBuZXdJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSAkaC5tb3ZlQXJyYXkoc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZywgb2xkSW5kZXgsIG5ld0luZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnW2ldICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0gc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZ1tpXS5rZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lID0gJChcIi5rdi1maWxlLXJlbW92ZVtkYXRhLWtleT0nXCIgKyBrZXkgKyBcIiddXCIpLmNsb3Nlc3QoJGguRlJBTUVTKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnLCAnaW5pdF8nICsgaSkuYXR0cignZGF0YS1maWxlaW5kZXgnLCAnaW5pdF8nICsgaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVzb3J0ZWQnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aWV3SWQ6ICQoZS5pdGVtKS5hdHRyKCdpZCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ29sZEluZGV4Jzogb2xkSW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAnbmV3SW5kZXgnOiBuZXdJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YWNrOiBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoJGVsLmRhdGEoJ2t2c29ydGFibGUnKSkge1xuICAgICAgICAgICAgICAgICRlbC5rdnNvcnRhYmxlKCdkZXN0cm95Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBzZXR0aW5ncywgc2VsZi5maWxlQWN0aW9uU2V0dGluZ3MuZHJhZ1NldHRpbmdzKTtcbiAgICAgICAgICAgICRlbC5rdnNvcnRhYmxlKHNldHRpbmdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRQcmV2aWV3OiBmdW5jdGlvbiAoaXNJbml0KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcCA9IHNlbGYuaW5pdGlhbENhcHRpb24gfHwgJycsIG91dDtcbiAgICAgICAgICAgIGlmICghc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgICAgIGlmIChpc0luaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRDYXB0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG91dCA9IHNlbGYucHJldmlld0NhY2hlLm91dCgpO1xuICAgICAgICAgICAgY2FwID0gaXNJbml0ICYmIHNlbGYuaW5pdGlhbENhcHRpb24gPyBzZWxmLmluaXRpYWxDYXB0aW9uIDogb3V0LmNhcHRpb247XG4gICAgICAgICAgICBzZWxmLiRwcmV2aWV3Lmh0bWwob3V0LmNvbnRlbnQpO1xuICAgICAgICAgICAgc2VsZi5fc2V0SW5pdFRodW1iQXR0cigpO1xuICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkob3V0LmNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfZ2V0Wm9vbUJ1dHRvbjogZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgbGFiZWwgPSBzZWxmLnByZXZpZXdab29tQnV0dG9uSWNvbnNbdHlwZV0sIGNzcyA9IHNlbGYucHJldmlld1pvb21CdXR0b25DbGFzc2VzW3R5cGVdLFxuICAgICAgICAgICAgICAgIHRpdGxlID0gJyB0aXRsZT1cIicgKyAoc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvblRpdGxlc1t0eXBlXSB8fCAnJykgKyAnXCIgJyxcbiAgICAgICAgICAgICAgICBwYXJhbXMgPSB0aXRsZSArICh0eXBlID09PSAnY2xvc2UnID8gJyBkYXRhLWRpc21pc3M9XCJtb2RhbFwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiJyA6ICcnKTtcbiAgICAgICAgICAgIGlmICh0eXBlID09PSAnZnVsbHNjcmVlbicgfHwgdHlwZSA9PT0gJ2JvcmRlcmxlc3MnIHx8IHR5cGUgPT09ICd0b2dnbGVoZWFkZXInKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zICs9ICcgZGF0YS10b2dnbGU9XCJidXR0b25cIiBhcmlhLXByZXNzZWQ9XCJmYWxzZVwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCInICsgY3NzICsgJyBidG4tJyArIHR5cGUgKyAnXCInICsgcGFyYW1zICsgJz4nICsgbGFiZWwgKyAnPC9idXR0b24+JztcbiAgICAgICAgfSxcbiAgICAgICAgX2dldE1vZGFsQ29udGVudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdtb2RhbCcpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgJ3J0bCc6IHNlbGYucnRsID8gJyBrdi1ydGwnIDogJycsXG4gICAgICAgICAgICAgICAgJ3pvb21GcmFtZUNsYXNzJzogc2VsZi5mcmFtZUNsYXNzLFxuICAgICAgICAgICAgICAgICdoZWFkaW5nJzogc2VsZi5tc2dab29tTW9kYWxIZWFkaW5nLFxuICAgICAgICAgICAgICAgICdwcmV2Jzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbigncHJldicpLFxuICAgICAgICAgICAgICAgICduZXh0Jzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbignbmV4dCcpLFxuICAgICAgICAgICAgICAgICd0b2dnbGVoZWFkZXInOiBzZWxmLl9nZXRab29tQnV0dG9uKCd0b2dnbGVoZWFkZXInKSxcbiAgICAgICAgICAgICAgICAnZnVsbHNjcmVlbic6IHNlbGYuX2dldFpvb21CdXR0b24oJ2Z1bGxzY3JlZW4nKSxcbiAgICAgICAgICAgICAgICAnYm9yZGVybGVzcyc6IHNlbGYuX2dldFpvb21CdXR0b24oJ2JvcmRlcmxlc3MnKSxcbiAgICAgICAgICAgICAgICAnY2xvc2UnOiBzZWxmLl9nZXRab29tQnV0dG9uKCdjbG9zZScpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2xpc3Rlbk1vZGFsRXZlbnQ6IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgZ2V0UGFyYW1zID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2VFdmVudDogZSxcbiAgICAgICAgICAgICAgICAgICAgcHJldmlld0lkOiAkbW9kYWwuZGF0YSgncHJldmlld0lkJyksXG4gICAgICAgICAgICAgICAgICAgIG1vZGFsOiAkbW9kYWxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICRtb2RhbC5vbihldmVudCArICcuYnMubW9kYWwnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHZhciAkYnRuRnVsbCA9ICRtb2RhbC5maW5kKCcuYnRuLWZ1bGxzY3JlZW4nKSwgJGJ0bkJvcmQgPSAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGV6b29tJyArIGV2ZW50LCBnZXRQYXJhbXMoZSkpO1xuICAgICAgICAgICAgICAgIGlmIChldmVudCA9PT0gJ3Nob3duJykge1xuICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgICAgICRidG5GdWxsLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRtb2RhbC5oYXNDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fbWF4aW1pemVab29tRGlhbG9nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJGguY2hlY2tGdWxsU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuRnVsbC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkJvcmQuYWRkQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRab29tOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRkaWFsb2csIG1vZGFsTWFpbiA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdtb2RhbE1haW4nKSwgbW9kYWxJZCA9ICcjJyArICRoLk1PREFMX0lEO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kbW9kYWwgPSAkKG1vZGFsSWQpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLiRtb2RhbCB8fCAhc2VsZi4kbW9kYWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGRpYWxvZyA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwobW9kYWxNYWluKS5pbnNlcnRBZnRlcihzZWxmLiRjb250YWluZXIpO1xuICAgICAgICAgICAgICAgIHNlbGYuJG1vZGFsID0gJChtb2RhbElkKS5pbnNlcnRCZWZvcmUoJGRpYWxvZyk7XG4gICAgICAgICAgICAgICAgJGRpYWxvZy5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRoLmluaXRNb2RhbChzZWxmLiRtb2RhbCk7XG4gICAgICAgICAgICBzZWxmLiRtb2RhbC5odG1sKHNlbGYuX2dldE1vZGFsQ29udGVudCgpKTtcbiAgICAgICAgICAgICQuZWFjaCgkaC5NT0RBTF9FVkVOVFMsIGZ1bmN0aW9uIChrZXksIGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbGlzdGVuTW9kYWxFdmVudChldmVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRab29tQnV0dG9uczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBwcmV2aWV3SWQgPSBzZWxmLiRtb2RhbC5kYXRhKCdwcmV2aWV3SWQnKSB8fCAnJywgJGZpcnN0LCAkbGFzdCxcbiAgICAgICAgICAgICAgICB0aHVtYnMgPSBzZWxmLmdldEZyYW1lcygpLnRvQXJyYXkoKSwgbGVuID0gdGh1bWJzLmxlbmd0aCwgJHByZXYgPSBzZWxmLiRtb2RhbC5maW5kKCcuYnRuLXByZXYnKSxcbiAgICAgICAgICAgICAgICAkbmV4dCA9IHNlbGYuJG1vZGFsLmZpbmQoJy5idG4tbmV4dCcpO1xuICAgICAgICAgICAgaWYgKHRodW1icy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgJHByZXYuaGlkZSgpO1xuICAgICAgICAgICAgICAgICRuZXh0LmhpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICRwcmV2LnNob3coKTtcbiAgICAgICAgICAgICAgICAkbmV4dC5zaG93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWxlbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRmaXJzdCA9ICQodGh1bWJzWzBdKTtcbiAgICAgICAgICAgICRsYXN0ID0gJCh0aHVtYnNbbGVuIC0gMV0pO1xuICAgICAgICAgICAgJHByZXYucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICRuZXh0LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBpZiAoJGZpcnN0Lmxlbmd0aCAmJiAkZmlyc3QuYXR0cignaWQnKSA9PT0gcHJldmlld0lkKSB7XG4gICAgICAgICAgICAgICAgJHByZXYuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkbGFzdC5sZW5ndGggJiYgJGxhc3QuYXR0cignaWQnKSA9PT0gcHJldmlld0lkKSB7XG4gICAgICAgICAgICAgICAgJG5leHQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX21heGltaXplWm9vbURpYWxvZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJGhlYWQgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWhlYWRlcjp2aXNpYmxlJyksXG4gICAgICAgICAgICAgICAgJGZvb3QgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWZvb3Rlcjp2aXNpYmxlJyksICRib2R5ID0gJG1vZGFsLmZpbmQoJy5tb2RhbC1ib2R5JyksXG4gICAgICAgICAgICAgICAgaCA9ICQod2luZG93KS5oZWlnaHQoKSwgZGlmZiA9IDA7XG4gICAgICAgICAgICAkbW9kYWwuYWRkQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJyk7XG4gICAgICAgICAgICBpZiAoJGhlYWQgJiYgJGhlYWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaCAtPSAkaGVhZC5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkZm9vdCAmJiAkZm9vdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBoIC09ICRmb290Lm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRib2R5ICYmICRib2R5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGRpZmYgPSAkYm9keS5vdXRlckhlaWdodCh0cnVlKSAtICRib2R5LmhlaWdodCgpO1xuICAgICAgICAgICAgICAgIGggLT0gZGlmZjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5JykuaGVpZ2h0KGgpO1xuICAgICAgICB9LFxuICAgICAgICBfcmVzaXplWm9vbURpYWxvZzogZnVuY3Rpb24gKGZ1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJG1vZGFsID0gc2VsZi4kbW9kYWwsICRidG5GdWxsID0gJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpLFxuICAgICAgICAgICAgICAgICRidG5Cb3JkID0gJG1vZGFsLmZpbmQoJy5idG4tYm9yZGVybGVzcycpO1xuICAgICAgICAgICAgaWYgKCRtb2RhbC5oYXNDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgICRoLnRvZ2dsZUZ1bGxTY3JlZW4oZmFsc2UpO1xuICAgICAgICAgICAgICAgIGlmICghZnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRidG5GdWxsLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJG1vZGFsLnJlbW92ZUNsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi4kbW9kYWwuZmluZCgnLmt2LXpvb20tYm9keScpLmNzcygnaGVpZ2h0Jywgc2VsZi56b29tTW9kYWxIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkZ1bGwucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkYnRuRnVsbC5oYXNDbGFzcygnYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRtb2RhbC5yZW1vdmVDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2l6ZVpvb21EaWFsb2codHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJGJ0bkJvcmQuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkJvcmQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIWZ1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fbWF4aW1pemVab29tRGlhbG9nKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJGgudG9nZ2xlRnVsbFNjcmVlbih0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRtb2RhbC5mb2N1cygpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0Wm9vbUNvbnRlbnQ6IGZ1bmN0aW9uICgkZnJhbWUsIGFuaW1hdGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGNvbnRlbnQsIHRtcGx0LCBib2R5LCB0aXRsZSwgJGJvZHksICRkYXRhRWwsIGNvbmZpZywgcGlkID0gJGZyYW1lLmF0dHIoJ2lkJyksXG4gICAgICAgICAgICAgICAgJG1vZGFsID0gc2VsZi4kbW9kYWwsICRwcmV2ID0gJG1vZGFsLmZpbmQoJy5idG4tcHJldicpLCAkbmV4dCA9ICRtb2RhbC5maW5kKCcuYnRuLW5leHQnKSwgJHRtcCxcbiAgICAgICAgICAgICAgICAkYnRuRnVsbCA9ICRtb2RhbC5maW5kKCcuYnRuLWZ1bGxzY3JlZW4nKSwgJGJ0bkJvcmQgPSAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyksIGNhcCwgc2l6ZSxcbiAgICAgICAgICAgICAgICAkYnRuVG9naCA9ICRtb2RhbC5maW5kKCcuYnRuLXRvZ2dsZWhlYWRlcicpLCAkem9vbVByZXZpZXcgPSBzZWxmLiRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyBwaWQpO1xuICAgICAgICAgICAgdG1wbHQgPSAkem9vbVByZXZpZXcuYXR0cignZGF0YS10ZW1wbGF0ZScpIHx8ICdnZW5lcmljJztcbiAgICAgICAgICAgICRjb250ZW50ID0gJHpvb21QcmV2aWV3LmZpbmQoJy5rdi1maWxlLWNvbnRlbnQnKTtcbiAgICAgICAgICAgIGJvZHkgPSAkY29udGVudC5sZW5ndGggPyAkY29udGVudC5odG1sKCkgOiAnJztcbiAgICAgICAgICAgIGNhcCA9ICRmcmFtZS5kYXRhKCdjYXB0aW9uJykgfHwgJyc7XG4gICAgICAgICAgICBzaXplID0gJGZyYW1lLmRhdGEoJ3NpemUnKSB8fCAnJztcbiAgICAgICAgICAgIHRpdGxlID0gY2FwICsgJyAnICsgc2l6ZTtcbiAgICAgICAgICAgICRtb2RhbC5maW5kKCcua3Ytem9vbS10aXRsZScpLmh0bWwodGl0bGUpO1xuICAgICAgICAgICAgJGJvZHkgPSAkbW9kYWwuZmluZCgnLmt2LXpvb20tYm9keScpO1xuICAgICAgICAgICAgJG1vZGFsLnJlbW92ZUNsYXNzKCdrdi1zaW5nbGUtY29udGVudCcpO1xuICAgICAgICAgICAgaWYgKGFuaW1hdGUpIHtcbiAgICAgICAgICAgICAgICAkdG1wID0gJGJvZHkuYWRkQ2xhc3MoJ2ZpbGUtdGh1bWItbG9hZGluZycpLmNsb25lKCkuaW5zZXJ0QWZ0ZXIoJGJvZHkpO1xuICAgICAgICAgICAgICAgICRib2R5Lmh0bWwoYm9keSkuaGlkZSgpO1xuICAgICAgICAgICAgICAgICR0bXAuZmFkZU91dCgnZmFzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJGJvZHkuZmFkZUluKCdmYXN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGJvZHkucmVtb3ZlQ2xhc3MoJ2ZpbGUtdGh1bWItbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgJHRtcC5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJGJvZHkuaHRtbChib2R5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbmZpZyA9IHNlbGYucHJldmlld1pvb21TZXR0aW5nc1t0bXBsdF07XG4gICAgICAgICAgICBpZiAoY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgJGRhdGFFbCA9ICRib2R5LmZpbmQoJy5rdi1wcmV2aWV3LWRhdGEnKTtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJGRhdGFFbCwgJ2ZpbGUtem9vbS1kZXRhaWwnKTtcbiAgICAgICAgICAgICAgICAkLmVhY2goY29uZmlnLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAkZGF0YUVsLmNzcyhrZXksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCgkZGF0YUVsLmF0dHIoJ3dpZHRoJykgJiYga2V5ID09PSAnd2lkdGgnKSB8fCAoJGRhdGFFbC5hdHRyKCdoZWlnaHQnKSAmJiBrZXkgPT09ICdoZWlnaHQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGRhdGFFbC5yZW1vdmVBdHRyKGtleSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRtb2RhbC5kYXRhKCdwcmV2aWV3SWQnLCBwaWQpO1xuICAgICAgICAgICAgdmFyICRpbWcgPSAkYm9keS5maW5kKCdpbWcnKTtcbiAgICAgICAgICAgIGlmICgkaW1nLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICRoLmFkanVzdE9yaWVudGVkSW1hZ2UoJGltZywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRwcmV2LCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fem9vbVNsaWRlU2hvdygncHJldicsIHBpZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJG5leHQsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCduZXh0JywgcGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkYnRuRnVsbCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2l6ZVpvb21EaWFsb2codHJ1ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGJ0bkJvcmQsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZXNpemVab29tRGlhbG9nKGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkYnRuVG9naCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkaGVhZGVyID0gJG1vZGFsLmZpbmQoJy5tb2RhbC1oZWFkZXInKSwgJGZsb2F0QmFyID0gJG1vZGFsLmZpbmQoJy5tb2RhbC1ib2R5IC5mbG9hdGluZy1idXR0b25zJyksXG4gICAgICAgICAgICAgICAgICAgIGh0LCAkYWN0aW9ucyA9ICRoZWFkZXIuZmluZCgnLmt2LXpvb20tYWN0aW9ucycpLCByZXNpemUgPSBmdW5jdGlvbiAoaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJGJvZHkgPSBzZWxmLiRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5JyksIGggPSBzZWxmLnpvb21Nb2RhbEhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkbW9kYWwuaGFzQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoID0gJGJvZHkub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaCA9IGggLSAkaGVhZGVyLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICRib2R5LmNzcygnaGVpZ2h0JywgaGVpZ2h0ID8gaCArIGhlaWdodCA6IGgpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmICgkaGVhZGVyLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGh0ID0gJGhlYWRlci5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgJGhlYWRlci5zbGlkZVVwKCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGFjdGlvbnMuZmluZCgnLmJ0bicpLmFwcGVuZFRvKCRmbG9hdEJhcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNpemUoaHQpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkZmxvYXRCYXIuZmluZCgnLmJ0bicpLmFwcGVuZFRvKCRhY3Rpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgJGhlYWRlci5zbGlkZURvd24oJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNpemUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRtb2RhbC5mb2N1cygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRtb2RhbCwgJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBlLndoaWNoIHx8IGUua2V5Q29kZTtcbiAgICAgICAgICAgICAgICBpZiAoa2V5ID09PSAzNyAmJiAhJHByZXYuYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCdwcmV2JywgcGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gMzkgJiYgISRuZXh0LmF0dHIoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fem9vbVNsaWRlU2hvdygnbmV4dCcsIHBpZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF96b29tUHJldmlldzogZnVuY3Rpb24gKCRidG4pIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lLCAkbW9kYWwgPSBzZWxmLiRtb2RhbDtcbiAgICAgICAgICAgIGlmICghJGJ0bi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyAnQ2Fubm90IHpvb20gdG8gZGV0YWlsZWQgcHJldmlldyEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguaW5pdE1vZGFsKCRtb2RhbCk7XG4gICAgICAgICAgICAkbW9kYWwuaHRtbChzZWxmLl9nZXRNb2RhbENvbnRlbnQoKSk7XG4gICAgICAgICAgICAkZnJhbWUgPSAkYnRuLmNsb3Nlc3QoJGguRlJBTUVTKTtcbiAgICAgICAgICAgIHNlbGYuX3NldFpvb21Db250ZW50KCRmcmFtZSk7XG4gICAgICAgICAgICAkbW9kYWwubW9kYWwoJ3Nob3cnKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9ucygpO1xuICAgICAgICB9LFxuICAgICAgICBfem9vbVNsaWRlU2hvdzogZnVuY3Rpb24gKGRpciwgcHJldmlld0lkKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRidG4gPSBzZWxmLiRtb2RhbC5maW5kKCcua3Ytem9vbS1hY3Rpb25zIC5idG4tJyArIGRpciksICR0YXJnRnJhbWUsIGksXG4gICAgICAgICAgICAgICAgdGh1bWJzID0gc2VsZi5nZXRGcmFtZXMoKS50b0FycmF5KCksIGxlbiA9IHRodW1icy5sZW5ndGgsIG91dDtcbiAgICAgICAgICAgIGlmICgkYnRuLmF0dHIoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoJCh0aHVtYnNbaV0pLmF0dHIoJ2lkJykgPT09IHByZXZpZXdJZCkge1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSBkaXIgPT09ICdwcmV2JyA/IGkgLSAxIDogaSArIDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdXQgPCAwIHx8IG91dCA+PSBsZW4gfHwgIXRodW1ic1tvdXRdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRhcmdGcmFtZSA9ICQodGh1bWJzW291dF0pO1xuICAgICAgICAgICAgaWYgKCR0YXJnRnJhbWUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0Wm9vbUNvbnRlbnQoJHRhcmdGcmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9pbml0Wm9vbUJ1dHRvbnMoKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlem9vbScgKyBkaXIsIHsncHJldmlld0lkJzogcHJldmlld0lkLCBtb2RhbDogc2VsZi4kbW9kYWx9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRab29tQnV0dG9uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLiRwcmV2aWV3LmZpbmQoJy5rdi1maWxlLXpvb20nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVsID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlbCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl96b29tUHJldmlldygkZWwpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jbGVhck9iamVjdHM6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgICAgICAgICRlbC5maW5kKCd2aWRlbyBhdWRpbycpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGF1c2UoKTtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkZWwuZmluZCgnaW1nIG9iamVjdCBkaXYnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jbGVhckZpbGVJbnB1dDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50LCAkc3JjRnJtLCAkdG1wRnJtLCAkdG1wRWw7XG4gICAgICAgICAgICBzZWxmLmZpbGVJbnB1dENsZWFyZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoJGVsLnZhbCgpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEZpeCBmb3IgSUUgdmVyIDwgMTEsIHRoYXQgZG9lcyBub3QgY2xlYXIgZmlsZSBpbnB1dHMuIFJlcXVpcmVzIGEgc2VxdWVuY2Ugb2Ygc3RlcHMgdG8gcHJldmVudCBJRVxuICAgICAgICAgICAgLy8gY3Jhc2hpbmcgYnV0IHN0aWxsIGFsbG93IGNsZWFyaW5nIG9mIHRoZSBmaWxlIGlucHV0LlxuICAgICAgICAgICAgaWYgKHNlbGYuaXNJRTkgfHwgc2VsZi5pc0lFMTApIHtcbiAgICAgICAgICAgICAgICAkc3JjRnJtID0gJGVsLmNsb3Nlc3QoJ2Zvcm0nKTtcbiAgICAgICAgICAgICAgICAkdG1wRnJtID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdmb3JtJykpO1xuICAgICAgICAgICAgICAgICR0bXBFbCA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpO1xuICAgICAgICAgICAgICAgICRlbC5iZWZvcmUoJHRtcEVsKTtcbiAgICAgICAgICAgICAgICBpZiAoJHNyY0ZybS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgJHNyY0ZybS5hZnRlcigkdG1wRnJtKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdG1wRWwuYWZ0ZXIoJHRtcEZybSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICR0bXBGcm0uYXBwZW5kKCRlbCkudHJpZ2dlcigncmVzZXQnKTtcbiAgICAgICAgICAgICAgICAkdG1wRWwuYmVmb3JlKCRlbCkucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgJHRtcEZybS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vIG5vcm1hbCBpbnB1dCBjbGVhciBiZWhhdmlvciBmb3Igb3RoZXIgc2FuZSBicm93c2Vyc1xuICAgICAgICAgICAgICAgICRlbC52YWwoJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfcmVzZXRVcGxvYWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUgPSB7Y29udGVudDogW10sIGNvbmZpZzogW10sIHRhZ3M6IFtdLCBhcHBlbmQ6IHRydWV9O1xuICAgICAgICAgICAgc2VsZi51cGxvYWRDb3VudCA9IDA7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1cyA9IHt9O1xuICAgICAgICAgICAgc2VsZi51cGxvYWRMb2cgPSBbXTtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkQXN5bmNDb3VudCA9IDA7XG4gICAgICAgICAgICBzZWxmLmxvYWRlZEltYWdlcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi50b3RhbEltYWdlc0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYuJGJ0blVwbG9hZC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMCk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kcHJvZ3Jlc3MsICdoaWRlJyk7XG4gICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycyhmYWxzZSk7XG4gICAgICAgICAgICBzZWxmLmFqYXhBYm9ydGVkID0gZmFsc2U7XG4gICAgICAgICAgICBzZWxmLmFqYXhSZXF1ZXN0cyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRDYW52YXMoKTtcbiAgICAgICAgICAgIHNlbGYuY2FjaGVJbml0aWFsUHJldmlldyA9IHt9O1xuICAgICAgICAgICAgaWYgKHNlbGYub3ZlcndyaXRlSW5pdGlhbCkge1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSBbXTtcbiAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnID0gW107XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFncyA9IFtdO1xuICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtdLFxuICAgICAgICAgICAgICAgICAgICBjb25maWc6IFtdLFxuICAgICAgICAgICAgICAgICAgICB0YWdzOiBbXVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldENhbnZhczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHNlbGYuY2FudmFzICYmIHNlbGYuaW1hZ2VDYW52YXNDb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pbWFnZUNhbnZhc0NvbnRleHQuY2xlYXJSZWN0KDAsIDAsIHNlbGYuY2FudmFzLndpZHRoLCBzZWxmLmNhbnZhcy5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaGFzSW5pdGlhbFByZXZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiAhc2VsZi5vdmVyd3JpdGVJbml0aWFsICYmIHNlbGYucHJldmlld0NhY2hlLmNvdW50KCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldFByZXZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgb3V0LCBjYXA7XG4gICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSkge1xuICAgICAgICAgICAgICAgIG91dCA9IHNlbGYucHJldmlld0NhY2hlLm91dCgpO1xuICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbChvdXQuY29udGVudCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0SW5pdFRodW1iQXR0cigpO1xuICAgICAgICAgICAgICAgIGNhcCA9IHNlbGYuaW5pdGlhbENhcHRpb24gPyBzZWxmLmluaXRpYWxDYXB0aW9uIDogb3V0LmNhcHRpb247XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhclByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9pbml0Q2FwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9pbml0Wm9vbSgpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfY2xlYXJEZWZhdWx0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi4kcHJldmlldy5maW5kKCcuZmlsZS1kZWZhdWx0LXByZXZpZXcnKS5yZW1vdmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3ZhbGlkYXRlRGVmYXVsdFByZXZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldyB8fCAkaC5pc0VtcHR5KHNlbGYuZGVmYXVsdFByZXZpZXdDb250ZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbCgnPGRpdiBjbGFzcz1cImZpbGUtZGVmYXVsdC1wcmV2aWV3XCI+JyArIHNlbGYuZGVmYXVsdFByZXZpZXdDb250ZW50ICsgJzwvZGl2PicpO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgc2VsZi5faW5pdENsaWNrYWJsZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfcmVzZXRQcmV2aWV3VGh1bWJzOiBmdW5jdGlvbiAoaXNBamF4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIG91dDtcbiAgICAgICAgICAgIGlmIChpc0FqYXgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhclByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5faGFzSW5pdGlhbFByZXZpZXcoKSkge1xuICAgICAgICAgICAgICAgIG91dCA9IHNlbGYucHJldmlld0NhY2hlLm91dCgpO1xuICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbChvdXQuY29udGVudCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0SW5pdFRodW1iQXR0cigpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24ob3V0LmNhcHRpb24pO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3QWN0aW9ucygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhclByZXZpZXcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2dldExheW91dFRlbXBsYXRlOiBmdW5jdGlvbiAodCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0ZW1wbGF0ZSA9IHNlbGYubGF5b3V0VGVtcGxhdGVzW3RdO1xuICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoc2VsZi5jdXN0b21MYXlvdXRUYWdzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkaC5yZXBsYWNlVGFncyh0ZW1wbGF0ZSwgc2VsZi5jdXN0b21MYXlvdXRUYWdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldFByZXZpZXdUZW1wbGF0ZTogZnVuY3Rpb24gKHQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdGVtcGxhdGUgPSBzZWxmLnByZXZpZXdUZW1wbGF0ZXNbdF07XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eShzZWxmLmN1c3RvbVByZXZpZXdUYWdzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkaC5yZXBsYWNlVGFncyh0ZW1wbGF0ZSwgc2VsZi5jdXN0b21QcmV2aWV3VGFncyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRPdXREYXRhOiBmdW5jdGlvbiAoanFYSFIsIHJlc3BvbnNlRGF0YSwgZmlsZXNEYXRhKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBqcVhIUiA9IGpxWEhSIHx8IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VEYXRhID0gcmVzcG9uc2VEYXRhIHx8IHt9O1xuICAgICAgICAgICAgZmlsZXNEYXRhID0gZmlsZXNEYXRhIHx8IHNlbGYuZmlsZXN0YWNrLnNsaWNlKDApIHx8IHt9O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmb3JtOiBzZWxmLmZvcm1kYXRhLFxuICAgICAgICAgICAgICAgIGZpbGVzOiBmaWxlc0RhdGEsXG4gICAgICAgICAgICAgICAgZmlsZW5hbWVzOiBzZWxmLmZpbGVuYW1lcyxcbiAgICAgICAgICAgICAgICBmaWxlc2NvdW50OiBzZWxmLmdldEZpbGVzQ291bnQoKSxcbiAgICAgICAgICAgICAgICBleHRyYTogc2VsZi5fZ2V0RXh0cmFEYXRhKCksXG4gICAgICAgICAgICAgICAgcmVzcG9uc2U6IHJlc3BvbnNlRGF0YSxcbiAgICAgICAgICAgICAgICByZWFkZXI6IHNlbGYucmVhZGVyLFxuICAgICAgICAgICAgICAgIGpxWEhSOiBqcVhIUlxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldE1zZ1NlbGVjdGVkOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBzdHJGaWxlcyA9IG4gPT09IDEgPyBzZWxmLmZpbGVTaW5nbGUgOiBzZWxmLmZpbGVQbHVyYWw7XG4gICAgICAgICAgICByZXR1cm4gbiA+IDAgPyBzZWxmLm1zZ1NlbGVjdGVkLnJlcGxhY2UoJ3tufScsIG4pLnJlcGxhY2UoJ3tmaWxlc30nLCBzdHJGaWxlcykgOiBzZWxmLm1zZ05vRmlsZXNTZWxlY3RlZDtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZyYW1lOiBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gJCgnIycgKyBpZCk7XG4gICAgICAgICAgICBpZiAoISRmcmFtZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9sb2coJ0ludmFsaWQgdGh1bWIgZnJhbWUgd2l0aCBpZDogXCInICsgaWQgKyAnXCIuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJGZyYW1lO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0VGh1bWJzOiBmdW5jdGlvbiAoY3NzKSB7XG4gICAgICAgICAgICBjc3MgPSBjc3MgfHwgJyc7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRGcmFtZXMoJzpub3QoLmZpbGUtcHJldmlldy1pbml0aWFsKScgKyBjc3MpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RXh0cmFEYXRhOiBmdW5jdGlvbiAocHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhID0gc2VsZi51cGxvYWRFeHRyYURhdGE7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNlbGYudXBsb2FkRXh0cmFEYXRhID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gc2VsZi51cGxvYWRFeHRyYURhdGEocHJldmlld0lkLCBpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRYaHI6IGZ1bmN0aW9uICh4aHJvYmosIHByZXZpZXdJZCwgZmlsZUNvdW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoeGhyb2JqLnVwbG9hZCkge1xuICAgICAgICAgICAgICAgIHhocm9iai51cGxvYWQuYWRkRXZlbnRMaXN0ZW5lcigncHJvZ3Jlc3MnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBjdCA9IDAsIHRvdGFsID0gZXZlbnQudG90YWwsIHBvc2l0aW9uID0gZXZlbnQubG9hZGVkIHx8IGV2ZW50LnBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBldmVudC5sZW5ndGhDb21wdXRhYmxlICovXG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5sZW5ndGhDb21wdXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwY3QgPSBNYXRoLmZsb29yKHBvc2l0aW9uIC8gdG90YWwgKiAxMDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldEFzeW5jVXBsb2FkU3RhdHVzKHByZXZpZXdJZCwgcGN0LCBmaWxlQ291bnQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MocGN0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB4aHJvYmo7XG4gICAgICAgIH0sXG4gICAgICAgIF9hamF4U3VibWl0OiBmdW5jdGlvbiAoZm5CZWZvcmUsIGZuU3VjY2VzcywgZm5Db21wbGV0ZSwgZm5FcnJvciwgcHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBzZXR0aW5ncztcbiAgICAgICAgICAgIGlmICghc2VsZi5fcmFpc2UoJ2ZpbGVwcmVhamF4JywgW3ByZXZpZXdJZCwgaW5kZXhdKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3VwbG9hZEV4dHJhKHByZXZpZXdJZCwgaW5kZXgpO1xuICAgICAgICAgICAgc2V0dGluZ3MgPSAkLmV4dGVuZCh0cnVlLCB7fSwge1xuICAgICAgICAgICAgICAgIHhocjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgeGhyb2JqID0gJC5hamF4U2V0dGluZ3MueGhyKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLl9pbml0WGhyKHhocm9iaiwgcHJldmlld0lkLCBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB1cmw6IHNlbGYudXBsb2FkVXJsLFxuICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgIGRhdGE6IHNlbGYuZm9ybWRhdGEsXG4gICAgICAgICAgICAgICAgY2FjaGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHByb2Nlc3NEYXRhOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBjb250ZW50VHlwZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgYmVmb3JlU2VuZDogZm5CZWZvcmUsXG4gICAgICAgICAgICAgICAgc3VjY2VzczogZm5TdWNjZXNzLFxuICAgICAgICAgICAgICAgIGNvbXBsZXRlOiBmbkNvbXBsZXRlLFxuICAgICAgICAgICAgICAgIGVycm9yOiBmbkVycm9yXG4gICAgICAgICAgICB9LCBzZWxmLmFqYXhTZXR0aW5ncyk7XG4gICAgICAgICAgICBzZWxmLmFqYXhSZXF1ZXN0cy5wdXNoKCQuYWpheChzZXR0aW5ncykpO1xuICAgICAgICB9LFxuICAgICAgICBfbWVyZ2VBcnJheTogZnVuY3Rpb24gKHByb3AsIGNvbnRlbnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgYXJyMSA9ICRoLmNsZWFuQXJyYXkoc2VsZltwcm9wXSksIGFycjIgPSAkaC5jbGVhbkFycmF5KGNvbnRlbnQpO1xuICAgICAgICAgICAgc2VsZltwcm9wXSA9IGFycjEuY29uY2F0KGFycjIpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFVwbG9hZFN1Y2Nlc3M6IGZ1bmN0aW9uIChvdXQsICR0aHVtYiwgYWxsRmlsZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgYXBwZW5kLCBkYXRhLCBpbmRleCwgJGRpdiwgJG5ld0NhY2hlLCBjb250ZW50LCBjb25maWcsIHRhZ3MsIGk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcgfHwgdHlwZW9mIG91dCAhPT0gJ29iamVjdCcgfHwgJC5pc0VtcHR5T2JqZWN0KG91dCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3V0LmluaXRpYWxQcmV2aWV3ICE9PSB1bmRlZmluZWQgJiYgb3V0LmluaXRpYWxQcmV2aWV3Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzZWxmLmhhc0luaXREYXRhID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gb3V0LmluaXRpYWxQcmV2aWV3IHx8IFtdO1xuICAgICAgICAgICAgICAgIGNvbmZpZyA9IG91dC5pbml0aWFsUHJldmlld0NvbmZpZyB8fCBbXTtcbiAgICAgICAgICAgICAgICB0YWdzID0gb3V0LmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzIHx8IFtdO1xuICAgICAgICAgICAgICAgIGFwcGVuZCA9IG91dC5hcHBlbmQgPT09IHVuZGVmaW5lZCB8fCBvdXQuYXBwZW5kID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmIChjb250ZW50Lmxlbmd0aCA+IDAgJiYgISRoLmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3BsaXQoc2VsZi5pbml0aWFsUHJldmlld0RlbGltaXRlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX21lcmdlQXJyYXkoJ2luaXRpYWxQcmV2aWV3JywgY29udGVudCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fbWVyZ2VBcnJheSgnaW5pdGlhbFByZXZpZXdDb25maWcnLCBjb25maWcpO1xuICAgICAgICAgICAgICAgIHNlbGYuX21lcmdlQXJyYXkoJ2luaXRpYWxQcmV2aWV3VGh1bWJUYWdzJywgdGFncyk7XG4gICAgICAgICAgICAgICAgaWYgKCR0aHVtYiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gc2VsZi5wcmV2aWV3Q2FjaGUuYWRkKGNvbnRlbnQsIGNvbmZpZ1swXSwgdGFnc1swXSwgYXBwZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBzZWxmLnByZXZpZXdDYWNoZS5nZXQoaW5kZXgsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRkaXYgPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKS5odG1sKGRhdGEpLmhpZGUoKS5pbnNlcnRBZnRlcigkdGh1bWIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJG5ld0NhY2hlID0gJGRpdi5maW5kKCcua3Ytem9vbS1jYWNoZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRuZXdDYWNoZSAmJiAkbmV3Q2FjaGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJG5ld0NhY2hlLmluc2VydEFmdGVyKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIuZmFkZU91dCgnc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJG5ld1RodW1iID0gJGRpdi5maW5kKCcuZmlsZS1wcmV2aWV3LWZyYW1lJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRuZXdUaHVtYiAmJiAkbmV3VGh1bWIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuZXdUaHVtYi5pbnNlcnRCZWZvcmUoJHRodW1iKS5mYWRlSW4oJ3Nsb3cnKS5jc3MoJ2Rpc3BsYXk6aW5saW5lLWJsb2NrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3QWN0aW9ucygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguY2xlYW5ab29tQ2FjaGUoc2VsZi4kcHJldmlldy5maW5kKCcjem9vbS0nICsgJHRodW1iLmF0dHIoJ2lkJykpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRpdi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaSA9ICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS5jb250ZW50W2ldID0gY29udGVudFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuY29uZmlnW2ldID0gY29uZmlnWzBdIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS50YWdzW2ldID0gdGFnc1swXSB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuYXBwZW5kID0gYXBwZW5kO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuc2V0KGNvbnRlbnQsIGNvbmZpZywgdGFncywgYXBwZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaW5pdFN1Y2Nlc3NUaHVtYnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygkaC5GUkFNRVMgKyAnLmZpbGUtcHJldmlldy1zdWNjZXNzJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldywgJHJlbW92ZSA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS1yZW1vdmUnKTtcbiAgICAgICAgICAgICAgICAkcmVtb3ZlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkcmVtb3ZlLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpZCA9ICR0aHVtYi5hdHRyKCdpZCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5fcmFpc2UoJ2ZpbGVzdWNjZXNzcmVtb3ZlJywgW2lkLCAkdGh1bWIuYXR0cignZGF0YS1maWxlaW5kZXgnKV0pO1xuICAgICAgICAgICAgICAgICAgICAkaC5jbGVhbk1lbW9yeSgkdGh1bWIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3V0ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5mYWRlT3V0KCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguY2xlYW5ab29tQ2FjaGUoJHByZXZpZXcuZmluZCgnI3pvb20tJyArIGlkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuZ2V0RnJhbWVzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfY2hlY2tBc3luY0NvbXBsZXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHByZXZpZXdJZCwgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWxmLmZpbGVzdGFjay5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLmZpbGVzdGFja1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aWV3SWQgPSBzZWxmLnByZXZpZXdJbml0SWQgKyBcIi1cIiArIGk7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkLmluQXJyYXkocHJldmlld0lkLCBzZWxmLnVwbG9hZExvZykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKHNlbGYudXBsb2FkQXN5bmNDb3VudCA9PT0gc2VsZi51cGxvYWRMb2cubGVuZ3RoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwbG9hZEV4dHJhOiBmdW5jdGlvbiAocHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhID0gc2VsZi5fZ2V0RXh0cmFEYXRhKHByZXZpZXdJZCwgaW5kZXgpO1xuICAgICAgICAgICAgaWYgKGRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJC5lYWNoKGRhdGEsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5mb3JtZGF0YS5hcHBlbmQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwbG9hZFNpbmdsZTogZnVuY3Rpb24gKGksIGZpbGVzLCBhbGxGaWxlcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0b3RhbCA9IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoLCBmb3JtZGF0YSA9IG5ldyBGb3JtRGF0YSgpLCBvdXREYXRhLFxuICAgICAgICAgICAgICAgIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArIFwiLVwiICsgaSwgJHRodW1iLCBjaGtDb21wbGV0ZSwgJGJ0blVwbG9hZCwgJGJ0bkRlbGV0ZSxcbiAgICAgICAgICAgICAgICBoYXNQb3N0RGF0YSA9IHNlbGYuZmlsZXN0YWNrLmxlbmd0aCA+IDAgfHwgISQuaXNFbXB0eU9iamVjdChzZWxmLnVwbG9hZEV4dHJhRGF0YSksXG4gICAgICAgICAgICAgICAgJHByb2cgPSAkKCcjJyArIHByZXZpZXdJZCkuZmluZCgnLmZpbGUtdGh1bWItcHJvZ3Jlc3MnKSxcbiAgICAgICAgICAgICAgICBmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yLCB1cGRhdGVVcGxvYWRMb2csIHBhcmFtcyA9IHtpZDogcHJldmlld0lkLCBpbmRleDogaX0sXG4gICAgICAgICAgICAgICAgdXBsb2FkRmFpbGVkLCBtdWx0aVVwbG9hZE1vZGUgPSAhJGguaXNFbXB0eShzZWxmLiRlbGVtZW50LmF0dHIoJ211bHRpcGxlJykpO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IGZvcm1kYXRhO1xuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAkdGh1bWIgPSAkKCcjJyArIHByZXZpZXdJZCArICc6bm90KC5maWxlLXByZXZpZXctaW5pdGlhbCknKTtcbiAgICAgICAgICAgICAgICAkYnRuVXBsb2FkID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpO1xuICAgICAgICAgICAgICAgICRidG5EZWxldGUgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJyk7XG4gICAgICAgICAgICAgICAgJHByb2cucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3RhbCA9PT0gMCB8fCAhaGFzUG9zdERhdGEgfHwgKCRidG5VcGxvYWQgJiYgJGJ0blVwbG9hZC5oYXNDbGFzcygnZGlzYWJsZWQnKSkgfHwgc2VsZi5fYWJvcnQocGFyYW1zKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHVwZGF0ZVVwbG9hZExvZyA9IGZ1bmN0aW9uIChpLCBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICBpZiAobXVsdGlVcGxvYWRNb2RlIHx8ICF1cGxvYWRGYWlsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGRhdGVTdGFjayhpLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZExvZy5wdXNoKHByZXZpZXdJZCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2NoZWNrQXN5bmNDb21wbGV0ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZmlsZUJhdGNoQ29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY2hrQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHUgPSBzZWxmLnVwbG9hZENhY2hlLCAkaW5pdFRodW1icywgaSwgaiwgbGVuID0gMCwgZGF0YSA9IHNlbGYuY2FjaGVJbml0aWFsUHJldmlldztcbiAgICAgICAgICAgICAgICBpZiAoIXNlbGYuZmlsZUJhdGNoQ29tcGxldGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5jb250ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGxlbiA9IGRhdGEuY29udGVudC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJpZ2dlclJlc2V0ID0gbXVsdGlVcGxvYWRNb2RlIHx8ICF1cGxvYWRGYWlsZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5zZXQodS5jb250ZW50LCB1LmNvbmZpZywgdS50YWdzLCB1LmFwcGVuZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHUuY29udGVudC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqID0gaSArIGxlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb250ZW50W2pdID0gdS5jb250ZW50W2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5jb25maWcubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZ1tqXSA9IHUuY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnRhZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3Nbal0gPSB1LnRhZ3NbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9ICRoLmNsZWFuQXJyYXkoZGF0YS5jb250ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnID0gJGguY2xlYW5BcnJheShkYXRhLmNvbmZpZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFncyA9ICRoLmNsZWFuQXJyYXkoZGF0YS50YWdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9IHUuY29udGVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnID0gdS5jb25maWc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFncyA9IHUudGFncztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY2FjaGVJbml0aWFsUHJldmlldyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaGFzSW5pdERhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlldygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3QWN0aW9ucygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudW5sb2NrKHRyaWdnZXJSZXNldCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0cmlnZ2VyUmVzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJGluaXRUaHVtYnMgPSBzZWxmLiRwcmV2aWV3LmZpbmQoJy5maWxlLXByZXZpZXctaW5pdGlhbCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi51cGxvYWRBc3luYyAmJiAkaW5pdFRodW1icy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkaW5pdFRodW1icywgJGguU09SVF9DU1MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHVwbG9hZGNvbXBsZXRlJywgW3NlbGYuZmlsZXN0YWNrLCBzZWxmLl9nZXRFeHRyYURhdGEoKV0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRTdGF0dXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRMb2cgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxKTtcbiAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuQmVmb3JlID0gZnVuY3Rpb24gKGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpO1xuICAgICAgICAgICAgICAgIHNlbGYuZmlsZUJhdGNoQ29tcGxldGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdGh1bWIuaGFzQ2xhc3MoJ2ZpbGUtcHJldmlldy1zdWNjZXNzJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFRodW1iU3RhdHVzKCR0aHVtYiwgJ0xvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkdGh1bWIsICdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYubG9jaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXByZXVwbG9hZCcsIFtvdXREYXRhLCBwcmV2aWV3SWQsIGldKTtcbiAgICAgICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBwYXJhbXMsIG91dERhdGEpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGpxWEhSLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzQ2FuY2VsbGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuU3VjY2VzcyA9IGZ1bmN0aW9uIChkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgIHZhciBwaWQgPSBzZWxmLnNob3dQcmV2aWV3ICYmICR0aHVtYi5hdHRyKCdpZCcpID8gJHRodW1iLmF0dHIoJ2lkJykgOiBwcmV2aWV3SWQ7XG4gICAgICAgICAgICAgICAgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIsIGRhdGEpO1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHBhcmFtcywgb3V0RGF0YSk7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KGRhdGEpIHx8ICRoLmlzRW1wdHkoZGF0YS5lcnJvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnU3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEsICR0aHVtYiwgYWxsRmlsZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSwgJHByb2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGV1cGxvYWRlZCcsIFtvdXREYXRhLCBwaWQsIGldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGksIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZVVwbG9hZExvZyhpLCBwaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBsb2FkRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihkYXRhLmVycm9yLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYiwgaSwgKG11bHRpVXBsb2FkTW9kZSA/IG51bGwgOiBzZWxmLmZpbGVzdGFja1tpXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nKGksIHBpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYnRuRGVsZXRlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlQ2xhc3MoJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51bmxvY2soZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoa0NvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFN1Y2Nlc3NUaHVtYnMoKTtcbiAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuRXJyb3IgPSBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9wID0gc2VsZi5hamF4T3BlcmF0aW9ucy51cGxvYWRUaHVtYixcbiAgICAgICAgICAgICAgICAgICAgZXJyTXNnID0gc2VsZi5fcGFyc2VFcnJvcihvcCwganFYSFIsIGVycm9yVGhyb3duLCAoYWxsRmlsZXMgPyBmaWxlc1tpXS5uYW1lIDogbnVsbCkpO1xuICAgICAgICAgICAgICAgIHVwbG9hZEZhaWxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nKGksIHByZXZpZXdJZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRTdGF0dXNbcHJldmlld0lkXSA9IDEwMDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYiwgaSwgKG11bHRpVXBsb2FkTW9kZSA/IG51bGwgOiBzZWxmLmZpbGVzdGFja1tpXSkpO1xuICAgICAgICAgICAgICAgICAgICAkLmV4dGVuZCh0cnVlLCBwYXJhbXMsIHNlbGYuX2dldE91dERhdGEoanFYSFIpKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxLCAkcHJvZywgc2VsZi5tc2dBamF4UHJvZ3Jlc3NFcnJvci5yZXBsYWNlKCd7b3BlcmF0aW9ufScsIG9wKSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihlcnJNc2csIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfSwgMTAwKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmb3JtZGF0YS5hcHBlbmQoc2VsZi51cGxvYWRGaWxlQXR0ciwgZmlsZXNbaV0sIHNlbGYuZmlsZW5hbWVzW2ldKTtcbiAgICAgICAgICAgIGZvcm1kYXRhLmFwcGVuZCgnZmlsZV9pZCcsIGkpO1xuICAgICAgICAgICAgc2VsZi5fYWpheFN1Ym1pdChmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yLCBwcmV2aWV3SWQsIGkpO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkQmF0Y2g6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZmlsZXMgPSBzZWxmLmZpbGVzdGFjaywgdG90YWwgPSBmaWxlcy5sZW5ndGgsIHBhcmFtcyA9IHt9LCBmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkVycm9yLFxuICAgICAgICAgICAgICAgIGZuQ29tcGxldGUsIGhhc1Bvc3REYXRhID0gc2VsZi5maWxlc3RhY2subGVuZ3RoID4gMCB8fCAhJC5pc0VtcHR5T2JqZWN0KHNlbGYudXBsb2FkRXh0cmFEYXRhKSxcbiAgICAgICAgICAgICAgICBzZXRBbGxVcGxvYWRlZDtcbiAgICAgICAgICAgIHNlbGYuZm9ybWRhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgIGlmICh0b3RhbCA9PT0gMCB8fCAhaGFzUG9zdERhdGEgfHwgc2VsZi5fYWJvcnQocGFyYW1zKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldEFsbFVwbG9hZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICQuZWFjaChmaWxlcywgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGtleSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuQmVmb3JlID0gZnVuY3Rpb24gKGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5sb2NrKCk7XG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCAkYnRuVXBsb2FkID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5EZWxldGUgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISR0aHVtYi5oYXNDbGFzcygnZmlsZS1wcmV2aWV3LXN1Y2Nlc3MnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFRodW1iU3RhdHVzKCR0aHVtYiwgJ0xvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJHRodW1iLCAnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5EZWxldGUuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hwcmV1cGxvYWQnLCBbb3V0RGF0YV0pO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLl9hYm9ydChvdXREYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICBqcVhIUi5hYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzc0NhbmNlbGxlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmblN1Y2Nlc3MgPSBmdW5jdGlvbiAoZGF0YSwgdGV4dFN0YXR1cywganFYSFIpIHtcbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkYXRhLmVycm9ya2V5cyAqL1xuICAgICAgICAgICAgICAgIHZhciBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUiwgZGF0YSksICR0aHVtYnMgPSBzZWxmLl9nZXRUaHVtYnMoJzpub3QoLmZpbGUtcHJldmlldy1lcnJvciknKSxcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gMCxcbiAgICAgICAgICAgICAgICAgICAga2V5cyA9ICRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9ya2V5cykgPyBbXSA6IGRhdGEuZXJyb3JrZXlzO1xuICAgICAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KGRhdGEpIHx8ICRoLmlzRW1wdHkoZGF0YS5lcnJvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHVwbG9hZHN1Y2Nlc3MnLCBbb3V0RGF0YV0pO1xuICAgICAgICAgICAgICAgICAgICBzZXRBbGxVcGxvYWRlZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRodW1icy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwgJGJ0blVwbG9hZCA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFRodW1iU3RhdHVzKCR0aHVtYiwgJ1N1Y2Nlc3MnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlQ2xhc3MoJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0VXBsb2FkU3VjY2VzcyhkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWJzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCAkYnRuRGVsZXRlID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXJlbW92ZScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuVXBsb2FkID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZXlzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJC5pbkFycmF5KGtleSwga2V5cykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFRodW1iU3RhdHVzKCR0aHVtYiwgJ1N1Y2Nlc3MnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGRhdGVTdGFjayhrZXksIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0VXBsb2FkU3VjY2VzcyhkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3IoZGF0YS5lcnJvciwgb3V0RGF0YSwgJ2ZpbGViYXRjaHVwbG9hZGVycm9yJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi51bmxvY2soKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9pbml0U3VjY2Vzc1RodW1icygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHVwbG9hZGNvbXBsZXRlJywgW3NlbGYuZmlsZXN0YWNrLCBzZWxmLl9nZXRFeHRyYURhdGEoKV0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuRXJyb3IgPSBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSKSwgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLnVwbG9hZEJhdGNoLFxuICAgICAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihlcnJNc2csIG91dERhdGEsICdmaWxlYmF0Y2h1cGxvYWRlcnJvcicpO1xuICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkRmlsZUNvdW50ID0gdG90YWwgLSAxO1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwga2V5ID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4Jyk7XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoJyAua3YtZmlsZS11cGxvYWQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygnIC5rdi1maWxlLWRlbGV0ZScpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxLCBzZWxmLiRwcm9ncmVzcywgc2VsZi5tc2dBamF4UHJvZ3Jlc3NFcnJvci5yZXBsYWNlKCd7b3BlcmF0aW9ufScsIG9wKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoa2V5LCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KGZpbGVzW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZm9ybWRhdGEuYXBwZW5kKHNlbGYudXBsb2FkRmlsZUF0dHIsIGRhdGEsIHNlbGYuZmlsZW5hbWVzW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5fYWpheFN1Ym1pdChmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwbG9hZEV4dHJhT25seTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBwYXJhbXMgPSB7fSwgZm5CZWZvcmUsIGZuU3VjY2VzcywgZm5Db21wbGV0ZSwgZm5FcnJvcjtcbiAgICAgICAgICAgIHNlbGYuZm9ybWRhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgIGlmIChzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm5CZWZvcmUgPSBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmxvY2soKTtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hwcmV1cGxvYWQnLCBbb3V0RGF0YV0pO1xuICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDUwKTtcbiAgICAgICAgICAgICAgICBwYXJhbXMuZGF0YSA9IG91dERhdGE7XG4gICAgICAgICAgICAgICAgcGFyYW1zLnhociA9IGpxWEhSO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGpxWEhSLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzQ2FuY2VsbGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuU3VjY2VzcyA9IGZ1bmN0aW9uIChkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgIHZhciBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUiwgZGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2Fkc3VjY2VzcycsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihkYXRhLmVycm9yLCBvdXREYXRhLCAnZmlsZWJhdGNodXBsb2FkZXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVubG9jaygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHVwbG9hZGNvbXBsZXRlJywgW3NlbGYuZmlsZXN0YWNrLCBzZWxmLl9nZXRFeHRyYURhdGEoKV0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuRXJyb3IgPSBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSKSwgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLnVwbG9hZEV4dHJhLFxuICAgICAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgICAgIHBhcmFtcy5kYXRhID0gb3V0RGF0YTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3IoZXJyTXNnLCBvdXREYXRhLCAnZmlsZWJhdGNodXBsb2FkZXJyb3InKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0FqYXhQcm9ncmVzc0Vycm9yLnJlcGxhY2UoJ3tvcGVyYXRpb259Jywgb3ApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBzZWxmLl9hamF4U3VibWl0KGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IpO1xuICAgICAgICB9LFxuICAgICAgICBfZGVsZXRlRmlsZUluZGV4OiBmdW5jdGlvbiAoJGZyYW1lKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGluZCA9ICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgaWYgKGluZC5zdWJzdHJpbmcoMCwgNSkgPT09ICdpbml0XycpIHtcbiAgICAgICAgICAgICAgICBpbmQgPSBwYXJzZUludChpbmQucmVwbGFjZSgnaW5pdF8nLCAnJykpO1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSAkaC5zcGxpY2VBcnJheShzZWxmLmluaXRpYWxQcmV2aWV3LCBpbmQpO1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSAkaC5zcGxpY2VBcnJheShzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnLCBpbmQpO1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MgPSAkaC5zcGxpY2VBcnJheShzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzLCBpbmQpO1xuICAgICAgICAgICAgICAgIHNlbGYuZ2V0RnJhbWVzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkbkZyYW1lID0gJCh0aGlzKSwgbkluZCA9ICRuRnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5JbmQuc3Vic3RyaW5nKDAsIDUpID09PSAnaW5pdF8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuSW5kID0gcGFyc2VJbnQobkluZC5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobkluZCA+IGluZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5JbmQtLTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbkZyYW1lLmF0dHIoJ2RhdGEtZmlsZWluZGV4JywgJ2luaXRfJyArIG5JbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYudXBsb2FkQXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0gc2VsZi5nZXRQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaW5pdEZpbGVBY3Rpb25zOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldztcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9uKCk7XG4gICAgICAgICAgICBzZWxmLmdldEZyYW1lcygnIC5rdi1maWxlLXJlbW92ZScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkZWwgPSAkKHRoaXMpLCAkZnJhbWUgPSAkZWwuY2xvc2VzdCgkaC5GUkFNRVMpLCBoYXNFcnJvciwgaWQgPSAkZnJhbWUuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAgICAgaW5kID0gJGZyYW1lLmF0dHIoJ2RhdGEtZmlsZWluZGV4JyksIG4sIGNhcCwgc3RhdHVzO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXR1cyA9IHNlbGYuX3JhaXNlKCdmaWxlcHJlcmVtb3ZlJywgW2lkLCBpbmRdKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gZmFsc2UgfHwgIXNlbGYuX3ZhbGlkYXRlTWluQ291bnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGhhc0Vycm9yID0gJGZyYW1lLmhhc0NsYXNzKCdmaWxlLXByZXZpZXctZXJyb3InKTtcbiAgICAgICAgICAgICAgICAgICAgJGguY2xlYW5NZW1vcnkoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgJGZyYW1lLmZhZGVPdXQoJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZSgkcHJldmlldy5maW5kKCcjem9vbS0nICsgaWQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soaW5kLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJPYmplY3RzKCRmcmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaWQgJiYgaGFzRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLiRlcnJvckNvbnRhaW5lci5maW5kKCdsaVtkYXRhLWZpbGUtaWQ9XCInICsgaWQgKyAnXCJdJykuZmFkZU91dCgnZmFzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLl9lcnJvcnNFeGlzdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGVzdGFjayA9IHNlbGYuZ2V0RmlsZVN0YWNrKHRydWUpLCBjaGsgPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbiA9IGZpbGVzdGFjay5sZW5ndGgsIGhhc1RodW1iID0gc2VsZi5zaG93UHJldmlldyAmJiBzZWxmLmdldEZyYW1lcygpLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZW4gPT09IDAgJiYgY2hrID09PSAwICYmICFoYXNUaHVtYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbiA9IGNoayArIGxlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXAgPSBuID4gMSA/IHNlbGYuX2dldE1zZ1NlbGVjdGVkKG4pIDogKGZpbGVzdGFja1swXSA/IHNlbGYuX2dldEZpbGVOYW1lcygpWzBdIDogJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oY2FwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlcmVtb3ZlZCcsIFtpZCwgaW5kXSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLmdldEZyYW1lcygnIC5rdi1maWxlLXVwbG9hZCcpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkZWwgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkZnJhbWUgPSAkZWwuY2xvc2VzdCgkaC5GUkFNRVMpLCBpbmQgPSAkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkZnJhbWUuaGFzQ2xhc3MoJ2ZpbGUtcHJldmlldy1lcnJvcicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGxvYWRTaW5nbGUoaW5kLCBzZWxmLmZpbGVzdGFjaywgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRQcmV2aWV3QWN0aW9uczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkcHJldmlldyA9IHNlbGYuJHByZXZpZXcsIGRlbGV0ZUV4dHJhRGF0YSA9IHNlbGYuZGVsZXRlRXh0cmFEYXRhIHx8IHt9LFxuICAgICAgICAgICAgICAgIGJ0blJlbW92ZSA9ICRoLkZSQU1FUyArICcgLmt2LWZpbGUtcmVtb3ZlJyxcbiAgICAgICAgICAgICAgICByZXNldFByb2dyZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaGFzRmlsZXMgPSBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCkgOiBzZWxmLiRlbGVtZW50LmdldCgwKS5maWxlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkcHJldmlldy5maW5kKGJ0blJlbW92ZSkubGVuZ3RoID09PSAwICYmICFoYXNGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsQ2FwdGlvbiA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9uKCk7XG4gICAgICAgICAgICAkcHJldmlldy5maW5kKGJ0blJlbW92ZSkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlbCA9ICQodGhpcyksIHZVcmwgPSAkZWwuZGF0YSgndXJsJykgfHwgc2VsZi5kZWxldGVVcmwsIHZLZXkgPSAkZWwuZGF0YSgna2V5Jyk7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkodlVybCkgfHwgdktleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyICRmcmFtZSA9ICRlbC5jbG9zZXN0KCRoLkZSQU1FUyksIGNhY2hlID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MsIHBhcmFtcywgaW5kZXggPSAkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKSwgY29uZmlnLCBleHRyYURhdGE7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBwYXJzZUludChpbmRleC5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgY29uZmlnID0gJGguaXNFbXB0eShjYWNoZS5jb25maWcpICYmICRoLmlzRW1wdHkoY2FjaGUuY29uZmlnW2luZGV4XSkgPyBudWxsIDogY2FjaGUuY29uZmlnW2luZGV4XTtcbiAgICAgICAgICAgICAgICBleHRyYURhdGEgPSAkaC5pc0VtcHR5KGNvbmZpZykgfHwgJGguaXNFbXB0eShjb25maWcuZXh0cmEpID8gZGVsZXRlRXh0cmFEYXRhIDogY29uZmlnLmV4dHJhO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZXh0cmFEYXRhID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZXh0cmFEYXRhID0gZXh0cmFEYXRhKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtpZDogJGVsLmF0dHIoJ2lkJyksIGtleTogdktleSwgZXh0cmE6IGV4dHJhRGF0YX07XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSAkLmV4dGVuZCh0cnVlLCB7fSwge1xuICAgICAgICAgICAgICAgICAgICB1cmw6IHZVcmwsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogJC5leHRlbmQodHJ1ZSwge30sIHtrZXk6IHZLZXl9LCBleHRyYURhdGEpLFxuICAgICAgICAgICAgICAgICAgICBiZWZvcmVTZW5kOiBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlcHJlZGVsZXRlJywgW3ZLZXksIGpxWEhSLCBleHRyYURhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmFqYXhBYm9ydGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganFYSFIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRmcmFtZSwgJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRlbCwgJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG4sIGNhcDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KGRhdGEpIHx8ICRoLmlzRW1wdHkoZGF0YS5lcnJvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IHBhcnNlSW50KCgkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKSkucmVwbGFjZSgnaW5pdF8nLCAnJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLnVuc2V0KGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXAgPSBuID4gMCA/IHNlbGYuX2dldE1zZ1NlbGVjdGVkKG4pIDogJyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fZGVsZXRlRmlsZUluZGV4KCRmcmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlZGVsZXRlZCcsIFt2S2V5LCBqcVhIUiwgZXh0cmFEYXRhXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy5qcVhIUiA9IGpxWEhSO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy5yZXNwb25zZSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd0Vycm9yKGRhdGEuZXJyb3IsIHBhcmFtcywgJ2ZpbGVkZWxldGVlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZWwucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRQcm9ncmVzcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKS5hZGRDbGFzcygnZmlsZS1kZWxldGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUuZmFkZU91dCgnc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZSgkcHJldmlldy5maW5kKCcjem9vbS0nICsgJGZyYW1lLmF0dHIoJ2lkJykpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhck9iamVjdHMoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRQcm9ncmVzcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbiAmJiBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24gKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9wID0gc2VsZi5hamF4T3BlcmF0aW9ucy5kZWxldGVUaHVtYiwgZXJyTXNnID0gc2VsZi5fcGFyc2VFcnJvcihvcCwganFYSFIsIGVycm9yVGhyb3duKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy5qcVhIUiA9IGpxWEhSO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnJlc3BvbnNlID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zaG93RXJyb3IoZXJyTXNnLCBwYXJhbXMsICdmaWxlZGVsZXRlZXJyb3InKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0UHJvZ3Jlc3MoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIHNlbGYuYWpheERlbGV0ZVNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlbCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuX3ZhbGlkYXRlTWluQ291bnQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICQuYWpheChzZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2hpZGVGaWxlSWNvbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMub3ZlcndyaXRlSW5pdGlhbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmt2LWNhcHRpb24taWNvbicpLmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3Nob3dGaWxlSWNvbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy4kY2FwdGlvbkNvbnRhaW5lci5maW5kKCcua3YtY2FwdGlvbi1pY29uJykuc2hvdygpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0U2l6ZTogZnVuY3Rpb24gKGJ5dGVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHNpemUgPSBwYXJzZUZsb2F0KGJ5dGVzKSwgaSwgZnVuYyA9IHNlbGYuZmlsZVNpemVHZXR0ZXIsIHNpemVzLCBvdXQ7XG4gICAgICAgICAgICBpZiAoISQuaXNOdW1lcmljKGJ5dGVzKSB8fCAhJC5pc051bWVyaWMoc2l6ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBvdXQgPSBmdW5jKHNpemUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoc2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSAnMC4wMCBCJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpID0gTWF0aC5mbG9vcihNYXRoLmxvZyhzaXplKSAvIE1hdGgubG9nKDEwMjQpKTtcbiAgICAgICAgICAgICAgICAgICAgc2l6ZXMgPSBbJ0InLCAnS0InLCAnTUInLCAnR0InLCAnVEInLCAnUEInLCAnRUInLCAnWkInLCAnWUInXTtcbiAgICAgICAgICAgICAgICAgICAgb3V0ID0gKHNpemUgLyBNYXRoLnBvdygxMDI0LCBpKSkudG9GaXhlZCgyKSAqIDEgKyAnICcgKyBzaXplc1tpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ3NpemUnKS5yZXBsYWNlKCd7c2l6ZVRleHR9Jywgb3V0KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dlbmVyYXRlUHJldmlld1RlbXBsYXRlOiBmdW5jdGlvbiAoY2F0LCBkYXRhLCBmbmFtZSwgZnR5cGUsIHByZXZpZXdJZCwgaXNFcnJvciwgc2l6ZSwgZnJhbWVDbGFzcywgZm9vdCwgaW5kLCB0ZW1wbCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBjYXB0aW9uID0gc2VsZi5zbHVnKGZuYW1lKSwgcHJldkNvbnRlbnQsIHpvb21Db250ZW50ID0gJycsXG4gICAgICAgICAgICAgICAgY29uZmlnID0gc2VsZi5wcmV2aWV3U2V0dGluZ3NbY2F0XSB8fCBzZWxmLmRlZmF1bHRzLnByZXZpZXdTZXR0aW5nc1tjYXRdLFxuICAgICAgICAgICAgICAgIHcgPSBjb25maWcgJiYgY29uZmlnLndpZHRoID8gY29uZmlnLndpZHRoIDogJycsIGggPSBjb25maWcgJiYgY29uZmlnLmhlaWdodCA/IGNvbmZpZy5oZWlnaHQgOiAnJyxcbiAgICAgICAgICAgICAgICBmb290ZXIgPSBmb290IHx8IHNlbGYuX3JlbmRlckZpbGVGb290ZXIoY2FwdGlvbiwgc2l6ZSwgKCRoLmlzRW1wdHkodykgPyAnYXV0bycgOiB3KSwgaXNFcnJvciksXG4gICAgICAgICAgICAgICAgaGFzSWNvblNldHRpbmcgPSBzZWxmLl9nZXRQcmV2aWV3SWNvbihmbmFtZSksIHR5cGVDc3MgPSAndHlwZS1kZWZhdWx0JyxcbiAgICAgICAgICAgICAgICBmb3JjZVByZXZJY29uID0gaGFzSWNvblNldHRpbmcgJiYgc2VsZi5wcmVmZXJJY29uaWNQcmV2aWV3LFxuICAgICAgICAgICAgICAgIGZvcmNlWm9vbUljb24gPSBoYXNJY29uU2V0dGluZyAmJiBzZWxmLnByZWZlckljb25pY1pvb21QcmV2aWV3LFxuICAgICAgICAgICAgICAgIGdldENvbnRlbnQgPSBmdW5jdGlvbiAoYywgZCwgem9vbSwgZnJhbWVDc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkID0gem9vbSA/ICd6b29tLScgKyBwcmV2aWV3SWQgOiBwcmV2aWV3SWQsIHRtcGx0ID0gc2VsZi5fZ2V0UHJldmlld1RlbXBsYXRlKGMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3NzID0gKGZyYW1lQ2xhc3MgfHwgJycpICsgJyAnICsgZnJhbWVDc3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmZyYW1lQ2xhc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNzcyA9IHNlbGYuZnJhbWVDbGFzcyArICcgJyArIGNzcztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoem9vbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3NzID0gY3NzLnJlcGxhY2UoJyAnICsgJGguU09SVF9DU1MsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0bXBsdCA9IHNlbGYuX3BhcnNlRmlsZVByZXZpZXdJY29uKHRtcGx0LCBmbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjID09PSAndGV4dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGQgPSAkaC5odG1sRW5jb2RlKGQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYXQgPT09ICdvYmplY3QnICYmICFmdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJC5lYWNoKHNlbGYuZGVmYXVsdHMuZmlsZVR5cGVTZXR0aW5ncywgZnVuY3Rpb24gKGtleSwgZnVuYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZXkgPT09ICdvYmplY3QnIHx8IGtleSA9PT0gJ290aGVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmdW5jKGZuYW1lLCBmdHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZUNzcyA9ICd0eXBlLScgKyBrZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRtcGx0LnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAncHJldmlld0lkJzogaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAnZnJhbWVDbGFzcyc6IGNzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogZnR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZmlsZWluZGV4JzogaW5kLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogdyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdoZWlnaHQnOiBoLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGVDc3MnOiB0eXBlQ3NzLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2Zvb3Rlcic6IGZvb3RlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICdkYXRhJzogZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICd0ZW1wbGF0ZSc6IHRlbXBsIHx8IGNhdFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgaW5kID0gaW5kIHx8IHByZXZpZXdJZC5zbGljZShwcmV2aWV3SWQubGFzdEluZGV4T2YoJy0nKSArIDEpO1xuICAgICAgICAgICAgaWYgKHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLnNob3dab29tKSB7XG4gICAgICAgICAgICAgICAgem9vbUNvbnRlbnQgPSBnZXRDb250ZW50KChmb3JjZVpvb21JY29uID8gJ290aGVyJyA6IGNhdCksIGRhdGEsIHRydWUsICdrdi16b29tLXRodW1iJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB6b29tQ29udGVudCA9ICdcXG4nICsgc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ3pvb21DYWNoZScpLnJlcGxhY2UoJ3t6b29tQ29udGVudH0nLCB6b29tQ29udGVudCk7XG4gICAgICAgICAgICBwcmV2Q29udGVudCA9IGdldENvbnRlbnQoKGZvcmNlUHJldkljb24gPyAnb3RoZXInIDogY2F0KSwgZGF0YSwgZmFsc2UsICdrdi1wcmV2aWV3LXRodW1iJyk7XG4gICAgICAgICAgICByZXR1cm4gcHJldkNvbnRlbnQgKyB6b29tQ29udGVudDtcbiAgICAgICAgfSxcbiAgICAgICAgX3ByZXZpZXdEZWZhdWx0OiBmdW5jdGlvbiAoZmlsZSwgcHJldmlld0lkLCBpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldztcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBmbmFtZSA9IGZpbGUgPyBmaWxlLm5hbWUgOiAnJywgZnR5cGUgPSBmaWxlID8gZmlsZS50eXBlIDogJycsIGNvbnRlbnQsIHNpemUgPSBmaWxlLnNpemUgfHwgMCxcbiAgICAgICAgICAgICAgICBjYXB0aW9uID0gc2VsZi5zbHVnKGZuYW1lKSwgaXNFcnJvciA9IGlzRGlzYWJsZWQgPT09IHRydWUgJiYgIXNlbGYuaXNVcGxvYWRhYmxlLFxuICAgICAgICAgICAgICAgIGRhdGEgPSAkaC5vYmpVcmwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpO1xuICAgICAgICAgICAgc2VsZi5fY2xlYXJEZWZhdWx0UHJldmlldygpO1xuICAgICAgICAgICAgY29udGVudCA9IHNlbGYuX2dlbmVyYXRlUHJldmlld1RlbXBsYXRlKCdvdGhlcicsIGRhdGEsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBpc0Vycm9yLCBzaXplKTtcbiAgICAgICAgICAgICRwcmV2aWV3LmFwcGVuZChcIlxcblwiICsgY29udGVudCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRUaHVtYkF0dHIocHJldmlld0lkLCBjYXB0aW9uLCBzaXplKTtcbiAgICAgICAgICAgIGlmIChpc0Rpc2FibGVkID09PSB0cnVlICYmIHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJCgnIycgKyBwcmV2aWV3SWQpLCAnRXJyb3InKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3ByZXZpZXdGaWxlOiBmdW5jdGlvbiAoaSwgZmlsZSwgdGhlRmlsZSwgcHJldmlld0lkLCBkYXRhKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhdCA9IHNlbGYuX3BhcnNlRmlsZVR5cGUoZmlsZSksIGZuYW1lID0gZmlsZSA/IGZpbGUubmFtZSA6ICcnLCBjYXB0aW9uID0gc2VsZi5zbHVnKGZuYW1lKSxcbiAgICAgICAgICAgICAgICB0eXBlcyA9IHNlbGYuYWxsb3dlZFByZXZpZXdUeXBlcywgbWltZXMgPSBzZWxmLmFsbG93ZWRQcmV2aWV3TWltZVR5cGVzLCAkcHJldmlldyA9IHNlbGYuJHByZXZpZXcsXG4gICAgICAgICAgICAgICAgY2hrVHlwZXMgPSB0eXBlcyAmJiB0eXBlcy5pbmRleE9mKGNhdCkgPj0gMCwgZnNpemUgPSBmaWxlLnNpemUgfHwgMCwgZnR5cGUgPSBmaWxlLnR5cGUsXG4gICAgICAgICAgICAgICAgaURhdGEgPSAoY2F0ID09PSAndGV4dCcgfHwgY2F0ID09PSAnaHRtbCcgfHwgY2F0ID09PSAnaW1hZ2UnKSA/IHRoZUZpbGUudGFyZ2V0LnJlc3VsdCA6IGRhdGEsIGNvbnRlbnQsXG4gICAgICAgICAgICAgICAgY2hrTWltZXMgPSBtaW1lcyAmJiBtaW1lcy5pbmRleE9mKGZ0eXBlKSAhPT0gLTE7XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSB3aW5kb3cuRE9NUHVyaWZ5ICovXG4gICAgICAgICAgICBpZiAoY2F0ID09PSAnaHRtbCcgJiYgc2VsZi5wdXJpZnlIdG1sICYmIHdpbmRvdy5ET01QdXJpZnkpIHtcbiAgICAgICAgICAgICAgICBpRGF0YSA9IHdpbmRvdy5ET01QdXJpZnkuc2FuaXRpemUoaURhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNoa1R5cGVzIHx8IGNoa01pbWVzKSB7XG4gICAgICAgICAgICAgICAgY29udGVudCA9IHNlbGYuX2dlbmVyYXRlUHJldmlld1RlbXBsYXRlKGNhdCwgaURhdGEsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBmYWxzZSwgZnNpemUpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRGVmYXVsdFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICAkcHJldmlldy5hcHBlbmQoXCJcXG5cIiArIGNvbnRlbnQpO1xuICAgICAgICAgICAgICAgIHZhciAkaW1nID0gJHByZXZpZXcuZmluZCgnIycgKyBwcmV2aWV3SWQgKyAnIGltZycpO1xuICAgICAgICAgICAgICAgIGlmICgkaW1nLmxlbmd0aCAmJiBzZWxmLmF1dG9PcmllbnRJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICAkaC52YWxpZGF0ZU9yaWVudGF0aW9uKGZpbGUsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR6b29tSW1nID0gJHByZXZpZXcuZmluZCgnI3pvb20tJyArIHByZXZpZXdJZCArICcgaW1nJyksIGNzcyA9ICdyb3RhdGUtJyArIHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA+IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3NzICs9ICgkaW1nLndpZHRoKCkgPiAkaW1nLmhlaWdodCgpID8gJyBpcy1wb3J0cmFpdC1ndDQnIDogJyBpcy1sYW5kc2NhcGUtZ3Q0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkaW1nLCBjc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkem9vbUltZywgY3NzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlb3JpZW50ZWQnLCB7JyRpbWcnOiAkaW1nLCAnZmlsZSc6IGZpbGV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlSW1hZ2UocHJldmlld0lkLCBjYXB0aW9uLCBmdHlwZSwgZnNpemUsIGlEYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkanVzdE9yaWVudGVkSW1hZ2UoJGltZyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlSW1hZ2UocHJldmlld0lkLCBjYXB0aW9uLCBmdHlwZSwgZnNpemUsIGlEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdEZWZhdWx0KGZpbGUsIHByZXZpZXdJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRUaHVtYkF0dHIocHJldmlld0lkLCBjYXB0aW9uLCBmc2l6ZSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3NldFRodW1iQXR0cjogZnVuY3Rpb24gKGlkLCBjYXB0aW9uLCBzaXplKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRmcmFtZSA9ICQoJyMnICsgaWQpO1xuICAgICAgICAgICAgaWYgKCRmcmFtZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzaXplID0gc2l6ZSAmJiBzaXplID4gMCA/IHNlbGYuX2dldFNpemUoc2l6ZSkgOiAnJztcbiAgICAgICAgICAgICAgICAkZnJhbWUuZGF0YSh7J2NhcHRpb24nOiBjYXB0aW9uLCAnc2l6ZSc6IHNpemV9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3NldEluaXRUaHVtYkF0dHI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGxlbiA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KHRydWUpLCBjb25maWcsXG4gICAgICAgICAgICAgICAgY2FwdGlvbiwgc2l6ZSwgcHJldmlld0lkO1xuICAgICAgICAgICAgaWYgKGxlbiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25maWcgPSBkYXRhLmNvbmZpZ1tpXTtcbiAgICAgICAgICAgICAgICBwcmV2aWV3SWQgPSBzZWxmLnByZXZpZXdJbml0SWQgKyAnLScgKyAnaW5pdF8nICsgaTtcbiAgICAgICAgICAgICAgICBjYXB0aW9uID0gJGguaWZTZXQoJ2NhcHRpb24nLCBjb25maWcsICRoLmlmU2V0KCdmaWxlbmFtZScsIGNvbmZpZykpO1xuICAgICAgICAgICAgICAgIHNpemUgPSAkaC5pZlNldCgnc2l6ZScsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJBdHRyKHByZXZpZXdJZCwgY2FwdGlvbiwgc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9zbHVnRGVmYXVsdDogZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiAkaC5pc0VtcHR5KHRleHQpID8gJycgOiBTdHJpbmcodGV4dCkucmVwbGFjZSgvW1xcLVxcW1xcXVxcL1xce306OyMlPVxcKFxcKVxcKlxcK1xcP1xcXFxcXF5cXCRcXHw8PiZcIiddL2csICdfJyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZWFkRmlsZXM6IGZ1bmN0aW9uIChmaWxlcykge1xuICAgICAgICAgICAgdGhpcy5yZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50LCAkcHJldmlldyA9IHNlbGYuJHByZXZpZXcsIHJlYWRlciA9IHNlbGYucmVhZGVyLFxuICAgICAgICAgICAgICAgICRjb250YWluZXIgPSBzZWxmLiRwcmV2aWV3Q29udGFpbmVyLCAkc3RhdHVzID0gc2VsZi4kcHJldmlld1N0YXR1cywgbXNnTG9hZGluZyA9IHNlbGYubXNnTG9hZGluZyxcbiAgICAgICAgICAgICAgICBtc2dQcm9ncmVzcyA9IHNlbGYubXNnUHJvZ3Jlc3MsIHByZXZpZXdJbml0SWQgPSBzZWxmLnByZXZpZXdJbml0SWQsIG51bUZpbGVzID0gZmlsZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgIHNldHRpbmdzID0gc2VsZi5maWxlVHlwZVNldHRpbmdzLCBjdHIgPSBzZWxmLmZpbGVzdGFjay5sZW5ndGgsIHJlYWRGaWxlLFxuICAgICAgICAgICAgICAgIGZpbGVUeXBlcyA9IHNlbGYuYWxsb3dlZEZpbGVUeXBlcywgdHlwTGVuID0gZmlsZVR5cGVzID8gZmlsZVR5cGVzLmxlbmd0aCA6IDAsXG4gICAgICAgICAgICAgICAgZmlsZUV4dCA9IHNlbGYuYWxsb3dlZEZpbGVFeHRlbnNpb25zLCBzdHJFeHQgPSAkaC5pc0VtcHR5KGZpbGVFeHQpID8gJycgOiBmaWxlRXh0LmpvaW4oJywgJyksXG4gICAgICAgICAgICAgICAgbWF4UHJldmlld1NpemUgPSBzZWxmLm1heEZpbGVQcmV2aWV3U2l6ZSAmJiBwYXJzZUZsb2F0KHNlbGYubWF4RmlsZVByZXZpZXdTaXplKSxcbiAgICAgICAgICAgICAgICBjYW5QcmV2aWV3ID0gJHByZXZpZXcubGVuZ3RoICYmICghbWF4UHJldmlld1NpemUgfHwgaXNOYU4obWF4UHJldmlld1NpemUpKSxcbiAgICAgICAgICAgICAgICB0aHJvd0Vycm9yID0gZnVuY3Rpb24gKG1zZywgZmlsZSwgcHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcDEgPSAkLmV4dGVuZCh0cnVlLCB7fSwgc2VsZi5fZ2V0T3V0RGF0YSh7fSwge30sIGZpbGVzKSwge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpbmRleH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgcDIgPSB7aWQ6IHByZXZpZXdJZCwgaW5kZXg6IGluZGV4LCBmaWxlOiBmaWxlLCBmaWxlczogZmlsZXN9O1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9wcmV2aWV3RGVmYXVsdChmaWxlLCBwcmV2aWV3SWQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWRkVG9TdGFjayh1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdEZpbGVBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnJlbW92ZUZyb21QcmV2aWV3T25FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCgnIycgKyBwcmV2aWV3SWQpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYuX3Nob3dVcGxvYWRFcnJvcihtc2csIHAxKSA6IHNlbGYuX3Nob3dFcnJvcihtc2csIHAyKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBzZWxmLmxvYWRlZEltYWdlcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi50b3RhbEltYWdlc0NvdW50ID0gMDtcblxuICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoa2V5LCBmaWxlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBzZWxmLmZpbGVUeXBlU2V0dGluZ3MuaW1hZ2U7XG4gICAgICAgICAgICAgICAgaWYgKGZ1bmMgJiYgZnVuYyhmaWxlLnR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudG90YWxJbWFnZXNDb3VudCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVhZEZpbGUgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KCRlbC5hdHRyKCdtdWx0aXBsZScpKSkge1xuICAgICAgICAgICAgICAgICAgICBudW1GaWxlcyA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpID49IG51bUZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSAmJiBzZWxmLmZpbGVzdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNoc2VsZWN0ZWQnLCBbc2VsZi5nZXRGaWxlU3RhY2soKV0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHNlbGVjdGVkJywgW2ZpbGVzXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSBjdHIgKyBpLCBwcmV2aWV3SWQgPSBwcmV2aWV3SW5pdElkICsgXCItXCIgKyBub2RlLCBpc1RleHQsIGlzSW1hZ2UsIGZpbGUgPSBmaWxlc1tpXSwgZlNpemVLQixcbiAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9IGZpbGUubmFtZSA/IHNlbGYuc2x1ZyhmaWxlLm5hbWUpIDogJycsIGZpbGVTaXplID0gKGZpbGUuc2l6ZSB8fCAwKSAvIDEwMDAsIGosIG1zZyxcbiAgICAgICAgICAgICAgICAgICAgZmlsZUV4dEV4cHIgPSAnJywgcHJldmlld0RhdGEgPSAkaC5vYmpVcmwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpLCB0eXAsIGNoaywgdHlwMSwgdHlwMixcbiAgICAgICAgICAgICAgICAgICAgZmlsZUNvdW50ID0gMCwgc3RyVHlwZXMgPSAnJywgZnVuYztcbiAgICAgICAgICAgICAgICBpZiAodHlwTGVuID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgdHlwTGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cDEgPSBmaWxlVHlwZXNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXAyID0gc2VsZi5tc2dGaWxlVHlwZXNbdHlwMV0gfHwgdHlwMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0clR5cGVzICs9IGogPT09IDAgPyB0eXAyIDogJywgJyArIHR5cDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNhcHRpb24gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRGaWxlKGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2FwdGlvbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dJbnZhbGlkRmlsZU5hbWUucmVwbGFjZSgne25hbWV9JywgJGguaHRtbEVuY29kZShmaWxlLm5hbWUpKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIGZpbGUsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KGZpbGVFeHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVFeHRFeHByID0gbmV3IFJlZ0V4cCgnXFxcXC4oJyArIGZpbGVFeHQuam9pbignfCcpICsgJykkJywgJ2knKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZlNpemVLQiA9IGZpbGVTaXplLnRvRml4ZWQoMik7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYubWF4RmlsZVNpemUgPiAwICYmIGZpbGVTaXplID4gc2VsZi5tYXhGaWxlU2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ1NpemVUb29MYXJnZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBmU2l6ZUtCLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ21heFNpemUnOiBzZWxmLm1heEZpbGVTaXplXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5taW5GaWxlU2l6ZSAhPT0gbnVsbCAmJiBmaWxlU2l6ZSA8PSAkaC5nZXROdW0oc2VsZi5taW5GaWxlU2l6ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dTaXplVG9vU21hbGwuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICduYW1lJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICdzaXplJzogZlNpemVLQixcbiAgICAgICAgICAgICAgICAgICAgICAgICdtaW5TaXplJzogc2VsZi5taW5GaWxlU2l6ZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIGZpbGUsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KGZpbGVUeXBlcykgJiYgJGguaXNBcnJheShmaWxlVHlwZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBmaWxlVHlwZXMubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cCA9IGZpbGVUeXBlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmMgPSBzZXR0aW5nc1t0eXBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZUNvdW50ICs9ICFmdW5jIHx8ICh0eXBlb2YgZnVuYyAhPT0gJ2Z1bmN0aW9uJykgPyAwIDogKGZ1bmMoZmlsZS50eXBlLCBmaWxlLm5hbWUpID8gMSA6IDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnSW52YWxpZEZpbGVUeXBlLnNldFRva2Vucyh7J25hbWUnOiBjYXB0aW9uLCAndHlwZXMnOiBzdHJUeXBlc30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIGZpbGUsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpbGVDb3VudCA9PT0gMCAmJiAhJGguaXNFbXB0eShmaWxlRXh0KSAmJiAkaC5pc0FycmF5KGZpbGVFeHQpICYmICEkaC5pc0VtcHR5KGZpbGVFeHRFeHByKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGsgPSAkaC5jb21wYXJlKGNhcHRpb24sIGZpbGVFeHRFeHByKTtcbiAgICAgICAgICAgICAgICAgICAgZmlsZUNvdW50ICs9ICRoLmlzRW1wdHkoY2hrKSA/IDAgOiBjaGsubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmlsZUNvdW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ludmFsaWRGaWxlRXh0ZW5zaW9uLnNldFRva2Vucyh7J25hbWUnOiBjYXB0aW9uLCAnZXh0ZW5zaW9ucyc6IHN0ckV4dH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIGZpbGUsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRUb1N0YWNrKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMobnVtRmlsZXMpO1xuICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWxvYWRlZCcsIFtmaWxlLCBwcmV2aWV3SWQsIGksIHJlYWRlcl0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghY2FuUHJldmlldyAmJiBmaWxlU2l6ZSA+IG1heFByZXZpZXdTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuYWRkVG9TdGFjayhmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci5hZGRDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdEZWZhdWx0KGZpbGUsIHByZXZpZXdJZCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRGaWxlQWN0aW9ucygpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIHJlYWRGaWxlKGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoJHByZXZpZXcubGVuZ3RoICYmIEZpbGVSZWFkZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAkc3RhdHVzLmh0bWwobXNnTG9hZGluZy5yZXBsYWNlKCd7aW5kZXh9JywgaSArIDEpLnJlcGxhY2UoJ3tmaWxlc30nLCBudW1GaWxlcykpO1xuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLmFkZENsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLm9uZXJyb3IgPSBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9lcnJvckhhbmRsZXIoZXZ0LCBjYXB0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICh0aGVGaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9wcmV2aWV3RmlsZShpLCBmaWxlLCB0aGVGaWxlLCBwcmV2aWV3SWQsIHByZXZpZXdEYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRGaWxlQWN0aW9ucygpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICByZWFkZXIub25sb2FkZW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXNnID0gbXNnUHJvZ3Jlc3Muc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaW5kZXgnOiBpICsgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmlsZXMnOiBudW1GaWxlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAncGVyY2VudCc6IDUwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICduYW1lJzogY2FwdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc3RhdHVzLmh0bWwobXNnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlbG9hZGVkJywgW2ZpbGUsIHByZXZpZXdJZCwgaSwgcmVhZGVyXSk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5vbnByb2dyZXNzID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmxlbmd0aENvbXB1dGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmFjdCA9IChkYXRhLmxvYWRlZCAvIGRhdGEudG90YWwpICogMTAwLCBwcm9ncmVzcyA9IE1hdGguY2VpbChmYWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBtc2dQcm9ncmVzcy5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaW5kZXgnOiBpICsgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2ZpbGVzJzogbnVtRmlsZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdwZXJjZW50JzogcHJvZ3Jlc3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICduYW1lJzogY2FwdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc3RhdHVzLmh0bWwobXNnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBpc1RleHQgPSBzZXR0aW5ncy50ZXh0O1xuICAgICAgICAgICAgICAgICAgICBpc0ltYWdlID0gc2V0dGluZ3MuaW1hZ2U7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVGV4dChmaWxlLnR5cGUsIGNhcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIucmVhZEFzVGV4dChmaWxlLCBzZWxmLnRleHRFbmNvZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNJbWFnZShmaWxlLnR5cGUsIGNhcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdEZWZhdWx0KGZpbGUsIHByZXZpZXdJZCk7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMobnVtRmlsZXMpO1xuICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWxvYWRlZCcsIFtmaWxlLCBwcmV2aWV3SWQsIGksIHJlYWRlcl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmLmFkZFRvU3RhY2soZmlsZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZWFkRmlsZSgwKTtcbiAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKG51bUZpbGVzLCBmYWxzZSk7XG4gICAgICAgIH0sXG4gICAgICAgIF91cGRhdGVGaWxlRGV0YWlsczogZnVuY3Rpb24gKG51bUZpbGVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsIGZpbGVTdGFjayA9IHNlbGYuZ2V0RmlsZVN0YWNrKCksXG4gICAgICAgICAgICAgICAgbmFtZSA9ICgkaC5pc0lFKDkpICYmICRoLmZpbmRGaWxlTmFtZSgkZWwudmFsKCkpKSB8fFxuICAgICAgICAgICAgICAgICAgICAoJGVsWzBdLmZpbGVzWzBdICYmICRlbFswXS5maWxlc1swXS5uYW1lKSB8fCAoZmlsZVN0YWNrLmxlbmd0aCAmJiBmaWxlU3RhY2tbMF0ubmFtZSkgfHwgJycsXG4gICAgICAgICAgICAgICAgbGFiZWwgPSBzZWxmLnNsdWcobmFtZSksIG4gPSBzZWxmLmlzVXBsb2FkYWJsZSA/IGZpbGVTdGFjay5sZW5ndGggOiBudW1GaWxlcyxcbiAgICAgICAgICAgICAgICBuRmlsZXMgPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpICsgbiwgbG9nID0gbiA+IDEgPyBzZWxmLl9nZXRNc2dTZWxlY3RlZChuRmlsZXMpIDogbGFiZWw7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Vycm9yKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlld0NvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlld1N0YXR1cy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5oaWRlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dGaWxlSWNvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihsb2csIHNlbGYuaXNFcnJvcik7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3IGZpbGUtaW5wdXQtYWpheC1uZXcnKTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVzZWxlY3QnLCBbbnVtRmlsZXMsIGxhYmVsXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3QWN0aW9ucygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2V0VGh1bWJTdGF0dXM6IGZ1bmN0aW9uICgkdGh1bWIsIHN0YXR1cykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGljb24gPSAnaW5kaWNhdG9yJyArIHN0YXR1cywgbXNnID0gaWNvbiArICdUaXRsZScsXG4gICAgICAgICAgICAgICAgY3NzID0gJ2ZpbGUtcHJldmlldy0nICsgc3RhdHVzLnRvTG93ZXJDYXNlKCksXG4gICAgICAgICAgICAgICAgJGluZGljYXRvciA9ICR0aHVtYi5maW5kKCcuZmlsZS11cGxvYWQtaW5kaWNhdG9yJyksXG4gICAgICAgICAgICAgICAgY29uZmlnID0gc2VsZi5maWxlQWN0aW9uU2V0dGluZ3M7XG4gICAgICAgICAgICAkdGh1bWIucmVtb3ZlQ2xhc3MoJ2ZpbGUtcHJldmlldy1zdWNjZXNzIGZpbGUtcHJldmlldy1lcnJvciBmaWxlLXByZXZpZXctbG9hZGluZycpO1xuICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ0Vycm9yJykge1xuICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ1N1Y2Nlc3MnKSB7XG4gICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5maWxlLWRyYWctaGFuZGxlJykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgJGluZGljYXRvci5jc3MoJ21hcmdpbi1sZWZ0JywgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaW5kaWNhdG9yLmh0bWwoY29uZmlnW2ljb25dKTtcbiAgICAgICAgICAgICRpbmRpY2F0b3IuYXR0cigndGl0bGUnLCBjb25maWdbbXNnXSk7XG4gICAgICAgICAgICAkdGh1bWIuYWRkQ2xhc3MoY3NzKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3NldFByb2dyZXNzQ2FuY2VsbGVkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0NhbmNlbGxlZCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRQcm9ncmVzczogZnVuY3Rpb24gKHAsICRlbCwgZXJyb3IpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgcGN0ID0gTWF0aC5taW4ocCwgMTAwKSwgb3V0LCBwY3RMaW1pdCA9IHNlbGYucHJvZ3Jlc3NVcGxvYWRUaHJlc2hvbGQsXG4gICAgICAgICAgICAgICAgdCA9IHAgPD0gMTAwID8gc2VsZi5wcm9ncmVzc1RlbXBsYXRlIDogc2VsZi5wcm9ncmVzc0NvbXBsZXRlVGVtcGxhdGUsXG4gICAgICAgICAgICAgICAgdGVtcGxhdGUgPSBwY3QgPCAxMDAgPyBzZWxmLnByb2dyZXNzVGVtcGxhdGUgOiAoZXJyb3IgPyBzZWxmLnByb2dyZXNzRXJyb3JUZW1wbGF0ZSA6IHQpO1xuICAgICAgICAgICAgJGVsID0gJGVsIHx8IHNlbGYuJHByb2dyZXNzO1xuICAgICAgICAgICAgaWYgKCEkaC5pc0VtcHR5KHRlbXBsYXRlKSkge1xuICAgICAgICAgICAgICAgIGlmIChwY3RMaW1pdCAmJiBwY3QgPiBwY3RMaW1pdCAmJiBwIDw9IDEwMCkge1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSB0ZW1wbGF0ZS5zZXRUb2tlbnMoeydwZXJjZW50JzogcGN0TGltaXQsICdzdGF0dXMnOiBzZWxmLm1zZ1VwbG9hZFRocmVzaG9sZH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7J3BlcmNlbnQnOiBwY3QsICdzdGF0dXMnOiAocCA+IDEwMCA/IHNlbGYubXNnVXBsb2FkRW5kIDogcGN0ICsgJyUnKX0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkZWwuaHRtbChvdXQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAkZWwuZmluZCgnW3JvbGU9XCJwcm9ncmVzc2JhclwiXScpLmh0bWwoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3NldEZpbGVEcm9wWm9uZVRpdGxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICR6b25lID0gc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlLWRyb3Atem9uZScpLCB0aXRsZSA9IHNlbGYuZHJvcFpvbmVUaXRsZSwgc3RyRmlsZXM7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0NsaWNrYWJsZSkge1xuICAgICAgICAgICAgICAgIHN0ckZpbGVzID0gJGguaXNFbXB0eShzZWxmLiRlbGVtZW50LmF0dHIoJ211bHRpcGxlJykpID8gc2VsZi5maWxlU2luZ2xlIDogc2VsZi5maWxlUGx1cmFsO1xuICAgICAgICAgICAgICAgIHRpdGxlICs9IHNlbGYuZHJvcFpvbmVDbGlja1RpdGxlLnJlcGxhY2UoJ3tmaWxlc30nLCBzdHJGaWxlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkem9uZS5maW5kKCcuJyArIHNlbGYuZHJvcFpvbmVUaXRsZUNsYXNzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGlmICghc2VsZi5pc1VwbG9hZGFibGUgfHwgIXNlbGYuc2hvd1ByZXZpZXcgfHwgJHpvbmUubGVuZ3RoID09PSAwIHx8IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoID4gMCB8fCAhc2VsZi5kcm9wWm9uZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJHpvbmUuZmluZCgkaC5GUkFNRVMpLmxlbmd0aCA9PT0gMCAmJiAkaC5pc0VtcHR5KHNlbGYuZGVmYXVsdFByZXZpZXdDb250ZW50KSkge1xuICAgICAgICAgICAgICAgICR6b25lLnByZXBlbmQoJzxkaXYgY2xhc3M9XCInICsgc2VsZi5kcm9wWm9uZVRpdGxlQ2xhc3MgKyAnXCI+JyArIHRpdGxlICsgJzwvZGl2PicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2ZpbGUtaW5wdXQtYWpheC1uZXcnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3NldEFzeW5jVXBsb2FkU3RhdHVzOiBmdW5jdGlvbiAocHJldmlld0lkLCBwY3QsIHRvdGFsKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHN1bSA9IDA7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcyhwY3QsICQoJyMnICsgcHJldmlld0lkKS5maW5kKCcuZmlsZS10aHVtYi1wcm9ncmVzcycpKTtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzW3ByZXZpZXdJZF0gPSBwY3Q7XG4gICAgICAgICAgICAkLmVhY2goc2VsZi51cGxvYWRTdGF0dXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgc3VtICs9IHZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcyhNYXRoLmZsb29yKHN1bSAvIHRvdGFsKSk7XG5cbiAgICAgICAgfSxcbiAgICAgICAgX3ZhbGlkYXRlTWluQ291bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgbGVuID0gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCA6IHNlbGYuJGVsZW1lbnQuZ2V0KDApLmZpbGVzLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChzZWxmLnZhbGlkYXRlSW5pdGlhbENvdW50ICYmIHNlbGYubWluRmlsZUNvdW50ID4gMCAmJiBzZWxmLl9nZXRGaWxlQ291bnQobGVuIC0gMSkgPCBzZWxmLm1pbkZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX25vRmlsZXNFcnJvcih7fSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlQ291bnQ6IGZ1bmN0aW9uIChmaWxlQ291bnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgYWRkQ291bnQgPSAwO1xuICAgICAgICAgICAgaWYgKHNlbGYudmFsaWRhdGVJbml0aWFsQ291bnQgJiYgIXNlbGYub3ZlcndyaXRlSW5pdGlhbCkge1xuICAgICAgICAgICAgICAgIGFkZENvdW50ID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgICAgICAgICBmaWxlQ291bnQgKz0gYWRkQ291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmlsZUNvdW50O1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RmlsZUlkOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBjdXN0b20gPSBzZWxmLmdlbmVyYXRlRmlsZUlkLCByZWxhdGl2ZVBhdGg7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGN1c3RvbSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBjdXN0b20oZmlsZSwgZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBmaWxlLndlYmtpdFJlbGF0aXZlUGF0aCAqL1xuICAgICAgICAgICAgcmVsYXRpdmVQYXRoID0gZmlsZS53ZWJraXRSZWxhdGl2ZVBhdGggfHwgZmlsZS5maWxlTmFtZSB8fCBmaWxlLm5hbWUgfHwgbnVsbDtcbiAgICAgICAgICAgIGlmICghcmVsYXRpdmVQYXRoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKGZpbGUuc2l6ZSArICctJyArIHJlbGF0aXZlUGF0aC5yZXBsYWNlKC9bXjAtOWEtekEtWl8tXS9pbWcsICcnKSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlTmFtZTogZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmaWxlICYmIGZpbGUubmFtZSA/IHRoaXMuc2x1ZyhmaWxlLm5hbWUpIDogdW5kZWZpbmVkO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RmlsZUlkczogZnVuY3Rpb24gKHNraXBOdWxsKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5maWxlaWRzLmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgIHJldHVybiAoc2tpcE51bGwgPyBuICE9PSB1bmRlZmluZWQgOiBuICE9PSB1bmRlZmluZWQgJiYgbiAhPT0gbnVsbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZpbGVOYW1lczogZnVuY3Rpb24gKHNraXBOdWxsKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5maWxlbmFtZXMuZmlsdGVyKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChza2lwTnVsbCA/IG4gIT09IHVuZGVmaW5lZCA6IG4gIT09IHVuZGVmaW5lZCAmJiBuICE9PSBudWxsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0UHJldmlld0Vycm9yOiBmdW5jdGlvbiAoJHRodW1iLCBpLCB2YWwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmIChpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGksIHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5yZW1vdmVGcm9tUHJldmlld09uRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX3NldFRodW1iU3RhdHVzKCR0aHVtYiwgJ0Vycm9yJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9jaGVja0RpbWVuc2lvbnM6IGZ1bmN0aW9uIChpLCBjaGssICRpbWcsICR0aHVtYiwgZm5hbWUsIHR5cGUsIHBhcmFtcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBtc2csIGRpbSwgdGFnID0gY2hrID09PSAnU21hbGwnID8gJ21pbicgOiAnbWF4JywgbGltaXQgPSBzZWxmW3RhZyArICdJbWFnZScgKyB0eXBlXSxcbiAgICAgICAgICAgICAgICAkaW1nRWwsIGlzVmFsaWQ7XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eShsaW1pdCkgfHwgISRpbWcubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGltZ0VsID0gJGltZ1swXTtcbiAgICAgICAgICAgIGRpbSA9ICh0eXBlID09PSAnV2lkdGgnKSA/ICRpbWdFbC5uYXR1cmFsV2lkdGggfHwgJGltZ0VsLndpZHRoIDogJGltZ0VsLm5hdHVyYWxIZWlnaHQgfHwgJGltZ0VsLmhlaWdodDtcbiAgICAgICAgICAgIGlzVmFsaWQgPSBjaGsgPT09ICdTbWFsbCcgPyBkaW0gPj0gbGltaXQgOiBkaW0gPD0gbGltaXQ7XG4gICAgICAgICAgICBpZiAoaXNWYWxpZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1zZyA9IHNlbGZbJ21zZ0ltYWdlJyArIHR5cGUgKyBjaGtdLnNldFRva2Vucyh7J25hbWUnOiBmbmFtZSwgJ3NpemUnOiBsaW1pdH0pO1xuICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1zZywgcGFyYW1zKTtcbiAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIsIGksIG51bGwpO1xuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGVJbWFnZTogZnVuY3Rpb24gKHByZXZpZXdJZCwgZm5hbWUsIGZ0eXBlLCBmc2l6ZSwgaURhdGEpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3LCBwYXJhbXMsIHcxLCB3MiwgJHRodW1iID0gJHByZXZpZXcuZmluZChcIiNcIiArIHByZXZpZXdJZCksXG4gICAgICAgICAgICAgICAgaSA9ICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpLCAkaW1nID0gJHRodW1iLmZpbmQoJ2ltZycpLCBleGlmT2JqZWN0O1xuICAgICAgICAgICAgZm5hbWUgPSBmbmFtZSB8fCAnVW50aXRsZWQnO1xuICAgICAgICAgICAgJGltZy5vbmUoJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdzEgPSAkdGh1bWIud2lkdGgoKTtcbiAgICAgICAgICAgICAgICB3MiA9ICRwcmV2aWV3LndpZHRoKCk7XG4gICAgICAgICAgICAgICAgaWYgKHcxID4gdzIpIHtcbiAgICAgICAgICAgICAgICAgICAgJGltZy5jc3MoJ3dpZHRoJywgJzEwMCUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge2luZDogaSwgaWQ6IHByZXZpZXdJZH07XG4gICAgICAgICAgICAgICAgc2VsZi5fY2hlY2tEaW1lbnNpb25zKGksICdTbWFsbCcsICRpbWcsICR0aHVtYiwgZm5hbWUsICdXaWR0aCcsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2hlY2tEaW1lbnNpb25zKGksICdTbWFsbCcsICRpbWcsICR0aHVtYiwgZm5hbWUsICdIZWlnaHQnLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5yZXNpemVJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ0xhcmdlJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ1dpZHRoJywgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2hlY2tEaW1lbnNpb25zKGksICdMYXJnZScsICRpbWcsICR0aHVtYiwgZm5hbWUsICdIZWlnaHQnLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlbG9hZGVkJywgW3ByZXZpZXdJZF0pO1xuICAgICAgICAgICAgICAgIGV4aWZPYmplY3QgPSB3aW5kb3cucGlleGlmID8gd2luZG93LnBpZXhpZi5sb2FkKGlEYXRhKSA6IG51bGw7XG4gICAgICAgICAgICAgICAgc2VsZi5sb2FkZWRJbWFnZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGluZDogaSxcbiAgICAgICAgICAgICAgICAgICAgaW1nOiAkaW1nLFxuICAgICAgICAgICAgICAgICAgICB0aHVtYjogJHRodW1iLFxuICAgICAgICAgICAgICAgICAgICBwaWQ6IHByZXZpZXdJZCxcbiAgICAgICAgICAgICAgICAgICAgdHlwOiBmdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgc2l6OiBmc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGVkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YTogaURhdGEsXG4gICAgICAgICAgICAgICAgICAgIGV4aWZPYmo6IGV4aWZPYmplY3RcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAkdGh1bWIuZGF0YSgnZXhpZicsIGV4aWZPYmplY3QpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlQWxsSW1hZ2VzKCk7XG4gICAgICAgICAgICB9KS5vbmUoJ2Vycm9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2Vsb2FkZXJyb3InLCBbcHJldmlld0lkXSk7XG4gICAgICAgICAgICB9KS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRyaWdnZXIoJ2xvYWQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS50cmlnZ2VyKCdlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF92YWxpZGF0ZUFsbEltYWdlczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpLCBjb3VudGVyID0ge3ZhbDogMH0sIG51bUltZ3MgPSBzZWxmLmxvYWRlZEltYWdlcy5sZW5ndGgsIGNvbmZpZyxcbiAgICAgICAgICAgICAgICBmc2l6ZSwgbWluU2l6ZSA9IHNlbGYucmVzaXplSWZTaXplTW9yZVRoYW47XG4gICAgICAgICAgICBpZiAobnVtSW1ncyAhPT0gc2VsZi50b3RhbEltYWdlc0NvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZXNsb2FkZWQnKTtcbiAgICAgICAgICAgIGlmICghc2VsZi5yZXNpemVJbWFnZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWxmLmxvYWRlZEltYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbmZpZyA9IHNlbGYubG9hZGVkSW1hZ2VzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcudmFsaWRhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmc2l6ZSA9IGNvbmZpZy5zaXo7XG4gICAgICAgICAgICAgICAgaWYgKGZzaXplICYmIGZzaXplID4gbWluU2l6ZSAqIDEwMDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fZ2V0UmVzaXplZEltYWdlKGNvbmZpZywgY291bnRlciwgbnVtSW1ncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzW2ldLnZhbGlkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRSZXNpemVkSW1hZ2U6IGZ1bmN0aW9uIChjb25maWcsIGNvdW50ZXIsIG51bUltZ3MpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaW1nID0gJChjb25maWcuaW1nKVswXSwgd2lkdGggPSBpbWcubmF0dXJhbFdpZHRoLCBoZWlnaHQgPSBpbWcubmF0dXJhbEhlaWdodCwgYmxvYixcbiAgICAgICAgICAgICAgICByYXRpbyA9IDEsIG1heFdpZHRoID0gc2VsZi5tYXhJbWFnZVdpZHRoIHx8IHdpZHRoLCBtYXhIZWlnaHQgPSBzZWxmLm1heEltYWdlSGVpZ2h0IHx8IGhlaWdodCxcbiAgICAgICAgICAgICAgICBpc1ZhbGlkSW1hZ2UgPSAhISh3aWR0aCAmJiBoZWlnaHQpLCBjaGtXaWR0aCwgY2hrSGVpZ2h0LCBjYW52YXMgPSBzZWxmLmltYWdlQ2FudmFzLCBkYXRhVVJJLFxuICAgICAgICAgICAgICAgIGNvbnRleHQgPSBzZWxmLmltYWdlQ2FudmFzQ29udGV4dCwgdHlwZSA9IGNvbmZpZy50eXAsIHBpZCA9IGNvbmZpZy5waWQsIGluZCA9IGNvbmZpZy5pbmQsXG4gICAgICAgICAgICAgICAgJHRodW1iID0gY29uZmlnLnRodW1iLCB0aHJvd0Vycm9yLCBtc2csIGV4aWZPYmogPSBjb25maWcuZXhpZk9iaiwgZXhpZlN0cjtcbiAgICAgICAgICAgIHRocm93RXJyb3IgPSBmdW5jdGlvbiAobXNnLCBwYXJhbXMsIGV2KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihtc2csIHBhcmFtcywgZXYpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dFcnJvcihtc2csIHBhcmFtcywgZXYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iLCBpbmQpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICghc2VsZi5maWxlc3RhY2tbaW5kXSB8fCAhaXNWYWxpZEltYWdlIHx8ICh3aWR0aCA8PSBtYXhXaWR0aCAmJiBoZWlnaHQgPD0gbWF4SGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkSW1hZ2UgJiYgc2VsZi5maWxlc3RhY2tbaW5kXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlcmVzaXplZCcsIFtwaWQsIGluZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb3VudGVyLnZhbCsrO1xuICAgICAgICAgICAgICAgIGlmIChjb3VudGVyLnZhbCA9PT0gbnVtSW1ncykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlc3Jlc2l6ZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkSW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihzZWxmLm1zZ0ltYWdlUmVzaXplRXJyb3IsIHtpZDogcGlkLCAnaW5kZXgnOiBpbmR9LCAnZmlsZWltYWdlcmVzaXplZXJyb3InKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHR5cGUgPSB0eXBlIHx8IHNlbGYucmVzaXplRGVmYXVsdEltYWdlVHlwZTtcbiAgICAgICAgICAgIGNoa1dpZHRoID0gd2lkdGggPiBtYXhXaWR0aDtcbiAgICAgICAgICAgIGNoa0hlaWdodCA9IGhlaWdodCA+IG1heEhlaWdodDtcbiAgICAgICAgICAgIGlmIChzZWxmLnJlc2l6ZVByZWZlcmVuY2UgPT09ICd3aWR0aCcpIHtcbiAgICAgICAgICAgICAgICByYXRpbyA9IGNoa1dpZHRoID8gbWF4V2lkdGggLyB3aWR0aCA6IChjaGtIZWlnaHQgPyBtYXhIZWlnaHQgLyBoZWlnaHQgOiAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmF0aW8gPSBjaGtIZWlnaHQgPyBtYXhIZWlnaHQgLyBoZWlnaHQgOiAoY2hrV2lkdGggPyBtYXhXaWR0aCAvIHdpZHRoIDogMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldENhbnZhcygpO1xuICAgICAgICAgICAgd2lkdGggKj0gcmF0aW87XG4gICAgICAgICAgICBoZWlnaHQgKj0gcmF0aW87XG4gICAgICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGltZywgMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAgICAgZGF0YVVSSSA9IGNhbnZhcy50b0RhdGFVUkwodHlwZSwgc2VsZi5yZXNpemVRdWFsaXR5KTtcbiAgICAgICAgICAgICAgICBpZiAoZXhpZk9iaikge1xuICAgICAgICAgICAgICAgICAgICBleGlmU3RyID0gd2luZG93LnBpZXhpZi5kdW1wKGV4aWZPYmopO1xuICAgICAgICAgICAgICAgICAgICBkYXRhVVJJID0gd2luZG93LnBpZXhpZi5pbnNlcnQoZXhpZlN0ciwgZGF0YVVSSSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJsb2IgPSAkaC5kYXRhVVJJMkJsb2IoZGF0YVVSSSk7XG4gICAgICAgICAgICAgICAgc2VsZi5maWxlc3RhY2tbaW5kXSA9IGJsb2I7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZXJlc2l6ZWQnLCBbcGlkLCBpbmRdKTtcbiAgICAgICAgICAgICAgICBjb3VudGVyLnZhbCsrO1xuICAgICAgICAgICAgICAgIGlmIChjb3VudGVyLnZhbCA9PT0gbnVtSW1ncykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlc3Jlc2l6ZWQnLCBbdW5kZWZpbmVkLCB1bmRlZmluZWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEoYmxvYiBpbnN0YW5jZW9mIEJsb2IpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93RXJyb3Ioc2VsZi5tc2dJbWFnZVJlc2l6ZUVycm9yLCB7aWQ6IHBpZCwgJ2luZGV4JzogaW5kfSwgJ2ZpbGVpbWFnZXJlc2l6ZWVycm9yJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGNvdW50ZXIudmFsKys7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIudmFsID09PSBudW1JbWdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VzcmVzaXplZCcsIFt1bmRlZmluZWQsIHVuZGVmaW5lZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ltYWdlUmVzaXplRXhjZXB0aW9uLnJlcGxhY2UoJ3tlcnJvcnN9JywgZXJyLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIHRocm93RXJyb3IobXNnLCB7aWQ6IHBpZCwgJ2luZGV4JzogaW5kfSwgJ2ZpbGVpbWFnZXJlc2l6ZWV4Y2VwdGlvbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaW5pdEJyb3dzZTogZnVuY3Rpb24gKCRjb250YWluZXIpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dCcm93c2UpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRidG5GaWxlID0gJGNvbnRhaW5lci5maW5kKCcuYnRuLWZpbGUnKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRidG5GaWxlLmFwcGVuZChzZWxmLiRlbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0Q2FwdGlvbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBjYXAgPSBzZWxmLmluaXRpYWxDYXB0aW9uIHx8ICcnO1xuICAgICAgICAgICAgaWYgKHNlbGYub3ZlcndyaXRlSW5pdGlhbCB8fCAkaC5pc0VtcHR5KGNhcCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uLmh0bWwoJycpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oY2FwKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0Q2FwdGlvbjogZnVuY3Rpb24gKGNvbnRlbnQsIGlzRXJyb3IpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdGl0bGUsIG91dCwgbiwgY2FwLCBzdGFjayA9IHNlbGYuZ2V0RmlsZVN0YWNrKCk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuJGNhcHRpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzRXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aXRsZSA9ICQoJzxkaXY+JyArIHNlbGYubXNnVmFsaWRhdGlvbkVycm9yICsgJzwvZGl2PicpLnRleHQoKTtcbiAgICAgICAgICAgICAgICBuID0gc3RhY2subGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChuKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhcCA9IG4gPT09IDEgJiYgc3RhY2tbMF0gPyBzZWxmLl9nZXRGaWxlTmFtZXMoKVswXSA6IHNlbGYuX2dldE1zZ1NlbGVjdGVkKG4pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNhcCA9IHNlbGYuX2dldE1zZ1NlbGVjdGVkKHNlbGYubXNnTm8pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvdXQgPSAnPHNwYW4gY2xhc3M9XCInICsgc2VsZi5tc2dWYWxpZGF0aW9uRXJyb3JDbGFzcyArICdcIj4nICsgc2VsZi5tc2dWYWxpZGF0aW9uRXJyb3JJY29uICtcbiAgICAgICAgICAgICAgICAgICAgKCRoLmlzRW1wdHkoY29udGVudCkgPyBjYXAgOiBjb250ZW50KSArICc8L3NwYW4+JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aXRsZSA9ICQoJzxkaXY+JyArIGNvbnRlbnQgKyAnPC9kaXY+JykudGV4dCgpO1xuICAgICAgICAgICAgICAgIG91dCA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdmaWxlSWNvbicpICsgdGl0bGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRjYXB0aW9uLmh0bWwob3V0KTtcbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uYXR0cigndGl0bGUnLCB0aXRsZSk7XG4gICAgICAgICAgICBzZWxmLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5maWxlLWNhcHRpb24tZWxsaXBzaXMnKS5hdHRyKCd0aXRsZScsIHRpdGxlKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NyZWF0ZUNvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhdHRyaWJzID0ge1wiY2xhc3NcIjogJ2ZpbGUtaW5wdXQgZmlsZS1pbnB1dC1uZXcnICsgKHNlbGYucnRsID8gJyBrdi1ydGwnIDogJycpfSxcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpKS5hdHRyKGF0dHJpYnMpLmh0bWwoc2VsZi5fcmVuZGVyTWFpbigpKTtcbiAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQuYmVmb3JlKCRjb250YWluZXIpO1xuICAgICAgICAgICAgc2VsZi5faW5pdEJyb3dzZSgkY29udGFpbmVyKTtcbiAgICAgICAgICAgIGlmIChzZWxmLnRoZW1lKSB7XG4gICAgICAgICAgICAgICAgJGNvbnRhaW5lci5hZGRDbGFzcygndGhlbWUtJyArIHNlbGYudGhlbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRjb250YWluZXI7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZWZyZXNoQ29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRjb250YWluZXIgPSBzZWxmLiRjb250YWluZXI7XG4gICAgICAgICAgICAkY29udGFpbmVyLmJlZm9yZShzZWxmLiRlbGVtZW50KTtcbiAgICAgICAgICAgICRjb250YWluZXIuaHRtbChzZWxmLl9yZW5kZXJNYWluKCkpO1xuICAgICAgICAgICAgc2VsZi5faW5pdEJyb3dzZSgkY29udGFpbmVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlbmRlck1haW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgICAgICAgICBkcm9wQ3NzID0gKHNlbGYuaXNVcGxvYWRhYmxlICYmIHNlbGYuZHJvcFpvbmVFbmFibGVkKSA/ICcgZmlsZS1kcm9wLXpvbmUnIDogJ2ZpbGUtZHJvcC1kaXNhYmxlZCcsXG4gICAgICAgICAgICAgICAgY2xvc2UgPSAhc2VsZi5zaG93Q2xvc2UgPyAnJyA6IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdjbG9zZScpLFxuICAgICAgICAgICAgICAgIHByZXZpZXcgPSAhc2VsZi5zaG93UHJldmlldyA/ICcnIDogc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ3ByZXZpZXcnKVxuICAgICAgICAgICAgICAgICAgICAuc2V0VG9rZW5zKHsnY2xhc3MnOiBzZWxmLnByZXZpZXdDbGFzcywgJ2Ryb3BDbGFzcyc6IGRyb3BDc3N9KSxcbiAgICAgICAgICAgICAgICBjc3MgPSBzZWxmLmlzRGlzYWJsZWQgPyBzZWxmLmNhcHRpb25DbGFzcyArICcgZmlsZS1jYXB0aW9uLWRpc2FibGVkJyA6IHNlbGYuY2FwdGlvbkNsYXNzLFxuICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzZWxmLmNhcHRpb25UZW1wbGF0ZS5zZXRUb2tlbnMoeydjbGFzcyc6IGNzcyArICcga3YtZmlsZWlucHV0LWNhcHRpb24nfSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5tYWluVGVtcGxhdGUuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAnY2xhc3MnOiBzZWxmLm1haW5DbGFzcyArICghc2VsZi5zaG93QnJvd3NlICYmIHNlbGYuc2hvd0NhcHRpb24gPyAnIG5vLWJyb3dzZScgOiAnJyksXG4gICAgICAgICAgICAgICAgJ3ByZXZpZXcnOiBwcmV2aWV3LFxuICAgICAgICAgICAgICAgICdjbG9zZSc6IGNsb3NlLFxuICAgICAgICAgICAgICAgICdjYXB0aW9uJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAndXBsb2FkJzogc2VsZi5fcmVuZGVyQnV0dG9uKCd1cGxvYWQnKSxcbiAgICAgICAgICAgICAgICAncmVtb3ZlJzogc2VsZi5fcmVuZGVyQnV0dG9uKCdyZW1vdmUnKSxcbiAgICAgICAgICAgICAgICAnY2FuY2VsJzogc2VsZi5fcmVuZGVyQnV0dG9uKCdjYW5jZWwnKSxcbiAgICAgICAgICAgICAgICAnYnJvd3NlJzogc2VsZi5fcmVuZGVyQnV0dG9uKCdicm93c2UnKVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgfSxcbiAgICAgICAgX3JlbmRlckJ1dHRvbjogZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdG1wbHQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYnRuRGVmYXVsdCcpLCBjc3MgPSBzZWxmW3R5cGUgKyAnQ2xhc3MnXSxcbiAgICAgICAgICAgICAgICB0aXRsZSA9IHNlbGZbdHlwZSArICdUaXRsZSddLCBpY29uID0gc2VsZlt0eXBlICsgJ0ljb24nXSwgbGFiZWwgPSBzZWxmW3R5cGUgKyAnTGFiZWwnXSxcbiAgICAgICAgICAgICAgICBzdGF0dXMgPSBzZWxmLmlzRGlzYWJsZWQgPyAnIGRpc2FibGVkJyA6ICcnLCBidG5UeXBlID0gJ2J1dHRvbic7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdyZW1vdmUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1JlbW92ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NhbmNlbCc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5zaG93Q2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY3NzICs9ICcgaGlkZSc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3VwbG9hZCc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5zaG93VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlICYmICFzZWxmLmlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRtcGx0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2J0bkxpbmsnKS5yZXBsYWNlKCd7aHJlZn0nLCBzZWxmLnVwbG9hZFVybCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBidG5UeXBlID0gJ3N1Ym1pdCc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYnJvd3NlJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dCcm93c2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0bXBsdCA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdidG5Ccm93c2UnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjc3MgKz0gdHlwZSA9PT0gJ2Jyb3dzZScgPyAnIGJ0bi1maWxlJyA6ICcgZmlsZWlucHV0LScgKyB0eXBlICsgJyBmaWxlaW5wdXQtJyArIHR5cGUgKyAnLWJ1dHRvbic7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkobGFiZWwpKSB7XG4gICAgICAgICAgICAgICAgbGFiZWwgPSAnIDxzcGFuIGNsYXNzPVwiJyArIHNlbGYuYnV0dG9uTGFiZWxDbGFzcyArICdcIj4nICsgbGFiZWwgKyAnPC9zcGFuPic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdG1wbHQuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAndHlwZSc6IGJ0blR5cGUsICdjc3MnOiBjc3MsICd0aXRsZSc6IHRpdGxlLCAnc3RhdHVzJzogc3RhdHVzLCAnaWNvbic6IGljb24sICdsYWJlbCc6IGxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlbmRlclRodW1iUHJvZ3Jlc3M6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiAnPGRpdiBjbGFzcz1cImZpbGUtdGh1bWItcHJvZ3Jlc3MgaGlkZVwiPicgK1xuICAgICAgICAgICAgICAgIHNlbGYucHJvZ3Jlc3NUZW1wbGF0ZS5zZXRUb2tlbnMoeydwZXJjZW50JzogJzAnLCAnc3RhdHVzJzogc2VsZi5tc2dVcGxvYWRCZWdpbn0pICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgfSxcbiAgICAgICAgX3JlbmRlckZpbGVGb290ZXI6IGZ1bmN0aW9uIChjYXB0aW9uLCBzaXplLCB3aWR0aCwgaXNFcnJvcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBjb25maWcgPSBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncywgcmVtID0gY29uZmlnLnNob3dSZW1vdmUsIGRyZyA9IGNvbmZpZy5zaG93RHJhZyxcbiAgICAgICAgICAgICAgICB1cGwgPSBjb25maWcuc2hvd1VwbG9hZCwgem9vbSA9IGNvbmZpZy5zaG93Wm9vbSwgb3V0LCB0ZW1wbGF0ZSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdmb290ZXInKSxcbiAgICAgICAgICAgICAgICBpbmQgPSBpc0Vycm9yID8gY29uZmlnLmluZGljYXRvckVycm9yIDogY29uZmlnLmluZGljYXRvck5ldyxcbiAgICAgICAgICAgICAgICB0SW5kID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2luZGljYXRvcicpLFxuICAgICAgICAgICAgICAgIHRpdGxlID0gaXNFcnJvciA/IGNvbmZpZy5pbmRpY2F0b3JFcnJvclRpdGxlIDogY29uZmlnLmluZGljYXRvck5ld1RpdGxlLFxuICAgICAgICAgICAgICAgIGluZGljYXRvciA9IHRJbmQuc2V0VG9rZW5zKHsnaW5kaWNhdG9yJzogaW5kLCAnaW5kaWNhdG9yVGl0bGUnOiB0aXRsZX0pO1xuICAgICAgICAgICAgc2l6ZSA9IHNlbGYuX2dldFNpemUoc2l6ZSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICBvdXQgPSB0ZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAnYWN0aW9ucyc6IHNlbGYuX3JlbmRlckZpbGVBY3Rpb25zKHVwbCwgcmVtLCB6b29tLCBkcmcsIGZhbHNlLCBmYWxzZSwgZmFsc2UpLFxuICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICdzaXplJzogc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICdwcm9ncmVzcyc6IHNlbGYuX3JlbmRlclRodW1iUHJvZ3Jlc3MoKSxcbiAgICAgICAgICAgICAgICAgICAgJ2luZGljYXRvcic6IGluZGljYXRvclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvdXQgPSB0ZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAnYWN0aW9ucyc6IHNlbGYuX3JlbmRlckZpbGVBY3Rpb25zKGZhbHNlLCBmYWxzZSwgem9vbSwgZHJnLCBmYWxzZSwgZmFsc2UsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgJ2NhcHRpb24nOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAnc2l6ZSc6IHNpemUsXG4gICAgICAgICAgICAgICAgICAgICd3aWR0aCc6IHdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAncHJvZ3Jlc3MnOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgJ2luZGljYXRvcic6IGluZGljYXRvclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3V0ID0gJGgucmVwbGFjZVRhZ3Mob3V0LCBzZWxmLnByZXZpZXdUaHVtYlRhZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlbmRlckZpbGVBY3Rpb25zOiBmdW5jdGlvbiAoc2hvd1VwbG9hZCwgc2hvd0RlbGV0ZSwgc2hvd1pvb20sIHNob3dEcmFnLCBkaXNhYmxlZCwgdXJsLCBrZXksIGlzSW5pdCkge1xuICAgICAgICAgICAgaWYgKCFzaG93VXBsb2FkICYmICFzaG93RGVsZXRlICYmICFzaG93Wm9vbSAmJiAhc2hvd0RyYWcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHZVcmwgPSB1cmwgPT09IGZhbHNlID8gJycgOiAnIGRhdGEtdXJsPVwiJyArIHVybCArICdcIicsXG4gICAgICAgICAgICAgICAgdktleSA9IGtleSA9PT0gZmFsc2UgPyAnJyA6ICcgZGF0YS1rZXk9XCInICsga2V5ICsgJ1wiJyxcbiAgICAgICAgICAgICAgICBidG5EZWxldGUgPSAnJywgYnRuVXBsb2FkID0gJycsIGJ0blpvb20gPSAnJywgYnRuRHJhZyA9ICcnLCBjc3MsXG4gICAgICAgICAgICAgICAgdGVtcGxhdGUgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYWN0aW9ucycpLCBjb25maWcgPSBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncyxcbiAgICAgICAgICAgICAgICBvdGhlckJ1dHRvbnMgPSBzZWxmLm90aGVyQWN0aW9uQnV0dG9ucy5zZXRUb2tlbnMoeydkYXRhS2V5JzogdktleX0pLFxuICAgICAgICAgICAgICAgIHJlbW92ZUNsYXNzID0gZGlzYWJsZWQgPyBjb25maWcucmVtb3ZlQ2xhc3MgKyAnIGRpc2FibGVkJyA6IGNvbmZpZy5yZW1vdmVDbGFzcztcbiAgICAgICAgICAgIGlmIChzaG93RGVsZXRlKSB7XG4gICAgICAgICAgICAgICAgYnRuRGVsZXRlID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvbkRlbGV0ZScpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdyZW1vdmVDbGFzcyc6IHJlbW92ZUNsYXNzLFxuICAgICAgICAgICAgICAgICAgICAncmVtb3ZlSWNvbic6IGNvbmZpZy5yZW1vdmVJY29uLFxuICAgICAgICAgICAgICAgICAgICAncmVtb3ZlVGl0bGUnOiBjb25maWcucmVtb3ZlVGl0bGUsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhVXJsJzogdlVybCxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGFLZXknOiB2S2V5XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hvd1VwbG9hZCkge1xuICAgICAgICAgICAgICAgIGJ0blVwbG9hZCA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdhY3Rpb25VcGxvYWQnKS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAndXBsb2FkQ2xhc3MnOiBjb25maWcudXBsb2FkQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgICd1cGxvYWRJY29uJzogY29uZmlnLnVwbG9hZEljb24sXG4gICAgICAgICAgICAgICAgICAgICd1cGxvYWRUaXRsZSc6IGNvbmZpZy51cGxvYWRUaXRsZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNob3dab29tKSB7XG4gICAgICAgICAgICAgICAgYnRuWm9vbSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdhY3Rpb25ab29tJykuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgJ3pvb21DbGFzcyc6IGNvbmZpZy56b29tQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgICd6b29tSWNvbic6IGNvbmZpZy56b29tSWNvbixcbiAgICAgICAgICAgICAgICAgICAgJ3pvb21UaXRsZSc6IGNvbmZpZy56b29tVGl0bGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzaG93RHJhZyAmJiBpc0luaXQpIHtcbiAgICAgICAgICAgICAgICBjc3MgPSAnZHJhZy1oYW5kbGUtaW5pdCAnICsgY29uZmlnLmRyYWdDbGFzcztcbiAgICAgICAgICAgICAgICBidG5EcmFnID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvbkRyYWcnKS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAnZHJhZ0NsYXNzJzogY3NzLFxuICAgICAgICAgICAgICAgICAgICAnZHJhZ1RpdGxlJzogY29uZmlnLmRyYWdUaXRsZSxcbiAgICAgICAgICAgICAgICAgICAgJ2RyYWdJY29uJzogY29uZmlnLmRyYWdJY29uXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGVtcGxhdGUuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAnZGVsZXRlJzogYnRuRGVsZXRlLFxuICAgICAgICAgICAgICAgICd1cGxvYWQnOiBidG5VcGxvYWQsXG4gICAgICAgICAgICAgICAgJ3pvb20nOiBidG5ab29tLFxuICAgICAgICAgICAgICAgICdkcmFnJzogYnRuRHJhZyxcbiAgICAgICAgICAgICAgICAnb3RoZXInOiBvdGhlckJ1dHRvbnNcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfYnJvd3NlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVicm93c2UnKTtcbiAgICAgICAgICAgIGlmIChlICYmIGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Vycm9yICYmICFzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuY2xlYXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZm9jdXMoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2ZpbHRlckR1cGxpY2F0ZTogZnVuY3Rpb24gKGZpbGUsIGZpbGVzLCBmaWxlSWRzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGZpbGVJZCA9IHNlbGYuX2dldEZpbGVJZChmaWxlKTtcbiAgICAgICAgICAgIGlmIChmaWxlSWQgJiYgZmlsZUlkcyAmJiBmaWxlSWRzLmluZGV4T2YoZmlsZUlkKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFmaWxlSWRzKSB7XG4gICAgICAgICAgICAgICAgZmlsZUlkcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmlsZXMucHVzaChmaWxlKTtcbiAgICAgICAgICAgIGZpbGVJZHMucHVzaChmaWxlSWQpO1xuICAgICAgICB9LFxuICAgICAgICBfY2hhbmdlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50O1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSAmJiAkaC5pc0VtcHR5KCRlbC52YWwoKSkgJiYgc2VsZi5maWxlSW5wdXRDbGVhcmVkKSB7IC8vIElFIDExIGZpeFxuICAgICAgICAgICAgICAgIHNlbGYuZmlsZUlucHV0Q2xlYXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuZmlsZUlucHV0Q2xlYXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIHRmaWxlcyA9IFtdLCBtc2csIHRvdGFsLCBpc0RyYWdEcm9wID0gYXJndW1lbnRzLmxlbmd0aCA+IDEsIGlzQWpheFVwbG9hZCA9IHNlbGYuaXNVcGxvYWRhYmxlLCBuLCBsZW4sXG4gICAgICAgICAgICAgICAgZmlsZXMgPSBpc0RyYWdEcm9wID8gZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcyA6ICRlbC5nZXQoMCkuZmlsZXMsIGN0ciA9IHNlbGYuZmlsZXN0YWNrLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBpc1NpbmdsZVVwbG9hZCA9ICRoLmlzRW1wdHkoJGVsLmF0dHIoJ211bHRpcGxlJykpLCBmbGFnU2luZ2xlID0gKGlzU2luZ2xlVXBsb2FkICYmIGN0ciA+IDApLFxuICAgICAgICAgICAgICAgIGZvbGRlcnMgPSAwLCBmaWxlSWRzID0gc2VsZi5fZ2V0RmlsZUlkcygpLCB0aHJvd0Vycm9yID0gZnVuY3Rpb24gKG1lc2csIGZpbGUsIHByZXZpZXdJZCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHAxID0gJC5leHRlbmQodHJ1ZSwge30sIHNlbGYuX2dldE91dERhdGEoe30sIHt9LCBmaWxlcyksIHtpZDogcHJldmlld0lkLCBpbmRleDogaW5kZXh9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHAyID0ge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpbmRleCwgZmlsZTogZmlsZSwgZmlsZXM6IGZpbGVzfTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1lc2csIHAxKSA6IHNlbGYuX3Nob3dFcnJvcihtZXNnLCBwMik7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGYucmVhZGVyID0gbnVsbDtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0VXBsb2FkKCk7XG4gICAgICAgICAgICBzZWxmLl9oaWRlRmlsZUljb24oKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZS1kcm9wLXpvbmUgLicgKyBzZWxmLmRyb3Bab25lVGl0bGVDbGFzcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNEcmFnRHJvcCkge1xuICAgICAgICAgICAgICAgICQuZWFjaChmaWxlcywgZnVuY3Rpb24gKGksIGYpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGYgJiYgIWYudHlwZSAmJiBmLnNpemUgIT09IHVuZGVmaW5lZCAmJiBmLnNpemUgJSA0MDk2ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb2xkZXJzKys7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9maWx0ZXJEdXBsaWNhdGUoZiwgdGZpbGVzLCBmaWxlSWRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZS50YXJnZXQgJiYgZS50YXJnZXQuZmlsZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBmaWxlcyA9IGUudGFyZ2V0LnZhbHVlID8gW3tuYW1lOiBlLnRhcmdldC52YWx1ZS5yZXBsYWNlKC9eLitcXFxcLywgJycpfV0gOiBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmaWxlcyA9IGUudGFyZ2V0LmZpbGVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaXNBamF4VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgICQuZWFjaChmaWxlcywgZnVuY3Rpb24gKGksIGYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2ZpbHRlckR1cGxpY2F0ZShmLCB0ZmlsZXMsIGZpbGVJZHMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0ZmlsZXMgPSBmaWxlcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eSh0ZmlsZXMpIHx8IHRmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzQWpheFVwbG9hZCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dGb2xkZXJFcnJvcihmb2xkZXJzKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXNlbGVjdG5vbmUnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycygpO1xuICAgICAgICAgICAgbGVuID0gdGZpbGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHRvdGFsID0gc2VsZi5fZ2V0RmlsZUNvdW50KHNlbGYuaXNVcGxvYWRhYmxlID8gKHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoICsgbGVuKSA6IGxlbik7XG4gICAgICAgICAgICBpZiAoc2VsZi5tYXhGaWxlQ291bnQgPiAwICYmIHRvdGFsID4gc2VsZi5tYXhGaWxlQ291bnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNlbGYuYXV0b1JlcGxhY2UgfHwgbGVuID4gc2VsZi5tYXhGaWxlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgbiA9IChzZWxmLmF1dG9SZXBsYWNlICYmIGxlbiA+IHNlbGYubWF4RmlsZUNvdW50KSA/IGxlbiA6IHRvdGFsO1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ZpbGVzVG9vTWFueS5yZXBsYWNlKCd7bX0nLCBzZWxmLm1heEZpbGVDb3VudCkucmVwbGFjZSgne259Jywgbik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IHRocm93RXJyb3IobXNnLCBudWxsLCBudWxsLCBudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lci5maW5kKCcua3YtY2FwdGlvbi1pY29uJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKCcnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldyBmaWxlLWlucHV0LWFqYXgtbmV3Jyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRvdGFsID4gc2VsZi5tYXhGaWxlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRQcmV2aWV3VGh1bWJzKGlzQWpheFVwbG9hZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzQWpheFVwbG9hZCB8fCBmbGFnU2luZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0UHJldmlld1RodW1icyhmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmbGFnU2luZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FqYXhVcGxvYWQgJiYgY3RyID09PSAwICYmICghc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSB8fCBzZWxmLm92ZXJ3cml0ZUluaXRpYWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXdUaHVtYnModHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5pc1ByZXZpZXdhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVhZEZpbGVzKHRmaWxlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fc2hvd0ZvbGRlckVycm9yKGZvbGRlcnMpO1xuICAgICAgICB9LFxuICAgICAgICBfYWJvcnQ6IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZGF0YTtcbiAgICAgICAgICAgIGlmIChzZWxmLmFqYXhBYm9ydGVkICYmIHR5cGVvZiBzZWxmLmFqYXhBYm9ydGVkID09PSBcIm9iamVjdFwiICYmIHNlbGYuYWpheEFib3J0ZWQubWVzc2FnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBzZWxmLl9nZXRPdXREYXRhKCksIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgZGF0YS5hYm9ydERhdGEgPSBzZWxmLmFqYXhBYm9ydGVkLmRhdGEgfHwge307XG4gICAgICAgICAgICAgICAgZGF0YS5hYm9ydE1lc3NhZ2UgPSBzZWxmLmFqYXhBYm9ydGVkLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxLCBzZWxmLiRwcm9ncmVzcywgc2VsZi5tc2dDYW5jZWxsZWQpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihzZWxmLmFqYXhBYm9ydGVkLm1lc3NhZ2UsIGRhdGEsICdmaWxlY3VzdG9tZXJyb3InKTtcbiAgICAgICAgICAgICAgICBzZWxmLmNhbmNlbCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBfcmVzZXRGaWxlU3RhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaSA9IDAsIG5ld3N0YWNrID0gW10sIG5ld25hbWVzID0gW10sIG5ld2lkcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksIGluZCA9ICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpLCBmaWxlID0gc2VsZi5maWxlc3RhY2tbaW5kXSxcbiAgICAgICAgICAgICAgICAgICAgcGlkID0gJHRodW1iLmF0dHIoJ2lkJyksIG5ld0lkO1xuICAgICAgICAgICAgICAgIGlmIChpbmQgPT09ICctMScgfHwgaW5kID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmaWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3c3RhY2tbaV0gPSBmaWxlO1xuICAgICAgICAgICAgICAgICAgICBuZXduYW1lc1tpXSA9IHNlbGYuX2dldEZpbGVOYW1lKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICBuZXdpZHNbaV0gPSBzZWxmLl9nZXRGaWxlSWQoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5hdHRyKHsnaWQnOiBzZWxmLnByZXZpZXdJbml0SWQgKyAnLScgKyBpLCAnZGF0YS1maWxlaW5kZXgnOiBpfSk7XG4gICAgICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdJZCA9ICd1cGxvYWRlZC0nICsgJGgudW5pcUlkKCk7XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5hdHRyKHsnaWQnOiBuZXdJZCwgJ2RhdGEtZmlsZWluZGV4JzogJy0xJ30pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyBwaWQpLmF0dHIoJ2lkJywgJ3pvb20tJyArIG5ld0lkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuZmlsZXN0YWNrID0gbmV3c3RhY2s7XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lcyA9IG5ld25hbWVzO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzID0gbmV3aWRzO1xuICAgICAgICB9LFxuICAgICAgICBfaXNGaWxlU2VsZWN0aW9uVmFsaWQ6IGZ1bmN0aW9uIChjbnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGNudCA9IGNudCB8fCAwO1xuICAgICAgICAgICAgaWYgKHNlbGYucmVxdWlyZWQgJiYgIXNlbGYuZ2V0RmlsZXNDb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kZXJyb3JDb250YWluZXIuaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKHNlbGYubXNnRmlsZVJlcXVpcmVkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5taW5GaWxlQ291bnQgPiAwICYmIHNlbGYuX2dldEZpbGVDb3VudChjbnQpIDwgc2VsZi5taW5GaWxlQ291bnQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9ub0ZpbGVzRXJyb3Ioe30pO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBjbGVhclN0YWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmZpbGVzdGFjayA9IFtdO1xuICAgICAgICAgICAgc2VsZi5maWxlbmFtZXMgPSBbXTtcbiAgICAgICAgICAgIHNlbGYuZmlsZWlkcyA9IFtdO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHVwZGF0ZVN0YWNrOiBmdW5jdGlvbiAoaSwgZmlsZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5maWxlc3RhY2tbaV0gPSBmaWxlO1xuICAgICAgICAgICAgc2VsZi5maWxlbmFtZXNbaV0gPSBzZWxmLl9nZXRGaWxlTmFtZShmaWxlKTtcbiAgICAgICAgICAgIHNlbGYuZmlsZWlkc1tpXSA9IGZpbGUgJiYgc2VsZi5fZ2V0RmlsZUlkKGZpbGUpIHx8IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgYWRkVG9TdGFjazogZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuZmlsZXN0YWNrLnB1c2goZmlsZSk7XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lcy5wdXNoKHNlbGYuX2dldEZpbGVOYW1lKGZpbGUpKTtcbiAgICAgICAgICAgIHNlbGYuZmlsZWlkcy5wdXNoKHNlbGYuX2dldEZpbGVJZChmaWxlKSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RmlsZVN0YWNrOiBmdW5jdGlvbiAoc2tpcE51bGwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmZpbGVzdGFjay5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHNraXBOdWxsID8gbiAhPT0gdW5kZWZpbmVkIDogbiAhPT0gdW5kZWZpbmVkICYmIG4gIT09IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldEZpbGVzQ291bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgbGVuID0gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCA6IHNlbGYuJGVsZW1lbnQuZ2V0KDApLmZpbGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9nZXRGaWxlQ291bnQobGVuKTtcbiAgICAgICAgfSxcbiAgICAgICAgbG9jazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRFcnJvcnMoKTtcbiAgICAgICAgICAgIHNlbGYuZGlzYWJsZSgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1JlbW92ZSkge1xuICAgICAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGVpbnB1dC1yZW1vdmUnKSwgJ2hpZGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGVpbnB1dC1jYW5jZWwnKS5yZW1vdmVDbGFzcygnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVsb2NrJywgW3NlbGYuZmlsZXN0YWNrLCBzZWxmLl9nZXRFeHRyYURhdGEoKV0pO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHVubG9jazogZnVuY3Rpb24gKHJlc2V0KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAocmVzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJlc2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuZW5hYmxlKCk7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93Q2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LWNhbmNlbCcpLCAnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1JlbW92ZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LXJlbW92ZScpLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVzZXQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZXNldEZpbGVTdGFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGV1bmxvY2snLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgY2FuY2VsOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHhociA9IHNlbGYuYWpheFJlcXVlc3RzLCBsZW4gPSB4aHIubGVuZ3RoLCBpO1xuICAgICAgICAgICAgaWYgKGxlbiA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYW5jZWxsaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgeGhyW2ldLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3NDYW5jZWxsZWQoKTtcbiAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCBpbmQgPSAkdGh1bWIuYXR0cignZGF0YS1maWxlaW5kZXgnKTtcbiAgICAgICAgICAgICAgICAkdGh1bWIucmVtb3ZlQ2xhc3MoJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2luZF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5rdi1maWxlLXJlbW92ZScpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYudW5sb2NrKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBjbGVhcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBjYXA7XG4gICAgICAgICAgICBpZiAoIXNlbGYuX3JhaXNlKCdmaWxlY2xlYXInKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGJ0blVwbG9hZC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZmluZCgndmlkZW8sYXVkaW8saW1nJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgJGguY2xlYW5NZW1vcnkoJCh0aGlzKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0VXBsb2FkKCk7XG4gICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycyh0cnVlKTtcbiAgICAgICAgICAgIGlmIChzZWxmLl9oYXNJbml0aWFsUHJldmlldygpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0ZpbGVJY29uKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJPYmplY3RzKCQodGhpcykpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhID0ge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgY2FwID0gKCFzZWxmLm92ZXJ3cml0ZUluaXRpYWwgJiYgc2VsZi5pbml0aWFsQ2FwdGlvbi5sZW5ndGggPiAwKSA/IHNlbGYuaW5pdGlhbENhcHRpb24gOiAnJztcbiAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uLmh0bWwoY2FwKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uLmF0dHIoJ3RpdGxlJywgJycpO1xuICAgICAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRjb250YWluZXIsICdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlRGVmYXVsdFByZXZpZXcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLiRjb250YWluZXIuZmluZCgkaC5GUkFNRVMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5faW5pdENhcHRpb24oKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faGlkZUZpbGVJY29uKCk7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWNsZWFyZWQnKTtcbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZm9jdXMoKTtcbiAgICAgICAgICAgIHNlbGYuX3NldEZpbGVEcm9wWm9uZVRpdGxlKCk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgcmVzZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICghc2VsZi5fcmFpc2UoJ2ZpbGVyZXNldCcpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fcmVzZXRQcmV2aWV3KCk7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGVpbnB1dC1maWxlbmFtZScpLnRleHQoJycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICBpZiAoc2VsZi5nZXRGcmFtZXMoKS5sZW5ndGggfHwgc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRGaWxlRHJvcFpvbmVUaXRsZSgpO1xuICAgICAgICAgICAgc2VsZi5jbGVhclN0YWNrKCk7XG4gICAgICAgICAgICBzZWxmLmZvcm1kYXRhID0ge307XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgZGlzYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5pc0Rpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQuYXR0cignZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKFwiLmt2LWZpbGVpbnB1dC1jYXB0aW9uXCIpLmFkZENsYXNzKFwiZmlsZS1jYXB0aW9uLWRpc2FibGVkXCIpO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoXCIuYnRuLWZpbGUsIC5maWxlaW5wdXQtcmVtb3ZlLCAuZmlsZWlucHV0LXVwbG9hZCwgLmZpbGUtcHJldmlldy1mcmFtZSBidXR0b25cIilcbiAgICAgICAgICAgICAgICAuYXR0cihcImRpc2FibGVkXCIsIHRydWUpO1xuICAgICAgICAgICAgc2VsZi5faW5pdERyYWdEcm9wKCk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgZW5hYmxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmlzRGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlZW5hYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoXCIua3YtZmlsZWlucHV0LWNhcHRpb25cIikucmVtb3ZlQ2xhc3MoXCJmaWxlLWNhcHRpb24tZGlzYWJsZWRcIik7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZChcIi5idG4tZmlsZSwgLmZpbGVpbnB1dC1yZW1vdmUsIC5maWxlaW5wdXQtdXBsb2FkLCAuZmlsZS1wcmV2aWV3LWZyYW1lIGJ1dHRvblwiKVxuICAgICAgICAgICAgICAgIC5yZW1vdmVBdHRyKFwiZGlzYWJsZWRcIik7XG4gICAgICAgICAgICBzZWxmLl9pbml0RHJhZ0Ryb3AoKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICB1cGxvYWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdG90TGVuID0gc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGgsIGksIG91dERhdGEsIGxlbixcbiAgICAgICAgICAgICAgICBoYXNFeHRyYURhdGEgPSAhJC5pc0VtcHR5T2JqZWN0KHNlbGYuX2dldEV4dHJhRGF0YSgpKTtcbiAgICAgICAgICAgIGlmICghc2VsZi5pc1VwbG9hZGFibGUgfHwgc2VsZi5pc0Rpc2FibGVkIHx8ICFzZWxmLl9pc0ZpbGVTZWxlY3Rpb25WYWxpZCh0b3RMZW4pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIGlmICh0b3RMZW4gPT09IDAgJiYgIWhhc0V4dHJhRGF0YSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihzZWxmLm1zZ1VwbG9hZEVtcHR5KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRwcm9ncmVzcy5yZW1vdmVDbGFzcygnaGlkZScpO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRDb3VudCA9IDA7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1cyA9IHt9O1xuICAgICAgICAgICAgc2VsZi51cGxvYWRMb2cgPSBbXTtcbiAgICAgICAgICAgIHNlbGYubG9jaygpO1xuICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMik7XG4gICAgICAgICAgICBpZiAodG90TGVuID09PSAwICYmIGhhc0V4dHJhRGF0YSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3VwbG9hZEV4dHJhT25seSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxlbiA9IHNlbGYuZmlsZXN0YWNrLmxlbmd0aDtcbiAgICAgICAgICAgIHNlbGYuaGFzSW5pdERhdGEgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzZWxmLnVwbG9hZEFzeW5jKSB7XG4gICAgICAgICAgICAgICAgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNocHJldXBsb2FkJywgW291dERhdGFdKTtcbiAgICAgICAgICAgICAgICBzZWxmLmZpbGVCYXRjaENvbXBsZXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUgPSB7Y29udGVudDogW10sIGNvbmZpZzogW10sIHRhZ3M6IFtdLCBhcHBlbmQ6IHRydWV9O1xuICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQXN5bmNDb3VudCA9IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLmNvbnRlbnRbaV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLmNvbmZpZ1tpXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUudGFnc1tpXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuZmluZCgnLmZpbGUtcHJldmlldy1pbml0aWFsJykucmVtb3ZlQ2xhc3MoJGguU09SVF9DU1MpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2FjaGVJbml0aWFsUHJldmlldyA9IHNlbGYuZ2V0UHJldmlldygpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmZpbGVzdGFja1tpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGxvYWRTaW5nbGUoaSwgc2VsZi5maWxlc3RhY2ssIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3VwbG9hZEJhdGNoKCk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZm9ybSA9IHNlbGYuJGZvcm0sICRjb250ID0gc2VsZi4kY29udGFpbmVyLCAkZWwgPSBzZWxmLiRlbGVtZW50LCBucyA9IHNlbGYubmFtZXNwYWNlO1xuICAgICAgICAgICAgJChkb2N1bWVudCkub2ZmKG5zKTtcbiAgICAgICAgICAgICQod2luZG93KS5vZmYobnMpO1xuICAgICAgICAgICAgaWYgKCRmb3JtICYmICRmb3JtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICRmb3JtLm9mZihucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fY2xlYW51cCgpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdDYWNoZSgpO1xuICAgICAgICAgICAgJGVsLmluc2VydEJlZm9yZSgkY29udCkub2ZmKG5zKS5yZW1vdmVEYXRhKCk7XG4gICAgICAgICAgICAkY29udC5vZmYoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybiAkZWw7XG4gICAgICAgIH0sXG4gICAgICAgIHJlZnJlc2g6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyA/ICQuZXh0ZW5kKHRydWUsIHt9LCBzZWxmLm9wdGlvbnMsIG9wdGlvbnMpIDogc2VsZi5vcHRpb25zO1xuICAgICAgICAgICAgc2VsZi5kZXN0cm95KCk7XG4gICAgICAgICAgICAkZWwuZmlsZWlucHV0KG9wdGlvbnMpO1xuICAgICAgICAgICAgc2VsZiA9ICRlbC5kYXRhKCdmaWxlaW5wdXQnKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGVsLnZhbCgpKSB7XG4gICAgICAgICAgICAgICAgJGVsLnRyaWdnZXIoJ2NoYW5nZS5maWxlaW5wdXQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkZWw7XG4gICAgICAgIH0sXG4gICAgICAgIHpvb206IGZ1bmN0aW9uIChmcmFtZUlkKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRmcmFtZSA9IHNlbGYuX2dldEZyYW1lKGZyYW1lSWQpLCAkbW9kYWwgPSBzZWxmLiRtb2RhbDtcbiAgICAgICAgICAgIGlmICghJGZyYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguaW5pdE1vZGFsKCRtb2RhbCk7XG4gICAgICAgICAgICAkbW9kYWwuaHRtbChzZWxmLl9nZXRNb2RhbENvbnRlbnQoKSk7XG4gICAgICAgICAgICBzZWxmLl9zZXRab29tQ29udGVudCgkZnJhbWUpO1xuICAgICAgICAgICAgJG1vZGFsLm1vZGFsKCdzaG93Jyk7XG4gICAgICAgICAgICBzZWxmLl9pbml0Wm9vbUJ1dHRvbnMoKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RXhpZjogZnVuY3Rpb24gKGZyYW1lSWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gc2VsZi5fZ2V0RnJhbWUoZnJhbWVJZCk7XG4gICAgICAgICAgICByZXR1cm4gJGZyYW1lICYmICRmcmFtZS5kYXRhKCdleGlmJykgfHwgbnVsbDtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RnJhbWVzOiBmdW5jdGlvbiAoY3NzRmlsdGVyKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBjc3NGaWx0ZXIgPSBjc3NGaWx0ZXIgfHwgJyc7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kcHJldmlldy5maW5kKCRoLkZSQU1FUyArIGNzc0ZpbHRlcik7XG4gICAgICAgIH0sXG4gICAgICAgIGdldFByZXZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29udGVudDogc2VsZi5pbml0aWFsUHJldmlldyxcbiAgICAgICAgICAgICAgICBjb25maWc6IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcsXG4gICAgICAgICAgICAgICAgdGFnczogc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFnc1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dCA9IGZ1bmN0aW9uIChvcHRpb24pIHtcbiAgICAgICAgaWYgKCEkaC5oYXNGaWxlQVBJU3VwcG9ydCgpICYmICEkaC5pc0lFKDkpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5hcHBseShudWxsLCBhcmd1bWVudHMpLCByZXR2YWxzID0gW107XG4gICAgICAgIGFyZ3Muc2hpZnQoKTtcbiAgICAgICAgdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gJCh0aGlzKSwgZGF0YSA9IHNlbGYuZGF0YSgnZmlsZWlucHV0JyksIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09PSAnb2JqZWN0JyAmJiBvcHRpb24sXG4gICAgICAgICAgICAgICAgdGhlbWUgPSBvcHRpb25zLnRoZW1lIHx8IHNlbGYuZGF0YSgndGhlbWUnKSwgbCA9IHt9LCB0ID0ge30sXG4gICAgICAgICAgICAgICAgbGFuZyA9IG9wdGlvbnMubGFuZ3VhZ2UgfHwgc2VsZi5kYXRhKCdsYW5ndWFnZScpIHx8ICQuZm4uZmlsZWlucHV0LmRlZmF1bHRzLmxhbmd1YWdlIHx8ICdlbicsIG9wdDtcbiAgICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGVtZSkge1xuICAgICAgICAgICAgICAgICAgICB0ID0gJC5mbi5maWxlaW5wdXRUaGVtZXNbdGhlbWVdIHx8IHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobGFuZyAhPT0gJ2VuJyAmJiAhJGguaXNFbXB0eSgkLmZuLmZpbGVpbnB1dExvY2FsZXNbbGFuZ10pKSB7XG4gICAgICAgICAgICAgICAgICAgIGwgPSAkLmZuLmZpbGVpbnB1dExvY2FsZXNbbGFuZ10gfHwge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9wdCA9ICQuZXh0ZW5kKHRydWUsIHt9LCAkLmZuLmZpbGVpbnB1dC5kZWZhdWx0cywgdCwgJC5mbi5maWxlaW5wdXRMb2NhbGVzLmVuLCBsLCBvcHRpb25zLCBzZWxmLmRhdGEoKSk7XG4gICAgICAgICAgICAgICAgZGF0YSA9IG5ldyBGaWxlSW5wdXQodGhpcywgb3B0KTtcbiAgICAgICAgICAgICAgICBzZWxmLmRhdGEoJ2ZpbGVpbnB1dCcsIGRhdGEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXR2YWxzLnB1c2goZGF0YVtvcHRpb25dLmFwcGx5KGRhdGEsIGFyZ3MpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHN3aXRjaCAocmV0dmFscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dmFsc1swXTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJldHZhbHM7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgJC5mbi5maWxlaW5wdXQuZGVmYXVsdHMgPSB7XG4gICAgICAgIGxhbmd1YWdlOiAnZW4nLFxuICAgICAgICBzaG93Q2FwdGlvbjogdHJ1ZSxcbiAgICAgICAgc2hvd0Jyb3dzZTogdHJ1ZSxcbiAgICAgICAgc2hvd1ByZXZpZXc6IHRydWUsXG4gICAgICAgIHNob3dSZW1vdmU6IHRydWUsXG4gICAgICAgIHNob3dVcGxvYWQ6IHRydWUsXG4gICAgICAgIHNob3dDYW5jZWw6IHRydWUsXG4gICAgICAgIHNob3dDbG9zZTogdHJ1ZSxcbiAgICAgICAgc2hvd1VwbG9hZGVkVGh1bWJzOiB0cnVlLFxuICAgICAgICBicm93c2VPblpvbmVDbGljazogZmFsc2UsXG4gICAgICAgIGF1dG9SZXBsYWNlOiBmYWxzZSxcbiAgICAgICAgYXV0b09yaWVudEltYWdlOiB0cnVlLCAvLyBmb3IgSlBFRyBpbWFnZXMgYmFzZWQgb24gRVhJRiBvcmllbnRhdGlvbiB0YWdcbiAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgICBydGw6IGZhbHNlLFxuICAgICAgICBoaWRlVGh1bWJuYWlsQ29udGVudDogZmFsc2UsXG4gICAgICAgIGdlbmVyYXRlRmlsZUlkOiBudWxsLFxuICAgICAgICBwcmV2aWV3Q2xhc3M6ICcnLFxuICAgICAgICBjYXB0aW9uQ2xhc3M6ICcnLFxuICAgICAgICBmcmFtZUNsYXNzOiAna3JhamVlLWRlZmF1bHQnLFxuICAgICAgICBtYWluQ2xhc3M6ICdmaWxlLWNhcHRpb24tbWFpbicsXG4gICAgICAgIG1haW5UZW1wbGF0ZTogbnVsbCxcbiAgICAgICAgcHVyaWZ5SHRtbDogdHJ1ZSxcbiAgICAgICAgZmlsZVNpemVHZXR0ZXI6IG51bGwsXG4gICAgICAgIGluaXRpYWxDYXB0aW9uOiAnJyxcbiAgICAgICAgaW5pdGlhbFByZXZpZXc6IFtdLFxuICAgICAgICBpbml0aWFsUHJldmlld0RlbGltaXRlcjogJyokJConLFxuICAgICAgICBpbml0aWFsUHJldmlld0FzRGF0YTogZmFsc2UsXG4gICAgICAgIGluaXRpYWxQcmV2aWV3RmlsZVR5cGU6ICdpbWFnZScsXG4gICAgICAgIGluaXRpYWxQcmV2aWV3Q29uZmlnOiBbXSxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3M6IFtdLFxuICAgICAgICBwcmV2aWV3VGh1bWJUYWdzOiB7fSxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdTaG93RGVsZXRlOiB0cnVlLFxuICAgICAgICByZW1vdmVGcm9tUHJldmlld09uRXJyb3I6IGZhbHNlLFxuICAgICAgICBkZWxldGVVcmw6ICcnLFxuICAgICAgICBkZWxldGVFeHRyYURhdGE6IHt9LFxuICAgICAgICBvdmVyd3JpdGVJbml0aWFsOiB0cnVlLFxuICAgICAgICBwcmV2aWV3Wm9vbUJ1dHRvbkljb25zOiB7XG4gICAgICAgICAgICBwcmV2OiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXRyaWFuZ2xlLWxlZnRcIj48L2k+JyxcbiAgICAgICAgICAgIG5leHQ6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJpYW5nbGUtcmlnaHRcIj48L2k+JyxcbiAgICAgICAgICAgIHRvZ2dsZWhlYWRlcjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1yZXNpemUtdmVydGljYWxcIj48L2k+JyxcbiAgICAgICAgICAgIGZ1bGxzY3JlZW46ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tZnVsbHNjcmVlblwiPjwvaT4nLFxuICAgICAgICAgICAgYm9yZGVybGVzczogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1yZXNpemUtZnVsbFwiPjwvaT4nLFxuICAgICAgICAgICAgY2xvc2U6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tcmVtb3ZlXCI+PC9pPidcbiAgICAgICAgfSxcbiAgICAgICAgcHJldmlld1pvb21CdXR0b25DbGFzc2VzOiB7XG4gICAgICAgICAgICBwcmV2OiAnYnRuIGJ0bi1uYXZpZ2F0ZScsXG4gICAgICAgICAgICBuZXh0OiAnYnRuIGJ0bi1uYXZpZ2F0ZScsXG4gICAgICAgICAgICB0b2dnbGVoZWFkZXI6ICdidG4gYnRuLWRlZmF1bHQgYnRuLWhlYWRlci10b2dnbGUnLFxuICAgICAgICAgICAgZnVsbHNjcmVlbjogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgICAgICBib3JkZXJsZXNzOiAnYnRuIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgICAgIGNsb3NlOiAnYnRuIGJ0bi1kZWZhdWx0J1xuICAgICAgICB9LFxuICAgICAgICBwcmVmZXJJY29uaWNQcmV2aWV3OiBmYWxzZSxcbiAgICAgICAgcHJlZmVySWNvbmljWm9vbVByZXZpZXc6IGZhbHNlLFxuICAgICAgICBhbGxvd2VkUHJldmlld1R5cGVzOiB1bmRlZmluZWQsXG4gICAgICAgIGFsbG93ZWRQcmV2aWV3TWltZVR5cGVzOiBudWxsLFxuICAgICAgICBhbGxvd2VkRmlsZVR5cGVzOiBudWxsLFxuICAgICAgICBhbGxvd2VkRmlsZUV4dGVuc2lvbnM6IG51bGwsXG4gICAgICAgIGRlZmF1bHRQcmV2aWV3Q29udGVudDogbnVsbCxcbiAgICAgICAgY3VzdG9tTGF5b3V0VGFnczoge30sXG4gICAgICAgIGN1c3RvbVByZXZpZXdUYWdzOiB7fSxcbiAgICAgICAgcHJldmlld0ZpbGVJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWZpbGVcIj48L2k+JyxcbiAgICAgICAgcHJldmlld0ZpbGVJY29uQ2xhc3M6ICdmaWxlLW90aGVyLWljb24nLFxuICAgICAgICBwcmV2aWV3RmlsZUljb25TZXR0aW5nczoge30sXG4gICAgICAgIHByZXZpZXdGaWxlRXh0U2V0dGluZ3M6IHt9LFxuICAgICAgICBidXR0b25MYWJlbENsYXNzOiAnaGlkZGVuLXhzJyxcbiAgICAgICAgYnJvd3NlSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1mb2xkZXItb3BlblwiPjwvaT4mbmJzcDsnLFxuICAgICAgICBicm93c2VDbGFzczogJ2J0biBidG4tcHJpbWFyeScsXG4gICAgICAgIHJlbW92ZUljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJhc2hcIj48L2k+JyxcbiAgICAgICAgcmVtb3ZlQ2xhc3M6ICdidG4gYnRuLWRlZmF1bHQnLFxuICAgICAgICBjYW5jZWxJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWJhbi1jaXJjbGVcIj48L2k+JyxcbiAgICAgICAgY2FuY2VsQ2xhc3M6ICdidG4gYnRuLWRlZmF1bHQnLFxuICAgICAgICB1cGxvYWRJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXVwbG9hZFwiPjwvaT4nLFxuICAgICAgICB1cGxvYWRDbGFzczogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgIHVwbG9hZFVybDogbnVsbCxcbiAgICAgICAgdXBsb2FkQXN5bmM6IHRydWUsXG4gICAgICAgIHVwbG9hZEV4dHJhRGF0YToge30sXG4gICAgICAgIHpvb21Nb2RhbEhlaWdodDogNDgwLFxuICAgICAgICBtaW5JbWFnZVdpZHRoOiBudWxsLFxuICAgICAgICBtaW5JbWFnZUhlaWdodDogbnVsbCxcbiAgICAgICAgbWF4SW1hZ2VXaWR0aDogbnVsbCxcbiAgICAgICAgbWF4SW1hZ2VIZWlnaHQ6IG51bGwsXG4gICAgICAgIHJlc2l6ZUltYWdlOiBmYWxzZSxcbiAgICAgICAgcmVzaXplUHJlZmVyZW5jZTogJ3dpZHRoJyxcbiAgICAgICAgcmVzaXplUXVhbGl0eTogMC45MixcbiAgICAgICAgcmVzaXplRGVmYXVsdEltYWdlVHlwZTogJ2ltYWdlL2pwZWcnLFxuICAgICAgICByZXNpemVJZlNpemVNb3JlVGhhbjogMCwgLy8gaW4gS0JcbiAgICAgICAgbWluRmlsZVNpemU6IDAsXG4gICAgICAgIG1heEZpbGVTaXplOiAwLFxuICAgICAgICBtYXhGaWxlUHJldmlld1NpemU6IDI1NjAwLCAvLyAyNSBNQlxuICAgICAgICBtaW5GaWxlQ291bnQ6IDAsXG4gICAgICAgIG1heEZpbGVDb3VudDogMCxcbiAgICAgICAgdmFsaWRhdGVJbml0aWFsQ291bnQ6IGZhbHNlLFxuICAgICAgICBtc2dWYWxpZGF0aW9uRXJyb3JDbGFzczogJ3RleHQtZGFuZ2VyJyxcbiAgICAgICAgbXNnVmFsaWRhdGlvbkVycm9ySWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1leGNsYW1hdGlvbi1zaWduXCI+PC9pPiAnLFxuICAgICAgICBtc2dFcnJvckNsYXNzOiAnZmlsZS1lcnJvci1tZXNzYWdlJyxcbiAgICAgICAgcHJvZ3Jlc3NUaHVtYkNsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItc3VjY2VzcyBwcm9ncmVzcy1iYXItc3RyaXBlZCBhY3RpdmVcIixcbiAgICAgICAgcHJvZ3Jlc3NDbGFzczogXCJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3MgcHJvZ3Jlc3MtYmFyLXN0cmlwZWQgYWN0aXZlXCIsXG4gICAgICAgIHByb2dyZXNzQ29tcGxldGVDbGFzczogXCJwcm9ncmVzcy1iYXIgcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3NcIixcbiAgICAgICAgcHJvZ3Jlc3NFcnJvckNsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItZGFuZ2VyXCIsXG4gICAgICAgIHByb2dyZXNzVXBsb2FkVGhyZXNob2xkOiA5OSxcbiAgICAgICAgcHJldmlld0ZpbGVUeXBlOiAnaW1hZ2UnLFxuICAgICAgICBlbENhcHRpb25Db250YWluZXI6IG51bGwsXG4gICAgICAgIGVsQ2FwdGlvblRleHQ6IG51bGwsXG4gICAgICAgIGVsUHJldmlld0NvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgZWxQcmV2aWV3SW1hZ2U6IG51bGwsXG4gICAgICAgIGVsUHJldmlld1N0YXR1czogbnVsbCxcbiAgICAgICAgZWxFcnJvckNvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgZXJyb3JDbG9zZUJ1dHRvbjogJzxzcGFuIGNsYXNzPVwiY2xvc2Uga3YtZXJyb3ItY2xvc2VcIj4mdGltZXM7PC9zcGFuPicsXG4gICAgICAgIHNsdWdDYWxsYmFjazogbnVsbCxcbiAgICAgICAgZHJvcFpvbmVFbmFibGVkOiB0cnVlLFxuICAgICAgICBkcm9wWm9uZVRpdGxlQ2xhc3M6ICdmaWxlLWRyb3Atem9uZS10aXRsZScsXG4gICAgICAgIGZpbGVBY3Rpb25TZXR0aW5nczoge30sXG4gICAgICAgIG90aGVyQWN0aW9uQnV0dG9uczogJycsXG4gICAgICAgIHRleHRFbmNvZGluZzogJ1VURi04JyxcbiAgICAgICAgYWpheFNldHRpbmdzOiB7fSxcbiAgICAgICAgYWpheERlbGV0ZVNldHRpbmdzOiB7fSxcbiAgICAgICAgc2hvd0FqYXhFcnJvckRldGFpbHM6IHRydWVcbiAgICB9O1xuXG4gICAgJC5mbi5maWxlaW5wdXRMb2NhbGVzLmVuID0ge1xuICAgICAgICBmaWxlU2luZ2xlOiAnZmlsZScsXG4gICAgICAgIGZpbGVQbHVyYWw6ICdmaWxlcycsXG4gICAgICAgIGJyb3dzZUxhYmVsOiAnQnJvd3NlICZoZWxsaXA7JyxcbiAgICAgICAgcmVtb3ZlTGFiZWw6ICdSZW1vdmUnLFxuICAgICAgICByZW1vdmVUaXRsZTogJ0NsZWFyIHNlbGVjdGVkIGZpbGVzJyxcbiAgICAgICAgY2FuY2VsTGFiZWw6ICdDYW5jZWwnLFxuICAgICAgICBjYW5jZWxUaXRsZTogJ0Fib3J0IG9uZ29pbmcgdXBsb2FkJyxcbiAgICAgICAgdXBsb2FkTGFiZWw6ICdVcGxvYWQnLFxuICAgICAgICB1cGxvYWRUaXRsZTogJ1VwbG9hZCBzZWxlY3RlZCBmaWxlcycsXG4gICAgICAgIG1zZ05vOiAnTm8nLFxuICAgICAgICBtc2dOb0ZpbGVzU2VsZWN0ZWQ6ICdObyBmaWxlcyBzZWxlY3RlZCcsXG4gICAgICAgIG1zZ0NhbmNlbGxlZDogJ0NhbmNlbGxlZCcsXG4gICAgICAgIG1zZ1pvb21Nb2RhbEhlYWRpbmc6ICdEZXRhaWxlZCBQcmV2aWV3JyxcbiAgICAgICAgbXNnRmlsZVJlcXVpcmVkOiAnWW91IG11c3Qgc2VsZWN0IGEgZmlsZSB0byB1cGxvYWQuJyxcbiAgICAgICAgbXNnU2l6ZVRvb1NtYWxsOiAnRmlsZSBcIntuYW1lfVwiICg8Yj57c2l6ZX0gS0I8L2I+KSBpcyB0b28gc21hbGwgYW5kIG11c3QgYmUgbGFyZ2VyIHRoYW4gPGI+e21pblNpemV9IEtCPC9iPi4nLFxuICAgICAgICBtc2dTaXplVG9vTGFyZ2U6ICdGaWxlIFwie25hbWV9XCIgKDxiPntzaXplfSBLQjwvYj4pIGV4Y2VlZHMgbWF4aW11bSBhbGxvd2VkIHVwbG9hZCBzaXplIG9mIDxiPnttYXhTaXplfSBLQjwvYj4uJyxcbiAgICAgICAgbXNnRmlsZXNUb29MZXNzOiAnWW91IG11c3Qgc2VsZWN0IGF0IGxlYXN0IDxiPntufTwvYj4ge2ZpbGVzfSB0byB1cGxvYWQuJyxcbiAgICAgICAgbXNnRmlsZXNUb29NYW55OiAnTnVtYmVyIG9mIGZpbGVzIHNlbGVjdGVkIGZvciB1cGxvYWQgPGI+KHtufSk8L2I+IGV4Y2VlZHMgbWF4aW11bSBhbGxvd2VkIGxpbWl0IG9mIDxiPnttfTwvYj4uJyxcbiAgICAgICAgbXNnRmlsZU5vdEZvdW5kOiAnRmlsZSBcIntuYW1lfVwiIG5vdCBmb3VuZCEnLFxuICAgICAgICBtc2dGaWxlU2VjdXJlZDogJ1NlY3VyaXR5IHJlc3RyaWN0aW9ucyBwcmV2ZW50IHJlYWRpbmcgdGhlIGZpbGUgXCJ7bmFtZX1cIi4nLFxuICAgICAgICBtc2dGaWxlTm90UmVhZGFibGU6ICdGaWxlIFwie25hbWV9XCIgaXMgbm90IHJlYWRhYmxlLicsXG4gICAgICAgIG1zZ0ZpbGVQcmV2aWV3QWJvcnRlZDogJ0ZpbGUgcHJldmlldyBhYm9ydGVkIGZvciBcIntuYW1lfVwiLicsXG4gICAgICAgIG1zZ0ZpbGVQcmV2aWV3RXJyb3I6ICdBbiBlcnJvciBvY2N1cnJlZCB3aGlsZSByZWFkaW5nIHRoZSBmaWxlIFwie25hbWV9XCIuJyxcbiAgICAgICAgbXNnSW52YWxpZEZpbGVOYW1lOiAnSW52YWxpZCBvciB1bnN1cHBvcnRlZCBjaGFyYWN0ZXJzIGluIGZpbGUgbmFtZSBcIntuYW1lfVwiLicsXG4gICAgICAgIG1zZ0ludmFsaWRGaWxlVHlwZTogJ0ludmFsaWQgdHlwZSBmb3IgZmlsZSBcIntuYW1lfVwiLiBPbmx5IFwie3R5cGVzfVwiIGZpbGVzIGFyZSBzdXBwb3J0ZWQuJyxcbiAgICAgICAgbXNnSW52YWxpZEZpbGVFeHRlbnNpb246ICdJbnZhbGlkIGV4dGVuc2lvbiBmb3IgZmlsZSBcIntuYW1lfVwiLiBPbmx5IFwie2V4dGVuc2lvbnN9XCIgZmlsZXMgYXJlIHN1cHBvcnRlZC4nLFxuICAgICAgICBtc2dGaWxlVHlwZXM6IHtcbiAgICAgICAgICAgICdpbWFnZSc6ICdpbWFnZScsXG4gICAgICAgICAgICAnaHRtbCc6ICdIVE1MJyxcbiAgICAgICAgICAgICd0ZXh0JzogJ3RleHQnLFxuICAgICAgICAgICAgJ3ZpZGVvJzogJ3ZpZGVvJyxcbiAgICAgICAgICAgICdhdWRpbyc6ICdhdWRpbycsXG4gICAgICAgICAgICAnZmxhc2gnOiAnZmxhc2gnLFxuICAgICAgICAgICAgJ3BkZic6ICdQREYnLFxuICAgICAgICAgICAgJ29iamVjdCc6ICdvYmplY3QnXG4gICAgICAgIH0sXG4gICAgICAgIG1zZ1VwbG9hZEFib3J0ZWQ6ICdUaGUgZmlsZSB1cGxvYWQgd2FzIGFib3J0ZWQnLFxuICAgICAgICBtc2dVcGxvYWRUaHJlc2hvbGQ6ICdQcm9jZXNzaW5nLi4uJyxcbiAgICAgICAgbXNnVXBsb2FkQmVnaW46ICdJbml0aWFsaXppbmcuLi4nLFxuICAgICAgICBtc2dVcGxvYWRFbmQ6ICdEb25lJyxcbiAgICAgICAgbXNnVXBsb2FkRW1wdHk6ICdObyB2YWxpZCBkYXRhIGF2YWlsYWJsZSBmb3IgdXBsb2FkLicsXG4gICAgICAgIG1zZ1ZhbGlkYXRpb25FcnJvcjogJ1ZhbGlkYXRpb24gRXJyb3InLFxuICAgICAgICBtc2dMb2FkaW5nOiAnTG9hZGluZyBmaWxlIHtpbmRleH0gb2Yge2ZpbGVzfSAmaGVsbGlwOycsXG4gICAgICAgIG1zZ1Byb2dyZXNzOiAnTG9hZGluZyBmaWxlIHtpbmRleH0gb2Yge2ZpbGVzfSAtIHtuYW1lfSAtIHtwZXJjZW50fSUgY29tcGxldGVkLicsXG4gICAgICAgIG1zZ1NlbGVjdGVkOiAne259IHtmaWxlc30gc2VsZWN0ZWQnLFxuICAgICAgICBtc2dGb2xkZXJzTm90QWxsb3dlZDogJ0RyYWcgJiBkcm9wIGZpbGVzIG9ubHkhIHtufSBmb2xkZXIocykgZHJvcHBlZCB3ZXJlIHNraXBwZWQuJyxcbiAgICAgICAgbXNnSW1hZ2VXaWR0aFNtYWxsOiAnV2lkdGggb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIG11c3QgYmUgYXQgbGVhc3Qge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlSGVpZ2h0U21hbGw6ICdIZWlnaHQgb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIG11c3QgYmUgYXQgbGVhc3Qge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlV2lkdGhMYXJnZTogJ1dpZHRoIG9mIGltYWdlIGZpbGUgXCJ7bmFtZX1cIiBjYW5ub3QgZXhjZWVkIHtzaXplfSBweC4nLFxuICAgICAgICBtc2dJbWFnZUhlaWdodExhcmdlOiAnSGVpZ2h0IG9mIGltYWdlIGZpbGUgXCJ7bmFtZX1cIiBjYW5ub3QgZXhjZWVkIHtzaXplfSBweC4nLFxuICAgICAgICBtc2dJbWFnZVJlc2l6ZUVycm9yOiAnQ291bGQgbm90IGdldCB0aGUgaW1hZ2UgZGltZW5zaW9ucyB0byByZXNpemUuJyxcbiAgICAgICAgbXNnSW1hZ2VSZXNpemVFeGNlcHRpb246ICdFcnJvciB3aGlsZSByZXNpemluZyB0aGUgaW1hZ2UuPHByZT57ZXJyb3JzfTwvcHJlPicsXG4gICAgICAgIG1zZ0FqYXhFcnJvcjogJ1NvbWV0aGluZyB3ZW50IHdyb25nIHdpdGggdGhlIHtvcGVyYXRpb259IG9wZXJhdGlvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlciEnLFxuICAgICAgICBtc2dBamF4UHJvZ3Jlc3NFcnJvcjogJ3tvcGVyYXRpb259IGZhaWxlZCcsXG4gICAgICAgIGFqYXhPcGVyYXRpb25zOiB7XG4gICAgICAgICAgICBkZWxldGVUaHVtYjogJ2ZpbGUgZGVsZXRlJyxcbiAgICAgICAgICAgIHVwbG9hZFRodW1iOiAnZmlsZSB1cGxvYWQnLFxuICAgICAgICAgICAgdXBsb2FkQmF0Y2g6ICdiYXRjaCBmaWxlIHVwbG9hZCcsXG4gICAgICAgICAgICB1cGxvYWRFeHRyYTogJ2Zvcm0gZGF0YSB1cGxvYWQnXG4gICAgICAgIH0sXG4gICAgICAgIGRyb3Bab25lVGl0bGU6ICdEcmFnICYgZHJvcCBmaWxlcyBoZXJlICZoZWxsaXA7JyxcbiAgICAgICAgZHJvcFpvbmVDbGlja1RpdGxlOiAnPGJyPihvciBjbGljayB0byBzZWxlY3Qge2ZpbGVzfSknLFxuICAgICAgICBwcmV2aWV3Wm9vbUJ1dHRvblRpdGxlczoge1xuICAgICAgICAgICAgcHJldjogJ1ZpZXcgcHJldmlvdXMgZmlsZScsXG4gICAgICAgICAgICBuZXh0OiAnVmlldyBuZXh0IGZpbGUnLFxuICAgICAgICAgICAgdG9nZ2xlaGVhZGVyOiAnVG9nZ2xlIGhlYWRlcicsXG4gICAgICAgICAgICBmdWxsc2NyZWVuOiAnVG9nZ2xlIGZ1bGwgc2NyZWVuJyxcbiAgICAgICAgICAgIGJvcmRlcmxlc3M6ICdUb2dnbGUgYm9yZGVybGVzcyBtb2RlJyxcbiAgICAgICAgICAgIGNsb3NlOiAnQ2xvc2UgZGV0YWlsZWQgcHJldmlldydcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dC5Db25zdHJ1Y3RvciA9IEZpbGVJbnB1dDtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgYXV0b21hdGljYWxseSBmaWxlIGlucHV0cyB3aXRoIGNsYXNzICdmaWxlJyBpbnRvIGEgYm9vdHN0cmFwIGZpbGVpbnB1dCBjb250cm9sLlxuICAgICAqL1xuICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRpbnB1dCA9ICQoJ2lucHV0LmZpbGVbdHlwZT1maWxlXScpO1xuICAgICAgICBpZiAoJGlucHV0Lmxlbmd0aCkge1xuICAgICAgICAgICAgJGlucHV0LmZpbGVpbnB1dCgpO1xuICAgICAgICB9XG4gICAgfSk7XG59KSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLWZpbGVpbnB1dC9qcy9maWxlaW5wdXQuanNcbi8vIG1vZHVsZSBpZCA9IDdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9jc3MvYm9vdHN0cmFwLmNzc1xuLy8gbW9kdWxlIGlkID0gOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1zZWxlY3QvZGlzdC9jc3MvYm9vdHN0cmFwLXNlbGVjdC5jc3Ncbi8vIG1vZHVsZSBpZCA9IDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2Nzcy9maWxlaW5wdXQuY3NzXG4vLyBtb2R1bGUgaWQgPSAxMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vc3JjL3N0eWxlLmNzc1xuLy8gbW9kdWxlIGlkID0gMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sInNvdXJjZVJvb3QiOiIifQ==