main.bundle.js 1.9 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295
  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__fortawesome_fontawesome_free_css_all_css__ = __webpack_require__(11);
  8413. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__fortawesome_fontawesome_free_css_all_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8__fortawesome_fontawesome_free_css_all_css__);
  8414. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__style_css__ = __webpack_require__(12);
  8415. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__style_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_9__style_css__);
  8416. // Javascript
  8417. // CSS
  8418. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(function () {
  8419. __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#myInput").on("keyup", function(eventObject) {
  8420. var input, filter, ul, li, a, i;
  8421. input = eventObject.currentTarget;
  8422. filter = input.value.toUpperCase();
  8423. ul = document.getElementById("myUL");
  8424. li = ul.getElementsByTagName('a');
  8425. // Loop through all list items, and hide those who don't match the search query
  8426. for (i = 0; i < li.length; i++) {
  8427. a = li[i]; //li[i].getElementsByTagName("a")[0];
  8428. if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
  8429. li[i].style.display = "";
  8430. } else {
  8431. li[i].style.display = "none";
  8432. }
  8433. }
  8434. });
  8435. function checkUsernameInputHandler(eventObject) {
  8436. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8437. var data = JSON.stringify({"username": input_el.val()});
  8438. var url = `/teachers/check_username/${input_el.val()}`
  8439. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8440. url,
  8441. data,
  8442. function(result) {
  8443. if (result.exists) {
  8444. console.log("Username exists");
  8445. }
  8446. },
  8447. "json"
  8448. );
  8449. }
  8450. function usernameGenerator(eventObject, firstname, surname) {
  8451. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8452. input_el.val(firstname+"."+surname);
  8453. }
  8454. function deleteRelationHandler(eventObject) {
  8455. var url = this.dataset.url;
  8456. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8457. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8458. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8459. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8460. url: url,
  8461. type: 'DELETE',
  8462. success: function(result) {
  8463. el.closest(".list-group-item").remove();
  8464. modalEl.modal('hide');
  8465. }
  8466. });
  8467. });
  8468. return false;
  8469. };
  8470. function deleteHandler(eventObject) {
  8471. var url = this.dataset.url;
  8472. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8473. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8474. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8475. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8476. url: url,
  8477. type: 'DELETE',
  8478. success: function(result) {
  8479. modalEl.modal('hide');
  8480. window.location.replace(result.redirect_url);
  8481. }
  8482. });
  8483. });
  8484. return false;
  8485. };
  8486. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".ajax-post").on("click", function(eventObject) {
  8487. var select_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.select).first();
  8488. var listgroup_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.listgroup).first();
  8489. var url = this.dataset.url;
  8490. var data = JSON.stringify({"ids": select_el.val()});
  8491. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8492. url,
  8493. data,
  8494. function(result) {
  8495. var i;
  8496. if (result.elements != null) {
  8497. for (i = 0; i < result.elements.length; i++) {
  8498. var newItem = `
  8499. <a href="#" class="list-group-item clearfix">
  8500. <span class="glyphicon glyphicon-book"></span>
  8501. ${result.elements[i].Name}
  8502. <span class="pull-right">
  8503. <button data-url="/${result.name1}/${result.id1}/${result.name2}/${result.id2[i]}/delete" class="btn btn-xs btn-warning karmen-ajax-delete">
  8504. <span class="glyphicon glyphicon-trash"></span>
  8505. </button>
  8506. </span>
  8507. `;
  8508. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(listgroup_el).append(newItem);
  8509. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8510. }
  8511. }
  8512. },
  8513. "json"
  8514. );
  8515. select_el.val('default');
  8516. select_el.selectpicker("refresh");
  8517. return false;
  8518. });
  8519. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete-relation").on("click", deleteRelationHandler);
  8520. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8521. });
  8522. /***/ }),
  8523. /* 2 */
  8524. /***/ (function(module, exports, __webpack_require__) {
  8525. /*!
  8526. * Bootstrap v4.1.3 (https://getbootstrap.com/)
  8527. * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  8528. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8529. */
  8530. (function (global, factory) {
  8531. true ? factory(exports, __webpack_require__(0), __webpack_require__(3)) :
  8532. typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :
  8533. (factory((global.bootstrap = {}),global.jQuery,global.Popper));
  8534. }(this, (function (exports,$,Popper) { 'use strict';
  8535. $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
  8536. Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;
  8537. function _defineProperties(target, props) {
  8538. for (var i = 0; i < props.length; i++) {
  8539. var descriptor = props[i];
  8540. descriptor.enumerable = descriptor.enumerable || false;
  8541. descriptor.configurable = true;
  8542. if ("value" in descriptor) descriptor.writable = true;
  8543. Object.defineProperty(target, descriptor.key, descriptor);
  8544. }
  8545. }
  8546. function _createClass(Constructor, protoProps, staticProps) {
  8547. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  8548. if (staticProps) _defineProperties(Constructor, staticProps);
  8549. return Constructor;
  8550. }
  8551. function _defineProperty(obj, key, value) {
  8552. if (key in obj) {
  8553. Object.defineProperty(obj, key, {
  8554. value: value,
  8555. enumerable: true,
  8556. configurable: true,
  8557. writable: true
  8558. });
  8559. } else {
  8560. obj[key] = value;
  8561. }
  8562. return obj;
  8563. }
  8564. function _objectSpread(target) {
  8565. for (var i = 1; i < arguments.length; i++) {
  8566. var source = arguments[i] != null ? arguments[i] : {};
  8567. var ownKeys = Object.keys(source);
  8568. if (typeof Object.getOwnPropertySymbols === 'function') {
  8569. ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
  8570. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  8571. }));
  8572. }
  8573. ownKeys.forEach(function (key) {
  8574. _defineProperty(target, key, source[key]);
  8575. });
  8576. }
  8577. return target;
  8578. }
  8579. function _inheritsLoose(subClass, superClass) {
  8580. subClass.prototype = Object.create(superClass.prototype);
  8581. subClass.prototype.constructor = subClass;
  8582. subClass.__proto__ = superClass;
  8583. }
  8584. /**
  8585. * --------------------------------------------------------------------------
  8586. * Bootstrap (v4.1.3): util.js
  8587. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8588. * --------------------------------------------------------------------------
  8589. */
  8590. var Util = function ($$$1) {
  8591. /**
  8592. * ------------------------------------------------------------------------
  8593. * Private TransitionEnd Helpers
  8594. * ------------------------------------------------------------------------
  8595. */
  8596. var TRANSITION_END = 'transitionend';
  8597. var MAX_UID = 1000000;
  8598. var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
  8599. function toType(obj) {
  8600. return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
  8601. }
  8602. function getSpecialTransitionEndEvent() {
  8603. return {
  8604. bindType: TRANSITION_END,
  8605. delegateType: TRANSITION_END,
  8606. handle: function handle(event) {
  8607. if ($$$1(event.target).is(this)) {
  8608. return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
  8609. }
  8610. return undefined; // eslint-disable-line no-undefined
  8611. }
  8612. };
  8613. }
  8614. function transitionEndEmulator(duration) {
  8615. var _this = this;
  8616. var called = false;
  8617. $$$1(this).one(Util.TRANSITION_END, function () {
  8618. called = true;
  8619. });
  8620. setTimeout(function () {
  8621. if (!called) {
  8622. Util.triggerTransitionEnd(_this);
  8623. }
  8624. }, duration);
  8625. return this;
  8626. }
  8627. function setTransitionEndSupport() {
  8628. $$$1.fn.emulateTransitionEnd = transitionEndEmulator;
  8629. $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
  8630. }
  8631. /**
  8632. * --------------------------------------------------------------------------
  8633. * Public Util Api
  8634. * --------------------------------------------------------------------------
  8635. */
  8636. var Util = {
  8637. TRANSITION_END: 'bsTransitionEnd',
  8638. getUID: function getUID(prefix) {
  8639. do {
  8640. // eslint-disable-next-line no-bitwise
  8641. prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
  8642. } while (document.getElementById(prefix));
  8643. return prefix;
  8644. },
  8645. getSelectorFromElement: function getSelectorFromElement(element) {
  8646. var selector = element.getAttribute('data-target');
  8647. if (!selector || selector === '#') {
  8648. selector = element.getAttribute('href') || '';
  8649. }
  8650. try {
  8651. return document.querySelector(selector) ? selector : null;
  8652. } catch (err) {
  8653. return null;
  8654. }
  8655. },
  8656. getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {
  8657. if (!element) {
  8658. return 0;
  8659. } // Get transition-duration of the element
  8660. var transitionDuration = $$$1(element).css('transition-duration');
  8661. var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found
  8662. if (!floatTransitionDuration) {
  8663. return 0;
  8664. } // If multiple durations are defined, take the first
  8665. transitionDuration = transitionDuration.split(',')[0];
  8666. return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER;
  8667. },
  8668. reflow: function reflow(element) {
  8669. return element.offsetHeight;
  8670. },
  8671. triggerTransitionEnd: function triggerTransitionEnd(element) {
  8672. $$$1(element).trigger(TRANSITION_END);
  8673. },
  8674. // TODO: Remove in v5
  8675. supportsTransitionEnd: function supportsTransitionEnd() {
  8676. return Boolean(TRANSITION_END);
  8677. },
  8678. isElement: function isElement(obj) {
  8679. return (obj[0] || obj).nodeType;
  8680. },
  8681. typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
  8682. for (var property in configTypes) {
  8683. if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
  8684. var expectedTypes = configTypes[property];
  8685. var value = config[property];
  8686. var valueType = value && Util.isElement(value) ? 'element' : toType(value);
  8687. if (!new RegExp(expectedTypes).test(valueType)) {
  8688. throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
  8689. }
  8690. }
  8691. }
  8692. }
  8693. };
  8694. setTransitionEndSupport();
  8695. return Util;
  8696. }($);
  8697. /**
  8698. * --------------------------------------------------------------------------
  8699. * Bootstrap (v4.1.3): alert.js
  8700. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8701. * --------------------------------------------------------------------------
  8702. */
  8703. var Alert = function ($$$1) {
  8704. /**
  8705. * ------------------------------------------------------------------------
  8706. * Constants
  8707. * ------------------------------------------------------------------------
  8708. */
  8709. var NAME = 'alert';
  8710. var VERSION = '4.1.3';
  8711. var DATA_KEY = 'bs.alert';
  8712. var EVENT_KEY = "." + DATA_KEY;
  8713. var DATA_API_KEY = '.data-api';
  8714. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8715. var Selector = {
  8716. DISMISS: '[data-dismiss="alert"]'
  8717. };
  8718. var Event = {
  8719. CLOSE: "close" + EVENT_KEY,
  8720. CLOSED: "closed" + EVENT_KEY,
  8721. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  8722. };
  8723. var ClassName = {
  8724. ALERT: 'alert',
  8725. FADE: 'fade',
  8726. SHOW: 'show'
  8727. /**
  8728. * ------------------------------------------------------------------------
  8729. * Class Definition
  8730. * ------------------------------------------------------------------------
  8731. */
  8732. };
  8733. var Alert =
  8734. /*#__PURE__*/
  8735. function () {
  8736. function Alert(element) {
  8737. this._element = element;
  8738. } // Getters
  8739. var _proto = Alert.prototype;
  8740. // Public
  8741. _proto.close = function close(element) {
  8742. var rootElement = this._element;
  8743. if (element) {
  8744. rootElement = this._getRootElement(element);
  8745. }
  8746. var customEvent = this._triggerCloseEvent(rootElement);
  8747. if (customEvent.isDefaultPrevented()) {
  8748. return;
  8749. }
  8750. this._removeElement(rootElement);
  8751. };
  8752. _proto.dispose = function dispose() {
  8753. $$$1.removeData(this._element, DATA_KEY);
  8754. this._element = null;
  8755. }; // Private
  8756. _proto._getRootElement = function _getRootElement(element) {
  8757. var selector = Util.getSelectorFromElement(element);
  8758. var parent = false;
  8759. if (selector) {
  8760. parent = document.querySelector(selector);
  8761. }
  8762. if (!parent) {
  8763. parent = $$$1(element).closest("." + ClassName.ALERT)[0];
  8764. }
  8765. return parent;
  8766. };
  8767. _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
  8768. var closeEvent = $$$1.Event(Event.CLOSE);
  8769. $$$1(element).trigger(closeEvent);
  8770. return closeEvent;
  8771. };
  8772. _proto._removeElement = function _removeElement(element) {
  8773. var _this = this;
  8774. $$$1(element).removeClass(ClassName.SHOW);
  8775. if (!$$$1(element).hasClass(ClassName.FADE)) {
  8776. this._destroyElement(element);
  8777. return;
  8778. }
  8779. var transitionDuration = Util.getTransitionDurationFromElement(element);
  8780. $$$1(element).one(Util.TRANSITION_END, function (event) {
  8781. return _this._destroyElement(element, event);
  8782. }).emulateTransitionEnd(transitionDuration);
  8783. };
  8784. _proto._destroyElement = function _destroyElement(element) {
  8785. $$$1(element).detach().trigger(Event.CLOSED).remove();
  8786. }; // Static
  8787. Alert._jQueryInterface = function _jQueryInterface(config) {
  8788. return this.each(function () {
  8789. var $element = $$$1(this);
  8790. var data = $element.data(DATA_KEY);
  8791. if (!data) {
  8792. data = new Alert(this);
  8793. $element.data(DATA_KEY, data);
  8794. }
  8795. if (config === 'close') {
  8796. data[config](this);
  8797. }
  8798. });
  8799. };
  8800. Alert._handleDismiss = function _handleDismiss(alertInstance) {
  8801. return function (event) {
  8802. if (event) {
  8803. event.preventDefault();
  8804. }
  8805. alertInstance.close(this);
  8806. };
  8807. };
  8808. _createClass(Alert, null, [{
  8809. key: "VERSION",
  8810. get: function get() {
  8811. return VERSION;
  8812. }
  8813. }]);
  8814. return Alert;
  8815. }();
  8816. /**
  8817. * ------------------------------------------------------------------------
  8818. * Data Api implementation
  8819. * ------------------------------------------------------------------------
  8820. */
  8821. $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
  8822. /**
  8823. * ------------------------------------------------------------------------
  8824. * jQuery
  8825. * ------------------------------------------------------------------------
  8826. */
  8827. $$$1.fn[NAME] = Alert._jQueryInterface;
  8828. $$$1.fn[NAME].Constructor = Alert;
  8829. $$$1.fn[NAME].noConflict = function () {
  8830. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  8831. return Alert._jQueryInterface;
  8832. };
  8833. return Alert;
  8834. }($);
  8835. /**
  8836. * --------------------------------------------------------------------------
  8837. * Bootstrap (v4.1.3): button.js
  8838. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8839. * --------------------------------------------------------------------------
  8840. */
  8841. var Button = function ($$$1) {
  8842. /**
  8843. * ------------------------------------------------------------------------
  8844. * Constants
  8845. * ------------------------------------------------------------------------
  8846. */
  8847. var NAME = 'button';
  8848. var VERSION = '4.1.3';
  8849. var DATA_KEY = 'bs.button';
  8850. var EVENT_KEY = "." + DATA_KEY;
  8851. var DATA_API_KEY = '.data-api';
  8852. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8853. var ClassName = {
  8854. ACTIVE: 'active',
  8855. BUTTON: 'btn',
  8856. FOCUS: 'focus'
  8857. };
  8858. var Selector = {
  8859. DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
  8860. DATA_TOGGLE: '[data-toggle="buttons"]',
  8861. INPUT: 'input',
  8862. ACTIVE: '.active',
  8863. BUTTON: '.btn'
  8864. };
  8865. var Event = {
  8866. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
  8867. FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY)
  8868. /**
  8869. * ------------------------------------------------------------------------
  8870. * Class Definition
  8871. * ------------------------------------------------------------------------
  8872. */
  8873. };
  8874. var Button =
  8875. /*#__PURE__*/
  8876. function () {
  8877. function Button(element) {
  8878. this._element = element;
  8879. } // Getters
  8880. var _proto = Button.prototype;
  8881. // Public
  8882. _proto.toggle = function toggle() {
  8883. var triggerChangeEvent = true;
  8884. var addAriaPressed = true;
  8885. var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0];
  8886. if (rootElement) {
  8887. var input = this._element.querySelector(Selector.INPUT);
  8888. if (input) {
  8889. if (input.type === 'radio') {
  8890. if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) {
  8891. triggerChangeEvent = false;
  8892. } else {
  8893. var activeElement = rootElement.querySelector(Selector.ACTIVE);
  8894. if (activeElement) {
  8895. $$$1(activeElement).removeClass(ClassName.ACTIVE);
  8896. }
  8897. }
  8898. }
  8899. if (triggerChangeEvent) {
  8900. if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {
  8901. return;
  8902. }
  8903. input.checked = !this._element.classList.contains(ClassName.ACTIVE);
  8904. $$$1(input).trigger('change');
  8905. }
  8906. input.focus();
  8907. addAriaPressed = false;
  8908. }
  8909. }
  8910. if (addAriaPressed) {
  8911. this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE));
  8912. }
  8913. if (triggerChangeEvent) {
  8914. $$$1(this._element).toggleClass(ClassName.ACTIVE);
  8915. }
  8916. };
  8917. _proto.dispose = function dispose() {
  8918. $$$1.removeData(this._element, DATA_KEY);
  8919. this._element = null;
  8920. }; // Static
  8921. Button._jQueryInterface = function _jQueryInterface(config) {
  8922. return this.each(function () {
  8923. var data = $$$1(this).data(DATA_KEY);
  8924. if (!data) {
  8925. data = new Button(this);
  8926. $$$1(this).data(DATA_KEY, data);
  8927. }
  8928. if (config === 'toggle') {
  8929. data[config]();
  8930. }
  8931. });
  8932. };
  8933. _createClass(Button, null, [{
  8934. key: "VERSION",
  8935. get: function get() {
  8936. return VERSION;
  8937. }
  8938. }]);
  8939. return Button;
  8940. }();
  8941. /**
  8942. * ------------------------------------------------------------------------
  8943. * Data Api implementation
  8944. * ------------------------------------------------------------------------
  8945. */
  8946. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
  8947. event.preventDefault();
  8948. var button = event.target;
  8949. if (!$$$1(button).hasClass(ClassName.BUTTON)) {
  8950. button = $$$1(button).closest(Selector.BUTTON);
  8951. }
  8952. Button._jQueryInterface.call($$$1(button), 'toggle');
  8953. }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
  8954. var button = $$$1(event.target).closest(Selector.BUTTON)[0];
  8955. $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
  8956. });
  8957. /**
  8958. * ------------------------------------------------------------------------
  8959. * jQuery
  8960. * ------------------------------------------------------------------------
  8961. */
  8962. $$$1.fn[NAME] = Button._jQueryInterface;
  8963. $$$1.fn[NAME].Constructor = Button;
  8964. $$$1.fn[NAME].noConflict = function () {
  8965. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  8966. return Button._jQueryInterface;
  8967. };
  8968. return Button;
  8969. }($);
  8970. /**
  8971. * --------------------------------------------------------------------------
  8972. * Bootstrap (v4.1.3): carousel.js
  8973. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8974. * --------------------------------------------------------------------------
  8975. */
  8976. var Carousel = function ($$$1) {
  8977. /**
  8978. * ------------------------------------------------------------------------
  8979. * Constants
  8980. * ------------------------------------------------------------------------
  8981. */
  8982. var NAME = 'carousel';
  8983. var VERSION = '4.1.3';
  8984. var DATA_KEY = 'bs.carousel';
  8985. var EVENT_KEY = "." + DATA_KEY;
  8986. var DATA_API_KEY = '.data-api';
  8987. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  8988. var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
  8989. var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
  8990. var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
  8991. var Default = {
  8992. interval: 5000,
  8993. keyboard: true,
  8994. slide: false,
  8995. pause: 'hover',
  8996. wrap: true
  8997. };
  8998. var DefaultType = {
  8999. interval: '(number|boolean)',
  9000. keyboard: 'boolean',
  9001. slide: '(boolean|string)',
  9002. pause: '(string|boolean)',
  9003. wrap: 'boolean'
  9004. };
  9005. var Direction = {
  9006. NEXT: 'next',
  9007. PREV: 'prev',
  9008. LEFT: 'left',
  9009. RIGHT: 'right'
  9010. };
  9011. var Event = {
  9012. SLIDE: "slide" + EVENT_KEY,
  9013. SLID: "slid" + EVENT_KEY,
  9014. KEYDOWN: "keydown" + EVENT_KEY,
  9015. MOUSEENTER: "mouseenter" + EVENT_KEY,
  9016. MOUSELEAVE: "mouseleave" + EVENT_KEY,
  9017. TOUCHEND: "touchend" + EVENT_KEY,
  9018. LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY,
  9019. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  9020. };
  9021. var ClassName = {
  9022. CAROUSEL: 'carousel',
  9023. ACTIVE: 'active',
  9024. SLIDE: 'slide',
  9025. RIGHT: 'carousel-item-right',
  9026. LEFT: 'carousel-item-left',
  9027. NEXT: 'carousel-item-next',
  9028. PREV: 'carousel-item-prev',
  9029. ITEM: 'carousel-item'
  9030. };
  9031. var Selector = {
  9032. ACTIVE: '.active',
  9033. ACTIVE_ITEM: '.active.carousel-item',
  9034. ITEM: '.carousel-item',
  9035. NEXT_PREV: '.carousel-item-next, .carousel-item-prev',
  9036. INDICATORS: '.carousel-indicators',
  9037. DATA_SLIDE: '[data-slide], [data-slide-to]',
  9038. DATA_RIDE: '[data-ride="carousel"]'
  9039. /**
  9040. * ------------------------------------------------------------------------
  9041. * Class Definition
  9042. * ------------------------------------------------------------------------
  9043. */
  9044. };
  9045. var Carousel =
  9046. /*#__PURE__*/
  9047. function () {
  9048. function Carousel(element, config) {
  9049. this._items = null;
  9050. this._interval = null;
  9051. this._activeElement = null;
  9052. this._isPaused = false;
  9053. this._isSliding = false;
  9054. this.touchTimeout = null;
  9055. this._config = this._getConfig(config);
  9056. this._element = $$$1(element)[0];
  9057. this._indicatorsElement = this._element.querySelector(Selector.INDICATORS);
  9058. this._addEventListeners();
  9059. } // Getters
  9060. var _proto = Carousel.prototype;
  9061. // Public
  9062. _proto.next = function next() {
  9063. if (!this._isSliding) {
  9064. this._slide(Direction.NEXT);
  9065. }
  9066. };
  9067. _proto.nextWhenVisible = function nextWhenVisible() {
  9068. // Don't call next when the page isn't visible
  9069. // or the carousel or its parent isn't visible
  9070. if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') {
  9071. this.next();
  9072. }
  9073. };
  9074. _proto.prev = function prev() {
  9075. if (!this._isSliding) {
  9076. this._slide(Direction.PREV);
  9077. }
  9078. };
  9079. _proto.pause = function pause(event) {
  9080. if (!event) {
  9081. this._isPaused = true;
  9082. }
  9083. if (this._element.querySelector(Selector.NEXT_PREV)) {
  9084. Util.triggerTransitionEnd(this._element);
  9085. this.cycle(true);
  9086. }
  9087. clearInterval(this._interval);
  9088. this._interval = null;
  9089. };
  9090. _proto.cycle = function cycle(event) {
  9091. if (!event) {
  9092. this._isPaused = false;
  9093. }
  9094. if (this._interval) {
  9095. clearInterval(this._interval);
  9096. this._interval = null;
  9097. }
  9098. if (this._config.interval && !this._isPaused) {
  9099. this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
  9100. }
  9101. };
  9102. _proto.to = function to(index) {
  9103. var _this = this;
  9104. this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);
  9105. var activeIndex = this._getItemIndex(this._activeElement);
  9106. if (index > this._items.length - 1 || index < 0) {
  9107. return;
  9108. }
  9109. if (this._isSliding) {
  9110. $$$1(this._element).one(Event.SLID, function () {
  9111. return _this.to(index);
  9112. });
  9113. return;
  9114. }
  9115. if (activeIndex === index) {
  9116. this.pause();
  9117. this.cycle();
  9118. return;
  9119. }
  9120. var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;
  9121. this._slide(direction, this._items[index]);
  9122. };
  9123. _proto.dispose = function dispose() {
  9124. $$$1(this._element).off(EVENT_KEY);
  9125. $$$1.removeData(this._element, DATA_KEY);
  9126. this._items = null;
  9127. this._config = null;
  9128. this._element = null;
  9129. this._interval = null;
  9130. this._isPaused = null;
  9131. this._isSliding = null;
  9132. this._activeElement = null;
  9133. this._indicatorsElement = null;
  9134. }; // Private
  9135. _proto._getConfig = function _getConfig(config) {
  9136. config = _objectSpread({}, Default, config);
  9137. Util.typeCheckConfig(NAME, config, DefaultType);
  9138. return config;
  9139. };
  9140. _proto._addEventListeners = function _addEventListeners() {
  9141. var _this2 = this;
  9142. if (this._config.keyboard) {
  9143. $$$1(this._element).on(Event.KEYDOWN, function (event) {
  9144. return _this2._keydown(event);
  9145. });
  9146. }
  9147. if (this._config.pause === 'hover') {
  9148. $$$1(this._element).on(Event.MOUSEENTER, function (event) {
  9149. return _this2.pause(event);
  9150. }).on(Event.MOUSELEAVE, function (event) {
  9151. return _this2.cycle(event);
  9152. });
  9153. if ('ontouchstart' in document.documentElement) {
  9154. // If it's a touch-enabled device, mouseenter/leave are fired as
  9155. // part of the mouse compatibility events on first tap - the carousel
  9156. // would stop cycling until user tapped out of it;
  9157. // here, we listen for touchend, explicitly pause the carousel
  9158. // (as if it's the second time we tap on it, mouseenter compat event
  9159. // is NOT fired) and after a timeout (to allow for mouse compatibility
  9160. // events to fire) we explicitly restart cycling
  9161. $$$1(this._element).on(Event.TOUCHEND, function () {
  9162. _this2.pause();
  9163. if (_this2.touchTimeout) {
  9164. clearTimeout(_this2.touchTimeout);
  9165. }
  9166. _this2.touchTimeout = setTimeout(function (event) {
  9167. return _this2.cycle(event);
  9168. }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);
  9169. });
  9170. }
  9171. }
  9172. };
  9173. _proto._keydown = function _keydown(event) {
  9174. if (/input|textarea/i.test(event.target.tagName)) {
  9175. return;
  9176. }
  9177. switch (event.which) {
  9178. case ARROW_LEFT_KEYCODE:
  9179. event.preventDefault();
  9180. this.prev();
  9181. break;
  9182. case ARROW_RIGHT_KEYCODE:
  9183. event.preventDefault();
  9184. this.next();
  9185. break;
  9186. default:
  9187. }
  9188. };
  9189. _proto._getItemIndex = function _getItemIndex(element) {
  9190. this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : [];
  9191. return this._items.indexOf(element);
  9192. };
  9193. _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
  9194. var isNextDirection = direction === Direction.NEXT;
  9195. var isPrevDirection = direction === Direction.PREV;
  9196. var activeIndex = this._getItemIndex(activeElement);
  9197. var lastItemIndex = this._items.length - 1;
  9198. var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
  9199. if (isGoingToWrap && !this._config.wrap) {
  9200. return activeElement;
  9201. }
  9202. var delta = direction === Direction.PREV ? -1 : 1;
  9203. var itemIndex = (activeIndex + delta) % this._items.length;
  9204. return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
  9205. };
  9206. _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
  9207. var targetIndex = this._getItemIndex(relatedTarget);
  9208. var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM));
  9209. var slideEvent = $$$1.Event(Event.SLIDE, {
  9210. relatedTarget: relatedTarget,
  9211. direction: eventDirectionName,
  9212. from: fromIndex,
  9213. to: targetIndex
  9214. });
  9215. $$$1(this._element).trigger(slideEvent);
  9216. return slideEvent;
  9217. };
  9218. _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
  9219. if (this._indicatorsElement) {
  9220. var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE));
  9221. $$$1(indicators).removeClass(ClassName.ACTIVE);
  9222. var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
  9223. if (nextIndicator) {
  9224. $$$1(nextIndicator).addClass(ClassName.ACTIVE);
  9225. }
  9226. }
  9227. };
  9228. _proto._slide = function _slide(direction, element) {
  9229. var _this3 = this;
  9230. var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM);
  9231. var activeElementIndex = this._getItemIndex(activeElement);
  9232. var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
  9233. var nextElementIndex = this._getItemIndex(nextElement);
  9234. var isCycling = Boolean(this._interval);
  9235. var directionalClassName;
  9236. var orderClassName;
  9237. var eventDirectionName;
  9238. if (direction === Direction.NEXT) {
  9239. directionalClassName = ClassName.LEFT;
  9240. orderClassName = ClassName.NEXT;
  9241. eventDirectionName = Direction.LEFT;
  9242. } else {
  9243. directionalClassName = ClassName.RIGHT;
  9244. orderClassName = ClassName.PREV;
  9245. eventDirectionName = Direction.RIGHT;
  9246. }
  9247. if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) {
  9248. this._isSliding = false;
  9249. return;
  9250. }
  9251. var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
  9252. if (slideEvent.isDefaultPrevented()) {
  9253. return;
  9254. }
  9255. if (!activeElement || !nextElement) {
  9256. // Some weirdness is happening, so we bail
  9257. return;
  9258. }
  9259. this._isSliding = true;
  9260. if (isCycling) {
  9261. this.pause();
  9262. }
  9263. this._setActiveIndicatorElement(nextElement);
  9264. var slidEvent = $$$1.Event(Event.SLID, {
  9265. relatedTarget: nextElement,
  9266. direction: eventDirectionName,
  9267. from: activeElementIndex,
  9268. to: nextElementIndex
  9269. });
  9270. if ($$$1(this._element).hasClass(ClassName.SLIDE)) {
  9271. $$$1(nextElement).addClass(orderClassName);
  9272. Util.reflow(nextElement);
  9273. $$$1(activeElement).addClass(directionalClassName);
  9274. $$$1(nextElement).addClass(directionalClassName);
  9275. var transitionDuration = Util.getTransitionDurationFromElement(activeElement);
  9276. $$$1(activeElement).one(Util.TRANSITION_END, function () {
  9277. $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE);
  9278. $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName);
  9279. _this3._isSliding = false;
  9280. setTimeout(function () {
  9281. return $$$1(_this3._element).trigger(slidEvent);
  9282. }, 0);
  9283. }).emulateTransitionEnd(transitionDuration);
  9284. } else {
  9285. $$$1(activeElement).removeClass(ClassName.ACTIVE);
  9286. $$$1(nextElement).addClass(ClassName.ACTIVE);
  9287. this._isSliding = false;
  9288. $$$1(this._element).trigger(slidEvent);
  9289. }
  9290. if (isCycling) {
  9291. this.cycle();
  9292. }
  9293. }; // Static
  9294. Carousel._jQueryInterface = function _jQueryInterface(config) {
  9295. return this.each(function () {
  9296. var data = $$$1(this).data(DATA_KEY);
  9297. var _config = _objectSpread({}, Default, $$$1(this).data());
  9298. if (typeof config === 'object') {
  9299. _config = _objectSpread({}, _config, config);
  9300. }
  9301. var action = typeof config === 'string' ? config : _config.slide;
  9302. if (!data) {
  9303. data = new Carousel(this, _config);
  9304. $$$1(this).data(DATA_KEY, data);
  9305. }
  9306. if (typeof config === 'number') {
  9307. data.to(config);
  9308. } else if (typeof action === 'string') {
  9309. if (typeof data[action] === 'undefined') {
  9310. throw new TypeError("No method named \"" + action + "\"");
  9311. }
  9312. data[action]();
  9313. } else if (_config.interval) {
  9314. data.pause();
  9315. data.cycle();
  9316. }
  9317. });
  9318. };
  9319. Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
  9320. var selector = Util.getSelectorFromElement(this);
  9321. if (!selector) {
  9322. return;
  9323. }
  9324. var target = $$$1(selector)[0];
  9325. if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) {
  9326. return;
  9327. }
  9328. var config = _objectSpread({}, $$$1(target).data(), $$$1(this).data());
  9329. var slideIndex = this.getAttribute('data-slide-to');
  9330. if (slideIndex) {
  9331. config.interval = false;
  9332. }
  9333. Carousel._jQueryInterface.call($$$1(target), config);
  9334. if (slideIndex) {
  9335. $$$1(target).data(DATA_KEY).to(slideIndex);
  9336. }
  9337. event.preventDefault();
  9338. };
  9339. _createClass(Carousel, null, [{
  9340. key: "VERSION",
  9341. get: function get() {
  9342. return VERSION;
  9343. }
  9344. }, {
  9345. key: "Default",
  9346. get: function get() {
  9347. return Default;
  9348. }
  9349. }]);
  9350. return Carousel;
  9351. }();
  9352. /**
  9353. * ------------------------------------------------------------------------
  9354. * Data Api implementation
  9355. * ------------------------------------------------------------------------
  9356. */
  9357. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
  9358. $$$1(window).on(Event.LOAD_DATA_API, function () {
  9359. var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE));
  9360. for (var i = 0, len = carousels.length; i < len; i++) {
  9361. var $carousel = $$$1(carousels[i]);
  9362. Carousel._jQueryInterface.call($carousel, $carousel.data());
  9363. }
  9364. });
  9365. /**
  9366. * ------------------------------------------------------------------------
  9367. * jQuery
  9368. * ------------------------------------------------------------------------
  9369. */
  9370. $$$1.fn[NAME] = Carousel._jQueryInterface;
  9371. $$$1.fn[NAME].Constructor = Carousel;
  9372. $$$1.fn[NAME].noConflict = function () {
  9373. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  9374. return Carousel._jQueryInterface;
  9375. };
  9376. return Carousel;
  9377. }($);
  9378. /**
  9379. * --------------------------------------------------------------------------
  9380. * Bootstrap (v4.1.3): collapse.js
  9381. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9382. * --------------------------------------------------------------------------
  9383. */
  9384. var Collapse = function ($$$1) {
  9385. /**
  9386. * ------------------------------------------------------------------------
  9387. * Constants
  9388. * ------------------------------------------------------------------------
  9389. */
  9390. var NAME = 'collapse';
  9391. var VERSION = '4.1.3';
  9392. var DATA_KEY = 'bs.collapse';
  9393. var EVENT_KEY = "." + DATA_KEY;
  9394. var DATA_API_KEY = '.data-api';
  9395. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  9396. var Default = {
  9397. toggle: true,
  9398. parent: ''
  9399. };
  9400. var DefaultType = {
  9401. toggle: 'boolean',
  9402. parent: '(string|element)'
  9403. };
  9404. var Event = {
  9405. SHOW: "show" + EVENT_KEY,
  9406. SHOWN: "shown" + EVENT_KEY,
  9407. HIDE: "hide" + EVENT_KEY,
  9408. HIDDEN: "hidden" + EVENT_KEY,
  9409. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  9410. };
  9411. var ClassName = {
  9412. SHOW: 'show',
  9413. COLLAPSE: 'collapse',
  9414. COLLAPSING: 'collapsing',
  9415. COLLAPSED: 'collapsed'
  9416. };
  9417. var Dimension = {
  9418. WIDTH: 'width',
  9419. HEIGHT: 'height'
  9420. };
  9421. var Selector = {
  9422. ACTIVES: '.show, .collapsing',
  9423. DATA_TOGGLE: '[data-toggle="collapse"]'
  9424. /**
  9425. * ------------------------------------------------------------------------
  9426. * Class Definition
  9427. * ------------------------------------------------------------------------
  9428. */
  9429. };
  9430. var Collapse =
  9431. /*#__PURE__*/
  9432. function () {
  9433. function Collapse(element, config) {
  9434. this._isTransitioning = false;
  9435. this._element = element;
  9436. this._config = this._getConfig(config);
  9437. this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
  9438. var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));
  9439. for (var i = 0, len = toggleList.length; i < len; i++) {
  9440. var elem = toggleList[i];
  9441. var selector = Util.getSelectorFromElement(elem);
  9442. var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {
  9443. return foundElem === element;
  9444. });
  9445. if (selector !== null && filterElement.length > 0) {
  9446. this._selector = selector;
  9447. this._triggerArray.push(elem);
  9448. }
  9449. }
  9450. this._parent = this._config.parent ? this._getParent() : null;
  9451. if (!this._config.parent) {
  9452. this._addAriaAndCollapsedClass(this._element, this._triggerArray);
  9453. }
  9454. if (this._config.toggle) {
  9455. this.toggle();
  9456. }
  9457. } // Getters
  9458. var _proto = Collapse.prototype;
  9459. // Public
  9460. _proto.toggle = function toggle() {
  9461. if ($$$1(this._element).hasClass(ClassName.SHOW)) {
  9462. this.hide();
  9463. } else {
  9464. this.show();
  9465. }
  9466. };
  9467. _proto.show = function show() {
  9468. var _this = this;
  9469. if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) {
  9470. return;
  9471. }
  9472. var actives;
  9473. var activesData;
  9474. if (this._parent) {
  9475. actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) {
  9476. return elem.getAttribute('data-parent') === _this._config.parent;
  9477. });
  9478. if (actives.length === 0) {
  9479. actives = null;
  9480. }
  9481. }
  9482. if (actives) {
  9483. activesData = $$$1(actives).not(this._selector).data(DATA_KEY);
  9484. if (activesData && activesData._isTransitioning) {
  9485. return;
  9486. }
  9487. }
  9488. var startEvent = $$$1.Event(Event.SHOW);
  9489. $$$1(this._element).trigger(startEvent);
  9490. if (startEvent.isDefaultPrevented()) {
  9491. return;
  9492. }
  9493. if (actives) {
  9494. Collapse._jQueryInterface.call($$$1(actives).not(this._selector), 'hide');
  9495. if (!activesData) {
  9496. $$$1(actives).data(DATA_KEY, null);
  9497. }
  9498. }
  9499. var dimension = this._getDimension();
  9500. $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
  9501. this._element.style[dimension] = 0;
  9502. if (this._triggerArray.length) {
  9503. $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
  9504. }
  9505. this.setTransitioning(true);
  9506. var complete = function complete() {
  9507. $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);
  9508. _this._element.style[dimension] = '';
  9509. _this.setTransitioning(false);
  9510. $$$1(_this._element).trigger(Event.SHOWN);
  9511. };
  9512. var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
  9513. var scrollSize = "scroll" + capitalizedDimension;
  9514. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  9515. $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  9516. this._element.style[dimension] = this._element[scrollSize] + "px";
  9517. };
  9518. _proto.hide = function hide() {
  9519. var _this2 = this;
  9520. if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) {
  9521. return;
  9522. }
  9523. var startEvent = $$$1.Event(Event.HIDE);
  9524. $$$1(this._element).trigger(startEvent);
  9525. if (startEvent.isDefaultPrevented()) {
  9526. return;
  9527. }
  9528. var dimension = this._getDimension();
  9529. this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
  9530. Util.reflow(this._element);
  9531. $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
  9532. var triggerArrayLength = this._triggerArray.length;
  9533. if (triggerArrayLength > 0) {
  9534. for (var i = 0; i < triggerArrayLength; i++) {
  9535. var trigger = this._triggerArray[i];
  9536. var selector = Util.getSelectorFromElement(trigger);
  9537. if (selector !== null) {
  9538. var $elem = $$$1([].slice.call(document.querySelectorAll(selector)));
  9539. if (!$elem.hasClass(ClassName.SHOW)) {
  9540. $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
  9541. }
  9542. }
  9543. }
  9544. }
  9545. this.setTransitioning(true);
  9546. var complete = function complete() {
  9547. _this2.setTransitioning(false);
  9548. $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
  9549. };
  9550. this._element.style[dimension] = '';
  9551. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  9552. $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  9553. };
  9554. _proto.setTransitioning = function setTransitioning(isTransitioning) {
  9555. this._isTransitioning = isTransitioning;
  9556. };
  9557. _proto.dispose = function dispose() {
  9558. $$$1.removeData(this._element, DATA_KEY);
  9559. this._config = null;
  9560. this._parent = null;
  9561. this._element = null;
  9562. this._triggerArray = null;
  9563. this._isTransitioning = null;
  9564. }; // Private
  9565. _proto._getConfig = function _getConfig(config) {
  9566. config = _objectSpread({}, Default, config);
  9567. config.toggle = Boolean(config.toggle); // Coerce string values
  9568. Util.typeCheckConfig(NAME, config, DefaultType);
  9569. return config;
  9570. };
  9571. _proto._getDimension = function _getDimension() {
  9572. var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH);
  9573. return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
  9574. };
  9575. _proto._getParent = function _getParent() {
  9576. var _this3 = this;
  9577. var parent = null;
  9578. if (Util.isElement(this._config.parent)) {
  9579. parent = this._config.parent; // It's a jQuery object
  9580. if (typeof this._config.parent.jquery !== 'undefined') {
  9581. parent = this._config.parent[0];
  9582. }
  9583. } else {
  9584. parent = document.querySelector(this._config.parent);
  9585. }
  9586. var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
  9587. var children = [].slice.call(parent.querySelectorAll(selector));
  9588. $$$1(children).each(function (i, element) {
  9589. _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
  9590. });
  9591. return parent;
  9592. };
  9593. _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
  9594. if (element) {
  9595. var isOpen = $$$1(element).hasClass(ClassName.SHOW);
  9596. if (triggerArray.length) {
  9597. $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
  9598. }
  9599. }
  9600. }; // Static
  9601. Collapse._getTargetFromElement = function _getTargetFromElement(element) {
  9602. var selector = Util.getSelectorFromElement(element);
  9603. return selector ? document.querySelector(selector) : null;
  9604. };
  9605. Collapse._jQueryInterface = function _jQueryInterface(config) {
  9606. return this.each(function () {
  9607. var $this = $$$1(this);
  9608. var data = $this.data(DATA_KEY);
  9609. var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {});
  9610. if (!data && _config.toggle && /show|hide/.test(config)) {
  9611. _config.toggle = false;
  9612. }
  9613. if (!data) {
  9614. data = new Collapse(this, _config);
  9615. $this.data(DATA_KEY, data);
  9616. }
  9617. if (typeof config === 'string') {
  9618. if (typeof data[config] === 'undefined') {
  9619. throw new TypeError("No method named \"" + config + "\"");
  9620. }
  9621. data[config]();
  9622. }
  9623. });
  9624. };
  9625. _createClass(Collapse, null, [{
  9626. key: "VERSION",
  9627. get: function get() {
  9628. return VERSION;
  9629. }
  9630. }, {
  9631. key: "Default",
  9632. get: function get() {
  9633. return Default;
  9634. }
  9635. }]);
  9636. return Collapse;
  9637. }();
  9638. /**
  9639. * ------------------------------------------------------------------------
  9640. * Data Api implementation
  9641. * ------------------------------------------------------------------------
  9642. */
  9643. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  9644. // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
  9645. if (event.currentTarget.tagName === 'A') {
  9646. event.preventDefault();
  9647. }
  9648. var $trigger = $$$1(this);
  9649. var selector = Util.getSelectorFromElement(this);
  9650. var selectors = [].slice.call(document.querySelectorAll(selector));
  9651. $$$1(selectors).each(function () {
  9652. var $target = $$$1(this);
  9653. var data = $target.data(DATA_KEY);
  9654. var config = data ? 'toggle' : $trigger.data();
  9655. Collapse._jQueryInterface.call($target, config);
  9656. });
  9657. });
  9658. /**
  9659. * ------------------------------------------------------------------------
  9660. * jQuery
  9661. * ------------------------------------------------------------------------
  9662. */
  9663. $$$1.fn[NAME] = Collapse._jQueryInterface;
  9664. $$$1.fn[NAME].Constructor = Collapse;
  9665. $$$1.fn[NAME].noConflict = function () {
  9666. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  9667. return Collapse._jQueryInterface;
  9668. };
  9669. return Collapse;
  9670. }($);
  9671. /**
  9672. * --------------------------------------------------------------------------
  9673. * Bootstrap (v4.1.3): dropdown.js
  9674. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9675. * --------------------------------------------------------------------------
  9676. */
  9677. var Dropdown = function ($$$1) {
  9678. /**
  9679. * ------------------------------------------------------------------------
  9680. * Constants
  9681. * ------------------------------------------------------------------------
  9682. */
  9683. var NAME = 'dropdown';
  9684. var VERSION = '4.1.3';
  9685. var DATA_KEY = 'bs.dropdown';
  9686. var EVENT_KEY = "." + DATA_KEY;
  9687. var DATA_API_KEY = '.data-api';
  9688. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  9689. var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  9690. var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
  9691. var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
  9692. var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
  9693. var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
  9694. var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
  9695. var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE);
  9696. var Event = {
  9697. HIDE: "hide" + EVENT_KEY,
  9698. HIDDEN: "hidden" + EVENT_KEY,
  9699. SHOW: "show" + EVENT_KEY,
  9700. SHOWN: "shown" + EVENT_KEY,
  9701. CLICK: "click" + EVENT_KEY,
  9702. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
  9703. KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY,
  9704. KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY
  9705. };
  9706. var ClassName = {
  9707. DISABLED: 'disabled',
  9708. SHOW: 'show',
  9709. DROPUP: 'dropup',
  9710. DROPRIGHT: 'dropright',
  9711. DROPLEFT: 'dropleft',
  9712. MENURIGHT: 'dropdown-menu-right',
  9713. MENULEFT: 'dropdown-menu-left',
  9714. POSITION_STATIC: 'position-static'
  9715. };
  9716. var Selector = {
  9717. DATA_TOGGLE: '[data-toggle="dropdown"]',
  9718. FORM_CHILD: '.dropdown form',
  9719. MENU: '.dropdown-menu',
  9720. NAVBAR_NAV: '.navbar-nav',
  9721. VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
  9722. };
  9723. var AttachmentMap = {
  9724. TOP: 'top-start',
  9725. TOPEND: 'top-end',
  9726. BOTTOM: 'bottom-start',
  9727. BOTTOMEND: 'bottom-end',
  9728. RIGHT: 'right-start',
  9729. RIGHTEND: 'right-end',
  9730. LEFT: 'left-start',
  9731. LEFTEND: 'left-end'
  9732. };
  9733. var Default = {
  9734. offset: 0,
  9735. flip: true,
  9736. boundary: 'scrollParent',
  9737. reference: 'toggle',
  9738. display: 'dynamic'
  9739. };
  9740. var DefaultType = {
  9741. offset: '(number|string|function)',
  9742. flip: 'boolean',
  9743. boundary: '(string|element)',
  9744. reference: '(string|element)',
  9745. display: 'string'
  9746. /**
  9747. * ------------------------------------------------------------------------
  9748. * Class Definition
  9749. * ------------------------------------------------------------------------
  9750. */
  9751. };
  9752. var Dropdown =
  9753. /*#__PURE__*/
  9754. function () {
  9755. function Dropdown(element, config) {
  9756. this._element = element;
  9757. this._popper = null;
  9758. this._config = this._getConfig(config);
  9759. this._menu = this._getMenuElement();
  9760. this._inNavbar = this._detectNavbar();
  9761. this._addEventListeners();
  9762. } // Getters
  9763. var _proto = Dropdown.prototype;
  9764. // Public
  9765. _proto.toggle = function toggle() {
  9766. if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) {
  9767. return;
  9768. }
  9769. var parent = Dropdown._getParentFromElement(this._element);
  9770. var isActive = $$$1(this._menu).hasClass(ClassName.SHOW);
  9771. Dropdown._clearMenus();
  9772. if (isActive) {
  9773. return;
  9774. }
  9775. var relatedTarget = {
  9776. relatedTarget: this._element
  9777. };
  9778. var showEvent = $$$1.Event(Event.SHOW, relatedTarget);
  9779. $$$1(parent).trigger(showEvent);
  9780. if (showEvent.isDefaultPrevented()) {
  9781. return;
  9782. } // Disable totally Popper.js for Dropdown in Navbar
  9783. if (!this._inNavbar) {
  9784. /**
  9785. * Check for Popper dependency
  9786. * Popper - https://popper.js.org
  9787. */
  9788. if (typeof Popper === 'undefined') {
  9789. throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)');
  9790. }
  9791. var referenceElement = this._element;
  9792. if (this._config.reference === 'parent') {
  9793. referenceElement = parent;
  9794. } else if (Util.isElement(this._config.reference)) {
  9795. referenceElement = this._config.reference; // Check if it's jQuery element
  9796. if (typeof this._config.reference.jquery !== 'undefined') {
  9797. referenceElement = this._config.reference[0];
  9798. }
  9799. } // If boundary is not `scrollParent`, then set position to `static`
  9800. // to allow the menu to "escape" the scroll parent's boundaries
  9801. // https://github.com/twbs/bootstrap/issues/24251
  9802. if (this._config.boundary !== 'scrollParent') {
  9803. $$$1(parent).addClass(ClassName.POSITION_STATIC);
  9804. }
  9805. this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig());
  9806. } // If this is a touch-enabled device we add extra
  9807. // empty mouseover listeners to the body's immediate children;
  9808. // only needed because of broken event delegation on iOS
  9809. // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
  9810. if ('ontouchstart' in document.documentElement && $$$1(parent).closest(Selector.NAVBAR_NAV).length === 0) {
  9811. $$$1(document.body).children().on('mouseover', null, $$$1.noop);
  9812. }
  9813. this._element.focus();
  9814. this._element.setAttribute('aria-expanded', true);
  9815. $$$1(this._menu).toggleClass(ClassName.SHOW);
  9816. $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget));
  9817. };
  9818. _proto.dispose = function dispose() {
  9819. $$$1.removeData(this._element, DATA_KEY);
  9820. $$$1(this._element).off(EVENT_KEY);
  9821. this._element = null;
  9822. this._menu = null;
  9823. if (this._popper !== null) {
  9824. this._popper.destroy();
  9825. this._popper = null;
  9826. }
  9827. };
  9828. _proto.update = function update() {
  9829. this._inNavbar = this._detectNavbar();
  9830. if (this._popper !== null) {
  9831. this._popper.scheduleUpdate();
  9832. }
  9833. }; // Private
  9834. _proto._addEventListeners = function _addEventListeners() {
  9835. var _this = this;
  9836. $$$1(this._element).on(Event.CLICK, function (event) {
  9837. event.preventDefault();
  9838. event.stopPropagation();
  9839. _this.toggle();
  9840. });
  9841. };
  9842. _proto._getConfig = function _getConfig(config) {
  9843. config = _objectSpread({}, this.constructor.Default, $$$1(this._element).data(), config);
  9844. Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
  9845. return config;
  9846. };
  9847. _proto._getMenuElement = function _getMenuElement() {
  9848. if (!this._menu) {
  9849. var parent = Dropdown._getParentFromElement(this._element);
  9850. if (parent) {
  9851. this._menu = parent.querySelector(Selector.MENU);
  9852. }
  9853. }
  9854. return this._menu;
  9855. };
  9856. _proto._getPlacement = function _getPlacement() {
  9857. var $parentDropdown = $$$1(this._element.parentNode);
  9858. var placement = AttachmentMap.BOTTOM; // Handle dropup
  9859. if ($parentDropdown.hasClass(ClassName.DROPUP)) {
  9860. placement = AttachmentMap.TOP;
  9861. if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
  9862. placement = AttachmentMap.TOPEND;
  9863. }
  9864. } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {
  9865. placement = AttachmentMap.RIGHT;
  9866. } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {
  9867. placement = AttachmentMap.LEFT;
  9868. } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
  9869. placement = AttachmentMap.BOTTOMEND;
  9870. }
  9871. return placement;
  9872. };
  9873. _proto._detectNavbar = function _detectNavbar() {
  9874. return $$$1(this._element).closest('.navbar').length > 0;
  9875. };
  9876. _proto._getPopperConfig = function _getPopperConfig() {
  9877. var _this2 = this;
  9878. var offsetConf = {};
  9879. if (typeof this._config.offset === 'function') {
  9880. offsetConf.fn = function (data) {
  9881. data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets) || {});
  9882. return data;
  9883. };
  9884. } else {
  9885. offsetConf.offset = this._config.offset;
  9886. }
  9887. var popperConfig = {
  9888. placement: this._getPlacement(),
  9889. modifiers: {
  9890. offset: offsetConf,
  9891. flip: {
  9892. enabled: this._config.flip
  9893. },
  9894. preventOverflow: {
  9895. boundariesElement: this._config.boundary
  9896. }
  9897. } // Disable Popper.js if we have a static display
  9898. };
  9899. if (this._config.display === 'static') {
  9900. popperConfig.modifiers.applyStyle = {
  9901. enabled: false
  9902. };
  9903. }
  9904. return popperConfig;
  9905. }; // Static
  9906. Dropdown._jQueryInterface = function _jQueryInterface(config) {
  9907. return this.each(function () {
  9908. var data = $$$1(this).data(DATA_KEY);
  9909. var _config = typeof config === 'object' ? config : null;
  9910. if (!data) {
  9911. data = new Dropdown(this, _config);
  9912. $$$1(this).data(DATA_KEY, data);
  9913. }
  9914. if (typeof config === 'string') {
  9915. if (typeof data[config] === 'undefined') {
  9916. throw new TypeError("No method named \"" + config + "\"");
  9917. }
  9918. data[config]();
  9919. }
  9920. });
  9921. };
  9922. Dropdown._clearMenus = function _clearMenus(event) {
  9923. if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
  9924. return;
  9925. }
  9926. var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));
  9927. for (var i = 0, len = toggles.length; i < len; i++) {
  9928. var parent = Dropdown._getParentFromElement(toggles[i]);
  9929. var context = $$$1(toggles[i]).data(DATA_KEY);
  9930. var relatedTarget = {
  9931. relatedTarget: toggles[i]
  9932. };
  9933. if (event && event.type === 'click') {
  9934. relatedTarget.clickEvent = event;
  9935. }
  9936. if (!context) {
  9937. continue;
  9938. }
  9939. var dropdownMenu = context._menu;
  9940. if (!$$$1(parent).hasClass(ClassName.SHOW)) {
  9941. continue;
  9942. }
  9943. if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) {
  9944. continue;
  9945. }
  9946. var hideEvent = $$$1.Event(Event.HIDE, relatedTarget);
  9947. $$$1(parent).trigger(hideEvent);
  9948. if (hideEvent.isDefaultPrevented()) {
  9949. continue;
  9950. } // If this is a touch-enabled device we remove the extra
  9951. // empty mouseover listeners we added for iOS support
  9952. if ('ontouchstart' in document.documentElement) {
  9953. $$$1(document.body).children().off('mouseover', null, $$$1.noop);
  9954. }
  9955. toggles[i].setAttribute('aria-expanded', 'false');
  9956. $$$1(dropdownMenu).removeClass(ClassName.SHOW);
  9957. $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget));
  9958. }
  9959. };
  9960. Dropdown._getParentFromElement = function _getParentFromElement(element) {
  9961. var parent;
  9962. var selector = Util.getSelectorFromElement(element);
  9963. if (selector) {
  9964. parent = document.querySelector(selector);
  9965. }
  9966. return parent || element.parentNode;
  9967. }; // eslint-disable-next-line complexity
  9968. Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
  9969. // If not input/textarea:
  9970. // - And not a key in REGEXP_KEYDOWN => not a dropdown command
  9971. // If input/textarea:
  9972. // - If space key => not a dropdown command
  9973. // - If key is other than escape
  9974. // - If key is not up or down => not a dropdown command
  9975. // - If trigger inside the menu => not a dropdown command
  9976. 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)) {
  9977. return;
  9978. }
  9979. event.preventDefault();
  9980. event.stopPropagation();
  9981. if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) {
  9982. return;
  9983. }
  9984. var parent = Dropdown._getParentFromElement(this);
  9985. var isActive = $$$1(parent).hasClass(ClassName.SHOW);
  9986. if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
  9987. if (event.which === ESCAPE_KEYCODE) {
  9988. var toggle = parent.querySelector(Selector.DATA_TOGGLE);
  9989. $$$1(toggle).trigger('focus');
  9990. }
  9991. $$$1(this).trigger('click');
  9992. return;
  9993. }
  9994. var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS));
  9995. if (items.length === 0) {
  9996. return;
  9997. }
  9998. var index = items.indexOf(event.target);
  9999. if (event.which === ARROW_UP_KEYCODE && index > 0) {
  10000. // Up
  10001. index--;
  10002. }
  10003. if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
  10004. // Down
  10005. index++;
  10006. }
  10007. if (index < 0) {
  10008. index = 0;
  10009. }
  10010. items[index].focus();
  10011. };
  10012. _createClass(Dropdown, null, [{
  10013. key: "VERSION",
  10014. get: function get() {
  10015. return VERSION;
  10016. }
  10017. }, {
  10018. key: "Default",
  10019. get: function get() {
  10020. return Default;
  10021. }
  10022. }, {
  10023. key: "DefaultType",
  10024. get: function get() {
  10025. return DefaultType;
  10026. }
  10027. }]);
  10028. return Dropdown;
  10029. }();
  10030. /**
  10031. * ------------------------------------------------------------------------
  10032. * Data Api implementation
  10033. * ------------------------------------------------------------------------
  10034. */
  10035. $$$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) {
  10036. event.preventDefault();
  10037. event.stopPropagation();
  10038. Dropdown._jQueryInterface.call($$$1(this), 'toggle');
  10039. }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
  10040. e.stopPropagation();
  10041. });
  10042. /**
  10043. * ------------------------------------------------------------------------
  10044. * jQuery
  10045. * ------------------------------------------------------------------------
  10046. */
  10047. $$$1.fn[NAME] = Dropdown._jQueryInterface;
  10048. $$$1.fn[NAME].Constructor = Dropdown;
  10049. $$$1.fn[NAME].noConflict = function () {
  10050. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  10051. return Dropdown._jQueryInterface;
  10052. };
  10053. return Dropdown;
  10054. }($, Popper);
  10055. /**
  10056. * --------------------------------------------------------------------------
  10057. * Bootstrap (v4.1.3): modal.js
  10058. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10059. * --------------------------------------------------------------------------
  10060. */
  10061. var Modal = function ($$$1) {
  10062. /**
  10063. * ------------------------------------------------------------------------
  10064. * Constants
  10065. * ------------------------------------------------------------------------
  10066. */
  10067. var NAME = 'modal';
  10068. var VERSION = '4.1.3';
  10069. var DATA_KEY = 'bs.modal';
  10070. var EVENT_KEY = "." + DATA_KEY;
  10071. var DATA_API_KEY = '.data-api';
  10072. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  10073. var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  10074. var Default = {
  10075. backdrop: true,
  10076. keyboard: true,
  10077. focus: true,
  10078. show: true
  10079. };
  10080. var DefaultType = {
  10081. backdrop: '(boolean|string)',
  10082. keyboard: 'boolean',
  10083. focus: 'boolean',
  10084. show: 'boolean'
  10085. };
  10086. var Event = {
  10087. HIDE: "hide" + EVENT_KEY,
  10088. HIDDEN: "hidden" + EVENT_KEY,
  10089. SHOW: "show" + EVENT_KEY,
  10090. SHOWN: "shown" + EVENT_KEY,
  10091. FOCUSIN: "focusin" + EVENT_KEY,
  10092. RESIZE: "resize" + EVENT_KEY,
  10093. CLICK_DISMISS: "click.dismiss" + EVENT_KEY,
  10094. KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY,
  10095. MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY,
  10096. MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY,
  10097. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  10098. };
  10099. var ClassName = {
  10100. SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
  10101. BACKDROP: 'modal-backdrop',
  10102. OPEN: 'modal-open',
  10103. FADE: 'fade',
  10104. SHOW: 'show'
  10105. };
  10106. var Selector = {
  10107. DIALOG: '.modal-dialog',
  10108. DATA_TOGGLE: '[data-toggle="modal"]',
  10109. DATA_DISMISS: '[data-dismiss="modal"]',
  10110. FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
  10111. STICKY_CONTENT: '.sticky-top'
  10112. /**
  10113. * ------------------------------------------------------------------------
  10114. * Class Definition
  10115. * ------------------------------------------------------------------------
  10116. */
  10117. };
  10118. var Modal =
  10119. /*#__PURE__*/
  10120. function () {
  10121. function Modal(element, config) {
  10122. this._config = this._getConfig(config);
  10123. this._element = element;
  10124. this._dialog = element.querySelector(Selector.DIALOG);
  10125. this._backdrop = null;
  10126. this._isShown = false;
  10127. this._isBodyOverflowing = false;
  10128. this._ignoreBackdropClick = false;
  10129. this._scrollbarWidth = 0;
  10130. } // Getters
  10131. var _proto = Modal.prototype;
  10132. // Public
  10133. _proto.toggle = function toggle(relatedTarget) {
  10134. return this._isShown ? this.hide() : this.show(relatedTarget);
  10135. };
  10136. _proto.show = function show(relatedTarget) {
  10137. var _this = this;
  10138. if (this._isTransitioning || this._isShown) {
  10139. return;
  10140. }
  10141. if ($$$1(this._element).hasClass(ClassName.FADE)) {
  10142. this._isTransitioning = true;
  10143. }
  10144. var showEvent = $$$1.Event(Event.SHOW, {
  10145. relatedTarget: relatedTarget
  10146. });
  10147. $$$1(this._element).trigger(showEvent);
  10148. if (this._isShown || showEvent.isDefaultPrevented()) {
  10149. return;
  10150. }
  10151. this._isShown = true;
  10152. this._checkScrollbar();
  10153. this._setScrollbar();
  10154. this._adjustDialog();
  10155. $$$1(document.body).addClass(ClassName.OPEN);
  10156. this._setEscapeEvent();
  10157. this._setResizeEvent();
  10158. $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {
  10159. return _this.hide(event);
  10160. });
  10161. $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
  10162. $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {
  10163. if ($$$1(event.target).is(_this._element)) {
  10164. _this._ignoreBackdropClick = true;
  10165. }
  10166. });
  10167. });
  10168. this._showBackdrop(function () {
  10169. return _this._showElement(relatedTarget);
  10170. });
  10171. };
  10172. _proto.hide = function hide(event) {
  10173. var _this2 = this;
  10174. if (event) {
  10175. event.preventDefault();
  10176. }
  10177. if (this._isTransitioning || !this._isShown) {
  10178. return;
  10179. }
  10180. var hideEvent = $$$1.Event(Event.HIDE);
  10181. $$$1(this._element).trigger(hideEvent);
  10182. if (!this._isShown || hideEvent.isDefaultPrevented()) {
  10183. return;
  10184. }
  10185. this._isShown = false;
  10186. var transition = $$$1(this._element).hasClass(ClassName.FADE);
  10187. if (transition) {
  10188. this._isTransitioning = true;
  10189. }
  10190. this._setEscapeEvent();
  10191. this._setResizeEvent();
  10192. $$$1(document).off(Event.FOCUSIN);
  10193. $$$1(this._element).removeClass(ClassName.SHOW);
  10194. $$$1(this._element).off(Event.CLICK_DISMISS);
  10195. $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS);
  10196. if (transition) {
  10197. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  10198. $$$1(this._element).one(Util.TRANSITION_END, function (event) {
  10199. return _this2._hideModal(event);
  10200. }).emulateTransitionEnd(transitionDuration);
  10201. } else {
  10202. this._hideModal();
  10203. }
  10204. };
  10205. _proto.dispose = function dispose() {
  10206. $$$1.removeData(this._element, DATA_KEY);
  10207. $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY);
  10208. this._config = null;
  10209. this._element = null;
  10210. this._dialog = null;
  10211. this._backdrop = null;
  10212. this._isShown = null;
  10213. this._isBodyOverflowing = null;
  10214. this._ignoreBackdropClick = null;
  10215. this._scrollbarWidth = null;
  10216. };
  10217. _proto.handleUpdate = function handleUpdate() {
  10218. this._adjustDialog();
  10219. }; // Private
  10220. _proto._getConfig = function _getConfig(config) {
  10221. config = _objectSpread({}, Default, config);
  10222. Util.typeCheckConfig(NAME, config, DefaultType);
  10223. return config;
  10224. };
  10225. _proto._showElement = function _showElement(relatedTarget) {
  10226. var _this3 = this;
  10227. var transition = $$$1(this._element).hasClass(ClassName.FADE);
  10228. if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
  10229. // Don't move modal's DOM position
  10230. document.body.appendChild(this._element);
  10231. }
  10232. this._element.style.display = 'block';
  10233. this._element.removeAttribute('aria-hidden');
  10234. this._element.scrollTop = 0;
  10235. if (transition) {
  10236. Util.reflow(this._element);
  10237. }
  10238. $$$1(this._element).addClass(ClassName.SHOW);
  10239. if (this._config.focus) {
  10240. this._enforceFocus();
  10241. }
  10242. var shownEvent = $$$1.Event(Event.SHOWN, {
  10243. relatedTarget: relatedTarget
  10244. });
  10245. var transitionComplete = function transitionComplete() {
  10246. if (_this3._config.focus) {
  10247. _this3._element.focus();
  10248. }
  10249. _this3._isTransitioning = false;
  10250. $$$1(_this3._element).trigger(shownEvent);
  10251. };
  10252. if (transition) {
  10253. var transitionDuration = Util.getTransitionDurationFromElement(this._element);
  10254. $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);
  10255. } else {
  10256. transitionComplete();
  10257. }
  10258. };
  10259. _proto._enforceFocus = function _enforceFocus() {
  10260. var _this4 = this;
  10261. $$$1(document).off(Event.FOCUSIN) // Guard against infinite focus loop
  10262. .on(Event.FOCUSIN, function (event) {
  10263. if (document !== event.target && _this4._element !== event.target && $$$1(_this4._element).has(event.target).length === 0) {
  10264. _this4._element.focus();
  10265. }
  10266. });
  10267. };
  10268. _proto._setEscapeEvent = function _setEscapeEvent() {
  10269. var _this5 = this;
  10270. if (this._isShown && this._config.keyboard) {
  10271. $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
  10272. if (event.which === ESCAPE_KEYCODE) {
  10273. event.preventDefault();
  10274. _this5.hide();
  10275. }
  10276. });
  10277. } else if (!this._isShown) {
  10278. $$$1(this._element).off(Event.KEYDOWN_DISMISS);
  10279. }
  10280. };
  10281. _proto._setResizeEvent = function _setResizeEvent() {
  10282. var _this6 = this;
  10283. if (this._isShown) {
  10284. $$$1(window).on(Event.RESIZE, function (event) {
  10285. return _this6.handleUpdate(event);
  10286. });
  10287. } else {
  10288. $$$1(window).off(Event.RESIZE);
  10289. }
  10290. };
  10291. _proto._hideModal = function _hideModal() {
  10292. var _this7 = this;
  10293. this._element.style.display = 'none';
  10294. this._element.setAttribute('aria-hidden', true);
  10295. this._isTransitioning = false;
  10296. this._showBackdrop(function () {
  10297. $$$1(document.body).removeClass(ClassName.OPEN);
  10298. _this7._resetAdjustments();
  10299. _this7._resetScrollbar();
  10300. $$$1(_this7._element).trigger(Event.HIDDEN);
  10301. });
  10302. };
  10303. _proto._removeBackdrop = function _removeBackdrop() {
  10304. if (this._backdrop) {
  10305. $$$1(this._backdrop).remove();
  10306. this._backdrop = null;
  10307. }
  10308. };
  10309. _proto._showBackdrop = function _showBackdrop(callback) {
  10310. var _this8 = this;
  10311. var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
  10312. if (this._isShown && this._config.backdrop) {
  10313. this._backdrop = document.createElement('div');
  10314. this._backdrop.className = ClassName.BACKDROP;
  10315. if (animate) {
  10316. this._backdrop.classList.add(animate);
  10317. }
  10318. $$$1(this._backdrop).appendTo(document.body);
  10319. $$$1(this._element).on(Event.CLICK_DISMISS, function (event) {
  10320. if (_this8._ignoreBackdropClick) {
  10321. _this8._ignoreBackdropClick = false;
  10322. return;
  10323. }
  10324. if (event.target !== event.currentTarget) {
  10325. return;
  10326. }
  10327. if (_this8._config.backdrop === 'static') {
  10328. _this8._element.focus();
  10329. } else {
  10330. _this8.hide();
  10331. }
  10332. });
  10333. if (animate) {
  10334. Util.reflow(this._backdrop);
  10335. }
  10336. $$$1(this._backdrop).addClass(ClassName.SHOW);
  10337. if (!callback) {
  10338. return;
  10339. }
  10340. if (!animate) {
  10341. callback();
  10342. return;
  10343. }
  10344. var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
  10345. $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);
  10346. } else if (!this._isShown && this._backdrop) {
  10347. $$$1(this._backdrop).removeClass(ClassName.SHOW);
  10348. var callbackRemove = function callbackRemove() {
  10349. _this8._removeBackdrop();
  10350. if (callback) {
  10351. callback();
  10352. }
  10353. };
  10354. if ($$$1(this._element).hasClass(ClassName.FADE)) {
  10355. var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
  10356. $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);
  10357. } else {
  10358. callbackRemove();
  10359. }
  10360. } else if (callback) {
  10361. callback();
  10362. }
  10363. }; // ----------------------------------------------------------------------
  10364. // the following methods are used to handle overflowing modals
  10365. // todo (fat): these should probably be refactored out of modal.js
  10366. // ----------------------------------------------------------------------
  10367. _proto._adjustDialog = function _adjustDialog() {
  10368. var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
  10369. if (!this._isBodyOverflowing && isModalOverflowing) {
  10370. this._element.style.paddingLeft = this._scrollbarWidth + "px";
  10371. }
  10372. if (this._isBodyOverflowing && !isModalOverflowing) {
  10373. this._element.style.paddingRight = this._scrollbarWidth + "px";
  10374. }
  10375. };
  10376. _proto._resetAdjustments = function _resetAdjustments() {
  10377. this._element.style.paddingLeft = '';
  10378. this._element.style.paddingRight = '';
  10379. };
  10380. _proto._checkScrollbar = function _checkScrollbar() {
  10381. var rect = document.body.getBoundingClientRect();
  10382. this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;
  10383. this._scrollbarWidth = this._getScrollbarWidth();
  10384. };
  10385. _proto._setScrollbar = function _setScrollbar() {
  10386. var _this9 = this;
  10387. if (this._isBodyOverflowing) {
  10388. // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
  10389. // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
  10390. var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
  10391. var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding
  10392. $$$1(fixedContent).each(function (index, element) {
  10393. var actualPadding = element.style.paddingRight;
  10394. var calculatedPadding = $$$1(element).css('padding-right');
  10395. $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px");
  10396. }); // Adjust sticky content margin
  10397. $$$1(stickyContent).each(function (index, element) {
  10398. var actualMargin = element.style.marginRight;
  10399. var calculatedMargin = $$$1(element).css('margin-right');
  10400. $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px");
  10401. }); // Adjust body padding
  10402. var actualPadding = document.body.style.paddingRight;
  10403. var calculatedPadding = $$$1(document.body).css('padding-right');
  10404. $$$1(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
  10405. }
  10406. };
  10407. _proto._resetScrollbar = function _resetScrollbar() {
  10408. // Restore fixed content padding
  10409. var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
  10410. $$$1(fixedContent).each(function (index, element) {
  10411. var padding = $$$1(element).data('padding-right');
  10412. $$$1(element).removeData('padding-right');
  10413. element.style.paddingRight = padding ? padding : '';
  10414. }); // Restore sticky content
  10415. var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT));
  10416. $$$1(elements).each(function (index, element) {
  10417. var margin = $$$1(element).data('margin-right');
  10418. if (typeof margin !== 'undefined') {
  10419. $$$1(element).css('margin-right', margin).removeData('margin-right');
  10420. }
  10421. }); // Restore body padding
  10422. var padding = $$$1(document.body).data('padding-right');
  10423. $$$1(document.body).removeData('padding-right');
  10424. document.body.style.paddingRight = padding ? padding : '';
  10425. };
  10426. _proto._getScrollbarWidth = function _getScrollbarWidth() {
  10427. // thx d.walsh
  10428. var scrollDiv = document.createElement('div');
  10429. scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
  10430. document.body.appendChild(scrollDiv);
  10431. var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
  10432. document.body.removeChild(scrollDiv);
  10433. return scrollbarWidth;
  10434. }; // Static
  10435. Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
  10436. return this.each(function () {
  10437. var data = $$$1(this).data(DATA_KEY);
  10438. var _config = _objectSpread({}, Default, $$$1(this).data(), typeof config === 'object' && config ? config : {});
  10439. if (!data) {
  10440. data = new Modal(this, _config);
  10441. $$$1(this).data(DATA_KEY, data);
  10442. }
  10443. if (typeof config === 'string') {
  10444. if (typeof data[config] === 'undefined') {
  10445. throw new TypeError("No method named \"" + config + "\"");
  10446. }
  10447. data[config](relatedTarget);
  10448. } else if (_config.show) {
  10449. data.show(relatedTarget);
  10450. }
  10451. });
  10452. };
  10453. _createClass(Modal, null, [{
  10454. key: "VERSION",
  10455. get: function get() {
  10456. return VERSION;
  10457. }
  10458. }, {
  10459. key: "Default",
  10460. get: function get() {
  10461. return Default;
  10462. }
  10463. }]);
  10464. return Modal;
  10465. }();
  10466. /**
  10467. * ------------------------------------------------------------------------
  10468. * Data Api implementation
  10469. * ------------------------------------------------------------------------
  10470. */
  10471. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  10472. var _this10 = this;
  10473. var target;
  10474. var selector = Util.getSelectorFromElement(this);
  10475. if (selector) {
  10476. target = document.querySelector(selector);
  10477. }
  10478. var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data());
  10479. if (this.tagName === 'A' || this.tagName === 'AREA') {
  10480. event.preventDefault();
  10481. }
  10482. var $target = $$$1(target).one(Event.SHOW, function (showEvent) {
  10483. if (showEvent.isDefaultPrevented()) {
  10484. // Only register focus restorer if modal will actually get shown
  10485. return;
  10486. }
  10487. $target.one(Event.HIDDEN, function () {
  10488. if ($$$1(_this10).is(':visible')) {
  10489. _this10.focus();
  10490. }
  10491. });
  10492. });
  10493. Modal._jQueryInterface.call($$$1(target), config, this);
  10494. });
  10495. /**
  10496. * ------------------------------------------------------------------------
  10497. * jQuery
  10498. * ------------------------------------------------------------------------
  10499. */
  10500. $$$1.fn[NAME] = Modal._jQueryInterface;
  10501. $$$1.fn[NAME].Constructor = Modal;
  10502. $$$1.fn[NAME].noConflict = function () {
  10503. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  10504. return Modal._jQueryInterface;
  10505. };
  10506. return Modal;
  10507. }($);
  10508. /**
  10509. * --------------------------------------------------------------------------
  10510. * Bootstrap (v4.1.3): tooltip.js
  10511. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10512. * --------------------------------------------------------------------------
  10513. */
  10514. var Tooltip = function ($$$1) {
  10515. /**
  10516. * ------------------------------------------------------------------------
  10517. * Constants
  10518. * ------------------------------------------------------------------------
  10519. */
  10520. var NAME = 'tooltip';
  10521. var VERSION = '4.1.3';
  10522. var DATA_KEY = 'bs.tooltip';
  10523. var EVENT_KEY = "." + DATA_KEY;
  10524. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  10525. var CLASS_PREFIX = 'bs-tooltip';
  10526. var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
  10527. var DefaultType = {
  10528. animation: 'boolean',
  10529. template: 'string',
  10530. title: '(string|element|function)',
  10531. trigger: 'string',
  10532. delay: '(number|object)',
  10533. html: 'boolean',
  10534. selector: '(string|boolean)',
  10535. placement: '(string|function)',
  10536. offset: '(number|string)',
  10537. container: '(string|element|boolean)',
  10538. fallbackPlacement: '(string|array)',
  10539. boundary: '(string|element)'
  10540. };
  10541. var AttachmentMap = {
  10542. AUTO: 'auto',
  10543. TOP: 'top',
  10544. RIGHT: 'right',
  10545. BOTTOM: 'bottom',
  10546. LEFT: 'left'
  10547. };
  10548. var Default = {
  10549. animation: true,
  10550. template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
  10551. trigger: 'hover focus',
  10552. title: '',
  10553. delay: 0,
  10554. html: false,
  10555. selector: false,
  10556. placement: 'top',
  10557. offset: 0,
  10558. container: false,
  10559. fallbackPlacement: 'flip',
  10560. boundary: 'scrollParent'
  10561. };
  10562. var HoverState = {
  10563. SHOW: 'show',
  10564. OUT: 'out'
  10565. };
  10566. var Event = {
  10567. HIDE: "hide" + EVENT_KEY,
  10568. HIDDEN: "hidden" + EVENT_KEY,
  10569. SHOW: "show" + EVENT_KEY,
  10570. SHOWN: "shown" + EVENT_KEY,
  10571. INSERTED: "inserted" + EVENT_KEY,
  10572. CLICK: "click" + EVENT_KEY,
  10573. FOCUSIN: "focusin" + EVENT_KEY,
  10574. FOCUSOUT: "focusout" + EVENT_KEY,
  10575. MOUSEENTER: "mouseenter" + EVENT_KEY,
  10576. MOUSELEAVE: "mouseleave" + EVENT_KEY
  10577. };
  10578. var ClassName = {
  10579. FADE: 'fade',
  10580. SHOW: 'show'
  10581. };
  10582. var Selector = {
  10583. TOOLTIP: '.tooltip',
  10584. TOOLTIP_INNER: '.tooltip-inner',
  10585. ARROW: '.arrow'
  10586. };
  10587. var Trigger = {
  10588. HOVER: 'hover',
  10589. FOCUS: 'focus',
  10590. CLICK: 'click',
  10591. MANUAL: 'manual'
  10592. /**
  10593. * ------------------------------------------------------------------------
  10594. * Class Definition
  10595. * ------------------------------------------------------------------------
  10596. */
  10597. };
  10598. var Tooltip =
  10599. /*#__PURE__*/
  10600. function () {
  10601. function Tooltip(element, config) {
  10602. /**
  10603. * Check for Popper dependency
  10604. * Popper - https://popper.js.org
  10605. */
  10606. if (typeof Popper === 'undefined') {
  10607. throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)');
  10608. } // private
  10609. this._isEnabled = true;
  10610. this._timeout = 0;
  10611. this._hoverState = '';
  10612. this._activeTrigger = {};
  10613. this._popper = null; // Protected
  10614. this.element = element;
  10615. this.config = this._getConfig(config);
  10616. this.tip = null;
  10617. this._setListeners();
  10618. } // Getters
  10619. var _proto = Tooltip.prototype;
  10620. // Public
  10621. _proto.enable = function enable() {
  10622. this._isEnabled = true;
  10623. };
  10624. _proto.disable = function disable() {
  10625. this._isEnabled = false;
  10626. };
  10627. _proto.toggleEnabled = function toggleEnabled() {
  10628. this._isEnabled = !this._isEnabled;
  10629. };
  10630. _proto.toggle = function toggle(event) {
  10631. if (!this._isEnabled) {
  10632. return;
  10633. }
  10634. if (event) {
  10635. var dataKey = this.constructor.DATA_KEY;
  10636. var context = $$$1(event.currentTarget).data(dataKey);
  10637. if (!context) {
  10638. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10639. $$$1(event.currentTarget).data(dataKey, context);
  10640. }
  10641. context._activeTrigger.click = !context._activeTrigger.click;
  10642. if (context._isWithActiveTrigger()) {
  10643. context._enter(null, context);
  10644. } else {
  10645. context._leave(null, context);
  10646. }
  10647. } else {
  10648. if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) {
  10649. this._leave(null, this);
  10650. return;
  10651. }
  10652. this._enter(null, this);
  10653. }
  10654. };
  10655. _proto.dispose = function dispose() {
  10656. clearTimeout(this._timeout);
  10657. $$$1.removeData(this.element, this.constructor.DATA_KEY);
  10658. $$$1(this.element).off(this.constructor.EVENT_KEY);
  10659. $$$1(this.element).closest('.modal').off('hide.bs.modal');
  10660. if (this.tip) {
  10661. $$$1(this.tip).remove();
  10662. }
  10663. this._isEnabled = null;
  10664. this._timeout = null;
  10665. this._hoverState = null;
  10666. this._activeTrigger = null;
  10667. if (this._popper !== null) {
  10668. this._popper.destroy();
  10669. }
  10670. this._popper = null;
  10671. this.element = null;
  10672. this.config = null;
  10673. this.tip = null;
  10674. };
  10675. _proto.show = function show() {
  10676. var _this = this;
  10677. if ($$$1(this.element).css('display') === 'none') {
  10678. throw new Error('Please use show on visible elements');
  10679. }
  10680. var showEvent = $$$1.Event(this.constructor.Event.SHOW);
  10681. if (this.isWithContent() && this._isEnabled) {
  10682. $$$1(this.element).trigger(showEvent);
  10683. var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element);
  10684. if (showEvent.isDefaultPrevented() || !isInTheDom) {
  10685. return;
  10686. }
  10687. var tip = this.getTipElement();
  10688. var tipId = Util.getUID(this.constructor.NAME);
  10689. tip.setAttribute('id', tipId);
  10690. this.element.setAttribute('aria-describedby', tipId);
  10691. this.setContent();
  10692. if (this.config.animation) {
  10693. $$$1(tip).addClass(ClassName.FADE);
  10694. }
  10695. var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
  10696. var attachment = this._getAttachment(placement);
  10697. this.addAttachmentClass(attachment);
  10698. var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container);
  10699. $$$1(tip).data(this.constructor.DATA_KEY, this);
  10700. if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) {
  10701. $$$1(tip).appendTo(container);
  10702. }
  10703. $$$1(this.element).trigger(this.constructor.Event.INSERTED);
  10704. this._popper = new Popper(this.element, tip, {
  10705. placement: attachment,
  10706. modifiers: {
  10707. offset: {
  10708. offset: this.config.offset
  10709. },
  10710. flip: {
  10711. behavior: this.config.fallbackPlacement
  10712. },
  10713. arrow: {
  10714. element: Selector.ARROW
  10715. },
  10716. preventOverflow: {
  10717. boundariesElement: this.config.boundary
  10718. }
  10719. },
  10720. onCreate: function onCreate(data) {
  10721. if (data.originalPlacement !== data.placement) {
  10722. _this._handlePopperPlacementChange(data);
  10723. }
  10724. },
  10725. onUpdate: function onUpdate(data) {
  10726. _this._handlePopperPlacementChange(data);
  10727. }
  10728. });
  10729. $$$1(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra
  10730. // empty mouseover listeners to the body's immediate children;
  10731. // only needed because of broken event delegation on iOS
  10732. // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
  10733. if ('ontouchstart' in document.documentElement) {
  10734. $$$1(document.body).children().on('mouseover', null, $$$1.noop);
  10735. }
  10736. var complete = function complete() {
  10737. if (_this.config.animation) {
  10738. _this._fixTransition();
  10739. }
  10740. var prevHoverState = _this._hoverState;
  10741. _this._hoverState = null;
  10742. $$$1(_this.element).trigger(_this.constructor.Event.SHOWN);
  10743. if (prevHoverState === HoverState.OUT) {
  10744. _this._leave(null, _this);
  10745. }
  10746. };
  10747. if ($$$1(this.tip).hasClass(ClassName.FADE)) {
  10748. var transitionDuration = Util.getTransitionDurationFromElement(this.tip);
  10749. $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  10750. } else {
  10751. complete();
  10752. }
  10753. }
  10754. };
  10755. _proto.hide = function hide(callback) {
  10756. var _this2 = this;
  10757. var tip = this.getTipElement();
  10758. var hideEvent = $$$1.Event(this.constructor.Event.HIDE);
  10759. var complete = function complete() {
  10760. if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {
  10761. tip.parentNode.removeChild(tip);
  10762. }
  10763. _this2._cleanTipClass();
  10764. _this2.element.removeAttribute('aria-describedby');
  10765. $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
  10766. if (_this2._popper !== null) {
  10767. _this2._popper.destroy();
  10768. }
  10769. if (callback) {
  10770. callback();
  10771. }
  10772. };
  10773. $$$1(this.element).trigger(hideEvent);
  10774. if (hideEvent.isDefaultPrevented()) {
  10775. return;
  10776. }
  10777. $$$1(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra
  10778. // empty mouseover listeners we added for iOS support
  10779. if ('ontouchstart' in document.documentElement) {
  10780. $$$1(document.body).children().off('mouseover', null, $$$1.noop);
  10781. }
  10782. this._activeTrigger[Trigger.CLICK] = false;
  10783. this._activeTrigger[Trigger.FOCUS] = false;
  10784. this._activeTrigger[Trigger.HOVER] = false;
  10785. if ($$$1(this.tip).hasClass(ClassName.FADE)) {
  10786. var transitionDuration = Util.getTransitionDurationFromElement(tip);
  10787. $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  10788. } else {
  10789. complete();
  10790. }
  10791. this._hoverState = '';
  10792. };
  10793. _proto.update = function update() {
  10794. if (this._popper !== null) {
  10795. this._popper.scheduleUpdate();
  10796. }
  10797. }; // Protected
  10798. _proto.isWithContent = function isWithContent() {
  10799. return Boolean(this.getTitle());
  10800. };
  10801. _proto.addAttachmentClass = function addAttachmentClass(attachment) {
  10802. $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
  10803. };
  10804. _proto.getTipElement = function getTipElement() {
  10805. this.tip = this.tip || $$$1(this.config.template)[0];
  10806. return this.tip;
  10807. };
  10808. _proto.setContent = function setContent() {
  10809. var tip = this.getTipElement();
  10810. this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle());
  10811. $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW);
  10812. };
  10813. _proto.setElementContent = function setElementContent($element, content) {
  10814. var html = this.config.html;
  10815. if (typeof content === 'object' && (content.nodeType || content.jquery)) {
  10816. // Content is a DOM node or a jQuery
  10817. if (html) {
  10818. if (!$$$1(content).parent().is($element)) {
  10819. $element.empty().append(content);
  10820. }
  10821. } else {
  10822. $element.text($$$1(content).text());
  10823. }
  10824. } else {
  10825. $element[html ? 'html' : 'text'](content);
  10826. }
  10827. };
  10828. _proto.getTitle = function getTitle() {
  10829. var title = this.element.getAttribute('data-original-title');
  10830. if (!title) {
  10831. title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
  10832. }
  10833. return title;
  10834. }; // Private
  10835. _proto._getAttachment = function _getAttachment(placement) {
  10836. return AttachmentMap[placement.toUpperCase()];
  10837. };
  10838. _proto._setListeners = function _setListeners() {
  10839. var _this3 = this;
  10840. var triggers = this.config.trigger.split(' ');
  10841. triggers.forEach(function (trigger) {
  10842. if (trigger === 'click') {
  10843. $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {
  10844. return _this3.toggle(event);
  10845. });
  10846. } else if (trigger !== Trigger.MANUAL) {
  10847. var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;
  10848. var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;
  10849. $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) {
  10850. return _this3._enter(event);
  10851. }).on(eventOut, _this3.config.selector, function (event) {
  10852. return _this3._leave(event);
  10853. });
  10854. }
  10855. $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () {
  10856. return _this3.hide();
  10857. });
  10858. });
  10859. if (this.config.selector) {
  10860. this.config = _objectSpread({}, this.config, {
  10861. trigger: 'manual',
  10862. selector: ''
  10863. });
  10864. } else {
  10865. this._fixTitle();
  10866. }
  10867. };
  10868. _proto._fixTitle = function _fixTitle() {
  10869. var titleType = typeof this.element.getAttribute('data-original-title');
  10870. if (this.element.getAttribute('title') || titleType !== 'string') {
  10871. this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
  10872. this.element.setAttribute('title', '');
  10873. }
  10874. };
  10875. _proto._enter = function _enter(event, context) {
  10876. var dataKey = this.constructor.DATA_KEY;
  10877. context = context || $$$1(event.currentTarget).data(dataKey);
  10878. if (!context) {
  10879. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10880. $$$1(event.currentTarget).data(dataKey, context);
  10881. }
  10882. if (event) {
  10883. context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
  10884. }
  10885. if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {
  10886. context._hoverState = HoverState.SHOW;
  10887. return;
  10888. }
  10889. clearTimeout(context._timeout);
  10890. context._hoverState = HoverState.SHOW;
  10891. if (!context.config.delay || !context.config.delay.show) {
  10892. context.show();
  10893. return;
  10894. }
  10895. context._timeout = setTimeout(function () {
  10896. if (context._hoverState === HoverState.SHOW) {
  10897. context.show();
  10898. }
  10899. }, context.config.delay.show);
  10900. };
  10901. _proto._leave = function _leave(event, context) {
  10902. var dataKey = this.constructor.DATA_KEY;
  10903. context = context || $$$1(event.currentTarget).data(dataKey);
  10904. if (!context) {
  10905. context = new this.constructor(event.currentTarget, this._getDelegateConfig());
  10906. $$$1(event.currentTarget).data(dataKey, context);
  10907. }
  10908. if (event) {
  10909. context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
  10910. }
  10911. if (context._isWithActiveTrigger()) {
  10912. return;
  10913. }
  10914. clearTimeout(context._timeout);
  10915. context._hoverState = HoverState.OUT;
  10916. if (!context.config.delay || !context.config.delay.hide) {
  10917. context.hide();
  10918. return;
  10919. }
  10920. context._timeout = setTimeout(function () {
  10921. if (context._hoverState === HoverState.OUT) {
  10922. context.hide();
  10923. }
  10924. }, context.config.delay.hide);
  10925. };
  10926. _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
  10927. for (var trigger in this._activeTrigger) {
  10928. if (this._activeTrigger[trigger]) {
  10929. return true;
  10930. }
  10931. }
  10932. return false;
  10933. };
  10934. _proto._getConfig = function _getConfig(config) {
  10935. config = _objectSpread({}, this.constructor.Default, $$$1(this.element).data(), typeof config === 'object' && config ? config : {});
  10936. if (typeof config.delay === 'number') {
  10937. config.delay = {
  10938. show: config.delay,
  10939. hide: config.delay
  10940. };
  10941. }
  10942. if (typeof config.title === 'number') {
  10943. config.title = config.title.toString();
  10944. }
  10945. if (typeof config.content === 'number') {
  10946. config.content = config.content.toString();
  10947. }
  10948. Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
  10949. return config;
  10950. };
  10951. _proto._getDelegateConfig = function _getDelegateConfig() {
  10952. var config = {};
  10953. if (this.config) {
  10954. for (var key in this.config) {
  10955. if (this.constructor.Default[key] !== this.config[key]) {
  10956. config[key] = this.config[key];
  10957. }
  10958. }
  10959. }
  10960. return config;
  10961. };
  10962. _proto._cleanTipClass = function _cleanTipClass() {
  10963. var $tip = $$$1(this.getTipElement());
  10964. var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
  10965. if (tabClass !== null && tabClass.length) {
  10966. $tip.removeClass(tabClass.join(''));
  10967. }
  10968. };
  10969. _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {
  10970. var popperInstance = popperData.instance;
  10971. this.tip = popperInstance.popper;
  10972. this._cleanTipClass();
  10973. this.addAttachmentClass(this._getAttachment(popperData.placement));
  10974. };
  10975. _proto._fixTransition = function _fixTransition() {
  10976. var tip = this.getTipElement();
  10977. var initConfigAnimation = this.config.animation;
  10978. if (tip.getAttribute('x-placement') !== null) {
  10979. return;
  10980. }
  10981. $$$1(tip).removeClass(ClassName.FADE);
  10982. this.config.animation = false;
  10983. this.hide();
  10984. this.show();
  10985. this.config.animation = initConfigAnimation;
  10986. }; // Static
  10987. Tooltip._jQueryInterface = function _jQueryInterface(config) {
  10988. return this.each(function () {
  10989. var data = $$$1(this).data(DATA_KEY);
  10990. var _config = typeof config === 'object' && config;
  10991. if (!data && /dispose|hide/.test(config)) {
  10992. return;
  10993. }
  10994. if (!data) {
  10995. data = new Tooltip(this, _config);
  10996. $$$1(this).data(DATA_KEY, data);
  10997. }
  10998. if (typeof config === 'string') {
  10999. if (typeof data[config] === 'undefined') {
  11000. throw new TypeError("No method named \"" + config + "\"");
  11001. }
  11002. data[config]();
  11003. }
  11004. });
  11005. };
  11006. _createClass(Tooltip, null, [{
  11007. key: "VERSION",
  11008. get: function get() {
  11009. return VERSION;
  11010. }
  11011. }, {
  11012. key: "Default",
  11013. get: function get() {
  11014. return Default;
  11015. }
  11016. }, {
  11017. key: "NAME",
  11018. get: function get() {
  11019. return NAME;
  11020. }
  11021. }, {
  11022. key: "DATA_KEY",
  11023. get: function get() {
  11024. return DATA_KEY;
  11025. }
  11026. }, {
  11027. key: "Event",
  11028. get: function get() {
  11029. return Event;
  11030. }
  11031. }, {
  11032. key: "EVENT_KEY",
  11033. get: function get() {
  11034. return EVENT_KEY;
  11035. }
  11036. }, {
  11037. key: "DefaultType",
  11038. get: function get() {
  11039. return DefaultType;
  11040. }
  11041. }]);
  11042. return Tooltip;
  11043. }();
  11044. /**
  11045. * ------------------------------------------------------------------------
  11046. * jQuery
  11047. * ------------------------------------------------------------------------
  11048. */
  11049. $$$1.fn[NAME] = Tooltip._jQueryInterface;
  11050. $$$1.fn[NAME].Constructor = Tooltip;
  11051. $$$1.fn[NAME].noConflict = function () {
  11052. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11053. return Tooltip._jQueryInterface;
  11054. };
  11055. return Tooltip;
  11056. }($, Popper);
  11057. /**
  11058. * --------------------------------------------------------------------------
  11059. * Bootstrap (v4.1.3): popover.js
  11060. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11061. * --------------------------------------------------------------------------
  11062. */
  11063. var Popover = function ($$$1) {
  11064. /**
  11065. * ------------------------------------------------------------------------
  11066. * Constants
  11067. * ------------------------------------------------------------------------
  11068. */
  11069. var NAME = 'popover';
  11070. var VERSION = '4.1.3';
  11071. var DATA_KEY = 'bs.popover';
  11072. var EVENT_KEY = "." + DATA_KEY;
  11073. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11074. var CLASS_PREFIX = 'bs-popover';
  11075. var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
  11076. var Default = _objectSpread({}, Tooltip.Default, {
  11077. placement: 'right',
  11078. trigger: 'click',
  11079. content: '',
  11080. template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
  11081. });
  11082. var DefaultType = _objectSpread({}, Tooltip.DefaultType, {
  11083. content: '(string|element|function)'
  11084. });
  11085. var ClassName = {
  11086. FADE: 'fade',
  11087. SHOW: 'show'
  11088. };
  11089. var Selector = {
  11090. TITLE: '.popover-header',
  11091. CONTENT: '.popover-body'
  11092. };
  11093. var Event = {
  11094. HIDE: "hide" + EVENT_KEY,
  11095. HIDDEN: "hidden" + EVENT_KEY,
  11096. SHOW: "show" + EVENT_KEY,
  11097. SHOWN: "shown" + EVENT_KEY,
  11098. INSERTED: "inserted" + EVENT_KEY,
  11099. CLICK: "click" + EVENT_KEY,
  11100. FOCUSIN: "focusin" + EVENT_KEY,
  11101. FOCUSOUT: "focusout" + EVENT_KEY,
  11102. MOUSEENTER: "mouseenter" + EVENT_KEY,
  11103. MOUSELEAVE: "mouseleave" + EVENT_KEY
  11104. /**
  11105. * ------------------------------------------------------------------------
  11106. * Class Definition
  11107. * ------------------------------------------------------------------------
  11108. */
  11109. };
  11110. var Popover =
  11111. /*#__PURE__*/
  11112. function (_Tooltip) {
  11113. _inheritsLoose(Popover, _Tooltip);
  11114. function Popover() {
  11115. return _Tooltip.apply(this, arguments) || this;
  11116. }
  11117. var _proto = Popover.prototype;
  11118. // Overrides
  11119. _proto.isWithContent = function isWithContent() {
  11120. return this.getTitle() || this._getContent();
  11121. };
  11122. _proto.addAttachmentClass = function addAttachmentClass(attachment) {
  11123. $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
  11124. };
  11125. _proto.getTipElement = function getTipElement() {
  11126. this.tip = this.tip || $$$1(this.config.template)[0];
  11127. return this.tip;
  11128. };
  11129. _proto.setContent = function setContent() {
  11130. var $tip = $$$1(this.getTipElement()); // We use append for html objects to maintain js events
  11131. this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
  11132. var content = this._getContent();
  11133. if (typeof content === 'function') {
  11134. content = content.call(this.element);
  11135. }
  11136. this.setElementContent($tip.find(Selector.CONTENT), content);
  11137. $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW);
  11138. }; // Private
  11139. _proto._getContent = function _getContent() {
  11140. return this.element.getAttribute('data-content') || this.config.content;
  11141. };
  11142. _proto._cleanTipClass = function _cleanTipClass() {
  11143. var $tip = $$$1(this.getTipElement());
  11144. var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
  11145. if (tabClass !== null && tabClass.length > 0) {
  11146. $tip.removeClass(tabClass.join(''));
  11147. }
  11148. }; // Static
  11149. Popover._jQueryInterface = function _jQueryInterface(config) {
  11150. return this.each(function () {
  11151. var data = $$$1(this).data(DATA_KEY);
  11152. var _config = typeof config === 'object' ? config : null;
  11153. if (!data && /destroy|hide/.test(config)) {
  11154. return;
  11155. }
  11156. if (!data) {
  11157. data = new Popover(this, _config);
  11158. $$$1(this).data(DATA_KEY, data);
  11159. }
  11160. if (typeof config === 'string') {
  11161. if (typeof data[config] === 'undefined') {
  11162. throw new TypeError("No method named \"" + config + "\"");
  11163. }
  11164. data[config]();
  11165. }
  11166. });
  11167. };
  11168. _createClass(Popover, null, [{
  11169. key: "VERSION",
  11170. // Getters
  11171. get: function get() {
  11172. return VERSION;
  11173. }
  11174. }, {
  11175. key: "Default",
  11176. get: function get() {
  11177. return Default;
  11178. }
  11179. }, {
  11180. key: "NAME",
  11181. get: function get() {
  11182. return NAME;
  11183. }
  11184. }, {
  11185. key: "DATA_KEY",
  11186. get: function get() {
  11187. return DATA_KEY;
  11188. }
  11189. }, {
  11190. key: "Event",
  11191. get: function get() {
  11192. return Event;
  11193. }
  11194. }, {
  11195. key: "EVENT_KEY",
  11196. get: function get() {
  11197. return EVENT_KEY;
  11198. }
  11199. }, {
  11200. key: "DefaultType",
  11201. get: function get() {
  11202. return DefaultType;
  11203. }
  11204. }]);
  11205. return Popover;
  11206. }(Tooltip);
  11207. /**
  11208. * ------------------------------------------------------------------------
  11209. * jQuery
  11210. * ------------------------------------------------------------------------
  11211. */
  11212. $$$1.fn[NAME] = Popover._jQueryInterface;
  11213. $$$1.fn[NAME].Constructor = Popover;
  11214. $$$1.fn[NAME].noConflict = function () {
  11215. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11216. return Popover._jQueryInterface;
  11217. };
  11218. return Popover;
  11219. }($);
  11220. /**
  11221. * --------------------------------------------------------------------------
  11222. * Bootstrap (v4.1.3): scrollspy.js
  11223. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11224. * --------------------------------------------------------------------------
  11225. */
  11226. var ScrollSpy = function ($$$1) {
  11227. /**
  11228. * ------------------------------------------------------------------------
  11229. * Constants
  11230. * ------------------------------------------------------------------------
  11231. */
  11232. var NAME = 'scrollspy';
  11233. var VERSION = '4.1.3';
  11234. var DATA_KEY = 'bs.scrollspy';
  11235. var EVENT_KEY = "." + DATA_KEY;
  11236. var DATA_API_KEY = '.data-api';
  11237. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11238. var Default = {
  11239. offset: 10,
  11240. method: 'auto',
  11241. target: ''
  11242. };
  11243. var DefaultType = {
  11244. offset: 'number',
  11245. method: 'string',
  11246. target: '(string|element)'
  11247. };
  11248. var Event = {
  11249. ACTIVATE: "activate" + EVENT_KEY,
  11250. SCROLL: "scroll" + EVENT_KEY,
  11251. LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
  11252. };
  11253. var ClassName = {
  11254. DROPDOWN_ITEM: 'dropdown-item',
  11255. DROPDOWN_MENU: 'dropdown-menu',
  11256. ACTIVE: 'active'
  11257. };
  11258. var Selector = {
  11259. DATA_SPY: '[data-spy="scroll"]',
  11260. ACTIVE: '.active',
  11261. NAV_LIST_GROUP: '.nav, .list-group',
  11262. NAV_LINKS: '.nav-link',
  11263. NAV_ITEMS: '.nav-item',
  11264. LIST_ITEMS: '.list-group-item',
  11265. DROPDOWN: '.dropdown',
  11266. DROPDOWN_ITEMS: '.dropdown-item',
  11267. DROPDOWN_TOGGLE: '.dropdown-toggle'
  11268. };
  11269. var OffsetMethod = {
  11270. OFFSET: 'offset',
  11271. POSITION: 'position'
  11272. /**
  11273. * ------------------------------------------------------------------------
  11274. * Class Definition
  11275. * ------------------------------------------------------------------------
  11276. */
  11277. };
  11278. var ScrollSpy =
  11279. /*#__PURE__*/
  11280. function () {
  11281. function ScrollSpy(element, config) {
  11282. var _this = this;
  11283. this._element = element;
  11284. this._scrollElement = element.tagName === 'BODY' ? window : element;
  11285. this._config = this._getConfig(config);
  11286. this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
  11287. this._offsets = [];
  11288. this._targets = [];
  11289. this._activeTarget = null;
  11290. this._scrollHeight = 0;
  11291. $$$1(this._scrollElement).on(Event.SCROLL, function (event) {
  11292. return _this._process(event);
  11293. });
  11294. this.refresh();
  11295. this._process();
  11296. } // Getters
  11297. var _proto = ScrollSpy.prototype;
  11298. // Public
  11299. _proto.refresh = function refresh() {
  11300. var _this2 = this;
  11301. var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;
  11302. var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
  11303. var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
  11304. this._offsets = [];
  11305. this._targets = [];
  11306. this._scrollHeight = this._getScrollHeight();
  11307. var targets = [].slice.call(document.querySelectorAll(this._selector));
  11308. targets.map(function (element) {
  11309. var target;
  11310. var targetSelector = Util.getSelectorFromElement(element);
  11311. if (targetSelector) {
  11312. target = document.querySelector(targetSelector);
  11313. }
  11314. if (target) {
  11315. var targetBCR = target.getBoundingClientRect();
  11316. if (targetBCR.width || targetBCR.height) {
  11317. // TODO (fat): remove sketch reliance on jQuery position/offset
  11318. return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector];
  11319. }
  11320. }
  11321. return null;
  11322. }).filter(function (item) {
  11323. return item;
  11324. }).sort(function (a, b) {
  11325. return a[0] - b[0];
  11326. }).forEach(function (item) {
  11327. _this2._offsets.push(item[0]);
  11328. _this2._targets.push(item[1]);
  11329. });
  11330. };
  11331. _proto.dispose = function dispose() {
  11332. $$$1.removeData(this._element, DATA_KEY);
  11333. $$$1(this._scrollElement).off(EVENT_KEY);
  11334. this._element = null;
  11335. this._scrollElement = null;
  11336. this._config = null;
  11337. this._selector = null;
  11338. this._offsets = null;
  11339. this._targets = null;
  11340. this._activeTarget = null;
  11341. this._scrollHeight = null;
  11342. }; // Private
  11343. _proto._getConfig = function _getConfig(config) {
  11344. config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});
  11345. if (typeof config.target !== 'string') {
  11346. var id = $$$1(config.target).attr('id');
  11347. if (!id) {
  11348. id = Util.getUID(NAME);
  11349. $$$1(config.target).attr('id', id);
  11350. }
  11351. config.target = "#" + id;
  11352. }
  11353. Util.typeCheckConfig(NAME, config, DefaultType);
  11354. return config;
  11355. };
  11356. _proto._getScrollTop = function _getScrollTop() {
  11357. return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
  11358. };
  11359. _proto._getScrollHeight = function _getScrollHeight() {
  11360. return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
  11361. };
  11362. _proto._getOffsetHeight = function _getOffsetHeight() {
  11363. return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
  11364. };
  11365. _proto._process = function _process() {
  11366. var scrollTop = this._getScrollTop() + this._config.offset;
  11367. var scrollHeight = this._getScrollHeight();
  11368. var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
  11369. if (this._scrollHeight !== scrollHeight) {
  11370. this.refresh();
  11371. }
  11372. if (scrollTop >= maxScroll) {
  11373. var target = this._targets[this._targets.length - 1];
  11374. if (this._activeTarget !== target) {
  11375. this._activate(target);
  11376. }
  11377. return;
  11378. }
  11379. if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
  11380. this._activeTarget = null;
  11381. this._clear();
  11382. return;
  11383. }
  11384. var offsetLength = this._offsets.length;
  11385. for (var i = offsetLength; i--;) {
  11386. var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
  11387. if (isActiveTarget) {
  11388. this._activate(this._targets[i]);
  11389. }
  11390. }
  11391. };
  11392. _proto._activate = function _activate(target) {
  11393. this._activeTarget = target;
  11394. this._clear();
  11395. var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style
  11396. queries = queries.map(function (selector) {
  11397. return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]");
  11398. });
  11399. var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(','))));
  11400. if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
  11401. $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
  11402. $link.addClass(ClassName.ACTIVE);
  11403. } else {
  11404. // Set triggered link as active
  11405. $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
  11406. // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
  11407. $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
  11408. $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
  11409. }
  11410. $$$1(this._scrollElement).trigger(Event.ACTIVATE, {
  11411. relatedTarget: target
  11412. });
  11413. };
  11414. _proto._clear = function _clear() {
  11415. var nodes = [].slice.call(document.querySelectorAll(this._selector));
  11416. $$$1(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
  11417. }; // Static
  11418. ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
  11419. return this.each(function () {
  11420. var data = $$$1(this).data(DATA_KEY);
  11421. var _config = typeof config === 'object' && config;
  11422. if (!data) {
  11423. data = new ScrollSpy(this, _config);
  11424. $$$1(this).data(DATA_KEY, data);
  11425. }
  11426. if (typeof config === 'string') {
  11427. if (typeof data[config] === 'undefined') {
  11428. throw new TypeError("No method named \"" + config + "\"");
  11429. }
  11430. data[config]();
  11431. }
  11432. });
  11433. };
  11434. _createClass(ScrollSpy, null, [{
  11435. key: "VERSION",
  11436. get: function get() {
  11437. return VERSION;
  11438. }
  11439. }, {
  11440. key: "Default",
  11441. get: function get() {
  11442. return Default;
  11443. }
  11444. }]);
  11445. return ScrollSpy;
  11446. }();
  11447. /**
  11448. * ------------------------------------------------------------------------
  11449. * Data Api implementation
  11450. * ------------------------------------------------------------------------
  11451. */
  11452. $$$1(window).on(Event.LOAD_DATA_API, function () {
  11453. var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));
  11454. var scrollSpysLength = scrollSpys.length;
  11455. for (var i = scrollSpysLength; i--;) {
  11456. var $spy = $$$1(scrollSpys[i]);
  11457. ScrollSpy._jQueryInterface.call($spy, $spy.data());
  11458. }
  11459. });
  11460. /**
  11461. * ------------------------------------------------------------------------
  11462. * jQuery
  11463. * ------------------------------------------------------------------------
  11464. */
  11465. $$$1.fn[NAME] = ScrollSpy._jQueryInterface;
  11466. $$$1.fn[NAME].Constructor = ScrollSpy;
  11467. $$$1.fn[NAME].noConflict = function () {
  11468. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11469. return ScrollSpy._jQueryInterface;
  11470. };
  11471. return ScrollSpy;
  11472. }($);
  11473. /**
  11474. * --------------------------------------------------------------------------
  11475. * Bootstrap (v4.1.3): tab.js
  11476. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11477. * --------------------------------------------------------------------------
  11478. */
  11479. var Tab = function ($$$1) {
  11480. /**
  11481. * ------------------------------------------------------------------------
  11482. * Constants
  11483. * ------------------------------------------------------------------------
  11484. */
  11485. var NAME = 'tab';
  11486. var VERSION = '4.1.3';
  11487. var DATA_KEY = 'bs.tab';
  11488. var EVENT_KEY = "." + DATA_KEY;
  11489. var DATA_API_KEY = '.data-api';
  11490. var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
  11491. var Event = {
  11492. HIDE: "hide" + EVENT_KEY,
  11493. HIDDEN: "hidden" + EVENT_KEY,
  11494. SHOW: "show" + EVENT_KEY,
  11495. SHOWN: "shown" + EVENT_KEY,
  11496. CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
  11497. };
  11498. var ClassName = {
  11499. DROPDOWN_MENU: 'dropdown-menu',
  11500. ACTIVE: 'active',
  11501. DISABLED: 'disabled',
  11502. FADE: 'fade',
  11503. SHOW: 'show'
  11504. };
  11505. var Selector = {
  11506. DROPDOWN: '.dropdown',
  11507. NAV_LIST_GROUP: '.nav, .list-group',
  11508. ACTIVE: '.active',
  11509. ACTIVE_UL: '> li > .active',
  11510. DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
  11511. DROPDOWN_TOGGLE: '.dropdown-toggle',
  11512. DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
  11513. /**
  11514. * ------------------------------------------------------------------------
  11515. * Class Definition
  11516. * ------------------------------------------------------------------------
  11517. */
  11518. };
  11519. var Tab =
  11520. /*#__PURE__*/
  11521. function () {
  11522. function Tab(element) {
  11523. this._element = element;
  11524. } // Getters
  11525. var _proto = Tab.prototype;
  11526. // Public
  11527. _proto.show = function show() {
  11528. var _this = this;
  11529. if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $$$1(this._element).hasClass(ClassName.ACTIVE) || $$$1(this._element).hasClass(ClassName.DISABLED)) {
  11530. return;
  11531. }
  11532. var target;
  11533. var previous;
  11534. var listElement = $$$1(this._element).closest(Selector.NAV_LIST_GROUP)[0];
  11535. var selector = Util.getSelectorFromElement(this._element);
  11536. if (listElement) {
  11537. var itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE;
  11538. previous = $$$1.makeArray($$$1(listElement).find(itemSelector));
  11539. previous = previous[previous.length - 1];
  11540. }
  11541. var hideEvent = $$$1.Event(Event.HIDE, {
  11542. relatedTarget: this._element
  11543. });
  11544. var showEvent = $$$1.Event(Event.SHOW, {
  11545. relatedTarget: previous
  11546. });
  11547. if (previous) {
  11548. $$$1(previous).trigger(hideEvent);
  11549. }
  11550. $$$1(this._element).trigger(showEvent);
  11551. if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
  11552. return;
  11553. }
  11554. if (selector) {
  11555. target = document.querySelector(selector);
  11556. }
  11557. this._activate(this._element, listElement);
  11558. var complete = function complete() {
  11559. var hiddenEvent = $$$1.Event(Event.HIDDEN, {
  11560. relatedTarget: _this._element
  11561. });
  11562. var shownEvent = $$$1.Event(Event.SHOWN, {
  11563. relatedTarget: previous
  11564. });
  11565. $$$1(previous).trigger(hiddenEvent);
  11566. $$$1(_this._element).trigger(shownEvent);
  11567. };
  11568. if (target) {
  11569. this._activate(target, target.parentNode, complete);
  11570. } else {
  11571. complete();
  11572. }
  11573. };
  11574. _proto.dispose = function dispose() {
  11575. $$$1.removeData(this._element, DATA_KEY);
  11576. this._element = null;
  11577. }; // Private
  11578. _proto._activate = function _activate(element, container, callback) {
  11579. var _this2 = this;
  11580. var activeElements;
  11581. if (container.nodeName === 'UL') {
  11582. activeElements = $$$1(container).find(Selector.ACTIVE_UL);
  11583. } else {
  11584. activeElements = $$$1(container).children(Selector.ACTIVE);
  11585. }
  11586. var active = activeElements[0];
  11587. var isTransitioning = callback && active && $$$1(active).hasClass(ClassName.FADE);
  11588. var complete = function complete() {
  11589. return _this2._transitionComplete(element, active, callback);
  11590. };
  11591. if (active && isTransitioning) {
  11592. var transitionDuration = Util.getTransitionDurationFromElement(active);
  11593. $$$1(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
  11594. } else {
  11595. complete();
  11596. }
  11597. };
  11598. _proto._transitionComplete = function _transitionComplete(element, active, callback) {
  11599. if (active) {
  11600. $$$1(active).removeClass(ClassName.SHOW + " " + ClassName.ACTIVE);
  11601. var dropdownChild = $$$1(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
  11602. if (dropdownChild) {
  11603. $$$1(dropdownChild).removeClass(ClassName.ACTIVE);
  11604. }
  11605. if (active.getAttribute('role') === 'tab') {
  11606. active.setAttribute('aria-selected', false);
  11607. }
  11608. }
  11609. $$$1(element).addClass(ClassName.ACTIVE);
  11610. if (element.getAttribute('role') === 'tab') {
  11611. element.setAttribute('aria-selected', true);
  11612. }
  11613. Util.reflow(element);
  11614. $$$1(element).addClass(ClassName.SHOW);
  11615. if (element.parentNode && $$$1(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
  11616. var dropdownElement = $$$1(element).closest(Selector.DROPDOWN)[0];
  11617. if (dropdownElement) {
  11618. var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE));
  11619. $$$1(dropdownToggleList).addClass(ClassName.ACTIVE);
  11620. }
  11621. element.setAttribute('aria-expanded', true);
  11622. }
  11623. if (callback) {
  11624. callback();
  11625. }
  11626. }; // Static
  11627. Tab._jQueryInterface = function _jQueryInterface(config) {
  11628. return this.each(function () {
  11629. var $this = $$$1(this);
  11630. var data = $this.data(DATA_KEY);
  11631. if (!data) {
  11632. data = new Tab(this);
  11633. $this.data(DATA_KEY, data);
  11634. }
  11635. if (typeof config === 'string') {
  11636. if (typeof data[config] === 'undefined') {
  11637. throw new TypeError("No method named \"" + config + "\"");
  11638. }
  11639. data[config]();
  11640. }
  11641. });
  11642. };
  11643. _createClass(Tab, null, [{
  11644. key: "VERSION",
  11645. get: function get() {
  11646. return VERSION;
  11647. }
  11648. }]);
  11649. return Tab;
  11650. }();
  11651. /**
  11652. * ------------------------------------------------------------------------
  11653. * Data Api implementation
  11654. * ------------------------------------------------------------------------
  11655. */
  11656. $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  11657. event.preventDefault();
  11658. Tab._jQueryInterface.call($$$1(this), 'show');
  11659. });
  11660. /**
  11661. * ------------------------------------------------------------------------
  11662. * jQuery
  11663. * ------------------------------------------------------------------------
  11664. */
  11665. $$$1.fn[NAME] = Tab._jQueryInterface;
  11666. $$$1.fn[NAME].Constructor = Tab;
  11667. $$$1.fn[NAME].noConflict = function () {
  11668. $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
  11669. return Tab._jQueryInterface;
  11670. };
  11671. return Tab;
  11672. }($);
  11673. /**
  11674. * --------------------------------------------------------------------------
  11675. * Bootstrap (v4.1.3): index.js
  11676. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11677. * --------------------------------------------------------------------------
  11678. */
  11679. (function ($$$1) {
  11680. if (typeof $$$1 === 'undefined') {
  11681. throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.');
  11682. }
  11683. var version = $$$1.fn.jquery.split(' ')[0].split('.');
  11684. var minMajor = 1;
  11685. var ltMajor = 2;
  11686. var minMinor = 9;
  11687. var minPatch = 1;
  11688. var maxMajor = 4;
  11689. if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
  11690. throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');
  11691. }
  11692. })($);
  11693. exports.Util = Util;
  11694. exports.Alert = Alert;
  11695. exports.Button = Button;
  11696. exports.Carousel = Carousel;
  11697. exports.Collapse = Collapse;
  11698. exports.Dropdown = Dropdown;
  11699. exports.Modal = Modal;
  11700. exports.Popover = Popover;
  11701. exports.Scrollspy = ScrollSpy;
  11702. exports.Tab = Tab;
  11703. exports.Tooltip = Tooltip;
  11704. Object.defineProperty(exports, '__esModule', { value: true });
  11705. })));
  11706. //# sourceMappingURL=bootstrap.js.map
  11707. /***/ }),
  11708. /* 3 */
  11709. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  11710. "use strict";
  11711. Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
  11712. /* WEBPACK VAR INJECTION */(function(global) {/**!
  11713. * @fileOverview Kickass library to create and place poppers near their reference elements.
  11714. * @version 1.14.4
  11715. * @license
  11716. * Copyright (c) 2016 Federico Zivolo and contributors
  11717. *
  11718. * Permission is hereby granted, free of charge, to any person obtaining a copy
  11719. * of this software and associated documentation files (the "Software"), to deal
  11720. * in the Software without restriction, including without limitation the rights
  11721. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11722. * copies of the Software, and to permit persons to whom the Software is
  11723. * furnished to do so, subject to the following conditions:
  11724. *
  11725. * The above copyright notice and this permission notice shall be included in all
  11726. * copies or substantial portions of the Software.
  11727. *
  11728. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11729. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  11730. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11731. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11732. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  11733. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  11734. * SOFTWARE.
  11735. */
  11736. var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
  11737. var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
  11738. var timeoutDuration = 0;
  11739. for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
  11740. if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
  11741. timeoutDuration = 1;
  11742. break;
  11743. }
  11744. }
  11745. function microtaskDebounce(fn) {
  11746. var called = false;
  11747. return function () {
  11748. if (called) {
  11749. return;
  11750. }
  11751. called = true;
  11752. window.Promise.resolve().then(function () {
  11753. called = false;
  11754. fn();
  11755. });
  11756. };
  11757. }
  11758. function taskDebounce(fn) {
  11759. var scheduled = false;
  11760. return function () {
  11761. if (!scheduled) {
  11762. scheduled = true;
  11763. setTimeout(function () {
  11764. scheduled = false;
  11765. fn();
  11766. }, timeoutDuration);
  11767. }
  11768. };
  11769. }
  11770. var supportsMicroTasks = isBrowser && window.Promise;
  11771. /**
  11772. * Create a debounced version of a method, that's asynchronously deferred
  11773. * but called in the minimum time possible.
  11774. *
  11775. * @method
  11776. * @memberof Popper.Utils
  11777. * @argument {Function} fn
  11778. * @returns {Function}
  11779. */
  11780. var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
  11781. /**
  11782. * Check if the given variable is a function
  11783. * @method
  11784. * @memberof Popper.Utils
  11785. * @argument {Any} functionToCheck - variable to check
  11786. * @returns {Boolean} answer to: is a function?
  11787. */
  11788. function isFunction(functionToCheck) {
  11789. var getType = {};
  11790. return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
  11791. }
  11792. /**
  11793. * Get CSS computed property of the given element
  11794. * @method
  11795. * @memberof Popper.Utils
  11796. * @argument {Eement} element
  11797. * @argument {String} property
  11798. */
  11799. function getStyleComputedProperty(element, property) {
  11800. if (element.nodeType !== 1) {
  11801. return [];
  11802. }
  11803. // NOTE: 1 DOM access here
  11804. var css = getComputedStyle(element, null);
  11805. return property ? css[property] : css;
  11806. }
  11807. /**
  11808. * Returns the parentNode or the host of the element
  11809. * @method
  11810. * @memberof Popper.Utils
  11811. * @argument {Element} element
  11812. * @returns {Element} parent
  11813. */
  11814. function getParentNode(element) {
  11815. if (element.nodeName === 'HTML') {
  11816. return element;
  11817. }
  11818. return element.parentNode || element.host;
  11819. }
  11820. /**
  11821. * Returns the scrolling parent of the given element
  11822. * @method
  11823. * @memberof Popper.Utils
  11824. * @argument {Element} element
  11825. * @returns {Element} scroll parent
  11826. */
  11827. function getScrollParent(element) {
  11828. // Return body, `getScroll` will take care to get the correct `scrollTop` from it
  11829. if (!element) {
  11830. return document.body;
  11831. }
  11832. switch (element.nodeName) {
  11833. case 'HTML':
  11834. case 'BODY':
  11835. return element.ownerDocument.body;
  11836. case '#document':
  11837. return element.body;
  11838. }
  11839. // Firefox want us to check `-x` and `-y` variations as well
  11840. var _getStyleComputedProp = getStyleComputedProperty(element),
  11841. overflow = _getStyleComputedProp.overflow,
  11842. overflowX = _getStyleComputedProp.overflowX,
  11843. overflowY = _getStyleComputedProp.overflowY;
  11844. if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
  11845. return element;
  11846. }
  11847. return getScrollParent(getParentNode(element));
  11848. }
  11849. var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
  11850. var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
  11851. /**
  11852. * Determines if the browser is Internet Explorer
  11853. * @method
  11854. * @memberof Popper.Utils
  11855. * @param {Number} version to check
  11856. * @returns {Boolean} isIE
  11857. */
  11858. function isIE(version) {
  11859. if (version === 11) {
  11860. return isIE11;
  11861. }
  11862. if (version === 10) {
  11863. return isIE10;
  11864. }
  11865. return isIE11 || isIE10;
  11866. }
  11867. /**
  11868. * Returns the offset parent of the given element
  11869. * @method
  11870. * @memberof Popper.Utils
  11871. * @argument {Element} element
  11872. * @returns {Element} offset parent
  11873. */
  11874. function getOffsetParent(element) {
  11875. if (!element) {
  11876. return document.documentElement;
  11877. }
  11878. var noOffsetParent = isIE(10) ? document.body : null;
  11879. // NOTE: 1 DOM access here
  11880. var offsetParent = element.offsetParent;
  11881. // Skip hidden elements which don't have an offsetParent
  11882. while (offsetParent === noOffsetParent && element.nextElementSibling) {
  11883. offsetParent = (element = element.nextElementSibling).offsetParent;
  11884. }
  11885. var nodeName = offsetParent && offsetParent.nodeName;
  11886. if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
  11887. return element ? element.ownerDocument.documentElement : document.documentElement;
  11888. }
  11889. // .offsetParent will return the closest TD or TABLE in case
  11890. // no offsetParent is present, I hate this job...
  11891. if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
  11892. return getOffsetParent(offsetParent);
  11893. }
  11894. return offsetParent;
  11895. }
  11896. function isOffsetContainer(element) {
  11897. var nodeName = element.nodeName;
  11898. if (nodeName === 'BODY') {
  11899. return false;
  11900. }
  11901. return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
  11902. }
  11903. /**
  11904. * Finds the root node (document, shadowDOM root) of the given element
  11905. * @method
  11906. * @memberof Popper.Utils
  11907. * @argument {Element} node
  11908. * @returns {Element} root node
  11909. */
  11910. function getRoot(node) {
  11911. if (node.parentNode !== null) {
  11912. return getRoot(node.parentNode);
  11913. }
  11914. return node;
  11915. }
  11916. /**
  11917. * Finds the offset parent common to the two provided nodes
  11918. * @method
  11919. * @memberof Popper.Utils
  11920. * @argument {Element} element1
  11921. * @argument {Element} element2
  11922. * @returns {Element} common offset parent
  11923. */
  11924. function findCommonOffsetParent(element1, element2) {
  11925. // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  11926. if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
  11927. return document.documentElement;
  11928. }
  11929. // Here we make sure to give as "start" the element that comes first in the DOM
  11930. var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
  11931. var start = order ? element1 : element2;
  11932. var end = order ? element2 : element1;
  11933. // Get common ancestor container
  11934. var range = document.createRange();
  11935. range.setStart(start, 0);
  11936. range.setEnd(end, 0);
  11937. var commonAncestorContainer = range.commonAncestorContainer;
  11938. // Both nodes are inside #document
  11939. if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
  11940. if (isOffsetContainer(commonAncestorContainer)) {
  11941. return commonAncestorContainer;
  11942. }
  11943. return getOffsetParent(commonAncestorContainer);
  11944. }
  11945. // one of the nodes is inside shadowDOM, find which one
  11946. var element1root = getRoot(element1);
  11947. if (element1root.host) {
  11948. return findCommonOffsetParent(element1root.host, element2);
  11949. } else {
  11950. return findCommonOffsetParent(element1, getRoot(element2).host);
  11951. }
  11952. }
  11953. /**
  11954. * Gets the scroll value of the given element in the given side (top and left)
  11955. * @method
  11956. * @memberof Popper.Utils
  11957. * @argument {Element} element
  11958. * @argument {String} side `top` or `left`
  11959. * @returns {number} amount of scrolled pixels
  11960. */
  11961. function getScroll(element) {
  11962. var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
  11963. var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
  11964. var nodeName = element.nodeName;
  11965. if (nodeName === 'BODY' || nodeName === 'HTML') {
  11966. var html = element.ownerDocument.documentElement;
  11967. var scrollingElement = element.ownerDocument.scrollingElement || html;
  11968. return scrollingElement[upperSide];
  11969. }
  11970. return element[upperSide];
  11971. }
  11972. /*
  11973. * Sum or subtract the element scroll values (left and top) from a given rect object
  11974. * @method
  11975. * @memberof Popper.Utils
  11976. * @param {Object} rect - Rect object you want to change
  11977. * @param {HTMLElement} element - The element from the function reads the scroll values
  11978. * @param {Boolean} subtract - set to true if you want to subtract the scroll values
  11979. * @return {Object} rect - The modifier rect object
  11980. */
  11981. function includeScroll(rect, element) {
  11982. var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  11983. var scrollTop = getScroll(element, 'top');
  11984. var scrollLeft = getScroll(element, 'left');
  11985. var modifier = subtract ? -1 : 1;
  11986. rect.top += scrollTop * modifier;
  11987. rect.bottom += scrollTop * modifier;
  11988. rect.left += scrollLeft * modifier;
  11989. rect.right += scrollLeft * modifier;
  11990. return rect;
  11991. }
  11992. /*
  11993. * Helper to detect borders of a given element
  11994. * @method
  11995. * @memberof Popper.Utils
  11996. * @param {CSSStyleDeclaration} styles
  11997. * Result of `getStyleComputedProperty` on the given element
  11998. * @param {String} axis - `x` or `y`
  11999. * @return {number} borders - The borders size of the given axis
  12000. */
  12001. function getBordersSize(styles, axis) {
  12002. var sideA = axis === 'x' ? 'Left' : 'Top';
  12003. var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
  12004. return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
  12005. }
  12006. function getSize(axis, body, html, computedStyle) {
  12007. 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);
  12008. }
  12009. function getWindowSizes(document) {
  12010. var body = document.body;
  12011. var html = document.documentElement;
  12012. var computedStyle = isIE(10) && getComputedStyle(html);
  12013. return {
  12014. height: getSize('Height', body, html, computedStyle),
  12015. width: getSize('Width', body, html, computedStyle)
  12016. };
  12017. }
  12018. var classCallCheck = function (instance, Constructor) {
  12019. if (!(instance instanceof Constructor)) {
  12020. throw new TypeError("Cannot call a class as a function");
  12021. }
  12022. };
  12023. var createClass = function () {
  12024. function defineProperties(target, props) {
  12025. for (var i = 0; i < props.length; i++) {
  12026. var descriptor = props[i];
  12027. descriptor.enumerable = descriptor.enumerable || false;
  12028. descriptor.configurable = true;
  12029. if ("value" in descriptor) descriptor.writable = true;
  12030. Object.defineProperty(target, descriptor.key, descriptor);
  12031. }
  12032. }
  12033. return function (Constructor, protoProps, staticProps) {
  12034. if (protoProps) defineProperties(Constructor.prototype, protoProps);
  12035. if (staticProps) defineProperties(Constructor, staticProps);
  12036. return Constructor;
  12037. };
  12038. }();
  12039. var defineProperty = function (obj, key, value) {
  12040. if (key in obj) {
  12041. Object.defineProperty(obj, key, {
  12042. value: value,
  12043. enumerable: true,
  12044. configurable: true,
  12045. writable: true
  12046. });
  12047. } else {
  12048. obj[key] = value;
  12049. }
  12050. return obj;
  12051. };
  12052. var _extends = Object.assign || function (target) {
  12053. for (var i = 1; i < arguments.length; i++) {
  12054. var source = arguments[i];
  12055. for (var key in source) {
  12056. if (Object.prototype.hasOwnProperty.call(source, key)) {
  12057. target[key] = source[key];
  12058. }
  12059. }
  12060. }
  12061. return target;
  12062. };
  12063. /**
  12064. * Given element offsets, generate an output similar to getBoundingClientRect
  12065. * @method
  12066. * @memberof Popper.Utils
  12067. * @argument {Object} offsets
  12068. * @returns {Object} ClientRect like output
  12069. */
  12070. function getClientRect(offsets) {
  12071. return _extends({}, offsets, {
  12072. right: offsets.left + offsets.width,
  12073. bottom: offsets.top + offsets.height
  12074. });
  12075. }
  12076. /**
  12077. * Get bounding client rect of given element
  12078. * @method
  12079. * @memberof Popper.Utils
  12080. * @param {HTMLElement} element
  12081. * @return {Object} client rect
  12082. */
  12083. function getBoundingClientRect(element) {
  12084. var rect = {};
  12085. // IE10 10 FIX: Please, don't ask, the element isn't
  12086. // considered in DOM in some circumstances...
  12087. // This isn't reproducible in IE10 compatibility mode of IE11
  12088. try {
  12089. if (isIE(10)) {
  12090. rect = element.getBoundingClientRect();
  12091. var scrollTop = getScroll(element, 'top');
  12092. var scrollLeft = getScroll(element, 'left');
  12093. rect.top += scrollTop;
  12094. rect.left += scrollLeft;
  12095. rect.bottom += scrollTop;
  12096. rect.right += scrollLeft;
  12097. } else {
  12098. rect = element.getBoundingClientRect();
  12099. }
  12100. } catch (e) {}
  12101. var result = {
  12102. left: rect.left,
  12103. top: rect.top,
  12104. width: rect.right - rect.left,
  12105. height: rect.bottom - rect.top
  12106. };
  12107. // subtract scrollbar size from sizes
  12108. var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
  12109. var width = sizes.width || element.clientWidth || result.right - result.left;
  12110. var height = sizes.height || element.clientHeight || result.bottom - result.top;
  12111. var horizScrollbar = element.offsetWidth - width;
  12112. var vertScrollbar = element.offsetHeight - height;
  12113. // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
  12114. // we make this check conditional for performance reasons
  12115. if (horizScrollbar || vertScrollbar) {
  12116. var styles = getStyleComputedProperty(element);
  12117. horizScrollbar -= getBordersSize(styles, 'x');
  12118. vertScrollbar -= getBordersSize(styles, 'y');
  12119. result.width -= horizScrollbar;
  12120. result.height -= vertScrollbar;
  12121. }
  12122. return getClientRect(result);
  12123. }
  12124. function getOffsetRectRelativeToArbitraryNode(children, parent) {
  12125. var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  12126. var isIE10 = isIE(10);
  12127. var isHTML = parent.nodeName === 'HTML';
  12128. var childrenRect = getBoundingClientRect(children);
  12129. var parentRect = getBoundingClientRect(parent);
  12130. var scrollParent = getScrollParent(children);
  12131. var styles = getStyleComputedProperty(parent);
  12132. var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
  12133. var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
  12134. // In cases where the parent is fixed, we must ignore negative scroll in offset calc
  12135. if (fixedPosition && isHTML) {
  12136. parentRect.top = Math.max(parentRect.top, 0);
  12137. parentRect.left = Math.max(parentRect.left, 0);
  12138. }
  12139. var offsets = getClientRect({
  12140. top: childrenRect.top - parentRect.top - borderTopWidth,
  12141. left: childrenRect.left - parentRect.left - borderLeftWidth,
  12142. width: childrenRect.width,
  12143. height: childrenRect.height
  12144. });
  12145. offsets.marginTop = 0;
  12146. offsets.marginLeft = 0;
  12147. // Subtract margins of documentElement in case it's being used as parent
  12148. // we do this only on HTML because it's the only element that behaves
  12149. // differently when margins are applied to it. The margins are included in
  12150. // the box of the documentElement, in the other cases not.
  12151. if (!isIE10 && isHTML) {
  12152. var marginTop = parseFloat(styles.marginTop, 10);
  12153. var marginLeft = parseFloat(styles.marginLeft, 10);
  12154. offsets.top -= borderTopWidth - marginTop;
  12155. offsets.bottom -= borderTopWidth - marginTop;
  12156. offsets.left -= borderLeftWidth - marginLeft;
  12157. offsets.right -= borderLeftWidth - marginLeft;
  12158. // Attach marginTop and marginLeft because in some circumstances we may need them
  12159. offsets.marginTop = marginTop;
  12160. offsets.marginLeft = marginLeft;
  12161. }
  12162. if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
  12163. offsets = includeScroll(offsets, parent);
  12164. }
  12165. return offsets;
  12166. }
  12167. function getViewportOffsetRectRelativeToArtbitraryNode(element) {
  12168. var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  12169. var html = element.ownerDocument.documentElement;
  12170. var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
  12171. var width = Math.max(html.clientWidth, window.innerWidth || 0);
  12172. var height = Math.max(html.clientHeight, window.innerHeight || 0);
  12173. var scrollTop = !excludeScroll ? getScroll(html) : 0;
  12174. var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
  12175. var offset = {
  12176. top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
  12177. left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
  12178. width: width,
  12179. height: height
  12180. };
  12181. return getClientRect(offset);
  12182. }
  12183. /**
  12184. * Check if the given element is fixed or is inside a fixed parent
  12185. * @method
  12186. * @memberof Popper.Utils
  12187. * @argument {Element} element
  12188. * @argument {Element} customContainer
  12189. * @returns {Boolean} answer to "isFixed?"
  12190. */
  12191. function isFixed(element) {
  12192. var nodeName = element.nodeName;
  12193. if (nodeName === 'BODY' || nodeName === 'HTML') {
  12194. return false;
  12195. }
  12196. if (getStyleComputedProperty(element, 'position') === 'fixed') {
  12197. return true;
  12198. }
  12199. return isFixed(getParentNode(element));
  12200. }
  12201. /**
  12202. * Finds the first parent of an element that has a transformed property defined
  12203. * @method
  12204. * @memberof Popper.Utils
  12205. * @argument {Element} element
  12206. * @returns {Element} first transformed parent or documentElement
  12207. */
  12208. function getFixedPositionOffsetParent(element) {
  12209. // This check is needed to avoid errors in case one of the elements isn't defined for any reason
  12210. if (!element || !element.parentElement || isIE()) {
  12211. return document.documentElement;
  12212. }
  12213. var el = element.parentElement;
  12214. while (el && getStyleComputedProperty(el, 'transform') === 'none') {
  12215. el = el.parentElement;
  12216. }
  12217. return el || document.documentElement;
  12218. }
  12219. /**
  12220. * Computed the boundaries limits and return them
  12221. * @method
  12222. * @memberof Popper.Utils
  12223. * @param {HTMLElement} popper
  12224. * @param {HTMLElement} reference
  12225. * @param {number} padding
  12226. * @param {HTMLElement} boundariesElement - Element used to define the boundaries
  12227. * @param {Boolean} fixedPosition - Is in fixed position mode
  12228. * @returns {Object} Coordinates of the boundaries
  12229. */
  12230. function getBoundaries(popper, reference, padding, boundariesElement) {
  12231. var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
  12232. // NOTE: 1 DOM access here
  12233. var boundaries = { top: 0, left: 0 };
  12234. var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
  12235. // Handle viewport case
  12236. if (boundariesElement === 'viewport') {
  12237. boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
  12238. } else {
  12239. // Handle other cases based on DOM element used as boundaries
  12240. var boundariesNode = void 0;
  12241. if (boundariesElement === 'scrollParent') {
  12242. boundariesNode = getScrollParent(getParentNode(reference));
  12243. if (boundariesNode.nodeName === 'BODY') {
  12244. boundariesNode = popper.ownerDocument.documentElement;
  12245. }
  12246. } else if (boundariesElement === 'window') {
  12247. boundariesNode = popper.ownerDocument.documentElement;
  12248. } else {
  12249. boundariesNode = boundariesElement;
  12250. }
  12251. var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
  12252. // In case of HTML, we need a different computation
  12253. if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
  12254. var _getWindowSizes = getWindowSizes(popper.ownerDocument),
  12255. height = _getWindowSizes.height,
  12256. width = _getWindowSizes.width;
  12257. boundaries.top += offsets.top - offsets.marginTop;
  12258. boundaries.bottom = height + offsets.top;
  12259. boundaries.left += offsets.left - offsets.marginLeft;
  12260. boundaries.right = width + offsets.left;
  12261. } else {
  12262. // for all the other DOM elements, this one is good
  12263. boundaries = offsets;
  12264. }
  12265. }
  12266. // Add paddings
  12267. padding = padding || 0;
  12268. var isPaddingNumber = typeof padding === 'number';
  12269. boundaries.left += isPaddingNumber ? padding : padding.left || 0;
  12270. boundaries.top += isPaddingNumber ? padding : padding.top || 0;
  12271. boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
  12272. boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
  12273. return boundaries;
  12274. }
  12275. function getArea(_ref) {
  12276. var width = _ref.width,
  12277. height = _ref.height;
  12278. return width * height;
  12279. }
  12280. /**
  12281. * Utility used to transform the `auto` placement to the placement with more
  12282. * available space.
  12283. * @method
  12284. * @memberof Popper.Utils
  12285. * @argument {Object} data - The data object generated by update method
  12286. * @argument {Object} options - Modifiers configuration and options
  12287. * @returns {Object} The data object, properly modified
  12288. */
  12289. function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
  12290. var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
  12291. if (placement.indexOf('auto') === -1) {
  12292. return placement;
  12293. }
  12294. var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
  12295. var rects = {
  12296. top: {
  12297. width: boundaries.width,
  12298. height: refRect.top - boundaries.top
  12299. },
  12300. right: {
  12301. width: boundaries.right - refRect.right,
  12302. height: boundaries.height
  12303. },
  12304. bottom: {
  12305. width: boundaries.width,
  12306. height: boundaries.bottom - refRect.bottom
  12307. },
  12308. left: {
  12309. width: refRect.left - boundaries.left,
  12310. height: boundaries.height
  12311. }
  12312. };
  12313. var sortedAreas = Object.keys(rects).map(function (key) {
  12314. return _extends({
  12315. key: key
  12316. }, rects[key], {
  12317. area: getArea(rects[key])
  12318. });
  12319. }).sort(function (a, b) {
  12320. return b.area - a.area;
  12321. });
  12322. var filteredAreas = sortedAreas.filter(function (_ref2) {
  12323. var width = _ref2.width,
  12324. height = _ref2.height;
  12325. return width >= popper.clientWidth && height >= popper.clientHeight;
  12326. });
  12327. var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
  12328. var variation = placement.split('-')[1];
  12329. return computedPlacement + (variation ? '-' + variation : '');
  12330. }
  12331. /**
  12332. * Get offsets to the reference element
  12333. * @method
  12334. * @memberof Popper.Utils
  12335. * @param {Object} state
  12336. * @param {Element} popper - the popper element
  12337. * @param {Element} reference - the reference element (the popper will be relative to this)
  12338. * @param {Element} fixedPosition - is in fixed position mode
  12339. * @returns {Object} An object containing the offsets which will be applied to the popper
  12340. */
  12341. function getReferenceOffsets(state, popper, reference) {
  12342. var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  12343. var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
  12344. return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
  12345. }
  12346. /**
  12347. * Get the outer sizes of the given element (offset size + margins)
  12348. * @method
  12349. * @memberof Popper.Utils
  12350. * @argument {Element} element
  12351. * @returns {Object} object containing width and height properties
  12352. */
  12353. function getOuterSizes(element) {
  12354. var styles = getComputedStyle(element);
  12355. var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
  12356. var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
  12357. var result = {
  12358. width: element.offsetWidth + y,
  12359. height: element.offsetHeight + x
  12360. };
  12361. return result;
  12362. }
  12363. /**
  12364. * Get the opposite placement of the given one
  12365. * @method
  12366. * @memberof Popper.Utils
  12367. * @argument {String} placement
  12368. * @returns {String} flipped placement
  12369. */
  12370. function getOppositePlacement(placement) {
  12371. var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
  12372. return placement.replace(/left|right|bottom|top/g, function (matched) {
  12373. return hash[matched];
  12374. });
  12375. }
  12376. /**
  12377. * Get offsets to the popper
  12378. * @method
  12379. * @memberof Popper.Utils
  12380. * @param {Object} position - CSS position the Popper will get applied
  12381. * @param {HTMLElement} popper - the popper element
  12382. * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
  12383. * @param {String} placement - one of the valid placement options
  12384. * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
  12385. */
  12386. function getPopperOffsets(popper, referenceOffsets, placement) {
  12387. placement = placement.split('-')[0];
  12388. // Get popper node sizes
  12389. var popperRect = getOuterSizes(popper);
  12390. // Add position, width and height to our offsets object
  12391. var popperOffsets = {
  12392. width: popperRect.width,
  12393. height: popperRect.height
  12394. };
  12395. // depending by the popper placement we have to compute its offsets slightly differently
  12396. var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
  12397. var mainSide = isHoriz ? 'top' : 'left';
  12398. var secondarySide = isHoriz ? 'left' : 'top';
  12399. var measurement = isHoriz ? 'height' : 'width';
  12400. var secondaryMeasurement = !isHoriz ? 'height' : 'width';
  12401. popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
  12402. if (placement === secondarySide) {
  12403. popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
  12404. } else {
  12405. popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
  12406. }
  12407. return popperOffsets;
  12408. }
  12409. /**
  12410. * Mimics the `find` method of Array
  12411. * @method
  12412. * @memberof Popper.Utils
  12413. * @argument {Array} arr
  12414. * @argument prop
  12415. * @argument value
  12416. * @returns index or -1
  12417. */
  12418. function find(arr, check) {
  12419. // use native find if supported
  12420. if (Array.prototype.find) {
  12421. return arr.find(check);
  12422. }
  12423. // use `filter` to obtain the same behavior of `find`
  12424. return arr.filter(check)[0];
  12425. }
  12426. /**
  12427. * Return the index of the matching object
  12428. * @method
  12429. * @memberof Popper.Utils
  12430. * @argument {Array} arr
  12431. * @argument prop
  12432. * @argument value
  12433. * @returns index or -1
  12434. */
  12435. function findIndex(arr, prop, value) {
  12436. // use native findIndex if supported
  12437. if (Array.prototype.findIndex) {
  12438. return arr.findIndex(function (cur) {
  12439. return cur[prop] === value;
  12440. });
  12441. }
  12442. // use `find` + `indexOf` if `findIndex` isn't supported
  12443. var match = find(arr, function (obj) {
  12444. return obj[prop] === value;
  12445. });
  12446. return arr.indexOf(match);
  12447. }
  12448. /**
  12449. * Loop trough the list of modifiers and run them in order,
  12450. * each of them will then edit the data object.
  12451. * @method
  12452. * @memberof Popper.Utils
  12453. * @param {dataObject} data
  12454. * @param {Array} modifiers
  12455. * @param {String} ends - Optional modifier name used as stopper
  12456. * @returns {dataObject}
  12457. */
  12458. function runModifiers(modifiers, data, ends) {
  12459. var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
  12460. modifiersToRun.forEach(function (modifier) {
  12461. if (modifier['function']) {
  12462. // eslint-disable-line dot-notation
  12463. console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
  12464. }
  12465. var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
  12466. if (modifier.enabled && isFunction(fn)) {
  12467. // Add properties to offsets to make them a complete clientRect object
  12468. // we do this before each modifier to make sure the previous one doesn't
  12469. // mess with these values
  12470. data.offsets.popper = getClientRect(data.offsets.popper);
  12471. data.offsets.reference = getClientRect(data.offsets.reference);
  12472. data = fn(data, modifier);
  12473. }
  12474. });
  12475. return data;
  12476. }
  12477. /**
  12478. * Updates the position of the popper, computing the new offsets and applying
  12479. * the new style.<br />
  12480. * Prefer `scheduleUpdate` over `update` because of performance reasons.
  12481. * @method
  12482. * @memberof Popper
  12483. */
  12484. function update() {
  12485. // if popper is destroyed, don't perform any further update
  12486. if (this.state.isDestroyed) {
  12487. return;
  12488. }
  12489. var data = {
  12490. instance: this,
  12491. styles: {},
  12492. arrowStyles: {},
  12493. attributes: {},
  12494. flipped: false,
  12495. offsets: {}
  12496. };
  12497. // compute reference element offsets
  12498. data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
  12499. // compute auto placement, store placement inside the data object,
  12500. // modifiers will be able to edit `placement` if needed
  12501. // and refer to originalPlacement to know the original value
  12502. data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
  12503. // store the computed placement inside `originalPlacement`
  12504. data.originalPlacement = data.placement;
  12505. data.positionFixed = this.options.positionFixed;
  12506. // compute the popper offsets
  12507. data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
  12508. data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
  12509. // run the modifiers
  12510. data = runModifiers(this.modifiers, data);
  12511. // the first `update` will call `onCreate` callback
  12512. // the other ones will call `onUpdate` callback
  12513. if (!this.state.isCreated) {
  12514. this.state.isCreated = true;
  12515. this.options.onCreate(data);
  12516. } else {
  12517. this.options.onUpdate(data);
  12518. }
  12519. }
  12520. /**
  12521. * Helper used to know if the given modifier is enabled.
  12522. * @method
  12523. * @memberof Popper.Utils
  12524. * @returns {Boolean}
  12525. */
  12526. function isModifierEnabled(modifiers, modifierName) {
  12527. return modifiers.some(function (_ref) {
  12528. var name = _ref.name,
  12529. enabled = _ref.enabled;
  12530. return enabled && name === modifierName;
  12531. });
  12532. }
  12533. /**
  12534. * Get the prefixed supported property name
  12535. * @method
  12536. * @memberof Popper.Utils
  12537. * @argument {String} property (camelCase)
  12538. * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
  12539. */
  12540. function getSupportedPropertyName(property) {
  12541. var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
  12542. var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
  12543. for (var i = 0; i < prefixes.length; i++) {
  12544. var prefix = prefixes[i];
  12545. var toCheck = prefix ? '' + prefix + upperProp : property;
  12546. if (typeof document.body.style[toCheck] !== 'undefined') {
  12547. return toCheck;
  12548. }
  12549. }
  12550. return null;
  12551. }
  12552. /**
  12553. * Destroys the popper.
  12554. * @method
  12555. * @memberof Popper
  12556. */
  12557. function destroy() {
  12558. this.state.isDestroyed = true;
  12559. // touch DOM only if `applyStyle` modifier is enabled
  12560. if (isModifierEnabled(this.modifiers, 'applyStyle')) {
  12561. this.popper.removeAttribute('x-placement');
  12562. this.popper.style.position = '';
  12563. this.popper.style.top = '';
  12564. this.popper.style.left = '';
  12565. this.popper.style.right = '';
  12566. this.popper.style.bottom = '';
  12567. this.popper.style.willChange = '';
  12568. this.popper.style[getSupportedPropertyName('transform')] = '';
  12569. }
  12570. this.disableEventListeners();
  12571. // remove the popper if user explicity asked for the deletion on destroy
  12572. // do not use `remove` because IE11 doesn't support it
  12573. if (this.options.removeOnDestroy) {
  12574. this.popper.parentNode.removeChild(this.popper);
  12575. }
  12576. return this;
  12577. }
  12578. /**
  12579. * Get the window associated with the element
  12580. * @argument {Element} element
  12581. * @returns {Window}
  12582. */
  12583. function getWindow(element) {
  12584. var ownerDocument = element.ownerDocument;
  12585. return ownerDocument ? ownerDocument.defaultView : window;
  12586. }
  12587. function attachToScrollParents(scrollParent, event, callback, scrollParents) {
  12588. var isBody = scrollParent.nodeName === 'BODY';
  12589. var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
  12590. target.addEventListener(event, callback, { passive: true });
  12591. if (!isBody) {
  12592. attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
  12593. }
  12594. scrollParents.push(target);
  12595. }
  12596. /**
  12597. * Setup needed event listeners used to update the popper position
  12598. * @method
  12599. * @memberof Popper.Utils
  12600. * @private
  12601. */
  12602. function setupEventListeners(reference, options, state, updateBound) {
  12603. // Resize event listener on window
  12604. state.updateBound = updateBound;
  12605. getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
  12606. // Scroll event listener on scroll parents
  12607. var scrollElement = getScrollParent(reference);
  12608. attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
  12609. state.scrollElement = scrollElement;
  12610. state.eventsEnabled = true;
  12611. return state;
  12612. }
  12613. /**
  12614. * It will add resize/scroll events and start recalculating
  12615. * position of the popper element when they are triggered.
  12616. * @method
  12617. * @memberof Popper
  12618. */
  12619. function enableEventListeners() {
  12620. if (!this.state.eventsEnabled) {
  12621. this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
  12622. }
  12623. }
  12624. /**
  12625. * Remove event listeners used to update the popper position
  12626. * @method
  12627. * @memberof Popper.Utils
  12628. * @private
  12629. */
  12630. function removeEventListeners(reference, state) {
  12631. // Remove resize event listener on window
  12632. getWindow(reference).removeEventListener('resize', state.updateBound);
  12633. // Remove scroll event listener on scroll parents
  12634. state.scrollParents.forEach(function (target) {
  12635. target.removeEventListener('scroll', state.updateBound);
  12636. });
  12637. // Reset state
  12638. state.updateBound = null;
  12639. state.scrollParents = [];
  12640. state.scrollElement = null;
  12641. state.eventsEnabled = false;
  12642. return state;
  12643. }
  12644. /**
  12645. * It will remove resize/scroll events and won't recalculate popper position
  12646. * when they are triggered. It also won't trigger `onUpdate` callback anymore,
  12647. * unless you call `update` method manually.
  12648. * @method
  12649. * @memberof Popper
  12650. */
  12651. function disableEventListeners() {
  12652. if (this.state.eventsEnabled) {
  12653. cancelAnimationFrame(this.scheduleUpdate);
  12654. this.state = removeEventListeners(this.reference, this.state);
  12655. }
  12656. }
  12657. /**
  12658. * Tells if a given input is a number
  12659. * @method
  12660. * @memberof Popper.Utils
  12661. * @param {*} input to check
  12662. * @return {Boolean}
  12663. */
  12664. function isNumeric(n) {
  12665. return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
  12666. }
  12667. /**
  12668. * Set the style to the given popper
  12669. * @method
  12670. * @memberof Popper.Utils
  12671. * @argument {Element} element - Element to apply the style to
  12672. * @argument {Object} styles
  12673. * Object with a list of properties and values which will be applied to the element
  12674. */
  12675. function setStyles(element, styles) {
  12676. Object.keys(styles).forEach(function (prop) {
  12677. var unit = '';
  12678. // add unit if the value is numeric and is one of the following
  12679. if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
  12680. unit = 'px';
  12681. }
  12682. element.style[prop] = styles[prop] + unit;
  12683. });
  12684. }
  12685. /**
  12686. * Set the attributes to the given popper
  12687. * @method
  12688. * @memberof Popper.Utils
  12689. * @argument {Element} element - Element to apply the attributes to
  12690. * @argument {Object} styles
  12691. * Object with a list of properties and values which will be applied to the element
  12692. */
  12693. function setAttributes(element, attributes) {
  12694. Object.keys(attributes).forEach(function (prop) {
  12695. var value = attributes[prop];
  12696. if (value !== false) {
  12697. element.setAttribute(prop, attributes[prop]);
  12698. } else {
  12699. element.removeAttribute(prop);
  12700. }
  12701. });
  12702. }
  12703. /**
  12704. * @function
  12705. * @memberof Modifiers
  12706. * @argument {Object} data - The data object generated by `update` method
  12707. * @argument {Object} data.styles - List of style properties - values to apply to popper element
  12708. * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
  12709. * @argument {Object} options - Modifiers configuration and options
  12710. * @returns {Object} The same data object
  12711. */
  12712. function applyStyle(data) {
  12713. // any property present in `data.styles` will be applied to the popper,
  12714. // in this way we can make the 3rd party modifiers add custom styles to it
  12715. // Be aware, modifiers could override the properties defined in the previous
  12716. // lines of this modifier!
  12717. setStyles(data.instance.popper, data.styles);
  12718. // any property present in `data.attributes` will be applied to the popper,
  12719. // they will be set as HTML attributes of the element
  12720. setAttributes(data.instance.popper, data.attributes);
  12721. // if arrowElement is defined and arrowStyles has some properties
  12722. if (data.arrowElement && Object.keys(data.arrowStyles).length) {
  12723. setStyles(data.arrowElement, data.arrowStyles);
  12724. }
  12725. return data;
  12726. }
  12727. /**
  12728. * Set the x-placement attribute before everything else because it could be used
  12729. * to add margins to the popper margins needs to be calculated to get the
  12730. * correct popper offsets.
  12731. * @method
  12732. * @memberof Popper.modifiers
  12733. * @param {HTMLElement} reference - The reference element used to position the popper
  12734. * @param {HTMLElement} popper - The HTML element used as popper
  12735. * @param {Object} options - Popper.js options
  12736. */
  12737. function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
  12738. // compute reference element offsets
  12739. var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
  12740. // compute auto placement, store placement inside the data object,
  12741. // modifiers will be able to edit `placement` if needed
  12742. // and refer to originalPlacement to know the original value
  12743. var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
  12744. popper.setAttribute('x-placement', placement);
  12745. // Apply `position` to popper before anything else because
  12746. // without the position applied we can't guarantee correct computations
  12747. setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
  12748. return options;
  12749. }
  12750. /**
  12751. * @function
  12752. * @memberof Modifiers
  12753. * @argument {Object} data - The data object generated by `update` method
  12754. * @argument {Object} options - Modifiers configuration and options
  12755. * @returns {Object} The data object, properly modified
  12756. */
  12757. function computeStyle(data, options) {
  12758. var x = options.x,
  12759. y = options.y;
  12760. var popper = data.offsets.popper;
  12761. // Remove this legacy support in Popper.js v2
  12762. var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
  12763. return modifier.name === 'applyStyle';
  12764. }).gpuAcceleration;
  12765. if (legacyGpuAccelerationOption !== undefined) {
  12766. console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
  12767. }
  12768. var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
  12769. var offsetParent = getOffsetParent(data.instance.popper);
  12770. var offsetParentRect = getBoundingClientRect(offsetParent);
  12771. // Styles
  12772. var styles = {
  12773. position: popper.position
  12774. };
  12775. // Avoid blurry text by using full pixel integers.
  12776. // For pixel-perfect positioning, top/bottom prefers rounded
  12777. // values, while left/right prefers floored values.
  12778. var offsets = {
  12779. left: Math.floor(popper.left),
  12780. top: Math.round(popper.top),
  12781. bottom: Math.round(popper.bottom),
  12782. right: Math.floor(popper.right)
  12783. };
  12784. var sideA = x === 'bottom' ? 'top' : 'bottom';
  12785. var sideB = y === 'right' ? 'left' : 'right';
  12786. // if gpuAcceleration is set to `true` and transform is supported,
  12787. // we use `translate3d` to apply the position to the popper we
  12788. // automatically use the supported prefixed version if needed
  12789. var prefixedProperty = getSupportedPropertyName('transform');
  12790. // now, let's make a step back and look at this code closely (wtf?)
  12791. // If the content of the popper grows once it's been positioned, it
  12792. // may happen that the popper gets misplaced because of the new content
  12793. // overflowing its reference element
  12794. // To avoid this problem, we provide two options (x and y), which allow
  12795. // the consumer to define the offset origin.
  12796. // If we position a popper on top of a reference element, we can set
  12797. // `x` to `top` to make the popper grow towards its top instead of
  12798. // its bottom.
  12799. var left = void 0,
  12800. top = void 0;
  12801. if (sideA === 'bottom') {
  12802. // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
  12803. // and not the bottom of the html element
  12804. if (offsetParent.nodeName === 'HTML') {
  12805. top = -offsetParent.clientHeight + offsets.bottom;
  12806. } else {
  12807. top = -offsetParentRect.height + offsets.bottom;
  12808. }
  12809. } else {
  12810. top = offsets.top;
  12811. }
  12812. if (sideB === 'right') {
  12813. if (offsetParent.nodeName === 'HTML') {
  12814. left = -offsetParent.clientWidth + offsets.right;
  12815. } else {
  12816. left = -offsetParentRect.width + offsets.right;
  12817. }
  12818. } else {
  12819. left = offsets.left;
  12820. }
  12821. if (gpuAcceleration && prefixedProperty) {
  12822. styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
  12823. styles[sideA] = 0;
  12824. styles[sideB] = 0;
  12825. styles.willChange = 'transform';
  12826. } else {
  12827. // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
  12828. var invertTop = sideA === 'bottom' ? -1 : 1;
  12829. var invertLeft = sideB === 'right' ? -1 : 1;
  12830. styles[sideA] = top * invertTop;
  12831. styles[sideB] = left * invertLeft;
  12832. styles.willChange = sideA + ', ' + sideB;
  12833. }
  12834. // Attributes
  12835. var attributes = {
  12836. 'x-placement': data.placement
  12837. };
  12838. // Update `data` attributes, styles and arrowStyles
  12839. data.attributes = _extends({}, attributes, data.attributes);
  12840. data.styles = _extends({}, styles, data.styles);
  12841. data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
  12842. return data;
  12843. }
  12844. /**
  12845. * Helper used to know if the given modifier depends from another one.<br />
  12846. * It checks if the needed modifier is listed and enabled.
  12847. * @method
  12848. * @memberof Popper.Utils
  12849. * @param {Array} modifiers - list of modifiers
  12850. * @param {String} requestingName - name of requesting modifier
  12851. * @param {String} requestedName - name of requested modifier
  12852. * @returns {Boolean}
  12853. */
  12854. function isModifierRequired(modifiers, requestingName, requestedName) {
  12855. var requesting = find(modifiers, function (_ref) {
  12856. var name = _ref.name;
  12857. return name === requestingName;
  12858. });
  12859. var isRequired = !!requesting && modifiers.some(function (modifier) {
  12860. return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
  12861. });
  12862. if (!isRequired) {
  12863. var _requesting = '`' + requestingName + '`';
  12864. var requested = '`' + requestedName + '`';
  12865. console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
  12866. }
  12867. return isRequired;
  12868. }
  12869. /**
  12870. * @function
  12871. * @memberof Modifiers
  12872. * @argument {Object} data - The data object generated by update method
  12873. * @argument {Object} options - Modifiers configuration and options
  12874. * @returns {Object} The data object, properly modified
  12875. */
  12876. function arrow(data, options) {
  12877. var _data$offsets$arrow;
  12878. // arrow depends on keepTogether in order to work
  12879. if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
  12880. return data;
  12881. }
  12882. var arrowElement = options.element;
  12883. // if arrowElement is a string, suppose it's a CSS selector
  12884. if (typeof arrowElement === 'string') {
  12885. arrowElement = data.instance.popper.querySelector(arrowElement);
  12886. // if arrowElement is not found, don't run the modifier
  12887. if (!arrowElement) {
  12888. return data;
  12889. }
  12890. } else {
  12891. // if the arrowElement isn't a query selector we must check that the
  12892. // provided DOM node is child of its popper node
  12893. if (!data.instance.popper.contains(arrowElement)) {
  12894. console.warn('WARNING: `arrow.element` must be child of its popper element!');
  12895. return data;
  12896. }
  12897. }
  12898. var placement = data.placement.split('-')[0];
  12899. var _data$offsets = data.offsets,
  12900. popper = _data$offsets.popper,
  12901. reference = _data$offsets.reference;
  12902. var isVertical = ['left', 'right'].indexOf(placement) !== -1;
  12903. var len = isVertical ? 'height' : 'width';
  12904. var sideCapitalized = isVertical ? 'Top' : 'Left';
  12905. var side = sideCapitalized.toLowerCase();
  12906. var altSide = isVertical ? 'left' : 'top';
  12907. var opSide = isVertical ? 'bottom' : 'right';
  12908. var arrowElementSize = getOuterSizes(arrowElement)[len];
  12909. //
  12910. // extends keepTogether behavior making sure the popper and its
  12911. // reference have enough pixels in conjunction
  12912. //
  12913. // top/left side
  12914. if (reference[opSide] - arrowElementSize < popper[side]) {
  12915. data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
  12916. }
  12917. // bottom/right side
  12918. if (reference[side] + arrowElementSize > popper[opSide]) {
  12919. data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
  12920. }
  12921. data.offsets.popper = getClientRect(data.offsets.popper);
  12922. // compute center of the popper
  12923. var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
  12924. // Compute the sideValue using the updated popper offsets
  12925. // take popper margin in account because we don't have this info available
  12926. var css = getStyleComputedProperty(data.instance.popper);
  12927. var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
  12928. var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
  12929. var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
  12930. // prevent arrowElement from being placed not contiguously to its popper
  12931. sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
  12932. data.arrowElement = arrowElement;
  12933. data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
  12934. return data;
  12935. }
  12936. /**
  12937. * Get the opposite placement variation of the given one
  12938. * @method
  12939. * @memberof Popper.Utils
  12940. * @argument {String} placement variation
  12941. * @returns {String} flipped placement variation
  12942. */
  12943. function getOppositeVariation(variation) {
  12944. if (variation === 'end') {
  12945. return 'start';
  12946. } else if (variation === 'start') {
  12947. return 'end';
  12948. }
  12949. return variation;
  12950. }
  12951. /**
  12952. * List of accepted placements to use as values of the `placement` option.<br />
  12953. * Valid placements are:
  12954. * - `auto`
  12955. * - `top`
  12956. * - `right`
  12957. * - `bottom`
  12958. * - `left`
  12959. *
  12960. * Each placement can have a variation from this list:
  12961. * - `-start`
  12962. * - `-end`
  12963. *
  12964. * Variations are interpreted easily if you think of them as the left to right
  12965. * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
  12966. * is right.<br />
  12967. * Vertically (`left` and `right`), `start` is top and `end` is bottom.
  12968. *
  12969. * Some valid examples are:
  12970. * - `top-end` (on top of reference, right aligned)
  12971. * - `right-start` (on right of reference, top aligned)
  12972. * - `bottom` (on bottom, centered)
  12973. * - `auto-end` (on the side with more space available, alignment depends by placement)
  12974. *
  12975. * @static
  12976. * @type {Array}
  12977. * @enum {String}
  12978. * @readonly
  12979. * @method placements
  12980. * @memberof Popper
  12981. */
  12982. 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'];
  12983. // Get rid of `auto` `auto-start` and `auto-end`
  12984. var validPlacements = placements.slice(3);
  12985. /**
  12986. * Given an initial placement, returns all the subsequent placements
  12987. * clockwise (or counter-clockwise).
  12988. *
  12989. * @method
  12990. * @memberof Popper.Utils
  12991. * @argument {String} placement - A valid placement (it accepts variations)
  12992. * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
  12993. * @returns {Array} placements including their variations
  12994. */
  12995. function clockwise(placement) {
  12996. var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  12997. var index = validPlacements.indexOf(placement);
  12998. var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
  12999. return counter ? arr.reverse() : arr;
  13000. }
  13001. var BEHAVIORS = {
  13002. FLIP: 'flip',
  13003. CLOCKWISE: 'clockwise',
  13004. COUNTERCLOCKWISE: 'counterclockwise'
  13005. };
  13006. /**
  13007. * @function
  13008. * @memberof Modifiers
  13009. * @argument {Object} data - The data object generated by update method
  13010. * @argument {Object} options - Modifiers configuration and options
  13011. * @returns {Object} The data object, properly modified
  13012. */
  13013. function flip(data, options) {
  13014. // if `inner` modifier is enabled, we can't use the `flip` modifier
  13015. if (isModifierEnabled(data.instance.modifiers, 'inner')) {
  13016. return data;
  13017. }
  13018. if (data.flipped && data.placement === data.originalPlacement) {
  13019. // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
  13020. return data;
  13021. }
  13022. var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
  13023. var placement = data.placement.split('-')[0];
  13024. var placementOpposite = getOppositePlacement(placement);
  13025. var variation = data.placement.split('-')[1] || '';
  13026. var flipOrder = [];
  13027. switch (options.behavior) {
  13028. case BEHAVIORS.FLIP:
  13029. flipOrder = [placement, placementOpposite];
  13030. break;
  13031. case BEHAVIORS.CLOCKWISE:
  13032. flipOrder = clockwise(placement);
  13033. break;
  13034. case BEHAVIORS.COUNTERCLOCKWISE:
  13035. flipOrder = clockwise(placement, true);
  13036. break;
  13037. default:
  13038. flipOrder = options.behavior;
  13039. }
  13040. flipOrder.forEach(function (step, index) {
  13041. if (placement !== step || flipOrder.length === index + 1) {
  13042. return data;
  13043. }
  13044. placement = data.placement.split('-')[0];
  13045. placementOpposite = getOppositePlacement(placement);
  13046. var popperOffsets = data.offsets.popper;
  13047. var refOffsets = data.offsets.reference;
  13048. // using floor because the reference offsets may contain decimals we are not going to consider here
  13049. var floor = Math.floor;
  13050. 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);
  13051. var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
  13052. var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
  13053. var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
  13054. var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
  13055. var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
  13056. // flip the variation if required
  13057. var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
  13058. var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
  13059. if (overlapsRef || overflowsBoundaries || flippedVariation) {
  13060. // this boolean to detect any flip loop
  13061. data.flipped = true;
  13062. if (overlapsRef || overflowsBoundaries) {
  13063. placement = flipOrder[index + 1];
  13064. }
  13065. if (flippedVariation) {
  13066. variation = getOppositeVariation(variation);
  13067. }
  13068. data.placement = placement + (variation ? '-' + variation : '');
  13069. // this object contains `position`, we want to preserve it along with
  13070. // any additional property we may add in the future
  13071. data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
  13072. data = runModifiers(data.instance.modifiers, data, 'flip');
  13073. }
  13074. });
  13075. return data;
  13076. }
  13077. /**
  13078. * @function
  13079. * @memberof Modifiers
  13080. * @argument {Object} data - The data object generated by update method
  13081. * @argument {Object} options - Modifiers configuration and options
  13082. * @returns {Object} The data object, properly modified
  13083. */
  13084. function keepTogether(data) {
  13085. var _data$offsets = data.offsets,
  13086. popper = _data$offsets.popper,
  13087. reference = _data$offsets.reference;
  13088. var placement = data.placement.split('-')[0];
  13089. var floor = Math.floor;
  13090. var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
  13091. var side = isVertical ? 'right' : 'bottom';
  13092. var opSide = isVertical ? 'left' : 'top';
  13093. var measurement = isVertical ? 'width' : 'height';
  13094. if (popper[side] < floor(reference[opSide])) {
  13095. data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
  13096. }
  13097. if (popper[opSide] > floor(reference[side])) {
  13098. data.offsets.popper[opSide] = floor(reference[side]);
  13099. }
  13100. return data;
  13101. }
  13102. /**
  13103. * Converts a string containing value + unit into a px value number
  13104. * @function
  13105. * @memberof {modifiers~offset}
  13106. * @private
  13107. * @argument {String} str - Value + unit string
  13108. * @argument {String} measurement - `height` or `width`
  13109. * @argument {Object} popperOffsets
  13110. * @argument {Object} referenceOffsets
  13111. * @returns {Number|String}
  13112. * Value in pixels, or original string if no values were extracted
  13113. */
  13114. function toValue(str, measurement, popperOffsets, referenceOffsets) {
  13115. // separate value from unit
  13116. var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
  13117. var value = +split[1];
  13118. var unit = split[2];
  13119. // If it's not a number it's an operator, I guess
  13120. if (!value) {
  13121. return str;
  13122. }
  13123. if (unit.indexOf('%') === 0) {
  13124. var element = void 0;
  13125. switch (unit) {
  13126. case '%p':
  13127. element = popperOffsets;
  13128. break;
  13129. case '%':
  13130. case '%r':
  13131. default:
  13132. element = referenceOffsets;
  13133. }
  13134. var rect = getClientRect(element);
  13135. return rect[measurement] / 100 * value;
  13136. } else if (unit === 'vh' || unit === 'vw') {
  13137. // if is a vh or vw, we calculate the size based on the viewport
  13138. var size = void 0;
  13139. if (unit === 'vh') {
  13140. size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  13141. } else {
  13142. size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  13143. }
  13144. return size / 100 * value;
  13145. } else {
  13146. // if is an explicit pixel unit, we get rid of the unit and keep the value
  13147. // if is an implicit unit, it's px, and we return just the value
  13148. return value;
  13149. }
  13150. }
  13151. /**
  13152. * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
  13153. * @function
  13154. * @memberof {modifiers~offset}
  13155. * @private
  13156. * @argument {String} offset
  13157. * @argument {Object} popperOffsets
  13158. * @argument {Object} referenceOffsets
  13159. * @argument {String} basePlacement
  13160. * @returns {Array} a two cells array with x and y offsets in numbers
  13161. */
  13162. function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
  13163. var offsets = [0, 0];
  13164. // Use height if placement is left or right and index is 0 otherwise use width
  13165. // in this way the first offset will use an axis and the second one
  13166. // will use the other one
  13167. var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
  13168. // Split the offset string to obtain a list of values and operands
  13169. // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
  13170. var fragments = offset.split(/(\+|\-)/).map(function (frag) {
  13171. return frag.trim();
  13172. });
  13173. // Detect if the offset string contains a pair of values or a single one
  13174. // they could be separated by comma or space
  13175. var divider = fragments.indexOf(find(fragments, function (frag) {
  13176. return frag.search(/,|\s/) !== -1;
  13177. }));
  13178. if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
  13179. console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
  13180. }
  13181. // If divider is found, we divide the list of values and operands to divide
  13182. // them by ofset X and Y.
  13183. var splitRegex = /\s*,\s*|\s+/;
  13184. 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];
  13185. // Convert the values with units to absolute pixels to allow our computations
  13186. ops = ops.map(function (op, index) {
  13187. // Most of the units rely on the orientation of the popper
  13188. var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
  13189. var mergeWithPrevious = false;
  13190. return op
  13191. // This aggregates any `+` or `-` sign that aren't considered operators
  13192. // e.g.: 10 + +5 => [10, +, +5]
  13193. .reduce(function (a, b) {
  13194. if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
  13195. a[a.length - 1] = b;
  13196. mergeWithPrevious = true;
  13197. return a;
  13198. } else if (mergeWithPrevious) {
  13199. a[a.length - 1] += b;
  13200. mergeWithPrevious = false;
  13201. return a;
  13202. } else {
  13203. return a.concat(b);
  13204. }
  13205. }, [])
  13206. // Here we convert the string values into number values (in px)
  13207. .map(function (str) {
  13208. return toValue(str, measurement, popperOffsets, referenceOffsets);
  13209. });
  13210. });
  13211. // Loop trough the offsets arrays and execute the operations
  13212. ops.forEach(function (op, index) {
  13213. op.forEach(function (frag, index2) {
  13214. if (isNumeric(frag)) {
  13215. offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
  13216. }
  13217. });
  13218. });
  13219. return offsets;
  13220. }
  13221. /**
  13222. * @function
  13223. * @memberof Modifiers
  13224. * @argument {Object} data - The data object generated by update method
  13225. * @argument {Object} options - Modifiers configuration and options
  13226. * @argument {Number|String} options.offset=0
  13227. * The offset value as described in the modifier description
  13228. * @returns {Object} The data object, properly modified
  13229. */
  13230. function offset(data, _ref) {
  13231. var offset = _ref.offset;
  13232. var placement = data.placement,
  13233. _data$offsets = data.offsets,
  13234. popper = _data$offsets.popper,
  13235. reference = _data$offsets.reference;
  13236. var basePlacement = placement.split('-')[0];
  13237. var offsets = void 0;
  13238. if (isNumeric(+offset)) {
  13239. offsets = [+offset, 0];
  13240. } else {
  13241. offsets = parseOffset(offset, popper, reference, basePlacement);
  13242. }
  13243. if (basePlacement === 'left') {
  13244. popper.top += offsets[0];
  13245. popper.left -= offsets[1];
  13246. } else if (basePlacement === 'right') {
  13247. popper.top += offsets[0];
  13248. popper.left += offsets[1];
  13249. } else if (basePlacement === 'top') {
  13250. popper.left += offsets[0];
  13251. popper.top -= offsets[1];
  13252. } else if (basePlacement === 'bottom') {
  13253. popper.left += offsets[0];
  13254. popper.top += offsets[1];
  13255. }
  13256. data.popper = popper;
  13257. return data;
  13258. }
  13259. /**
  13260. * @function
  13261. * @memberof Modifiers
  13262. * @argument {Object} data - The data object generated by `update` method
  13263. * @argument {Object} options - Modifiers configuration and options
  13264. * @returns {Object} The data object, properly modified
  13265. */
  13266. function preventOverflow(data, options) {
  13267. var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
  13268. // If offsetParent is the reference element, we really want to
  13269. // go one step up and use the next offsetParent as reference to
  13270. // avoid to make this modifier completely useless and look like broken
  13271. if (data.instance.reference === boundariesElement) {
  13272. boundariesElement = getOffsetParent(boundariesElement);
  13273. }
  13274. // NOTE: DOM access here
  13275. // resets the popper's position so that the document size can be calculated excluding
  13276. // the size of the popper element itself
  13277. var transformProp = getSupportedPropertyName('transform');
  13278. var popperStyles = data.instance.popper.style; // assignment to help minification
  13279. var top = popperStyles.top,
  13280. left = popperStyles.left,
  13281. transform = popperStyles[transformProp];
  13282. popperStyles.top = '';
  13283. popperStyles.left = '';
  13284. popperStyles[transformProp] = '';
  13285. var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
  13286. // NOTE: DOM access here
  13287. // restores the original style properties after the offsets have been computed
  13288. popperStyles.top = top;
  13289. popperStyles.left = left;
  13290. popperStyles[transformProp] = transform;
  13291. options.boundaries = boundaries;
  13292. var order = options.priority;
  13293. var popper = data.offsets.popper;
  13294. var check = {
  13295. primary: function primary(placement) {
  13296. var value = popper[placement];
  13297. if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
  13298. value = Math.max(popper[placement], boundaries[placement]);
  13299. }
  13300. return defineProperty({}, placement, value);
  13301. },
  13302. secondary: function secondary(placement) {
  13303. var mainSide = placement === 'right' ? 'left' : 'top';
  13304. var value = popper[mainSide];
  13305. if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
  13306. value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
  13307. }
  13308. return defineProperty({}, mainSide, value);
  13309. }
  13310. };
  13311. order.forEach(function (placement) {
  13312. var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
  13313. popper = _extends({}, popper, check[side](placement));
  13314. });
  13315. data.offsets.popper = popper;
  13316. return data;
  13317. }
  13318. /**
  13319. * @function
  13320. * @memberof Modifiers
  13321. * @argument {Object} data - The data object generated by `update` method
  13322. * @argument {Object} options - Modifiers configuration and options
  13323. * @returns {Object} The data object, properly modified
  13324. */
  13325. function shift(data) {
  13326. var placement = data.placement;
  13327. var basePlacement = placement.split('-')[0];
  13328. var shiftvariation = placement.split('-')[1];
  13329. // if shift shiftvariation is specified, run the modifier
  13330. if (shiftvariation) {
  13331. var _data$offsets = data.offsets,
  13332. reference = _data$offsets.reference,
  13333. popper = _data$offsets.popper;
  13334. var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
  13335. var side = isVertical ? 'left' : 'top';
  13336. var measurement = isVertical ? 'width' : 'height';
  13337. var shiftOffsets = {
  13338. start: defineProperty({}, side, reference[side]),
  13339. end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
  13340. };
  13341. data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
  13342. }
  13343. return data;
  13344. }
  13345. /**
  13346. * @function
  13347. * @memberof Modifiers
  13348. * @argument {Object} data - The data object generated by update method
  13349. * @argument {Object} options - Modifiers configuration and options
  13350. * @returns {Object} The data object, properly modified
  13351. */
  13352. function hide(data) {
  13353. if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
  13354. return data;
  13355. }
  13356. var refRect = data.offsets.reference;
  13357. var bound = find(data.instance.modifiers, function (modifier) {
  13358. return modifier.name === 'preventOverflow';
  13359. }).boundaries;
  13360. if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
  13361. // Avoid unnecessary DOM access if visibility hasn't changed
  13362. if (data.hide === true) {
  13363. return data;
  13364. }
  13365. data.hide = true;
  13366. data.attributes['x-out-of-boundaries'] = '';
  13367. } else {
  13368. // Avoid unnecessary DOM access if visibility hasn't changed
  13369. if (data.hide === false) {
  13370. return data;
  13371. }
  13372. data.hide = false;
  13373. data.attributes['x-out-of-boundaries'] = false;
  13374. }
  13375. return data;
  13376. }
  13377. /**
  13378. * @function
  13379. * @memberof Modifiers
  13380. * @argument {Object} data - The data object generated by `update` method
  13381. * @argument {Object} options - Modifiers configuration and options
  13382. * @returns {Object} The data object, properly modified
  13383. */
  13384. function inner(data) {
  13385. var placement = data.placement;
  13386. var basePlacement = placement.split('-')[0];
  13387. var _data$offsets = data.offsets,
  13388. popper = _data$offsets.popper,
  13389. reference = _data$offsets.reference;
  13390. var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
  13391. var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
  13392. popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
  13393. data.placement = getOppositePlacement(placement);
  13394. data.offsets.popper = getClientRect(popper);
  13395. return data;
  13396. }
  13397. /**
  13398. * Modifier function, each modifier can have a function of this type assigned
  13399. * to its `fn` property.<br />
  13400. * These functions will be called on each update, this means that you must
  13401. * make sure they are performant enough to avoid performance bottlenecks.
  13402. *
  13403. * @function ModifierFn
  13404. * @argument {dataObject} data - The data object generated by `update` method
  13405. * @argument {Object} options - Modifiers configuration and options
  13406. * @returns {dataObject} The data object, properly modified
  13407. */
  13408. /**
  13409. * Modifiers are plugins used to alter the behavior of your poppers.<br />
  13410. * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
  13411. * needed by the library.
  13412. *
  13413. * Usually you don't want to override the `order`, `fn` and `onLoad` props.
  13414. * All the other properties are configurations that could be tweaked.
  13415. * @namespace modifiers
  13416. */
  13417. var modifiers = {
  13418. /**
  13419. * Modifier used to shift the popper on the start or end of its reference
  13420. * element.<br />
  13421. * It will read the variation of the `placement` property.<br />
  13422. * It can be one either `-end` or `-start`.
  13423. * @memberof modifiers
  13424. * @inner
  13425. */
  13426. shift: {
  13427. /** @prop {number} order=100 - Index used to define the order of execution */
  13428. order: 100,
  13429. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13430. enabled: true,
  13431. /** @prop {ModifierFn} */
  13432. fn: shift
  13433. },
  13434. /**
  13435. * The `offset` modifier can shift your popper on both its axis.
  13436. *
  13437. * It accepts the following units:
  13438. * - `px` or unit-less, interpreted as pixels
  13439. * - `%` or `%r`, percentage relative to the length of the reference element
  13440. * - `%p`, percentage relative to the length of the popper element
  13441. * - `vw`, CSS viewport width unit
  13442. * - `vh`, CSS viewport height unit
  13443. *
  13444. * For length is intended the main axis relative to the placement of the popper.<br />
  13445. * This means that if the placement is `top` or `bottom`, the length will be the
  13446. * `width`. In case of `left` or `right`, it will be the `height`.
  13447. *
  13448. * You can provide a single value (as `Number` or `String`), or a pair of values
  13449. * as `String` divided by a comma or one (or more) white spaces.<br />
  13450. * The latter is a deprecated method because it leads to confusion and will be
  13451. * removed in v2.<br />
  13452. * Additionally, it accepts additions and subtractions between different units.
  13453. * Note that multiplications and divisions aren't supported.
  13454. *
  13455. * Valid examples are:
  13456. * ```
  13457. * 10
  13458. * '10%'
  13459. * '10, 10'
  13460. * '10%, 10'
  13461. * '10 + 10%'
  13462. * '10 - 5vh + 3%'
  13463. * '-10px + 5vh, 5px - 6%'
  13464. * ```
  13465. * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
  13466. * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
  13467. * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
  13468. *
  13469. * @memberof modifiers
  13470. * @inner
  13471. */
  13472. offset: {
  13473. /** @prop {number} order=200 - Index used to define the order of execution */
  13474. order: 200,
  13475. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13476. enabled: true,
  13477. /** @prop {ModifierFn} */
  13478. fn: offset,
  13479. /** @prop {Number|String} offset=0
  13480. * The offset value as described in the modifier description
  13481. */
  13482. offset: 0
  13483. },
  13484. /**
  13485. * Modifier used to prevent the popper from being positioned outside the boundary.
  13486. *
  13487. * A scenario exists where the reference itself is not within the boundaries.<br />
  13488. * We can say it has "escaped the boundaries" — or just "escaped".<br />
  13489. * In this case we need to decide whether the popper should either:
  13490. *
  13491. * - detach from the reference and remain "trapped" in the boundaries, or
  13492. * - if it should ignore the boundary and "escape with its reference"
  13493. *
  13494. * When `escapeWithReference` is set to`true` and reference is completely
  13495. * outside its boundaries, the popper will overflow (or completely leave)
  13496. * the boundaries in order to remain attached to the edge of the reference.
  13497. *
  13498. * @memberof modifiers
  13499. * @inner
  13500. */
  13501. preventOverflow: {
  13502. /** @prop {number} order=300 - Index used to define the order of execution */
  13503. order: 300,
  13504. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13505. enabled: true,
  13506. /** @prop {ModifierFn} */
  13507. fn: preventOverflow,
  13508. /**
  13509. * @prop {Array} [priority=['left','right','top','bottom']]
  13510. * Popper will try to prevent overflow following these priorities by default,
  13511. * then, it could overflow on the left and on top of the `boundariesElement`
  13512. */
  13513. priority: ['left', 'right', 'top', 'bottom'],
  13514. /**
  13515. * @prop {number} padding=5
  13516. * Amount of pixel used to define a minimum distance between the boundaries
  13517. * and the popper. This makes sure the popper always has a little padding
  13518. * between the edges of its container
  13519. */
  13520. padding: 5,
  13521. /**
  13522. * @prop {String|HTMLElement} boundariesElement='scrollParent'
  13523. * Boundaries used by the modifier. Can be `scrollParent`, `window`,
  13524. * `viewport` or any DOM element.
  13525. */
  13526. boundariesElement: 'scrollParent'
  13527. },
  13528. /**
  13529. * Modifier used to make sure the reference and its popper stay near each other
  13530. * without leaving any gap between the two. Especially useful when the arrow is
  13531. * enabled and you want to ensure that it points to its reference element.
  13532. * It cares only about the first axis. You can still have poppers with margin
  13533. * between the popper and its reference element.
  13534. * @memberof modifiers
  13535. * @inner
  13536. */
  13537. keepTogether: {
  13538. /** @prop {number} order=400 - Index used to define the order of execution */
  13539. order: 400,
  13540. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13541. enabled: true,
  13542. /** @prop {ModifierFn} */
  13543. fn: keepTogether
  13544. },
  13545. /**
  13546. * This modifier is used to move the `arrowElement` of the popper to make
  13547. * sure it is positioned between the reference element and its popper element.
  13548. * It will read the outer size of the `arrowElement` node to detect how many
  13549. * pixels of conjunction are needed.
  13550. *
  13551. * It has no effect if no `arrowElement` is provided.
  13552. * @memberof modifiers
  13553. * @inner
  13554. */
  13555. arrow: {
  13556. /** @prop {number} order=500 - Index used to define the order of execution */
  13557. order: 500,
  13558. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13559. enabled: true,
  13560. /** @prop {ModifierFn} */
  13561. fn: arrow,
  13562. /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
  13563. element: '[x-arrow]'
  13564. },
  13565. /**
  13566. * Modifier used to flip the popper's placement when it starts to overlap its
  13567. * reference element.
  13568. *
  13569. * Requires the `preventOverflow` modifier before it in order to work.
  13570. *
  13571. * **NOTE:** this modifier will interrupt the current update cycle and will
  13572. * restart it if it detects the need to flip the placement.
  13573. * @memberof modifiers
  13574. * @inner
  13575. */
  13576. flip: {
  13577. /** @prop {number} order=600 - Index used to define the order of execution */
  13578. order: 600,
  13579. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13580. enabled: true,
  13581. /** @prop {ModifierFn} */
  13582. fn: flip,
  13583. /**
  13584. * @prop {String|Array} behavior='flip'
  13585. * The behavior used to change the popper's placement. It can be one of
  13586. * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
  13587. * placements (with optional variations)
  13588. */
  13589. behavior: 'flip',
  13590. /**
  13591. * @prop {number} padding=5
  13592. * The popper will flip if it hits the edges of the `boundariesElement`
  13593. */
  13594. padding: 5,
  13595. /**
  13596. * @prop {String|HTMLElement} boundariesElement='viewport'
  13597. * The element which will define the boundaries of the popper position.
  13598. * The popper will never be placed outside of the defined boundaries
  13599. * (except if `keepTogether` is enabled)
  13600. */
  13601. boundariesElement: 'viewport'
  13602. },
  13603. /**
  13604. * Modifier used to make the popper flow toward the inner of the reference element.
  13605. * By default, when this modifier is disabled, the popper will be placed outside
  13606. * the reference element.
  13607. * @memberof modifiers
  13608. * @inner
  13609. */
  13610. inner: {
  13611. /** @prop {number} order=700 - Index used to define the order of execution */
  13612. order: 700,
  13613. /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
  13614. enabled: false,
  13615. /** @prop {ModifierFn} */
  13616. fn: inner
  13617. },
  13618. /**
  13619. * Modifier used to hide the popper when its reference element is outside of the
  13620. * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
  13621. * be used to hide with a CSS selector the popper when its reference is
  13622. * out of boundaries.
  13623. *
  13624. * Requires the `preventOverflow` modifier before it in order to work.
  13625. * @memberof modifiers
  13626. * @inner
  13627. */
  13628. hide: {
  13629. /** @prop {number} order=800 - Index used to define the order of execution */
  13630. order: 800,
  13631. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13632. enabled: true,
  13633. /** @prop {ModifierFn} */
  13634. fn: hide
  13635. },
  13636. /**
  13637. * Computes the style that will be applied to the popper element to gets
  13638. * properly positioned.
  13639. *
  13640. * Note that this modifier will not touch the DOM, it just prepares the styles
  13641. * so that `applyStyle` modifier can apply it. This separation is useful
  13642. * in case you need to replace `applyStyle` with a custom implementation.
  13643. *
  13644. * This modifier has `850` as `order` value to maintain backward compatibility
  13645. * with previous versions of Popper.js. Expect the modifiers ordering method
  13646. * to change in future major versions of the library.
  13647. *
  13648. * @memberof modifiers
  13649. * @inner
  13650. */
  13651. computeStyle: {
  13652. /** @prop {number} order=850 - Index used to define the order of execution */
  13653. order: 850,
  13654. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13655. enabled: true,
  13656. /** @prop {ModifierFn} */
  13657. fn: computeStyle,
  13658. /**
  13659. * @prop {Boolean} gpuAcceleration=true
  13660. * If true, it uses the CSS 3D transformation to position the popper.
  13661. * Otherwise, it will use the `top` and `left` properties
  13662. */
  13663. gpuAcceleration: true,
  13664. /**
  13665. * @prop {string} [x='bottom']
  13666. * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
  13667. * Change this if your popper should grow in a direction different from `bottom`
  13668. */
  13669. x: 'bottom',
  13670. /**
  13671. * @prop {string} [x='left']
  13672. * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
  13673. * Change this if your popper should grow in a direction different from `right`
  13674. */
  13675. y: 'right'
  13676. },
  13677. /**
  13678. * Applies the computed styles to the popper element.
  13679. *
  13680. * All the DOM manipulations are limited to this modifier. This is useful in case
  13681. * you want to integrate Popper.js inside a framework or view library and you
  13682. * want to delegate all the DOM manipulations to it.
  13683. *
  13684. * Note that if you disable this modifier, you must make sure the popper element
  13685. * has its position set to `absolute` before Popper.js can do its work!
  13686. *
  13687. * Just disable this modifier and define your own to achieve the desired effect.
  13688. *
  13689. * @memberof modifiers
  13690. * @inner
  13691. */
  13692. applyStyle: {
  13693. /** @prop {number} order=900 - Index used to define the order of execution */
  13694. order: 900,
  13695. /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
  13696. enabled: true,
  13697. /** @prop {ModifierFn} */
  13698. fn: applyStyle,
  13699. /** @prop {Function} */
  13700. onLoad: applyStyleOnLoad,
  13701. /**
  13702. * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
  13703. * @prop {Boolean} gpuAcceleration=true
  13704. * If true, it uses the CSS 3D transformation to position the popper.
  13705. * Otherwise, it will use the `top` and `left` properties
  13706. */
  13707. gpuAcceleration: undefined
  13708. }
  13709. };
  13710. /**
  13711. * The `dataObject` is an object containing all the information used by Popper.js.
  13712. * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
  13713. * @name dataObject
  13714. * @property {Object} data.instance The Popper.js instance
  13715. * @property {String} data.placement Placement applied to popper
  13716. * @property {String} data.originalPlacement Placement originally defined on init
  13717. * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
  13718. * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
  13719. * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
  13720. * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
  13721. * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
  13722. * @property {Object} data.boundaries Offsets of the popper boundaries
  13723. * @property {Object} data.offsets The measurements of popper, reference and arrow elements
  13724. * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
  13725. * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
  13726. * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
  13727. */
  13728. /**
  13729. * Default options provided to Popper.js constructor.<br />
  13730. * These can be overridden using the `options` argument of Popper.js.<br />
  13731. * To override an option, simply pass an object with the same
  13732. * structure of the `options` object, as the 3rd argument. For example:
  13733. * ```
  13734. * new Popper(ref, pop, {
  13735. * modifiers: {
  13736. * preventOverflow: { enabled: false }
  13737. * }
  13738. * })
  13739. * ```
  13740. * @type {Object}
  13741. * @static
  13742. * @memberof Popper
  13743. */
  13744. var Defaults = {
  13745. /**
  13746. * Popper's placement.
  13747. * @prop {Popper.placements} placement='bottom'
  13748. */
  13749. placement: 'bottom',
  13750. /**
  13751. * Set this to true if you want popper to position it self in 'fixed' mode
  13752. * @prop {Boolean} positionFixed=false
  13753. */
  13754. positionFixed: false,
  13755. /**
  13756. * Whether events (resize, scroll) are initially enabled.
  13757. * @prop {Boolean} eventsEnabled=true
  13758. */
  13759. eventsEnabled: true,
  13760. /**
  13761. * Set to true if you want to automatically remove the popper when
  13762. * you call the `destroy` method.
  13763. * @prop {Boolean} removeOnDestroy=false
  13764. */
  13765. removeOnDestroy: false,
  13766. /**
  13767. * Callback called when the popper is created.<br />
  13768. * By default, it is set to no-op.<br />
  13769. * Access Popper.js instance with `data.instance`.
  13770. * @prop {onCreate}
  13771. */
  13772. onCreate: function onCreate() {},
  13773. /**
  13774. * Callback called when the popper is updated. This callback is not called
  13775. * on the initialization/creation of the popper, but only on subsequent
  13776. * updates.<br />
  13777. * By default, it is set to no-op.<br />
  13778. * Access Popper.js instance with `data.instance`.
  13779. * @prop {onUpdate}
  13780. */
  13781. onUpdate: function onUpdate() {},
  13782. /**
  13783. * List of modifiers used to modify the offsets before they are applied to the popper.
  13784. * They provide most of the functionalities of Popper.js.
  13785. * @prop {modifiers}
  13786. */
  13787. modifiers: modifiers
  13788. };
  13789. /**
  13790. * @callback onCreate
  13791. * @param {dataObject} data
  13792. */
  13793. /**
  13794. * @callback onUpdate
  13795. * @param {dataObject} data
  13796. */
  13797. // Utils
  13798. // Methods
  13799. var Popper = function () {
  13800. /**
  13801. * Creates a new Popper.js instance.
  13802. * @class Popper
  13803. * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
  13804. * @param {HTMLElement} popper - The HTML element used as the popper
  13805. * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
  13806. * @return {Object} instance - The generated Popper.js instance
  13807. */
  13808. function Popper(reference, popper) {
  13809. var _this = this;
  13810. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  13811. classCallCheck(this, Popper);
  13812. this.scheduleUpdate = function () {
  13813. return requestAnimationFrame(_this.update);
  13814. };
  13815. // make update() debounced, so that it only runs at most once-per-tick
  13816. this.update = debounce(this.update.bind(this));
  13817. // with {} we create a new object with the options inside it
  13818. this.options = _extends({}, Popper.Defaults, options);
  13819. // init state
  13820. this.state = {
  13821. isDestroyed: false,
  13822. isCreated: false,
  13823. scrollParents: []
  13824. };
  13825. // get reference and popper elements (allow jQuery wrappers)
  13826. this.reference = reference && reference.jquery ? reference[0] : reference;
  13827. this.popper = popper && popper.jquery ? popper[0] : popper;
  13828. // Deep merge modifiers options
  13829. this.options.modifiers = {};
  13830. Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
  13831. _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
  13832. });
  13833. // Refactoring modifiers' list (Object => Array)
  13834. this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
  13835. return _extends({
  13836. name: name
  13837. }, _this.options.modifiers[name]);
  13838. })
  13839. // sort the modifiers by order
  13840. .sort(function (a, b) {
  13841. return a.order - b.order;
  13842. });
  13843. // modifiers have the ability to execute arbitrary code when Popper.js get inited
  13844. // such code is executed in the same order of its modifier
  13845. // they could add new properties to their options configuration
  13846. // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
  13847. this.modifiers.forEach(function (modifierOptions) {
  13848. if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
  13849. modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
  13850. }
  13851. });
  13852. // fire the first update to position the popper in the right place
  13853. this.update();
  13854. var eventsEnabled = this.options.eventsEnabled;
  13855. if (eventsEnabled) {
  13856. // setup event listeners, they will take care of update the position in specific situations
  13857. this.enableEventListeners();
  13858. }
  13859. this.state.eventsEnabled = eventsEnabled;
  13860. }
  13861. // We can't use class properties because they don't get listed in the
  13862. // class prototype and break stuff like Sinon stubs
  13863. createClass(Popper, [{
  13864. key: 'update',
  13865. value: function update$$1() {
  13866. return update.call(this);
  13867. }
  13868. }, {
  13869. key: 'destroy',
  13870. value: function destroy$$1() {
  13871. return destroy.call(this);
  13872. }
  13873. }, {
  13874. key: 'enableEventListeners',
  13875. value: function enableEventListeners$$1() {
  13876. return enableEventListeners.call(this);
  13877. }
  13878. }, {
  13879. key: 'disableEventListeners',
  13880. value: function disableEventListeners$$1() {
  13881. return disableEventListeners.call(this);
  13882. }
  13883. /**
  13884. * Schedules an update. It will run on the next UI update available.
  13885. * @method scheduleUpdate
  13886. * @memberof Popper
  13887. */
  13888. /**
  13889. * Collection of utilities useful when writing custom modifiers.
  13890. * Starting from version 1.7, this method is available only if you
  13891. * include `popper-utils.js` before `popper.js`.
  13892. *
  13893. * **DEPRECATION**: This way to access PopperUtils is deprecated
  13894. * and will be removed in v2! Use the PopperUtils module directly instead.
  13895. * Due to the high instability of the methods contained in Utils, we can't
  13896. * guarantee them to follow semver. Use them at your own risk!
  13897. * @static
  13898. * @private
  13899. * @type {Object}
  13900. * @deprecated since version 1.8
  13901. * @member Utils
  13902. * @memberof Popper
  13903. */
  13904. }]);
  13905. return Popper;
  13906. }();
  13907. /**
  13908. * The `referenceObject` is an object that provides an interface compatible with Popper.js
  13909. * and lets you use it as replacement of a real DOM node.<br />
  13910. * You can use this method to position a popper relatively to a set of coordinates
  13911. * in case you don't have a DOM node to use as reference.
  13912. *
  13913. * ```
  13914. * new Popper(referenceObject, popperNode);
  13915. * ```
  13916. *
  13917. * NB: This feature isn't supported in Internet Explorer 10.
  13918. * @name referenceObject
  13919. * @property {Function} data.getBoundingClientRect
  13920. * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
  13921. * @property {number} data.clientWidth
  13922. * An ES6 getter that will return the width of the virtual reference element.
  13923. * @property {number} data.clientHeight
  13924. * An ES6 getter that will return the height of the virtual reference element.
  13925. */
  13926. Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
  13927. Popper.placements = placements;
  13928. Popper.Defaults = Defaults;
  13929. /* harmony default export */ __webpack_exports__["default"] = (Popper);
  13930. //# sourceMappingURL=popper.js.map
  13931. /* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(4)))
  13932. /***/ }),
  13933. /* 4 */
  13934. /***/ (function(module, exports) {
  13935. var g;
  13936. // This works in non-strict mode
  13937. g = (function() {
  13938. return this;
  13939. })();
  13940. try {
  13941. // This works if eval is allowed (see CSP)
  13942. g = g || Function("return this")() || (1,eval)("this");
  13943. } catch(e) {
  13944. // This works if the window reference is available
  13945. if(typeof window === "object")
  13946. g = window;
  13947. }
  13948. // g can still be undefined, but nothing to do about it...
  13949. // We return undefined, instead of nothing here, so it's
  13950. // easier to handle this case. if(!global) { ...}
  13951. module.exports = g;
  13952. /***/ }),
  13953. /* 5 */
  13954. /***/ (function(module, exports, __webpack_require__) {
  13955. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  13956. * Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
  13957. *
  13958. * Copyright 2013-2017 bootstrap-select
  13959. * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
  13960. */
  13961. (function (root, factory) {
  13962. if (true) {
  13963. // AMD. Register as an anonymous module unless amdModuleId is set
  13964. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = function (a0) {
  13965. return (factory(a0));
  13966. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  13967. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  13968. } else if (typeof module === 'object' && module.exports) {
  13969. // Node. Does not work with strict CommonJS, but
  13970. // only CommonJS-like environments that support module.exports,
  13971. // like Node.
  13972. module.exports = factory(require("jquery"));
  13973. } else {
  13974. factory(root["jQuery"]);
  13975. }
  13976. }(this, function (jQuery) {
  13977. (function ($) {
  13978. 'use strict';
  13979. //<editor-fold desc="Shims">
  13980. if (!String.prototype.includes) {
  13981. (function () {
  13982. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  13983. var toString = {}.toString;
  13984. var defineProperty = (function () {
  13985. // IE 8 only supports `Object.defineProperty` on DOM elements
  13986. try {
  13987. var object = {};
  13988. var $defineProperty = Object.defineProperty;
  13989. var result = $defineProperty(object, object, object) && $defineProperty;
  13990. } catch (error) {
  13991. }
  13992. return result;
  13993. }());
  13994. var indexOf = ''.indexOf;
  13995. var includes = function (search) {
  13996. if (this == null) {
  13997. throw new TypeError();
  13998. }
  13999. var string = String(this);
  14000. if (search && toString.call(search) == '[object RegExp]') {
  14001. throw new TypeError();
  14002. }
  14003. var stringLength = string.length;
  14004. var searchString = String(search);
  14005. var searchLength = searchString.length;
  14006. var position = arguments.length > 1 ? arguments[1] : undefined;
  14007. // `ToInteger`
  14008. var pos = position ? Number(position) : 0;
  14009. if (pos != pos) { // better `isNaN`
  14010. pos = 0;
  14011. }
  14012. var start = Math.min(Math.max(pos, 0), stringLength);
  14013. // Avoid the `indexOf` call if no match is possible
  14014. if (searchLength + start > stringLength) {
  14015. return false;
  14016. }
  14017. return indexOf.call(string, searchString, pos) != -1;
  14018. };
  14019. if (defineProperty) {
  14020. defineProperty(String.prototype, 'includes', {
  14021. 'value': includes,
  14022. 'configurable': true,
  14023. 'writable': true
  14024. });
  14025. } else {
  14026. String.prototype.includes = includes;
  14027. }
  14028. }());
  14029. }
  14030. if (!String.prototype.startsWith) {
  14031. (function () {
  14032. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  14033. var defineProperty = (function () {
  14034. // IE 8 only supports `Object.defineProperty` on DOM elements
  14035. try {
  14036. var object = {};
  14037. var $defineProperty = Object.defineProperty;
  14038. var result = $defineProperty(object, object, object) && $defineProperty;
  14039. } catch (error) {
  14040. }
  14041. return result;
  14042. }());
  14043. var toString = {}.toString;
  14044. var startsWith = function (search) {
  14045. if (this == null) {
  14046. throw new TypeError();
  14047. }
  14048. var string = String(this);
  14049. if (search && toString.call(search) == '[object RegExp]') {
  14050. throw new TypeError();
  14051. }
  14052. var stringLength = string.length;
  14053. var searchString = String(search);
  14054. var searchLength = searchString.length;
  14055. var position = arguments.length > 1 ? arguments[1] : undefined;
  14056. // `ToInteger`
  14057. var pos = position ? Number(position) : 0;
  14058. if (pos != pos) { // better `isNaN`
  14059. pos = 0;
  14060. }
  14061. var start = Math.min(Math.max(pos, 0), stringLength);
  14062. // Avoid the `indexOf` call if no match is possible
  14063. if (searchLength + start > stringLength) {
  14064. return false;
  14065. }
  14066. var index = -1;
  14067. while (++index < searchLength) {
  14068. if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
  14069. return false;
  14070. }
  14071. }
  14072. return true;
  14073. };
  14074. if (defineProperty) {
  14075. defineProperty(String.prototype, 'startsWith', {
  14076. 'value': startsWith,
  14077. 'configurable': true,
  14078. 'writable': true
  14079. });
  14080. } else {
  14081. String.prototype.startsWith = startsWith;
  14082. }
  14083. }());
  14084. }
  14085. if (!Object.keys) {
  14086. Object.keys = function (
  14087. o, // object
  14088. k, // key
  14089. r // result array
  14090. ){
  14091. // initialize object and result
  14092. r=[];
  14093. // iterate over object keys
  14094. for (k in o)
  14095. // fill result array with non-prototypical keys
  14096. r.hasOwnProperty.call(o, k) && r.push(k);
  14097. // return result
  14098. return r;
  14099. };
  14100. }
  14101. // set data-selected on select element if the value has been programmatically selected
  14102. // prior to initialization of bootstrap-select
  14103. // * consider removing or replacing an alternative method *
  14104. var valHooks = {
  14105. useDefault: false,
  14106. _set: $.valHooks.select.set
  14107. };
  14108. $.valHooks.select.set = function(elem, value) {
  14109. if (value && !valHooks.useDefault) $(elem).data('selected', true);
  14110. return valHooks._set.apply(this, arguments);
  14111. };
  14112. var changed_arguments = null;
  14113. var EventIsSupported = (function() {
  14114. try {
  14115. new Event('change');
  14116. return true;
  14117. } catch (e) {
  14118. return false;
  14119. }
  14120. })();
  14121. $.fn.triggerNative = function (eventName) {
  14122. var el = this[0],
  14123. event;
  14124. if (el.dispatchEvent) { // for modern browsers & IE9+
  14125. if (EventIsSupported) {
  14126. // For modern browsers
  14127. event = new Event(eventName, {
  14128. bubbles: true
  14129. });
  14130. } else {
  14131. // For IE since it doesn't support Event constructor
  14132. event = document.createEvent('Event');
  14133. event.initEvent(eventName, true, false);
  14134. }
  14135. el.dispatchEvent(event);
  14136. } else if (el.fireEvent) { // for IE8
  14137. event = document.createEventObject();
  14138. event.eventType = eventName;
  14139. el.fireEvent('on' + eventName, event);
  14140. } else {
  14141. // fall back to jQuery.trigger
  14142. this.trigger(eventName);
  14143. }
  14144. };
  14145. //</editor-fold>
  14146. // Case insensitive contains search
  14147. $.expr.pseudos.icontains = function (obj, index, meta) {
  14148. var $obj = $(obj).find('a');
  14149. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  14150. return haystack.includes(meta[3].toUpperCase());
  14151. };
  14152. // Case insensitive begins search
  14153. $.expr.pseudos.ibegins = function (obj, index, meta) {
  14154. var $obj = $(obj).find('a');
  14155. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  14156. return haystack.startsWith(meta[3].toUpperCase());
  14157. };
  14158. // Case and accent insensitive contains search
  14159. $.expr.pseudos.aicontains = function (obj, index, meta) {
  14160. var $obj = $(obj).find('a');
  14161. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  14162. return haystack.includes(meta[3].toUpperCase());
  14163. };
  14164. // Case and accent insensitive begins search
  14165. $.expr.pseudos.aibegins = function (obj, index, meta) {
  14166. var $obj = $(obj).find('a');
  14167. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  14168. return haystack.startsWith(meta[3].toUpperCase());
  14169. };
  14170. /**
  14171. * Remove all diatrics from the given text.
  14172. * @access private
  14173. * @param {String} text
  14174. * @returns {String}
  14175. */
  14176. function normalizeToBase(text) {
  14177. var rExps = [
  14178. {re: /[\xC0-\xC6]/g, ch: "A"},
  14179. {re: /[\xE0-\xE6]/g, ch: "a"},
  14180. {re: /[\xC8-\xCB]/g, ch: "E"},
  14181. {re: /[\xE8-\xEB]/g, ch: "e"},
  14182. {re: /[\xCC-\xCF]/g, ch: "I"},
  14183. {re: /[\xEC-\xEF]/g, ch: "i"},
  14184. {re: /[\xD2-\xD6]/g, ch: "O"},
  14185. {re: /[\xF2-\xF6]/g, ch: "o"},
  14186. {re: /[\xD9-\xDC]/g, ch: "U"},
  14187. {re: /[\xF9-\xFC]/g, ch: "u"},
  14188. {re: /[\xC7-\xE7]/g, ch: "c"},
  14189. {re: /[\xD1]/g, ch: "N"},
  14190. {re: /[\xF1]/g, ch: "n"}
  14191. ];
  14192. $.each(rExps, function () {
  14193. text = text ? text.replace(this.re, this.ch) : '';
  14194. });
  14195. return text;
  14196. }
  14197. // List of HTML entities for escaping.
  14198. var escapeMap = {
  14199. '&': '&amp;',
  14200. '<': '&lt;',
  14201. '>': '&gt;',
  14202. '"': '&quot;',
  14203. "'": '&#x27;',
  14204. '`': '&#x60;'
  14205. };
  14206. var unescapeMap = {
  14207. '&amp;': '&',
  14208. '&lt;': '<',
  14209. '&gt;': '>',
  14210. '&quot;': '"',
  14211. '&#x27;': "'",
  14212. '&#x60;': '`'
  14213. };
  14214. // Functions for escaping and unescaping strings to/from HTML interpolation.
  14215. var createEscaper = function(map) {
  14216. var escaper = function(match) {
  14217. return map[match];
  14218. };
  14219. // Regexes for identifying a key that needs to be escaped.
  14220. var source = '(?:' + Object.keys(map).join('|') + ')';
  14221. var testRegexp = RegExp(source);
  14222. var replaceRegexp = RegExp(source, 'g');
  14223. return function(string) {
  14224. string = string == null ? '' : '' + string;
  14225. return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
  14226. };
  14227. };
  14228. var htmlEscape = createEscaper(escapeMap);
  14229. var htmlUnescape = createEscaper(unescapeMap);
  14230. var Selectpicker = function (element, options) {
  14231. // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
  14232. if (!valHooks.useDefault) {
  14233. $.valHooks.select.set = valHooks._set;
  14234. valHooks.useDefault = true;
  14235. }
  14236. this.$element = $(element);
  14237. this.$newElement = null;
  14238. this.$button = null;
  14239. this.$menu = null;
  14240. this.$lis = null;
  14241. this.options = options;
  14242. // 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
  14243. // data-attribute)
  14244. if (this.options.title === null) {
  14245. this.options.title = this.$element.attr('title');
  14246. }
  14247. // Format window padding
  14248. var winPad = this.options.windowPadding;
  14249. if (typeof winPad === 'number') {
  14250. this.options.windowPadding = [winPad, winPad, winPad, winPad];
  14251. }
  14252. //Expose public methods
  14253. this.val = Selectpicker.prototype.val;
  14254. this.render = Selectpicker.prototype.render;
  14255. this.refresh = Selectpicker.prototype.refresh;
  14256. this.setStyle = Selectpicker.prototype.setStyle;
  14257. this.selectAll = Selectpicker.prototype.selectAll;
  14258. this.deselectAll = Selectpicker.prototype.deselectAll;
  14259. this.destroy = Selectpicker.prototype.destroy;
  14260. this.remove = Selectpicker.prototype.remove;
  14261. this.show = Selectpicker.prototype.show;
  14262. this.hide = Selectpicker.prototype.hide;
  14263. this.init();
  14264. };
  14265. Selectpicker.VERSION = '1.12.4';
  14266. // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
  14267. Selectpicker.DEFAULTS = {
  14268. noneSelectedText: 'Nothing selected',
  14269. noneResultsText: 'No results matched {0}',
  14270. countSelectedText: function (numSelected, numTotal) {
  14271. return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
  14272. },
  14273. maxOptionsText: function (numAll, numGroup) {
  14274. return [
  14275. (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
  14276. (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
  14277. ];
  14278. },
  14279. selectAllText: 'Select All',
  14280. deselectAllText: 'Deselect All',
  14281. doneButton: false,
  14282. doneButtonText: 'Close',
  14283. multipleSeparator: ', ',
  14284. styleBase: 'btn',
  14285. style: 'btn-default',
  14286. size: 'auto',
  14287. title: null,
  14288. selectedTextFormat: 'values',
  14289. width: false,
  14290. container: false,
  14291. hideDisabled: false,
  14292. showSubtext: false,
  14293. showIcon: true,
  14294. showContent: true,
  14295. dropupAuto: true,
  14296. header: false,
  14297. liveSearch: false,
  14298. liveSearchPlaceholder: null,
  14299. liveSearchNormalize: false,
  14300. liveSearchStyle: 'contains',
  14301. actionsBox: false,
  14302. iconBase: 'glyphicon',
  14303. tickIcon: 'glyphicon-ok',
  14304. showTick: false,
  14305. template: {
  14306. caret: '<span class="caret"></span>'
  14307. },
  14308. maxOptions: false,
  14309. mobile: false,
  14310. selectOnTab: false,
  14311. dropdownAlignRight: false,
  14312. windowPadding: 0
  14313. };
  14314. Selectpicker.prototype = {
  14315. constructor: Selectpicker,
  14316. init: function () {
  14317. var that = this,
  14318. id = this.$element.attr('id');
  14319. this.$element.addClass('bs-select-hidden');
  14320. // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
  14321. // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
  14322. this.liObj = {};
  14323. this.multiple = this.$element.prop('multiple');
  14324. this.autofocus = this.$element.prop('autofocus');
  14325. this.$newElement = this.createView();
  14326. this.$element
  14327. .after(this.$newElement)
  14328. .appendTo(this.$newElement);
  14329. this.$button = this.$newElement.children('button');
  14330. this.$menu = this.$newElement.children('.dropdown-menu');
  14331. this.$menuInner = this.$menu.children('.inner');
  14332. this.$searchbox = this.$menu.find('input');
  14333. this.$element.removeClass('bs-select-hidden');
  14334. if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
  14335. if (typeof id !== 'undefined') {
  14336. this.$button.attr('data-id', id);
  14337. $('label[for="' + id + '"]').click(function (e) {
  14338. e.preventDefault();
  14339. that.$button.focus();
  14340. });
  14341. }
  14342. this.checkDisabled();
  14343. this.clickListener();
  14344. if (this.options.liveSearch) this.liveSearchListener();
  14345. this.render();
  14346. this.setStyle();
  14347. this.setWidth();
  14348. if (this.options.container) this.selectPosition();
  14349. this.$menu.data('this', this);
  14350. this.$newElement.data('this', this);
  14351. if (this.options.mobile) this.mobile();
  14352. this.$newElement.on({
  14353. 'hide.bs.dropdown': function (e) {
  14354. that.$menuInner.attr('aria-expanded', false);
  14355. that.$element.trigger('hide.bs.select', e);
  14356. },
  14357. 'hidden.bs.dropdown': function (e) {
  14358. that.$element.trigger('hidden.bs.select', e);
  14359. },
  14360. 'show.bs.dropdown': function (e) {
  14361. that.$menuInner.attr('aria-expanded', true);
  14362. that.$element.trigger('show.bs.select', e);
  14363. },
  14364. 'shown.bs.dropdown': function (e) {
  14365. that.$element.trigger('shown.bs.select', e);
  14366. }
  14367. });
  14368. if (that.$element[0].hasAttribute('required')) {
  14369. this.$element.on('invalid', function () {
  14370. that.$button.addClass('bs-invalid');
  14371. that.$element.on({
  14372. 'focus.bs.select': function () {
  14373. that.$button.focus();
  14374. that.$element.off('focus.bs.select');
  14375. },
  14376. 'shown.bs.select': function () {
  14377. that.$element
  14378. .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
  14379. .off('shown.bs.select');
  14380. },
  14381. 'rendered.bs.select': function () {
  14382. // if select is no longer invalid, remove the bs-invalid class
  14383. if (this.validity.valid) that.$button.removeClass('bs-invalid');
  14384. that.$element.off('rendered.bs.select');
  14385. }
  14386. });
  14387. that.$button.on('blur.bs.select', function() {
  14388. that.$element.focus().blur();
  14389. that.$button.off('blur.bs.select');
  14390. });
  14391. });
  14392. }
  14393. setTimeout(function () {
  14394. that.$element.trigger('loaded.bs.select');
  14395. });
  14396. },
  14397. createDropdown: function () {
  14398. // Options
  14399. // If we are multiple or showTick option is set, then add the show-tick class
  14400. var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
  14401. inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
  14402. autofocus = this.autofocus ? ' autofocus' : '';
  14403. // Elements
  14404. var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
  14405. var searchbox = this.options.liveSearch ?
  14406. '<div class="bs-searchbox">' +
  14407. '<input type="text" class="form-control" autocomplete="off"' +
  14408. (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
  14409. '</div>'
  14410. : '';
  14411. var actionsbox = this.multiple && this.options.actionsBox ?
  14412. '<div class="bs-actionsbox">' +
  14413. '<div class="btn-group btn-group-sm btn-block">' +
  14414. '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
  14415. this.options.selectAllText +
  14416. '</button>' +
  14417. '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
  14418. this.options.deselectAllText +
  14419. '</button>' +
  14420. '</div>' +
  14421. '</div>'
  14422. : '';
  14423. var donebutton = this.multiple && this.options.doneButton ?
  14424. '<div class="bs-donebutton">' +
  14425. '<div class="btn-group btn-block">' +
  14426. '<button type="button" class="btn btn-sm btn-default">' +
  14427. this.options.doneButtonText +
  14428. '</button>' +
  14429. '</div>' +
  14430. '</div>'
  14431. : '';
  14432. var drop =
  14433. '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
  14434. '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
  14435. '<span class="filter-option pull-left"></span>&nbsp;' +
  14436. '<span class="bs-caret">' +
  14437. this.options.template.caret +
  14438. '</span>' +
  14439. '</button>' +
  14440. '<div class="dropdown-menu open" role="combobox">' +
  14441. header +
  14442. searchbox +
  14443. actionsbox +
  14444. '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
  14445. '</ul>' +
  14446. donebutton +
  14447. '</div>' +
  14448. '</div>';
  14449. return $(drop);
  14450. },
  14451. createView: function () {
  14452. var $drop = this.createDropdown(),
  14453. li = this.createLi();
  14454. $drop.find('ul')[0].innerHTML = li;
  14455. return $drop;
  14456. },
  14457. reloadLi: function () {
  14458. // rebuild
  14459. var li = this.createLi();
  14460. this.$menuInner[0].innerHTML = li;
  14461. },
  14462. createLi: function () {
  14463. var that = this,
  14464. _li = [],
  14465. optID = 0,
  14466. titleOption = document.createElement('option'),
  14467. liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
  14468. // Helper functions
  14469. /**
  14470. * @param content
  14471. * @param [index]
  14472. * @param [classes]
  14473. * @param [optgroup]
  14474. * @returns {string}
  14475. */
  14476. var generateLI = function (content, index, classes, optgroup) {
  14477. return '<li' +
  14478. ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
  14479. ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
  14480. ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
  14481. '>' + content + '</li>';
  14482. };
  14483. /**
  14484. * @param text
  14485. * @param [classes]
  14486. * @param [inline]
  14487. * @param [tokens]
  14488. * @returns {string}
  14489. */
  14490. var generateA = function (text, classes, inline, tokens) {
  14491. return '<a tabindex="0"' +
  14492. (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
  14493. (inline ? ' style="' + inline + '"' : '') +
  14494. (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
  14495. (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
  14496. ' role="option">' + text +
  14497. '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
  14498. '</a>';
  14499. };
  14500. if (this.options.title && !this.multiple) {
  14501. // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
  14502. // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
  14503. liIndex--;
  14504. if (!this.$element.find('.bs-title-option').length) {
  14505. // Use native JS to prepend option (faster)
  14506. var element = this.$element[0];
  14507. titleOption.className = 'bs-title-option';
  14508. titleOption.innerHTML = this.options.title;
  14509. titleOption.value = '';
  14510. element.insertBefore(titleOption, element.firstChild);
  14511. // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
  14512. // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
  14513. // if so, the select will have the data-selected attribute
  14514. var $opt = $(element.options[element.selectedIndex]);
  14515. if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
  14516. titleOption.selected = true;
  14517. }
  14518. }
  14519. }
  14520. var $selectOptions = this.$element.find('option');
  14521. $selectOptions.each(function (index) {
  14522. var $this = $(this);
  14523. liIndex++;
  14524. if ($this.hasClass('bs-title-option')) return;
  14525. // Get the class and text for the option
  14526. var optionClass = this.className || '',
  14527. inline = htmlEscape(this.style.cssText),
  14528. text = $this.data('content') ? $this.data('content') : $this.html(),
  14529. tokens = $this.data('tokens') ? $this.data('tokens') : null,
  14530. subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
  14531. icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
  14532. $parent = $this.parent(),
  14533. isOptgroup = $parent[0].tagName === 'OPTGROUP',
  14534. isOptgroupDisabled = isOptgroup && $parent[0].disabled,
  14535. isDisabled = this.disabled || isOptgroupDisabled,
  14536. prevHiddenIndex;
  14537. if (icon !== '' && isDisabled) {
  14538. icon = '<span>' + icon + '</span>';
  14539. }
  14540. if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
  14541. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  14542. // used to determine whether or not a divider should be placed after an optgroup if there are
  14543. // hidden options between the optgroup and the first visible option
  14544. prevHiddenIndex = $this.data('prevHiddenIndex');
  14545. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  14546. liIndex--;
  14547. return;
  14548. }
  14549. if (!$this.data('content')) {
  14550. // Prepend any icon and append any subtext to the main text.
  14551. text = icon + '<span class="text">' + text + subtext + '</span>';
  14552. }
  14553. if (isOptgroup && $this.data('divider') !== true) {
  14554. if (that.options.hideDisabled && isDisabled) {
  14555. if ($parent.data('allOptionsDisabled') === undefined) {
  14556. var $options = $parent.children();
  14557. $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
  14558. }
  14559. if ($parent.data('allOptionsDisabled')) {
  14560. liIndex--;
  14561. return;
  14562. }
  14563. }
  14564. var optGroupClass = ' ' + $parent[0].className || '';
  14565. if ($this.index() === 0) { // Is it the first option of the optgroup?
  14566. optID += 1;
  14567. // Get the opt group label
  14568. var label = $parent[0].label,
  14569. labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
  14570. labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
  14571. label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
  14572. if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
  14573. liIndex++;
  14574. _li.push(generateLI('', null, 'divider', optID + 'div'));
  14575. }
  14576. liIndex++;
  14577. _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
  14578. }
  14579. if (that.options.hideDisabled && isDisabled) {
  14580. liIndex--;
  14581. return;
  14582. }
  14583. _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
  14584. } else if ($this.data('divider') === true) {
  14585. _li.push(generateLI('', index, 'divider'));
  14586. } else if ($this.data('hidden') === true) {
  14587. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  14588. // used to determine whether or not a divider should be placed after an optgroup if there are
  14589. // hidden options between the optgroup and the first visible option
  14590. prevHiddenIndex = $this.data('prevHiddenIndex');
  14591. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  14592. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
  14593. } else {
  14594. var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
  14595. // if previous element is not an optgroup and hideDisabled is true
  14596. if (!showDivider && that.options.hideDisabled) {
  14597. prevHiddenIndex = $this.data('prevHiddenIndex');
  14598. if (prevHiddenIndex !== undefined) {
  14599. // select the element **before** the first hidden element in the group
  14600. var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
  14601. if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
  14602. showDivider = true;
  14603. }
  14604. }
  14605. }
  14606. if (showDivider) {
  14607. liIndex++;
  14608. _li.push(generateLI('', null, 'divider', optID + 'div'));
  14609. }
  14610. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
  14611. }
  14612. that.liObj[index] = liIndex;
  14613. });
  14614. //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
  14615. if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
  14616. this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
  14617. }
  14618. return _li.join('');
  14619. },
  14620. findLis: function () {
  14621. if (this.$lis == null) this.$lis = this.$menu.find('li');
  14622. return this.$lis;
  14623. },
  14624. /**
  14625. * @param [updateLi] defaults to true
  14626. */
  14627. render: function (updateLi) {
  14628. var that = this,
  14629. notDisabled,
  14630. $selectOptions = this.$element.find('option');
  14631. //Update the LI to match the SELECT
  14632. if (updateLi !== false) {
  14633. $selectOptions.each(function (index) {
  14634. var $lis = that.findLis().eq(that.liObj[index]);
  14635. that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
  14636. that.setSelected(index, this.selected, $lis);
  14637. });
  14638. }
  14639. this.togglePlaceholder();
  14640. this.tabIndex();
  14641. var selectedItems = $selectOptions.map(function () {
  14642. if (this.selected) {
  14643. if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
  14644. var $this = $(this),
  14645. icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
  14646. subtext;
  14647. if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
  14648. subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
  14649. } else {
  14650. subtext = '';
  14651. }
  14652. if (typeof $this.attr('title') !== 'undefined') {
  14653. return $this.attr('title');
  14654. } else if ($this.data('content') && that.options.showContent) {
  14655. return $this.data('content').toString();
  14656. } else {
  14657. return icon + $this.html() + subtext;
  14658. }
  14659. }
  14660. }).toArray();
  14661. //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
  14662. //Convert all the values into a comma delimited string
  14663. var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
  14664. //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
  14665. if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
  14666. var max = this.options.selectedTextFormat.split('>');
  14667. if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
  14668. notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
  14669. var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
  14670. tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
  14671. title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
  14672. }
  14673. }
  14674. if (this.options.title == undefined) {
  14675. this.options.title = this.$element.attr('title');
  14676. }
  14677. if (this.options.selectedTextFormat == 'static') {
  14678. title = this.options.title;
  14679. }
  14680. //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
  14681. if (!title) {
  14682. title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
  14683. }
  14684. //strip all HTML tags and trim the result, then unescape any escaped tags
  14685. this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
  14686. this.$button.children('.filter-option').html(title);
  14687. this.$element.trigger('rendered.bs.select');
  14688. },
  14689. /**
  14690. * @param [style]
  14691. * @param [status]
  14692. */
  14693. setStyle: function (style, status) {
  14694. if (this.$element.attr('class')) {
  14695. this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
  14696. }
  14697. var buttonClass = style ? style : this.options.style;
  14698. if (status == 'add') {
  14699. this.$button.addClass(buttonClass);
  14700. } else if (status == 'remove') {
  14701. this.$button.removeClass(buttonClass);
  14702. } else {
  14703. this.$button.removeClass(this.options.style);
  14704. this.$button.addClass(buttonClass);
  14705. }
  14706. },
  14707. liHeight: function (refresh) {
  14708. if (!refresh && (this.options.size === false || this.sizeInfo)) return;
  14709. var newElement = document.createElement('div'),
  14710. menu = document.createElement('div'),
  14711. menuInner = document.createElement('ul'),
  14712. divider = document.createElement('li'),
  14713. li = document.createElement('li'),
  14714. a = document.createElement('a'),
  14715. text = document.createElement('span'),
  14716. header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
  14717. search = this.options.liveSearch ? document.createElement('div') : null,
  14718. actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
  14719. doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
  14720. text.className = 'text';
  14721. newElement.className = this.$menu[0].parentNode.className + ' open';
  14722. menu.className = 'dropdown-menu open';
  14723. menuInner.className = 'dropdown-menu inner';
  14724. divider.className = 'divider';
  14725. text.appendChild(document.createTextNode('Inner text'));
  14726. a.appendChild(text);
  14727. li.appendChild(a);
  14728. menuInner.appendChild(li);
  14729. menuInner.appendChild(divider);
  14730. if (header) menu.appendChild(header);
  14731. if (search) {
  14732. var input = document.createElement('input');
  14733. search.className = 'bs-searchbox';
  14734. input.className = 'form-control';
  14735. search.appendChild(input);
  14736. menu.appendChild(search);
  14737. }
  14738. if (actions) menu.appendChild(actions);
  14739. menu.appendChild(menuInner);
  14740. if (doneButton) menu.appendChild(doneButton);
  14741. newElement.appendChild(menu);
  14742. document.body.appendChild(newElement);
  14743. var liHeight = a.offsetHeight,
  14744. headerHeight = header ? header.offsetHeight : 0,
  14745. searchHeight = search ? search.offsetHeight : 0,
  14746. actionsHeight = actions ? actions.offsetHeight : 0,
  14747. doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
  14748. dividerHeight = $(divider).outerHeight(true),
  14749. // fall back to jQuery if getComputedStyle is not supported
  14750. menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
  14751. $menu = menuStyle ? null : $(menu),
  14752. menuPadding = {
  14753. vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
  14754. parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
  14755. parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
  14756. parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
  14757. horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
  14758. parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
  14759. parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
  14760. parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
  14761. },
  14762. menuExtras = {
  14763. vert: menuPadding.vert +
  14764. parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
  14765. parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
  14766. horiz: menuPadding.horiz +
  14767. parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
  14768. parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
  14769. }
  14770. document.body.removeChild(newElement);
  14771. this.sizeInfo = {
  14772. liHeight: liHeight,
  14773. headerHeight: headerHeight,
  14774. searchHeight: searchHeight,
  14775. actionsHeight: actionsHeight,
  14776. doneButtonHeight: doneButtonHeight,
  14777. dividerHeight: dividerHeight,
  14778. menuPadding: menuPadding,
  14779. menuExtras: menuExtras
  14780. };
  14781. },
  14782. setSize: function () {
  14783. this.findLis();
  14784. this.liHeight();
  14785. if (this.options.header) this.$menu.css('padding-top', 0);
  14786. if (this.options.size === false) return;
  14787. var that = this,
  14788. $menu = this.$menu,
  14789. $menuInner = this.$menuInner,
  14790. $window = $(window),
  14791. selectHeight = this.$newElement[0].offsetHeight,
  14792. selectWidth = this.$newElement[0].offsetWidth,
  14793. liHeight = this.sizeInfo['liHeight'],
  14794. headerHeight = this.sizeInfo['headerHeight'],
  14795. searchHeight = this.sizeInfo['searchHeight'],
  14796. actionsHeight = this.sizeInfo['actionsHeight'],
  14797. doneButtonHeight = this.sizeInfo['doneButtonHeight'],
  14798. divHeight = this.sizeInfo['dividerHeight'],
  14799. menuPadding = this.sizeInfo['menuPadding'],
  14800. menuExtras = this.sizeInfo['menuExtras'],
  14801. notDisabled = this.options.hideDisabled ? '.disabled' : '',
  14802. menuHeight,
  14803. menuWidth,
  14804. getHeight,
  14805. getWidth,
  14806. selectOffsetTop,
  14807. selectOffsetBot,
  14808. selectOffsetLeft,
  14809. selectOffsetRight,
  14810. getPos = function() {
  14811. var pos = that.$newElement.offset(),
  14812. $container = $(that.options.container),
  14813. containerPos;
  14814. if (that.options.container && !$container.is('body')) {
  14815. containerPos = $container.offset();
  14816. containerPos.top += parseInt($container.css('borderTopWidth'));
  14817. containerPos.left += parseInt($container.css('borderLeftWidth'));
  14818. } else {
  14819. containerPos = { top: 0, left: 0 };
  14820. }
  14821. var winPad = that.options.windowPadding;
  14822. selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
  14823. selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
  14824. selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
  14825. selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
  14826. selectOffsetTop -= winPad[0];
  14827. selectOffsetLeft -= winPad[3];
  14828. };
  14829. getPos();
  14830. if (this.options.size === 'auto') {
  14831. var getSize = function () {
  14832. var minHeight,
  14833. hasClass = function (className, include) {
  14834. return function (element) {
  14835. if (include) {
  14836. return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  14837. } else {
  14838. return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  14839. }
  14840. };
  14841. },
  14842. lis = that.$menuInner[0].getElementsByTagName('li'),
  14843. lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
  14844. optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
  14845. getPos();
  14846. menuHeight = selectOffsetBot - menuExtras.vert;
  14847. menuWidth = selectOffsetRight - menuExtras.horiz;
  14848. if (that.options.container) {
  14849. if (!$menu.data('height')) $menu.data('height', $menu.height());
  14850. getHeight = $menu.data('height');
  14851. if (!$menu.data('width')) $menu.data('width', $menu.width());
  14852. getWidth = $menu.data('width');
  14853. } else {
  14854. getHeight = $menu.height();
  14855. getWidth = $menu.width();
  14856. }
  14857. if (that.options.dropupAuto) {
  14858. that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  14859. }
  14860. if (that.$newElement.hasClass('dropup')) {
  14861. menuHeight = selectOffsetTop - menuExtras.vert;
  14862. }
  14863. if (that.options.dropdownAlignRight === 'auto') {
  14864. $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
  14865. }
  14866. if ((lisVisible.length + optGroup.length) > 3) {
  14867. minHeight = liHeight * 3 + menuExtras.vert - 2;
  14868. } else {
  14869. minHeight = 0;
  14870. }
  14871. $menu.css({
  14872. 'max-height': menuHeight + 'px',
  14873. 'overflow': 'hidden',
  14874. 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
  14875. });
  14876. $menuInner.css({
  14877. 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
  14878. 'overflow-y': 'auto',
  14879. 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
  14880. });
  14881. };
  14882. getSize();
  14883. this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
  14884. $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
  14885. } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
  14886. var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
  14887. divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
  14888. menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
  14889. if (that.options.container) {
  14890. if (!$menu.data('height')) $menu.data('height', $menu.height());
  14891. getHeight = $menu.data('height');
  14892. } else {
  14893. getHeight = $menu.height();
  14894. }
  14895. if (that.options.dropupAuto) {
  14896. //noinspection JSUnusedAssignment
  14897. this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  14898. }
  14899. $menu.css({
  14900. 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
  14901. 'overflow': 'hidden',
  14902. 'min-height': ''
  14903. });
  14904. $menuInner.css({
  14905. 'max-height': menuHeight - menuPadding.vert + 'px',
  14906. 'overflow-y': 'auto',
  14907. 'min-height': ''
  14908. });
  14909. }
  14910. },
  14911. setWidth: function () {
  14912. if (this.options.width === 'auto') {
  14913. this.$menu.css('min-width', '0');
  14914. // Get correct width if element is hidden
  14915. var $selectClone = this.$menu.parent().clone().appendTo('body'),
  14916. $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
  14917. ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
  14918. btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
  14919. $selectClone.remove();
  14920. $selectClone2.remove();
  14921. // Set width to whatever's larger, button title or longest option
  14922. this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
  14923. } else if (this.options.width === 'fit') {
  14924. // Remove inline min-width so width can be changed from 'auto'
  14925. this.$menu.css('min-width', '');
  14926. this.$newElement.css('width', '').addClass('fit-width');
  14927. } else if (this.options.width) {
  14928. // Remove inline min-width so width can be changed from 'auto'
  14929. this.$menu.css('min-width', '');
  14930. this.$newElement.css('width', this.options.width);
  14931. } else {
  14932. // Remove inline min-width/width so width can be changed
  14933. this.$menu.css('min-width', '');
  14934. this.$newElement.css('width', '');
  14935. }
  14936. // Remove fit-width class if width is changed programmatically
  14937. if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
  14938. this.$newElement.removeClass('fit-width');
  14939. }
  14940. },
  14941. selectPosition: function () {
  14942. this.$bsContainer = $('<div class="bs-container" />');
  14943. var that = this,
  14944. $container = $(this.options.container),
  14945. pos,
  14946. containerPos,
  14947. actualHeight,
  14948. getPlacement = function ($element) {
  14949. that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
  14950. pos = $element.offset();
  14951. if (!$container.is('body')) {
  14952. containerPos = $container.offset();
  14953. containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
  14954. containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
  14955. } else {
  14956. containerPos = { top: 0, left: 0 };
  14957. }
  14958. actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
  14959. that.$bsContainer.css({
  14960. 'top': pos.top - containerPos.top + actualHeight,
  14961. 'left': pos.left - containerPos.left,
  14962. 'width': $element[0].offsetWidth
  14963. });
  14964. };
  14965. this.$button.on('click', function () {
  14966. var $this = $(this);
  14967. if (that.isDisabled()) {
  14968. return;
  14969. }
  14970. getPlacement(that.$newElement);
  14971. that.$bsContainer
  14972. .appendTo(that.options.container)
  14973. .toggleClass('open', !$this.hasClass('open'))
  14974. .append(that.$menu);
  14975. });
  14976. $(window).on('resize scroll', function () {
  14977. getPlacement(that.$newElement);
  14978. });
  14979. this.$element.on('hide.bs.select', function () {
  14980. that.$menu.data('height', that.$menu.height());
  14981. that.$bsContainer.detach();
  14982. });
  14983. },
  14984. /**
  14985. * @param {number} index - the index of the option that is being changed
  14986. * @param {boolean} selected - true if the option is being selected, false if being deselected
  14987. * @param {JQuery} $lis - the 'li' element that is being modified
  14988. */
  14989. setSelected: function (index, selected, $lis) {
  14990. if (!$lis) {
  14991. this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
  14992. $lis = this.findLis().eq(this.liObj[index]);
  14993. }
  14994. $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
  14995. },
  14996. /**
  14997. * @param {number} index - the index of the option that is being disabled
  14998. * @param {boolean} disabled - true if the option is being disabled, false if being enabled
  14999. * @param {JQuery} $lis - the 'li' element that is being modified
  15000. */
  15001. setDisabled: function (index, disabled, $lis) {
  15002. if (!$lis) {
  15003. $lis = this.findLis().eq(this.liObj[index]);
  15004. }
  15005. if (disabled) {
  15006. $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
  15007. } else {
  15008. $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
  15009. }
  15010. },
  15011. isDisabled: function () {
  15012. return this.$element[0].disabled;
  15013. },
  15014. checkDisabled: function () {
  15015. var that = this;
  15016. if (this.isDisabled()) {
  15017. this.$newElement.addClass('disabled');
  15018. this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
  15019. } else {
  15020. if (this.$button.hasClass('disabled')) {
  15021. this.$newElement.removeClass('disabled');
  15022. this.$button.removeClass('disabled').attr('aria-disabled', false);
  15023. }
  15024. if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
  15025. this.$button.removeAttr('tabindex');
  15026. }
  15027. }
  15028. this.$button.click(function () {
  15029. return !that.isDisabled();
  15030. });
  15031. },
  15032. togglePlaceholder: function () {
  15033. var value = this.$element.val();
  15034. this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
  15035. },
  15036. tabIndex: function () {
  15037. if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
  15038. (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
  15039. this.$element.data('tabindex', this.$element.attr('tabindex'));
  15040. this.$button.attr('tabindex', this.$element.data('tabindex'));
  15041. }
  15042. this.$element.attr('tabindex', -98);
  15043. },
  15044. clickListener: function () {
  15045. var that = this,
  15046. $document = $(document);
  15047. $document.data('spaceSelect', false);
  15048. this.$button.on('keyup', function (e) {
  15049. if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
  15050. e.preventDefault();
  15051. $document.data('spaceSelect', false);
  15052. }
  15053. });
  15054. this.$button.on('click', function () {
  15055. that.setSize();
  15056. });
  15057. this.$element.on('shown.bs.select', function () {
  15058. if (!that.options.liveSearch && !that.multiple) {
  15059. that.$menuInner.find('.selected a').focus();
  15060. } else if (!that.multiple) {
  15061. var selectedIndex = that.liObj[that.$element[0].selectedIndex];
  15062. if (typeof selectedIndex !== 'number' || that.options.size === false) return;
  15063. // scroll to selected option
  15064. var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
  15065. offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
  15066. that.$menuInner[0].scrollTop = offset;
  15067. }
  15068. });
  15069. this.$menuInner.on('click', 'li a', function (e) {
  15070. var $this = $(this),
  15071. clickedIndex = $this.parent().data('originalIndex'),
  15072. prevValue = that.$element.val(),
  15073. prevIndex = that.$element.prop('selectedIndex'),
  15074. triggerChange = true;
  15075. // Don't close on multi choice menu
  15076. if (that.multiple && that.options.maxOptions !== 1) {
  15077. e.stopPropagation();
  15078. }
  15079. e.preventDefault();
  15080. //Don't run if we have been disabled
  15081. if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
  15082. var $options = that.$element.find('option'),
  15083. $option = $options.eq(clickedIndex),
  15084. state = $option.prop('selected'),
  15085. $optgroup = $option.parent('optgroup'),
  15086. maxOptions = that.options.maxOptions,
  15087. maxOptionsGrp = $optgroup.data('maxOptions') || false;
  15088. if (!that.multiple) { // Deselect all others if not multi select box
  15089. $options.prop('selected', false);
  15090. $option.prop('selected', true);
  15091. that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
  15092. that.setSelected(clickedIndex, true);
  15093. } else { // Toggle the one we have chosen if we are multi select.
  15094. $option.prop('selected', !state);
  15095. that.setSelected(clickedIndex, !state);
  15096. $this.blur();
  15097. if (maxOptions !== false || maxOptionsGrp !== false) {
  15098. var maxReached = maxOptions < $options.filter(':selected').length,
  15099. maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
  15100. if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
  15101. if (maxOptions && maxOptions == 1) {
  15102. $options.prop('selected', false);
  15103. $option.prop('selected', true);
  15104. that.$menuInner.find('.selected').removeClass('selected');
  15105. that.setSelected(clickedIndex, true);
  15106. } else if (maxOptionsGrp && maxOptionsGrp == 1) {
  15107. $optgroup.find('option:selected').prop('selected', false);
  15108. $option.prop('selected', true);
  15109. var optgroupID = $this.parent().data('optgroup');
  15110. that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
  15111. that.setSelected(clickedIndex, true);
  15112. } else {
  15113. var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
  15114. maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
  15115. maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
  15116. maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
  15117. $notify = $('<div class="notify"></div>');
  15118. // If {var} is set in array, replace it
  15119. /** @deprecated */
  15120. if (maxOptionsArr[2]) {
  15121. maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
  15122. maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
  15123. }
  15124. $option.prop('selected', false);
  15125. that.$menu.append($notify);
  15126. if (maxOptions && maxReached) {
  15127. $notify.append($('<div>' + maxTxt + '</div>'));
  15128. triggerChange = false;
  15129. that.$element.trigger('maxReached.bs.select');
  15130. }
  15131. if (maxOptionsGrp && maxReachedGrp) {
  15132. $notify.append($('<div>' + maxTxtGrp + '</div>'));
  15133. triggerChange = false;
  15134. that.$element.trigger('maxReachedGrp.bs.select');
  15135. }
  15136. setTimeout(function () {
  15137. that.setSelected(clickedIndex, false);
  15138. }, 10);
  15139. $notify.delay(750).fadeOut(300, function () {
  15140. $(this).remove();
  15141. });
  15142. }
  15143. }
  15144. }
  15145. }
  15146. if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
  15147. that.$button.focus();
  15148. } else if (that.options.liveSearch) {
  15149. that.$searchbox.focus();
  15150. }
  15151. // Trigger select 'change'
  15152. if (triggerChange) {
  15153. if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
  15154. // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
  15155. changed_arguments = [clickedIndex, $option.prop('selected'), state];
  15156. that.$element
  15157. .triggerNative('change');
  15158. }
  15159. }
  15160. }
  15161. });
  15162. this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
  15163. if (e.currentTarget == this) {
  15164. e.preventDefault();
  15165. e.stopPropagation();
  15166. if (that.options.liveSearch && !$(e.target).hasClass('close')) {
  15167. that.$searchbox.focus();
  15168. } else {
  15169. that.$button.focus();
  15170. }
  15171. }
  15172. });
  15173. this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
  15174. e.preventDefault();
  15175. e.stopPropagation();
  15176. if (that.options.liveSearch) {
  15177. that.$searchbox.focus();
  15178. } else {
  15179. that.$button.focus();
  15180. }
  15181. });
  15182. this.$menu.on('click', '.popover-title .close', function () {
  15183. that.$button.click();
  15184. });
  15185. this.$searchbox.on('click', function (e) {
  15186. e.stopPropagation();
  15187. });
  15188. this.$menu.on('click', '.actions-btn', function (e) {
  15189. if (that.options.liveSearch) {
  15190. that.$searchbox.focus();
  15191. } else {
  15192. that.$button.focus();
  15193. }
  15194. e.preventDefault();
  15195. e.stopPropagation();
  15196. if ($(this).hasClass('bs-select-all')) {
  15197. that.selectAll();
  15198. } else {
  15199. that.deselectAll();
  15200. }
  15201. });
  15202. this.$element.change(function () {
  15203. that.render(false);
  15204. that.$element.trigger('changed.bs.select', changed_arguments);
  15205. changed_arguments = null;
  15206. });
  15207. },
  15208. liveSearchListener: function () {
  15209. var that = this,
  15210. $no_results = $('<li class="no-results"></li>');
  15211. this.$button.on('click.dropdown.data-api', function () {
  15212. that.$menuInner.find('.active').removeClass('active');
  15213. if (!!that.$searchbox.val()) {
  15214. that.$searchbox.val('');
  15215. that.$lis.not('.is-hidden').removeClass('hidden');
  15216. if (!!$no_results.parent().length) $no_results.remove();
  15217. }
  15218. if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
  15219. setTimeout(function () {
  15220. that.$searchbox.focus();
  15221. }, 10);
  15222. });
  15223. this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
  15224. e.stopPropagation();
  15225. });
  15226. this.$searchbox.on('input propertychange', function () {
  15227. that.$lis.not('.is-hidden').removeClass('hidden');
  15228. that.$lis.filter('.active').removeClass('active');
  15229. $no_results.remove();
  15230. if (that.$searchbox.val()) {
  15231. var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
  15232. $hideItems;
  15233. if (that.options.liveSearchNormalize) {
  15234. $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
  15235. } else {
  15236. $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
  15237. }
  15238. if ($hideItems.length === $searchBase.length) {
  15239. $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
  15240. that.$menuInner.append($no_results);
  15241. that.$lis.addClass('hidden');
  15242. } else {
  15243. $hideItems.addClass('hidden');
  15244. var $lisVisible = that.$lis.not('.hidden'),
  15245. $foundDiv;
  15246. // hide divider if first or last visible, or if followed by another divider
  15247. $lisVisible.each(function (index) {
  15248. var $this = $(this);
  15249. if ($this.hasClass('divider')) {
  15250. if ($foundDiv === undefined) {
  15251. $this.addClass('hidden');
  15252. } else {
  15253. if ($foundDiv) $foundDiv.addClass('hidden');
  15254. $foundDiv = $this;
  15255. }
  15256. } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
  15257. $this.addClass('hidden');
  15258. } else {
  15259. $foundDiv = null;
  15260. }
  15261. });
  15262. if ($foundDiv) $foundDiv.addClass('hidden');
  15263. $searchBase.not('.hidden').first().addClass('active');
  15264. that.$menuInner.scrollTop(0);
  15265. }
  15266. }
  15267. });
  15268. },
  15269. _searchStyle: function () {
  15270. var styles = {
  15271. begins: 'ibegins',
  15272. startsWith: 'ibegins'
  15273. };
  15274. return styles[this.options.liveSearchStyle] || 'icontains';
  15275. },
  15276. val: function (value) {
  15277. if (typeof value !== 'undefined') {
  15278. this.$element.val(value);
  15279. this.render();
  15280. return this.$element;
  15281. } else {
  15282. return this.$element.val();
  15283. }
  15284. },
  15285. changeAll: function (status) {
  15286. if (!this.multiple) return;
  15287. if (typeof status === 'undefined') status = true;
  15288. this.findLis();
  15289. var $options = this.$element.find('option'),
  15290. $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
  15291. lisVisLen = $lisVisible.length,
  15292. selectedOptions = [];
  15293. if (status) {
  15294. if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
  15295. } else {
  15296. if ($lisVisible.filter('.selected').length === 0) return;
  15297. }
  15298. $lisVisible.toggleClass('selected', status);
  15299. for (var i = 0; i < lisVisLen; i++) {
  15300. var origIndex = $lisVisible[i].getAttribute('data-original-index');
  15301. selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
  15302. }
  15303. $(selectedOptions).prop('selected', status);
  15304. this.render(false);
  15305. this.togglePlaceholder();
  15306. this.$element
  15307. .triggerNative('change');
  15308. },
  15309. selectAll: function () {
  15310. return this.changeAll(true);
  15311. },
  15312. deselectAll: function () {
  15313. return this.changeAll(false);
  15314. },
  15315. toggle: function (e) {
  15316. e = e || window.event;
  15317. if (e) e.stopPropagation();
  15318. this.$button.trigger('click');
  15319. },
  15320. keydown: function (e) {
  15321. var $this = $(this),
  15322. $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
  15323. $items,
  15324. that = $parent.data('this'),
  15325. index,
  15326. prevIndex,
  15327. isActive,
  15328. selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
  15329. keyCodeMap = {
  15330. 32: ' ',
  15331. 48: '0',
  15332. 49: '1',
  15333. 50: '2',
  15334. 51: '3',
  15335. 52: '4',
  15336. 53: '5',
  15337. 54: '6',
  15338. 55: '7',
  15339. 56: '8',
  15340. 57: '9',
  15341. 59: ';',
  15342. 65: 'a',
  15343. 66: 'b',
  15344. 67: 'c',
  15345. 68: 'd',
  15346. 69: 'e',
  15347. 70: 'f',
  15348. 71: 'g',
  15349. 72: 'h',
  15350. 73: 'i',
  15351. 74: 'j',
  15352. 75: 'k',
  15353. 76: 'l',
  15354. 77: 'm',
  15355. 78: 'n',
  15356. 79: 'o',
  15357. 80: 'p',
  15358. 81: 'q',
  15359. 82: 'r',
  15360. 83: 's',
  15361. 84: 't',
  15362. 85: 'u',
  15363. 86: 'v',
  15364. 87: 'w',
  15365. 88: 'x',
  15366. 89: 'y',
  15367. 90: 'z',
  15368. 96: '0',
  15369. 97: '1',
  15370. 98: '2',
  15371. 99: '3',
  15372. 100: '4',
  15373. 101: '5',
  15374. 102: '6',
  15375. 103: '7',
  15376. 104: '8',
  15377. 105: '9'
  15378. };
  15379. isActive = that.$newElement.hasClass('open');
  15380. if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
  15381. if (!that.options.container) {
  15382. that.setSize();
  15383. that.$menu.parent().addClass('open');
  15384. isActive = true;
  15385. } else {
  15386. that.$button.trigger('click');
  15387. }
  15388. that.$searchbox.focus();
  15389. return;
  15390. }
  15391. if (that.options.liveSearch) {
  15392. if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
  15393. e.preventDefault();
  15394. e.stopPropagation();
  15395. that.$menuInner.click();
  15396. that.$button.focus();
  15397. }
  15398. }
  15399. if (/(38|40)/.test(e.keyCode.toString(10))) {
  15400. $items = that.$lis.filter(selector);
  15401. if (!$items.length) return;
  15402. if (!that.options.liveSearch) {
  15403. index = $items.index($items.find('a').filter(':focus').parent());
  15404. } else {
  15405. index = $items.index($items.filter('.active'));
  15406. }
  15407. prevIndex = that.$menuInner.data('prevIndex');
  15408. if (e.keyCode == 38) {
  15409. if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
  15410. if (index < 0) index += $items.length;
  15411. } else if (e.keyCode == 40) {
  15412. if (that.options.liveSearch || index == prevIndex) index++;
  15413. index = index % $items.length;
  15414. }
  15415. that.$menuInner.data('prevIndex', index);
  15416. if (!that.options.liveSearch) {
  15417. $items.eq(index).children('a').focus();
  15418. } else {
  15419. e.preventDefault();
  15420. if (!$this.hasClass('dropdown-toggle')) {
  15421. $items.removeClass('active').eq(index).addClass('active').children('a').focus();
  15422. $this.focus();
  15423. }
  15424. }
  15425. } else if (!$this.is('input')) {
  15426. var keyIndex = [],
  15427. count,
  15428. prevKey;
  15429. $items = that.$lis.filter(selector);
  15430. $items.each(function (i) {
  15431. if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
  15432. keyIndex.push(i);
  15433. }
  15434. });
  15435. count = $(document).data('keycount');
  15436. count++;
  15437. $(document).data('keycount', count);
  15438. prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
  15439. if (prevKey != keyCodeMap[e.keyCode]) {
  15440. count = 1;
  15441. $(document).data('keycount', count);
  15442. } else if (count >= keyIndex.length) {
  15443. $(document).data('keycount', 0);
  15444. if (count > keyIndex.length) count = 1;
  15445. }
  15446. $items.eq(keyIndex[count - 1]).children('a').focus();
  15447. }
  15448. // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
  15449. if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
  15450. if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
  15451. if (!that.options.liveSearch) {
  15452. var elem = $(':focus');
  15453. elem.click();
  15454. // Bring back focus for multiselects
  15455. elem.focus();
  15456. // Prevent screen from scrolling if the user hit the spacebar
  15457. e.preventDefault();
  15458. // Fixes spacebar selection of dropdown items in FF & IE
  15459. $(document).data('spaceSelect', true);
  15460. } else if (!/(32)/.test(e.keyCode.toString(10))) {
  15461. that.$menuInner.find('.active a').click();
  15462. $this.focus();
  15463. }
  15464. $(document).data('keycount', 0);
  15465. }
  15466. if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
  15467. that.$menu.parent().removeClass('open');
  15468. if (that.options.container) that.$newElement.removeClass('open');
  15469. that.$button.focus();
  15470. }
  15471. },
  15472. mobile: function () {
  15473. this.$element.addClass('mobile-device');
  15474. },
  15475. refresh: function () {
  15476. this.$lis = null;
  15477. this.liObj = {};
  15478. this.reloadLi();
  15479. this.render();
  15480. this.checkDisabled();
  15481. this.liHeight(true);
  15482. this.setStyle();
  15483. this.setWidth();
  15484. if (this.$lis) this.$searchbox.trigger('propertychange');
  15485. this.$element.trigger('refreshed.bs.select');
  15486. },
  15487. hide: function () {
  15488. this.$newElement.hide();
  15489. },
  15490. show: function () {
  15491. this.$newElement.show();
  15492. },
  15493. remove: function () {
  15494. this.$newElement.remove();
  15495. this.$element.remove();
  15496. },
  15497. destroy: function () {
  15498. this.$newElement.before(this.$element).remove();
  15499. if (this.$bsContainer) {
  15500. this.$bsContainer.remove();
  15501. } else {
  15502. this.$menu.remove();
  15503. }
  15504. this.$element
  15505. .off('.bs.select')
  15506. .removeData('selectpicker')
  15507. .removeClass('bs-select-hidden selectpicker');
  15508. }
  15509. };
  15510. // SELECTPICKER PLUGIN DEFINITION
  15511. // ==============================
  15512. function Plugin(option) {
  15513. // get the args of the outer function..
  15514. var args = arguments;
  15515. // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
  15516. // to get lost/corrupted in android 2.3 and IE9 #715 #775
  15517. var _option = option;
  15518. [].shift.apply(args);
  15519. var value;
  15520. var chain = this.each(function () {
  15521. var $this = $(this);
  15522. if ($this.is('select')) {
  15523. var data = $this.data('selectpicker'),
  15524. options = typeof _option == 'object' && _option;
  15525. if (!data) {
  15526. var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
  15527. config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
  15528. $this.data('selectpicker', (data = new Selectpicker(this, config)));
  15529. } else if (options) {
  15530. for (var i in options) {
  15531. if (options.hasOwnProperty(i)) {
  15532. data.options[i] = options[i];
  15533. }
  15534. }
  15535. }
  15536. if (typeof _option == 'string') {
  15537. if (data[_option] instanceof Function) {
  15538. value = data[_option].apply(data, args);
  15539. } else {
  15540. value = data.options[_option];
  15541. }
  15542. }
  15543. }
  15544. });
  15545. if (typeof value !== 'undefined') {
  15546. //noinspection JSUnusedAssignment
  15547. return value;
  15548. } else {
  15549. return chain;
  15550. }
  15551. }
  15552. var old = $.fn.selectpicker;
  15553. $.fn.selectpicker = Plugin;
  15554. $.fn.selectpicker.Constructor = Selectpicker;
  15555. // SELECTPICKER NO CONFLICT
  15556. // ========================
  15557. $.fn.selectpicker.noConflict = function () {
  15558. $.fn.selectpicker = old;
  15559. return this;
  15560. };
  15561. $(document)
  15562. .data('keycount', 0)
  15563. .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
  15564. .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
  15565. e.stopPropagation();
  15566. });
  15567. // SELECTPICKER DATA-API
  15568. // =====================
  15569. $(window).on('load.bs.select.data-api', function () {
  15570. $('.selectpicker').each(function () {
  15571. var $selectpicker = $(this);
  15572. Plugin.call($selectpicker, $selectpicker.data());
  15573. })
  15574. });
  15575. })(jQuery);
  15576. }));
  15577. /***/ }),
  15578. /* 6 */
  15579. /***/ (function(module, exports, __webpack_require__) {
  15580. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  15581. * Bootstrap (plugin): validator.js v0.11.9
  15582. * ========================================================================
  15583. * The MIT License (MIT)
  15584. *
  15585. * Copyright (c) 2016 Cina Saffary.
  15586. * Made by @1000hz in the style of Bootstrap 3 era @fat
  15587. *
  15588. * Permission is hereby granted, free of charge, to any person obtaining a copy
  15589. * of this software and associated documentation files (the "Software"), to deal
  15590. * in the Software without restriction, including without limitation the rights
  15591. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15592. * copies of the Software, and to permit persons to whom the Software is
  15593. * furnished to do so, subject to the following conditions:
  15594. *
  15595. * The above copyright notice and this permission notice shall be included in
  15596. * all copies or substantial portions of the Software.
  15597. *
  15598. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15599. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15600. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15601. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15602. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15603. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  15604. * THE SOFTWARE.
  15605. * ======================================================================== */
  15606. +function ($) {
  15607. 'use strict';
  15608. // VALIDATOR CLASS DEFINITION
  15609. // ==========================
  15610. function getValue($el) {
  15611. return $el.is('[type="checkbox"]') ? $el.prop('checked') :
  15612. $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
  15613. $el.is('select[multiple]') ? ($el.val() || []).length :
  15614. $el.val()
  15615. }
  15616. var Validator = function (element, options) {
  15617. this.options = options
  15618. this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
  15619. this.$element = $(element)
  15620. this.$btn = $('button[type="submit"], input[type="submit"]')
  15621. .filter('[form="' + this.$element.attr('id') + '"]')
  15622. .add(this.$element.find('input[type="submit"], button[type="submit"]'))
  15623. this.update()
  15624. this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this))
  15625. this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
  15626. this.$element.on('reset.bs.validator', $.proxy(this.reset, this))
  15627. this.$element.find('[data-match]').each(function () {
  15628. var $this = $(this)
  15629. var target = $this.attr('data-match')
  15630. $(target).on('input.bs.validator', function (e) {
  15631. getValue($this) && $this.trigger('input.bs.validator')
  15632. })
  15633. })
  15634. // run validators for fields with values, but don't clobber server-side errors
  15635. this.$inputs.filter(function () {
  15636. return getValue($(this)) && !$(this).closest('.has-error').length
  15637. }).trigger('focusout')
  15638. this.$element.attr('novalidate', true) // disable automatic native validation
  15639. }
  15640. Validator.VERSION = '0.11.9'
  15641. Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'
  15642. Validator.FOCUS_OFFSET = 20
  15643. Validator.DEFAULTS = {
  15644. delay: 500,
  15645. html: false,
  15646. disable: true,
  15647. focus: true,
  15648. custom: {},
  15649. errors: {
  15650. match: 'Does not match',
  15651. minlength: 'Not long enough'
  15652. },
  15653. feedback: {
  15654. success: 'glyphicon-ok',
  15655. error: 'glyphicon-remove'
  15656. }
  15657. }
  15658. Validator.VALIDATORS = {
  15659. 'native': function ($el) {
  15660. var el = $el[0]
  15661. if (el.checkValidity) {
  15662. return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
  15663. }
  15664. },
  15665. 'match': function ($el) {
  15666. var target = $el.attr('data-match')
  15667. return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
  15668. },
  15669. 'minlength': function ($el) {
  15670. var minlength = $el.attr('data-minlength')
  15671. return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
  15672. }
  15673. }
  15674. Validator.prototype.update = function () {
  15675. var self = this
  15676. this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
  15677. .add(this.$element.find('[data-validate="true"]'))
  15678. .not(this.$element.find('[data-validate="false"]')
  15679. .each(function () { self.clearErrors($(this)) })
  15680. )
  15681. this.toggleSubmit()
  15682. return this
  15683. }
  15684. Validator.prototype.onInput = function (e) {
  15685. var self = this
  15686. var $el = $(e.target)
  15687. var deferErrors = e.type !== 'focusout'
  15688. if (!this.$inputs.is($el)) return
  15689. this.validateInput($el, deferErrors).done(function () {
  15690. self.toggleSubmit()
  15691. })
  15692. }
  15693. Validator.prototype.validateInput = function ($el, deferErrors) {
  15694. var value = getValue($el)
  15695. var prevErrors = $el.data('bs.validator.errors')
  15696. if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
  15697. var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
  15698. this.$element.trigger(e)
  15699. if (e.isDefaultPrevented()) return
  15700. var self = this
  15701. return this.runValidators($el).done(function (errors) {
  15702. $el.data('bs.validator.errors', errors)
  15703. errors.length
  15704. ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
  15705. : self.clearErrors($el)
  15706. if (!prevErrors || errors.toString() !== prevErrors.toString()) {
  15707. e = errors.length
  15708. ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
  15709. : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
  15710. self.$element.trigger(e)
  15711. }
  15712. self.toggleSubmit()
  15713. self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
  15714. })
  15715. }
  15716. Validator.prototype.runValidators = function ($el) {
  15717. var errors = []
  15718. var deferred = $.Deferred()
  15719. $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
  15720. $el.data('bs.validator.deferred', deferred)
  15721. function getValidatorSpecificError(key) {
  15722. return $el.attr('data-' + key + '-error')
  15723. }
  15724. function getValidityStateError() {
  15725. var validity = $el[0].validity
  15726. return validity.typeMismatch ? $el.attr('data-type-error')
  15727. : validity.patternMismatch ? $el.attr('data-pattern-error')
  15728. : validity.stepMismatch ? $el.attr('data-step-error')
  15729. : validity.rangeOverflow ? $el.attr('data-max-error')
  15730. : validity.rangeUnderflow ? $el.attr('data-min-error')
  15731. : validity.valueMissing ? $el.attr('data-required-error')
  15732. : null
  15733. }
  15734. function getGenericError() {
  15735. return $el.attr('data-error')
  15736. }
  15737. function getErrorMessage(key) {
  15738. return getValidatorSpecificError(key)
  15739. || getValidityStateError()
  15740. || getGenericError()
  15741. }
  15742. $.each(this.validators, $.proxy(function (key, validator) {
  15743. var error = null
  15744. if ((getValue($el) || $el.attr('required')) &&
  15745. ($el.attr('data-' + key) !== undefined || key == 'native') &&
  15746. (error = validator.call(this, $el))) {
  15747. error = getErrorMessage(key) || error
  15748. !~errors.indexOf(error) && errors.push(error)
  15749. }
  15750. }, this))
  15751. if (!errors.length && getValue($el) && $el.attr('data-remote')) {
  15752. this.defer($el, function () {
  15753. var data = {}
  15754. data[$el.attr('name')] = getValue($el)
  15755. $.get($el.attr('data-remote'), data)
  15756. .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
  15757. .always(function () { deferred.resolve(errors)})
  15758. })
  15759. } else deferred.resolve(errors)
  15760. return deferred.promise()
  15761. }
  15762. Validator.prototype.validate = function () {
  15763. var self = this
  15764. $.when(this.$inputs.map(function (el) {
  15765. return self.validateInput($(this), false)
  15766. })).then(function () {
  15767. self.toggleSubmit()
  15768. self.focusError()
  15769. })
  15770. return this
  15771. }
  15772. Validator.prototype.focusError = function () {
  15773. if (!this.options.focus) return
  15774. var $input = this.$element.find(".has-error:first :input")
  15775. if ($input.length === 0) return
  15776. $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
  15777. $input.focus()
  15778. }
  15779. Validator.prototype.showErrors = function ($el) {
  15780. var method = this.options.html ? 'html' : 'text'
  15781. var errors = $el.data('bs.validator.errors')
  15782. var $group = $el.closest('.form-group')
  15783. var $block = $group.find('.help-block.with-errors')
  15784. var $feedback = $group.find('.form-control-feedback')
  15785. if (!errors.length) return
  15786. errors = $('<ul/>')
  15787. .addClass('list-unstyled')
  15788. .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
  15789. $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
  15790. $block.empty().append(errors)
  15791. $group.addClass('has-error has-danger')
  15792. $group.hasClass('has-feedback')
  15793. && $feedback.removeClass(this.options.feedback.success)
  15794. && $feedback.addClass(this.options.feedback.error)
  15795. && $group.removeClass('has-success')
  15796. }
  15797. Validator.prototype.clearErrors = function ($el) {
  15798. var $group = $el.closest('.form-group')
  15799. var $block = $group.find('.help-block.with-errors')
  15800. var $feedback = $group.find('.form-control-feedback')
  15801. $block.html($block.data('bs.validator.originalContent'))
  15802. $group.removeClass('has-error has-danger has-success')
  15803. $group.hasClass('has-feedback')
  15804. && $feedback.removeClass(this.options.feedback.error)
  15805. && $feedback.removeClass(this.options.feedback.success)
  15806. && getValue($el)
  15807. && $feedback.addClass(this.options.feedback.success)
  15808. && $group.addClass('has-success')
  15809. }
  15810. Validator.prototype.hasErrors = function () {
  15811. function fieldErrors() {
  15812. return !!($(this).data('bs.validator.errors') || []).length
  15813. }
  15814. return !!this.$inputs.filter(fieldErrors).length
  15815. }
  15816. Validator.prototype.isIncomplete = function () {
  15817. function fieldIncomplete() {
  15818. var value = getValue($(this))
  15819. return !(typeof value == "string" ? $.trim(value) : value)
  15820. }
  15821. return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  15822. }
  15823. Validator.prototype.onSubmit = function (e) {
  15824. this.validate()
  15825. if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  15826. }
  15827. Validator.prototype.toggleSubmit = function () {
  15828. if (!this.options.disable) return
  15829. this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  15830. }
  15831. Validator.prototype.defer = function ($el, callback) {
  15832. callback = $.proxy(callback, this, $el)
  15833. if (!this.options.delay) return callback()
  15834. window.clearTimeout($el.data('bs.validator.timeout'))
  15835. $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  15836. }
  15837. Validator.prototype.reset = function () {
  15838. this.$element.find('.form-control-feedback')
  15839. .removeClass(this.options.feedback.error)
  15840. .removeClass(this.options.feedback.success)
  15841. this.$inputs
  15842. .removeData(['bs.validator.errors', 'bs.validator.deferred'])
  15843. .each(function () {
  15844. var $this = $(this)
  15845. var timeout = $this.data('bs.validator.timeout')
  15846. window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
  15847. })
  15848. this.$element.find('.help-block.with-errors')
  15849. .each(function () {
  15850. var $this = $(this)
  15851. var originalContent = $this.data('bs.validator.originalContent')
  15852. $this
  15853. .removeData('bs.validator.originalContent')
  15854. .html(originalContent)
  15855. })
  15856. this.$btn.removeClass('disabled')
  15857. this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
  15858. return this
  15859. }
  15860. Validator.prototype.destroy = function () {
  15861. this.reset()
  15862. this.$element
  15863. .removeAttr('novalidate')
  15864. .removeData('bs.validator')
  15865. .off('.bs.validator')
  15866. this.$inputs
  15867. .off('.bs.validator')
  15868. this.options = null
  15869. this.validators = null
  15870. this.$element = null
  15871. this.$btn = null
  15872. this.$inputs = null
  15873. return this
  15874. }
  15875. // VALIDATOR PLUGIN DEFINITION
  15876. // ===========================
  15877. function Plugin(option) {
  15878. return this.each(function () {
  15879. var $this = $(this)
  15880. var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
  15881. var data = $this.data('bs.validator')
  15882. if (!data && option == 'destroy') return
  15883. if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
  15884. if (typeof option == 'string') data[option]()
  15885. })
  15886. }
  15887. var old = $.fn.validator
  15888. $.fn.validator = Plugin
  15889. $.fn.validator.Constructor = Validator
  15890. // VALIDATOR NO CONFLICT
  15891. // =====================
  15892. $.fn.validator.noConflict = function () {
  15893. $.fn.validator = old
  15894. return this
  15895. }
  15896. // VALIDATOR DATA-API
  15897. // ==================
  15898. $(window).on('load', function () {
  15899. $('form[data-toggle="validator"]').each(function () {
  15900. var $form = $(this)
  15901. Plugin.call($form, $form.data())
  15902. })
  15903. })
  15904. }(jQuery);
  15905. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  15906. /***/ }),
  15907. /* 7 */
  15908. /***/ (function(module, exports, __webpack_require__) {
  15909. var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  15910. * bootstrap-fileinput v4.4.2
  15911. * http://plugins.krajee.com/file-input
  15912. *
  15913. * Author: Kartik Visweswaran
  15914. * Copyright: 2014 - 2017, Kartik Visweswaran, Krajee.com
  15915. *
  15916. * Licensed under the BSD 3-Clause
  15917. * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
  15918. */
  15919. (function (factory) {
  15920. "use strict";
  15921. //noinspection JSUnresolvedVariable
  15922. if (true) { // jshint ignore:line
  15923. // AMD. Register as an anonymous module.
  15924. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
  15925. __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
  15926. (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
  15927. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // jshint ignore:line
  15928. } else { // noinspection JSUnresolvedVariable
  15929. if (typeof module === 'object' && module.exports) { // jshint ignore:line
  15930. // Node/CommonJS
  15931. // noinspection JSUnresolvedVariable
  15932. module.exports = factory(require('jquery')); // jshint ignore:line
  15933. } else {
  15934. // Browser globals
  15935. factory(window.jQuery);
  15936. }
  15937. }
  15938. }(function ($) {
  15939. "use strict";
  15940. $.fn.fileinputLocales = {};
  15941. $.fn.fileinputThemes = {};
  15942. String.prototype.setTokens = function (replacePairs) {
  15943. var str = this.toString(), key, re;
  15944. for (key in replacePairs) {
  15945. if (replacePairs.hasOwnProperty(key)) {
  15946. re = new RegExp("\{" + key + "\}", "g");
  15947. str = str.replace(re, replacePairs[key]);
  15948. }
  15949. }
  15950. return str;
  15951. };
  15952. var $h, FileInput;
  15953. // fileinput helper object for all global variables and internal helper methods
  15954. //noinspection JSUnresolvedVariable
  15955. $h = {
  15956. FRAMES: '.kv-preview-thumb',
  15957. SORT_CSS: 'file-sortable',
  15958. STYLE_SETTING: 'style="width:{width};height:{height};"',
  15959. OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
  15960. '<param name="allowFullScreen" value="true" />\n' +
  15961. '<param name="allowScriptAccess" value="always" />\n' +
  15962. '<param name="autoPlay" value="false" />\n' +
  15963. '<param name="autoStart" value="false" />\n' +
  15964. '<param name="quality" value="high" />\n',
  15965. DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
  15966. '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
  15967. '</div>',
  15968. MODAL_ID: 'kvFileinputModal',
  15969. MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
  15970. objUrl: window.URL || window.webkitURL,
  15971. compare: function (input, str, exact) {
  15972. return input !== undefined && (exact ? input === str : input.match(str));
  15973. },
  15974. isIE: function (ver) {
  15975. // check for IE versions < 11
  15976. if (navigator.appName !== 'Microsoft Internet Explorer') {
  15977. return false;
  15978. }
  15979. if (ver === 10) {
  15980. return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
  15981. }
  15982. var div = document.createElement("div"), status;
  15983. div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
  15984. status = div.getElementsByTagName("i").length;
  15985. document.body.appendChild(div);
  15986. div.parentNode.removeChild(div);
  15987. return status;
  15988. },
  15989. initModal: function ($modal) {
  15990. var $body = $('body');
  15991. if ($body.length) {
  15992. $modal.appendTo($body);
  15993. }
  15994. },
  15995. isEmpty: function (value, trim) {
  15996. return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
  15997. },
  15998. isArray: function (a) {
  15999. return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
  16000. },
  16001. ifSet: function (needle, haystack, def) {
  16002. def = def || '';
  16003. return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
  16004. },
  16005. cleanArray: function (arr) {
  16006. if (!(arr instanceof Array)) {
  16007. arr = [];
  16008. }
  16009. return arr.filter(function (e) {
  16010. return (e !== undefined && e !== null);
  16011. });
  16012. },
  16013. spliceArray: function (arr, index) {
  16014. var i, j = 0, out = [];
  16015. if (!(arr instanceof Array)) {
  16016. return [];
  16017. }
  16018. for (i = 0; i < arr.length; i++) {
  16019. if (i !== index) {
  16020. out[j] = arr[i];
  16021. j++;
  16022. }
  16023. }
  16024. return out;
  16025. },
  16026. getNum: function (num, def) {
  16027. def = def || 0;
  16028. if (typeof num === "number") {
  16029. return num;
  16030. }
  16031. if (typeof num === "string") {
  16032. num = parseFloat(num);
  16033. }
  16034. return isNaN(num) ? def : num;
  16035. },
  16036. hasFileAPISupport: function () {
  16037. return !!(window.File && window.FileReader);
  16038. },
  16039. hasDragDropSupport: function () {
  16040. var div = document.createElement('div');
  16041. /** @namespace div.draggable */
  16042. /** @namespace div.ondragstart */
  16043. /** @namespace div.ondrop */
  16044. return !$h.isIE(9) &&
  16045. (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
  16046. },
  16047. hasFileUploadSupport: function () {
  16048. return $h.hasFileAPISupport() && window.FormData;
  16049. },
  16050. hasBlobSupport: function () {
  16051. try {
  16052. return !!window.Blob && Boolean(new Blob());
  16053. } catch (e) {
  16054. return false;
  16055. }
  16056. },
  16057. hasArrayBufferViewSupport: function () {
  16058. try {
  16059. return new Blob([new Uint8Array(100)]).size === 100;
  16060. } catch (e) {
  16061. return false;
  16062. }
  16063. },
  16064. dataURI2Blob: function (dataURI) {
  16065. //noinspection JSUnresolvedVariable
  16066. var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
  16067. window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
  16068. canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
  16069. if (!canProceed) {
  16070. return null;
  16071. }
  16072. if (dataURI.split(',')[0].indexOf('base64') >= 0) {
  16073. byteStr = atob(dataURI.split(',')[1]);
  16074. } else {
  16075. byteStr = decodeURIComponent(dataURI.split(',')[1]);
  16076. }
  16077. arrayBuffer = new ArrayBuffer(byteStr.length);
  16078. intArray = new Uint8Array(arrayBuffer);
  16079. for (i = 0; i < byteStr.length; i += 1) {
  16080. intArray[i] = byteStr.charCodeAt(i);
  16081. }
  16082. mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
  16083. if (canBlob) {
  16084. return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
  16085. }
  16086. bb = new BlobBuilder();
  16087. bb.append(arrayBuffer);
  16088. return bb.getBlob(mimeStr);
  16089. },
  16090. addCss: function ($el, css) {
  16091. $el.removeClass(css).addClass(css);
  16092. },
  16093. getElement: function (options, param, value) {
  16094. return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
  16095. },
  16096. uniqId: function () {
  16097. return Math.round(new Date().getTime() + (Math.random() * 100));
  16098. },
  16099. htmlEncode: function (str) {
  16100. return str.replace(/&/g, '&amp;')
  16101. .replace(/</g, '&lt;')
  16102. .replace(/>/g, '&gt;')
  16103. .replace(/"/g, '&quot;')
  16104. .replace(/'/g, '&apos;');
  16105. },
  16106. replaceTags: function (str, tags) {
  16107. var out = str;
  16108. if (!tags) {
  16109. return out;
  16110. }
  16111. $.each(tags, function (key, value) {
  16112. if (typeof value === "function") {
  16113. value = value();
  16114. }
  16115. out = out.split(key).join(value);
  16116. });
  16117. return out;
  16118. },
  16119. cleanMemory: function ($thumb) {
  16120. var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
  16121. /** @namespace $h.objUrl.revokeObjectURL */
  16122. $h.objUrl.revokeObjectURL(data);
  16123. },
  16124. findFileName: function (filePath) {
  16125. var sepIndex = filePath.lastIndexOf('/');
  16126. if (sepIndex === -1) {
  16127. sepIndex = filePath.lastIndexOf('\\');
  16128. }
  16129. return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
  16130. },
  16131. checkFullScreen: function () {
  16132. //noinspection JSUnresolvedVariable
  16133. return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
  16134. document.msFullscreenElement;
  16135. },
  16136. toggleFullScreen: function (maximize) {
  16137. var doc = document, de = doc.documentElement;
  16138. if (de && maximize && !$h.checkFullScreen()) {
  16139. /** @namespace document.requestFullscreen */
  16140. /** @namespace document.msRequestFullscreen */
  16141. /** @namespace document.mozRequestFullScreen */
  16142. /** @namespace document.webkitRequestFullscreen */
  16143. /** @namespace Element.ALLOW_KEYBOARD_INPUT */
  16144. if (de.requestFullscreen) {
  16145. de.requestFullscreen();
  16146. } else if (de.msRequestFullscreen) {
  16147. de.msRequestFullscreen();
  16148. } else if (de.mozRequestFullScreen) {
  16149. de.mozRequestFullScreen();
  16150. } else if (de.webkitRequestFullscreen) {
  16151. de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  16152. }
  16153. } else {
  16154. /** @namespace document.exitFullscreen */
  16155. /** @namespace document.msExitFullscreen */
  16156. /** @namespace document.mozCancelFullScreen */
  16157. /** @namespace document.webkitExitFullscreen */
  16158. if (doc.exitFullscreen) {
  16159. doc.exitFullscreen();
  16160. } else if (doc.msExitFullscreen) {
  16161. doc.msExitFullscreen();
  16162. } else if (doc.mozCancelFullScreen) {
  16163. doc.mozCancelFullScreen();
  16164. } else if (doc.webkitExitFullscreen) {
  16165. doc.webkitExitFullscreen();
  16166. }
  16167. }
  16168. },
  16169. moveArray: function (arr, oldIndex, newIndex) {
  16170. if (newIndex >= arr.length) {
  16171. var k = newIndex - arr.length;
  16172. while ((k--) + 1) {
  16173. arr.push(undefined);
  16174. }
  16175. }
  16176. arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);
  16177. return arr;
  16178. },
  16179. cleanZoomCache: function ($el) {
  16180. var $cache = $el.closest('.kv-zoom-cache-theme');
  16181. if (!$cache.length) {
  16182. $cache = $el.closest('.kv-zoom-cache');
  16183. }
  16184. $cache.remove();
  16185. },
  16186. setOrientation: function (buffer, callback) {
  16187. var scanner = new DataView(buffer), idx = 0, value = 1, // Non-rotated is the default
  16188. maxBytes, uInt16, exifLength;
  16189. if (scanner.getUint16(idx) !== 0xFFD8 || buffer.length < 2) {
  16190. return; // not a proper JPEG
  16191. }
  16192. idx += 2;
  16193. maxBytes = scanner.byteLength;
  16194. while (idx < maxBytes - 2) {
  16195. uInt16 = scanner.getUint16(idx);
  16196. idx += 2;
  16197. switch (uInt16) {
  16198. case 0xFFE1: // Start of EXIF
  16199. exifLength = scanner.getUint16(idx);
  16200. maxBytes = exifLength - idx;
  16201. idx += 2;
  16202. break;
  16203. case 0x0112: // Orientation tag
  16204. value = scanner.getUint16(idx + 6, false);
  16205. maxBytes = 0; // Stop scanning
  16206. break;
  16207. }
  16208. }
  16209. if (callback) {
  16210. callback(value);
  16211. }
  16212. },
  16213. validateOrientation: function (file, callback) {
  16214. if (!window.FileReader || !window.DataView) {
  16215. return; // skip orientation if pre-requisite libraries not supported by browser
  16216. }
  16217. var reader = new FileReader(), buffer;
  16218. reader.onloadend = function () {
  16219. buffer = reader.result;
  16220. $h.setOrientation(buffer, callback);
  16221. };
  16222. reader.readAsArrayBuffer(file);
  16223. },
  16224. adjustOrientedImage: function ($img, isZoom) {
  16225. var offsetContTop, offsetTop, newTop;
  16226. if (!$img.hasClass('is-portrait-gt4')) {
  16227. return;
  16228. }
  16229. if (isZoom) {
  16230. $img.css({width: $img.parent().height()});
  16231. return;
  16232. } else {
  16233. $img.css({height: 'auto', width: $img.height()});
  16234. }
  16235. offsetContTop = $img.parent().offset().top;
  16236. offsetTop = $img.offset().top;
  16237. newTop = offsetContTop - offsetTop;
  16238. $img.css('margin-top', newTop);
  16239. }
  16240. };
  16241. FileInput = function (element, options) {
  16242. var self = this;
  16243. self.$element = $(element);
  16244. if (!self._validate()) {
  16245. return;
  16246. }
  16247. self.isPreviewable = $h.hasFileAPISupport();
  16248. self.isIE9 = $h.isIE(9);
  16249. self.isIE10 = $h.isIE(10);
  16250. if (self.isPreviewable || self.isIE9) {
  16251. self._init(options);
  16252. self._listen();
  16253. } else {
  16254. self.$element.removeClass('file-loading');
  16255. }
  16256. };
  16257. //noinspection JSUnusedGlobalSymbols
  16258. FileInput.prototype = {
  16259. constructor: FileInput,
  16260. _cleanup: function () {
  16261. var self = this;
  16262. self.reader = null;
  16263. self.formdata = {};
  16264. self.uploadCount = 0;
  16265. self.uploadStatus = {};
  16266. self.uploadLog = [];
  16267. self.uploadAsyncCount = 0;
  16268. self.loadedImages = [];
  16269. self.totalImagesCount = 0;
  16270. self.ajaxRequests = [];
  16271. self.clearStack();
  16272. self.fileInputCleared = false;
  16273. self.fileBatchCompleted = true;
  16274. if (!self.isPreviewable) {
  16275. self.showPreview = false;
  16276. }
  16277. self.isError = false;
  16278. self.ajaxAborted = false;
  16279. self.cancelling = false;
  16280. },
  16281. _init: function (options) {
  16282. var self = this, $el = self.$element, $cont, t, tmp;
  16283. self.options = options;
  16284. $.each(options, function (key, value) {
  16285. switch (key) {
  16286. case 'minFileCount':
  16287. case 'maxFileCount':
  16288. case 'minFileSize':
  16289. case 'maxFileSize':
  16290. case 'maxFilePreviewSize':
  16291. case 'resizeImageQuality':
  16292. case 'resizeIfSizeMoreThan':
  16293. case 'progressUploadThreshold':
  16294. case 'initialPreviewCount':
  16295. case 'zoomModalHeight':
  16296. case 'minImageHeight':
  16297. case 'maxImageHeight':
  16298. case 'minImageWidth':
  16299. case 'maxImageWidth':
  16300. self[key] = $h.getNum(value);
  16301. break;
  16302. default:
  16303. self[key] = value;
  16304. break;
  16305. }
  16306. });
  16307. if (self.rtl) { // swap buttons for rtl
  16308. tmp = self.previewZoomButtonIcons.prev;
  16309. self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
  16310. self.previewZoomButtonIcons.next = tmp;
  16311. }
  16312. self._cleanup();
  16313. self.$form = $el.closest('form');
  16314. self._initTemplateDefaults();
  16315. self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
  16316. t = self._getLayoutTemplate('progress');
  16317. self.progressTemplate = t.replace('{class}', self.progressClass);
  16318. self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
  16319. self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
  16320. self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
  16321. self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
  16322. if (self.isDisabled) {
  16323. $el.attr('disabled', true);
  16324. }
  16325. self.isUploadable = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
  16326. self.isClickable = self.browseOnZoneClick && self.showPreview &&
  16327. (self.isUploadable && self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
  16328. self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self._slugDefault;
  16329. self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
  16330. self.captionTemplate = self._getLayoutTemplate('caption');
  16331. self.previewGenericTemplate = self._getPreviewTemplate('generic');
  16332. if (self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
  16333. self.imageCanvas = document.createElement('canvas');
  16334. self.imageCanvasContext = self.imageCanvas.getContext('2d');
  16335. }
  16336. if ($h.isEmpty($el.attr('id'))) {
  16337. $el.attr('id', $h.uniqId());
  16338. }
  16339. self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
  16340. if (self.$container === undefined) {
  16341. self.$container = self._createContainer();
  16342. } else {
  16343. self._refreshContainer();
  16344. }
  16345. $cont = self.$container;
  16346. self.$dropZone = $cont.find('.file-drop-zone');
  16347. self.$progress = $cont.find('.kv-upload-progress');
  16348. self.$btnUpload = $cont.find('.fileinput-upload');
  16349. self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
  16350. self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
  16351. self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
  16352. self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
  16353. self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
  16354. self.$errorContainer = $h.getElement(options, 'elErrorContainer',
  16355. self.$previewContainer.find('.kv-fileinput-error'));
  16356. if (!$h.isEmpty(self.msgErrorClass)) {
  16357. $h.addCss(self.$errorContainer, self.msgErrorClass);
  16358. }
  16359. self.$errorContainer.hide();
  16360. self.previewInitId = "preview-" + $h.uniqId();
  16361. self._initPreviewCache();
  16362. self._initPreview(true);
  16363. self._initPreviewActions();
  16364. self._setFileDropZoneTitle();
  16365. $el.removeClass('file-loading');
  16366. if ($el.attr('disabled')) {
  16367. self.disable();
  16368. }
  16369. self._initZoom();
  16370. if (self.hideThumbnailContent) {
  16371. $h.addCss(self.$preview, 'hide-content');
  16372. }
  16373. },
  16374. _initTemplateDefaults: function () {
  16375. var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
  16376. tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionZoom,
  16377. tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage, tText, tVideo,
  16378. tAudio, tFlash, tObject, tPdf, tOther, tZoomCache, vDefaultDim;
  16379. tMain1 = '{preview}\n' +
  16380. '<div class="kv-upload-progress hide"></div>\n' +
  16381. '<div class="input-group {class}">\n' +
  16382. ' {caption}\n' +
  16383. ' <div class="input-group-btn">\n' +
  16384. ' {remove}\n' +
  16385. ' {cancel}\n' +
  16386. ' {upload}\n' +
  16387. ' {browse}\n' +
  16388. ' </div>\n' +
  16389. '</div>';
  16390. tMain2 = '{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
  16391. tPreview = '<div class="file-preview {class}">\n' +
  16392. ' {close}' +
  16393. ' <div class="{dropClass}">\n' +
  16394. ' <div class="file-preview-thumbnails">\n' +
  16395. ' </div>\n' +
  16396. ' <div class="clearfix"></div>' +
  16397. ' <div class="file-preview-status text-center text-success"></div>\n' +
  16398. ' <div class="kv-fileinput-error"></div>\n' +
  16399. ' </div>\n' +
  16400. '</div>';
  16401. tClose = '<div class="close fileinput-remove">&times;</div>\n';
  16402. tFileIcon = '<i class="glyphicon glyphicon-file kv-caption-icon"></i>';
  16403. tCaption = '<div tabindex="500" class="form-control file-caption {class}">\n' +
  16404. ' <div class="file-caption-name"></div>\n' +
  16405. '</div>\n';
  16406. //noinspection HtmlUnknownAttribute
  16407. tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" ' +
  16408. '{status}>{icon} {label}</button>';
  16409. //noinspection HtmlUnknownAttribute
  16410. tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon} {label}</a>';
  16411. //noinspection HtmlUnknownAttribute
  16412. tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon} {label}</div>';
  16413. tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
  16414. 'tabindex="-1" aria-labelledby="' + $h.MODAL_ID + 'Label"></div>';
  16415. tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
  16416. ' <div class="modal-content">\n' +
  16417. ' <div class="modal-header">\n' +
  16418. ' <div class="kv-zoom-actions pull-right">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
  16419. ' <h3 class="modal-title">{heading} <small><span class="kv-zoom-title"></span></small></h3>\n' +
  16420. ' </div>\n' +
  16421. ' <div class="modal-body">\n' +
  16422. ' <div class="floating-buttons"></div>\n' +
  16423. ' <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
  16424. ' </div>\n' +
  16425. ' </div>\n' +
  16426. '</div>\n';
  16427. tProgress = '<div class="progress">\n' +
  16428. ' <div class="{class}" role="progressbar"' +
  16429. ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
  16430. ' {status}\n' +
  16431. ' </div>\n' +
  16432. '</div>';
  16433. tSize = ' <samp>({sizeText})</samp>';
  16434. tFooter = '<div class="file-thumbnail-footer">\n' +
  16435. ' <div class="file-footer-caption" title="{caption}">{caption}<br>{size}</div>\n' +
  16436. ' {progress} {indicator} {actions}\n' +
  16437. '</div>';
  16438. tActions = '{drag}\n' +
  16439. '<div class="file-actions">\n' +
  16440. ' <div class="file-footer-buttons">\n' +
  16441. ' {upload} {delete} {zoom} {other}' +
  16442. ' </div>\n' +
  16443. ' <div class="clearfix"></div>\n' +
  16444. '</div>';
  16445. //noinspection HtmlUnknownAttribute
  16446. tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
  16447. 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
  16448. tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
  16449. '{uploadIcon}</button>';
  16450. tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
  16451. 'title="{zoomTitle}">{zoomIcon}</button>';
  16452. tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
  16453. tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
  16454. tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  16455. ' data-template="{template}"';
  16456. tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
  16457. tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
  16458. tTagAft = '</div>{footer}\n</div>\n';
  16459. tGeneric = '{content}\n';
  16460. tHtml = '<div class="kv-preview-data file-preview-html" title="{caption}" ' + $h.STYLE_SETTING +
  16461. '>{data}</div>\n';
  16462. tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{caption}" alt="{caption}" ' +
  16463. $h.STYLE_SETTING + '>\n';
  16464. tText = '<textarea class="kv-preview-data file-preview-text" title="{caption}" readonly ' +
  16465. $h.STYLE_SETTING + '>{data}</textarea>\n';
  16466. tVideo = '<video class="kv-preview-data file-preview-video" width="{width}" ' +
  16467. 'height="{height}" controls>\n' + '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW +
  16468. '\n</video>\n';
  16469. tAudio = '<div class="file-preview-audio"><audio class="kv-preview-data" controls>\n<source src="{data}" ' +
  16470. 'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio></div>\n';
  16471. tFlash = '<object class="kv-preview-data file-object" type="application/x-shockwave-flash" ' +
  16472. 'width="{width}" height="{height}" data="{data}">\n' + $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW +
  16473. '\n</object>\n';
  16474. tObject = '<object class="kv-preview-data file-object {typeCss}" data="{data}" type="{type}" ' +
  16475. 'width="{width}" height="{height}">\n' + '<param name="movie" value="{caption}" />\n' +
  16476. $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
  16477. tPdf = '<embed class="kv-preview-data" src="{data}" ' +
  16478. 'width="{width}" height="{height}" type="application/pdf">\n';
  16479. tOther = '<div class="kv-preview-data file-preview-other-frame">\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
  16480. tZoomCache = '<div class="kv-zoom-cache" style="display:none">{zoomContent}</div>';
  16481. vDefaultDim = {width: "100%", height: "100%", 'min-height': "480px"};
  16482. self.defaults = {
  16483. layoutTemplates: {
  16484. main1: tMain1,
  16485. main2: tMain2,
  16486. preview: tPreview,
  16487. close: tClose,
  16488. fileIcon: tFileIcon,
  16489. caption: tCaption,
  16490. modalMain: tModalMain,
  16491. modal: tModal,
  16492. progress: tProgress,
  16493. size: tSize,
  16494. footer: tFooter,
  16495. indicator: tIndicator,
  16496. actions: tActions,
  16497. actionDelete: tActionDelete,
  16498. actionUpload: tActionUpload,
  16499. actionZoom: tActionZoom,
  16500. actionDrag: tActionDrag,
  16501. btnDefault: tBtnDefault,
  16502. btnLink: tBtnLink,
  16503. btnBrowse: tBtnBrowse,
  16504. zoomCache: tZoomCache
  16505. },
  16506. previewMarkupTags: {
  16507. tagBefore1: tTagBef1,
  16508. tagBefore2: tTagBef2,
  16509. tagAfter: tTagAft
  16510. },
  16511. previewContentTemplates: {
  16512. generic: tGeneric,
  16513. html: tHtml,
  16514. image: tImage,
  16515. text: tText,
  16516. video: tVideo,
  16517. audio: tAudio,
  16518. flash: tFlash,
  16519. object: tObject,
  16520. pdf: tPdf,
  16521. other: tOther
  16522. },
  16523. allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
  16524. previewTemplates: {},
  16525. previewSettings: {
  16526. image: {width: "auto", height: "160px"},
  16527. html: {width: "213px", height: "160px"},
  16528. text: {width: "213px", height: "160px"},
  16529. video: {width: "auto", height: "100%", 'max-width': "100%"},
  16530. audio: {width: "100%", height: "30px"},
  16531. flash: {width: "auto", height: "100%", 'max-width': "100%"},
  16532. object: {height: "100%"},
  16533. pdf: {width: "160px", height: "160px"},
  16534. other: {width: "160px", height: "160px"}
  16535. },
  16536. previewZoomSettings: {
  16537. image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
  16538. html: vDefaultDim,
  16539. text: vDefaultDim,
  16540. video: {width: "auto", height: "100%", 'max-width': "100%"},
  16541. audio: {width: "100%", height: "30px"},
  16542. flash: {width: "auto", height: "480px"},
  16543. object: {width: "auto", height: "100%", 'max-width': "100%", 'min-height': "480px"},
  16544. pdf: vDefaultDim,
  16545. other: {width: "auto", height: "100%", 'min-height': "480px"}
  16546. },
  16547. fileTypeSettings: {
  16548. image: function (vType, vName) {
  16549. return $h.compare(vType, 'image.*') || $h.compare(vName, /\.(gif|png|jpe?g)$/i);
  16550. },
  16551. html: function (vType, vName) {
  16552. return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
  16553. },
  16554. text: function (vType, vName) {
  16555. return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
  16556. $h.compare(vName, /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
  16557. },
  16558. video: function (vType, vName) {
  16559. return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
  16560. $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
  16561. },
  16562. audio: function (vType, vName) {
  16563. return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
  16564. $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
  16565. },
  16566. flash: function (vType, vName) {
  16567. return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName, /\.(swf)$/i);
  16568. },
  16569. pdf: function (vType, vName) {
  16570. return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
  16571. },
  16572. object: function () {
  16573. return true;
  16574. },
  16575. other: function () {
  16576. return true;
  16577. }
  16578. },
  16579. fileActionSettings: {
  16580. showRemove: true,
  16581. showUpload: true,
  16582. showZoom: true,
  16583. showDrag: true,
  16584. removeIcon: '<i class="glyphicon glyphicon-trash text-danger"></i>',
  16585. removeClass: 'btn btn-xs btn-default',
  16586. removeTitle: 'Remove file',
  16587. uploadIcon: '<i class="glyphicon glyphicon-upload text-info"></i>',
  16588. uploadClass: 'btn btn-xs btn-default',
  16589. uploadTitle: 'Upload file',
  16590. zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
  16591. zoomClass: 'btn btn-xs btn-default',
  16592. zoomTitle: 'View Details',
  16593. dragIcon: '<i class="glyphicon glyphicon-menu-hamburger"></i>',
  16594. dragClass: 'text-info',
  16595. dragTitle: 'Move / Rearrange',
  16596. dragSettings: {},
  16597. indicatorNew: '<i class="glyphicon glyphicon-hand-down text-warning"></i>',
  16598. indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
  16599. indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
  16600. indicatorLoading: '<i class="glyphicon glyphicon-hand-up text-muted"></i>',
  16601. indicatorNewTitle: 'Not uploaded yet',
  16602. indicatorSuccessTitle: 'Uploaded',
  16603. indicatorErrorTitle: 'Upload Error',
  16604. indicatorLoadingTitle: 'Uploading ...'
  16605. }
  16606. };
  16607. $.each(self.defaults, function (key, setting) {
  16608. if (key === 'allowedPreviewTypes') {
  16609. if (self.allowedPreviewTypes === undefined) {
  16610. self.allowedPreviewTypes = setting;
  16611. }
  16612. return;
  16613. }
  16614. self[key] = $.extend(true, {}, setting, self[key]);
  16615. });
  16616. self._initPreviewTemplates();
  16617. },
  16618. _initPreviewTemplates: function () {
  16619. var self = this, cfg = self.defaults, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
  16620. $.each(cfg.previewContentTemplates, function (key, value) {
  16621. if ($h.isEmpty(self.previewTemplates[key])) {
  16622. tagBef = tags.tagBefore2;
  16623. if (key === 'generic' || key === 'image' || key === 'html' || key === 'text') {
  16624. tagBef = tags.tagBefore1;
  16625. }
  16626. self.previewTemplates[key] = tagBef + value + tagAft;
  16627. }
  16628. });
  16629. },
  16630. _initPreviewCache: function () {
  16631. var self = this;
  16632. self.previewCache = {
  16633. data: {},
  16634. init: function () {
  16635. var content = self.initialPreview;
  16636. if (content.length > 0 && !$h.isArray(content)) {
  16637. content = content.split(self.initialPreviewDelimiter);
  16638. }
  16639. self.previewCache.data = {
  16640. content: content,
  16641. config: self.initialPreviewConfig,
  16642. tags: self.initialPreviewThumbTags
  16643. };
  16644. },
  16645. fetch: function () {
  16646. return self.previewCache.data.content.filter(function (n) {
  16647. return n !== null;
  16648. });
  16649. },
  16650. count: function (all) {
  16651. return !!self.previewCache.data && !!self.previewCache.data.content ?
  16652. (all ? self.previewCache.data.content.length : self.previewCache.fetch().length) : 0;
  16653. },
  16654. get: function (i, isDisabled) {
  16655. var ind = 'init_' + i, data = self.previewCache.data, config = data.config[i],
  16656. content = data.content[i], previewId = self.previewInitId + '-' + ind, out, $tmp, cat, ftr,
  16657. fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
  16658. parseTemplate = function (cat, dat, fn, ft, id, ftr, ind, fc, t) {
  16659. fc = ' file-preview-initial ' + $h.SORT_CSS + (fc ? ' ' + fc : '');
  16660. return self._generatePreviewTemplate(cat, dat, fn, ft, id, false, null, fc, ftr, ind, t);
  16661. };
  16662. if (!content) {
  16663. return '';
  16664. }
  16665. isDisabled = isDisabled === undefined ? true : isDisabled;
  16666. cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
  16667. fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
  16668. ftype = $h.ifSet('filetype', config, cat);
  16669. ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
  16670. frameClass = $h.ifSet('frameClass', config);
  16671. if (asData) {
  16672. out = parseTemplate(cat, content, fname, ftype, previewId, ftr, ind, frameClass);
  16673. } else {
  16674. out = parseTemplate('generic', content, fname, ftype, previewId, ftr, ind, frameClass, cat)
  16675. .setTokens({'content': data.content[i]});
  16676. }
  16677. if (data.tags.length && data.tags[i]) {
  16678. out = $h.replaceTags(out, data.tags[i]);
  16679. }
  16680. /** @namespace config.frameAttr */
  16681. if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
  16682. $tmp = $(document.createElement('div')).html(out);
  16683. $tmp.find('.file-preview-initial').attr(config.frameAttr);
  16684. out = $tmp.html();
  16685. $tmp.remove();
  16686. }
  16687. return out;
  16688. },
  16689. add: function (content, config, tags, append) {
  16690. var data = self.previewCache.data, index;
  16691. if (!$h.isArray(content)) {
  16692. content = content.split(self.initialPreviewDelimiter);
  16693. }
  16694. if (append) {
  16695. index = data.content.push(content) - 1;
  16696. data.config[index] = config;
  16697. data.tags[index] = tags;
  16698. } else {
  16699. index = content.length - 1;
  16700. data.content = content;
  16701. data.config = config;
  16702. data.tags = tags;
  16703. }
  16704. self.previewCache.data = data;
  16705. return index;
  16706. },
  16707. set: function (content, config, tags, append) {
  16708. var data = self.previewCache.data, i, chk;
  16709. if (!content || !content.length) {
  16710. return;
  16711. }
  16712. if (!$h.isArray(content)) {
  16713. content = content.split(self.initialPreviewDelimiter);
  16714. }
  16715. chk = content.filter(function (n) {
  16716. return n !== null;
  16717. });
  16718. if (!chk.length) {
  16719. return;
  16720. }
  16721. if (data.content === undefined) {
  16722. data.content = [];
  16723. }
  16724. if (data.config === undefined) {
  16725. data.config = [];
  16726. }
  16727. if (data.tags === undefined) {
  16728. data.tags = [];
  16729. }
  16730. if (append) {
  16731. for (i = 0; i < content.length; i++) {
  16732. if (content[i]) {
  16733. data.content.push(content[i]);
  16734. }
  16735. }
  16736. for (i = 0; i < config.length; i++) {
  16737. if (config[i]) {
  16738. data.config.push(config[i]);
  16739. }
  16740. }
  16741. for (i = 0; i < tags.length; i++) {
  16742. if (tags[i]) {
  16743. data.tags.push(tags[i]);
  16744. }
  16745. }
  16746. } else {
  16747. data.content = content;
  16748. data.config = config;
  16749. data.tags = tags;
  16750. }
  16751. self.previewCache.data = data;
  16752. },
  16753. unset: function (index) {
  16754. var chk = self.previewCache.count();
  16755. if (!chk) {
  16756. return;
  16757. }
  16758. if (chk === 1) {
  16759. self.previewCache.data.content = [];
  16760. self.previewCache.data.config = [];
  16761. self.previewCache.data.tags = [];
  16762. self.initialPreview = [];
  16763. self.initialPreviewConfig = [];
  16764. self.initialPreviewThumbTags = [];
  16765. return;
  16766. }
  16767. self.previewCache.data.content[index] = null;
  16768. self.previewCache.data.config[index] = null;
  16769. self.previewCache.data.tags[index] = null;
  16770. },
  16771. out: function () {
  16772. var html = '', caption, len = self.previewCache.count(true), i;
  16773. if (len === 0) {
  16774. return {content: '', caption: ''};
  16775. }
  16776. for (i = 0; i < len; i++) {
  16777. html += self.previewCache.get(i);
  16778. }
  16779. caption = self._getMsgSelected(self.previewCache.count());
  16780. return {content: html, caption: caption};
  16781. },
  16782. footer: function (i, isDisabled, size) {
  16783. var data = self.previewCache.data;
  16784. if (!data || !data.config || data.config.length === 0 || $h.isEmpty(data.config[i])) {
  16785. return '';
  16786. }
  16787. isDisabled = isDisabled === undefined ? true : isDisabled;
  16788. var config = data.config[i], caption = $h.ifSet('caption', config), actions,
  16789. width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
  16790. key = $h.ifSet('key', config, null), fs = self.fileActionSettings,
  16791. initPreviewShowDel = self.initialPreviewShowDelete || false,
  16792. showDel = $h.ifSet('showDelete', config, $h.ifSet('showDelete', fs, initPreviewShowDel)),
  16793. showZoom = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
  16794. showDrag = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
  16795. disabled = (url === false) && isDisabled;
  16796. actions = self._renderFileActions(false, showDel, showZoom, showDrag, disabled, url, key, true);
  16797. return self._getLayoutTemplate('footer').setTokens({
  16798. 'progress': self._renderThumbProgress(),
  16799. 'actions': actions,
  16800. 'caption': caption,
  16801. 'size': self._getSize(size),
  16802. 'width': width,
  16803. 'indicator': ''
  16804. });
  16805. }
  16806. };
  16807. self.previewCache.init();
  16808. },
  16809. _handler: function ($el, event, callback) {
  16810. var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
  16811. if (!$el || !$el.length) {
  16812. return;
  16813. }
  16814. $el.off(ev).on(ev, callback);
  16815. },
  16816. _log: function (msg) {
  16817. var self = this, id = self.$element.attr('id');
  16818. if (id) {
  16819. msg = '"' + id + '": ' + msg;
  16820. }
  16821. if (typeof window.console.log !== "undefined") {
  16822. window.console.log(msg);
  16823. } else {
  16824. window.alert(msg);
  16825. }
  16826. },
  16827. _validate: function () {
  16828. var self = this, status = self.$element.attr('type') === 'file';
  16829. if (!status) {
  16830. self._log('The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.');
  16831. }
  16832. return status;
  16833. },
  16834. _errorsExist: function () {
  16835. var self = this, $err;
  16836. if (self.$errorContainer.find('li').length) {
  16837. return true;
  16838. }
  16839. $err = $(document.createElement('div')).html(self.$errorContainer.html());
  16840. $err.find('span.kv-error-close').remove();
  16841. $err.find('ul').remove();
  16842. return $.trim($err.text()).length ? true : false;
  16843. },
  16844. _errorHandler: function (evt, caption) {
  16845. var self = this, err = evt.target.error, showError = function (msg) {
  16846. self._showError(msg.replace('{name}', caption));
  16847. };
  16848. /** @namespace err.NOT_FOUND_ERR */
  16849. /** @namespace err.SECURITY_ERR */
  16850. /** @namespace err.NOT_READABLE_ERR */
  16851. if (err.code === err.NOT_FOUND_ERR) {
  16852. showError(self.msgFileNotFound);
  16853. } else if (err.code === err.SECURITY_ERR) {
  16854. showError(self.msgFileSecured);
  16855. } else if (err.code === err.NOT_READABLE_ERR) {
  16856. showError(self.msgFileNotReadable);
  16857. } else if (err.code === err.ABORT_ERR) {
  16858. showError(self.msgFilePreviewAborted);
  16859. } else {
  16860. showError(self.msgFilePreviewError);
  16861. }
  16862. },
  16863. _addError: function (msg) {
  16864. var self = this, $error = self.$errorContainer;
  16865. if (msg && $error.length) {
  16866. $error.html(self.errorCloseButton + msg);
  16867. self._handler($error.find('.kv-error-close'), 'click', function () {
  16868. $error.fadeOut('slow');
  16869. });
  16870. }
  16871. },
  16872. _resetErrors: function (fade) {
  16873. var self = this, $error = self.$errorContainer;
  16874. self.isError = false;
  16875. self.$container.removeClass('has-error');
  16876. $error.html('');
  16877. if (fade) {
  16878. $error.fadeOut('slow');
  16879. } else {
  16880. $error.hide();
  16881. }
  16882. },
  16883. _showFolderError: function (folders) {
  16884. var self = this, $error = self.$errorContainer, msg;
  16885. if (!folders) {
  16886. return;
  16887. }
  16888. msg = self.msgFoldersNotAllowed.replace('{n}', folders);
  16889. self._addError(msg);
  16890. $h.addCss(self.$container, 'has-error');
  16891. $error.fadeIn(800);
  16892. self._raise('filefoldererror', [folders, msg]);
  16893. },
  16894. _showUploadError: function (msg, params, event) {
  16895. var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror', e = params && params.id ?
  16896. '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
  16897. if ($error.find('ul').length === 0) {
  16898. self._addError('<ul>' + e + '</ul>');
  16899. } else {
  16900. $error.find('ul').append(e);
  16901. }
  16902. $error.fadeIn(800);
  16903. self._raise(ev, [params, msg]);
  16904. self.$container.removeClass('file-input-new');
  16905. $h.addCss(self.$container, 'has-error');
  16906. return true;
  16907. },
  16908. _showError: function (msg, params, event) {
  16909. var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
  16910. params = params || {};
  16911. params.reader = self.reader;
  16912. self._addError(msg);
  16913. $error.fadeIn(800);
  16914. self._raise(ev, [params, msg]);
  16915. if (!self.isUploadable) {
  16916. self._clearFileInput();
  16917. }
  16918. self.$container.removeClass('file-input-new');
  16919. $h.addCss(self.$container, 'has-error');
  16920. self.$btnUpload.attr('disabled', true);
  16921. return true;
  16922. },
  16923. _noFilesError: function (params) {
  16924. var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
  16925. msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
  16926. $error = self.$errorContainer;
  16927. self._addError(msg);
  16928. self.isError = true;
  16929. self._updateFileDetails(0);
  16930. $error.fadeIn(800);
  16931. self._raise('fileerror', [params, msg]);
  16932. self._clearFileInput();
  16933. $h.addCss(self.$container, 'has-error');
  16934. },
  16935. _parseError: function (operation, jqXHR, errorThrown, fileName) {
  16936. /** @namespace jqXHR.responseJSON */
  16937. var self = this, errMsg = $.trim(errorThrown + ''), dot = errMsg.slice(-1) === '.' ? '' : '.',
  16938. text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
  16939. jqXHR.responseJSON.error : jqXHR.responseText;
  16940. if (self.cancelling && self.msgUploadAborted) {
  16941. errMsg = self.msgUploadAborted;
  16942. }
  16943. if (self.showAjaxErrorDetails && text) {
  16944. text = $.trim(text.replace(/\n\s*\n/g, '\n'));
  16945. text = text.length > 0 ? '<pre>' + text + '</pre>' : '';
  16946. errMsg += dot + text;
  16947. } else {
  16948. errMsg += dot;
  16949. }
  16950. if (errMsg === dot) {
  16951. errMsg = self.msgAjaxError.replace('{operation}', operation);
  16952. }
  16953. self.cancelling = false;
  16954. return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
  16955. },
  16956. _parseFileType: function (file) {
  16957. var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
  16958. for (i = 0; i < types.length; i++) {
  16959. cat = types[i];
  16960. isValid = self.fileTypeSettings[cat];
  16961. vType = isValid(file.type, file.name) ? cat : '';
  16962. if (!$h.isEmpty(vType)) {
  16963. return vType;
  16964. }
  16965. }
  16966. return 'other';
  16967. },
  16968. _getPreviewIcon: function (fname) {
  16969. var self = this, ext, out = null;
  16970. if (fname && fname.indexOf('.') > -1) {
  16971. ext = fname.split('.').pop();
  16972. if (self.previewFileIconSettings) {
  16973. out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
  16974. }
  16975. if (self.previewFileExtSettings) {
  16976. $.each(self.previewFileExtSettings, function (key, func) {
  16977. if (self.previewFileIconSettings[key] && func(ext)) {
  16978. out = self.previewFileIconSettings[key];
  16979. //noinspection UnnecessaryReturnStatementJS
  16980. return;
  16981. }
  16982. });
  16983. }
  16984. }
  16985. return out;
  16986. },
  16987. _parseFilePreviewIcon: function (content, fname) {
  16988. var self = this, icn = self._getPreviewIcon(fname) || self.previewFileIcon, out = content;
  16989. if (out.indexOf('{previewFileIcon}') > -1) {
  16990. out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
  16991. }
  16992. return out;
  16993. },
  16994. _raise: function (event, params) {
  16995. var self = this, e = $.Event(event);
  16996. if (params !== undefined) {
  16997. self.$element.trigger(e, params);
  16998. } else {
  16999. self.$element.trigger(e);
  17000. }
  17001. if (e.isDefaultPrevented() || e.result === false) {
  17002. return false;
  17003. }
  17004. switch (event) {
  17005. // ignore these events
  17006. case 'filebatchuploadcomplete':
  17007. case 'filebatchuploadsuccess':
  17008. case 'fileuploaded':
  17009. case 'fileclear':
  17010. case 'filecleared':
  17011. case 'filereset':
  17012. case 'fileerror':
  17013. case 'filefoldererror':
  17014. case 'fileuploaderror':
  17015. case 'filebatchuploaderror':
  17016. case 'filedeleteerror':
  17017. case 'filecustomerror':
  17018. case 'filesuccessremove':
  17019. break;
  17020. // receive data response via `filecustomerror` event`
  17021. default:
  17022. if (!self.ajaxAborted) {
  17023. self.ajaxAborted = e.result;
  17024. }
  17025. break;
  17026. }
  17027. return true;
  17028. },
  17029. _listenFullScreen: function (isFullScreen) {
  17030. var self = this, $modal = self.$modal, $btnFull, $btnBord;
  17031. if (!$modal || !$modal.length) {
  17032. return;
  17033. }
  17034. $btnFull = $modal && $modal.find('.btn-fullscreen');
  17035. $btnBord = $modal && $modal.find('.btn-borderless');
  17036. if (!$btnFull.length || !$btnBord.length) {
  17037. return;
  17038. }
  17039. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17040. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17041. if (isFullScreen) {
  17042. $btnFull.addClass('active').attr('aria-pressed', 'true');
  17043. } else {
  17044. $btnBord.addClass('active').attr('aria-pressed', 'true');
  17045. }
  17046. if ($modal.hasClass('file-zoom-fullscreen')) {
  17047. self._maximizeZoomDialog();
  17048. } else {
  17049. if (isFullScreen) {
  17050. self._maximizeZoomDialog();
  17051. } else {
  17052. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17053. }
  17054. }
  17055. },
  17056. _listen: function () {
  17057. var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEvents;
  17058. self._handler($el, 'change', $.proxy(self._change, self));
  17059. if (self.showBrowse) {
  17060. self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
  17061. }
  17062. self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
  17063. self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
  17064. self._initDragDrop();
  17065. self._handler($form, 'reset', $.proxy(self.reset, self));
  17066. if (!self.isUploadable) {
  17067. self._handler($form, 'submit', $.proxy(self._submitForm, self));
  17068. }
  17069. self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
  17070. self._handler($(window), 'resize', function () {
  17071. self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
  17072. });
  17073. fullScreenEvents = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
  17074. self._handler($(document), fullScreenEvents, function () {
  17075. self._listenFullScreen($h.checkFullScreen());
  17076. });
  17077. self._initClickable();
  17078. },
  17079. _initClickable: function () {
  17080. var self = this, $zone;
  17081. if (!self.isClickable) {
  17082. return;
  17083. }
  17084. $zone = self.isUploadable ? self.$dropZone : self.$preview.find('.file-default-preview');
  17085. $h.addCss($zone, 'clickable');
  17086. $zone.attr('tabindex', -1);
  17087. self._handler($zone, 'click', function (e) {
  17088. var $tar = $(e.target);
  17089. if (!$tar.parents('.file-preview-thumbnails').length || $tar.parents('.file-default-preview').length) {
  17090. self.$element.trigger('click');
  17091. $zone.blur();
  17092. }
  17093. });
  17094. },
  17095. _initDragDrop: function () {
  17096. var self = this, $zone = self.$dropZone;
  17097. if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
  17098. self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
  17099. self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
  17100. self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
  17101. self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
  17102. }
  17103. },
  17104. _zoneDragDropInit: function (e) {
  17105. e.stopPropagation();
  17106. e.preventDefault();
  17107. },
  17108. _zoneDragEnter: function (e) {
  17109. var self = this, hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
  17110. self._zoneDragDropInit(e);
  17111. if (self.isDisabled || !hasFiles) {
  17112. e.originalEvent.dataTransfer.effectAllowed = 'none';
  17113. e.originalEvent.dataTransfer.dropEffect = 'none';
  17114. return;
  17115. }
  17116. $h.addCss(self.$dropZone, 'file-highlighted');
  17117. },
  17118. _zoneDragLeave: function (e) {
  17119. var self = this;
  17120. self._zoneDragDropInit(e);
  17121. if (self.isDisabled) {
  17122. return;
  17123. }
  17124. self.$dropZone.removeClass('file-highlighted');
  17125. },
  17126. _zoneDrop: function (e) {
  17127. var self = this;
  17128. e.preventDefault();
  17129. /** @namespace e.originalEvent.dataTransfer */
  17130. if (self.isDisabled || $h.isEmpty(e.originalEvent.dataTransfer.files)) {
  17131. return;
  17132. }
  17133. self._change(e, 'dragdrop');
  17134. self.$dropZone.removeClass('file-highlighted');
  17135. },
  17136. _uploadClick: function (e) {
  17137. var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
  17138. isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
  17139. if (e && e.isDefaultPrevented()) {
  17140. return;
  17141. }
  17142. if (!self.isUploadable) {
  17143. if (isEnabled && $btn.attr('type') !== 'submit') {
  17144. $form = $btn.closest('form');
  17145. // downgrade to normal form submit if possible
  17146. if ($form.length) {
  17147. $form.trigger('submit');
  17148. }
  17149. e.preventDefault();
  17150. }
  17151. return;
  17152. }
  17153. e.preventDefault();
  17154. if (isEnabled) {
  17155. self.upload();
  17156. }
  17157. },
  17158. _submitForm: function () {
  17159. var self = this;
  17160. return self._isFileSelectionValid() && !self._abort({});
  17161. },
  17162. _clearPreview: function () {
  17163. var self = this, $p = self.$preview,
  17164. $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
  17165. $thumbs.each(function () {
  17166. var $thumb = $(this);
  17167. $thumb.remove();
  17168. $h.cleanZoomCache($p.find('#zoom-' + $thumb.attr('id')));
  17169. });
  17170. if (!self.getFrames().length || !self.showPreview) {
  17171. self._resetUpload();
  17172. }
  17173. self._validateDefaultPreview();
  17174. },
  17175. _initSortable: function () {
  17176. var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS;
  17177. if (!window.KvSortable || $el.find(selector).length === 0) {
  17178. return;
  17179. }
  17180. //noinspection JSUnusedGlobalSymbols
  17181. settings = {
  17182. handle: '.drag-handle-init',
  17183. dataIdAttr: 'data-preview-id',
  17184. scroll: false,
  17185. draggable: selector,
  17186. onSort: function (e) {
  17187. var oldIndex = e.oldIndex, newIndex = e.newIndex, key, $frame;
  17188. self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex);
  17189. self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex);
  17190. self.previewCache.init();
  17191. for (var i = 0; i < self.initialPreviewConfig.length; i++) {
  17192. if (self.initialPreviewConfig[i] !== null) {
  17193. key = self.initialPreviewConfig[i].key;
  17194. $frame = $(".kv-file-remove[data-key='" + key + "']").closest($h.FRAMES);
  17195. $frame.attr('data-fileindex', 'init_' + i).attr('data-fileindex', 'init_' + i);
  17196. }
  17197. }
  17198. self._raise('filesorted', {
  17199. previewId: $(e.item).attr('id'),
  17200. 'oldIndex': oldIndex,
  17201. 'newIndex': newIndex,
  17202. stack: self.initialPreviewConfig
  17203. });
  17204. }
  17205. };
  17206. if ($el.data('kvsortable')) {
  17207. $el.kvsortable('destroy');
  17208. }
  17209. $.extend(true, settings, self.fileActionSettings.dragSettings);
  17210. $el.kvsortable(settings);
  17211. },
  17212. _initPreview: function (isInit) {
  17213. var self = this, cap = self.initialCaption || '', out;
  17214. if (!self.previewCache.count()) {
  17215. self._clearPreview();
  17216. if (isInit) {
  17217. self._setCaption(cap);
  17218. } else {
  17219. self._initCaption();
  17220. }
  17221. return;
  17222. }
  17223. out = self.previewCache.out();
  17224. cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
  17225. self.$preview.html(out.content);
  17226. self._setInitThumbAttr();
  17227. self._setCaption(cap);
  17228. self._initSortable();
  17229. if (!$h.isEmpty(out.content)) {
  17230. self.$container.removeClass('file-input-new');
  17231. }
  17232. },
  17233. _getZoomButton: function (type) {
  17234. var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
  17235. title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ',
  17236. params = title + (type === 'close' ? ' data-dismiss="modal" aria-hidden="true"' : '');
  17237. if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
  17238. params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
  17239. }
  17240. return '<button type="button" class="' + css + ' btn-' + type + '"' + params + '>' + label + '</button>';
  17241. },
  17242. _getModalContent: function () {
  17243. var self = this;
  17244. return self._getLayoutTemplate('modal').setTokens({
  17245. 'rtl': self.rtl ? ' kv-rtl' : '',
  17246. 'zoomFrameClass': self.frameClass,
  17247. 'heading': self.msgZoomModalHeading,
  17248. 'prev': self._getZoomButton('prev'),
  17249. 'next': self._getZoomButton('next'),
  17250. 'toggleheader': self._getZoomButton('toggleheader'),
  17251. 'fullscreen': self._getZoomButton('fullscreen'),
  17252. 'borderless': self._getZoomButton('borderless'),
  17253. 'close': self._getZoomButton('close')
  17254. });
  17255. },
  17256. _listenModalEvent: function (event) {
  17257. var self = this, $modal = self.$modal, getParams = function (e) {
  17258. return {
  17259. sourceEvent: e,
  17260. previewId: $modal.data('previewId'),
  17261. modal: $modal
  17262. };
  17263. };
  17264. $modal.on(event + '.bs.modal', function (e) {
  17265. var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
  17266. self._raise('filezoom' + event, getParams(e));
  17267. if (event === 'shown') {
  17268. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17269. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17270. if ($modal.hasClass('file-zoom-fullscreen')) {
  17271. self._maximizeZoomDialog();
  17272. if ($h.checkFullScreen()) {
  17273. $btnFull.addClass('active').attr('aria-pressed', 'true');
  17274. } else {
  17275. $btnBord.addClass('active').attr('aria-pressed', 'true');
  17276. }
  17277. }
  17278. }
  17279. });
  17280. },
  17281. _initZoom: function () {
  17282. var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
  17283. if (!self.showPreview) {
  17284. return;
  17285. }
  17286. self.$modal = $(modalId);
  17287. if (!self.$modal || !self.$modal.length) {
  17288. $dialog = $(document.createElement('div')).html(modalMain).insertAfter(self.$container);
  17289. self.$modal = $(modalId).insertBefore($dialog);
  17290. $dialog.remove();
  17291. }
  17292. $h.initModal(self.$modal);
  17293. self.$modal.html(self._getModalContent());
  17294. $.each($h.MODAL_EVENTS, function (key, event) {
  17295. self._listenModalEvent(event);
  17296. });
  17297. },
  17298. _initZoomButtons: function () {
  17299. var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
  17300. thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-prev'),
  17301. $next = self.$modal.find('.btn-next');
  17302. if (thumbs.length < 2) {
  17303. $prev.hide();
  17304. $next.hide();
  17305. return;
  17306. } else {
  17307. $prev.show();
  17308. $next.show();
  17309. }
  17310. if (!len) {
  17311. return;
  17312. }
  17313. $first = $(thumbs[0]);
  17314. $last = $(thumbs[len - 1]);
  17315. $prev.removeAttr('disabled');
  17316. $next.removeAttr('disabled');
  17317. if ($first.length && $first.attr('id') === previewId) {
  17318. $prev.attr('disabled', true);
  17319. }
  17320. if ($last.length && $last.attr('id') === previewId) {
  17321. $next.attr('disabled', true);
  17322. }
  17323. },
  17324. _maximizeZoomDialog: function () {
  17325. var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
  17326. $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.modal-body'),
  17327. h = $(window).height(), diff = 0;
  17328. $modal.addClass('file-zoom-fullscreen');
  17329. if ($head && $head.length) {
  17330. h -= $head.outerHeight(true);
  17331. }
  17332. if ($foot && $foot.length) {
  17333. h -= $foot.outerHeight(true);
  17334. }
  17335. if ($body && $body.length) {
  17336. diff = $body.outerHeight(true) - $body.height();
  17337. h -= diff;
  17338. }
  17339. $modal.find('.kv-zoom-body').height(h);
  17340. },
  17341. _resizeZoomDialog: function (fullScreen) {
  17342. var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-fullscreen'),
  17343. $btnBord = $modal.find('.btn-borderless');
  17344. if ($modal.hasClass('file-zoom-fullscreen')) {
  17345. $h.toggleFullScreen(false);
  17346. if (!fullScreen) {
  17347. if (!$btnFull.hasClass('active')) {
  17348. $modal.removeClass('file-zoom-fullscreen');
  17349. self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
  17350. } else {
  17351. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  17352. }
  17353. } else {
  17354. if (!$btnFull.hasClass('active')) {
  17355. $modal.removeClass('file-zoom-fullscreen');
  17356. self._resizeZoomDialog(true);
  17357. if ($btnBord.hasClass('active')) {
  17358. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  17359. }
  17360. }
  17361. }
  17362. } else {
  17363. if (!fullScreen) {
  17364. self._maximizeZoomDialog();
  17365. return;
  17366. }
  17367. $h.toggleFullScreen(true);
  17368. }
  17369. $modal.focus();
  17370. },
  17371. _setZoomContent: function ($frame, animate) {
  17372. var self = this, $content, tmplt, body, title, $body, $dataEl, config, pid = $frame.attr('id'),
  17373. $modal = self.$modal, $prev = $modal.find('.btn-prev'), $next = $modal.find('.btn-next'), $tmp,
  17374. $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless'), cap, size,
  17375. $btnTogh = $modal.find('.btn-toggleheader'), $zoomPreview = self.$preview.find('#zoom-' + pid);
  17376. tmplt = $zoomPreview.attr('data-template') || 'generic';
  17377. $content = $zoomPreview.find('.kv-file-content');
  17378. body = $content.length ? $content.html() : '';
  17379. cap = $frame.data('caption') || '';
  17380. size = $frame.data('size') || '';
  17381. title = cap + ' ' + size;
  17382. $modal.find('.kv-zoom-title').html(title);
  17383. $body = $modal.find('.kv-zoom-body');
  17384. $modal.removeClass('kv-single-content');
  17385. if (animate) {
  17386. $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
  17387. $body.html(body).hide();
  17388. $tmp.fadeOut('fast', function () {
  17389. $body.fadeIn('fast', function () {
  17390. $body.removeClass('file-thumb-loading');
  17391. });
  17392. $tmp.remove();
  17393. });
  17394. } else {
  17395. $body.html(body);
  17396. }
  17397. config = self.previewZoomSettings[tmplt];
  17398. if (config) {
  17399. $dataEl = $body.find('.kv-preview-data');
  17400. $h.addCss($dataEl, 'file-zoom-detail');
  17401. $.each(config, function (key, value) {
  17402. $dataEl.css(key, value);
  17403. if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
  17404. $dataEl.removeAttr(key);
  17405. }
  17406. });
  17407. }
  17408. $modal.data('previewId', pid);
  17409. var $img = $body.find('img');
  17410. if ($img.length) {
  17411. $h.adjustOrientedImage($img, true);
  17412. }
  17413. self._handler($prev, 'click', function () {
  17414. self._zoomSlideShow('prev', pid);
  17415. });
  17416. self._handler($next, 'click', function () {
  17417. self._zoomSlideShow('next', pid);
  17418. });
  17419. self._handler($btnFull, 'click', function () {
  17420. self._resizeZoomDialog(true);
  17421. });
  17422. self._handler($btnBord, 'click', function () {
  17423. self._resizeZoomDialog(false);
  17424. });
  17425. self._handler($btnTogh, 'click', function () {
  17426. var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.modal-body .floating-buttons'),
  17427. ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
  17428. var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
  17429. if ($modal.hasClass('file-zoom-fullscreen')) {
  17430. h = $body.outerHeight(true);
  17431. if (!height) {
  17432. h = h - $header.outerHeight(true);
  17433. }
  17434. }
  17435. $body.css('height', height ? h + height : h);
  17436. };
  17437. if ($header.is(':visible')) {
  17438. ht = $header.outerHeight(true);
  17439. $header.slideUp('slow', function () {
  17440. $actions.find('.btn').appendTo($floatBar);
  17441. resize(ht);
  17442. });
  17443. } else {
  17444. $floatBar.find('.btn').appendTo($actions);
  17445. $header.slideDown('slow', function () {
  17446. resize();
  17447. });
  17448. }
  17449. $modal.focus();
  17450. });
  17451. self._handler($modal, 'keydown', function (e) {
  17452. var key = e.which || e.keyCode;
  17453. if (key === 37 && !$prev.attr('disabled')) {
  17454. self._zoomSlideShow('prev', pid);
  17455. }
  17456. if (key === 39 && !$next.attr('disabled')) {
  17457. self._zoomSlideShow('next', pid);
  17458. }
  17459. });
  17460. },
  17461. _zoomPreview: function ($btn) {
  17462. var self = this, $frame, $modal = self.$modal;
  17463. if (!$btn.length) {
  17464. throw 'Cannot zoom to detailed preview!';
  17465. }
  17466. $h.initModal($modal);
  17467. $modal.html(self._getModalContent());
  17468. $frame = $btn.closest($h.FRAMES);
  17469. self._setZoomContent($frame);
  17470. $modal.modal('show');
  17471. self._initZoomButtons();
  17472. },
  17473. _zoomSlideShow: function (dir, previewId) {
  17474. var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-' + dir), $targFrame, i,
  17475. thumbs = self.getFrames().toArray(), len = thumbs.length, out;
  17476. if ($btn.attr('disabled')) {
  17477. return;
  17478. }
  17479. for (i = 0; i < len; i++) {
  17480. if ($(thumbs[i]).attr('id') === previewId) {
  17481. out = dir === 'prev' ? i - 1 : i + 1;
  17482. break;
  17483. }
  17484. }
  17485. if (out < 0 || out >= len || !thumbs[out]) {
  17486. return;
  17487. }
  17488. $targFrame = $(thumbs[out]);
  17489. if ($targFrame.length) {
  17490. self._setZoomContent($targFrame, true);
  17491. }
  17492. self._initZoomButtons();
  17493. self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
  17494. },
  17495. _initZoomButton: function () {
  17496. var self = this;
  17497. self.$preview.find('.kv-file-zoom').each(function () {
  17498. var $el = $(this);
  17499. self._handler($el, 'click', function () {
  17500. self._zoomPreview($el);
  17501. });
  17502. });
  17503. },
  17504. _clearObjects: function ($el) {
  17505. $el.find('video audio').each(function () {
  17506. this.pause();
  17507. $(this).remove();
  17508. });
  17509. $el.find('img object div').each(function () {
  17510. $(this).remove();
  17511. });
  17512. },
  17513. _clearFileInput: function () {
  17514. var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
  17515. self.fileInputCleared = true;
  17516. if ($h.isEmpty($el.val())) {
  17517. return;
  17518. }
  17519. // Fix for IE ver < 11, that does not clear file inputs. Requires a sequence of steps to prevent IE
  17520. // crashing but still allow clearing of the file input.
  17521. if (self.isIE9 || self.isIE10) {
  17522. $srcFrm = $el.closest('form');
  17523. $tmpFrm = $(document.createElement('form'));
  17524. $tmpEl = $(document.createElement('div'));
  17525. $el.before($tmpEl);
  17526. if ($srcFrm.length) {
  17527. $srcFrm.after($tmpFrm);
  17528. } else {
  17529. $tmpEl.after($tmpFrm);
  17530. }
  17531. $tmpFrm.append($el).trigger('reset');
  17532. $tmpEl.before($el).remove();
  17533. $tmpFrm.remove();
  17534. } else { // normal input clear behavior for other sane browsers
  17535. $el.val('');
  17536. }
  17537. },
  17538. _resetUpload: function () {
  17539. var self = this;
  17540. self.uploadCache = {content: [], config: [], tags: [], append: true};
  17541. self.uploadCount = 0;
  17542. self.uploadStatus = {};
  17543. self.uploadLog = [];
  17544. self.uploadAsyncCount = 0;
  17545. self.loadedImages = [];
  17546. self.totalImagesCount = 0;
  17547. self.$btnUpload.removeAttr('disabled');
  17548. self._setProgress(0);
  17549. $h.addCss(self.$progress, 'hide');
  17550. self._resetErrors(false);
  17551. self.ajaxAborted = false;
  17552. self.ajaxRequests = [];
  17553. self._resetCanvas();
  17554. self.cacheInitialPreview = {};
  17555. if (self.overwriteInitial) {
  17556. self.initialPreview = [];
  17557. self.initialPreviewConfig = [];
  17558. self.initialPreviewThumbTags = [];
  17559. self.previewCache.data = {
  17560. content: [],
  17561. config: [],
  17562. tags: []
  17563. };
  17564. }
  17565. },
  17566. _resetCanvas: function () {
  17567. var self = this;
  17568. if (self.canvas && self.imageCanvasContext) {
  17569. self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
  17570. }
  17571. },
  17572. _hasInitialPreview: function () {
  17573. var self = this;
  17574. return !self.overwriteInitial && self.previewCache.count();
  17575. },
  17576. _resetPreview: function () {
  17577. var self = this, out, cap;
  17578. if (self.previewCache.count()) {
  17579. out = self.previewCache.out();
  17580. self.$preview.html(out.content);
  17581. self._setInitThumbAttr();
  17582. cap = self.initialCaption ? self.initialCaption : out.caption;
  17583. self._setCaption(cap);
  17584. } else {
  17585. self._clearPreview();
  17586. self._initCaption();
  17587. }
  17588. if (self.showPreview) {
  17589. self._initZoom();
  17590. self._initSortable();
  17591. }
  17592. },
  17593. _clearDefaultPreview: function () {
  17594. var self = this;
  17595. self.$preview.find('.file-default-preview').remove();
  17596. },
  17597. _validateDefaultPreview: function () {
  17598. var self = this;
  17599. if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
  17600. return;
  17601. }
  17602. self.$preview.html('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
  17603. self.$container.removeClass('file-input-new');
  17604. self._initClickable();
  17605. },
  17606. _resetPreviewThumbs: function (isAjax) {
  17607. var self = this, out;
  17608. if (isAjax) {
  17609. self._clearPreview();
  17610. self.clearStack();
  17611. return;
  17612. }
  17613. if (self._hasInitialPreview()) {
  17614. out = self.previewCache.out();
  17615. self.$preview.html(out.content);
  17616. self._setInitThumbAttr();
  17617. self._setCaption(out.caption);
  17618. self._initPreviewActions();
  17619. } else {
  17620. self._clearPreview();
  17621. }
  17622. },
  17623. _getLayoutTemplate: function (t) {
  17624. var self = this, template = self.layoutTemplates[t];
  17625. if ($h.isEmpty(self.customLayoutTags)) {
  17626. return template;
  17627. }
  17628. return $h.replaceTags(template, self.customLayoutTags);
  17629. },
  17630. _getPreviewTemplate: function (t) {
  17631. var self = this, template = self.previewTemplates[t];
  17632. if ($h.isEmpty(self.customPreviewTags)) {
  17633. return template;
  17634. }
  17635. return $h.replaceTags(template, self.customPreviewTags);
  17636. },
  17637. _getOutData: function (jqXHR, responseData, filesData) {
  17638. var self = this;
  17639. jqXHR = jqXHR || {};
  17640. responseData = responseData || {};
  17641. filesData = filesData || self.filestack.slice(0) || {};
  17642. return {
  17643. form: self.formdata,
  17644. files: filesData,
  17645. filenames: self.filenames,
  17646. filescount: self.getFilesCount(),
  17647. extra: self._getExtraData(),
  17648. response: responseData,
  17649. reader: self.reader,
  17650. jqXHR: jqXHR
  17651. };
  17652. },
  17653. _getMsgSelected: function (n) {
  17654. var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
  17655. return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) : self.msgNoFilesSelected;
  17656. },
  17657. _getFrame: function (id) {
  17658. var self = this, $frame = $('#' + id);
  17659. if (!$frame.length) {
  17660. self._log('Invalid thumb frame with id: "' + id + '".');
  17661. return null;
  17662. }
  17663. return $frame;
  17664. },
  17665. _getThumbs: function (css) {
  17666. css = css || '';
  17667. return this.getFrames(':not(.file-preview-initial)' + css);
  17668. },
  17669. _getExtraData: function (previewId, index) {
  17670. var self = this, data = self.uploadExtraData;
  17671. if (typeof self.uploadExtraData === "function") {
  17672. data = self.uploadExtraData(previewId, index);
  17673. }
  17674. return data;
  17675. },
  17676. _initXhr: function (xhrobj, previewId, fileCount) {
  17677. var self = this;
  17678. if (xhrobj.upload) {
  17679. xhrobj.upload.addEventListener('progress', function (event) {
  17680. var pct = 0, total = event.total, position = event.loaded || event.position;
  17681. /** @namespace event.lengthComputable */
  17682. if (event.lengthComputable) {
  17683. pct = Math.floor(position / total * 100);
  17684. }
  17685. if (previewId) {
  17686. self._setAsyncUploadStatus(previewId, pct, fileCount);
  17687. } else {
  17688. self._setProgress(pct);
  17689. }
  17690. }, false);
  17691. }
  17692. return xhrobj;
  17693. },
  17694. _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
  17695. var self = this, settings;
  17696. if (!self._raise('filepreajax', [previewId, index])) {
  17697. return;
  17698. }
  17699. self._uploadExtra(previewId, index);
  17700. settings = $.extend(true, {}, {
  17701. xhr: function () {
  17702. var xhrobj = $.ajaxSettings.xhr();
  17703. return self._initXhr(xhrobj, previewId, self.getFileStack().length);
  17704. },
  17705. url: self.uploadUrl,
  17706. type: 'POST',
  17707. dataType: 'json',
  17708. data: self.formdata,
  17709. cache: false,
  17710. processData: false,
  17711. contentType: false,
  17712. beforeSend: fnBefore,
  17713. success: fnSuccess,
  17714. complete: fnComplete,
  17715. error: fnError
  17716. }, self.ajaxSettings);
  17717. self.ajaxRequests.push($.ajax(settings));
  17718. },
  17719. _mergeArray: function (prop, content) {
  17720. var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
  17721. self[prop] = arr1.concat(arr2);
  17722. },
  17723. _initUploadSuccess: function (out, $thumb, allFiles) {
  17724. var self = this, append, data, index, $div, $newCache, content, config, tags, i;
  17725. if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
  17726. return;
  17727. }
  17728. if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
  17729. self.hasInitData = true;
  17730. content = out.initialPreview || [];
  17731. config = out.initialPreviewConfig || [];
  17732. tags = out.initialPreviewThumbTags || [];
  17733. append = out.append === undefined || out.append ? true : false;
  17734. if (content.length > 0 && !$h.isArray(content)) {
  17735. content = content.split(self.initialPreviewDelimiter);
  17736. }
  17737. self._mergeArray('initialPreview', content);
  17738. self._mergeArray('initialPreviewConfig', config);
  17739. self._mergeArray('initialPreviewThumbTags', tags);
  17740. if ($thumb !== undefined) {
  17741. if (!allFiles) {
  17742. index = self.previewCache.add(content, config[0], tags[0], append);
  17743. data = self.previewCache.get(index, false);
  17744. $div = $(document.createElement('div')).html(data).hide().insertAfter($thumb);
  17745. $newCache = $div.find('.kv-zoom-cache');
  17746. if ($newCache && $newCache.length) {
  17747. $newCache.insertAfter($thumb);
  17748. }
  17749. $thumb.fadeOut('slow', function () {
  17750. var $newThumb = $div.find('.file-preview-frame');
  17751. if ($newThumb && $newThumb.length) {
  17752. $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
  17753. }
  17754. self._initPreviewActions();
  17755. self._clearFileInput();
  17756. $h.cleanZoomCache(self.$preview.find('#zoom-' + $thumb.attr('id')));
  17757. $thumb.remove();
  17758. $div.remove();
  17759. self._initSortable();
  17760. });
  17761. } else {
  17762. i = $thumb.attr('data-fileindex');
  17763. self.uploadCache.content[i] = content[0];
  17764. self.uploadCache.config[i] = config[0] || [];
  17765. self.uploadCache.tags[i] = tags[0] || [];
  17766. self.uploadCache.append = append;
  17767. }
  17768. } else {
  17769. self.previewCache.set(content, config, tags, append);
  17770. self._initPreview();
  17771. self._initPreviewActions();
  17772. }
  17773. }
  17774. },
  17775. _initSuccessThumbs: function () {
  17776. var self = this;
  17777. if (!self.showPreview) {
  17778. return;
  17779. }
  17780. self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
  17781. var $thumb = $(this), $preview = self.$preview, $remove = $thumb.find('.kv-file-remove');
  17782. $remove.removeAttr('disabled');
  17783. self._handler($remove, 'click', function () {
  17784. var id = $thumb.attr('id'),
  17785. out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
  17786. $h.cleanMemory($thumb);
  17787. if (out === false) {
  17788. return;
  17789. }
  17790. $thumb.fadeOut('slow', function () {
  17791. $h.cleanZoomCache($preview.find('#zoom-' + id));
  17792. $thumb.remove();
  17793. if (!self.getFrames().length) {
  17794. self.reset();
  17795. }
  17796. });
  17797. });
  17798. });
  17799. },
  17800. _checkAsyncComplete: function () {
  17801. var self = this, previewId, i;
  17802. for (i = 0; i < self.filestack.length; i++) {
  17803. if (self.filestack[i]) {
  17804. previewId = self.previewInitId + "-" + i;
  17805. if ($.inArray(previewId, self.uploadLog) === -1) {
  17806. return false;
  17807. }
  17808. }
  17809. }
  17810. return (self.uploadAsyncCount === self.uploadLog.length);
  17811. },
  17812. _uploadExtra: function (previewId, index) {
  17813. var self = this, data = self._getExtraData(previewId, index);
  17814. if (data.length === 0) {
  17815. return;
  17816. }
  17817. $.each(data, function (key, value) {
  17818. self.formdata.append(key, value);
  17819. });
  17820. },
  17821. _uploadSingle: function (i, files, allFiles) {
  17822. var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
  17823. previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
  17824. hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  17825. $prog = $('#' + previewId).find('.file-thumb-progress'),
  17826. fnBefore, fnSuccess, fnComplete, fnError, updateUploadLog, params = {id: previewId, index: i},
  17827. uploadFailed, multiUploadMode = !$h.isEmpty(self.$element.attr('multiple'));
  17828. self.formdata = formdata;
  17829. if (self.showPreview) {
  17830. $thumb = $('#' + previewId + ':not(.file-preview-initial)');
  17831. $btnUpload = $thumb.find('.kv-file-upload');
  17832. $btnDelete = $thumb.find('.kv-file-remove');
  17833. $prog.removeClass('hide');
  17834. }
  17835. if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self._abort(params)) {
  17836. return;
  17837. }
  17838. updateUploadLog = function (i, previewId) {
  17839. if (multiUploadMode || !uploadFailed) {
  17840. self.updateStack(i, undefined);
  17841. }
  17842. self.uploadLog.push(previewId);
  17843. if (self._checkAsyncComplete()) {
  17844. self.fileBatchCompleted = true;
  17845. }
  17846. };
  17847. chkComplete = function () {
  17848. var u = self.uploadCache, $initThumbs, i, j, len = 0, data = self.cacheInitialPreview;
  17849. if (!self.fileBatchCompleted) {
  17850. return;
  17851. }
  17852. if (data && data.content) {
  17853. len = data.content.length;
  17854. }
  17855. setTimeout(function () {
  17856. var triggerReset = multiUploadMode || !uploadFailed;
  17857. if (self.showPreview) {
  17858. self.previewCache.set(u.content, u.config, u.tags, u.append);
  17859. if (len) {
  17860. for (i = 0; i < u.content.length; i++) {
  17861. j = i + len;
  17862. data.content[j] = u.content[i];
  17863. //noinspection JSUnresolvedVariable
  17864. if (data.config.length) {
  17865. data.config[j] = u.config[i];
  17866. }
  17867. if (data.tags.length) {
  17868. data.tags[j] = u.tags[i];
  17869. }
  17870. }
  17871. self.initialPreview = $h.cleanArray(data.content);
  17872. self.initialPreviewConfig = $h.cleanArray(data.config);
  17873. self.initialPreviewThumbTags = $h.cleanArray(data.tags);
  17874. } else {
  17875. self.initialPreview = u.content;
  17876. self.initialPreviewConfig = u.config;
  17877. self.initialPreviewThumbTags = u.tags;
  17878. }
  17879. self.cacheInitialPreview = {};
  17880. if (self.hasInitData) {
  17881. self._initPreview();
  17882. self._initPreviewActions();
  17883. }
  17884. }
  17885. self.unlock(triggerReset);
  17886. if (triggerReset) {
  17887. self._clearFileInput();
  17888. }
  17889. $initThumbs = self.$preview.find('.file-preview-initial');
  17890. if (self.uploadAsync && $initThumbs.length) {
  17891. $h.addCss($initThumbs, $h.SORT_CSS);
  17892. self._initSortable();
  17893. }
  17894. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  17895. self.uploadCount = 0;
  17896. self.uploadStatus = {};
  17897. self.uploadLog = [];
  17898. self._setProgress(101);
  17899. }, 100);
  17900. };
  17901. fnBefore = function (jqXHR) {
  17902. outData = self._getOutData(jqXHR);
  17903. self.fileBatchCompleted = false;
  17904. if (self.showPreview) {
  17905. if (!$thumb.hasClass('file-preview-success')) {
  17906. self._setThumbStatus($thumb, 'Loading');
  17907. $h.addCss($thumb, 'file-uploading');
  17908. }
  17909. $btnUpload.attr('disabled', true);
  17910. $btnDelete.attr('disabled', true);
  17911. }
  17912. if (!allFiles) {
  17913. self.lock();
  17914. }
  17915. self._raise('filepreupload', [outData, previewId, i]);
  17916. $.extend(true, params, outData);
  17917. if (self._abort(params)) {
  17918. jqXHR.abort();
  17919. self._setProgressCancelled();
  17920. }
  17921. };
  17922. fnSuccess = function (data, textStatus, jqXHR) {
  17923. var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
  17924. outData = self._getOutData(jqXHR, data);
  17925. $.extend(true, params, outData);
  17926. setTimeout(function () {
  17927. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  17928. if (self.showPreview) {
  17929. self._setThumbStatus($thumb, 'Success');
  17930. $btnUpload.hide();
  17931. self._initUploadSuccess(data, $thumb, allFiles);
  17932. self._setProgress(101, $prog);
  17933. }
  17934. self._raise('fileuploaded', [outData, pid, i]);
  17935. if (!allFiles) {
  17936. self.updateStack(i, undefined);
  17937. } else {
  17938. updateUploadLog(i, pid);
  17939. }
  17940. } else {
  17941. uploadFailed = true;
  17942. self._showUploadError(data.error, params);
  17943. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  17944. if (allFiles) {
  17945. updateUploadLog(i, pid);
  17946. }
  17947. }
  17948. }, 100);
  17949. };
  17950. fnComplete = function () {
  17951. setTimeout(function () {
  17952. if (self.showPreview) {
  17953. $btnUpload.removeAttr('disabled');
  17954. $btnDelete.removeAttr('disabled');
  17955. $thumb.removeClass('file-uploading');
  17956. }
  17957. if (!allFiles) {
  17958. self.unlock(false);
  17959. self._clearFileInput();
  17960. } else {
  17961. chkComplete();
  17962. }
  17963. self._initSuccessThumbs();
  17964. }, 100);
  17965. };
  17966. fnError = function (jqXHR, textStatus, errorThrown) {
  17967. var op = self.ajaxOperations.uploadThumb,
  17968. errMsg = self._parseError(op, jqXHR, errorThrown, (allFiles ? files[i].name : null));
  17969. uploadFailed = true;
  17970. setTimeout(function () {
  17971. if (allFiles) {
  17972. updateUploadLog(i, previewId);
  17973. }
  17974. self.uploadStatus[previewId] = 100;
  17975. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  17976. $.extend(true, params, self._getOutData(jqXHR));
  17977. self._setProgress(101, $prog, self.msgAjaxProgressError.replace('{operation}', op));
  17978. self._showUploadError(errMsg, params);
  17979. }, 100);
  17980. };
  17981. formdata.append(self.uploadFileAttr, files[i], self.filenames[i]);
  17982. formdata.append('file_id', i);
  17983. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
  17984. },
  17985. _uploadBatch: function () {
  17986. var self = this, files = self.filestack, total = files.length, params = {}, fnBefore, fnSuccess, fnError,
  17987. fnComplete, hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  17988. setAllUploaded;
  17989. self.formdata = new FormData();
  17990. if (total === 0 || !hasPostData || self._abort(params)) {
  17991. return;
  17992. }
  17993. setAllUploaded = function () {
  17994. $.each(files, function (key) {
  17995. self.updateStack(key, undefined);
  17996. });
  17997. self._clearFileInput();
  17998. };
  17999. fnBefore = function (jqXHR) {
  18000. self.lock();
  18001. var outData = self._getOutData(jqXHR);
  18002. if (self.showPreview) {
  18003. self._getThumbs().each(function () {
  18004. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
  18005. $btnDelete = $thumb.find('.kv-file-remove');
  18006. if (!$thumb.hasClass('file-preview-success')) {
  18007. self._setThumbStatus($thumb, 'Loading');
  18008. $h.addCss($thumb, 'file-uploading');
  18009. }
  18010. $btnUpload.attr('disabled', true);
  18011. $btnDelete.attr('disabled', true);
  18012. });
  18013. }
  18014. self._raise('filebatchpreupload', [outData]);
  18015. if (self._abort(outData)) {
  18016. jqXHR.abort();
  18017. self._setProgressCancelled();
  18018. }
  18019. };
  18020. fnSuccess = function (data, textStatus, jqXHR) {
  18021. /** @namespace data.errorkeys */
  18022. var outData = self._getOutData(jqXHR, data), $thumbs = self._getThumbs(':not(.file-preview-error)'),
  18023. key = 0,
  18024. keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
  18025. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18026. self._raise('filebatchuploadsuccess', [outData]);
  18027. setAllUploaded();
  18028. if (self.showPreview) {
  18029. $thumbs.each(function () {
  18030. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload');
  18031. $thumb.find('.kv-file-upload').hide();
  18032. self._setThumbStatus($thumb, 'Success');
  18033. $thumb.removeClass('file-uploading');
  18034. $btnUpload.removeAttr('disabled');
  18035. });
  18036. self._initUploadSuccess(data);
  18037. } else {
  18038. self.reset();
  18039. }
  18040. self._setProgress(101);
  18041. } else {
  18042. if (self.showPreview) {
  18043. $thumbs.each(function () {
  18044. var $thumb = $(this), $btnDelete = $thumb.find('.kv-file-remove'),
  18045. $btnUpload = $thumb.find('.kv-file-upload');
  18046. $thumb.removeClass('file-uploading');
  18047. $btnUpload.removeAttr('disabled');
  18048. $btnDelete.removeAttr('disabled');
  18049. if (keys.length === 0) {
  18050. self._setPreviewError($thumb);
  18051. return;
  18052. }
  18053. if ($.inArray(key, keys) !== -1) {
  18054. self._setPreviewError($thumb);
  18055. } else {
  18056. $thumb.find('.kv-file-upload').hide();
  18057. self._setThumbStatus($thumb, 'Success');
  18058. self.updateStack(key, undefined);
  18059. }
  18060. key++;
  18061. });
  18062. self._initUploadSuccess(data);
  18063. }
  18064. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  18065. }
  18066. };
  18067. fnComplete = function () {
  18068. self.unlock();
  18069. self._initSuccessThumbs();
  18070. self._clearFileInput();
  18071. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  18072. };
  18073. fnError = function (jqXHR, textStatus, errorThrown) {
  18074. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadBatch,
  18075. errMsg = self._parseError(op, jqXHR, errorThrown);
  18076. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  18077. self.uploadFileCount = total - 1;
  18078. if (!self.showPreview) {
  18079. return;
  18080. }
  18081. self._getThumbs().each(function () {
  18082. var $thumb = $(this), key = $thumb.attr('data-fileindex');
  18083. $thumb.removeClass('file-uploading');
  18084. if (self.filestack[key] !== undefined) {
  18085. self._setPreviewError($thumb);
  18086. }
  18087. });
  18088. self._getThumbs().removeClass('file-uploading');
  18089. self._getThumbs(' .kv-file-upload').removeAttr('disabled');
  18090. self._getThumbs(' .kv-file-delete').removeAttr('disabled');
  18091. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  18092. };
  18093. $.each(files, function (key, data) {
  18094. if (!$h.isEmpty(files[key])) {
  18095. self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
  18096. }
  18097. });
  18098. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  18099. },
  18100. _uploadExtraOnly: function () {
  18101. var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
  18102. self.formdata = new FormData();
  18103. if (self._abort(params)) {
  18104. return;
  18105. }
  18106. fnBefore = function (jqXHR) {
  18107. self.lock();
  18108. var outData = self._getOutData(jqXHR);
  18109. self._raise('filebatchpreupload', [outData]);
  18110. self._setProgress(50);
  18111. params.data = outData;
  18112. params.xhr = jqXHR;
  18113. if (self._abort(params)) {
  18114. jqXHR.abort();
  18115. self._setProgressCancelled();
  18116. }
  18117. };
  18118. fnSuccess = function (data, textStatus, jqXHR) {
  18119. var outData = self._getOutData(jqXHR, data);
  18120. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18121. self._raise('filebatchuploadsuccess', [outData]);
  18122. self._clearFileInput();
  18123. self._initUploadSuccess(data);
  18124. self._setProgress(101);
  18125. } else {
  18126. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  18127. }
  18128. };
  18129. fnComplete = function () {
  18130. self.unlock();
  18131. self._clearFileInput();
  18132. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  18133. };
  18134. fnError = function (jqXHR, textStatus, errorThrown) {
  18135. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadExtra,
  18136. errMsg = self._parseError(op, jqXHR, errorThrown);
  18137. params.data = outData;
  18138. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  18139. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  18140. };
  18141. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  18142. },
  18143. _deleteFileIndex: function ($frame) {
  18144. var self = this, ind = $frame.attr('data-fileindex');
  18145. if (ind.substring(0, 5) === 'init_') {
  18146. ind = parseInt(ind.replace('init_', ''));
  18147. self.initialPreview = $h.spliceArray(self.initialPreview, ind);
  18148. self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind);
  18149. self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind);
  18150. self.getFrames().each(function () {
  18151. var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
  18152. if (nInd.substring(0, 5) === 'init_') {
  18153. nInd = parseInt(nInd.replace('init_', ''));
  18154. if (nInd > ind) {
  18155. nInd--;
  18156. $nFrame.attr('data-fileindex', 'init_' + nInd);
  18157. }
  18158. }
  18159. });
  18160. if (self.uploadAsync) {
  18161. self.cacheInitialPreview = self.getPreview();
  18162. }
  18163. }
  18164. },
  18165. _initFileActions: function () {
  18166. var self = this, $preview = self.$preview;
  18167. if (!self.showPreview) {
  18168. return;
  18169. }
  18170. self._initZoomButton();
  18171. self.getFrames(' .kv-file-remove').each(function () {
  18172. var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
  18173. ind = $frame.attr('data-fileindex'), n, cap, status;
  18174. self._handler($el, 'click', function () {
  18175. status = self._raise('filepreremove', [id, ind]);
  18176. if (status === false || !self._validateMinCount()) {
  18177. return false;
  18178. }
  18179. hasError = $frame.hasClass('file-preview-error');
  18180. $h.cleanMemory($frame);
  18181. $frame.fadeOut('slow', function () {
  18182. $h.cleanZoomCache($preview.find('#zoom-' + id));
  18183. self.updateStack(ind, undefined);
  18184. self._clearObjects($frame);
  18185. $frame.remove();
  18186. if (id && hasError) {
  18187. self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
  18188. $(this).remove();
  18189. if (!self._errorsExist()) {
  18190. self._resetErrors();
  18191. }
  18192. });
  18193. }
  18194. self._clearFileInput();
  18195. var filestack = self.getFileStack(true), chk = self.previewCache.count(),
  18196. len = filestack.length, hasThumb = self.showPreview && self.getFrames().length;
  18197. if (len === 0 && chk === 0 && !hasThumb) {
  18198. self.reset();
  18199. } else {
  18200. n = chk + len;
  18201. cap = n > 1 ? self._getMsgSelected(n) : (filestack[0] ? self._getFileNames()[0] : '');
  18202. self._setCaption(cap);
  18203. }
  18204. self._raise('fileremoved', [id, ind]);
  18205. });
  18206. });
  18207. });
  18208. self.getFrames(' .kv-file-upload').each(function () {
  18209. var $el = $(this);
  18210. self._handler($el, 'click', function () {
  18211. var $frame = $el.closest($h.FRAMES), ind = $frame.attr('data-fileindex');
  18212. if (!$frame.hasClass('file-preview-error')) {
  18213. self._uploadSingle(ind, self.filestack, false);
  18214. }
  18215. });
  18216. });
  18217. },
  18218. _initPreviewActions: function () {
  18219. var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
  18220. btnRemove = $h.FRAMES + ' .kv-file-remove',
  18221. resetProgress = function () {
  18222. var hasFiles = self.isUploadable ? self.previewCache.count() : self.$element.get(0).files.length;
  18223. if ($preview.find(btnRemove).length === 0 && !hasFiles) {
  18224. self.reset();
  18225. self.initialCaption = '';
  18226. }
  18227. };
  18228. self._initZoomButton();
  18229. $preview.find(btnRemove).each(function () {
  18230. var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
  18231. if ($h.isEmpty(vUrl) || vKey === undefined) {
  18232. return;
  18233. }
  18234. var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data,
  18235. settings, params, index = $frame.attr('data-fileindex'), config, extraData;
  18236. index = parseInt(index.replace('init_', ''));
  18237. config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
  18238. extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
  18239. if (typeof extraData === "function") {
  18240. extraData = extraData();
  18241. }
  18242. params = {id: $el.attr('id'), key: vKey, extra: extraData};
  18243. settings = $.extend(true, {}, {
  18244. url: vUrl,
  18245. type: 'POST',
  18246. dataType: 'json',
  18247. data: $.extend(true, {}, {key: vKey}, extraData),
  18248. beforeSend: function (jqXHR) {
  18249. self.ajaxAborted = false;
  18250. self._raise('filepredelete', [vKey, jqXHR, extraData]);
  18251. if (self.ajaxAborted) {
  18252. jqXHR.abort();
  18253. } else {
  18254. $h.addCss($frame, 'file-uploading');
  18255. $h.addCss($el, 'disabled');
  18256. }
  18257. },
  18258. success: function (data, textStatus, jqXHR) {
  18259. var n, cap;
  18260. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  18261. index = parseInt(($frame.attr('data-fileindex')).replace('init_', ''));
  18262. self.previewCache.unset(index);
  18263. n = self.previewCache.count();
  18264. cap = n > 0 ? self._getMsgSelected(n) : '';
  18265. self._deleteFileIndex($frame);
  18266. self._setCaption(cap);
  18267. self._raise('filedeleted', [vKey, jqXHR, extraData]);
  18268. } else {
  18269. params.jqXHR = jqXHR;
  18270. params.response = data;
  18271. self._showError(data.error, params, 'filedeleteerror');
  18272. $frame.removeClass('file-uploading');
  18273. $el.removeClass('disabled');
  18274. resetProgress();
  18275. return;
  18276. }
  18277. $frame.removeClass('file-uploading').addClass('file-deleted');
  18278. $frame.fadeOut('slow', function () {
  18279. $h.cleanZoomCache($preview.find('#zoom-' + $frame.attr('id')));
  18280. self._clearObjects($frame);
  18281. $frame.remove();
  18282. resetProgress();
  18283. if (!n && self.getFileStack().length === 0) {
  18284. self._setCaption('');
  18285. self.reset();
  18286. }
  18287. });
  18288. },
  18289. error: function (jqXHR, textStatus, errorThrown) {
  18290. var op = self.ajaxOperations.deleteThumb, errMsg = self._parseError(op, jqXHR, errorThrown);
  18291. params.jqXHR = jqXHR;
  18292. params.response = {};
  18293. self._showError(errMsg, params, 'filedeleteerror');
  18294. $frame.removeClass('file-uploading');
  18295. resetProgress();
  18296. }
  18297. }, self.ajaxDeleteSettings);
  18298. self._handler($el, 'click', function () {
  18299. if (!self._validateMinCount()) {
  18300. return false;
  18301. }
  18302. $.ajax(settings);
  18303. });
  18304. });
  18305. },
  18306. _hideFileIcon: function () {
  18307. if (this.overwriteInitial) {
  18308. this.$captionContainer.find('.kv-caption-icon').hide();
  18309. }
  18310. },
  18311. _showFileIcon: function () {
  18312. this.$captionContainer.find('.kv-caption-icon').show();
  18313. },
  18314. _getSize: function (bytes) {
  18315. var self = this, size = parseFloat(bytes), i, func = self.fileSizeGetter, sizes, out;
  18316. if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
  18317. return '';
  18318. }
  18319. if (typeof func === 'function') {
  18320. out = func(size);
  18321. } else {
  18322. if (size === 0) {
  18323. out = '0.00 B';
  18324. } else {
  18325. i = Math.floor(Math.log(size) / Math.log(1024));
  18326. sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  18327. out = (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
  18328. }
  18329. }
  18330. return self._getLayoutTemplate('size').replace('{sizeText}', out);
  18331. },
  18332. _generatePreviewTemplate: function (cat, data, fname, ftype, previewId, isError, size, frameClass, foot, ind, templ) {
  18333. var self = this, caption = self.slug(fname), prevContent, zoomContent = '',
  18334. config = self.previewSettings[cat] || self.defaults.previewSettings[cat],
  18335. w = config && config.width ? config.width : '', h = config && config.height ? config.height : '',
  18336. footer = foot || self._renderFileFooter(caption, size, ($h.isEmpty(w) ? 'auto' : w), isError),
  18337. hasIconSetting = self._getPreviewIcon(fname), typeCss = 'type-default',
  18338. forcePrevIcon = hasIconSetting && self.preferIconicPreview,
  18339. forceZoomIcon = hasIconSetting && self.preferIconicZoomPreview,
  18340. getContent = function (c, d, zoom, frameCss) {
  18341. var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(c),
  18342. css = (frameClass || '') + ' ' + frameCss;
  18343. if (self.frameClass) {
  18344. css = self.frameClass + ' ' + css;
  18345. }
  18346. if (zoom) {
  18347. css = css.replace(' ' + $h.SORT_CSS, '');
  18348. }
  18349. tmplt = self._parseFilePreviewIcon(tmplt, fname);
  18350. if (c === 'text') {
  18351. d = $h.htmlEncode(d);
  18352. }
  18353. if (cat === 'object' && !ftype) {
  18354. $.each(self.defaults.fileTypeSettings, function (key, func) {
  18355. if (key === 'object' || key === 'other') {
  18356. return;
  18357. }
  18358. if (func(fname, ftype)) {
  18359. typeCss = 'type-' + key;
  18360. }
  18361. });
  18362. }
  18363. return tmplt.setTokens({
  18364. 'previewId': id,
  18365. 'caption': caption,
  18366. 'frameClass': css,
  18367. 'type': ftype,
  18368. 'fileindex': ind,
  18369. 'width': w,
  18370. 'height': h,
  18371. 'typeCss': typeCss,
  18372. 'footer': footer,
  18373. 'data': d,
  18374. 'template': templ || cat
  18375. });
  18376. };
  18377. ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
  18378. if (self.fileActionSettings.showZoom) {
  18379. zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb');
  18380. }
  18381. zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
  18382. prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb');
  18383. return prevContent + zoomContent;
  18384. },
  18385. _previewDefault: function (file, previewId, isDisabled) {
  18386. var self = this, $preview = self.$preview;
  18387. if (!self.showPreview) {
  18388. return;
  18389. }
  18390. var fname = file ? file.name : '', ftype = file ? file.type : '', content, size = file.size || 0,
  18391. caption = self.slug(fname), isError = isDisabled === true && !self.isUploadable,
  18392. data = $h.objUrl.createObjectURL(file);
  18393. self._clearDefaultPreview();
  18394. content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, isError, size);
  18395. $preview.append("\n" + content);
  18396. self._setThumbAttr(previewId, caption, size);
  18397. if (isDisabled === true && self.isUploadable) {
  18398. self._setThumbStatus($('#' + previewId), 'Error');
  18399. }
  18400. },
  18401. _previewFile: function (i, file, theFile, previewId, data) {
  18402. if (!this.showPreview) {
  18403. return;
  18404. }
  18405. var self = this, cat = self._parseFileType(file), fname = file ? file.name : '', caption = self.slug(fname),
  18406. types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes, $preview = self.$preview,
  18407. chkTypes = types && types.indexOf(cat) >= 0, fsize = file.size || 0, ftype = file.type,
  18408. iData = (cat === 'text' || cat === 'html' || cat === 'image') ? theFile.target.result : data, content,
  18409. chkMimes = mimes && mimes.indexOf(ftype) !== -1;
  18410. /** @namespace window.DOMPurify */
  18411. if (cat === 'html' && self.purifyHtml && window.DOMPurify) {
  18412. iData = window.DOMPurify.sanitize(iData);
  18413. }
  18414. if (chkTypes || chkMimes) {
  18415. content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, false, fsize);
  18416. self._clearDefaultPreview();
  18417. $preview.append("\n" + content);
  18418. var $img = $preview.find('#' + previewId + ' img');
  18419. if ($img.length && self.autoOrientImage) {
  18420. $h.validateOrientation(file, function (value) {
  18421. if (value) {
  18422. var $zoomImg = $preview.find('#zoom-' + previewId + ' img'), css = 'rotate-' + value;
  18423. if (value > 4) {
  18424. css += ($img.width() > $img.height() ? ' is-portrait-gt4' : ' is-landscape-gt4');
  18425. }
  18426. $h.addCss($img, css);
  18427. $h.addCss($zoomImg, css);
  18428. self._raise('fileimageoriented', {'$img': $img, 'file': file});
  18429. }
  18430. self._validateImage(previewId, caption, ftype, fsize, iData);
  18431. $h.adjustOrientedImage($img);
  18432. });
  18433. } else {
  18434. self._validateImage(previewId, caption, ftype, fsize, iData);
  18435. }
  18436. } else {
  18437. self._previewDefault(file, previewId);
  18438. }
  18439. self._setThumbAttr(previewId, caption, fsize);
  18440. self._initSortable();
  18441. },
  18442. _setThumbAttr: function (id, caption, size) {
  18443. var self = this, $frame = $('#' + id);
  18444. if ($frame.length) {
  18445. size = size && size > 0 ? self._getSize(size) : '';
  18446. $frame.data({'caption': caption, 'size': size});
  18447. }
  18448. },
  18449. _setInitThumbAttr: function () {
  18450. var self = this, data = self.previewCache.data, len = self.previewCache.count(true), config,
  18451. caption, size, previewId;
  18452. if (len === 0) {
  18453. return;
  18454. }
  18455. for (var i = 0; i < len; i++) {
  18456. config = data.config[i];
  18457. previewId = self.previewInitId + '-' + 'init_' + i;
  18458. caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
  18459. size = $h.ifSet('size', config);
  18460. self._setThumbAttr(previewId, caption, size);
  18461. }
  18462. },
  18463. _slugDefault: function (text) {
  18464. return $h.isEmpty(text) ? '' : String(text).replace(/[\-\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
  18465. },
  18466. _readFiles: function (files) {
  18467. this.reader = new FileReader();
  18468. var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
  18469. $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
  18470. msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
  18471. settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
  18472. fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
  18473. fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
  18474. maxPreviewSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize),
  18475. canPreview = $preview.length && (!maxPreviewSize || isNaN(maxPreviewSize)),
  18476. throwError = function (msg, file, previewId, index) {
  18477. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  18478. p2 = {id: previewId, index: index, file: file, files: files};
  18479. self._previewDefault(file, previewId, true);
  18480. if (self.isUploadable) {
  18481. self.addToStack(undefined);
  18482. setTimeout(function () {
  18483. readFile(index + 1);
  18484. }, 100);
  18485. }
  18486. self._initFileActions();
  18487. if (self.removeFromPreviewOnError) {
  18488. $('#' + previewId).remove();
  18489. }
  18490. return self.isUploadable ? self._showUploadError(msg, p1) : self._showError(msg, p2);
  18491. };
  18492. self.loadedImages = [];
  18493. self.totalImagesCount = 0;
  18494. $.each(files, function (key, file) {
  18495. var func = self.fileTypeSettings.image;
  18496. if (func && func(file.type)) {
  18497. self.totalImagesCount++;
  18498. }
  18499. });
  18500. readFile = function (i) {
  18501. if ($h.isEmpty($el.attr('multiple'))) {
  18502. numFiles = 1;
  18503. }
  18504. if (i >= numFiles) {
  18505. if (self.isUploadable && self.filestack.length > 0) {
  18506. self._raise('filebatchselected', [self.getFileStack()]);
  18507. } else {
  18508. self._raise('filebatchselected', [files]);
  18509. }
  18510. $container.removeClass('file-thumb-loading');
  18511. $status.html('');
  18512. return;
  18513. }
  18514. var node = ctr + i, previewId = previewInitId + "-" + node, isText, isImage, file = files[i], fSizeKB,
  18515. caption = file.name ? self.slug(file.name) : '', fileSize = (file.size || 0) / 1000, j, msg,
  18516. fileExtExpr = '', previewData = $h.objUrl.createObjectURL(file), typ, chk, typ1, typ2,
  18517. fileCount = 0, strTypes = '', func;
  18518. if (typLen > 0) {
  18519. for (j = 0; j < typLen; j++) {
  18520. typ1 = fileTypes[j];
  18521. typ2 = self.msgFileTypes[typ1] || typ1;
  18522. strTypes += j === 0 ? typ2 : ', ' + typ2;
  18523. }
  18524. }
  18525. if (caption === false) {
  18526. readFile(i + 1);
  18527. return;
  18528. }
  18529. if (caption.length === 0) {
  18530. msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode(file.name));
  18531. self.isError = throwError(msg, file, previewId, i);
  18532. return;
  18533. }
  18534. if (!$h.isEmpty(fileExt)) {
  18535. fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
  18536. }
  18537. fSizeKB = fileSize.toFixed(2);
  18538. if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
  18539. msg = self.msgSizeTooLarge.setTokens({
  18540. 'name': caption,
  18541. 'size': fSizeKB,
  18542. 'maxSize': self.maxFileSize
  18543. });
  18544. self.isError = throwError(msg, file, previewId, i);
  18545. return;
  18546. }
  18547. if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
  18548. msg = self.msgSizeTooSmall.setTokens({
  18549. 'name': caption,
  18550. 'size': fSizeKB,
  18551. 'minSize': self.minFileSize
  18552. });
  18553. self.isError = throwError(msg, file, previewId, i);
  18554. return;
  18555. }
  18556. if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
  18557. for (j = 0; j < fileTypes.length; j += 1) {
  18558. typ = fileTypes[j];
  18559. func = settings[typ];
  18560. fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type, file.name) ? 1 : 0);
  18561. }
  18562. if (fileCount === 0) {
  18563. msg = self.msgInvalidFileType.setTokens({'name': caption, 'types': strTypes});
  18564. self.isError = throwError(msg, file, previewId, i);
  18565. return;
  18566. }
  18567. }
  18568. if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
  18569. chk = $h.compare(caption, fileExtExpr);
  18570. fileCount += $h.isEmpty(chk) ? 0 : chk.length;
  18571. if (fileCount === 0) {
  18572. msg = self.msgInvalidFileExtension.setTokens({'name': caption, 'extensions': strExt});
  18573. self.isError = throwError(msg, file, previewId, i);
  18574. return;
  18575. }
  18576. }
  18577. if (!self.showPreview) {
  18578. if (self.isUploadable) {
  18579. self.addToStack(file);
  18580. }
  18581. setTimeout(function () {
  18582. readFile(i + 1);
  18583. self._updateFileDetails(numFiles);
  18584. }, 100);
  18585. self._raise('fileloaded', [file, previewId, i, reader]);
  18586. return;
  18587. }
  18588. if (!canPreview && fileSize > maxPreviewSize) {
  18589. self.addToStack(file);
  18590. $container.addClass('file-thumb-loading');
  18591. self._previewDefault(file, previewId);
  18592. self._initFileActions();
  18593. self._updateFileDetails(numFiles);
  18594. readFile(i + 1);
  18595. return;
  18596. }
  18597. if ($preview.length && FileReader !== undefined) {
  18598. $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
  18599. $container.addClass('file-thumb-loading');
  18600. reader.onerror = function (evt) {
  18601. self._errorHandler(evt, caption);
  18602. };
  18603. reader.onload = function (theFile) {
  18604. self._previewFile(i, file, theFile, previewId, previewData);
  18605. self._initFileActions();
  18606. };
  18607. reader.onloadend = function () {
  18608. msg = msgProgress.setTokens({
  18609. 'index': i + 1,
  18610. 'files': numFiles,
  18611. 'percent': 50,
  18612. 'name': caption
  18613. });
  18614. setTimeout(function () {
  18615. $status.html(msg);
  18616. self._updateFileDetails(numFiles);
  18617. readFile(i + 1);
  18618. }, 100);
  18619. self._raise('fileloaded', [file, previewId, i, reader]);
  18620. };
  18621. reader.onprogress = function (data) {
  18622. if (data.lengthComputable) {
  18623. var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
  18624. msg = msgProgress.setTokens({
  18625. 'index': i + 1,
  18626. 'files': numFiles,
  18627. 'percent': progress,
  18628. 'name': caption
  18629. });
  18630. setTimeout(function () {
  18631. $status.html(msg);
  18632. }, 100);
  18633. }
  18634. };
  18635. isText = settings.text;
  18636. isImage = settings.image;
  18637. if (isText(file.type, caption)) {
  18638. reader.readAsText(file, self.textEncoding);
  18639. } else {
  18640. if (isImage(file.type, caption)) {
  18641. reader.readAsDataURL(file);
  18642. } else {
  18643. reader.readAsArrayBuffer(file);
  18644. }
  18645. }
  18646. } else {
  18647. self._previewDefault(file, previewId);
  18648. setTimeout(function () {
  18649. readFile(i + 1);
  18650. self._updateFileDetails(numFiles);
  18651. }, 100);
  18652. self._raise('fileloaded', [file, previewId, i, reader]);
  18653. }
  18654. self.addToStack(file);
  18655. };
  18656. readFile(0);
  18657. self._updateFileDetails(numFiles, false);
  18658. },
  18659. _updateFileDetails: function (numFiles) {
  18660. var self = this, $el = self.$element, fileStack = self.getFileStack(),
  18661. name = ($h.isIE(9) && $h.findFileName($el.val())) ||
  18662. ($el[0].files[0] && $el[0].files[0].name) || (fileStack.length && fileStack[0].name) || '',
  18663. label = self.slug(name), n = self.isUploadable ? fileStack.length : numFiles,
  18664. nFiles = self.previewCache.count() + n, log = n > 1 ? self._getMsgSelected(nFiles) : label;
  18665. if (self.isError) {
  18666. self.$previewContainer.removeClass('file-thumb-loading');
  18667. self.$previewStatus.html('');
  18668. self.$captionContainer.find('.kv-caption-icon').hide();
  18669. } else {
  18670. self._showFileIcon();
  18671. }
  18672. self._setCaption(log, self.isError);
  18673. self.$container.removeClass('file-input-new file-input-ajax-new');
  18674. if (arguments.length === 1) {
  18675. self._raise('fileselect', [numFiles, label]);
  18676. }
  18677. if (self.previewCache.count()) {
  18678. self._initPreviewActions();
  18679. }
  18680. },
  18681. _setThumbStatus: function ($thumb, status) {
  18682. var self = this;
  18683. if (!self.showPreview) {
  18684. return;
  18685. }
  18686. var icon = 'indicator' + status, msg = icon + 'Title',
  18687. css = 'file-preview-' + status.toLowerCase(),
  18688. $indicator = $thumb.find('.file-upload-indicator'),
  18689. config = self.fileActionSettings;
  18690. $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
  18691. if (status === 'Error') {
  18692. $thumb.find('.kv-file-upload').attr('disabled', true);
  18693. }
  18694. if (status === 'Success') {
  18695. $thumb.find('.file-drag-handle').remove();
  18696. $indicator.css('margin-left', 0);
  18697. }
  18698. $indicator.html(config[icon]);
  18699. $indicator.attr('title', config[msg]);
  18700. $thumb.addClass(css);
  18701. },
  18702. _setProgressCancelled: function () {
  18703. var self = this;
  18704. self._setProgress(101, self.$progress, self.msgCancelled);
  18705. },
  18706. _setProgress: function (p, $el, error) {
  18707. var self = this, pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
  18708. t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
  18709. template = pct < 100 ? self.progressTemplate : (error ? self.progressErrorTemplate : t);
  18710. $el = $el || self.$progress;
  18711. if (!$h.isEmpty(template)) {
  18712. if (pctLimit && pct > pctLimit && p <= 100) {
  18713. out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
  18714. } else {
  18715. out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
  18716. }
  18717. $el.html(out);
  18718. if (error) {
  18719. $el.find('[role="progressbar"]').html(error);
  18720. }
  18721. }
  18722. },
  18723. _setFileDropZoneTitle: function () {
  18724. var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
  18725. if (self.isClickable) {
  18726. strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
  18727. title += self.dropZoneClickTitle.replace('{files}', strFiles);
  18728. }
  18729. $zone.find('.' + self.dropZoneTitleClass).remove();
  18730. if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
  18731. return;
  18732. }
  18733. if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
  18734. $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
  18735. }
  18736. self.$container.removeClass('file-input-new');
  18737. $h.addCss(self.$container, 'file-input-ajax-new');
  18738. },
  18739. _setAsyncUploadStatus: function (previewId, pct, total) {
  18740. var self = this, sum = 0;
  18741. self._setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
  18742. self.uploadStatus[previewId] = pct;
  18743. $.each(self.uploadStatus, function (key, value) {
  18744. sum += value;
  18745. });
  18746. self._setProgress(Math.floor(sum / total));
  18747. },
  18748. _validateMinCount: function () {
  18749. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  18750. if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
  18751. self._noFilesError({});
  18752. return false;
  18753. }
  18754. return true;
  18755. },
  18756. _getFileCount: function (fileCount) {
  18757. var self = this, addCount = 0;
  18758. if (self.validateInitialCount && !self.overwriteInitial) {
  18759. addCount = self.previewCache.count();
  18760. fileCount += addCount;
  18761. }
  18762. return fileCount;
  18763. },
  18764. _getFileId: function (file) {
  18765. var self = this, custom = self.generateFileId, relativePath;
  18766. if (typeof custom === 'function') {
  18767. return custom(file, event);
  18768. }
  18769. if (!file) {
  18770. return null;
  18771. }
  18772. /** @namespace file.webkitRelativePath */
  18773. relativePath = file.webkitRelativePath || file.fileName || file.name || null;
  18774. if (!relativePath) {
  18775. return null;
  18776. }
  18777. return (file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
  18778. },
  18779. _getFileName: function (file) {
  18780. return file && file.name ? this.slug(file.name) : undefined;
  18781. },
  18782. _getFileIds: function (skipNull) {
  18783. var self = this;
  18784. return self.fileids.filter(function (n) {
  18785. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  18786. });
  18787. },
  18788. _getFileNames: function (skipNull) {
  18789. var self = this;
  18790. return self.filenames.filter(function (n) {
  18791. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  18792. });
  18793. },
  18794. _setPreviewError: function ($thumb, i, val) {
  18795. var self = this;
  18796. if (i !== undefined) {
  18797. self.updateStack(i, val);
  18798. }
  18799. if (self.removeFromPreviewOnError) {
  18800. $thumb.remove();
  18801. } else {
  18802. self._setThumbStatus($thumb, 'Error');
  18803. }
  18804. },
  18805. _checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
  18806. var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type],
  18807. $imgEl, isValid;
  18808. if ($h.isEmpty(limit) || !$img.length) {
  18809. return;
  18810. }
  18811. $imgEl = $img[0];
  18812. dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
  18813. isValid = chk === 'Small' ? dim >= limit : dim <= limit;
  18814. if (isValid) {
  18815. return;
  18816. }
  18817. msg = self['msgImage' + type + chk].setTokens({'name': fname, 'size': limit});
  18818. self._showUploadError(msg, params);
  18819. self._setPreviewError($thumb, i, null);
  18820. },
  18821. _validateImage: function (previewId, fname, ftype, fsize, iData) {
  18822. var self = this, $preview = self.$preview, params, w1, w2, $thumb = $preview.find("#" + previewId),
  18823. i = $thumb.attr('data-fileindex'), $img = $thumb.find('img'), exifObject;
  18824. fname = fname || 'Untitled';
  18825. $img.one('load', function () {
  18826. w1 = $thumb.width();
  18827. w2 = $preview.width();
  18828. if (w1 > w2) {
  18829. $img.css('width', '100%');
  18830. }
  18831. params = {ind: i, id: previewId};
  18832. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
  18833. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
  18834. if (!self.resizeImage) {
  18835. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
  18836. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
  18837. }
  18838. self._raise('fileimageloaded', [previewId]);
  18839. exifObject = window.piexif ? window.piexif.load(iData) : null;
  18840. self.loadedImages.push({
  18841. ind: i,
  18842. img: $img,
  18843. thumb: $thumb,
  18844. pid: previewId,
  18845. typ: ftype,
  18846. siz: fsize,
  18847. validated: false,
  18848. imgData: iData,
  18849. exifObj: exifObject
  18850. });
  18851. $thumb.data('exif', exifObject);
  18852. self._validateAllImages();
  18853. }).one('error', function () {
  18854. self._raise('fileimageloaderror', [previewId]);
  18855. }).each(function () {
  18856. if (this.complete) {
  18857. $(this).trigger('load');
  18858. } else {
  18859. if (this.error) {
  18860. $(this).trigger('error');
  18861. }
  18862. }
  18863. });
  18864. },
  18865. _validateAllImages: function () {
  18866. var self = this, i, counter = {val: 0}, numImgs = self.loadedImages.length, config,
  18867. fsize, minSize = self.resizeIfSizeMoreThan;
  18868. if (numImgs !== self.totalImagesCount) {
  18869. return;
  18870. }
  18871. self._raise('fileimagesloaded');
  18872. if (!self.resizeImage) {
  18873. return;
  18874. }
  18875. for (i = 0; i < self.loadedImages.length; i++) {
  18876. config = self.loadedImages[i];
  18877. if (config.validated) {
  18878. continue;
  18879. }
  18880. fsize = config.siz;
  18881. if (fsize && fsize > minSize * 1000) {
  18882. self._getResizedImage(config, counter, numImgs);
  18883. }
  18884. self.loadedImages[i].validated = true;
  18885. }
  18886. },
  18887. _getResizedImage: function (config, counter, numImgs) {
  18888. var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
  18889. ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
  18890. isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
  18891. context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
  18892. $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr;
  18893. throwError = function (msg, params, ev) {
  18894. if (self.isUploadable) {
  18895. self._showUploadError(msg, params, ev);
  18896. } else {
  18897. self._showError(msg, params, ev);
  18898. }
  18899. self._setPreviewError($thumb, ind);
  18900. };
  18901. if (!self.filestack[ind] || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
  18902. if (isValidImage && self.filestack[ind]) {
  18903. self._raise('fileimageresized', [pid, ind]);
  18904. }
  18905. counter.val++;
  18906. if (counter.val === numImgs) {
  18907. self._raise('fileimagesresized');
  18908. }
  18909. if (!isValidImage) {
  18910. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  18911. return;
  18912. }
  18913. }
  18914. type = type || self.resizeDefaultImageType;
  18915. chkWidth = width > maxWidth;
  18916. chkHeight = height > maxHeight;
  18917. if (self.resizePreference === 'width') {
  18918. ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
  18919. } else {
  18920. ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
  18921. }
  18922. self._resetCanvas();
  18923. width *= ratio;
  18924. height *= ratio;
  18925. canvas.width = width;
  18926. canvas.height = height;
  18927. try {
  18928. context.drawImage(img, 0, 0, width, height);
  18929. dataURI = canvas.toDataURL(type, self.resizeQuality);
  18930. if (exifObj) {
  18931. exifStr = window.piexif.dump(exifObj);
  18932. dataURI = window.piexif.insert(exifStr, dataURI);
  18933. }
  18934. blob = $h.dataURI2Blob(dataURI);
  18935. self.filestack[ind] = blob;
  18936. self._raise('fileimageresized', [pid, ind]);
  18937. counter.val++;
  18938. if (counter.val === numImgs) {
  18939. self._raise('fileimagesresized', [undefined, undefined]);
  18940. }
  18941. if (!(blob instanceof Blob)) {
  18942. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  18943. }
  18944. }
  18945. catch (err) {
  18946. counter.val++;
  18947. if (counter.val === numImgs) {
  18948. self._raise('fileimagesresized', [undefined, undefined]);
  18949. }
  18950. msg = self.msgImageResizeException.replace('{errors}', err.message);
  18951. throwError(msg, {id: pid, 'index': ind}, 'fileimageresizeexception');
  18952. }
  18953. },
  18954. _initBrowse: function ($container) {
  18955. var self = this;
  18956. if (self.showBrowse) {
  18957. self.$btnFile = $container.find('.btn-file');
  18958. self.$btnFile.append(self.$element);
  18959. } else {
  18960. self.$element.hide();
  18961. }
  18962. },
  18963. _initCaption: function () {
  18964. var self = this, cap = self.initialCaption || '';
  18965. if (self.overwriteInitial || $h.isEmpty(cap)) {
  18966. self.$caption.html('');
  18967. return false;
  18968. }
  18969. self._setCaption(cap);
  18970. return true;
  18971. },
  18972. _setCaption: function (content, isError) {
  18973. var self = this, title, out, n, cap, stack = self.getFileStack();
  18974. if (!self.$caption.length) {
  18975. return;
  18976. }
  18977. if (isError) {
  18978. title = $('<div>' + self.msgValidationError + '</div>').text();
  18979. n = stack.length;
  18980. if (n) {
  18981. cap = n === 1 && stack[0] ? self._getFileNames()[0] : self._getMsgSelected(n);
  18982. } else {
  18983. cap = self._getMsgSelected(self.msgNo);
  18984. }
  18985. out = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon +
  18986. ($h.isEmpty(content) ? cap : content) + '</span>';
  18987. } else {
  18988. if ($h.isEmpty(content)) {
  18989. return;
  18990. }
  18991. title = $('<div>' + content + '</div>').text();
  18992. out = self._getLayoutTemplate('fileIcon') + title;
  18993. }
  18994. self.$caption.html(out);
  18995. self.$caption.attr('title', title);
  18996. self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
  18997. },
  18998. _createContainer: function () {
  18999. var self = this, attribs = {"class": 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
  19000. $container = $(document.createElement("div")).attr(attribs).html(self._renderMain());
  19001. self.$element.before($container);
  19002. self._initBrowse($container);
  19003. if (self.theme) {
  19004. $container.addClass('theme-' + self.theme);
  19005. }
  19006. return $container;
  19007. },
  19008. _refreshContainer: function () {
  19009. var self = this, $container = self.$container;
  19010. $container.before(self.$element);
  19011. $container.html(self._renderMain());
  19012. self._initBrowse($container);
  19013. },
  19014. _renderMain: function () {
  19015. var self = this,
  19016. dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : 'file-drop-disabled',
  19017. close = !self.showClose ? '' : self._getLayoutTemplate('close'),
  19018. preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
  19019. .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
  19020. css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
  19021. caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
  19022. return self.mainTemplate.setTokens({
  19023. 'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
  19024. 'preview': preview,
  19025. 'close': close,
  19026. 'caption': caption,
  19027. 'upload': self._renderButton('upload'),
  19028. 'remove': self._renderButton('remove'),
  19029. 'cancel': self._renderButton('cancel'),
  19030. 'browse': self._renderButton('browse')
  19031. });
  19032. },
  19033. _renderButton: function (type) {
  19034. var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
  19035. title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
  19036. status = self.isDisabled ? ' disabled' : '', btnType = 'button';
  19037. switch (type) {
  19038. case 'remove':
  19039. if (!self.showRemove) {
  19040. return '';
  19041. }
  19042. break;
  19043. case 'cancel':
  19044. if (!self.showCancel) {
  19045. return '';
  19046. }
  19047. css += ' hide';
  19048. break;
  19049. case 'upload':
  19050. if (!self.showUpload) {
  19051. return '';
  19052. }
  19053. if (self.isUploadable && !self.isDisabled) {
  19054. tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
  19055. } else {
  19056. btnType = 'submit';
  19057. }
  19058. break;
  19059. case 'browse':
  19060. if (!self.showBrowse) {
  19061. return '';
  19062. }
  19063. tmplt = self._getLayoutTemplate('btnBrowse');
  19064. break;
  19065. default:
  19066. return '';
  19067. }
  19068. css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
  19069. if (!$h.isEmpty(label)) {
  19070. label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
  19071. }
  19072. return tmplt.setTokens({
  19073. 'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
  19074. });
  19075. },
  19076. _renderThumbProgress: function () {
  19077. var self = this;
  19078. return '<div class="file-thumb-progress hide">' +
  19079. self.progressTemplate.setTokens({'percent': '0', 'status': self.msgUploadBegin}) +
  19080. '</div>';
  19081. },
  19082. _renderFileFooter: function (caption, size, width, isError) {
  19083. var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
  19084. upl = config.showUpload, zoom = config.showZoom, out, template = self._getLayoutTemplate('footer'),
  19085. ind = isError ? config.indicatorError : config.indicatorNew,
  19086. tInd = self._getLayoutTemplate('indicator'),
  19087. title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
  19088. indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
  19089. size = self._getSize(size);
  19090. if (self.isUploadable) {
  19091. out = template.setTokens({
  19092. 'actions': self._renderFileActions(upl, rem, zoom, drg, false, false, false),
  19093. 'caption': caption,
  19094. 'size': size,
  19095. 'width': width,
  19096. 'progress': self._renderThumbProgress(),
  19097. 'indicator': indicator
  19098. });
  19099. } else {
  19100. out = template.setTokens({
  19101. 'actions': self._renderFileActions(false, false, zoom, drg, false, false, false),
  19102. 'caption': caption,
  19103. 'size': size,
  19104. 'width': width,
  19105. 'progress': '',
  19106. 'indicator': indicator
  19107. });
  19108. }
  19109. out = $h.replaceTags(out, self.previewThumbTags);
  19110. return out;
  19111. },
  19112. _renderFileActions: function (showUpload, showDelete, showZoom, showDrag, disabled, url, key, isInit) {
  19113. if (!showUpload && !showDelete && !showZoom && !showDrag) {
  19114. return '';
  19115. }
  19116. var self = this, vUrl = url === false ? '' : ' data-url="' + url + '"',
  19117. vKey = key === false ? '' : ' data-key="' + key + '"',
  19118. btnDelete = '', btnUpload = '', btnZoom = '', btnDrag = '', css,
  19119. template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
  19120. otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey}),
  19121. removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
  19122. if (showDelete) {
  19123. btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
  19124. 'removeClass': removeClass,
  19125. 'removeIcon': config.removeIcon,
  19126. 'removeTitle': config.removeTitle,
  19127. 'dataUrl': vUrl,
  19128. 'dataKey': vKey
  19129. });
  19130. }
  19131. if (showUpload) {
  19132. btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
  19133. 'uploadClass': config.uploadClass,
  19134. 'uploadIcon': config.uploadIcon,
  19135. 'uploadTitle': config.uploadTitle
  19136. });
  19137. }
  19138. if (showZoom) {
  19139. btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
  19140. 'zoomClass': config.zoomClass,
  19141. 'zoomIcon': config.zoomIcon,
  19142. 'zoomTitle': config.zoomTitle
  19143. });
  19144. }
  19145. if (showDrag && isInit) {
  19146. css = 'drag-handle-init ' + config.dragClass;
  19147. btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
  19148. 'dragClass': css,
  19149. 'dragTitle': config.dragTitle,
  19150. 'dragIcon': config.dragIcon
  19151. });
  19152. }
  19153. return template.setTokens({
  19154. 'delete': btnDelete,
  19155. 'upload': btnUpload,
  19156. 'zoom': btnZoom,
  19157. 'drag': btnDrag,
  19158. 'other': otherButtons
  19159. });
  19160. },
  19161. _browse: function (e) {
  19162. var self = this;
  19163. self._raise('filebrowse');
  19164. if (e && e.isDefaultPrevented()) {
  19165. return;
  19166. }
  19167. if (self.isError && !self.isUploadable) {
  19168. self.clear();
  19169. }
  19170. self.$captionContainer.focus();
  19171. },
  19172. _filterDuplicate: function (file, files, fileIds) {
  19173. var self = this, fileId = self._getFileId(file);
  19174. if (fileId && fileIds && fileIds.indexOf(fileId) > -1) {
  19175. return;
  19176. }
  19177. if (!fileIds) {
  19178. fileIds = [];
  19179. }
  19180. files.push(file);
  19181. fileIds.push(fileId);
  19182. },
  19183. _change: function (e) {
  19184. var self = this, $el = self.$element;
  19185. if (!self.isUploadable && $h.isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
  19186. self.fileInputCleared = false;
  19187. return;
  19188. }
  19189. self.fileInputCleared = false;
  19190. var tfiles = [], msg, total, isDragDrop = arguments.length > 1, isAjaxUpload = self.isUploadable, n, len,
  19191. files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files, ctr = self.filestack.length,
  19192. isSingleUpload = $h.isEmpty($el.attr('multiple')), flagSingle = (isSingleUpload && ctr > 0),
  19193. folders = 0, fileIds = self._getFileIds(), throwError = function (mesg, file, previewId, index) {
  19194. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  19195. p2 = {id: previewId, index: index, file: file, files: files};
  19196. return self.isUploadable ? self._showUploadError(mesg, p1) : self._showError(mesg, p2);
  19197. };
  19198. self.reader = null;
  19199. self._resetUpload();
  19200. self._hideFileIcon();
  19201. if (self.isUploadable) {
  19202. self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
  19203. }
  19204. if (isDragDrop) {
  19205. $.each(files, function (i, f) {
  19206. if (f && !f.type && f.size !== undefined && f.size % 4096 === 0) {
  19207. folders++;
  19208. } else {
  19209. self._filterDuplicate(f, tfiles, fileIds);
  19210. }
  19211. });
  19212. } else {
  19213. if (e.target && e.target.files === undefined) {
  19214. files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
  19215. } else {
  19216. files = e.target.files || {};
  19217. }
  19218. if (isAjaxUpload) {
  19219. $.each(files, function (i, f) {
  19220. self._filterDuplicate(f, tfiles, fileIds);
  19221. });
  19222. } else {
  19223. tfiles = files;
  19224. }
  19225. }
  19226. if ($h.isEmpty(tfiles) || tfiles.length === 0) {
  19227. if (!isAjaxUpload) {
  19228. self.clear();
  19229. }
  19230. self._showFolderError(folders);
  19231. self._raise('fileselectnone');
  19232. return;
  19233. }
  19234. self._resetErrors();
  19235. len = tfiles.length;
  19236. total = self._getFileCount(self.isUploadable ? (self.getFileStack().length + len) : len);
  19237. if (self.maxFileCount > 0 && total > self.maxFileCount) {
  19238. if (!self.autoReplace || len > self.maxFileCount) {
  19239. n = (self.autoReplace && len > self.maxFileCount) ? len : total;
  19240. msg = self.msgFilesTooMany.replace('{m}', self.maxFileCount).replace('{n}', n);
  19241. self.isError = throwError(msg, null, null, null);
  19242. self.$captionContainer.find('.kv-caption-icon').hide();
  19243. self._setCaption('', true);
  19244. self.$container.removeClass('file-input-new file-input-ajax-new');
  19245. return;
  19246. }
  19247. if (total > self.maxFileCount) {
  19248. self._resetPreviewThumbs(isAjaxUpload);
  19249. }
  19250. } else {
  19251. if (!isAjaxUpload || flagSingle) {
  19252. self._resetPreviewThumbs(false);
  19253. if (flagSingle) {
  19254. self.clearStack();
  19255. }
  19256. } else {
  19257. if (isAjaxUpload && ctr === 0 && (!self.previewCache.count() || self.overwriteInitial)) {
  19258. self._resetPreviewThumbs(true);
  19259. }
  19260. }
  19261. }
  19262. if (self.isPreviewable) {
  19263. self._readFiles(tfiles);
  19264. } else {
  19265. self._updateFileDetails(1);
  19266. }
  19267. self._showFolderError(folders);
  19268. },
  19269. _abort: function (params) {
  19270. var self = this, data;
  19271. if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
  19272. data = $.extend(true, {}, self._getOutData(), params);
  19273. data.abortData = self.ajaxAborted.data || {};
  19274. data.abortMessage = self.ajaxAborted.message;
  19275. self._setProgress(101, self.$progress, self.msgCancelled);
  19276. self._showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
  19277. self.cancel();
  19278. return true;
  19279. }
  19280. return false;
  19281. },
  19282. _resetFileStack: function () {
  19283. var self = this, i = 0, newstack = [], newnames = [], newids = [];
  19284. self._getThumbs().each(function () {
  19285. var $thumb = $(this), ind = $thumb.attr('data-fileindex'), file = self.filestack[ind],
  19286. pid = $thumb.attr('id'), newId;
  19287. if (ind === '-1' || ind === -1) {
  19288. return;
  19289. }
  19290. if (file !== undefined) {
  19291. newstack[i] = file;
  19292. newnames[i] = self._getFileName(file);
  19293. newids[i] = self._getFileId(file);
  19294. $thumb.attr({'id': self.previewInitId + '-' + i, 'data-fileindex': i});
  19295. i++;
  19296. } else {
  19297. newId = 'uploaded-' + $h.uniqId();
  19298. $thumb.attr({'id': newId, 'data-fileindex': '-1'});
  19299. self.$preview.find('#zoom-' + pid).attr('id', 'zoom-' + newId);
  19300. }
  19301. });
  19302. self.filestack = newstack;
  19303. self.filenames = newnames;
  19304. self.fileids = newids;
  19305. },
  19306. _isFileSelectionValid: function (cnt) {
  19307. var self = this;
  19308. cnt = cnt || 0;
  19309. if (self.required && !self.getFilesCount()) {
  19310. self.$errorContainer.html('');
  19311. self._showUploadError(self.msgFileRequired);
  19312. return false;
  19313. }
  19314. if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
  19315. self._noFilesError({});
  19316. return false;
  19317. }
  19318. return true;
  19319. },
  19320. clearStack: function () {
  19321. var self = this;
  19322. self.filestack = [];
  19323. self.filenames = [];
  19324. self.fileids = [];
  19325. return self.$element;
  19326. },
  19327. updateStack: function (i, file) {
  19328. var self = this;
  19329. self.filestack[i] = file;
  19330. self.filenames[i] = self._getFileName(file);
  19331. self.fileids[i] = file && self._getFileId(file) || null;
  19332. return self.$element;
  19333. },
  19334. addToStack: function (file) {
  19335. var self = this;
  19336. self.filestack.push(file);
  19337. self.filenames.push(self._getFileName(file));
  19338. self.fileids.push(self._getFileId(file));
  19339. return self.$element;
  19340. },
  19341. getFileStack: function (skipNull) {
  19342. var self = this;
  19343. return self.filestack.filter(function (n) {
  19344. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  19345. });
  19346. },
  19347. getFilesCount: function () {
  19348. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  19349. return self._getFileCount(len);
  19350. },
  19351. lock: function () {
  19352. var self = this;
  19353. self._resetErrors();
  19354. self.disable();
  19355. if (self.showRemove) {
  19356. $h.addCss(self.$container.find('.fileinput-remove'), 'hide');
  19357. }
  19358. if (self.showCancel) {
  19359. self.$container.find('.fileinput-cancel').removeClass('hide');
  19360. }
  19361. self._raise('filelock', [self.filestack, self._getExtraData()]);
  19362. return self.$element;
  19363. },
  19364. unlock: function (reset) {
  19365. var self = this;
  19366. if (reset === undefined) {
  19367. reset = true;
  19368. }
  19369. self.enable();
  19370. if (self.showCancel) {
  19371. $h.addCss(self.$container.find('.fileinput-cancel'), 'hide');
  19372. }
  19373. if (self.showRemove) {
  19374. self.$container.find('.fileinput-remove').removeClass('hide');
  19375. }
  19376. if (reset) {
  19377. self._resetFileStack();
  19378. }
  19379. self._raise('fileunlock', [self.filestack, self._getExtraData()]);
  19380. return self.$element;
  19381. },
  19382. cancel: function () {
  19383. var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
  19384. if (len > 0) {
  19385. for (i = 0; i < len; i += 1) {
  19386. self.cancelling = true;
  19387. xhr[i].abort();
  19388. }
  19389. }
  19390. self._setProgressCancelled();
  19391. self._getThumbs().each(function () {
  19392. var $thumb = $(this), ind = $thumb.attr('data-fileindex');
  19393. $thumb.removeClass('file-uploading');
  19394. if (self.filestack[ind] !== undefined) {
  19395. $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
  19396. $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
  19397. }
  19398. self.unlock();
  19399. });
  19400. return self.$element;
  19401. },
  19402. clear: function () {
  19403. var self = this, cap;
  19404. if (!self._raise('fileclear')) {
  19405. return;
  19406. }
  19407. self.$btnUpload.removeAttr('disabled');
  19408. self._getThumbs().find('video,audio,img').each(function () {
  19409. $h.cleanMemory($(this));
  19410. });
  19411. self._resetUpload();
  19412. self.clearStack();
  19413. self._clearFileInput();
  19414. self._resetErrors(true);
  19415. if (self._hasInitialPreview()) {
  19416. self._showFileIcon();
  19417. self._resetPreview();
  19418. self._initPreviewActions();
  19419. self.$container.removeClass('file-input-new');
  19420. } else {
  19421. self._getThumbs().each(function () {
  19422. self._clearObjects($(this));
  19423. });
  19424. if (self.isUploadable) {
  19425. self.previewCache.data = {};
  19426. }
  19427. self.$preview.html('');
  19428. cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
  19429. self.$caption.html(cap);
  19430. self.$caption.attr('title', '');
  19431. $h.addCss(self.$container, 'file-input-new');
  19432. self._validateDefaultPreview();
  19433. }
  19434. if (self.$container.find($h.FRAMES).length === 0) {
  19435. if (!self._initCaption()) {
  19436. self.$captionContainer.find('.kv-caption-icon').hide();
  19437. }
  19438. }
  19439. self._hideFileIcon();
  19440. self._raise('filecleared');
  19441. self.$captionContainer.focus();
  19442. self._setFileDropZoneTitle();
  19443. return self.$element;
  19444. },
  19445. reset: function () {
  19446. var self = this;
  19447. if (!self._raise('filereset')) {
  19448. return;
  19449. }
  19450. self._resetPreview();
  19451. self.$container.find('.fileinput-filename').text('');
  19452. $h.addCss(self.$container, 'file-input-new');
  19453. if (self.getFrames().length || self.isUploadable && self.dropZoneEnabled) {
  19454. self.$container.removeClass('file-input-new');
  19455. }
  19456. self._setFileDropZoneTitle();
  19457. self.clearStack();
  19458. self.formdata = {};
  19459. return self.$element;
  19460. },
  19461. disable: function () {
  19462. var self = this;
  19463. self.isDisabled = true;
  19464. self._raise('filedisabled');
  19465. self.$element.attr('disabled', 'disabled');
  19466. self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
  19467. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  19468. .attr("disabled", true);
  19469. self._initDragDrop();
  19470. return self.$element;
  19471. },
  19472. enable: function () {
  19473. var self = this;
  19474. self.isDisabled = false;
  19475. self._raise('fileenabled');
  19476. self.$element.removeAttr('disabled');
  19477. self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
  19478. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  19479. .removeAttr("disabled");
  19480. self._initDragDrop();
  19481. return self.$element;
  19482. },
  19483. upload: function () {
  19484. var self = this, totLen = self.getFileStack().length, i, outData, len,
  19485. hasExtraData = !$.isEmptyObject(self._getExtraData());
  19486. if (!self.isUploadable || self.isDisabled || !self._isFileSelectionValid(totLen)) {
  19487. return;
  19488. }
  19489. self._resetUpload();
  19490. if (totLen === 0 && !hasExtraData) {
  19491. self._showUploadError(self.msgUploadEmpty);
  19492. return;
  19493. }
  19494. self.$progress.removeClass('hide');
  19495. self.uploadCount = 0;
  19496. self.uploadStatus = {};
  19497. self.uploadLog = [];
  19498. self.lock();
  19499. self._setProgress(2);
  19500. if (totLen === 0 && hasExtraData) {
  19501. self._uploadExtraOnly();
  19502. return;
  19503. }
  19504. len = self.filestack.length;
  19505. self.hasInitData = false;
  19506. if (self.uploadAsync) {
  19507. outData = self._getOutData();
  19508. self._raise('filebatchpreupload', [outData]);
  19509. self.fileBatchCompleted = false;
  19510. self.uploadCache = {content: [], config: [], tags: [], append: true};
  19511. self.uploadAsyncCount = self.getFileStack().length;
  19512. for (i = 0; i < len; i++) {
  19513. self.uploadCache.content[i] = null;
  19514. self.uploadCache.config[i] = null;
  19515. self.uploadCache.tags[i] = null;
  19516. }
  19517. self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
  19518. self._initSortable();
  19519. self.cacheInitialPreview = self.getPreview();
  19520. for (i = 0; i < len; i++) {
  19521. if (self.filestack[i] !== undefined) {
  19522. self._uploadSingle(i, self.filestack, true);
  19523. }
  19524. }
  19525. return;
  19526. }
  19527. self._uploadBatch();
  19528. return self.$element;
  19529. },
  19530. destroy: function () {
  19531. var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
  19532. $(document).off(ns);
  19533. $(window).off(ns);
  19534. if ($form && $form.length) {
  19535. $form.off(ns);
  19536. }
  19537. if (self.isUploadable) {
  19538. self._clearFileInput();
  19539. }
  19540. self._cleanup();
  19541. self._initPreviewCache();
  19542. $el.insertBefore($cont).off(ns).removeData();
  19543. $cont.off().remove();
  19544. return $el;
  19545. },
  19546. refresh: function (options) {
  19547. var self = this, $el = self.$element;
  19548. options = options ? $.extend(true, {}, self.options, options) : self.options;
  19549. self.destroy();
  19550. $el.fileinput(options);
  19551. self = $el.data('fileinput');
  19552. if (self.isUploadable) {
  19553. self._clearFileInput();
  19554. }
  19555. if ($el.val()) {
  19556. $el.trigger('change.fileinput');
  19557. }
  19558. return $el;
  19559. },
  19560. zoom: function (frameId) {
  19561. var self = this, $frame = self._getFrame(frameId), $modal = self.$modal;
  19562. if (!$frame) {
  19563. return;
  19564. }
  19565. $h.initModal($modal);
  19566. $modal.html(self._getModalContent());
  19567. self._setZoomContent($frame);
  19568. $modal.modal('show');
  19569. self._initZoomButtons();
  19570. },
  19571. getExif: function (frameId) {
  19572. var self = this, $frame = self._getFrame(frameId);
  19573. return $frame && $frame.data('exif') || null;
  19574. },
  19575. getFrames: function (cssFilter) {
  19576. var self = this;
  19577. cssFilter = cssFilter || '';
  19578. return self.$preview.find($h.FRAMES + cssFilter);
  19579. },
  19580. getPreview: function () {
  19581. var self = this;
  19582. return {
  19583. content: self.initialPreview,
  19584. config: self.initialPreviewConfig,
  19585. tags: self.initialPreviewThumbTags
  19586. };
  19587. }
  19588. };
  19589. $.fn.fileinput = function (option) {
  19590. if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
  19591. return;
  19592. }
  19593. var args = Array.apply(null, arguments), retvals = [];
  19594. args.shift();
  19595. this.each(function () {
  19596. var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
  19597. theme = options.theme || self.data('theme'), l = {}, t = {},
  19598. lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
  19599. if (!data) {
  19600. if (theme) {
  19601. t = $.fn.fileinputThemes[theme] || {};
  19602. }
  19603. if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
  19604. l = $.fn.fileinputLocales[lang] || {};
  19605. }
  19606. opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
  19607. data = new FileInput(this, opt);
  19608. self.data('fileinput', data);
  19609. }
  19610. if (typeof option === 'string') {
  19611. retvals.push(data[option].apply(data, args));
  19612. }
  19613. });
  19614. switch (retvals.length) {
  19615. case 0:
  19616. return this;
  19617. case 1:
  19618. return retvals[0];
  19619. default:
  19620. return retvals;
  19621. }
  19622. };
  19623. $.fn.fileinput.defaults = {
  19624. language: 'en',
  19625. showCaption: true,
  19626. showBrowse: true,
  19627. showPreview: true,
  19628. showRemove: true,
  19629. showUpload: true,
  19630. showCancel: true,
  19631. showClose: true,
  19632. showUploadedThumbs: true,
  19633. browseOnZoneClick: false,
  19634. autoReplace: false,
  19635. autoOrientImage: true, // for JPEG images based on EXIF orientation tag
  19636. required: false,
  19637. rtl: false,
  19638. hideThumbnailContent: false,
  19639. generateFileId: null,
  19640. previewClass: '',
  19641. captionClass: '',
  19642. frameClass: 'krajee-default',
  19643. mainClass: 'file-caption-main',
  19644. mainTemplate: null,
  19645. purifyHtml: true,
  19646. fileSizeGetter: null,
  19647. initialCaption: '',
  19648. initialPreview: [],
  19649. initialPreviewDelimiter: '*$$*',
  19650. initialPreviewAsData: false,
  19651. initialPreviewFileType: 'image',
  19652. initialPreviewConfig: [],
  19653. initialPreviewThumbTags: [],
  19654. previewThumbTags: {},
  19655. initialPreviewShowDelete: true,
  19656. removeFromPreviewOnError: false,
  19657. deleteUrl: '',
  19658. deleteExtraData: {},
  19659. overwriteInitial: true,
  19660. previewZoomButtonIcons: {
  19661. prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
  19662. next: '<i class="glyphicon glyphicon-triangle-right"></i>',
  19663. toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
  19664. fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
  19665. borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
  19666. close: '<i class="glyphicon glyphicon-remove"></i>'
  19667. },
  19668. previewZoomButtonClasses: {
  19669. prev: 'btn btn-navigate',
  19670. next: 'btn btn-navigate',
  19671. toggleheader: 'btn btn-default btn-header-toggle',
  19672. fullscreen: 'btn btn-default',
  19673. borderless: 'btn btn-default',
  19674. close: 'btn btn-default'
  19675. },
  19676. preferIconicPreview: false,
  19677. preferIconicZoomPreview: false,
  19678. allowedPreviewTypes: undefined,
  19679. allowedPreviewMimeTypes: null,
  19680. allowedFileTypes: null,
  19681. allowedFileExtensions: null,
  19682. defaultPreviewContent: null,
  19683. customLayoutTags: {},
  19684. customPreviewTags: {},
  19685. previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
  19686. previewFileIconClass: 'file-other-icon',
  19687. previewFileIconSettings: {},
  19688. previewFileExtSettings: {},
  19689. buttonLabelClass: 'hidden-xs',
  19690. browseIcon: '<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',
  19691. browseClass: 'btn btn-primary',
  19692. removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
  19693. removeClass: 'btn btn-default',
  19694. cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
  19695. cancelClass: 'btn btn-default',
  19696. uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
  19697. uploadClass: 'btn btn-default',
  19698. uploadUrl: null,
  19699. uploadAsync: true,
  19700. uploadExtraData: {},
  19701. zoomModalHeight: 480,
  19702. minImageWidth: null,
  19703. minImageHeight: null,
  19704. maxImageWidth: null,
  19705. maxImageHeight: null,
  19706. resizeImage: false,
  19707. resizePreference: 'width',
  19708. resizeQuality: 0.92,
  19709. resizeDefaultImageType: 'image/jpeg',
  19710. resizeIfSizeMoreThan: 0, // in KB
  19711. minFileSize: 0,
  19712. maxFileSize: 0,
  19713. maxFilePreviewSize: 25600, // 25 MB
  19714. minFileCount: 0,
  19715. maxFileCount: 0,
  19716. validateInitialCount: false,
  19717. msgValidationErrorClass: 'text-danger',
  19718. msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
  19719. msgErrorClass: 'file-error-message',
  19720. progressThumbClass: "progress-bar progress-bar-success progress-bar-striped active",
  19721. progressClass: "progress-bar progress-bar-success progress-bar-striped active",
  19722. progressCompleteClass: "progress-bar progress-bar-success",
  19723. progressErrorClass: "progress-bar progress-bar-danger",
  19724. progressUploadThreshold: 99,
  19725. previewFileType: 'image',
  19726. elCaptionContainer: null,
  19727. elCaptionText: null,
  19728. elPreviewContainer: null,
  19729. elPreviewImage: null,
  19730. elPreviewStatus: null,
  19731. elErrorContainer: null,
  19732. errorCloseButton: '<span class="close kv-error-close">&times;</span>',
  19733. slugCallback: null,
  19734. dropZoneEnabled: true,
  19735. dropZoneTitleClass: 'file-drop-zone-title',
  19736. fileActionSettings: {},
  19737. otherActionButtons: '',
  19738. textEncoding: 'UTF-8',
  19739. ajaxSettings: {},
  19740. ajaxDeleteSettings: {},
  19741. showAjaxErrorDetails: true
  19742. };
  19743. $.fn.fileinputLocales.en = {
  19744. fileSingle: 'file',
  19745. filePlural: 'files',
  19746. browseLabel: 'Browse &hellip;',
  19747. removeLabel: 'Remove',
  19748. removeTitle: 'Clear selected files',
  19749. cancelLabel: 'Cancel',
  19750. cancelTitle: 'Abort ongoing upload',
  19751. uploadLabel: 'Upload',
  19752. uploadTitle: 'Upload selected files',
  19753. msgNo: 'No',
  19754. msgNoFilesSelected: 'No files selected',
  19755. msgCancelled: 'Cancelled',
  19756. msgZoomModalHeading: 'Detailed Preview',
  19757. msgFileRequired: 'You must select a file to upload.',
  19758. msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
  19759. msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
  19760. msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
  19761. msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
  19762. msgFileNotFound: 'File "{name}" not found!',
  19763. msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
  19764. msgFileNotReadable: 'File "{name}" is not readable.',
  19765. msgFilePreviewAborted: 'File preview aborted for "{name}".',
  19766. msgFilePreviewError: 'An error occurred while reading the file "{name}".',
  19767. msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
  19768. msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
  19769. msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
  19770. msgFileTypes: {
  19771. 'image': 'image',
  19772. 'html': 'HTML',
  19773. 'text': 'text',
  19774. 'video': 'video',
  19775. 'audio': 'audio',
  19776. 'flash': 'flash',
  19777. 'pdf': 'PDF',
  19778. 'object': 'object'
  19779. },
  19780. msgUploadAborted: 'The file upload was aborted',
  19781. msgUploadThreshold: 'Processing...',
  19782. msgUploadBegin: 'Initializing...',
  19783. msgUploadEnd: 'Done',
  19784. msgUploadEmpty: 'No valid data available for upload.',
  19785. msgValidationError: 'Validation Error',
  19786. msgLoading: 'Loading file {index} of {files} &hellip;',
  19787. msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
  19788. msgSelected: '{n} {files} selected',
  19789. msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
  19790. msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
  19791. msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
  19792. msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
  19793. msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
  19794. msgImageResizeError: 'Could not get the image dimensions to resize.',
  19795. msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
  19796. msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
  19797. msgAjaxProgressError: '{operation} failed',
  19798. ajaxOperations: {
  19799. deleteThumb: 'file delete',
  19800. uploadThumb: 'file upload',
  19801. uploadBatch: 'batch file upload',
  19802. uploadExtra: 'form data upload'
  19803. },
  19804. dropZoneTitle: 'Drag & drop files here &hellip;',
  19805. dropZoneClickTitle: '<br>(or click to select {files})',
  19806. previewZoomButtonTitles: {
  19807. prev: 'View previous file',
  19808. next: 'View next file',
  19809. toggleheader: 'Toggle header',
  19810. fullscreen: 'Toggle full screen',
  19811. borderless: 'Toggle borderless mode',
  19812. close: 'Close detailed preview'
  19813. }
  19814. };
  19815. $.fn.fileinput.Constructor = FileInput;
  19816. /**
  19817. * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
  19818. */
  19819. $(document).ready(function () {
  19820. var $input = $('input.file[type=file]');
  19821. if ($input.length) {
  19822. $input.fileinput();
  19823. }
  19824. });
  19825. }));
  19826. /***/ }),
  19827. /* 8 */
  19828. /***/ (function(module, exports) {
  19829. // removed by extract-text-webpack-plugin
  19830. /***/ }),
  19831. /* 9 */
  19832. /***/ (function(module, exports) {
  19833. // removed by extract-text-webpack-plugin
  19834. /***/ }),
  19835. /* 10 */
  19836. /***/ (function(module, exports) {
  19837. // removed by extract-text-webpack-plugin
  19838. /***/ }),
  19839. /* 11 */
  19840. /***/ (function(module, exports) {
  19841. // removed by extract-text-webpack-plugin
  19842. /***/ }),
  19843. /* 12 */
  19844. /***/ (function(module, exports) {
  19845. // removed by extract-text-webpack-plugin
  19846. /***/ })
  19847. /******/ ]);
  19848. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgNzYwN2Y0OTU5MTc4OTdhNzUyNGIiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS9kaXN0L2pxdWVyeS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2pzL2Jvb3RzdHJhcC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcG9wcGVyLmpzL2Rpc3QvZXNtL3BvcHBlci5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtc2VsZWN0L2Rpc3QvanMvYm9vdHN0cmFwLXNlbGVjdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXZhbGlkYXRvci9qcy92YWxpZGF0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvanMvZmlsZWlucHV0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9jc3MvYm9vdHN0cmFwLmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLWZpbGVpbnB1dC9jc3MvZmlsZWlucHV0LmNzcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGZvcnRhd2Vzb21lL2ZvbnRhd2Vzb21lLWZyZWUvY3NzL2FsbC5jc3MiLCJ3ZWJwYWNrOi8vLy4vc3JjL3N0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7OztBQUlBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsWUFBWTs7QUFFcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxTQUFTO0FBQ2xCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyxZQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLFNBQVM7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxnQkFBZ0IsSUFBSTs7QUFFcEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esd0NBQXdDLElBQUk7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSx5QkFBeUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUSw2QkFBNkI7QUFDaEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGdCQUFnQjtBQUMzQixhQUFhLHVCQUF1QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGNBQWM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGVBQWU7O0FBRWYsU0FBUzs7QUFFVDtBQUNBLFFBQVEsaUNBQWlDO0FBQ3pDLFFBQVEsb0JBQW9CO0FBQzVCLFFBQVEsc0NBQXNDO0FBQzlDLFFBQVE7QUFDUixFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYSxFQUFFO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw0REFBNEQ7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEOztBQUU3RDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0VBQWdFOztBQUVoRTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFLFVBQVU7QUFDM0Usc0NBQXNDLDJCQUEyQjtBQUNqRTtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxVQUFVO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsY0FBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFlBQVksdUVBQXVFO0FBQ25GO0FBQ0E7QUFDQSxZQUFZLDRCQUE0QjtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLFNBQVM7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSwyREFBMkQ7O0FBRTNEO0FBQ0E7QUFDQSxvRkFBb0Y7O0FBRXBGO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaURBQWlEO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pELFVBQVUsd0NBQXdDO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsTUFBTTtBQUNqQixXQUFXLE1BQU07QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUEsQ0FBQzs7OztBQUlEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLFFBQVEsR0FBRztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOzs7O0FBSUE7O0FBRUE7O0FBRUE7QUFDQTs7OztBQUlBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLFNBQVM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUEsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVLE9BQU87QUFDakIsMEJBQTBCLHdCQUF3Qjs7QUFFbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsMENBQTBDO0FBQzFDLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxjQUFjO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLHNDQUFzQztBQUM5RSxvQ0FBb0MsdUNBQXVDO0FBQzNFLG9DQUFvQyxzQ0FBc0M7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUixPQUFPO0FBQ1A7QUFDQSxNQUFNO0FBQ04sS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTs7QUFFVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQyxxQ0FBcUM7QUFDckMsb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7Ozs7O0FBS0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxTQUFTO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGFBQWE7QUFDcEMsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsU0FBUztBQUM3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSxnQkFBZ0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsT0FBTztBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLE9BQU87QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRSxnQkFBZ0I7QUFDbEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQVc7O0FBRVg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsY0FBYzs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix1Q0FBdUM7QUFDakU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVEQUF1RDtBQUM5RTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGNBQWM7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixnQkFBZ0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLCtCQUErQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLE9BQU87QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLE9BQU87QUFDL0M7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLHFDQUFxQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBLFNBQVMsOEJBQThCO0FBQ3ZDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxZQUFZLE9BQU87QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLFdBQVc7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7O0FBSUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCLHNCQUFzQixjQUFjO0FBQ3BDLGdCQUFnQixXQUFXLFlBQVk7QUFDdkMsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFVBQVUsU0FBUyxNQUFNLGFBQWE7QUFDM0UsYUFBYSxlQUFlO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0YsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwrREFBK0Q7QUFDM0U7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsUUFBUSxPQUFPOztBQUVmO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGdCQUFnQjtBQUNsQztBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQSxVQUFVLE9BQU87QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQSxRQUFRLE9BQU87QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsZ0JBQWdCO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osaURBQWlELDBCQUEwQjtBQUMzRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsZ0JBQWdCO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0E7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQSxRQUFRLGdCQUFnQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVMsZ0JBQWdCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLGNBQWM7QUFDbEMsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxrQkFBa0I7QUFDNUIsV0FBVyxrQkFBa0I7QUFDN0IsY0FBYztBQUNkLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSxtQkFBbUI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEOzs7QUFHQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBOztBQUVBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQztBQUMzQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsS0FBSztBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQ0FBcUM7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsS0FBSztBQUNMOztBQUVBLFdBQVc7QUFDWCxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEIsZ0RBQWdEO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakIsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0Esc0JBQXNCO0FBQ3RCLDJCQUEyQjs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHVCQUF1QjtBQUNsQyxXQUFXLHlCQUF5QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFEQUFxRDtBQUNyRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CLDREQUE0RCxlQUFlO0FBQzNFO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGNBQWMsc0RBQXNEO0FBQ3BFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0EsY0FBYyxtQ0FBbUM7QUFDakQsZUFBZSw2REFBNkQ7QUFDNUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLEVBQUU7QUFDRixDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQUE7QUFDRjs7Ozs7QUFLQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDNWdVRDtBQUFBO0FBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSxlQUFlO0FBQzlCLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSwrQkFBK0IsMkJBQTJCO0FBQzFELDBDQUEwQyxlQUFlOztBQUV6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsdUJBQXVCOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLDRCQUE0QjtBQUMxQztBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSx1QkFBdUIsYUFBYSxHQUFHLFdBQVcsR0FBRyxhQUFhLEdBQUcsY0FBYztBQUNuRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBOztBQUVBLENBQUM7Ozs7Ozs7QUN0SkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQyxDQUFDLHFDQUFxQzs7QUFFdEM7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQixrQkFBa0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLHNCQUFzQjtBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1Qzs7QUFFdkM7QUFDQSxlQUFlO0FBQ2Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFO0FBQ2xFOztBQUVBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQsU0FBUzs7QUFFVDtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7O0FBR1Q7QUFDQSxxRUFBcUU7O0FBRXJFO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQzs7QUFFaEMsaUNBQWlDOztBQUVqQyxxQ0FBcUM7O0FBRXJDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOzs7QUFHUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGVBQWU7QUFDZixhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBLHdDQUF3Qzs7QUFFeEM7QUFDQSxzQ0FBc0M7QUFDdEM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUM7O0FBRXJDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUEsNkNBQTZDLFNBQVM7QUFDdEQ7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdEQUFnRCxTQUFTO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUJBQXlCLHdCQUF3QjtBQUNqRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBLGlDQUFpQztBQUNqQywrQ0FBK0M7O0FBRS9DO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsdUNBQXVDOztBQUV2QztBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHdDQUF3QywyRUFBMkU7O0FBRW5IO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0Qjs7QUFFNUIsMkJBQTJCOztBQUUzQix3QkFBd0I7O0FBRXhCLDhCQUE4Qjs7QUFFOUIsZ0NBQWdDOztBQUVoQyxxQ0FBcUM7O0FBRXJDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYLHNEQUFzRDs7QUFFdEQ7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDOztBQUU3QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLDJDQUEyQyx5REFBeUQ7QUFDcEc7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSw2Q0FBNkMsU0FBUztBQUN0RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0Qjs7QUFFNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTOztBQUVUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdHQUFnRzs7QUFFaEc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEVBQUU7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsRUFBRTs7QUFFWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUyxFQUFFOztBQUVYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLGdGQUFnRjs7QUFFeEg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDRFQUE0RTs7QUFFNUU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTzs7QUFFUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7O0FBRTVCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87OztBQUdQOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw4Q0FBOEM7QUFDOUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUTs7O0FBR1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTOztBQUVUO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMseUdBQXlHOztBQUUxSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUwsc0NBQXNDO0FBQ3RDO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhDQUE4Qzs7QUFFOUM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBLE9BQU87OztBQUdQOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBLGlDQUFpQyw2REFBNkQ7O0FBRTlGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsa0NBQWtDLEtBQUs7QUFDdkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLGdEQUFnRDs7O0FBR2hEO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsMkNBQTJDO0FBQzNDOztBQUVBLGtJQUFrSTs7QUFFbEk7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0MsS0FBSztBQUN6Qzs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7O0FBR1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7OztBQUdSO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFROzs7QUFHUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnREFBZ0QsY0FBYzs7QUFFOUQsQ0FBQztBQUNEOzs7Ozs7Ozs7QUN2MkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxlQUFlLGtDQUFrQztBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLFlBQVk7QUFDWjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxJQUFJO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFlBQVk7QUFDdkIsV0FBVyxRQUFRO0FBQ25CLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxvQkFBb0I7QUFDL0I7QUFDQSxXQUFXLE9BQU87QUFDbEIsWUFBWSxPQUFPO0FBQ25COztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixrQkFBa0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7OztBQU1EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsc0JBQXNCO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFlBQVk7QUFDdkIsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsWUFBWTtBQUN2QixXQUFXLE9BQU87QUFDbEIsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBOztBQUVBLG9CQUFvQjtBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsV0FBVztBQUN0QixXQUFXLE1BQU07QUFDakIsV0FBVyxPQUFPO0FBQ2xCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWM7QUFDZCxtQkFBbUI7QUFDbkIsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLHFCQUFxQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEMsZ0JBQWdCOztBQUU1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxnQkFBZ0I7O0FBRXRGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsWUFBWTtBQUN2QixXQUFXLFlBQVk7QUFDdkIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxQkFBcUIseURBQXlEOztBQUU5RTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCO0FBQy9CLDJCQUEyQjtBQUMzQixnQ0FBZ0M7O0FBRWhDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsTUFBTTtBQUNqQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdEQUFnRDs7QUFFaEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1YsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsTUFBTTtBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSx1Q0FBdUM7O0FBRXZDO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxNQUFNO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLGNBQWM7QUFDNUI7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCO0FBQzlCLDRCQUE0QjtBQUM1Qjs7QUFFQSxxQ0FBcUM7QUFDckM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsV0FBVztBQUN6QixjQUFjLE9BQU87QUFDckIsYUFBYSxXQUFXO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxlQUFlLGNBQWM7QUFDN0I7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLGVBQWUsbUJBQW1CO0FBQ2xDO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQTtBQUNBLGNBQWMsYUFBYTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEIsY0FBYyxZQUFZO0FBQzFCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksa0JBQWtCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0Esa0NBQWtDOztBQUVsQztBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFdBQVc7QUFDdEI7O0FBRUE7QUFDQTtBQUNBLFdBQVcsV0FBVztBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLDRCQUE0QjtBQUN6QyxhQUFhLFlBQVk7QUFDekIsYUFBYSxPQUFPO0FBQ3BCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxjQUFjO0FBQ2QsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0IsaURBQWlELHVDQUF1QyxrREFBa0Q7QUFDMUksS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFNBQVM7QUFDdkI7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7O0FDbitFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDOztBQUU1Qzs7Ozs7OztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFBQTtBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQix1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUCx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUEsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUsseUJBQXlCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sNEJBQTRCO0FBQ25DLE9BQU8sdUJBQXVCO0FBQzlCLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGVBQWU7QUFDZixjQUFjO0FBQ2QsY0FBYztBQUNkLGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEIsZ0JBQWdCO0FBQ2hCOztBQUVBO0FBQ0EsVUFBVTtBQUNWLFNBQVM7QUFDVCxTQUFTO0FBQ1QsV0FBVztBQUNYLFdBQVc7QUFDWCxXQUFXO0FBQ1g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsRUFBRTtBQUM1QztBQUNBLG9DQUFvQyxFQUFFLG9CQUFvQixFQUFFO0FBQzVELEtBQUs7QUFDTDtBQUNBO0FBQ0EseUNBQXlDLEVBQUUsK0JBQStCLEVBQUU7QUFDNUUsaURBQWlELEVBQUUscUNBQXFDLEVBQUU7QUFDMUY7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUlBQW1JO0FBQ25JO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDtBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCOztBQUV2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsb0NBQW9DO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGdEQUFnRDtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxFQUFFLDhDQUE4QyxFQUFFO0FBQ3ZGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsOEJBQThCO0FBQzlCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLFFBQVE7QUFDdkIsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLFFBQVE7QUFDdkIsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLDBEQUEwRCxFQUFFO0FBQzVELDZEQUE2RCxFQUFFO0FBQy9EO0FBQ0EseUJBQXlCLElBQUk7QUFDN0I7QUFDQTtBQUNBLDhDQUE4QyxJQUFJO0FBQ2xELG9EQUFvRCxJQUFJO0FBQ3hEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1COztBQUVuQjtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTzs7QUFFUDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQSxvRUFBb0UsRUFBRTtBQUN0RTtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCLGVBQWU7QUFDcEM7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MseURBQXlEO0FBQzNGLHVDQUF1Qyx3R0FBd0c7QUFDL0k7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0gsQ0FBQzs7O0FBR0QsQ0FBQzs7Ozs7OztBQy8wREQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQiw0QkFBNEI7QUFDdkQ7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSw4Q0FBOEMsc0JBQXNCO0FBQ3BFO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDZDQUE2QyxzQ0FBc0M7QUFDbkYsMkNBQTJDLDBDQUEwQzs7QUFFckY7QUFDQTs7QUFFQTs7QUFFQSwrREFBK0Qsc0JBQXNCO0FBQ3JGLEtBQUs7QUFDTDs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQsa0RBQWtEO0FBQ3ZHLCtCQUErQiwwQkFBMEI7QUFDekQsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsNkJBQTZCLHdEQUF3RDtBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsOENBQThDLG1DQUFtQzs7QUFFakY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRzs7QUFFSCxDQUFDOzs7Ozs7OztBQzdaRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQXFEO0FBQ3JEO0FBQ0E7QUFBQTtBQUFBO0FBQUEscUdBQW9DO0FBQ3BDLEtBQUssT0FBTztBQUNaLDJEQUEyRDtBQUMzRDtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hELFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLGFBQWE7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDLE9BQU8sUUFBUSxRQUFRO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHFCQUFxQixHQUFHLGdCQUFnQjtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGdCQUFnQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixvQkFBb0I7QUFDM0M7QUFDQTtBQUNBLGtFQUFrRTtBQUNsRTtBQUNBLDRGQUE0RixjQUFjO0FBQzFHO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsMkNBQTJDO0FBQzNDLG9DQUFvQztBQUNwQyxvQ0FBb0M7QUFDcEMsc0NBQXNDO0FBQ3RDLHNDQUFzQztBQUN0QyxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLDhCQUE4QjtBQUN4RDtBQUNBLGFBQWE7QUFDYiwwQkFBMEIscUNBQXFDO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRCxNQUFNO0FBQ3RELHdEQUF3RCxNQUFNO0FBQzlELHFEQUFxRCxNQUFNO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLFFBQVE7QUFDL0I7QUFDQSwwQ0FBMEMsTUFBTTtBQUNoRCxxQkFBcUIsUUFBUTtBQUM3QjtBQUNBLHlCQUF5QixPQUFPO0FBQ2hDLHlCQUF5QixPQUFPO0FBQ2hDLHlCQUF5QixPQUFPO0FBQ2hDLHlCQUF5QixPQUFPO0FBQ2hDO0FBQ0E7QUFDQSx1QkFBdUIsUUFBUSxnREFBZ0QsT0FBTyxHQUFHLE9BQU8sR0FBRyxPQUFPLEdBQUcsT0FBTztBQUNwSCxrREFBa0QsTUFBTTtBQUN4RCxzQkFBc0IsTUFBTTtBQUM1QixrQ0FBa0MsVUFBVTtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBLDhFQUE4RSxNQUFNO0FBQ3BGO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxLQUFLLHlCQUF5QixNQUFNLFVBQVUsSUFBSTtBQUM1RixrQkFBa0IsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNO0FBQ3hDO0FBQ0Esa0NBQWtDLEtBQUsseUJBQXlCLE1BQU0sVUFBVSxJQUFJLEdBQUcsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNO0FBQzdHO0FBQ0Esc0RBQXNELElBQUksR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDbkY7QUFDQTtBQUNBLHdEQUF3RCxJQUFJO0FBQzVEO0FBQ0E7QUFDQSxnRUFBZ0UsY0FBYyxZQUFZLFlBQVksTUFBTTtBQUM1RyxnREFBZ0QsUUFBUTtBQUN4RDtBQUNBO0FBQ0E7QUFDQSxtRUFBbUUsZUFBZSxnQkFBZ0IsS0FBSyxFQUFFLEtBQUs7QUFDOUc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsTUFBTTtBQUN4QyxrQ0FBa0MsUUFBUSxzREFBc0QsUUFBUSxFQUFFO0FBQzFHLDBCQUEwQixPQUFPO0FBQ2pDO0FBQ0E7QUFDQSw4QkFBOEIsU0FBUztBQUN2QztBQUNBLDhEQUE4RCxRQUFRLEdBQUcsUUFBUSxLQUFLLEtBQUs7QUFDM0Ysc0JBQXNCLFNBQVMsRUFBRSxVQUFVLEVBQUUsUUFBUTtBQUNyRDtBQUNBLHlCQUF5QixLQUFLO0FBQzlCO0FBQ0E7QUFDQSwwQkFBMEIsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTTtBQUN6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBFQUEwRSxZQUFZO0FBQ3RGLHlCQUF5QixZQUFZLEdBQUcsU0FBUyxRQUFRLEVBQUUsV0FBVztBQUN0RSwwRUFBMEUsWUFBWSxVQUFVLFlBQVk7QUFDNUcsa0JBQWtCLFdBQVc7QUFDN0Isc0VBQXNFLFVBQVU7QUFDaEYseUJBQXlCLFVBQVUsR0FBRyxTQUFTO0FBQy9DLDBEQUEwRCxVQUFVLFVBQVUsVUFBVSxHQUFHLFNBQVM7QUFDcEcscUVBQXFFLGVBQWUsR0FBRyxVQUFVO0FBQ2pHLHVEQUF1RCxXQUFXLE9BQU8sVUFBVSxtQkFBbUIsVUFBVTtBQUNoSCxrQ0FBa0MsU0FBUztBQUMzQztBQUNBLDJDQUEyQyxRQUFRO0FBQ25ELDhCQUE4QixPQUFPO0FBQ3JDLHlCQUF5QixRQUFRO0FBQ2pDLDRFQUE0RSxRQUFRO0FBQ3BGLG1CQUFtQixLQUFLO0FBQ3hCLGlDQUFpQyxLQUFLLHFEQUFxRCxRQUFRLFFBQVEsUUFBUTtBQUNuSDtBQUNBLGlGQUFpRixRQUFRO0FBQ3pGLHNDQUFzQyxLQUFLO0FBQzNDLGdGQUFnRixNQUFNO0FBQ3RGLDBCQUEwQixPQUFPLGdDQUFnQyxLQUFLLFNBQVMsS0FBSztBQUNwRjtBQUNBLDhHQUE4RyxLQUFLO0FBQ25ILHdCQUF3QixLQUFLO0FBQzdCO0FBQ0EseUJBQXlCLE1BQU0sV0FBVyxPQUFPLFNBQVMsS0FBSztBQUMvRDtBQUNBLG1FQUFtRSxRQUFRLFNBQVMsS0FBSyxTQUFTLEtBQUs7QUFDdkcseUJBQXlCLE1BQU0sV0FBVyxPQUFPLHFDQUFxQyxRQUFRO0FBQzlGO0FBQ0EseURBQXlELEtBQUs7QUFDOUQseUJBQXlCLE1BQU0sV0FBVyxPQUFPO0FBQ2pEO0FBQ0EsMkVBQTJFLFlBQVk7QUFDdkYsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLG9DQUFvQztBQUNwQztBQUNBLDRCQUE0QiwrQkFBK0I7QUFDM0QsMkJBQTJCLGdDQUFnQztBQUMzRCwyQkFBMkIsZ0NBQWdDO0FBQzNELDRCQUE0QixtREFBbUQ7QUFDL0UsNEJBQTRCLDhCQUE4QjtBQUMxRCw0QkFBNEIsbURBQW1EO0FBQy9FLDZCQUE2QixlQUFlO0FBQzVDLDBCQUEwQixnQ0FBZ0M7QUFDMUQsNEJBQTRCO0FBQzVCLGlCQUFpQjtBQUNqQjtBQUNBLDRCQUE0Qix5RUFBeUU7QUFDckc7QUFDQTtBQUNBLDRCQUE0QixtREFBbUQ7QUFDL0UsNEJBQTRCLDhCQUE4QjtBQUMxRCw0QkFBNEIsK0JBQStCO0FBQzNELDZCQUE2QiwwRUFBMEU7QUFDdkc7QUFDQSw0QkFBNEI7QUFDNUIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7QUFDN0MsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSx3Q0FBd0MsMkJBQTJCO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsb0JBQW9CO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLG1CQUFtQjtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxpQkFBaUI7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQztBQUNBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLDhDQUE4QyxLQUFLO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0QsRUFBRTtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHFEQUFxRCxFQUFFLGdDQUFnQyxNQUFNO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxVQUFVO0FBQy9EO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLGtCQUFrQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSw4QkFBOEIsZ0JBQWdCO0FBQzlDLHFDQUFxQywwRUFBMEU7QUFDL0c7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEUsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHNDQUFzQztBQUN6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsU0FBUztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQywyQ0FBMkM7QUFDdEYsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxzREFBc0QsRUFBRSxnQkFBZ0IsTUFBTTtBQUM5RSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBLHVCQUF1QiwyQkFBMkI7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFGQUFxRix3QkFBd0I7QUFDN0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLHNCQUFzQjtBQUM3RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRkFBc0YsVUFBVTtBQUNoRztBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLHNGQUFzRjtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRixVQUFVO0FBQ3JHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRixVQUFVO0FBQ3JHO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBLG1HQUFtRztBQUNuRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQiw0Q0FBNEM7QUFDNUM7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLEdBQUcsVUFBVTtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZELFNBQVM7QUFDdEUsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdGQUFnRixZQUFZO0FBQzVGO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RCwyQkFBMkI7QUFDekY7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLGlDQUFpQztBQUM5RDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSw2RUFBNkUsRUFBRTtBQUMvRSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxxQkFBcUIsSUFBSSxXQUFXLDRCQUE0QjtBQUM5Ryw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixZQUFZO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNERBQTRELEtBQUs7QUFDakU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0Isc0JBQXNCO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpRUFBaUUsbUNBQW1DO0FBQ3BHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRUFBc0Usc0NBQXNDO0FBQzVHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0QsTUFBTSxvQkFBb0IsTUFBTTtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHVEQUF1RDtBQUNyRyxpQkFBaUI7QUFDakIsOENBQThDLG9FQUFvRTtBQUNsSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsTUFBTTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsNkJBQTZCO0FBQ3hGO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQSwyQ0FBMkMsT0FBTztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLDhCQUE4QjtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsc0JBQXNCO0FBQ2hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsc0JBQXNCO0FBQ2hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZELE9BQU87QUFDcEUsaUNBQWlDLHNCQUFzQjtBQUN2RDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSx3Q0FBd0MsbUVBQW1FO0FBQzNHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQyxpREFBaUQ7QUFDakY7QUFDQSwwREFBMEQsdUNBQXVDO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWIsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZFQUE2RSxLQUFLO0FBQ2xGLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsOENBQThDO0FBQy9GO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QywwQ0FBMEM7QUFDdEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtFQUFrRSxnQkFBZ0I7QUFDbEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUZBQXVGO0FBQ3ZGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMscUJBQXFCLElBQUksV0FBVyw0QkFBNEI7QUFDOUcsOEJBQThCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBLCtDQUErQywwQ0FBMEM7QUFDekYsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQsRUFBRSxnQ0FBZ0MsRUFBRTtBQUM3RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLHdEQUF3RDtBQUN6RjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlDQUFpQyxvQ0FBb0M7QUFDckU7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixTQUFTO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0EsMkJBQTJCLFNBQVM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsMkJBQTJCLFNBQVM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRUFBbUUsUUFBUTtBQUMzRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DLGtDQUFrQztBQUNsQztBQUNBLDBFQUEwRTtBQUMxRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxRUFBcUU7QUFDckU7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEIsOEJBQThCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsS0FBSyxPQUFPLEtBQUssa0RBQWtELFFBQVE7QUFDNUcsaUNBQWlDLEtBQUssT0FBTyxLQUFLLG9EQUFvRCxRQUFRO0FBQzlHLHVEQUF1RCxFQUFFLE1BQU0sTUFBTTtBQUNyRSxtRUFBbUUsRUFBRSwyQ0FBMkMsRUFBRTtBQUNsSCxpQ0FBaUMsS0FBSztBQUN0QywwRUFBMEUsS0FBSztBQUMvRSxvQ0FBb0MsS0FBSztBQUN6QywyREFBMkQsS0FBSztBQUNoRSx5RUFBeUUsS0FBSztBQUM5RSw4RUFBOEUsS0FBSztBQUNuRixxREFBcUQsS0FBSyxVQUFVLE1BQU07QUFDMUUsK0RBQStELEtBQUssVUFBVSxXQUFXO0FBQ3pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsTUFBTSxLQUFLLE1BQU0sU0FBUztBQUM3RCxvQ0FBb0MsTUFBTSxLQUFLLE1BQU0sSUFBSSxLQUFLLElBQUksUUFBUTtBQUMxRSx1QkFBdUIsRUFBRSxFQUFFLE1BQU07QUFDakMsd0RBQXdELEVBQUU7QUFDMUQsbURBQW1ELEtBQUssb0JBQW9CLEtBQUs7QUFDakYscURBQXFELEtBQUssb0JBQW9CLEtBQUs7QUFDbkYsbURBQW1ELEtBQUssaUJBQWlCLEtBQUs7QUFDOUUscURBQXFELEtBQUssaUJBQWlCLEtBQUs7QUFDaEY7QUFDQSx1RUFBdUUsT0FBTztBQUM5RSxzREFBc0QsVUFBVTtBQUNoRSxnQ0FBZ0MsVUFBVTtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULHVEQUF1RDtBQUN2RCxzREFBc0QsTUFBTTtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxDQUFDLEc7Ozs7OztBQzMxSEQseUM7Ozs7OztBQ0FBLHlDOzs7Ozs7QUNBQSx5Qzs7Ozs7O0FDQUEseUM7Ozs7OztBQ0FBLHlDIiwiZmlsZSI6Im1haW4uYnVuZGxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay9ib290c3RyYXAgNzYwN2Y0OTU5MTc4OTdhNzUyNGIiLCIvKiFcbiAqIGpRdWVyeSBKYXZhU2NyaXB0IExpYnJhcnkgdjMuMi4xXG4gKiBodHRwczovL2pxdWVyeS5jb20vXG4gKlxuICogSW5jbHVkZXMgU2l6emxlLmpzXG4gKiBodHRwczovL3NpenpsZWpzLmNvbS9cbiAqXG4gKiBDb3B5cmlnaHQgSlMgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIGh0dHBzOi8vanF1ZXJ5Lm9yZy9saWNlbnNlXG4gKlxuICogRGF0ZTogMjAxNy0wMy0yMFQxODo1OVpcbiAqL1xuKCBmdW5jdGlvbiggZ2xvYmFsLCBmYWN0b3J5ICkge1xuXG5cdFwidXNlIHN0cmljdFwiO1xuXG5cdGlmICggdHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgPT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHQvLyBGb3IgQ29tbW9uSlMgYW5kIENvbW1vbkpTLWxpa2UgZW52aXJvbm1lbnRzIHdoZXJlIGEgcHJvcGVyIGB3aW5kb3dgXG5cdFx0Ly8gaXMgcHJlc2VudCwgZXhlY3V0ZSB0aGUgZmFjdG9yeSBhbmQgZ2V0IGpRdWVyeS5cblx0XHQvLyBGb3IgZW52aXJvbm1lbnRzIHRoYXQgZG8gbm90IGhhdmUgYSBgd2luZG93YCB3aXRoIGEgYGRvY3VtZW50YFxuXHRcdC8vIChzdWNoIGFzIE5vZGUuanMpLCBleHBvc2UgYSBmYWN0b3J5IGFzIG1vZHVsZS5leHBvcnRzLlxuXHRcdC8vIFRoaXMgYWNjZW50dWF0ZXMgdGhlIG5lZWQgZm9yIHRoZSBjcmVhdGlvbiBvZiBhIHJlYWwgYHdpbmRvd2AuXG5cdFx0Ly8gZS5nLiB2YXIgalF1ZXJ5ID0gcmVxdWlyZShcImpxdWVyeVwiKSh3aW5kb3cpO1xuXHRcdC8vIFNlZSB0aWNrZXQgIzE0NTQ5IGZvciBtb3JlIGluZm8uXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBnbG9iYWwuZG9jdW1lbnQgP1xuXHRcdFx0ZmFjdG9yeSggZ2xvYmFsLCB0cnVlICkgOlxuXHRcdFx0ZnVuY3Rpb24oIHcgKSB7XG5cdFx0XHRcdGlmICggIXcuZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcImpRdWVyeSByZXF1aXJlcyBhIHdpbmRvdyB3aXRoIGEgZG9jdW1lbnRcIiApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmYWN0b3J5KCB3ICk7XG5cdFx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdGZhY3RvcnkoIGdsb2JhbCApO1xuXHR9XG5cbi8vIFBhc3MgdGhpcyBpZiB3aW5kb3cgaXMgbm90IGRlZmluZWQgeWV0XG59ICkoIHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0aGlzLCBmdW5jdGlvbiggd2luZG93LCBub0dsb2JhbCApIHtcblxuLy8gRWRnZSA8PSAxMiAtIDEzKywgRmlyZWZveCA8PTE4IC0gNDUrLCBJRSAxMCAtIDExLCBTYWZhcmkgNS4xIC0gOSssIGlPUyA2IC0gOS4xXG4vLyB0aHJvdyBleGNlcHRpb25zIHdoZW4gbm9uLXN0cmljdCBjb2RlIChlLmcuLCBBU1AuTkVUIDQuNSkgYWNjZXNzZXMgc3RyaWN0IG1vZGVcbi8vIGFyZ3VtZW50cy5jYWxsZWUuY2FsbGVyICh0cmFjLTEzMzM1KS4gQnV0IGFzIG9mIGpRdWVyeSAzLjAgKDIwMTYpLCBzdHJpY3QgbW9kZSBzaG91bGQgYmUgY29tbW9uXG4vLyBlbm91Z2ggdGhhdCBhbGwgc3VjaCBhdHRlbXB0cyBhcmUgZ3VhcmRlZCBpbiBhIHRyeSBibG9jay5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgYXJyID0gW107XG5cbnZhciBkb2N1bWVudCA9IHdpbmRvdy5kb2N1bWVudDtcblxudmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mO1xuXG52YXIgc2xpY2UgPSBhcnIuc2xpY2U7XG5cbnZhciBjb25jYXQgPSBhcnIuY29uY2F0O1xuXG52YXIgcHVzaCA9IGFyci5wdXNoO1xuXG52YXIgaW5kZXhPZiA9IGFyci5pbmRleE9mO1xuXG52YXIgY2xhc3MydHlwZSA9IHt9O1xuXG52YXIgdG9TdHJpbmcgPSBjbGFzczJ0eXBlLnRvU3RyaW5nO1xuXG52YXIgaGFzT3duID0gY2xhc3MydHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxudmFyIGZuVG9TdHJpbmcgPSBoYXNPd24udG9TdHJpbmc7XG5cbnZhciBPYmplY3RGdW5jdGlvblN0cmluZyA9IGZuVG9TdHJpbmcuY2FsbCggT2JqZWN0ICk7XG5cbnZhciBzdXBwb3J0ID0ge307XG5cblxuXG5cdGZ1bmN0aW9uIERPTUV2YWwoIGNvZGUsIGRvYyApIHtcblx0XHRkb2MgPSBkb2MgfHwgZG9jdW1lbnQ7XG5cblx0XHR2YXIgc2NyaXB0ID0gZG9jLmNyZWF0ZUVsZW1lbnQoIFwic2NyaXB0XCIgKTtcblxuXHRcdHNjcmlwdC50ZXh0ID0gY29kZTtcblx0XHRkb2MuaGVhZC5hcHBlbmRDaGlsZCggc2NyaXB0ICkucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggc2NyaXB0ICk7XG5cdH1cbi8qIGdsb2JhbCBTeW1ib2wgKi9cbi8vIERlZmluaW5nIHRoaXMgZ2xvYmFsIGluIC5lc2xpbnRyYy5qc29uIHdvdWxkIGNyZWF0ZSBhIGRhbmdlciBvZiB1c2luZyB0aGUgZ2xvYmFsXG4vLyB1bmd1YXJkZWQgaW4gYW5vdGhlciBwbGFjZSwgaXQgc2VlbXMgc2FmZXIgdG8gZGVmaW5lIGdsb2JhbCBvbmx5IGZvciB0aGlzIG1vZHVsZVxuXG5cblxudmFyXG5cdHZlcnNpb24gPSBcIjMuMi4xXCIsXG5cblx0Ly8gRGVmaW5lIGEgbG9jYWwgY29weSBvZiBqUXVlcnlcblx0alF1ZXJ5ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0ICkge1xuXG5cdFx0Ly8gVGhlIGpRdWVyeSBvYmplY3QgaXMgYWN0dWFsbHkganVzdCB0aGUgaW5pdCBjb25zdHJ1Y3RvciAnZW5oYW5jZWQnXG5cdFx0Ly8gTmVlZCBpbml0IGlmIGpRdWVyeSBpcyBjYWxsZWQgKGp1c3QgYWxsb3cgZXJyb3IgdG8gYmUgdGhyb3duIGlmIG5vdCBpbmNsdWRlZClcblx0XHRyZXR1cm4gbmV3IGpRdWVyeS5mbi5pbml0KCBzZWxlY3RvciwgY29udGV4dCApO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seVxuXHQvLyBNYWtlIHN1cmUgd2UgdHJpbSBCT00gYW5kIE5CU1Bcblx0cnRyaW0gPSAvXltcXHNcXHVGRUZGXFx4QTBdK3xbXFxzXFx1RkVGRlxceEEwXSskL2csXG5cblx0Ly8gTWF0Y2hlcyBkYXNoZWQgc3RyaW5nIGZvciBjYW1lbGl6aW5nXG5cdHJtc1ByZWZpeCA9IC9eLW1zLS8sXG5cdHJkYXNoQWxwaGEgPSAvLShbYS16XSkvZyxcblxuXHQvLyBVc2VkIGJ5IGpRdWVyeS5jYW1lbENhc2UgYXMgY2FsbGJhY2sgdG8gcmVwbGFjZSgpXG5cdGZjYW1lbENhc2UgPSBmdW5jdGlvbiggYWxsLCBsZXR0ZXIgKSB7XG5cdFx0cmV0dXJuIGxldHRlci50b1VwcGVyQ2FzZSgpO1xuXHR9O1xuXG5qUXVlcnkuZm4gPSBqUXVlcnkucHJvdG90eXBlID0ge1xuXG5cdC8vIFRoZSBjdXJyZW50IHZlcnNpb24gb2YgalF1ZXJ5IGJlaW5nIHVzZWRcblx0anF1ZXJ5OiB2ZXJzaW9uLFxuXG5cdGNvbnN0cnVjdG9yOiBqUXVlcnksXG5cblx0Ly8gVGhlIGRlZmF1bHQgbGVuZ3RoIG9mIGEgalF1ZXJ5IG9iamVjdCBpcyAwXG5cdGxlbmd0aDogMCxcblxuXHR0b0FycmF5OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2xpY2UuY2FsbCggdGhpcyApO1xuXHR9LFxuXG5cdC8vIEdldCB0aGUgTnRoIGVsZW1lbnQgaW4gdGhlIG1hdGNoZWQgZWxlbWVudCBzZXQgT1Jcblx0Ly8gR2V0IHRoZSB3aG9sZSBtYXRjaGVkIGVsZW1lbnQgc2V0IGFzIGEgY2xlYW4gYXJyYXlcblx0Z2V0OiBmdW5jdGlvbiggbnVtICkge1xuXG5cdFx0Ly8gUmV0dXJuIGFsbCB0aGUgZWxlbWVudHMgaW4gYSBjbGVhbiBhcnJheVxuXHRcdGlmICggbnVtID09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gc2xpY2UuY2FsbCggdGhpcyApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiBqdXN0IHRoZSBvbmUgZWxlbWVudCBmcm9tIHRoZSBzZXRcblx0XHRyZXR1cm4gbnVtIDwgMCA/IHRoaXNbIG51bSArIHRoaXMubGVuZ3RoIF0gOiB0aGlzWyBudW0gXTtcblx0fSxcblxuXHQvLyBUYWtlIGFuIGFycmF5IG9mIGVsZW1lbnRzIGFuZCBwdXNoIGl0IG9udG8gdGhlIHN0YWNrXG5cdC8vIChyZXR1cm5pbmcgdGhlIG5ldyBtYXRjaGVkIGVsZW1lbnQgc2V0KVxuXHRwdXNoU3RhY2s6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblxuXHRcdC8vIEJ1aWxkIGEgbmV3IGpRdWVyeSBtYXRjaGVkIGVsZW1lbnQgc2V0XG5cdFx0dmFyIHJldCA9IGpRdWVyeS5tZXJnZSggdGhpcy5jb25zdHJ1Y3RvcigpLCBlbGVtcyApO1xuXG5cdFx0Ly8gQWRkIHRoZSBvbGQgb2JqZWN0IG9udG8gdGhlIHN0YWNrIChhcyBhIHJlZmVyZW5jZSlcblx0XHRyZXQucHJldk9iamVjdCA9IHRoaXM7XG5cblx0XHQvLyBSZXR1cm4gdGhlIG5ld2x5LWZvcm1lZCBlbGVtZW50IHNldFxuXHRcdHJldHVybiByZXQ7XG5cdH0sXG5cblx0Ly8gRXhlY3V0ZSBhIGNhbGxiYWNrIGZvciBldmVyeSBlbGVtZW50IGluIHRoZSBtYXRjaGVkIHNldC5cblx0ZWFjaDogZnVuY3Rpb24oIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZWFjaCggdGhpcywgY2FsbGJhY2sgKTtcblx0fSxcblxuXHRtYXA6IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGpRdWVyeS5tYXAoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCBpICkge1xuXHRcdFx0cmV0dXJuIGNhbGxiYWNrLmNhbGwoIGVsZW0sIGksIGVsZW0gKTtcblx0XHR9ICkgKTtcblx0fSxcblxuXHRzbGljZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBzbGljZS5hcHBseSggdGhpcywgYXJndW1lbnRzICkgKTtcblx0fSxcblxuXHRmaXJzdDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZXEoIDAgKTtcblx0fSxcblxuXHRsYXN0OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5lcSggLTEgKTtcblx0fSxcblxuXHRlcTogZnVuY3Rpb24oIGkgKSB7XG5cdFx0dmFyIGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0aiA9ICtpICsgKCBpIDwgMCA/IGxlbiA6IDAgKTtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIGogPj0gMCAmJiBqIDwgbGVuID8gWyB0aGlzWyBqIF0gXSA6IFtdICk7XG5cdH0sXG5cblx0ZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5wcmV2T2JqZWN0IHx8IHRoaXMuY29uc3RydWN0b3IoKTtcblx0fSxcblxuXHQvLyBGb3IgaW50ZXJuYWwgdXNlIG9ubHkuXG5cdC8vIEJlaGF2ZXMgbGlrZSBhbiBBcnJheSdzIG1ldGhvZCwgbm90IGxpa2UgYSBqUXVlcnkgbWV0aG9kLlxuXHRwdXNoOiBwdXNoLFxuXHRzb3J0OiBhcnIuc29ydCxcblx0c3BsaWNlOiBhcnIuc3BsaWNlXG59O1xuXG5qUXVlcnkuZXh0ZW5kID0galF1ZXJ5LmZuLmV4dGVuZCA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgb3B0aW9ucywgbmFtZSwgc3JjLCBjb3B5LCBjb3B5SXNBcnJheSwgY2xvbmUsXG5cdFx0dGFyZ2V0ID0gYXJndW1lbnRzWyAwIF0gfHwge30sXG5cdFx0aSA9IDEsXG5cdFx0bGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcblx0XHRkZWVwID0gZmFsc2U7XG5cblx0Ly8gSGFuZGxlIGEgZGVlcCBjb3B5IHNpdHVhdGlvblxuXHRpZiAoIHR5cGVvZiB0YXJnZXQgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdGRlZXAgPSB0YXJnZXQ7XG5cblx0XHQvLyBTa2lwIHRoZSBib29sZWFuIGFuZCB0aGUgdGFyZ2V0XG5cdFx0dGFyZ2V0ID0gYXJndW1lbnRzWyBpIF0gfHwge307XG5cdFx0aSsrO1xuXHR9XG5cblx0Ly8gSGFuZGxlIGNhc2Ugd2hlbiB0YXJnZXQgaXMgYSBzdHJpbmcgb3Igc29tZXRoaW5nIChwb3NzaWJsZSBpbiBkZWVwIGNvcHkpXG5cdGlmICggdHlwZW9mIHRhcmdldCAhPT0gXCJvYmplY3RcIiAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIHRhcmdldCApICkge1xuXHRcdHRhcmdldCA9IHt9O1xuXHR9XG5cblx0Ly8gRXh0ZW5kIGpRdWVyeSBpdHNlbGYgaWYgb25seSBvbmUgYXJndW1lbnQgaXMgcGFzc2VkXG5cdGlmICggaSA9PT0gbGVuZ3RoICkge1xuXHRcdHRhcmdldCA9IHRoaXM7XG5cdFx0aS0tO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cblx0XHQvLyBPbmx5IGRlYWwgd2l0aCBub24tbnVsbC91bmRlZmluZWQgdmFsdWVzXG5cdFx0aWYgKCAoIG9wdGlvbnMgPSBhcmd1bWVudHNbIGkgXSApICE9IG51bGwgKSB7XG5cblx0XHRcdC8vIEV4dGVuZCB0aGUgYmFzZSBvYmplY3Rcblx0XHRcdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRcdFx0c3JjID0gdGFyZ2V0WyBuYW1lIF07XG5cdFx0XHRcdGNvcHkgPSBvcHRpb25zWyBuYW1lIF07XG5cblx0XHRcdFx0Ly8gUHJldmVudCBuZXZlci1lbmRpbmcgbG9vcFxuXHRcdFx0XHRpZiAoIHRhcmdldCA9PT0gY29weSApIHtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFJlY3Vyc2UgaWYgd2UncmUgbWVyZ2luZyBwbGFpbiBvYmplY3RzIG9yIGFycmF5c1xuXHRcdFx0XHRpZiAoIGRlZXAgJiYgY29weSAmJiAoIGpRdWVyeS5pc1BsYWluT2JqZWN0KCBjb3B5ICkgfHxcblx0XHRcdFx0XHQoIGNvcHlJc0FycmF5ID0gQXJyYXkuaXNBcnJheSggY29weSApICkgKSApIHtcblxuXHRcdFx0XHRcdGlmICggY29weUlzQXJyYXkgKSB7XG5cdFx0XHRcdFx0XHRjb3B5SXNBcnJheSA9IGZhbHNlO1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgQXJyYXkuaXNBcnJheSggc3JjICkgPyBzcmMgOiBbXTtcblxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjbG9uZSA9IHNyYyAmJiBqUXVlcnkuaXNQbGFpbk9iamVjdCggc3JjICkgPyBzcmMgOiB7fTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBOZXZlciBtb3ZlIG9yaWdpbmFsIG9iamVjdHMsIGNsb25lIHRoZW1cblx0XHRcdFx0XHR0YXJnZXRbIG5hbWUgXSA9IGpRdWVyeS5leHRlbmQoIGRlZXAsIGNsb25lLCBjb3B5ICk7XG5cblx0XHRcdFx0Ly8gRG9uJ3QgYnJpbmcgaW4gdW5kZWZpbmVkIHZhbHVlc1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb3B5ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBjb3B5O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmV0dXJuIHRoZSBtb2RpZmllZCBvYmplY3Rcblx0cmV0dXJuIHRhcmdldDtcbn07XG5cbmpRdWVyeS5leHRlbmQoIHtcblxuXHQvLyBVbmlxdWUgZm9yIGVhY2ggY29weSBvZiBqUXVlcnkgb24gdGhlIHBhZ2Vcblx0ZXhwYW5kbzogXCJqUXVlcnlcIiArICggdmVyc2lvbiArIE1hdGgucmFuZG9tKCkgKS5yZXBsYWNlKCAvXFxEL2csIFwiXCIgKSxcblxuXHQvLyBBc3N1bWUgalF1ZXJ5IGlzIHJlYWR5IHdpdGhvdXQgdGhlIHJlYWR5IG1vZHVsZVxuXHRpc1JlYWR5OiB0cnVlLFxuXG5cdGVycm9yOiBmdW5jdGlvbiggbXNnICkge1xuXHRcdHRocm93IG5ldyBFcnJvciggbXNnICk7XG5cdH0sXG5cblx0bm9vcDogZnVuY3Rpb24oKSB7fSxcblxuXHRpc0Z1bmN0aW9uOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdHJldHVybiBqUXVlcnkudHlwZSggb2JqICkgPT09IFwiZnVuY3Rpb25cIjtcblx0fSxcblxuXHRpc1dpbmRvdzogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4gb2JqICE9IG51bGwgJiYgb2JqID09PSBvYmoud2luZG93O1xuXHR9LFxuXG5cdGlzTnVtZXJpYzogZnVuY3Rpb24oIG9iaiApIHtcblxuXHRcdC8vIEFzIG9mIGpRdWVyeSAzLjAsIGlzTnVtZXJpYyBpcyBsaW1pdGVkIHRvXG5cdFx0Ly8gc3RyaW5ncyBhbmQgbnVtYmVycyAocHJpbWl0aXZlcyBvciBvYmplY3RzKVxuXHRcdC8vIHRoYXQgY2FuIGJlIGNvZXJjZWQgdG8gZmluaXRlIG51bWJlcnMgKGdoLTI2NjIpXG5cdFx0dmFyIHR5cGUgPSBqUXVlcnkudHlwZSggb2JqICk7XG5cdFx0cmV0dXJuICggdHlwZSA9PT0gXCJudW1iZXJcIiB8fCB0eXBlID09PSBcInN0cmluZ1wiICkgJiZcblxuXHRcdFx0Ly8gcGFyc2VGbG9hdCBOYU5zIG51bWVyaWMtY2FzdCBmYWxzZSBwb3NpdGl2ZXMgKFwiXCIpXG5cdFx0XHQvLyAuLi5idXQgbWlzaW50ZXJwcmV0cyBsZWFkaW5nLW51bWJlciBzdHJpbmdzLCBwYXJ0aWN1bGFybHkgaGV4IGxpdGVyYWxzIChcIjB4Li4uXCIpXG5cdFx0XHQvLyBzdWJ0cmFjdGlvbiBmb3JjZXMgaW5maW5pdGllcyB0byBOYU5cblx0XHRcdCFpc05hTiggb2JqIC0gcGFyc2VGbG9hdCggb2JqICkgKTtcblx0fSxcblxuXHRpc1BsYWluT2JqZWN0OiBmdW5jdGlvbiggb2JqICkge1xuXHRcdHZhciBwcm90bywgQ3RvcjtcblxuXHRcdC8vIERldGVjdCBvYnZpb3VzIG5lZ2F0aXZlc1xuXHRcdC8vIFVzZSB0b1N0cmluZyBpbnN0ZWFkIG9mIGpRdWVyeS50eXBlIHRvIGNhdGNoIGhvc3Qgb2JqZWN0c1xuXHRcdGlmICggIW9iaiB8fCB0b1N0cmluZy5jYWxsKCBvYmogKSAhPT0gXCJbb2JqZWN0IE9iamVjdF1cIiApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRwcm90byA9IGdldFByb3RvKCBvYmogKTtcblxuXHRcdC8vIE9iamVjdHMgd2l0aCBubyBwcm90b3R5cGUgKGUuZy4sIGBPYmplY3QuY3JlYXRlKCBudWxsIClgKSBhcmUgcGxhaW5cblx0XHRpZiAoICFwcm90byApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIE9iamVjdHMgd2l0aCBwcm90b3R5cGUgYXJlIHBsYWluIGlmZiB0aGV5IHdlcmUgY29uc3RydWN0ZWQgYnkgYSBnbG9iYWwgT2JqZWN0IGZ1bmN0aW9uXG5cdFx0Q3RvciA9IGhhc093bi5jYWxsKCBwcm90bywgXCJjb25zdHJ1Y3RvclwiICkgJiYgcHJvdG8uY29uc3RydWN0b3I7XG5cdFx0cmV0dXJuIHR5cGVvZiBDdG9yID09PSBcImZ1bmN0aW9uXCIgJiYgZm5Ub1N0cmluZy5jYWxsKCBDdG9yICkgPT09IE9iamVjdEZ1bmN0aW9uU3RyaW5nO1xuXHR9LFxuXG5cdGlzRW1wdHlPYmplY3Q6IGZ1bmN0aW9uKCBvYmogKSB7XG5cblx0XHQvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuXHRcdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZXNsaW50L2VzbGludC9pc3N1ZXMvNjEyNVxuXHRcdHZhciBuYW1lO1xuXG5cdFx0Zm9yICggbmFtZSBpbiBvYmogKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9LFxuXG5cdHR5cGU6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0aWYgKCBvYmogPT0gbnVsbCApIHtcblx0XHRcdHJldHVybiBvYmogKyBcIlwiO1xuXHRcdH1cblxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD0yLjMgb25seSAoZnVuY3Rpb25pc2ggUmVnRXhwKVxuXHRcdHJldHVybiB0eXBlb2Ygb2JqID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiA/XG5cdFx0XHRjbGFzczJ0eXBlWyB0b1N0cmluZy5jYWxsKCBvYmogKSBdIHx8IFwib2JqZWN0XCIgOlxuXHRcdFx0dHlwZW9mIG9iajtcblx0fSxcblxuXHQvLyBFdmFsdWF0ZXMgYSBzY3JpcHQgaW4gYSBnbG9iYWwgY29udGV4dFxuXHRnbG9iYWxFdmFsOiBmdW5jdGlvbiggY29kZSApIHtcblx0XHRET01FdmFsKCBjb2RlICk7XG5cdH0sXG5cblx0Ly8gQ29udmVydCBkYXNoZWQgdG8gY2FtZWxDYXNlOyB1c2VkIGJ5IHRoZSBjc3MgYW5kIGRhdGEgbW9kdWxlc1xuXHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSwgRWRnZSAxMiAtIDEzXG5cdC8vIE1pY3Jvc29mdCBmb3Jnb3QgdG8gaHVtcCB0aGVpciB2ZW5kb3IgcHJlZml4ICgjOTU3Milcblx0Y2FtZWxDYXNlOiBmdW5jdGlvbiggc3RyaW5nICkge1xuXHRcdHJldHVybiBzdHJpbmcucmVwbGFjZSggcm1zUHJlZml4LCBcIm1zLVwiICkucmVwbGFjZSggcmRhc2hBbHBoYSwgZmNhbWVsQ2FzZSApO1xuXHR9LFxuXG5cdGVhY2g6IGZ1bmN0aW9uKCBvYmosIGNhbGxiYWNrICkge1xuXHRcdHZhciBsZW5ndGgsIGkgPSAwO1xuXG5cdFx0aWYgKCBpc0FycmF5TGlrZSggb2JqICkgKSB7XG5cdFx0XHRsZW5ndGggPSBvYmoubGVuZ3RoO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2suY2FsbCggb2JqWyBpIF0sIGksIG9ialsgaSBdICkgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAoIGkgaW4gb2JqICkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBvYmo7XG5cdH0sXG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5XG5cdHRyaW06IGZ1bmN0aW9uKCB0ZXh0ICkge1xuXHRcdHJldHVybiB0ZXh0ID09IG51bGwgP1xuXHRcdFx0XCJcIiA6XG5cdFx0XHQoIHRleHQgKyBcIlwiICkucmVwbGFjZSggcnRyaW0sIFwiXCIgKTtcblx0fSxcblxuXHQvLyByZXN1bHRzIGlzIGZvciBpbnRlcm5hbCB1c2FnZSBvbmx5XG5cdG1ha2VBcnJheTogZnVuY3Rpb24oIGFyciwgcmVzdWx0cyApIHtcblx0XHR2YXIgcmV0ID0gcmVzdWx0cyB8fCBbXTtcblxuXHRcdGlmICggYXJyICE9IG51bGwgKSB7XG5cdFx0XHRpZiAoIGlzQXJyYXlMaWtlKCBPYmplY3QoIGFyciApICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggcmV0LFxuXHRcdFx0XHRcdHR5cGVvZiBhcnIgPT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFsgYXJyIF0gOiBhcnJcblx0XHRcdFx0KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHB1c2guY2FsbCggcmV0LCBhcnIgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdGluQXJyYXk6IGZ1bmN0aW9uKCBlbGVtLCBhcnIsIGkgKSB7XG5cdFx0cmV0dXJuIGFyciA9PSBudWxsID8gLTEgOiBpbmRleE9mLmNhbGwoIGFyciwgZWxlbSwgaSApO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdG1lcmdlOiBmdW5jdGlvbiggZmlyc3QsIHNlY29uZCApIHtcblx0XHR2YXIgbGVuID0gK3NlY29uZC5sZW5ndGgsXG5cdFx0XHRqID0gMCxcblx0XHRcdGkgPSBmaXJzdC5sZW5ndGg7XG5cblx0XHRmb3IgKCA7IGogPCBsZW47IGorKyApIHtcblx0XHRcdGZpcnN0WyBpKysgXSA9IHNlY29uZFsgaiBdO1xuXHRcdH1cblxuXHRcdGZpcnN0Lmxlbmd0aCA9IGk7XG5cblx0XHRyZXR1cm4gZmlyc3Q7XG5cdH0sXG5cblx0Z3JlcDogZnVuY3Rpb24oIGVsZW1zLCBjYWxsYmFjaywgaW52ZXJ0ICkge1xuXHRcdHZhciBjYWxsYmFja0ludmVyc2UsXG5cdFx0XHRtYXRjaGVzID0gW10sXG5cdFx0XHRpID0gMCxcblx0XHRcdGxlbmd0aCA9IGVsZW1zLmxlbmd0aCxcblx0XHRcdGNhbGxiYWNrRXhwZWN0ID0gIWludmVydDtcblxuXHRcdC8vIEdvIHRocm91Z2ggdGhlIGFycmF5LCBvbmx5IHNhdmluZyB0aGUgaXRlbXNcblx0XHQvLyB0aGF0IHBhc3MgdGhlIHZhbGlkYXRvciBmdW5jdGlvblxuXHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0Y2FsbGJhY2tJbnZlcnNlID0gIWNhbGxiYWNrKCBlbGVtc1sgaSBdLCBpICk7XG5cdFx0XHRpZiAoIGNhbGxiYWNrSW52ZXJzZSAhPT0gY2FsbGJhY2tFeHBlY3QgKSB7XG5cdFx0XHRcdG1hdGNoZXMucHVzaCggZWxlbXNbIGkgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBtYXRjaGVzO1xuXHR9LFxuXG5cdC8vIGFyZyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGFyZyApIHtcblx0XHR2YXIgbGVuZ3RoLCB2YWx1ZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0cmV0ID0gW107XG5cblx0XHQvLyBHbyB0aHJvdWdoIHRoZSBhcnJheSwgdHJhbnNsYXRpbmcgZWFjaCBvZiB0aGUgaXRlbXMgdG8gdGhlaXIgbmV3IHZhbHVlc1xuXHRcdGlmICggaXNBcnJheUxpa2UoIGVsZW1zICkgKSB7XG5cdFx0XHRsZW5ndGggPSBlbGVtcy5sZW5ndGg7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBHbyB0aHJvdWdoIGV2ZXJ5IGtleSBvbiB0aGUgb2JqZWN0LFxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIGVsZW1zICkge1xuXHRcdFx0XHR2YWx1ZSA9IGNhbGxiYWNrKCBlbGVtc1sgaSBdLCBpLCBhcmcgKTtcblxuXHRcdFx0XHRpZiAoIHZhbHVlICE9IG51bGwgKSB7XG5cdFx0XHRcdFx0cmV0LnB1c2goIHZhbHVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBGbGF0dGVuIGFueSBuZXN0ZWQgYXJyYXlzXG5cdFx0cmV0dXJuIGNvbmNhdC5hcHBseSggW10sIHJldCApO1xuXHR9LFxuXG5cdC8vIEEgZ2xvYmFsIEdVSUQgY291bnRlciBmb3Igb2JqZWN0c1xuXHRndWlkOiAxLFxuXG5cdC8vIEJpbmQgYSBmdW5jdGlvbiB0byBhIGNvbnRleHQsIG9wdGlvbmFsbHkgcGFydGlhbGx5IGFwcGx5aW5nIGFueVxuXHQvLyBhcmd1bWVudHMuXG5cdHByb3h5OiBmdW5jdGlvbiggZm4sIGNvbnRleHQgKSB7XG5cdFx0dmFyIHRtcCwgYXJncywgcHJveHk7XG5cblx0XHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0dG1wID0gZm5bIGNvbnRleHQgXTtcblx0XHRcdGNvbnRleHQgPSBmbjtcblx0XHRcdGZuID0gdG1wO1xuXHRcdH1cblxuXHRcdC8vIFF1aWNrIGNoZWNrIHRvIGRldGVybWluZSBpZiB0YXJnZXQgaXMgY2FsbGFibGUsIGluIHRoZSBzcGVjXG5cdFx0Ly8gdGhpcyB0aHJvd3MgYSBUeXBlRXJyb3IsIGJ1dCB3ZSB3aWxsIGp1c3QgcmV0dXJuIHVuZGVmaW5lZC5cblx0XHRpZiAoICFqUXVlcnkuaXNGdW5jdGlvbiggZm4gKSApIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gU2ltdWxhdGVkIGJpbmRcblx0XHRhcmdzID0gc2xpY2UuY2FsbCggYXJndW1lbnRzLCAyICk7XG5cdFx0cHJveHkgPSBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBmbi5hcHBseSggY29udGV4dCB8fCB0aGlzLCBhcmdzLmNvbmNhdCggc2xpY2UuY2FsbCggYXJndW1lbnRzICkgKSApO1xuXHRcdH07XG5cblx0XHQvLyBTZXQgdGhlIGd1aWQgb2YgdW5pcXVlIGhhbmRsZXIgdG8gdGhlIHNhbWUgb2Ygb3JpZ2luYWwgaGFuZGxlciwgc28gaXQgY2FuIGJlIHJlbW92ZWRcblx0XHRwcm94eS5ndWlkID0gZm4uZ3VpZCA9IGZuLmd1aWQgfHwgalF1ZXJ5Lmd1aWQrKztcblxuXHRcdHJldHVybiBwcm94eTtcblx0fSxcblxuXHRub3c6IERhdGUubm93LFxuXG5cdC8vIGpRdWVyeS5zdXBwb3J0IGlzIG5vdCB1c2VkIGluIENvcmUgYnV0IG90aGVyIHByb2plY3RzIGF0dGFjaCB0aGVpclxuXHQvLyBwcm9wZXJ0aWVzIHRvIGl0IHNvIGl0IG5lZWRzIHRvIGV4aXN0LlxuXHRzdXBwb3J0OiBzdXBwb3J0XG59ICk7XG5cbmlmICggdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRqUXVlcnkuZm5bIFN5bWJvbC5pdGVyYXRvciBdID0gYXJyWyBTeW1ib2wuaXRlcmF0b3IgXTtcbn1cblxuLy8gUG9wdWxhdGUgdGhlIGNsYXNzMnR5cGUgbWFwXG5qUXVlcnkuZWFjaCggXCJCb29sZWFuIE51bWJlciBTdHJpbmcgRnVuY3Rpb24gQXJyYXkgRGF0ZSBSZWdFeHAgT2JqZWN0IEVycm9yIFN5bWJvbFwiLnNwbGl0KCBcIiBcIiApLFxuZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdGNsYXNzMnR5cGVbIFwiW29iamVjdCBcIiArIG5hbWUgKyBcIl1cIiBdID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xufSApO1xuXG5mdW5jdGlvbiBpc0FycmF5TGlrZSggb2JqICkge1xuXG5cdC8vIFN1cHBvcnQ6IHJlYWwgaU9TIDguMiBvbmx5IChub3QgcmVwcm9kdWNpYmxlIGluIHNpbXVsYXRvcilcblx0Ly8gYGluYCBjaGVjayB1c2VkIHRvIHByZXZlbnQgSklUIGVycm9yIChnaC0yMTQ1KVxuXHQvLyBoYXNPd24gaXNuJ3QgdXNlZCBoZXJlIGR1ZSB0byBmYWxzZSBuZWdhdGl2ZXNcblx0Ly8gcmVnYXJkaW5nIE5vZGVsaXN0IGxlbmd0aCBpbiBJRVxuXHR2YXIgbGVuZ3RoID0gISFvYmogJiYgXCJsZW5ndGhcIiBpbiBvYmogJiYgb2JqLmxlbmd0aCxcblx0XHR0eXBlID0galF1ZXJ5LnR5cGUoIG9iaiApO1xuXG5cdGlmICggdHlwZSA9PT0gXCJmdW5jdGlvblwiIHx8IGpRdWVyeS5pc1dpbmRvdyggb2JqICkgKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0cmV0dXJuIHR5cGUgPT09IFwiYXJyYXlcIiB8fCBsZW5ndGggPT09IDAgfHxcblx0XHR0eXBlb2YgbGVuZ3RoID09PSBcIm51bWJlclwiICYmIGxlbmd0aCA+IDAgJiYgKCBsZW5ndGggLSAxICkgaW4gb2JqO1xufVxudmFyIFNpenpsZSA9XG4vKiFcbiAqIFNpenpsZSBDU1MgU2VsZWN0b3IgRW5naW5lIHYyLjMuM1xuICogaHR0cHM6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IGpRdWVyeSBGb3VuZGF0aW9uIGFuZCBvdGhlciBjb250cmlidXRvcnNcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTYtMDgtMDhcbiAqL1xuKGZ1bmN0aW9uKCB3aW5kb3cgKSB7XG5cbnZhciBpLFxuXHRzdXBwb3J0LFxuXHRFeHByLFxuXHRnZXRUZXh0LFxuXHRpc1hNTCxcblx0dG9rZW5pemUsXG5cdGNvbXBpbGUsXG5cdHNlbGVjdCxcblx0b3V0ZXJtb3N0Q29udGV4dCxcblx0c29ydElucHV0LFxuXHRoYXNEdXBsaWNhdGUsXG5cblx0Ly8gTG9jYWwgZG9jdW1lbnQgdmFyc1xuXHRzZXREb2N1bWVudCxcblx0ZG9jdW1lbnQsXG5cdGRvY0VsZW0sXG5cdGRvY3VtZW50SXNIVE1MLFxuXHRyYnVnZ3lRU0EsXG5cdHJidWdneU1hdGNoZXMsXG5cdG1hdGNoZXMsXG5cdGNvbnRhaW5zLFxuXG5cdC8vIEluc3RhbmNlLXNwZWNpZmljIGRhdGFcblx0ZXhwYW5kbyA9IFwic2l6emxlXCIgKyAxICogbmV3IERhdGUoKSxcblx0cHJlZmVycmVkRG9jID0gd2luZG93LmRvY3VtZW50LFxuXHRkaXJydW5zID0gMCxcblx0ZG9uZSA9IDAsXG5cdGNsYXNzQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHR0b2tlbkNhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0Y29tcGlsZXJDYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdHNvcnRPcmRlciA9IGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdGlmICggYSA9PT0gYiApIHtcblx0XHRcdGhhc0R1cGxpY2F0ZSA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiAwO1xuXHR9LFxuXG5cdC8vIEluc3RhbmNlIG1ldGhvZHNcblx0aGFzT3duID0gKHt9KS5oYXNPd25Qcm9wZXJ0eSxcblx0YXJyID0gW10sXG5cdHBvcCA9IGFyci5wb3AsXG5cdHB1c2hfbmF0aXZlID0gYXJyLnB1c2gsXG5cdHB1c2ggPSBhcnIucHVzaCxcblx0c2xpY2UgPSBhcnIuc2xpY2UsXG5cdC8vIFVzZSBhIHN0cmlwcGVkLWRvd24gaW5kZXhPZiBhcyBpdCdzIGZhc3RlciB0aGFuIG5hdGl2ZVxuXHQvLyBodHRwczovL2pzcGVyZi5jb20vdGhvci1pbmRleG9mLXZzLWZvci81XG5cdGluZGV4T2YgPSBmdW5jdGlvbiggbGlzdCwgZWxlbSApIHtcblx0XHR2YXIgaSA9IDAsXG5cdFx0XHRsZW4gPSBsaXN0Lmxlbmd0aDtcblx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGlmICggbGlzdFtpXSA9PT0gZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAtMTtcblx0fSxcblxuXHRib29sZWFucyA9IFwiY2hlY2tlZHxzZWxlY3RlZHxhc3luY3xhdXRvZm9jdXN8YXV0b3BsYXl8Y29udHJvbHN8ZGVmZXJ8ZGlzYWJsZWR8aGlkZGVufGlzbWFwfGxvb3B8bXVsdGlwbGV8b3BlbnxyZWFkb25seXxyZXF1aXJlZHxzY29wZWRcIixcblxuXHQvLyBSZWd1bGFyIGV4cHJlc3Npb25zXG5cblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvY3NzMy1zZWxlY3RvcnMvI3doaXRlc3BhY2Vcblx0d2hpdGVzcGFjZSA9IFwiW1xcXFx4MjBcXFxcdFxcXFxyXFxcXG5cXFxcZl1cIixcblxuXHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9DU1MyMS9zeW5kYXRhLmh0bWwjdmFsdWUtZGVmLWlkZW50aWZpZXJcblx0aWRlbnRpZmllciA9IFwiKD86XFxcXFxcXFwufFtcXFxcdy1dfFteXFwwLVxcXFx4YTBdKStcIixcblxuXHQvLyBBdHRyaWJ1dGUgc2VsZWN0b3JzOiBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2F0dHJpYnV0ZS1zZWxlY3RvcnNcblx0YXR0cmlidXRlcyA9IFwiXFxcXFtcIiArIHdoaXRlc3BhY2UgKyBcIiooXCIgKyBpZGVudGlmaWVyICsgXCIpKD86XCIgKyB3aGl0ZXNwYWNlICtcblx0XHQvLyBPcGVyYXRvciAoY2FwdHVyZSAyKVxuXHRcdFwiKihbKl4kfCF+XT89KVwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gXCJBdHRyaWJ1dGUgdmFsdWVzIG11c3QgYmUgQ1NTIGlkZW50aWZpZXJzIFtjYXB0dXJlIDVdIG9yIHN0cmluZ3MgW2NhcHR1cmUgMyBvciBjYXB0dXJlIDRdXCJcblx0XHRcIiooPzonKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJ10pKiknfFxcXCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFxcXFwiXSkqKVxcXCJ8KFwiICsgaWRlbnRpZmllciArIFwiKSl8KVwiICsgd2hpdGVzcGFjZSArXG5cdFx0XCIqXFxcXF1cIixcblxuXHRwc2V1ZG9zID0gXCI6KFwiICsgaWRlbnRpZmllciArIFwiKSg/OlxcXFwoKFwiICtcblx0XHQvLyBUbyByZWR1Y2UgdGhlIG51bWJlciBvZiBzZWxlY3RvcnMgbmVlZGluZyB0b2tlbml6ZSBpbiB0aGUgcHJlRmlsdGVyLCBwcmVmZXIgYXJndW1lbnRzOlxuXHRcdC8vIDEuIHF1b3RlZCAoY2FwdHVyZSAzOyBjYXB0dXJlIDQgb3IgY2FwdHVyZSA1KVxuXHRcdFwiKCcoKD86XFxcXFxcXFwufFteXFxcXFxcXFwnXSkqKSd8XFxcIigoPzpcXFxcXFxcXC58W15cXFxcXFxcXFxcXCJdKSopXFxcIil8XCIgK1xuXHRcdC8vIDIuIHNpbXBsZSAoY2FwdHVyZSA2KVxuXHRcdFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcKClbXFxcXF1dfFwiICsgYXR0cmlidXRlcyArIFwiKSopfFwiICtcblx0XHQvLyAzLiBhbnl0aGluZyBlbHNlIChjYXB0dXJlIDIpXG5cdFx0XCIuKlwiICtcblx0XHRcIilcXFxcKXwpXCIsXG5cblx0Ly8gTGVhZGluZyBhbmQgbm9uLWVzY2FwZWQgdHJhaWxpbmcgd2hpdGVzcGFjZSwgY2FwdHVyaW5nIHNvbWUgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVycyBwcmVjZWRpbmcgdGhlIGxhdHRlclxuXHRyd2hpdGVzcGFjZSA9IG5ldyBSZWdFeHAoIHdoaXRlc3BhY2UgKyBcIitcIiwgXCJnXCIgKSxcblx0cnRyaW0gPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIit8KCg/Ol58W15cXFxcXFxcXF0pKD86XFxcXFxcXFwuKSopXCIgKyB3aGl0ZXNwYWNlICsgXCIrJFwiLCBcImdcIiApLFxuXG5cdHJjb21tYSA9IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKixcIiArIHdoaXRlc3BhY2UgKyBcIipcIiApLFxuXHRyY29tYmluYXRvcnMgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiooWz4rfl18XCIgKyB3aGl0ZXNwYWNlICsgXCIpXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblxuXHRyYXR0cmlidXRlUXVvdGVzID0gbmV3IFJlZ0V4cCggXCI9XCIgKyB3aGl0ZXNwYWNlICsgXCIqKFteXFxcXF0nXFxcIl0qPylcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcXVwiLCBcImdcIiApLFxuXG5cdHJwc2V1ZG8gPSBuZXcgUmVnRXhwKCBwc2V1ZG9zICksXG5cdHJpZGVudGlmaWVyID0gbmV3IFJlZ0V4cCggXCJeXCIgKyBpZGVudGlmaWVyICsgXCIkXCIgKSxcblxuXHRtYXRjaEV4cHIgPSB7XG5cdFx0XCJJRFwiOiBuZXcgUmVnRXhwKCBcIl4jKFwiICsgaWRlbnRpZmllciArIFwiKVwiICksXG5cdFx0XCJDTEFTU1wiOiBuZXcgUmVnRXhwKCBcIl5cXFxcLihcIiArIGlkZW50aWZpZXIgKyBcIilcIiApLFxuXHRcdFwiVEFHXCI6IG5ldyBSZWdFeHAoIFwiXihcIiArIGlkZW50aWZpZXIgKyBcInxbKl0pXCIgKSxcblx0XHRcIkFUVFJcIjogbmV3IFJlZ0V4cCggXCJeXCIgKyBhdHRyaWJ1dGVzICksXG5cdFx0XCJQU0VVRE9cIjogbmV3IFJlZ0V4cCggXCJeXCIgKyBwc2V1ZG9zICksXG5cdFx0XCJDSElMRFwiOiBuZXcgUmVnRXhwKCBcIl46KG9ubHl8Zmlyc3R8bGFzdHxudGh8bnRoLWxhc3QpLShjaGlsZHxvZi10eXBlKSg/OlxcXFwoXCIgKyB3aGl0ZXNwYWNlICtcblx0XHRcdFwiKihldmVufG9kZHwoKFsrLV18KShcXFxcZCopbnwpXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86KFsrLV18KVwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooXFxcXGQrKXwpKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfClcIiwgXCJpXCIgKSxcblx0XHRcImJvb2xcIjogbmV3IFJlZ0V4cCggXCJeKD86XCIgKyBib29sZWFucyArIFwiKSRcIiwgXCJpXCIgKSxcblx0XHQvLyBGb3IgdXNlIGluIGxpYnJhcmllcyBpbXBsZW1lbnRpbmcgLmlzKClcblx0XHQvLyBXZSB1c2UgdGhpcyBmb3IgUE9TIG1hdGNoaW5nIGluIGBzZWxlY3RgXG5cdFx0XCJuZWVkc0NvbnRleHRcIjogbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqWz4rfl18OihldmVufG9kZHxlcXxndHxsdHxudGh8Zmlyc3R8bGFzdCkoPzpcXFxcKFwiICtcblx0XHRcdHdoaXRlc3BhY2UgKyBcIiooKD86LVxcXFxkKT9cXFxcZCopXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXCl8KSg/PVteLV18JClcIiwgXCJpXCIgKVxuXHR9LFxuXG5cdHJpbnB1dHMgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFxuXHRyaGVhZGVyID0gL15oXFxkJC9pLFxuXG5cdHJuYXRpdmUgPSAvXltee10rXFx7XFxzKlxcW25hdGl2ZSBcXHcvLFxuXG5cdC8vIEVhc2lseS1wYXJzZWFibGUvcmV0cmlldmFibGUgSUQgb3IgVEFHIG9yIENMQVNTIHNlbGVjdG9yc1xuXHRycXVpY2tFeHByID0gL14oPzojKFtcXHctXSspfChcXHcrKXxcXC4oW1xcdy1dKykpJC8sXG5cblx0cnNpYmxpbmcgPSAvWyt+XS8sXG5cblx0Ly8gQ1NTIGVzY2FwZXNcblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvQ1NTMjEvc3luZGF0YS5odG1sI2VzY2FwZWQtY2hhcmFjdGVyc1xuXHRydW5lc2NhcGUgPSBuZXcgUmVnRXhwKCBcIlxcXFxcXFxcKFtcXFxcZGEtZl17MSw2fVwiICsgd2hpdGVzcGFjZSArIFwiP3woXCIgKyB3aGl0ZXNwYWNlICsgXCIpfC4pXCIsIFwiaWdcIiApLFxuXHRmdW5lc2NhcGUgPSBmdW5jdGlvbiggXywgZXNjYXBlZCwgZXNjYXBlZFdoaXRlc3BhY2UgKSB7XG5cdFx0dmFyIGhpZ2ggPSBcIjB4XCIgKyBlc2NhcGVkIC0gMHgxMDAwMDtcblx0XHQvLyBOYU4gbWVhbnMgbm9uLWNvZGVwb2ludFxuXHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3g8MjRcblx0XHQvLyBXb3JrYXJvdW5kIGVycm9uZW91cyBudW1lcmljIGludGVycHJldGF0aW9uIG9mICtcIjB4XCJcblx0XHRyZXR1cm4gaGlnaCAhPT0gaGlnaCB8fCBlc2NhcGVkV2hpdGVzcGFjZSA/XG5cdFx0XHRlc2NhcGVkIDpcblx0XHRcdGhpZ2ggPCAwID9cblx0XHRcdFx0Ly8gQk1QIGNvZGVwb2ludFxuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoICsgMHgxMDAwMCApIDpcblx0XHRcdFx0Ly8gU3VwcGxlbWVudGFsIFBsYW5lIGNvZGVwb2ludCAoc3Vycm9nYXRlIHBhaXIpXG5cdFx0XHRcdFN0cmluZy5mcm9tQ2hhckNvZGUoIGhpZ2ggPj4gMTAgfCAweEQ4MDAsIGhpZ2ggJiAweDNGRiB8IDB4REMwMCApO1xuXHR9LFxuXG5cdC8vIENTUyBzdHJpbmcvaWRlbnRpZmllciBzZXJpYWxpemF0aW9uXG5cdC8vIGh0dHBzOi8vZHJhZnRzLmNzc3dnLm9yZy9jc3NvbS8jY29tbW9uLXNlcmlhbGl6aW5nLWlkaW9tc1xuXHRyY3NzZXNjYXBlID0gLyhbXFwwLVxceDFmXFx4N2ZdfF4tP1xcZCl8Xi0kfFteXFwwLVxceDFmXFx4N2YtXFx1RkZGRlxcdy1dL2csXG5cdGZjc3Nlc2NhcGUgPSBmdW5jdGlvbiggY2gsIGFzQ29kZVBvaW50ICkge1xuXHRcdGlmICggYXNDb2RlUG9pbnQgKSB7XG5cblx0XHRcdC8vIFUrMDAwMCBOVUxMIGJlY29tZXMgVStGRkZEIFJFUExBQ0VNRU5UIENIQVJBQ1RFUlxuXHRcdFx0aWYgKCBjaCA9PT0gXCJcXDBcIiApIHtcblx0XHRcdFx0cmV0dXJuIFwiXFx1RkZGRFwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb250cm9sIGNoYXJhY3RlcnMgYW5kIChkZXBlbmRlbnQgdXBvbiBwb3NpdGlvbikgbnVtYmVycyBnZXQgZXNjYXBlZCBhcyBjb2RlIHBvaW50c1xuXHRcdFx0cmV0dXJuIGNoLnNsaWNlKCAwLCAtMSApICsgXCJcXFxcXCIgKyBjaC5jaGFyQ29kZUF0KCBjaC5sZW5ndGggLSAxICkudG9TdHJpbmcoIDE2ICkgKyBcIiBcIjtcblx0XHR9XG5cblx0XHQvLyBPdGhlciBwb3RlbnRpYWxseS1zcGVjaWFsIEFTQ0lJIGNoYXJhY3RlcnMgZ2V0IGJhY2tzbGFzaC1lc2NhcGVkXG5cdFx0cmV0dXJuIFwiXFxcXFwiICsgY2g7XG5cdH0sXG5cblx0Ly8gVXNlZCBmb3IgaWZyYW1lc1xuXHQvLyBTZWUgc2V0RG9jdW1lbnQoKVxuXHQvLyBSZW1vdmluZyB0aGUgZnVuY3Rpb24gd3JhcHBlciBjYXVzZXMgYSBcIlBlcm1pc3Npb24gRGVuaWVkXCJcblx0Ly8gZXJyb3IgaW4gSUVcblx0dW5sb2FkSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuXHRcdHNldERvY3VtZW50KCk7XG5cdH0sXG5cblx0ZGlzYWJsZWRBbmNlc3RvciA9IGFkZENvbWJpbmF0b3IoXG5cdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gdHJ1ZSAmJiAoXCJmb3JtXCIgaW4gZWxlbSB8fCBcImxhYmVsXCIgaW4gZWxlbSk7XG5cdFx0fSxcblx0XHR7IGRpcjogXCJwYXJlbnROb2RlXCIsIG5leHQ6IFwibGVnZW5kXCIgfVxuXHQpO1xuXG4vLyBPcHRpbWl6ZSBmb3IgcHVzaC5hcHBseSggXywgTm9kZUxpc3QgKVxudHJ5IHtcblx0cHVzaC5hcHBseShcblx0XHQoYXJyID0gc2xpY2UuY2FsbCggcHJlZmVycmVkRG9jLmNoaWxkTm9kZXMgKSksXG5cdFx0cHJlZmVycmVkRG9jLmNoaWxkTm9kZXNcblx0KTtcblx0Ly8gU3VwcG9ydDogQW5kcm9pZDw0LjBcblx0Ly8gRGV0ZWN0IHNpbGVudGx5IGZhaWxpbmcgcHVzaC5hcHBseVxuXHRhcnJbIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzLmxlbmd0aCBdLm5vZGVUeXBlO1xufSBjYXRjaCAoIGUgKSB7XG5cdHB1c2ggPSB7IGFwcGx5OiBhcnIubGVuZ3RoID9cblxuXHRcdC8vIExldmVyYWdlIHNsaWNlIGlmIHBvc3NpYmxlXG5cdFx0ZnVuY3Rpb24oIHRhcmdldCwgZWxzICkge1xuXHRcdFx0cHVzaF9uYXRpdmUuYXBwbHkoIHRhcmdldCwgc2xpY2UuY2FsbChlbHMpICk7XG5cdFx0fSA6XG5cblx0XHQvLyBTdXBwb3J0OiBJRTw5XG5cdFx0Ly8gT3RoZXJ3aXNlIGFwcGVuZCBkaXJlY3RseVxuXHRcdGZ1bmN0aW9uKCB0YXJnZXQsIGVscyApIHtcblx0XHRcdHZhciBqID0gdGFyZ2V0Lmxlbmd0aCxcblx0XHRcdFx0aSA9IDA7XG5cdFx0XHQvLyBDYW4ndCB0cnVzdCBOb2RlTGlzdC5sZW5ndGhcblx0XHRcdHdoaWxlICggKHRhcmdldFtqKytdID0gZWxzW2krK10pICkge31cblx0XHRcdHRhcmdldC5sZW5ndGggPSBqIC0gMTtcblx0XHR9XG5cdH07XG59XG5cbmZ1bmN0aW9uIFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHQsIHJlc3VsdHMsIHNlZWQgKSB7XG5cdHZhciBtLCBpLCBlbGVtLCBuaWQsIG1hdGNoLCBncm91cHMsIG5ld1NlbGVjdG9yLFxuXHRcdG5ld0NvbnRleHQgPSBjb250ZXh0ICYmIGNvbnRleHQub3duZXJEb2N1bWVudCxcblxuXHRcdC8vIG5vZGVUeXBlIGRlZmF1bHRzIHRvIDksIHNpbmNlIGNvbnRleHQgZGVmYXVsdHMgdG8gZG9jdW1lbnRcblx0XHRub2RlVHlwZSA9IGNvbnRleHQgPyBjb250ZXh0Lm5vZGVUeXBlIDogOTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBSZXR1cm4gZWFybHkgZnJvbSBjYWxscyB3aXRoIGludmFsaWQgc2VsZWN0b3Igb3IgY29udGV4dFxuXHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiB8fCAhc2VsZWN0b3IgfHxcblx0XHRub2RlVHlwZSAhPT0gMSAmJiBub2RlVHlwZSAhPT0gOSAmJiBub2RlVHlwZSAhPT0gMTEgKSB7XG5cblx0XHRyZXR1cm4gcmVzdWx0cztcblx0fVxuXG5cdC8vIFRyeSB0byBzaG9ydGN1dCBmaW5kIG9wZXJhdGlvbnMgKGFzIG9wcG9zZWQgdG8gZmlsdGVycykgaW4gSFRNTCBkb2N1bWVudHNcblx0aWYgKCAhc2VlZCApIHtcblxuXHRcdGlmICggKCBjb250ZXh0ID8gY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHQgOiBwcmVmZXJyZWREb2MgKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHRcdH1cblx0XHRjb250ZXh0ID0gY29udGV4dCB8fCBkb2N1bWVudDtcblxuXHRcdGlmICggZG9jdW1lbnRJc0hUTUwgKSB7XG5cblx0XHRcdC8vIElmIHRoZSBzZWxlY3RvciBpcyBzdWZmaWNpZW50bHkgc2ltcGxlLCB0cnkgdXNpbmcgYSBcImdldCpCeSpcIiBET00gbWV0aG9kXG5cdFx0XHQvLyAoZXhjZXB0aW5nIERvY3VtZW50RnJhZ21lbnQgY29udGV4dCwgd2hlcmUgdGhlIG1ldGhvZHMgZG9uJ3QgZXhpc3QpXG5cdFx0XHRpZiAoIG5vZGVUeXBlICE9PSAxMSAmJiAobWF0Y2ggPSBycXVpY2tFeHByLmV4ZWMoIHNlbGVjdG9yICkpICkge1xuXG5cdFx0XHRcdC8vIElEIHNlbGVjdG9yXG5cdFx0XHRcdGlmICggKG0gPSBtYXRjaFsxXSkgKSB7XG5cblx0XHRcdFx0XHQvLyBEb2N1bWVudCBjb250ZXh0XG5cdFx0XHRcdFx0aWYgKCBub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0XHRcdGlmICggKGVsZW0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBtICkpICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFLCBPcGVyYSwgV2Via2l0XG5cdFx0XHRcdFx0XHRcdC8vIFRPRE86IGlkZW50aWZ5IHZlcnNpb25zXG5cdFx0XHRcdFx0XHRcdC8vIGdldEVsZW1lbnRCeUlkIGNhbiBtYXRjaCBlbGVtZW50cyBieSBuYW1lIGluc3RlYWQgb2YgSURcblx0XHRcdFx0XHRcdFx0aWYgKCBlbGVtLmlkID09PSBtICkge1xuXHRcdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIEVsZW1lbnQgY29udGV4dFxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFLCBPcGVyYSwgV2Via2l0XG5cdFx0XHRcdFx0XHQvLyBUT0RPOiBpZGVudGlmeSB2ZXJzaW9uc1xuXHRcdFx0XHRcdFx0Ly8gZ2V0RWxlbWVudEJ5SWQgY2FuIG1hdGNoIGVsZW1lbnRzIGJ5IG5hbWUgaW5zdGVhZCBvZiBJRFxuXHRcdFx0XHRcdFx0aWYgKCBuZXdDb250ZXh0ICYmIChlbGVtID0gbmV3Q29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApKSAmJlxuXHRcdFx0XHRcdFx0XHRjb250YWlucyggY29udGV4dCwgZWxlbSApICYmXG5cdFx0XHRcdFx0XHRcdGVsZW0uaWQgPT09IG0gKSB7XG5cblx0XHRcdFx0XHRcdFx0cmVzdWx0cy5wdXNoKCBlbGVtICk7XG5cdFx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBUeXBlIHNlbGVjdG9yXG5cdFx0XHRcdH0gZWxzZSBpZiAoIG1hdGNoWzJdICkge1xuXHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIHNlbGVjdG9yICkgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblxuXHRcdFx0XHQvLyBDbGFzcyBzZWxlY3RvclxuXHRcdFx0XHR9IGVsc2UgaWYgKCAobSA9IG1hdGNoWzNdKSAmJiBzdXBwb3J0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUgJiZcblx0XHRcdFx0XHRjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUgKSB7XG5cblx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIG0gKSApO1xuXHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRha2UgYWR2YW50YWdlIG9mIHF1ZXJ5U2VsZWN0b3JBbGxcblx0XHRcdGlmICggc3VwcG9ydC5xc2EgJiZcblx0XHRcdFx0IWNvbXBpbGVyQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXSAmJlxuXHRcdFx0XHQoIXJidWdneVFTQSB8fCAhcmJ1Z2d5UVNBLnRlc3QoIHNlbGVjdG9yICkpICkge1xuXG5cdFx0XHRcdGlmICggbm9kZVR5cGUgIT09IDEgKSB7XG5cdFx0XHRcdFx0bmV3Q29udGV4dCA9IGNvbnRleHQ7XG5cdFx0XHRcdFx0bmV3U2VsZWN0b3IgPSBzZWxlY3RvcjtcblxuXHRcdFx0XHQvLyBxU0EgbG9va3Mgb3V0c2lkZSBFbGVtZW50IGNvbnRleHQsIHdoaWNoIGlzIG5vdCB3aGF0IHdlIHdhbnRcblx0XHRcdFx0Ly8gVGhhbmtzIHRvIEFuZHJldyBEdXBvbnQgZm9yIHRoaXMgd29ya2Fyb3VuZCB0ZWNobmlxdWVcblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04XG5cdFx0XHRcdC8vIEV4Y2x1ZGUgb2JqZWN0IGVsZW1lbnRzXG5cdFx0XHRcdH0gZWxzZSBpZiAoIGNvbnRleHQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSAhPT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0XHRcdC8vIENhcHR1cmUgdGhlIGNvbnRleHQgSUQsIHNldHRpbmcgaXQgZmlyc3QgaWYgbmVjZXNzYXJ5XG5cdFx0XHRcdFx0aWYgKCAobmlkID0gY29udGV4dC5nZXRBdHRyaWJ1dGUoIFwiaWRcIiApKSApIHtcblx0XHRcdFx0XHRcdG5pZCA9IG5pZC5yZXBsYWNlKCByY3NzZXNjYXBlLCBmY3NzZXNjYXBlICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGNvbnRleHQuc2V0QXR0cmlidXRlKCBcImlkXCIsIChuaWQgPSBleHBhbmRvKSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZWZpeCBldmVyeSBzZWxlY3RvciBpbiB0aGUgbGlzdFxuXHRcdFx0XHRcdGdyb3VwcyA9IHRva2VuaXplKCBzZWxlY3RvciApO1xuXHRcdFx0XHRcdGkgPSBncm91cHMubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0Z3JvdXBzW2ldID0gXCIjXCIgKyBuaWQgKyBcIiBcIiArIHRvU2VsZWN0b3IoIGdyb3Vwc1tpXSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRuZXdTZWxlY3RvciA9IGdyb3Vwcy5qb2luKCBcIixcIiApO1xuXG5cdFx0XHRcdFx0Ly8gRXhwYW5kIGNvbnRleHQgZm9yIHNpYmxpbmcgc2VsZWN0b3JzXG5cdFx0XHRcdFx0bmV3Q29udGV4dCA9IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8XG5cdFx0XHRcdFx0XHRjb250ZXh0O1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBuZXdTZWxlY3RvciApIHtcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cyxcblx0XHRcdFx0XHRcdFx0bmV3Q29udGV4dC5xdWVyeVNlbGVjdG9yQWxsKCBuZXdTZWxlY3RvciApXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fSBjYXRjaCAoIHFzYUVycm9yICkge1xuXHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHRpZiAoIG5pZCA9PT0gZXhwYW5kbyApIHtcblx0XHRcdFx0XHRcdFx0Y29udGV4dC5yZW1vdmVBdHRyaWJ1dGUoIFwiaWRcIiApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIEFsbCBvdGhlcnNcblx0cmV0dXJuIHNlbGVjdCggc2VsZWN0b3IucmVwbGFjZSggcnRyaW0sIFwiJDFcIiApLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGtleS12YWx1ZSBjYWNoZXMgb2YgbGltaXRlZCBzaXplXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb24oc3RyaW5nLCBvYmplY3QpfSBSZXR1cm5zIHRoZSBPYmplY3QgZGF0YSBhZnRlciBzdG9yaW5nIGl0IG9uIGl0c2VsZiB3aXRoXG4gKlx0cHJvcGVydHkgbmFtZSB0aGUgKHNwYWNlLXN1ZmZpeGVkKSBzdHJpbmcgYW5kIChpZiB0aGUgY2FjaGUgaXMgbGFyZ2VyIHRoYW4gRXhwci5jYWNoZUxlbmd0aClcbiAqXHRkZWxldGluZyB0aGUgb2xkZXN0IGVudHJ5XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUNhY2hlKCkge1xuXHR2YXIga2V5cyA9IFtdO1xuXG5cdGZ1bmN0aW9uIGNhY2hlKCBrZXksIHZhbHVlICkge1xuXHRcdC8vIFVzZSAoa2V5ICsgXCIgXCIpIHRvIGF2b2lkIGNvbGxpc2lvbiB3aXRoIG5hdGl2ZSBwcm90b3R5cGUgcHJvcGVydGllcyAoc2VlIElzc3VlICMxNTcpXG5cdFx0aWYgKCBrZXlzLnB1c2goIGtleSArIFwiIFwiICkgPiBFeHByLmNhY2hlTGVuZ3RoICkge1xuXHRcdFx0Ly8gT25seSBrZWVwIHRoZSBtb3N0IHJlY2VudCBlbnRyaWVzXG5cdFx0XHRkZWxldGUgY2FjaGVbIGtleXMuc2hpZnQoKSBdO1xuXHRcdH1cblx0XHRyZXR1cm4gKGNhY2hlWyBrZXkgKyBcIiBcIiBdID0gdmFsdWUpO1xuXHR9XG5cdHJldHVybiBjYWNoZTtcbn1cblxuLyoqXG4gKiBNYXJrIGEgZnVuY3Rpb24gZm9yIHNwZWNpYWwgdXNlIGJ5IFNpenpsZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIG1hcmtcbiAqL1xuZnVuY3Rpb24gbWFya0Z1bmN0aW9uKCBmbiApIHtcblx0Zm5bIGV4cGFuZG8gXSA9IHRydWU7XG5cdHJldHVybiBmbjtcbn1cblxuLyoqXG4gKiBTdXBwb3J0IHRlc3RpbmcgdXNpbmcgYW4gZWxlbWVudFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gUGFzc2VkIHRoZSBjcmVhdGVkIGVsZW1lbnQgYW5kIHJldHVybnMgYSBib29sZWFuIHJlc3VsdFxuICovXG5mdW5jdGlvbiBhc3NlcnQoIGZuICkge1xuXHR2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZmllbGRzZXRcIik7XG5cblx0dHJ5IHtcblx0XHRyZXR1cm4gISFmbiggZWwgKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fSBmaW5hbGx5IHtcblx0XHQvLyBSZW1vdmUgZnJvbSBpdHMgcGFyZW50IGJ5IGRlZmF1bHRcblx0XHRpZiAoIGVsLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRlbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBlbCApO1xuXHRcdH1cblx0XHQvLyByZWxlYXNlIG1lbW9yeSBpbiBJRVxuXHRcdGVsID0gbnVsbDtcblx0fVxufVxuXG4vKipcbiAqIEFkZHMgdGhlIHNhbWUgaGFuZGxlciBmb3IgYWxsIG9mIHRoZSBzcGVjaWZpZWQgYXR0cnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBhdHRycyBQaXBlLXNlcGFyYXRlZCBsaXN0IG9mIGF0dHJpYnV0ZXNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXIgVGhlIG1ldGhvZCB0aGF0IHdpbGwgYmUgYXBwbGllZFxuICovXG5mdW5jdGlvbiBhZGRIYW5kbGUoIGF0dHJzLCBoYW5kbGVyICkge1xuXHR2YXIgYXJyID0gYXR0cnMuc3BsaXQoXCJ8XCIpLFxuXHRcdGkgPSBhcnIubGVuZ3RoO1xuXG5cdHdoaWxlICggaS0tICkge1xuXHRcdEV4cHIuYXR0ckhhbmRsZVsgYXJyW2ldIF0gPSBoYW5kbGVyO1xuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGRvY3VtZW50IG9yZGVyIG9mIHR3byBzaWJsaW5nc1xuICogQHBhcmFtIHtFbGVtZW50fSBhXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGJcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IFJldHVybnMgbGVzcyB0aGFuIDAgaWYgYSBwcmVjZWRlcyBiLCBncmVhdGVyIHRoYW4gMCBpZiBhIGZvbGxvd3MgYlxuICovXG5mdW5jdGlvbiBzaWJsaW5nQ2hlY2soIGEsIGIgKSB7XG5cdHZhciBjdXIgPSBiICYmIGEsXG5cdFx0ZGlmZiA9IGN1ciAmJiBhLm5vZGVUeXBlID09PSAxICYmIGIubm9kZVR5cGUgPT09IDEgJiZcblx0XHRcdGEuc291cmNlSW5kZXggLSBiLnNvdXJjZUluZGV4O1xuXG5cdC8vIFVzZSBJRSBzb3VyY2VJbmRleCBpZiBhdmFpbGFibGUgb24gYm90aCBub2Rlc1xuXHRpZiAoIGRpZmYgKSB7XG5cdFx0cmV0dXJuIGRpZmY7XG5cdH1cblxuXHQvLyBDaGVjayBpZiBiIGZvbGxvd3MgYVxuXHRpZiAoIGN1ciApIHtcblx0XHR3aGlsZSAoIChjdXIgPSBjdXIubmV4dFNpYmxpbmcpICkge1xuXHRcdFx0aWYgKCBjdXIgPT09IGIgKSB7XG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gYSA/IDEgOiAtMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGlucHV0IHR5cGVzXG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICovXG5mdW5jdGlvbiBjcmVhdGVJbnB1dFBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiBuYW1lID09PSBcImlucHV0XCIgJiYgZWxlbS50eXBlID09PSB0eXBlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgYnV0dG9uc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQnV0dG9uUHNldWRvKCB0eXBlICkge1xuXHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0dmFyIG5hbWUgPSBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0cmV0dXJuIChuYW1lID09PSBcImlucHV0XCIgfHwgbmFtZSA9PT0gXCJidXR0b25cIikgJiYgZWxlbS50eXBlID09PSB0eXBlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgOmVuYWJsZWQvOmRpc2FibGVkXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGRpc2FibGVkIHRydWUgZm9yIDpkaXNhYmxlZDsgZmFsc2UgZm9yIDplbmFibGVkXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZURpc2FibGVkUHNldWRvKCBkaXNhYmxlZCApIHtcblxuXHQvLyBLbm93biA6ZGlzYWJsZWQgZmFsc2UgcG9zaXRpdmVzOiBmaWVsZHNldFtkaXNhYmxlZF0gPiBsZWdlbmQ6bnRoLW9mLXR5cGUobisyKSA6Y2FuLWRpc2FibGVcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0Ly8gT25seSBjZXJ0YWluIGVsZW1lbnRzIGNhbiBtYXRjaCA6ZW5hYmxlZCBvciA6ZGlzYWJsZWRcblx0XHQvLyBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9zY3JpcHRpbmcuaHRtbCNzZWxlY3Rvci1lbmFibGVkXG5cdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc2NyaXB0aW5nLmh0bWwjc2VsZWN0b3ItZGlzYWJsZWRcblx0XHRpZiAoIFwiZm9ybVwiIGluIGVsZW0gKSB7XG5cblx0XHRcdC8vIENoZWNrIGZvciBpbmhlcml0ZWQgZGlzYWJsZWRuZXNzIG9uIHJlbGV2YW50IG5vbi1kaXNhYmxlZCBlbGVtZW50czpcblx0XHRcdC8vICogbGlzdGVkIGZvcm0tYXNzb2NpYXRlZCBlbGVtZW50cyBpbiBhIGRpc2FibGVkIGZpZWxkc2V0XG5cdFx0XHQvLyAgIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL2Zvcm1zLmh0bWwjY2F0ZWdvcnktbGlzdGVkXG5cdFx0XHQvLyAgIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL2Zvcm1zLmh0bWwjY29uY2VwdC1mZS1kaXNhYmxlZFxuXHRcdFx0Ly8gKiBvcHRpb24gZWxlbWVudHMgaW4gYSBkaXNhYmxlZCBvcHRncm91cFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NvbmNlcHQtb3B0aW9uLWRpc2FibGVkXG5cdFx0XHQvLyBBbGwgc3VjaCBlbGVtZW50cyBoYXZlIGEgXCJmb3JtXCIgcHJvcGVydHkuXG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSAmJiBlbGVtLmRpc2FibGVkID09PSBmYWxzZSApIHtcblxuXHRcdFx0XHQvLyBPcHRpb24gZWxlbWVudHMgZGVmZXIgdG8gYSBwYXJlbnQgb3B0Z3JvdXAgaWYgcHJlc2VudFxuXHRcdFx0XHRpZiAoIFwibGFiZWxcIiBpbiBlbGVtICkge1xuXHRcdFx0XHRcdGlmICggXCJsYWJlbFwiIGluIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtLnBhcmVudE5vZGUuZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gZGlzYWJsZWQ7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgNiAtIDExXG5cdFx0XHRcdC8vIFVzZSB0aGUgaXNEaXNhYmxlZCBzaG9ydGN1dCBwcm9wZXJ0eSB0byBjaGVjayBmb3IgZGlzYWJsZWQgZmllbGRzZXQgYW5jZXN0b3JzXG5cdFx0XHRcdHJldHVybiBlbGVtLmlzRGlzYWJsZWQgPT09IGRpc2FibGVkIHx8XG5cblx0XHRcdFx0XHQvLyBXaGVyZSB0aGVyZSBpcyBubyBpc0Rpc2FibGVkLCBjaGVjayBtYW51YWxseVxuXHRcdFx0XHRcdC8qIGpzaGludCAtVzAxOCAqL1xuXHRcdFx0XHRcdGVsZW0uaXNEaXNhYmxlZCAhPT0gIWRpc2FibGVkICYmXG5cdFx0XHRcdFx0XHRkaXNhYmxlZEFuY2VzdG9yKCBlbGVtICkgPT09IGRpc2FibGVkO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gZGlzYWJsZWQ7XG5cblx0XHQvLyBUcnkgdG8gd2lubm93IG91dCBlbGVtZW50cyB0aGF0IGNhbid0IGJlIGRpc2FibGVkIGJlZm9yZSB0cnVzdGluZyB0aGUgZGlzYWJsZWQgcHJvcGVydHkuXG5cdFx0Ly8gU29tZSB2aWN0aW1zIGdldCBjYXVnaHQgaW4gb3VyIG5ldCAobGFiZWwsIGxlZ2VuZCwgbWVudSwgdHJhY2spLCBidXQgaXQgc2hvdWxkbid0XG5cdFx0Ly8gZXZlbiBleGlzdCBvbiB0aGVtLCBsZXQgYWxvbmUgaGF2ZSBhIGJvb2xlYW4gdmFsdWUuXG5cdFx0fSBlbHNlIGlmICggXCJsYWJlbFwiIGluIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kaXNhYmxlZCA9PT0gZGlzYWJsZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gUmVtYWluaW5nIGVsZW1lbnRzIGFyZSBuZWl0aGVyIDplbmFibGVkIG5vciA6ZGlzYWJsZWRcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBwb3NpdGlvbmFsc1xuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlUG9zaXRpb25hbFBzZXVkbyggZm4gKSB7XG5cdHJldHVybiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIGFyZ3VtZW50ICkge1xuXHRcdGFyZ3VtZW50ID0gK2FyZ3VtZW50O1xuXHRcdHJldHVybiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlZWQsIG1hdGNoZXMgKSB7XG5cdFx0XHR2YXIgaixcblx0XHRcdFx0bWF0Y2hJbmRleGVzID0gZm4oIFtdLCBzZWVkLmxlbmd0aCwgYXJndW1lbnQgKSxcblx0XHRcdFx0aSA9IG1hdGNoSW5kZXhlcy5sZW5ndGg7XG5cblx0XHRcdC8vIE1hdGNoIGVsZW1lbnRzIGZvdW5kIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhlc1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggc2VlZFsgKGogPSBtYXRjaEluZGV4ZXNbaV0pIF0gKSB7XG5cdFx0XHRcdFx0c2VlZFtqXSA9ICEobWF0Y2hlc1tqXSA9IHNlZWRbal0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBhIG5vZGUgZm9yIHZhbGlkaXR5IGFzIGEgU2l6emxlIGNvbnRleHRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3Q9fSBjb250ZXh0XG4gKiBAcmV0dXJucyB7RWxlbWVudHxPYmplY3R8Qm9vbGVhbn0gVGhlIGlucHV0IG5vZGUgaWYgYWNjZXB0YWJsZSwgb3RoZXJ3aXNlIGEgZmFsc3kgdmFsdWVcbiAqL1xuZnVuY3Rpb24gdGVzdENvbnRleHQoIGNvbnRleHQgKSB7XG5cdHJldHVybiBjb250ZXh0ICYmIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lICE9PSBcInVuZGVmaW5lZFwiICYmIGNvbnRleHQ7XG59XG5cbi8vIEV4cG9zZSBzdXBwb3J0IHZhcnMgZm9yIGNvbnZlbmllbmNlXG5zdXBwb3J0ID0gU2l6emxlLnN1cHBvcnQgPSB7fTtcblxuLyoqXG4gKiBEZXRlY3RzIFhNTCBub2Rlc1xuICogQHBhcmFtIHtFbGVtZW50fE9iamVjdH0gZWxlbSBBbiBlbGVtZW50IG9yIGEgZG9jdW1lbnRcbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmZiBlbGVtIGlzIGEgbm9uLUhUTUwgWE1MIG5vZGVcbiAqL1xuaXNYTUwgPSBTaXp6bGUuaXNYTUwgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0Ly8gZG9jdW1lbnRFbGVtZW50IGlzIHZlcmlmaWVkIGZvciBjYXNlcyB3aGVyZSBpdCBkb2Vzbid0IHlldCBleGlzdFxuXHQvLyAoc3VjaCBhcyBsb2FkaW5nIGlmcmFtZXMgaW4gSUUgLSAjNDgzMylcblx0dmFyIGRvY3VtZW50RWxlbWVudCA9IGVsZW0gJiYgKGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtKS5kb2N1bWVudEVsZW1lbnQ7XG5cdHJldHVybiBkb2N1bWVudEVsZW1lbnQgPyBkb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgIT09IFwiSFRNTFwiIDogZmFsc2U7XG59O1xuXG4vKipcbiAqIFNldHMgZG9jdW1lbnQtcmVsYXRlZCB2YXJpYWJsZXMgb25jZSBiYXNlZCBvbiB0aGUgY3VycmVudCBkb2N1bWVudFxuICogQHBhcmFtIHtFbGVtZW50fE9iamVjdH0gW2RvY10gQW4gZWxlbWVudCBvciBkb2N1bWVudCBvYmplY3QgdG8gdXNlIHRvIHNldCB0aGUgZG9jdW1lbnRcbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqL1xuc2V0RG9jdW1lbnQgPSBTaXp6bGUuc2V0RG9jdW1lbnQgPSBmdW5jdGlvbiggbm9kZSApIHtcblx0dmFyIGhhc0NvbXBhcmUsIHN1YldpbmRvdyxcblx0XHRkb2MgPSBub2RlID8gbm9kZS5vd25lckRvY3VtZW50IHx8IG5vZGUgOiBwcmVmZXJyZWREb2M7XG5cblx0Ly8gUmV0dXJuIGVhcmx5IGlmIGRvYyBpcyBpbnZhbGlkIG9yIGFscmVhZHkgc2VsZWN0ZWRcblx0aWYgKCBkb2MgPT09IGRvY3VtZW50IHx8IGRvYy5ub2RlVHlwZSAhPT0gOSB8fCAhZG9jLmRvY3VtZW50RWxlbWVudCApIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQ7XG5cdH1cblxuXHQvLyBVcGRhdGUgZ2xvYmFsIHZhcmlhYmxlc1xuXHRkb2N1bWVudCA9IGRvYztcblx0ZG9jRWxlbSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblx0ZG9jdW1lbnRJc0hUTUwgPSAhaXNYTUwoIGRvY3VtZW50ICk7XG5cblx0Ly8gU3VwcG9ydDogSUUgOS0xMSwgRWRnZVxuXHQvLyBBY2Nlc3NpbmcgaWZyYW1lIGRvY3VtZW50cyBhZnRlciB1bmxvYWQgdGhyb3dzIFwicGVybWlzc2lvbiBkZW5pZWRcIiBlcnJvcnMgKGpRdWVyeSAjMTM5MzYpXG5cdGlmICggcHJlZmVycmVkRG9jICE9PSBkb2N1bWVudCAmJlxuXHRcdChzdWJXaW5kb3cgPSBkb2N1bWVudC5kZWZhdWx0VmlldykgJiYgc3ViV2luZG93LnRvcCAhPT0gc3ViV2luZG93ICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgMTEsIEVkZ2Vcblx0XHRpZiAoIHN1YldpbmRvdy5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0c3ViV2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIFwidW5sb2FkXCIsIHVubG9hZEhhbmRsZXIsIGZhbHNlICk7XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA5IC0gMTAgb25seVxuXHRcdH0gZWxzZSBpZiAoIHN1YldpbmRvdy5hdHRhY2hFdmVudCApIHtcblx0XHRcdHN1YldpbmRvdy5hdHRhY2hFdmVudCggXCJvbnVubG9hZFwiLCB1bmxvYWRIYW5kbGVyICk7XG5cdFx0fVxuXHR9XG5cblx0LyogQXR0cmlidXRlc1xuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cblx0Ly8gU3VwcG9ydDogSUU8OFxuXHQvLyBWZXJpZnkgdGhhdCBnZXRBdHRyaWJ1dGUgcmVhbGx5IHJldHVybnMgYXR0cmlidXRlcyBhbmQgbm90IHByb3BlcnRpZXNcblx0Ly8gKGV4Y2VwdGluZyBJRTggYm9vbGVhbnMpXG5cdHN1cHBvcnQuYXR0cmlidXRlcyA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZWwuY2xhc3NOYW1lID0gXCJpXCI7XG5cdFx0cmV0dXJuICFlbC5nZXRBdHRyaWJ1dGUoXCJjbGFzc05hbWVcIik7XG5cdH0pO1xuXG5cdC8qIGdldEVsZW1lbnQocylCeSpcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRzQnlUYWdOYW1lKFwiKlwiKSByZXR1cm5zIG9ubHkgZWxlbWVudHNcblx0c3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZWwuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoXCJcIikgKTtcblx0XHRyZXR1cm4gIWVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiKlwiKS5sZW5ndGg7XG5cdH0pO1xuXG5cdC8vIFN1cHBvcnQ6IElFPDlcblx0c3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lID0gcm5hdGl2ZS50ZXN0KCBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICk7XG5cblx0Ly8gU3VwcG9ydDogSUU8MTBcblx0Ly8gQ2hlY2sgaWYgZ2V0RWxlbWVudEJ5SWQgcmV0dXJucyBlbGVtZW50cyBieSBuYW1lXG5cdC8vIFRoZSBicm9rZW4gZ2V0RWxlbWVudEJ5SWQgbWV0aG9kcyBkb24ndCBwaWNrIHVwIHByb2dyYW1tYXRpY2FsbHktc2V0IG5hbWVzLFxuXHQvLyBzbyB1c2UgYSByb3VuZGFib3V0IGdldEVsZW1lbnRzQnlOYW1lIHRlc3Rcblx0c3VwcG9ydC5nZXRCeUlkID0gYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0XHRkb2NFbGVtLmFwcGVuZENoaWxkKCBlbCApLmlkID0gZXhwYW5kbztcblx0XHRyZXR1cm4gIWRvY3VtZW50LmdldEVsZW1lbnRzQnlOYW1lIHx8ICFkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSggZXhwYW5kbyApLmxlbmd0aDtcblx0fSk7XG5cblx0Ly8gSUQgZmlsdGVyIGFuZCBmaW5kXG5cdGlmICggc3VwcG9ydC5nZXRCeUlkICkge1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSBmdW5jdGlvbiggaWQgKSB7XG5cdFx0XHR2YXIgYXR0cklkID0gaWQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKFwiaWRcIikgPT09IGF0dHJJZDtcblx0XHRcdH07XG5cdFx0fTtcblx0XHRFeHByLmZpbmRbXCJJRFwiXSA9IGZ1bmN0aW9uKCBpZCwgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQgIT09IFwidW5kZWZpbmVkXCIgJiYgZG9jdW1lbnRJc0hUTUwgKSB7XG5cdFx0XHRcdHZhciBlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggaWQgKTtcblx0XHRcdFx0cmV0dXJuIGVsZW0gPyBbIGVsZW0gXSA6IFtdO1xuXHRcdFx0fVxuXHRcdH07XG5cdH0gZWxzZSB7XG5cdFx0RXhwci5maWx0ZXJbXCJJRFwiXSA9ICBmdW5jdGlvbiggaWQgKSB7XG5cdFx0XHR2YXIgYXR0cklkID0gaWQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIG5vZGUgPSB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGVOb2RlICE9PSBcInVuZGVmaW5lZFwiICYmXG5cdFx0XHRcdFx0ZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKFwiaWRcIik7XG5cdFx0XHRcdHJldHVybiBub2RlICYmIG5vZGUudmFsdWUgPT09IGF0dHJJZDtcblx0XHRcdH07XG5cdFx0fTtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDYgLSA3IG9ubHlcblx0XHQvLyBnZXRFbGVtZW50QnlJZCBpcyBub3QgcmVsaWFibGUgYXMgYSBmaW5kIHNob3J0Y3V0XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgbm9kZSwgaSwgZWxlbXMsXG5cdFx0XHRcdFx0ZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cblx0XHRcdFx0aWYgKCBlbGVtICkge1xuXG5cdFx0XHRcdFx0Ly8gVmVyaWZ5IHRoZSBpZCBhdHRyaWJ1dGVcblx0XHRcdFx0XHRub2RlID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKFwiaWRcIik7XG5cdFx0XHRcdFx0aWYgKCBub2RlICYmIG5vZGUudmFsdWUgPT09IGlkICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIFsgZWxlbSBdO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIEZhbGwgYmFjayBvbiBnZXRFbGVtZW50c0J5TmFtZVxuXHRcdFx0XHRcdGVsZW1zID0gY29udGV4dC5nZXRFbGVtZW50c0J5TmFtZSggaWQgKTtcblx0XHRcdFx0XHRpID0gMDtcblx0XHRcdFx0XHR3aGlsZSAoIChlbGVtID0gZWxlbXNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0XHRub2RlID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKFwiaWRcIik7XG5cdFx0XHRcdFx0XHRpZiAoIG5vZGUgJiYgbm9kZS52YWx1ZSA9PT0gaWQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBbIGVsZW0gXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gW107XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cdC8vIFRhZ1xuXHRFeHByLmZpbmRbXCJUQUdcIl0gPSBzdXBwb3J0LmdldEVsZW1lbnRzQnlUYWdOYW1lID9cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIHRhZyApO1xuXG5cdFx0XHQvLyBEb2N1bWVudEZyYWdtZW50IG5vZGVzIGRvbid0IGhhdmUgZ0VCVE5cblx0XHRcdH0gZWxzZSBpZiAoIHN1cHBvcnQucXNhICkge1xuXHRcdFx0XHRyZXR1cm4gY29udGV4dC5xdWVyeVNlbGVjdG9yQWxsKCB0YWcgKTtcblx0XHRcdH1cblx0XHR9IDpcblxuXHRcdGZ1bmN0aW9uKCB0YWcsIGNvbnRleHQgKSB7XG5cdFx0XHR2YXIgZWxlbSxcblx0XHRcdFx0dG1wID0gW10sXG5cdFx0XHRcdGkgPSAwLFxuXHRcdFx0XHQvLyBCeSBoYXBweSBjb2luY2lkZW5jZSwgYSAoYnJva2VuKSBnRUJUTiBhcHBlYXJzIG9uIERvY3VtZW50RnJhZ21lbnQgbm9kZXMgdG9vXG5cdFx0XHRcdHJlc3VsdHMgPSBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRmlsdGVyIG91dCBwb3NzaWJsZSBjb21tZW50c1xuXHRcdFx0aWYgKCB0YWcgPT09IFwiKlwiICkge1xuXHRcdFx0XHR3aGlsZSAoIChlbGVtID0gcmVzdWx0c1tpKytdKSApIHtcblx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHR0bXAucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiB0bXA7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHR9O1xuXG5cdC8vIENsYXNzXG5cdEV4cHIuZmluZFtcIkNMQVNTXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIGZ1bmN0aW9uKCBjbGFzc05hbWUsIGNvbnRleHQgKSB7XG5cdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSggY2xhc3NOYW1lICk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qIFFTQS9tYXRjaGVzU2VsZWN0b3Jcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIFFTQSBhbmQgbWF0Y2hlc1NlbGVjdG9yIHN1cHBvcnRcblxuXHQvLyBtYXRjaGVzU2VsZWN0b3IoOmFjdGl2ZSkgcmVwb3J0cyBmYWxzZSB3aGVuIHRydWUgKElFOS9PcGVyYSAxMS41KVxuXHRyYnVnZ3lNYXRjaGVzID0gW107XG5cblx0Ly8gcVNhKDpmb2N1cykgcmVwb3J0cyBmYWxzZSB3aGVuIHRydWUgKENocm9tZSAyMSlcblx0Ly8gV2UgYWxsb3cgdGhpcyBiZWNhdXNlIG9mIGEgYnVnIGluIElFOC85IHRoYXQgdGhyb3dzIGFuIGVycm9yXG5cdC8vIHdoZW5ldmVyIGBkb2N1bWVudC5hY3RpdmVFbGVtZW50YCBpcyBhY2Nlc3NlZCBvbiBhbiBpZnJhbWVcblx0Ly8gU28sIHdlIGFsbG93IDpmb2N1cyB0byBwYXNzIHRocm91Z2ggUVNBIGFsbCB0aGUgdGltZSB0byBhdm9pZCB0aGUgSUUgZXJyb3Jcblx0Ly8gU2VlIGh0dHBzOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMzM3OFxuXHRyYnVnZ3lRU0EgPSBbXTtcblxuXHRpZiAoIChzdXBwb3J0LnFzYSA9IHJuYXRpdmUudGVzdCggZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCApKSApIHtcblx0XHQvLyBCdWlsZCBRU0EgcmVnZXhcblx0XHQvLyBSZWdleCBzdHJhdGVneSBhZG9wdGVkIGZyb20gRGllZ28gUGVyaW5pXG5cdFx0YXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0XHRcdC8vIFNlbGVjdCBpcyBzZXQgdG8gZW1wdHkgc3RyaW5nIG9uIHB1cnBvc2Vcblx0XHRcdC8vIFRoaXMgaXMgdG8gdGVzdCBJRSdzIHRyZWF0bWVudCBvZiBub3QgZXhwbGljaXRseVxuXHRcdFx0Ly8gc2V0dGluZyBhIGJvb2xlYW4gY29udGVudCBhdHRyaWJ1dGUsXG5cdFx0XHQvLyBzaW5jZSBpdHMgcHJlc2VuY2Ugc2hvdWxkIGJlIGVub3VnaFxuXHRcdFx0Ly8gaHR0cHM6Ly9idWdzLmpxdWVyeS5jb20vdGlja2V0LzEyMzU5XG5cdFx0XHRkb2NFbGVtLmFwcGVuZENoaWxkKCBlbCApLmlubmVySFRNTCA9IFwiPGEgaWQ9J1wiICsgZXhwYW5kbyArIFwiJz48L2E+XCIgK1xuXHRcdFx0XHRcIjxzZWxlY3QgaWQ9J1wiICsgZXhwYW5kbyArIFwiLVxcclxcXFwnIG1zYWxsb3djYXB0dXJlPScnPlwiICtcblx0XHRcdFx0XCI8b3B0aW9uIHNlbGVjdGVkPScnPjwvb3B0aW9uPjwvc2VsZWN0PlwiO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRTgsIE9wZXJhIDExLTEyLjE2XG5cdFx0XHQvLyBOb3RoaW5nIHNob3VsZCBiZSBzZWxlY3RlZCB3aGVuIGVtcHR5IHN0cmluZ3MgZm9sbG93IF49IG9yICQ9IG9yICo9XG5cdFx0XHQvLyBUaGUgdGVzdCBhdHRyaWJ1dGUgbXVzdCBiZSB1bmtub3duIGluIE9wZXJhIGJ1dCBcInNhZmVcIiBmb3IgV2luUlRcblx0XHRcdC8vIGh0dHBzOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvaWUvaGg0NjUzODguYXNweCNhdHRyaWJ1dGVfc2VjdGlvblxuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW21zYWxsb3djYXB0dXJlXj0nJ11cIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCJbKl4kXT1cIiArIHdoaXRlc3BhY2UgKyBcIiooPzonJ3xcXFwiXFxcIilcIiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRThcblx0XHRcdC8vIEJvb2xlYW4gYXR0cmlidXRlcyBhbmQgXCJ2YWx1ZVwiIGFyZSBub3QgdHJlYXRlZCBjb3JyZWN0bHlcblx0XHRcdGlmICggIWVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCJbc2VsZWN0ZWRdXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiXFxcXFtcIiArIHdoaXRlc3BhY2UgKyBcIiooPzp2YWx1ZXxcIiArIGJvb2xlYW5zICsgXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lPDI5LCBBbmRyb2lkPDQuNCwgU2FmYXJpPDcuMCssIGlPUzw3LjArLCBQaGFudG9tSlM8MS45LjgrXG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKCBcIltpZH49XCIgKyBleHBhbmRvICsgXCItXVwiICkubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaChcIn49XCIpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBXZWJraXQvT3BlcmEgLSA6Y2hlY2tlZCBzaG91bGQgcmV0dXJuIHNlbGVjdGVkIG9wdGlvbiBlbGVtZW50c1xuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvMjAxMS9SRUMtY3NzMy1zZWxlY3RvcnMtMjAxMTA5MjkvI2NoZWNrZWRcblx0XHRcdC8vIElFOCB0aHJvd3MgZXJyb3IgaGVyZSBhbmQgd2lsbCBub3Qgc2VlIGxhdGVyIHRlc3RzXG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKFwiOmNoZWNrZWRcIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaChcIjpjaGVja2VkXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCssIGlPUyA4K1xuXHRcdFx0Ly8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEzNjg1MVxuXHRcdFx0Ly8gSW4tcGFnZSBgc2VsZWN0b3IjaWQgc2libGluZy1jb21iaW5hdG9yIHNlbGVjdG9yYCBmYWlsc1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbCggXCJhI1wiICsgZXhwYW5kbyArIFwiKypcIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCIuIy4rWyt+XVwiKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHRlbC5pbm5lckhUTUwgPSBcIjxhIGhyZWY9JycgZGlzYWJsZWQ9J2Rpc2FibGVkJz48L2E+XCIgK1xuXHRcdFx0XHRcIjxzZWxlY3QgZGlzYWJsZWQ9J2Rpc2FibGVkJz48b3B0aW9uLz48L3NlbGVjdD5cIjtcblxuXHRcdFx0Ly8gU3VwcG9ydDogV2luZG93cyA4IE5hdGl2ZSBBcHBzXG5cdFx0XHQvLyBUaGUgdHlwZSBhbmQgbmFtZSBhdHRyaWJ1dGVzIGFyZSByZXN0cmljdGVkIGR1cmluZyAuaW5uZXJIVE1MIGFzc2lnbm1lbnRcblx0XHRcdHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiKTtcblx0XHRcdGlucHV0LnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIFwiaGlkZGVuXCIgKTtcblx0XHRcdGVsLmFwcGVuZENoaWxkKCBpbnB1dCApLnNldEF0dHJpYnV0ZSggXCJuYW1lXCIsIFwiRFwiICk7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOFxuXHRcdFx0Ly8gRW5mb3JjZSBjYXNlLXNlbnNpdGl2aXR5IG9mIG5hbWUgYXR0cmlidXRlXG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCJbbmFtZT1kXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIm5hbWVcIiArIHdoaXRlc3BhY2UgKyBcIipbKl4kfCF+XT89XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRkYgMy41IC0gOmVuYWJsZWQvOmRpc2FibGVkIGFuZCBoaWRkZW4gZWxlbWVudHMgKGhpZGRlbiBlbGVtZW50cyBhcmUgc3RpbGwgZW5hYmxlZClcblx0XHRcdC8vIElFOCB0aHJvd3MgZXJyb3IgaGVyZSBhbmQgd2lsbCBub3Qgc2VlIGxhdGVyIHRlc3RzXG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZW5hYmxlZFwiKS5sZW5ndGggIT09IDIgKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIjplbmFibGVkXCIsIFwiOmRpc2FibGVkXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU5LTExK1xuXHRcdFx0Ly8gSUUncyA6ZGlzYWJsZWQgc2VsZWN0b3IgZG9lcyBub3QgcGljayB1cCB0aGUgY2hpbGRyZW4gb2YgZGlzYWJsZWQgZmllbGRzZXRzXG5cdFx0XHRkb2NFbGVtLmFwcGVuZENoaWxkKCBlbCApLmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdGlmICggZWwucXVlcnlTZWxlY3RvckFsbChcIjpkaXNhYmxlZFwiKS5sZW5ndGggIT09IDIgKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIjplbmFibGVkXCIsIFwiOmRpc2FibGVkXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gT3BlcmEgMTAtMTEgZG9lcyBub3QgdGhyb3cgb24gcG9zdC1jb21tYSBpbnZhbGlkIHBzZXVkb3Ncblx0XHRcdGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCIqLDp4XCIpO1xuXHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCIsLio6XCIpO1xuXHRcdH0pO1xuXHR9XG5cblx0aWYgKCAoc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgPSBybmF0aXZlLnRlc3QoIChtYXRjaGVzID0gZG9jRWxlbS5tYXRjaGVzIHx8XG5cdFx0ZG9jRWxlbS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1vek1hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ub01hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ubXNNYXRjaGVzU2VsZWN0b3IpICkpICkge1xuXG5cdFx0YXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0XHRcdC8vIENoZWNrIHRvIHNlZSBpZiBpdCdzIHBvc3NpYmxlIHRvIGRvIG1hdGNoZXNTZWxlY3RvclxuXHRcdFx0Ly8gb24gYSBkaXNjb25uZWN0ZWQgbm9kZSAoSUUgOSlcblx0XHRcdHN1cHBvcnQuZGlzY29ubmVjdGVkTWF0Y2ggPSBtYXRjaGVzLmNhbGwoIGVsLCBcIipcIiApO1xuXG5cdFx0XHQvLyBUaGlzIHNob3VsZCBmYWlsIHdpdGggYW4gZXhjZXB0aW9uXG5cdFx0XHQvLyBHZWNrbyBkb2VzIG5vdCBlcnJvciwgcmV0dXJucyBmYWxzZSBpbnN0ZWFkXG5cdFx0XHRtYXRjaGVzLmNhbGwoIGVsLCBcIltzIT0nJ106eFwiICk7XG5cdFx0XHRyYnVnZ3lNYXRjaGVzLnB1c2goIFwiIT1cIiwgcHNldWRvcyApO1xuXHRcdH0pO1xuXHR9XG5cblx0cmJ1Z2d5UVNBID0gcmJ1Z2d5UVNBLmxlbmd0aCAmJiBuZXcgUmVnRXhwKCByYnVnZ3lRU0Euam9pbihcInxcIikgKTtcblx0cmJ1Z2d5TWF0Y2hlcyA9IHJidWdneU1hdGNoZXMubGVuZ3RoICYmIG5ldyBSZWdFeHAoIHJidWdneU1hdGNoZXMuam9pbihcInxcIikgKTtcblxuXHQvKiBDb250YWluc1xuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cdGhhc0NvbXBhcmUgPSBybmF0aXZlLnRlc3QoIGRvY0VsZW0uY29tcGFyZURvY3VtZW50UG9zaXRpb24gKTtcblxuXHQvLyBFbGVtZW50IGNvbnRhaW5zIGFub3RoZXJcblx0Ly8gUHVycG9zZWZ1bGx5IHNlbGYtZXhjbHVzaXZlXG5cdC8vIEFzIGluLCBhbiBlbGVtZW50IGRvZXMgbm90IGNvbnRhaW4gaXRzZWxmXG5cdGNvbnRhaW5zID0gaGFzQ29tcGFyZSB8fCBybmF0aXZlLnRlc3QoIGRvY0VsZW0uY29udGFpbnMgKSA/XG5cdFx0ZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0XHR2YXIgYWRvd24gPSBhLm5vZGVUeXBlID09PSA5ID8gYS5kb2N1bWVudEVsZW1lbnQgOiBhLFxuXHRcdFx0XHRidXAgPSBiICYmIGIucGFyZW50Tm9kZTtcblx0XHRcdHJldHVybiBhID09PSBidXAgfHwgISEoIGJ1cCAmJiBidXAubm9kZVR5cGUgPT09IDEgJiYgKFxuXHRcdFx0XHRhZG93bi5jb250YWlucyA/XG5cdFx0XHRcdFx0YWRvd24uY29udGFpbnMoIGJ1cCApIDpcblx0XHRcdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICYmIGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGJ1cCApICYgMTZcblx0XHRcdCkpO1xuXHRcdH0gOlxuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0aWYgKCBiICkge1xuXHRcdFx0XHR3aGlsZSAoIChiID0gYi5wYXJlbnROb2RlKSApIHtcblx0XHRcdFx0XHRpZiAoIGIgPT09IGEgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9O1xuXG5cdC8qIFNvcnRpbmdcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIERvY3VtZW50IG9yZGVyIHNvcnRpbmdcblx0c29ydE9yZGVyID0gaGFzQ29tcGFyZSA/XG5cdGZ1bmN0aW9uKCBhLCBiICkge1xuXG5cdFx0Ly8gRmxhZyBmb3IgZHVwbGljYXRlIHJlbW92YWxcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXG5cdFx0Ly8gU29ydCBvbiBtZXRob2QgZXhpc3RlbmNlIGlmIG9ubHkgb25lIGlucHV0IGhhcyBjb21wYXJlRG9jdW1lbnRQb3NpdGlvblxuXHRcdHZhciBjb21wYXJlID0gIWEuY29tcGFyZURvY3VtZW50UG9zaXRpb24gLSAhYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbjtcblx0XHRpZiAoIGNvbXBhcmUgKSB7XG5cdFx0XHRyZXR1cm4gY29tcGFyZTtcblx0XHR9XG5cblx0XHQvLyBDYWxjdWxhdGUgcG9zaXRpb24gaWYgYm90aCBpbnB1dHMgYmVsb25nIHRvIHRoZSBzYW1lIGRvY3VtZW50XG5cdFx0Y29tcGFyZSA9ICggYS5vd25lckRvY3VtZW50IHx8IGEgKSA9PT0gKCBiLm93bmVyRG9jdW1lbnQgfHwgYiApID9cblx0XHRcdGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGIgKSA6XG5cblx0XHRcdC8vIE90aGVyd2lzZSB3ZSBrbm93IHRoZXkgYXJlIGRpc2Nvbm5lY3RlZFxuXHRcdFx0MTtcblxuXHRcdC8vIERpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdGlmICggY29tcGFyZSAmIDEgfHxcblx0XHRcdCghc3VwcG9ydC5zb3J0RGV0YWNoZWQgJiYgYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiggYSApID09PSBjb21wYXJlKSApIHtcblxuXHRcdFx0Ly8gQ2hvb3NlIHRoZSBmaXJzdCBlbGVtZW50IHRoYXQgaXMgcmVsYXRlZCB0byBvdXIgcHJlZmVycmVkIGRvY3VtZW50XG5cdFx0XHRpZiAoIGEgPT09IGRvY3VtZW50IHx8IGEub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYSkgKSB7XG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHRcdGlmICggYiA9PT0gZG9jdW1lbnQgfHwgYi5vd25lckRvY3VtZW50ID09PSBwcmVmZXJyZWREb2MgJiYgY29udGFpbnMocHJlZmVycmVkRG9jLCBiKSApIHtcblx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE1haW50YWluIG9yaWdpbmFsIG9yZGVyXG5cdFx0XHRyZXR1cm4gc29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXHRcdH1cblxuXHRcdHJldHVybiBjb21wYXJlICYgNCA/IC0xIDogMTtcblx0fSA6XG5cdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdC8vIEV4aXQgZWFybHkgaWYgdGhlIG5vZGVzIGFyZSBpZGVudGljYWxcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0YXVwID0gYS5wYXJlbnROb2RlLFxuXHRcdFx0YnVwID0gYi5wYXJlbnROb2RlLFxuXHRcdFx0YXAgPSBbIGEgXSxcblx0XHRcdGJwID0gWyBiIF07XG5cblx0XHQvLyBQYXJlbnRsZXNzIG5vZGVzIGFyZSBlaXRoZXIgZG9jdW1lbnRzIG9yIGRpc2Nvbm5lY3RlZFxuXHRcdGlmICggIWF1cCB8fCAhYnVwICkge1xuXHRcdFx0cmV0dXJuIGEgPT09IGRvY3VtZW50ID8gLTEgOlxuXHRcdFx0XHRiID09PSBkb2N1bWVudCA/IDEgOlxuXHRcdFx0XHRhdXAgPyAtMSA6XG5cdFx0XHRcdGJ1cCA/IDEgOlxuXHRcdFx0XHRzb3J0SW5wdXQgP1xuXHRcdFx0XHQoIGluZGV4T2YoIHNvcnRJbnB1dCwgYSApIC0gaW5kZXhPZiggc29ydElucHV0LCBiICkgKSA6XG5cdFx0XHRcdDA7XG5cblx0XHQvLyBJZiB0aGUgbm9kZXMgYXJlIHNpYmxpbmdzLCB3ZSBjYW4gZG8gYSBxdWljayBjaGVja1xuXHRcdH0gZWxzZSBpZiAoIGF1cCA9PT0gYnVwICkge1xuXHRcdFx0cmV0dXJuIHNpYmxpbmdDaGVjayggYSwgYiApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSB3ZSBuZWVkIGZ1bGwgbGlzdHMgb2YgdGhlaXIgYW5jZXN0b3JzIGZvciBjb21wYXJpc29uXG5cdFx0Y3VyID0gYTtcblx0XHR3aGlsZSAoIChjdXIgPSBjdXIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRhcC51bnNoaWZ0KCBjdXIgKTtcblx0XHR9XG5cdFx0Y3VyID0gYjtcblx0XHR3aGlsZSAoIChjdXIgPSBjdXIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRicC51bnNoaWZ0KCBjdXIgKTtcblx0XHR9XG5cblx0XHQvLyBXYWxrIGRvd24gdGhlIHRyZWUgbG9va2luZyBmb3IgYSBkaXNjcmVwYW5jeVxuXHRcdHdoaWxlICggYXBbaV0gPT09IGJwW2ldICkge1xuXHRcdFx0aSsrO1xuXHRcdH1cblxuXHRcdHJldHVybiBpID9cblx0XHRcdC8vIERvIGEgc2libGluZyBjaGVjayBpZiB0aGUgbm9kZXMgaGF2ZSBhIGNvbW1vbiBhbmNlc3RvclxuXHRcdFx0c2libGluZ0NoZWNrKCBhcFtpXSwgYnBbaV0gKSA6XG5cblx0XHRcdC8vIE90aGVyd2lzZSBub2RlcyBpbiBvdXIgZG9jdW1lbnQgc29ydCBmaXJzdFxuXHRcdFx0YXBbaV0gPT09IHByZWZlcnJlZERvYyA/IC0xIDpcblx0XHRcdGJwW2ldID09PSBwcmVmZXJyZWREb2MgPyAxIDpcblx0XHRcdDA7XG5cdH07XG5cblx0cmV0dXJuIGRvY3VtZW50O1xufTtcblxuU2l6emxlLm1hdGNoZXMgPSBmdW5jdGlvbiggZXhwciwgZWxlbWVudHMgKSB7XG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIG51bGwsIG51bGwsIGVsZW1lbnRzICk7XG59O1xuXG5TaXp6bGUubWF0Y2hlc1NlbGVjdG9yID0gZnVuY3Rpb24oIGVsZW0sIGV4cHIgKSB7XG5cdC8vIFNldCBkb2N1bWVudCB2YXJzIGlmIG5lZWRlZFxuXHRpZiAoICggZWxlbS5vd25lckRvY3VtZW50IHx8IGVsZW0gKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0c2V0RG9jdW1lbnQoIGVsZW0gKTtcblx0fVxuXG5cdC8vIE1ha2Ugc3VyZSB0aGF0IGF0dHJpYnV0ZSBzZWxlY3RvcnMgYXJlIHF1b3RlZFxuXHRleHByID0gZXhwci5yZXBsYWNlKCByYXR0cmlidXRlUXVvdGVzLCBcIj0nJDEnXVwiICk7XG5cblx0aWYgKCBzdXBwb3J0Lm1hdGNoZXNTZWxlY3RvciAmJiBkb2N1bWVudElzSFRNTCAmJlxuXHRcdCFjb21waWxlckNhY2hlWyBleHByICsgXCIgXCIgXSAmJlxuXHRcdCggIXJidWdneU1hdGNoZXMgfHwgIXJidWdneU1hdGNoZXMudGVzdCggZXhwciApICkgJiZcblx0XHQoICFyYnVnZ3lRU0EgICAgIHx8ICFyYnVnZ3lRU0EudGVzdCggZXhwciApICkgKSB7XG5cblx0XHR0cnkge1xuXHRcdFx0dmFyIHJldCA9IG1hdGNoZXMuY2FsbCggZWxlbSwgZXhwciApO1xuXG5cdFx0XHQvLyBJRSA5J3MgbWF0Y2hlc1NlbGVjdG9yIHJldHVybnMgZmFsc2Ugb24gZGlzY29ubmVjdGVkIG5vZGVzXG5cdFx0XHRpZiAoIHJldCB8fCBzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoIHx8XG5cdFx0XHRcdFx0Ly8gQXMgd2VsbCwgZGlzY29ubmVjdGVkIG5vZGVzIGFyZSBzYWlkIHRvIGJlIGluIGEgZG9jdW1lbnRcblx0XHRcdFx0XHQvLyBmcmFnbWVudCBpbiBJRSA5XG5cdFx0XHRcdFx0ZWxlbS5kb2N1bWVudCAmJiBlbGVtLmRvY3VtZW50Lm5vZGVUeXBlICE9PSAxMSApIHtcblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlKSB7fVxuXHR9XG5cblx0cmV0dXJuIFNpenpsZSggZXhwciwgZG9jdW1lbnQsIG51bGwsIFsgZWxlbSBdICkubGVuZ3RoID4gMDtcbn07XG5cblNpenpsZS5jb250YWlucyA9IGZ1bmN0aW9uKCBjb250ZXh0LCBlbGVtICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0ICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBjb250ZXh0ICk7XG5cdH1cblx0cmV0dXJuIGNvbnRhaW5zKCBjb250ZXh0LCBlbGVtICk7XG59O1xuXG5TaXp6bGUuYXR0ciA9IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHR2YXIgZm4gPSBFeHByLmF0dHJIYW5kbGVbIG5hbWUudG9Mb3dlckNhc2UoKSBdLFxuXHRcdC8vIERvbid0IGdldCBmb29sZWQgYnkgT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzIChqUXVlcnkgIzEzODA3KVxuXHRcdHZhbCA9IGZuICYmIGhhc093bi5jYWxsKCBFeHByLmF0dHJIYW5kbGUsIG5hbWUudG9Mb3dlckNhc2UoKSApID9cblx0XHRcdGZuKCBlbGVtLCBuYW1lLCAhZG9jdW1lbnRJc0hUTUwgKSA6XG5cdFx0XHR1bmRlZmluZWQ7XG5cblx0cmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkID9cblx0XHR2YWwgOlxuXHRcdHN1cHBvcnQuYXR0cmlidXRlcyB8fCAhZG9jdW1lbnRJc0hUTUwgP1xuXHRcdFx0ZWxlbS5nZXRBdHRyaWJ1dGUoIG5hbWUgKSA6XG5cdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKG5hbWUpKSAmJiB2YWwuc3BlY2lmaWVkID9cblx0XHRcdFx0dmFsLnZhbHVlIDpcblx0XHRcdFx0bnVsbDtcbn07XG5cblNpenpsZS5lc2NhcGUgPSBmdW5jdGlvbiggc2VsICkge1xuXHRyZXR1cm4gKHNlbCArIFwiXCIpLnJlcGxhY2UoIHJjc3Nlc2NhcGUsIGZjc3Nlc2NhcGUgKTtcbn07XG5cblNpenpsZS5lcnJvciA9IGZ1bmN0aW9uKCBtc2cgKSB7XG5cdHRocm93IG5ldyBFcnJvciggXCJTeW50YXggZXJyb3IsIHVucmVjb2duaXplZCBleHByZXNzaW9uOiBcIiArIG1zZyApO1xufTtcblxuLyoqXG4gKiBEb2N1bWVudCBzb3J0aW5nIGFuZCByZW1vdmluZyBkdXBsaWNhdGVzXG4gKiBAcGFyYW0ge0FycmF5TGlrZX0gcmVzdWx0c1xuICovXG5TaXp6bGUudW5pcXVlU29ydCA9IGZ1bmN0aW9uKCByZXN1bHRzICkge1xuXHR2YXIgZWxlbSxcblx0XHRkdXBsaWNhdGVzID0gW10sXG5cdFx0aiA9IDAsXG5cdFx0aSA9IDA7XG5cblx0Ly8gVW5sZXNzIHdlICprbm93KiB3ZSBjYW4gZGV0ZWN0IGR1cGxpY2F0ZXMsIGFzc3VtZSB0aGVpciBwcmVzZW5jZVxuXHRoYXNEdXBsaWNhdGUgPSAhc3VwcG9ydC5kZXRlY3REdXBsaWNhdGVzO1xuXHRzb3J0SW5wdXQgPSAhc3VwcG9ydC5zb3J0U3RhYmxlICYmIHJlc3VsdHMuc2xpY2UoIDAgKTtcblx0cmVzdWx0cy5zb3J0KCBzb3J0T3JkZXIgKTtcblxuXHRpZiAoIGhhc0R1cGxpY2F0ZSApIHtcblx0XHR3aGlsZSAoIChlbGVtID0gcmVzdWx0c1tpKytdKSApIHtcblx0XHRcdGlmICggZWxlbSA9PT0gcmVzdWx0c1sgaSBdICkge1xuXHRcdFx0XHRqID0gZHVwbGljYXRlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHdoaWxlICggai0tICkge1xuXHRcdFx0cmVzdWx0cy5zcGxpY2UoIGR1cGxpY2F0ZXNbIGogXSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdC8vIENsZWFyIGlucHV0IGFmdGVyIHNvcnRpbmcgdG8gcmVsZWFzZSBvYmplY3RzXG5cdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L3NpenpsZS9wdWxsLzIyNVxuXHRzb3J0SW5wdXQgPSBudWxsO1xuXG5cdHJldHVybiByZXN1bHRzO1xufTtcblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9uIGZvciByZXRyaWV2aW5nIHRoZSB0ZXh0IHZhbHVlIG9mIGFuIGFycmF5IG9mIERPTSBub2Rlc1xuICogQHBhcmFtIHtBcnJheXxFbGVtZW50fSBlbGVtXG4gKi9cbmdldFRleHQgPSBTaXp6bGUuZ2V0VGV4dCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHR2YXIgbm9kZSxcblx0XHRyZXQgPSBcIlwiLFxuXHRcdGkgPSAwLFxuXHRcdG5vZGVUeXBlID0gZWxlbS5ub2RlVHlwZTtcblxuXHRpZiAoICFub2RlVHlwZSApIHtcblx0XHQvLyBJZiBubyBub2RlVHlwZSwgdGhpcyBpcyBleHBlY3RlZCB0byBiZSBhbiBhcnJheVxuXHRcdHdoaWxlICggKG5vZGUgPSBlbGVtW2krK10pICkge1xuXHRcdFx0Ly8gRG8gbm90IHRyYXZlcnNlIGNvbW1lbnQgbm9kZXNcblx0XHRcdHJldCArPSBnZXRUZXh0KCBub2RlICk7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKCBub2RlVHlwZSA9PT0gMSB8fCBub2RlVHlwZSA9PT0gOSB8fCBub2RlVHlwZSA9PT0gMTEgKSB7XG5cdFx0Ly8gVXNlIHRleHRDb250ZW50IGZvciBlbGVtZW50c1xuXHRcdC8vIGlubmVyVGV4dCB1c2FnZSByZW1vdmVkIGZvciBjb25zaXN0ZW5jeSBvZiBuZXcgbGluZXMgKGpRdWVyeSAjMTExNTMpXG5cdFx0aWYgKCB0eXBlb2YgZWxlbS50ZXh0Q29udGVudCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiBlbGVtLnRleHRDb250ZW50O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBUcmF2ZXJzZSBpdHMgY2hpbGRyZW5cblx0XHRcdGZvciAoIGVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7IGVsZW07IGVsZW0gPSBlbGVtLm5leHRTaWJsaW5nICkge1xuXHRcdFx0XHRyZXQgKz0gZ2V0VGV4dCggZWxlbSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSBlbHNlIGlmICggbm9kZVR5cGUgPT09IDMgfHwgbm9kZVR5cGUgPT09IDQgKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZVZhbHVlO1xuXHR9XG5cdC8vIERvIG5vdCBpbmNsdWRlIGNvbW1lbnQgb3IgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbiBub2Rlc1xuXG5cdHJldHVybiByZXQ7XG59O1xuXG5FeHByID0gU2l6emxlLnNlbGVjdG9ycyA9IHtcblxuXHQvLyBDYW4gYmUgYWRqdXN0ZWQgYnkgdGhlIHVzZXJcblx0Y2FjaGVMZW5ndGg6IDUwLFxuXG5cdGNyZWF0ZVBzZXVkbzogbWFya0Z1bmN0aW9uLFxuXG5cdG1hdGNoOiBtYXRjaEV4cHIsXG5cblx0YXR0ckhhbmRsZToge30sXG5cblx0ZmluZDoge30sXG5cblx0cmVsYXRpdmU6IHtcblx0XHRcIj5cIjogeyBkaXI6IFwicGFyZW50Tm9kZVwiLCBmaXJzdDogdHJ1ZSB9LFxuXHRcdFwiIFwiOiB7IGRpcjogXCJwYXJlbnROb2RlXCIgfSxcblx0XHRcIitcIjogeyBkaXI6IFwicHJldmlvdXNTaWJsaW5nXCIsIGZpcnN0OiB0cnVlIH0sXG5cdFx0XCJ+XCI6IHsgZGlyOiBcInByZXZpb3VzU2libGluZ1wiIH1cblx0fSxcblxuXHRwcmVGaWx0ZXI6IHtcblx0XHRcIkFUVFJcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0bWF0Y2hbMV0gPSBtYXRjaFsxXS5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApO1xuXG5cdFx0XHQvLyBNb3ZlIHRoZSBnaXZlbiB2YWx1ZSB0byBtYXRjaFszXSB3aGV0aGVyIHF1b3RlZCBvciB1bnF1b3RlZFxuXHRcdFx0bWF0Y2hbM10gPSAoIG1hdGNoWzNdIHx8IG1hdGNoWzRdIHx8IG1hdGNoWzVdIHx8IFwiXCIgKS5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApO1xuXG5cdFx0XHRpZiAoIG1hdGNoWzJdID09PSBcIn49XCIgKSB7XG5cdFx0XHRcdG1hdGNoWzNdID0gXCIgXCIgKyBtYXRjaFszXSArIFwiIFwiO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbWF0Y2guc2xpY2UoIDAsIDQgKTtcblx0XHR9LFxuXG5cdFx0XCJDSElMRFwiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHQvKiBtYXRjaGVzIGZyb20gbWF0Y2hFeHByW1wiQ0hJTERcIl1cblx0XHRcdFx0MSB0eXBlIChvbmx5fG50aHwuLi4pXG5cdFx0XHRcdDIgd2hhdCAoY2hpbGR8b2YtdHlwZSlcblx0XHRcdFx0MyBhcmd1bWVudCAoZXZlbnxvZGR8XFxkKnxcXGQqbihbKy1dXFxkKyk/fC4uLilcblx0XHRcdFx0NCB4bi1jb21wb25lbnQgb2YgeG4reSBhcmd1bWVudCAoWystXT9cXGQqbnwpXG5cdFx0XHRcdDUgc2lnbiBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NiB4IG9mIHhuLWNvbXBvbmVudFxuXHRcdFx0XHQ3IHNpZ24gb2YgeS1jb21wb25lbnRcblx0XHRcdFx0OCB5IG9mIHktY29tcG9uZW50XG5cdFx0XHQqL1xuXHRcdFx0bWF0Y2hbMV0gPSBtYXRjaFsxXS50b0xvd2VyQ2FzZSgpO1xuXG5cdFx0XHRpZiAoIG1hdGNoWzFdLnNsaWNlKCAwLCAzICkgPT09IFwibnRoXCIgKSB7XG5cdFx0XHRcdC8vIG50aC0qIHJlcXVpcmVzIGFyZ3VtZW50XG5cdFx0XHRcdGlmICggIW1hdGNoWzNdICkge1xuXHRcdFx0XHRcdFNpenpsZS5lcnJvciggbWF0Y2hbMF0gKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIG51bWVyaWMgeCBhbmQgeSBwYXJhbWV0ZXJzIGZvciBFeHByLmZpbHRlci5DSElMRFxuXHRcdFx0XHQvLyByZW1lbWJlciB0aGF0IGZhbHNlL3RydWUgY2FzdCByZXNwZWN0aXZlbHkgdG8gMC8xXG5cdFx0XHRcdG1hdGNoWzRdID0gKyggbWF0Y2hbNF0gPyBtYXRjaFs1XSArIChtYXRjaFs2XSB8fCAxKSA6IDIgKiAoIG1hdGNoWzNdID09PSBcImV2ZW5cIiB8fCBtYXRjaFszXSA9PT0gXCJvZGRcIiApICk7XG5cdFx0XHRcdG1hdGNoWzVdID0gKyggKCBtYXRjaFs3XSArIG1hdGNoWzhdICkgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKTtcblxuXHRcdFx0Ly8gb3RoZXIgdHlwZXMgcHJvaGliaXQgYXJndW1lbnRzXG5cdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFszXSApIHtcblx0XHRcdFx0U2l6emxlLmVycm9yKCBtYXRjaFswXSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbWF0Y2g7XG5cdFx0fSxcblxuXHRcdFwiUFNFVURPXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdHZhciBleGNlc3MsXG5cdFx0XHRcdHVucXVvdGVkID0gIW1hdGNoWzZdICYmIG1hdGNoWzJdO1xuXG5cdFx0XHRpZiAoIG1hdGNoRXhwcltcIkNISUxEXCJdLnRlc3QoIG1hdGNoWzBdICkgKSB7XG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBY2NlcHQgcXVvdGVkIGFyZ3VtZW50cyBhcy1pc1xuXHRcdFx0aWYgKCBtYXRjaFszXSApIHtcblx0XHRcdFx0bWF0Y2hbMl0gPSBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiO1xuXG5cdFx0XHQvLyBTdHJpcCBleGNlc3MgY2hhcmFjdGVycyBmcm9tIHVucXVvdGVkIGFyZ3VtZW50c1xuXHRcdFx0fSBlbHNlIGlmICggdW5xdW90ZWQgJiYgcnBzZXVkby50ZXN0KCB1bnF1b3RlZCApICYmXG5cdFx0XHRcdC8vIEdldCBleGNlc3MgZnJvbSB0b2tlbml6ZSAocmVjdXJzaXZlbHkpXG5cdFx0XHRcdChleGNlc3MgPSB0b2tlbml6ZSggdW5xdW90ZWQsIHRydWUgKSkgJiZcblx0XHRcdFx0Ly8gYWR2YW5jZSB0byB0aGUgbmV4dCBjbG9zaW5nIHBhcmVudGhlc2lzXG5cdFx0XHRcdChleGNlc3MgPSB1bnF1b3RlZC5pbmRleE9mKCBcIilcIiwgdW5xdW90ZWQubGVuZ3RoIC0gZXhjZXNzICkgLSB1bnF1b3RlZC5sZW5ndGgpICkge1xuXG5cdFx0XHRcdC8vIGV4Y2VzcyBpcyBhIG5lZ2F0aXZlIGluZGV4XG5cdFx0XHRcdG1hdGNoWzBdID0gbWF0Y2hbMF0uc2xpY2UoIDAsIGV4Y2VzcyApO1xuXHRcdFx0XHRtYXRjaFsyXSA9IHVucXVvdGVkLnNsaWNlKCAwLCBleGNlc3MgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmV0dXJuIG9ubHkgY2FwdHVyZXMgbmVlZGVkIGJ5IHRoZSBwc2V1ZG8gZmlsdGVyIG1ldGhvZCAodHlwZSBhbmQgYXJndW1lbnQpXG5cdFx0XHRyZXR1cm4gbWF0Y2guc2xpY2UoIDAsIDMgKTtcblx0XHR9XG5cdH0sXG5cblx0ZmlsdGVyOiB7XG5cblx0XHRcIlRBR1wiOiBmdW5jdGlvbiggbm9kZU5hbWVTZWxlY3RvciApIHtcblx0XHRcdHZhciBub2RlTmFtZSA9IG5vZGVOYW1lU2VsZWN0b3IucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIG5vZGVOYW1lU2VsZWN0b3IgPT09IFwiKlwiID9cblx0XHRcdFx0ZnVuY3Rpb24oKSB7IHJldHVybiB0cnVlOyB9IDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGVsZW0ubm9kZU5hbWUgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBub2RlTmFtZTtcblx0XHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDTEFTU1wiOiBmdW5jdGlvbiggY2xhc3NOYW1lICkge1xuXHRcdFx0dmFyIHBhdHRlcm4gPSBjbGFzc0NhY2hlWyBjbGFzc05hbWUgKyBcIiBcIiBdO1xuXG5cdFx0XHRyZXR1cm4gcGF0dGVybiB8fFxuXHRcdFx0XHQocGF0dGVybiA9IG5ldyBSZWdFeHAoIFwiKF58XCIgKyB3aGl0ZXNwYWNlICsgXCIpXCIgKyBjbGFzc05hbWUgKyBcIihcIiArIHdoaXRlc3BhY2UgKyBcInwkKVwiICkpICYmXG5cdFx0XHRcdGNsYXNzQ2FjaGUoIGNsYXNzTmFtZSwgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHBhdHRlcm4udGVzdCggdHlwZW9mIGVsZW0uY2xhc3NOYW1lID09PSBcInN0cmluZ1wiICYmIGVsZW0uY2xhc3NOYW1lIHx8IHR5cGVvZiBlbGVtLmdldEF0dHJpYnV0ZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBlbGVtLmdldEF0dHJpYnV0ZShcImNsYXNzXCIpIHx8IFwiXCIgKTtcblx0XHRcdFx0fSk7XG5cdFx0fSxcblxuXHRcdFwiQVRUUlwiOiBmdW5jdGlvbiggbmFtZSwgb3BlcmF0b3IsIGNoZWNrICkge1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgcmVzdWx0ID0gU2l6emxlLmF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdFx0XHRpZiAoIHJlc3VsdCA9PSBudWxsICkge1xuXHRcdFx0XHRcdHJldHVybiBvcGVyYXRvciA9PT0gXCIhPVwiO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICggIW9wZXJhdG9yICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmVzdWx0ICs9IFwiXCI7XG5cblx0XHRcdFx0cmV0dXJuIG9wZXJhdG9yID09PSBcIj1cIiA/IHJlc3VsdCA9PT0gY2hlY2sgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIiE9XCIgPyByZXN1bHQgIT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCJePVwiID8gY2hlY2sgJiYgcmVzdWx0LmluZGV4T2YoIGNoZWNrICkgPT09IDAgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIio9XCIgPyBjaGVjayAmJiByZXN1bHQuaW5kZXhPZiggY2hlY2sgKSA+IC0xIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIkPVwiID8gY2hlY2sgJiYgcmVzdWx0LnNsaWNlKCAtY2hlY2subGVuZ3RoICkgPT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCJ+PVwiID8gKCBcIiBcIiArIHJlc3VsdC5yZXBsYWNlKCByd2hpdGVzcGFjZSwgXCIgXCIgKSArIFwiIFwiICkuaW5kZXhPZiggY2hlY2sgKSA+IC0xIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCJ8PVwiID8gcmVzdWx0ID09PSBjaGVjayB8fCByZXN1bHQuc2xpY2UoIDAsIGNoZWNrLmxlbmd0aCArIDEgKSA9PT0gY2hlY2sgKyBcIi1cIiA6XG5cdFx0XHRcdFx0ZmFsc2U7XG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIkNISUxEXCI6IGZ1bmN0aW9uKCB0eXBlLCB3aGF0LCBhcmd1bWVudCwgZmlyc3QsIGxhc3QgKSB7XG5cdFx0XHR2YXIgc2ltcGxlID0gdHlwZS5zbGljZSggMCwgMyApICE9PSBcIm50aFwiLFxuXHRcdFx0XHRmb3J3YXJkID0gdHlwZS5zbGljZSggLTQgKSAhPT0gXCJsYXN0XCIsXG5cdFx0XHRcdG9mVHlwZSA9IHdoYXQgPT09IFwib2YtdHlwZVwiO1xuXG5cdFx0XHRyZXR1cm4gZmlyc3QgPT09IDEgJiYgbGFzdCA9PT0gMCA/XG5cblx0XHRcdFx0Ly8gU2hvcnRjdXQgZm9yIDpudGgtKihuKVxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRyZXR1cm4gISFlbGVtLnBhcmVudE5vZGU7XG5cdFx0XHRcdH0gOlxuXG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0dmFyIGNhY2hlLCB1bmlxdWVDYWNoZSwgb3V0ZXJDYWNoZSwgbm9kZSwgbm9kZUluZGV4LCBzdGFydCxcblx0XHRcdFx0XHRcdGRpciA9IHNpbXBsZSAhPT0gZm9yd2FyZCA/IFwibmV4dFNpYmxpbmdcIiA6IFwicHJldmlvdXNTaWJsaW5nXCIsXG5cdFx0XHRcdFx0XHRwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGUsXG5cdFx0XHRcdFx0XHRuYW1lID0gb2ZUeXBlICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSxcblx0XHRcdFx0XHRcdHVzZUNhY2hlID0gIXhtbCAmJiAhb2ZUeXBlLFxuXHRcdFx0XHRcdFx0ZGlmZiA9IGZhbHNlO1xuXG5cdFx0XHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cblx0XHRcdFx0XHRcdC8vIDooZmlyc3R8bGFzdHxvbmx5KS0oY2hpbGR8b2YtdHlwZSlcblx0XHRcdFx0XHRcdGlmICggc2ltcGxlICkge1xuXHRcdFx0XHRcdFx0XHR3aGlsZSAoIGRpciApIHtcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gZWxlbTtcblx0XHRcdFx0XHRcdFx0XHR3aGlsZSAoIChub2RlID0gbm9kZVsgZGlyIF0pICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBvZlR5cGUgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUgOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRub2RlLm5vZGVUeXBlID09PSAxICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0Ly8gUmV2ZXJzZSBkaXJlY3Rpb24gZm9yIDpvbmx5LSogKGlmIHdlIGhhdmVuJ3QgeWV0IGRvbmUgc28pXG5cdFx0XHRcdFx0XHRcdFx0c3RhcnQgPSBkaXIgPSB0eXBlID09PSBcIm9ubHlcIiAmJiAhc3RhcnQgJiYgXCJuZXh0U2libGluZ1wiO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRzdGFydCA9IFsgZm9yd2FyZCA/IHBhcmVudC5maXJzdENoaWxkIDogcGFyZW50Lmxhc3RDaGlsZCBdO1xuXG5cdFx0XHRcdFx0XHQvLyBub24teG1sIDpudGgtY2hpbGQoLi4uKSBzdG9yZXMgY2FjaGUgZGF0YSBvbiBgcGFyZW50YFxuXHRcdFx0XHRcdFx0aWYgKCBmb3J3YXJkICYmIHVzZUNhY2hlICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIFNlZWsgYGVsZW1gIGZyb20gYSBwcmV2aW91c2x5LWNhY2hlZCBpbmRleFxuXG5cdFx0XHRcdFx0XHRcdC8vIC4uLmluIGEgZ3ppcC1mcmllbmRseSB3YXlcblx0XHRcdFx0XHRcdFx0bm9kZSA9IHBhcmVudDtcblx0XHRcdFx0XHRcdFx0b3V0ZXJDYWNoZSA9IG5vZGVbIGV4cGFuZG8gXSB8fCAobm9kZVsgZXhwYW5kbyBdID0ge30pO1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlID0gb3V0ZXJDYWNoZVsgbm9kZS51bmlxdWVJRCBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRjYWNoZSA9IHVuaXF1ZUNhY2hlWyB0eXBlIF0gfHwgW107XG5cdFx0XHRcdFx0XHRcdG5vZGVJbmRleCA9IGNhY2hlWyAwIF0gPT09IGRpcnJ1bnMgJiYgY2FjaGVbIDEgXTtcblx0XHRcdFx0XHRcdFx0ZGlmZiA9IG5vZGVJbmRleCAmJiBjYWNoZVsgMiBdO1xuXHRcdFx0XHRcdFx0XHRub2RlID0gbm9kZUluZGV4ICYmIHBhcmVudC5jaGlsZE5vZGVzWyBub2RlSW5kZXggXTtcblxuXHRcdFx0XHRcdFx0XHR3aGlsZSAoIChub2RlID0gKytub2RlSW5kZXggJiYgbm9kZSAmJiBub2RlWyBkaXIgXSB8fFxuXG5cdFx0XHRcdFx0XHRcdFx0Ly8gRmFsbGJhY2sgdG8gc2Vla2luZyBgZWxlbWAgZnJvbSB0aGUgc3RhcnRcblx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFdoZW4gZm91bmQsIGNhY2hlIGluZGV4ZXMgb24gYHBhcmVudGAgYW5kIGJyZWFrXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBub2RlLm5vZGVUeXBlID09PSAxICYmICsrZGlmZiAmJiBub2RlID09PSBlbGVtICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGVbIHR5cGUgXSA9IFsgZGlycnVucywgbm9kZUluZGV4LCBkaWZmIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0Ly8gVXNlIHByZXZpb3VzbHktY2FjaGVkIGVsZW1lbnQgaW5kZXggaWYgYXZhaWxhYmxlXG5cdFx0XHRcdFx0XHRcdGlmICggdXNlQ2FjaGUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gLi4uaW4gYSBnemlwLWZyaWVuZGx5IHdheVxuXHRcdFx0XHRcdFx0XHRcdG5vZGUgPSBlbGVtO1xuXHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0XHQvLyBEZWZlbmQgYWdhaW5zdCBjbG9uZWQgYXR0cm9wZXJ0aWVzIChqUXVlcnkgZ2gtMTcwOSlcblx0XHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdGNhY2hlID0gdW5pcXVlQ2FjaGVbIHR5cGUgXSB8fCBbXTtcblx0XHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVsgMCBdID09PSBkaXJydW5zICYmIGNhY2hlWyAxIF07XG5cdFx0XHRcdFx0XHRcdFx0ZGlmZiA9IG5vZGVJbmRleDtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdC8vIHhtbCA6bnRoLWNoaWxkKC4uLilcblx0XHRcdFx0XHRcdFx0Ly8gb3IgOm50aC1sYXN0LWNoaWxkKC4uLikgb3IgOm50aCgtbGFzdCk/LW9mLXR5cGUoLi4uKVxuXHRcdFx0XHRcdFx0XHRpZiAoIGRpZmYgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIFVzZSB0aGUgc2FtZSBsb29wIGFzIGFib3ZlIHRvIHNlZWsgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRcdChkaWZmID0gbm9kZUluZGV4ID0gMCkgfHwgc3RhcnQucG9wKCkpICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoICggb2ZUeXBlID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDpcblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlVHlwZSA9PT0gMSApICYmXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCsrZGlmZiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBDYWNoZSB0aGUgaW5kZXggb2YgZWFjaCBlbmNvdW50ZXJlZCBlbGVtZW50XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggdXNlQ2FjaGUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0b3V0ZXJDYWNoZSA9IG5vZGVbIGV4cGFuZG8gXSB8fCAobm9kZVsgZXhwYW5kbyBdID0ge30pO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPDkgb25seVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlID0gb3V0ZXJDYWNoZVsgbm9kZS51bmlxdWVJRCBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQob3V0ZXJDYWNoZVsgbm9kZS51bmlxdWVJRCBdID0ge30pO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGVbIHR5cGUgXSA9IFsgZGlycnVucywgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBub2RlID09PSBlbGVtICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIEluY29ycG9yYXRlIHRoZSBvZmZzZXQsIHRoZW4gY2hlY2sgYWdhaW5zdCBjeWNsZSBzaXplXG5cdFx0XHRcdFx0XHRkaWZmIC09IGxhc3Q7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZGlmZiA9PT0gZmlyc3QgfHwgKCBkaWZmICUgZmlyc3QgPT09IDAgJiYgZGlmZiAvIGZpcnN0ID49IDAgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiUFNFVURPXCI6IGZ1bmN0aW9uKCBwc2V1ZG8sIGFyZ3VtZW50ICkge1xuXHRcdFx0Ly8gcHNldWRvLWNsYXNzIG5hbWVzIGFyZSBjYXNlLWluc2Vuc2l0aXZlXG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI3BzZXVkby1jbGFzc2VzXG5cdFx0XHQvLyBQcmlvcml0aXplIGJ5IGNhc2Ugc2Vuc2l0aXZpdHkgaW4gY2FzZSBjdXN0b20gcHNldWRvcyBhcmUgYWRkZWQgd2l0aCB1cHBlcmNhc2UgbGV0dGVyc1xuXHRcdFx0Ly8gUmVtZW1iZXIgdGhhdCBzZXRGaWx0ZXJzIGluaGVyaXRzIGZyb20gcHNldWRvc1xuXHRcdFx0dmFyIGFyZ3MsXG5cdFx0XHRcdGZuID0gRXhwci5wc2V1ZG9zWyBwc2V1ZG8gXSB8fCBFeHByLnNldEZpbHRlcnNbIHBzZXVkby50b0xvd2VyQ2FzZSgpIF0gfHxcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIFwidW5zdXBwb3J0ZWQgcHNldWRvOiBcIiArIHBzZXVkbyApO1xuXG5cdFx0XHQvLyBUaGUgdXNlciBtYXkgdXNlIGNyZWF0ZVBzZXVkbyB0byBpbmRpY2F0ZSB0aGF0XG5cdFx0XHQvLyBhcmd1bWVudHMgYXJlIG5lZWRlZCB0byBjcmVhdGUgdGhlIGZpbHRlciBmdW5jdGlvblxuXHRcdFx0Ly8ganVzdCBhcyBTaXp6bGUgZG9lc1xuXHRcdFx0aWYgKCBmblsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHRyZXR1cm4gZm4oIGFyZ3VtZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEJ1dCBtYWludGFpbiBzdXBwb3J0IGZvciBvbGQgc2lnbmF0dXJlc1xuXHRcdFx0aWYgKCBmbi5sZW5ndGggPiAxICkge1xuXHRcdFx0XHRhcmdzID0gWyBwc2V1ZG8sIHBzZXVkbywgXCJcIiwgYXJndW1lbnQgXTtcblx0XHRcdFx0cmV0dXJuIEV4cHIuc2V0RmlsdGVycy5oYXNPd25Qcm9wZXJ0eSggcHNldWRvLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRcdFx0bWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0XHRcdFx0dmFyIGlkeCxcblx0XHRcdFx0XHRcdFx0bWF0Y2hlZCA9IGZuKCBzZWVkLCBhcmd1bWVudCApLFxuXHRcdFx0XHRcdFx0XHRpID0gbWF0Y2hlZC5sZW5ndGg7XG5cdFx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdFx0aWR4ID0gaW5kZXhPZiggc2VlZCwgbWF0Y2hlZFtpXSApO1xuXHRcdFx0XHRcdFx0XHRzZWVkWyBpZHggXSA9ICEoIG1hdGNoZXNbIGlkeCBdID0gbWF0Y2hlZFtpXSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pIDpcblx0XHRcdFx0XHRmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmbiggZWxlbSwgMCwgYXJncyApO1xuXHRcdFx0XHRcdH07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmbjtcblx0XHR9XG5cdH0sXG5cblx0cHNldWRvczoge1xuXHRcdC8vIFBvdGVudGlhbGx5IGNvbXBsZXggcHNldWRvc1xuXHRcdFwibm90XCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHQvLyBUcmltIHRoZSBzZWxlY3RvciBwYXNzZWQgdG8gY29tcGlsZVxuXHRcdFx0Ly8gdG8gYXZvaWQgdHJlYXRpbmcgbGVhZGluZyBhbmQgdHJhaWxpbmdcblx0XHRcdC8vIHNwYWNlcyBhcyBjb21iaW5hdG9yc1xuXHRcdFx0dmFyIGlucHV0ID0gW10sXG5cdFx0XHRcdHJlc3VsdHMgPSBbXSxcblx0XHRcdFx0bWF0Y2hlciA9IGNvbXBpbGUoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSApO1xuXG5cdFx0XHRyZXR1cm4gbWF0Y2hlclsgZXhwYW5kbyBdID9cblx0XHRcdFx0bWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdFx0XHR1bm1hdGNoZWQgPSBtYXRjaGVyKCBzZWVkLCBudWxsLCB4bWwsIFtdICksXG5cdFx0XHRcdFx0XHRpID0gc2VlZC5sZW5ndGg7XG5cblx0XHRcdFx0XHQvLyBNYXRjaCBlbGVtZW50cyB1bm1hdGNoZWQgYnkgYG1hdGNoZXJgXG5cdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gdW5tYXRjaGVkW2ldKSApIHtcblx0XHRcdFx0XHRcdFx0c2VlZFtpXSA9ICEobWF0Y2hlc1tpXSA9IGVsZW0pO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSkgOlxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdGlucHV0WzBdID0gZWxlbTtcblx0XHRcdFx0XHRtYXRjaGVyKCBpbnB1dCwgbnVsbCwgeG1sLCByZXN1bHRzICk7XG5cdFx0XHRcdFx0Ly8gRG9uJ3Qga2VlcCB0aGUgZWxlbWVudCAoaXNzdWUgIzI5OSlcblx0XHRcdFx0XHRpbnB1dFswXSA9IG51bGw7XG5cdFx0XHRcdFx0cmV0dXJuICFyZXN1bHRzLnBvcCgpO1xuXHRcdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0XCJoYXNcIjogbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIFNpenpsZSggc2VsZWN0b3IsIGVsZW0gKS5sZW5ndGggPiAwO1xuXHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiY29udGFpbnNcIjogbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCB0ZXh0ICkge1xuXHRcdFx0dGV4dCA9IHRleHQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuICggZWxlbS50ZXh0Q29udGVudCB8fCBlbGVtLmlubmVyVGV4dCB8fCBnZXRUZXh0KCBlbGVtICkgKS5pbmRleE9mKCB0ZXh0ICkgPiAtMTtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHQvLyBcIldoZXRoZXIgYW4gZWxlbWVudCBpcyByZXByZXNlbnRlZCBieSBhIDpsYW5nKCkgc2VsZWN0b3Jcblx0XHQvLyBpcyBiYXNlZCBzb2xlbHkgb24gdGhlIGVsZW1lbnQncyBsYW5ndWFnZSB2YWx1ZVxuXHRcdC8vIGJlaW5nIGVxdWFsIHRvIHRoZSBpZGVudGlmaWVyIEMsXG5cdFx0Ly8gb3IgYmVnaW5uaW5nIHdpdGggdGhlIGlkZW50aWZpZXIgQyBpbW1lZGlhdGVseSBmb2xsb3dlZCBieSBcIi1cIi5cblx0XHQvLyBUaGUgbWF0Y2hpbmcgb2YgQyBhZ2FpbnN0IHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWUgaXMgcGVyZm9ybWVkIGNhc2UtaW5zZW5zaXRpdmVseS5cblx0XHQvLyBUaGUgaWRlbnRpZmllciBDIGRvZXMgbm90IGhhdmUgdG8gYmUgYSB2YWxpZCBsYW5ndWFnZSBuYW1lLlwiXG5cdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNsYW5nLXBzZXVkb1xuXHRcdFwibGFuZ1wiOiBtYXJrRnVuY3Rpb24oIGZ1bmN0aW9uKCBsYW5nICkge1xuXHRcdFx0Ly8gbGFuZyB2YWx1ZSBtdXN0IGJlIGEgdmFsaWQgaWRlbnRpZmllclxuXHRcdFx0aWYgKCAhcmlkZW50aWZpZXIudGVzdChsYW5nIHx8IFwiXCIpICkge1xuXHRcdFx0XHRTaXp6bGUuZXJyb3IoIFwidW5zdXBwb3J0ZWQgbGFuZzogXCIgKyBsYW5nICk7XG5cdFx0XHR9XG5cdFx0XHRsYW5nID0gbGFuZy5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBlbGVtTGFuZztcblx0XHRcdFx0ZG8ge1xuXHRcdFx0XHRcdGlmICggKGVsZW1MYW5nID0gZG9jdW1lbnRJc0hUTUwgP1xuXHRcdFx0XHRcdFx0ZWxlbS5sYW5nIDpcblx0XHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKFwieG1sOmxhbmdcIikgfHwgZWxlbS5nZXRBdHRyaWJ1dGUoXCJsYW5nXCIpKSApIHtcblxuXHRcdFx0XHRcdFx0ZWxlbUxhbmcgPSBlbGVtTGFuZy50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW1MYW5nID09PSBsYW5nIHx8IGVsZW1MYW5nLmluZGV4T2YoIGxhbmcgKyBcIi1cIiApID09PSAwO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSB3aGlsZSAoIChlbGVtID0gZWxlbS5wYXJlbnROb2RlKSAmJiBlbGVtLm5vZGVUeXBlID09PSAxICk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHQvLyBNaXNjZWxsYW5lb3VzXG5cdFx0XCJ0YXJnZXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgaGFzaCA9IHdpbmRvdy5sb2NhdGlvbiAmJiB3aW5kb3cubG9jYXRpb24uaGFzaDtcblx0XHRcdHJldHVybiBoYXNoICYmIGhhc2guc2xpY2UoIDEgKSA9PT0gZWxlbS5pZDtcblx0XHR9LFxuXG5cdFx0XCJyb290XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY0VsZW07XG5cdFx0fSxcblxuXHRcdFwiZm9jdXNcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbSA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiAoIWRvY3VtZW50Lmhhc0ZvY3VzIHx8IGRvY3VtZW50Lmhhc0ZvY3VzKCkpICYmICEhKGVsZW0udHlwZSB8fCBlbGVtLmhyZWYgfHwgfmVsZW0udGFiSW5kZXgpO1xuXHRcdH0sXG5cblx0XHQvLyBCb29sZWFuIHByb3BlcnRpZXNcblx0XHRcImVuYWJsZWRcIjogY3JlYXRlRGlzYWJsZWRQc2V1ZG8oIGZhbHNlICksXG5cdFx0XCJkaXNhYmxlZFwiOiBjcmVhdGVEaXNhYmxlZFBzZXVkbyggdHJ1ZSApLFxuXG5cdFx0XCJjaGVja2VkXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0Ly8gSW4gQ1NTMywgOmNoZWNrZWQgc2hvdWxkIHJldHVybiBib3RoIGNoZWNrZWQgYW5kIHNlbGVjdGVkIGVsZW1lbnRzXG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi8yMDExL1JFQy1jc3MzLXNlbGVjdG9ycy0yMDExMDkyOS8jY2hlY2tlZFxuXHRcdFx0dmFyIG5vZGVOYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIChub2RlTmFtZSA9PT0gXCJpbnB1dFwiICYmICEhZWxlbS5jaGVja2VkKSB8fCAobm9kZU5hbWUgPT09IFwib3B0aW9uXCIgJiYgISFlbGVtLnNlbGVjdGVkKTtcblx0XHR9LFxuXG5cdFx0XCJzZWxlY3RlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEFjY2Vzc2luZyB0aGlzIHByb3BlcnR5IG1ha2VzIHNlbGVjdGVkLWJ5LWRlZmF1bHRcblx0XHRcdC8vIG9wdGlvbnMgaW4gU2FmYXJpIHdvcmsgcHJvcGVybHlcblx0XHRcdGlmICggZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRlbGVtLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uc2VsZWN0ZWQgPT09IHRydWU7XG5cdFx0fSxcblxuXHRcdC8vIENvbnRlbnRzXG5cdFx0XCJlbXB0eVwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jZW1wdHktcHNldWRvXG5cdFx0XHQvLyA6ZW1wdHkgaXMgbmVnYXRlZCBieSBlbGVtZW50ICgxKSBvciBjb250ZW50IG5vZGVzICh0ZXh0OiAzOyBjZGF0YTogNDsgZW50aXR5IHJlZjogNSksXG5cdFx0XHQvLyAgIGJ1dCBub3QgYnkgb3RoZXJzIChjb21tZW50OiA4OyBwcm9jZXNzaW5nIGluc3RydWN0aW9uOiA3OyBldGMuKVxuXHRcdFx0Ly8gbm9kZVR5cGUgPCA2IHdvcmtzIGJlY2F1c2UgYXR0cmlidXRlcyAoMikgZG8gbm90IGFwcGVhciBhcyBjaGlsZHJlblxuXHRcdFx0Zm9yICggZWxlbSA9IGVsZW0uZmlyc3RDaGlsZDsgZWxlbTsgZWxlbSA9IGVsZW0ubmV4dFNpYmxpbmcgKSB7XG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA8IDYgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9LFxuXG5cdFx0XCJwYXJlbnRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gIUV4cHIucHNldWRvc1tcImVtcHR5XCJdKCBlbGVtICk7XG5cdFx0fSxcblxuXHRcdC8vIEVsZW1lbnQvaW5wdXQgdHlwZXNcblx0XHRcImhlYWRlclwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiByaGVhZGVyLnRlc3QoIGVsZW0ubm9kZU5hbWUgKTtcblx0XHR9LFxuXG5cdFx0XCJpbnB1dFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiByaW5wdXRzLnRlc3QoIGVsZW0ubm9kZU5hbWUgKTtcblx0XHR9LFxuXG5cdFx0XCJidXR0b25cIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBuYW1lID09PSBcImlucHV0XCIgJiYgZWxlbS50eXBlID09PSBcImJ1dHRvblwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCI7XG5cdFx0fSxcblxuXHRcdFwidGV4dFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHZhciBhdHRyO1xuXHRcdFx0cmV0dXJuIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpbnB1dFwiICYmXG5cdFx0XHRcdGVsZW0udHlwZSA9PT0gXCJ0ZXh0XCIgJiZcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRTw4XG5cdFx0XHRcdC8vIE5ldyBIVE1MNSBhdHRyaWJ1dGUgdmFsdWVzIChlLmcuLCBcInNlYXJjaFwiKSBhcHBlYXIgd2l0aCBlbGVtLnR5cGUgPT09IFwidGV4dFwiXG5cdFx0XHRcdCggKGF0dHIgPSBlbGVtLmdldEF0dHJpYnV0ZShcInR5cGVcIikpID09IG51bGwgfHwgYXR0ci50b0xvd2VyQ2FzZSgpID09PSBcInRleHRcIiApO1xuXHRcdH0sXG5cblx0XHQvLyBQb3NpdGlvbi1pbi1jb2xsZWN0aW9uXG5cdFx0XCJmaXJzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIFsgMCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJsYXN0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0cmV0dXJuIFsgbGVuZ3RoIC0gMSBdO1xuXHRcdH0pLFxuXG5cdFx0XCJlcVwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCwgYXJndW1lbnQgKSB7XG5cdFx0XHRyZXR1cm4gWyBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50IF07XG5cdFx0fSksXG5cblx0XHRcImV2ZW5cIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDA7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcIm9kZFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHZhciBpID0gMTtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSArPSAyICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwibHRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyAtLWkgPj0gMDsgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJndFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCwgYXJndW1lbnQgKSB7XG5cdFx0XHR2YXIgaSA9IGFyZ3VtZW50IDwgMCA/IGFyZ3VtZW50ICsgbGVuZ3RoIDogYXJndW1lbnQ7XG5cdFx0XHRmb3IgKCA7ICsraSA8IGxlbmd0aDsgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pXG5cdH1cbn07XG5cbkV4cHIucHNldWRvc1tcIm50aFwiXSA9IEV4cHIucHNldWRvc1tcImVxXCJdO1xuXG4vLyBBZGQgYnV0dG9uL2lucHV0IHR5cGUgcHNldWRvc1xuZm9yICggaSBpbiB7IHJhZGlvOiB0cnVlLCBjaGVja2JveDogdHJ1ZSwgZmlsZTogdHJ1ZSwgcGFzc3dvcmQ6IHRydWUsIGltYWdlOiB0cnVlIH0gKSB7XG5cdEV4cHIucHNldWRvc1sgaSBdID0gY3JlYXRlSW5wdXRQc2V1ZG8oIGkgKTtcbn1cbmZvciAoIGkgaW4geyBzdWJtaXQ6IHRydWUsIHJlc2V0OiB0cnVlIH0gKSB7XG5cdEV4cHIucHNldWRvc1sgaSBdID0gY3JlYXRlQnV0dG9uUHNldWRvKCBpICk7XG59XG5cbi8vIEVhc3kgQVBJIGZvciBjcmVhdGluZyBuZXcgc2V0RmlsdGVyc1xuZnVuY3Rpb24gc2V0RmlsdGVycygpIHt9XG5zZXRGaWx0ZXJzLnByb3RvdHlwZSA9IEV4cHIuZmlsdGVycyA9IEV4cHIucHNldWRvcztcbkV4cHIuc2V0RmlsdGVycyA9IG5ldyBzZXRGaWx0ZXJzKCk7XG5cbnRva2VuaXplID0gU2l6emxlLnRva2VuaXplID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBwYXJzZU9ubHkgKSB7XG5cdHZhciBtYXRjaGVkLCBtYXRjaCwgdG9rZW5zLCB0eXBlLFxuXHRcdHNvRmFyLCBncm91cHMsIHByZUZpbHRlcnMsXG5cdFx0Y2FjaGVkID0gdG9rZW5DYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggY2FjaGVkICkge1xuXHRcdHJldHVybiBwYXJzZU9ubHkgPyAwIDogY2FjaGVkLnNsaWNlKCAwICk7XG5cdH1cblxuXHRzb0ZhciA9IHNlbGVjdG9yO1xuXHRncm91cHMgPSBbXTtcblx0cHJlRmlsdGVycyA9IEV4cHIucHJlRmlsdGVyO1xuXG5cdHdoaWxlICggc29GYXIgKSB7XG5cblx0XHQvLyBDb21tYSBhbmQgZmlyc3QgcnVuXG5cdFx0aWYgKCAhbWF0Y2hlZCB8fCAobWF0Y2ggPSByY29tbWEuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRpZiAoIG1hdGNoICkge1xuXHRcdFx0XHQvLyBEb24ndCBjb25zdW1lIHRyYWlsaW5nIGNvbW1hcyBhcyB2YWxpZFxuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaFswXS5sZW5ndGggKSB8fCBzb0Zhcjtcblx0XHRcdH1cblx0XHRcdGdyb3Vwcy5wdXNoKCAodG9rZW5zID0gW10pICk7XG5cdFx0fVxuXG5cdFx0bWF0Y2hlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gQ29tYmluYXRvcnNcblx0XHRpZiAoIChtYXRjaCA9IHJjb21iaW5hdG9ycy5leGVjKCBzb0ZhciApKSApIHtcblx0XHRcdG1hdGNoZWQgPSBtYXRjaC5zaGlmdCgpO1xuXHRcdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0Ly8gQ2FzdCBkZXNjZW5kYW50IGNvbWJpbmF0b3JzIHRvIHNwYWNlXG5cdFx0XHRcdHR5cGU6IG1hdGNoWzBdLnJlcGxhY2UoIHJ0cmltLCBcIiBcIiApXG5cdFx0XHR9KTtcblx0XHRcdHNvRmFyID0gc29GYXIuc2xpY2UoIG1hdGNoZWQubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmlsdGVyc1xuXHRcdGZvciAoIHR5cGUgaW4gRXhwci5maWx0ZXIgKSB7XG5cdFx0XHRpZiAoIChtYXRjaCA9IG1hdGNoRXhwclsgdHlwZSBdLmV4ZWMoIHNvRmFyICkpICYmICghcHJlRmlsdGVyc1sgdHlwZSBdIHx8XG5cdFx0XHRcdChtYXRjaCA9IHByZUZpbHRlcnNbIHR5cGUgXSggbWF0Y2ggKSkpICkge1xuXHRcdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0XHRcdHZhbHVlOiBtYXRjaGVkLFxuXHRcdFx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRcdFx0bWF0Y2hlczogbWF0Y2hcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHNvRmFyID0gc29GYXIuc2xpY2UoIG1hdGNoZWQubGVuZ3RoICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCAhbWF0Y2hlZCApIHtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbGVuZ3RoIG9mIHRoZSBpbnZhbGlkIGV4Y2Vzc1xuXHQvLyBpZiB3ZSdyZSBqdXN0IHBhcnNpbmdcblx0Ly8gT3RoZXJ3aXNlLCB0aHJvdyBhbiBlcnJvciBvciByZXR1cm4gdG9rZW5zXG5cdHJldHVybiBwYXJzZU9ubHkgP1xuXHRcdHNvRmFyLmxlbmd0aCA6XG5cdFx0c29GYXIgP1xuXHRcdFx0U2l6emxlLmVycm9yKCBzZWxlY3RvciApIDpcblx0XHRcdC8vIENhY2hlIHRoZSB0b2tlbnNcblx0XHRcdHRva2VuQ2FjaGUoIHNlbGVjdG9yLCBncm91cHMgKS5zbGljZSggMCApO1xufTtcblxuZnVuY3Rpb24gdG9TZWxlY3RvciggdG9rZW5zICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRzZWxlY3RvciA9IFwiXCI7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdHNlbGVjdG9yICs9IHRva2Vuc1tpXS52YWx1ZTtcblx0fVxuXHRyZXR1cm4gc2VsZWN0b3I7XG59XG5cbmZ1bmN0aW9uIGFkZENvbWJpbmF0b3IoIG1hdGNoZXIsIGNvbWJpbmF0b3IsIGJhc2UgKSB7XG5cdHZhciBkaXIgPSBjb21iaW5hdG9yLmRpcixcblx0XHRza2lwID0gY29tYmluYXRvci5uZXh0LFxuXHRcdGtleSA9IHNraXAgfHwgZGlyLFxuXHRcdGNoZWNrTm9uRWxlbWVudHMgPSBiYXNlICYmIGtleSA9PT0gXCJwYXJlbnROb2RlXCIsXG5cdFx0ZG9uZU5hbWUgPSBkb25lKys7XG5cblx0cmV0dXJuIGNvbWJpbmF0b3IuZmlyc3QgP1xuXHRcdC8vIENoZWNrIGFnYWluc3QgY2xvc2VzdCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHR3aGlsZSAoIChlbGVtID0gZWxlbVsgZGlyIF0pICkge1xuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgfHwgY2hlY2tOb25FbGVtZW50cyApIHtcblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9IDpcblxuXHRcdC8vIENoZWNrIGFnYWluc3QgYWxsIGFuY2VzdG9yL3ByZWNlZGluZyBlbGVtZW50c1xuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHR2YXIgb2xkQ2FjaGUsIHVuaXF1ZUNhY2hlLCBvdXRlckNhY2hlLFxuXHRcdFx0XHRuZXdDYWNoZSA9IFsgZGlycnVucywgZG9uZU5hbWUgXTtcblxuXHRcdFx0Ly8gV2UgY2FuJ3Qgc2V0IGFyYml0cmFyeSBkYXRhIG9uIFhNTCBub2Rlcywgc28gdGhleSBkb24ndCBiZW5lZml0IGZyb20gY29tYmluYXRvciBjYWNoaW5nXG5cdFx0XHRpZiAoIHhtbCApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgfHwgY2hlY2tOb25FbGVtZW50cyApIHtcblx0XHRcdFx0XHRcdGlmICggbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgfHwgY2hlY2tOb25FbGVtZW50cyApIHtcblx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBlbGVtWyBleHBhbmRvIF0gfHwgKGVsZW1bIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPDkgb25seVxuXHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIGVsZW0udW5pcXVlSUQgXSB8fCAob3V0ZXJDYWNoZVsgZWxlbS51bmlxdWVJRCBdID0ge30pO1xuXG5cdFx0XHRcdFx0XHRpZiAoIHNraXAgJiYgc2tpcCA9PT0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICkge1xuXHRcdFx0XHRcdFx0XHRlbGVtID0gZWxlbVsgZGlyIF0gfHwgZWxlbTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIChvbGRDYWNoZSA9IHVuaXF1ZUNhY2hlWyBrZXkgXSkgJiZcblx0XHRcdFx0XHRcdFx0b2xkQ2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBvbGRDYWNoZVsgMSBdID09PSBkb25lTmFtZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBBc3NpZ24gdG8gbmV3Q2FjaGUgc28gcmVzdWx0cyBiYWNrLXByb3BhZ2F0ZSB0byBwcmV2aW91cyBlbGVtZW50c1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKG5ld0NhY2hlWyAyIF0gPSBvbGRDYWNoZVsgMiBdKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFJldXNlIG5ld2NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGVbIGtleSBdID0gbmV3Q2FjaGU7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQSBtYXRjaCBtZWFucyB3ZSdyZSBkb25lOyBhIGZhaWwgbWVhbnMgd2UgaGF2ZSB0byBrZWVwIGNoZWNraW5nXG5cdFx0XHRcdFx0XHRcdGlmICggKG5ld0NhY2hlWyAyIF0gPSBtYXRjaGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9O1xufVxuXG5mdW5jdGlvbiBlbGVtZW50TWF0Y2hlciggbWF0Y2hlcnMgKSB7XG5cdHJldHVybiBtYXRjaGVycy5sZW5ndGggPiAxID9cblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIGkgPSBtYXRjaGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAhbWF0Y2hlcnNbaV0oIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSA6XG5cdFx0bWF0Y2hlcnNbMF07XG59XG5cbmZ1bmN0aW9uIG11bHRpcGxlQ29udGV4dHMoIHNlbGVjdG9yLCBjb250ZXh0cywgcmVzdWx0cyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGxlbiA9IGNvbnRleHRzLmxlbmd0aDtcblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0U2l6emxlKCBzZWxlY3RvciwgY29udGV4dHNbaV0sIHJlc3VsdHMgKTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0cztcbn1cblxuZnVuY3Rpb24gY29uZGVuc2UoIHVubWF0Y2hlZCwgbWFwLCBmaWx0ZXIsIGNvbnRleHQsIHhtbCApIHtcblx0dmFyIGVsZW0sXG5cdFx0bmV3VW5tYXRjaGVkID0gW10sXG5cdFx0aSA9IDAsXG5cdFx0bGVuID0gdW5tYXRjaGVkLmxlbmd0aCxcblx0XHRtYXBwZWQgPSBtYXAgIT0gbnVsbDtcblxuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRpZiAoIChlbGVtID0gdW5tYXRjaGVkW2ldKSApIHtcblx0XHRcdGlmICggIWZpbHRlciB8fCBmaWx0ZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRuZXdVbm1hdGNoZWQucHVzaCggZWxlbSApO1xuXHRcdFx0XHRpZiAoIG1hcHBlZCApIHtcblx0XHRcdFx0XHRtYXAucHVzaCggaSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIG5ld1VubWF0Y2hlZDtcbn1cblxuZnVuY3Rpb24gc2V0TWF0Y2hlciggcHJlRmlsdGVyLCBzZWxlY3RvciwgbWF0Y2hlciwgcG9zdEZpbHRlciwgcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICkge1xuXHRpZiAoIHBvc3RGaWx0ZXIgJiYgIXBvc3RGaWx0ZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmlsdGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbHRlciApO1xuXHR9XG5cdGlmICggcG9zdEZpbmRlciAmJiAhcG9zdEZpbmRlclsgZXhwYW5kbyBdICkge1xuXHRcdHBvc3RGaW5kZXIgPSBzZXRNYXRjaGVyKCBwb3N0RmluZGVyLCBwb3N0U2VsZWN0b3IgKTtcblx0fVxuXHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCByZXN1bHRzLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0dmFyIHRlbXAsIGksIGVsZW0sXG5cdFx0XHRwcmVNYXAgPSBbXSxcblx0XHRcdHBvc3RNYXAgPSBbXSxcblx0XHRcdHByZWV4aXN0aW5nID0gcmVzdWx0cy5sZW5ndGgsXG5cblx0XHRcdC8vIEdldCBpbml0aWFsIGVsZW1lbnRzIGZyb20gc2VlZCBvciBjb250ZXh0XG5cdFx0XHRlbGVtcyA9IHNlZWQgfHwgbXVsdGlwbGVDb250ZXh0cyggc2VsZWN0b3IgfHwgXCIqXCIsIGNvbnRleHQubm9kZVR5cGUgPyBbIGNvbnRleHQgXSA6IGNvbnRleHQsIFtdICksXG5cblx0XHRcdC8vIFByZWZpbHRlciB0byBnZXQgbWF0Y2hlciBpbnB1dCwgcHJlc2VydmluZyBhIG1hcCBmb3Igc2VlZC1yZXN1bHRzIHN5bmNocm9uaXphdGlvblxuXHRcdFx0bWF0Y2hlckluID0gcHJlRmlsdGVyICYmICggc2VlZCB8fCAhc2VsZWN0b3IgKSA/XG5cdFx0XHRcdGNvbmRlbnNlKCBlbGVtcywgcHJlTWFwLCBwcmVGaWx0ZXIsIGNvbnRleHQsIHhtbCApIDpcblx0XHRcdFx0ZWxlbXMsXG5cblx0XHRcdG1hdGNoZXJPdXQgPSBtYXRjaGVyID9cblx0XHRcdFx0Ly8gSWYgd2UgaGF2ZSBhIHBvc3RGaW5kZXIsIG9yIGZpbHRlcmVkIHNlZWQsIG9yIG5vbi1zZWVkIHBvc3RGaWx0ZXIgb3IgcHJlZXhpc3RpbmcgcmVzdWx0cyxcblx0XHRcdFx0cG9zdEZpbmRlciB8fCAoIHNlZWQgPyBwcmVGaWx0ZXIgOiBwcmVleGlzdGluZyB8fCBwb3N0RmlsdGVyICkgP1xuXG5cdFx0XHRcdFx0Ly8gLi4uaW50ZXJtZWRpYXRlIHByb2Nlc3NpbmcgaXMgbmVjZXNzYXJ5XG5cdFx0XHRcdFx0W10gOlxuXG5cdFx0XHRcdFx0Ly8gLi4ub3RoZXJ3aXNlIHVzZSByZXN1bHRzIGRpcmVjdGx5XG5cdFx0XHRcdFx0cmVzdWx0cyA6XG5cdFx0XHRcdG1hdGNoZXJJbjtcblxuXHRcdC8vIEZpbmQgcHJpbWFyeSBtYXRjaGVzXG5cdFx0aWYgKCBtYXRjaGVyICkge1xuXHRcdFx0bWF0Y2hlciggbWF0Y2hlckluLCBtYXRjaGVyT3V0LCBjb250ZXh0LCB4bWwgKTtcblx0XHR9XG5cblx0XHQvLyBBcHBseSBwb3N0RmlsdGVyXG5cdFx0aWYgKCBwb3N0RmlsdGVyICkge1xuXHRcdFx0dGVtcCA9IGNvbmRlbnNlKCBtYXRjaGVyT3V0LCBwb3N0TWFwICk7XG5cdFx0XHRwb3N0RmlsdGVyKCB0ZW1wLCBbXSwgY29udGV4dCwgeG1sICk7XG5cblx0XHRcdC8vIFVuLW1hdGNoIGZhaWxpbmcgZWxlbWVudHMgYnkgbW92aW5nIHRoZW0gYmFjayB0byBtYXRjaGVySW5cblx0XHRcdGkgPSB0ZW1wLmxlbmd0aDtcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoIChlbGVtID0gdGVtcFtpXSkgKSB7XG5cdFx0XHRcdFx0bWF0Y2hlck91dFsgcG9zdE1hcFtpXSBdID0gIShtYXRjaGVySW5bIHBvc3RNYXBbaV0gXSA9IGVsZW0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0aWYgKCBwb3N0RmluZGVyIHx8IHByZUZpbHRlciApIHtcblx0XHRcdFx0aWYgKCBwb3N0RmluZGVyICkge1xuXHRcdFx0XHRcdC8vIEdldCB0aGUgZmluYWwgbWF0Y2hlck91dCBieSBjb25kZW5zaW5nIHRoaXMgaW50ZXJtZWRpYXRlIGludG8gcG9zdEZpbmRlciBjb250ZXh0c1xuXHRcdFx0XHRcdHRlbXAgPSBbXTtcblx0XHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gbWF0Y2hlck91dFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFJlc3RvcmUgbWF0Y2hlckluIHNpbmNlIGVsZW0gaXMgbm90IHlldCBhIGZpbmFsIG1hdGNoXG5cdFx0XHRcdFx0XHRcdHRlbXAucHVzaCggKG1hdGNoZXJJbltpXSA9IGVsZW0pICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHBvc3RGaW5kZXIoIG51bGwsIChtYXRjaGVyT3V0ID0gW10pLCB0ZW1wLCB4bWwgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIE1vdmUgbWF0Y2hlZCBlbGVtZW50cyBmcm9tIHNlZWQgdG8gcmVzdWx0cyB0byBrZWVwIHRoZW0gc3luY2hyb25pemVkXG5cdFx0XHRcdGkgPSBtYXRjaGVyT3V0Lmxlbmd0aDtcblx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICYmXG5cdFx0XHRcdFx0XHQodGVtcCA9IHBvc3RGaW5kZXIgPyBpbmRleE9mKCBzZWVkLCBlbGVtICkgOiBwcmVNYXBbaV0pID4gLTEgKSB7XG5cblx0XHRcdFx0XHRcdHNlZWRbdGVtcF0gPSAhKHJlc3VsdHNbdGVtcF0gPSBlbGVtKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdC8vIEFkZCBlbGVtZW50cyB0byByZXN1bHRzLCB0aHJvdWdoIHBvc3RGaW5kZXIgaWYgZGVmaW5lZFxuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXRjaGVyT3V0ID0gY29uZGVuc2UoXG5cdFx0XHRcdG1hdGNoZXJPdXQgPT09IHJlc3VsdHMgP1xuXHRcdFx0XHRcdG1hdGNoZXJPdXQuc3BsaWNlKCBwcmVleGlzdGluZywgbWF0Y2hlck91dC5sZW5ndGggKSA6XG5cdFx0XHRcdFx0bWF0Y2hlck91dFxuXHRcdFx0KTtcblx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0cG9zdEZpbmRlciggbnVsbCwgcmVzdWx0cywgbWF0Y2hlck91dCwgeG1sICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBtYXRjaGVyT3V0ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hlckZyb21Ub2tlbnMoIHRva2VucyApIHtcblx0dmFyIGNoZWNrQ29udGV4dCwgbWF0Y2hlciwgaixcblx0XHRsZW4gPSB0b2tlbnMubGVuZ3RoLFxuXHRcdGxlYWRpbmdSZWxhdGl2ZSA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1swXS50eXBlIF0sXG5cdFx0aW1wbGljaXRSZWxhdGl2ZSA9IGxlYWRpbmdSZWxhdGl2ZSB8fCBFeHByLnJlbGF0aXZlW1wiIFwiXSxcblx0XHRpID0gbGVhZGluZ1JlbGF0aXZlID8gMSA6IDAsXG5cblx0XHQvLyBUaGUgZm91bmRhdGlvbmFsIG1hdGNoZXIgZW5zdXJlcyB0aGF0IGVsZW1lbnRzIGFyZSByZWFjaGFibGUgZnJvbSB0b3AtbGV2ZWwgY29udGV4dChzKVxuXHRcdG1hdGNoQ29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGNoZWNrQ29udGV4dDtcblx0XHR9LCBpbXBsaWNpdFJlbGF0aXZlLCB0cnVlICksXG5cdFx0bWF0Y2hBbnlDb250ZXh0ID0gYWRkQ29tYmluYXRvciggZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gaW5kZXhPZiggY2hlY2tDb250ZXh0LCBlbGVtICkgPiAtMTtcblx0XHR9LCBpbXBsaWNpdFJlbGF0aXZlLCB0cnVlICksXG5cdFx0bWF0Y2hlcnMgPSBbIGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHR2YXIgcmV0ID0gKCAhbGVhZGluZ1JlbGF0aXZlICYmICggeG1sIHx8IGNvbnRleHQgIT09IG91dGVybW9zdENvbnRleHQgKSApIHx8IChcblx0XHRcdFx0KGNoZWNrQ29udGV4dCA9IGNvbnRleHQpLm5vZGVUeXBlID9cblx0XHRcdFx0XHRtYXRjaENvbnRleHQoIGVsZW0sIGNvbnRleHQsIHhtbCApIDpcblx0XHRcdFx0XHRtYXRjaEFueUNvbnRleHQoIGVsZW0sIGNvbnRleHQsIHhtbCApICk7XG5cdFx0XHQvLyBBdm9pZCBoYW5naW5nIG9udG8gZWxlbWVudCAoaXNzdWUgIzI5OSlcblx0XHRcdGNoZWNrQ29udGV4dCA9IG51bGw7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH0gXTtcblxuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRpZiAoIChtYXRjaGVyID0gRXhwci5yZWxhdGl2ZVsgdG9rZW5zW2ldLnR5cGUgXSkgKSB7XG5cdFx0XHRtYXRjaGVycyA9IFsgYWRkQ29tYmluYXRvcihlbGVtZW50TWF0Y2hlciggbWF0Y2hlcnMgKSwgbWF0Y2hlcikgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bWF0Y2hlciA9IEV4cHIuZmlsdGVyWyB0b2tlbnNbaV0udHlwZSBdLmFwcGx5KCBudWxsLCB0b2tlbnNbaV0ubWF0Y2hlcyApO1xuXG5cdFx0XHQvLyBSZXR1cm4gc3BlY2lhbCB1cG9uIHNlZWluZyBhIHBvc2l0aW9uYWwgbWF0Y2hlclxuXHRcdFx0aWYgKCBtYXRjaGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdC8vIEZpbmQgdGhlIG5leHQgcmVsYXRpdmUgb3BlcmF0b3IgKGlmIGFueSkgZm9yIHByb3BlciBoYW5kbGluZ1xuXHRcdFx0XHRqID0gKytpO1xuXHRcdFx0XHRmb3IgKCA7IGogPCBsZW47IGorKyApIHtcblx0XHRcdFx0XHRpZiAoIEV4cHIucmVsYXRpdmVbIHRva2Vuc1tqXS50eXBlIF0gKSB7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHNldE1hdGNoZXIoXG5cdFx0XHRcdFx0aSA+IDEgJiYgZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksXG5cdFx0XHRcdFx0aSA+IDEgJiYgdG9TZWxlY3Rvcihcblx0XHRcdFx0XHRcdC8vIElmIHRoZSBwcmVjZWRpbmcgdG9rZW4gd2FzIGEgZGVzY2VuZGFudCBjb21iaW5hdG9yLCBpbnNlcnQgYW4gaW1wbGljaXQgYW55LWVsZW1lbnQgYCpgXG5cdFx0XHRcdFx0XHR0b2tlbnMuc2xpY2UoIDAsIGkgLSAxICkuY29uY2F0KHsgdmFsdWU6IHRva2Vuc1sgaSAtIDIgXS50eXBlID09PSBcIiBcIiA/IFwiKlwiIDogXCJcIiB9KVxuXHRcdFx0XHRcdCkucmVwbGFjZSggcnRyaW0sIFwiJDFcIiApLFxuXHRcdFx0XHRcdG1hdGNoZXIsXG5cdFx0XHRcdFx0aSA8IGogJiYgbWF0Y2hlckZyb21Ub2tlbnMoIHRva2Vucy5zbGljZSggaSwgaiApICksXG5cdFx0XHRcdFx0aiA8IGxlbiAmJiBtYXRjaGVyRnJvbVRva2VucyggKHRva2VucyA9IHRva2Vucy5zbGljZSggaiApKSApLFxuXHRcdFx0XHRcdGogPCBsZW4gJiYgdG9TZWxlY3RvciggdG9rZW5zIClcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHRcdG1hdGNoZXJzLnB1c2goIG1hdGNoZXIgKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXJGcm9tR3JvdXBNYXRjaGVycyggZWxlbWVudE1hdGNoZXJzLCBzZXRNYXRjaGVycyApIHtcblx0dmFyIGJ5U2V0ID0gc2V0TWF0Y2hlcnMubGVuZ3RoID4gMCxcblx0XHRieUVsZW1lbnQgPSBlbGVtZW50TWF0Y2hlcnMubGVuZ3RoID4gMCxcblx0XHRzdXBlck1hdGNoZXIgPSBmdW5jdGlvbiggc2VlZCwgY29udGV4dCwgeG1sLCByZXN1bHRzLCBvdXRlcm1vc3QgKSB7XG5cdFx0XHR2YXIgZWxlbSwgaiwgbWF0Y2hlcixcblx0XHRcdFx0bWF0Y2hlZENvdW50ID0gMCxcblx0XHRcdFx0aSA9IFwiMFwiLFxuXHRcdFx0XHR1bm1hdGNoZWQgPSBzZWVkICYmIFtdLFxuXHRcdFx0XHRzZXRNYXRjaGVkID0gW10sXG5cdFx0XHRcdGNvbnRleHRCYWNrdXAgPSBvdXRlcm1vc3RDb250ZXh0LFxuXHRcdFx0XHQvLyBXZSBtdXN0IGFsd2F5cyBoYXZlIGVpdGhlciBzZWVkIGVsZW1lbnRzIG9yIG91dGVybW9zdCBjb250ZXh0XG5cdFx0XHRcdGVsZW1zID0gc2VlZCB8fCBieUVsZW1lbnQgJiYgRXhwci5maW5kW1wiVEFHXCJdKCBcIipcIiwgb3V0ZXJtb3N0ICksXG5cdFx0XHRcdC8vIFVzZSBpbnRlZ2VyIGRpcnJ1bnMgaWZmIHRoaXMgaXMgdGhlIG91dGVybW9zdCBtYXRjaGVyXG5cdFx0XHRcdGRpcnJ1bnNVbmlxdWUgPSAoZGlycnVucyArPSBjb250ZXh0QmFja3VwID09IG51bGwgPyAxIDogTWF0aC5yYW5kb20oKSB8fCAwLjEpLFxuXHRcdFx0XHRsZW4gPSBlbGVtcy5sZW5ndGg7XG5cblx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRvdXRlcm1vc3RDb250ZXh0ID0gY29udGV4dCA9PT0gZG9jdW1lbnQgfHwgY29udGV4dCB8fCBvdXRlcm1vc3Q7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBlbGVtZW50cyBwYXNzaW5nIGVsZW1lbnRNYXRjaGVycyBkaXJlY3RseSB0byByZXN1bHRzXG5cdFx0XHQvLyBTdXBwb3J0OiBJRTw5LCBTYWZhcmlcblx0XHRcdC8vIFRvbGVyYXRlIE5vZGVMaXN0IHByb3BlcnRpZXMgKElFOiBcImxlbmd0aFwiOyBTYWZhcmk6IDxudW1iZXI+KSBtYXRjaGluZyBlbGVtZW50cyBieSBpZFxuXHRcdFx0Zm9yICggOyBpICE9PSBsZW4gJiYgKGVsZW0gPSBlbGVtc1tpXSkgIT0gbnVsbDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGJ5RWxlbWVudCAmJiBlbGVtICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdGlmICggIWNvbnRleHQgJiYgZWxlbS5vd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCApIHtcblx0XHRcdFx0XHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdFx0XHRcdFx0XHR4bWwgPSAhZG9jdW1lbnRJc0hUTUw7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHdoaWxlICggKG1hdGNoZXIgPSBlbGVtZW50TWF0Y2hlcnNbaisrXSkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQgfHwgZG9jdW1lbnQsIHhtbCkgKSB7XG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCBvdXRlcm1vc3QgKSB7XG5cdFx0XHRcdFx0XHRkaXJydW5zID0gZGlycnVuc1VuaXF1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBUcmFjayB1bm1hdGNoZWQgZWxlbWVudHMgZm9yIHNldCBmaWx0ZXJzXG5cdFx0XHRcdGlmICggYnlTZXQgKSB7XG5cdFx0XHRcdFx0Ly8gVGhleSB3aWxsIGhhdmUgZ29uZSB0aHJvdWdoIGFsbCBwb3NzaWJsZSBtYXRjaGVyc1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSAhbWF0Y2hlciAmJiBlbGVtKSApIHtcblx0XHRcdFx0XHRcdG1hdGNoZWRDb3VudC0tO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIExlbmd0aGVuIHRoZSBhcnJheSBmb3IgZXZlcnkgZWxlbWVudCwgbWF0Y2hlZCBvciBub3Rcblx0XHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0XHR1bm1hdGNoZWQucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBgaWAgaXMgbm93IHRoZSBjb3VudCBvZiBlbGVtZW50cyB2aXNpdGVkIGFib3ZlLCBhbmQgYWRkaW5nIGl0IHRvIGBtYXRjaGVkQ291bnRgXG5cdFx0XHQvLyBtYWtlcyB0aGUgbGF0dGVyIG5vbm5lZ2F0aXZlLlxuXHRcdFx0bWF0Y2hlZENvdW50ICs9IGk7XG5cblx0XHRcdC8vIEFwcGx5IHNldCBmaWx0ZXJzIHRvIHVubWF0Y2hlZCBlbGVtZW50c1xuXHRcdFx0Ly8gTk9URTogVGhpcyBjYW4gYmUgc2tpcHBlZCBpZiB0aGVyZSBhcmUgbm8gdW5tYXRjaGVkIGVsZW1lbnRzIChpLmUuLCBgbWF0Y2hlZENvdW50YFxuXHRcdFx0Ly8gZXF1YWxzIGBpYCksIHVubGVzcyB3ZSBkaWRuJ3QgdmlzaXQgX2FueV8gZWxlbWVudHMgaW4gdGhlIGFib3ZlIGxvb3AgYmVjYXVzZSB3ZSBoYXZlXG5cdFx0XHQvLyBubyBlbGVtZW50IG1hdGNoZXJzIGFuZCBubyBzZWVkLlxuXHRcdFx0Ly8gSW5jcmVtZW50aW5nIGFuIGluaXRpYWxseS1zdHJpbmcgXCIwXCIgYGlgIGFsbG93cyBgaWAgdG8gcmVtYWluIGEgc3RyaW5nIG9ubHkgaW4gdGhhdFxuXHRcdFx0Ly8gY2FzZSwgd2hpY2ggd2lsbCByZXN1bHQgaW4gYSBcIjAwXCIgYG1hdGNoZWRDb3VudGAgdGhhdCBkaWZmZXJzIGZyb20gYGlgIGJ1dCBpcyBhbHNvXG5cdFx0XHQvLyBudW1lcmljYWxseSB6ZXJvLlxuXHRcdFx0aWYgKCBieVNldCAmJiBpICE9PSBtYXRjaGVkQ291bnQgKSB7XG5cdFx0XHRcdGogPSAwO1xuXHRcdFx0XHR3aGlsZSAoIChtYXRjaGVyID0gc2V0TWF0Y2hlcnNbaisrXSkgKSB7XG5cdFx0XHRcdFx0bWF0Y2hlciggdW5tYXRjaGVkLCBzZXRNYXRjaGVkLCBjb250ZXh0LCB4bWwgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggc2VlZCApIHtcblx0XHRcdFx0XHQvLyBSZWludGVncmF0ZSBlbGVtZW50IG1hdGNoZXMgdG8gZWxpbWluYXRlIHRoZSBuZWVkIGZvciBzb3J0aW5nXG5cdFx0XHRcdFx0aWYgKCBtYXRjaGVkQ291bnQgPiAwICkge1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggISh1bm1hdGNoZWRbaV0gfHwgc2V0TWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0c2V0TWF0Y2hlZFtpXSA9IHBvcC5jYWxsKCByZXN1bHRzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBEaXNjYXJkIGluZGV4IHBsYWNlaG9sZGVyIHZhbHVlcyB0byBnZXQgb25seSBhY3R1YWwgbWF0Y2hlc1xuXHRcdFx0XHRcdHNldE1hdGNoZWQgPSBjb25kZW5zZSggc2V0TWF0Y2hlZCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQWRkIG1hdGNoZXMgdG8gcmVzdWx0c1xuXHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBzZXRNYXRjaGVkICk7XG5cblx0XHRcdFx0Ly8gU2VlZGxlc3Mgc2V0IG1hdGNoZXMgc3VjY2VlZGluZyBtdWx0aXBsZSBzdWNjZXNzZnVsIG1hdGNoZXJzIHN0aXB1bGF0ZSBzb3J0aW5nXG5cdFx0XHRcdGlmICggb3V0ZXJtb3N0ICYmICFzZWVkICYmIHNldE1hdGNoZWQubGVuZ3RoID4gMCAmJlxuXHRcdFx0XHRcdCggbWF0Y2hlZENvdW50ICsgc2V0TWF0Y2hlcnMubGVuZ3RoICkgPiAxICkge1xuXG5cdFx0XHRcdFx0U2l6emxlLnVuaXF1ZVNvcnQoIHJlc3VsdHMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBPdmVycmlkZSBtYW5pcHVsYXRpb24gb2YgZ2xvYmFscyBieSBuZXN0ZWQgbWF0Y2hlcnNcblx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRkaXJydW5zID0gZGlycnVuc1VuaXF1ZTtcblx0XHRcdFx0b3V0ZXJtb3N0Q29udGV4dCA9IGNvbnRleHRCYWNrdXA7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB1bm1hdGNoZWQ7XG5cdFx0fTtcblxuXHRyZXR1cm4gYnlTZXQgP1xuXHRcdG1hcmtGdW5jdGlvbiggc3VwZXJNYXRjaGVyICkgOlxuXHRcdHN1cGVyTWF0Y2hlcjtcbn1cblxuY29tcGlsZSA9IFNpenpsZS5jb21waWxlID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBtYXRjaCAvKiBJbnRlcm5hbCBVc2UgT25seSAqLyApIHtcblx0dmFyIGksXG5cdFx0c2V0TWF0Y2hlcnMgPSBbXSxcblx0XHRlbGVtZW50TWF0Y2hlcnMgPSBbXSxcblx0XHRjYWNoZWQgPSBjb21waWxlckNhY2hlWyBzZWxlY3RvciArIFwiIFwiIF07XG5cblx0aWYgKCAhY2FjaGVkICkge1xuXHRcdC8vIEdlbmVyYXRlIGEgZnVuY3Rpb24gb2YgcmVjdXJzaXZlIGZ1bmN0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIHRvIGNoZWNrIGVhY2ggZWxlbWVudFxuXHRcdGlmICggIW1hdGNoICkge1xuXHRcdFx0bWF0Y2ggPSB0b2tlbml6ZSggc2VsZWN0b3IgKTtcblx0XHR9XG5cdFx0aSA9IG1hdGNoLmxlbmd0aDtcblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdGNhY2hlZCA9IG1hdGNoZXJGcm9tVG9rZW5zKCBtYXRjaFtpXSApO1xuXHRcdFx0aWYgKCBjYWNoZWRbIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0c2V0TWF0Y2hlcnMucHVzaCggY2FjaGVkICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbGVtZW50TWF0Y2hlcnMucHVzaCggY2FjaGVkICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FjaGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZSggc2VsZWN0b3IsIG1hdGNoZXJGcm9tR3JvdXBNYXRjaGVycyggZWxlbWVudE1hdGNoZXJzLCBzZXRNYXRjaGVycyApICk7XG5cblx0XHQvLyBTYXZlIHNlbGVjdG9yIGFuZCB0b2tlbml6YXRpb25cblx0XHRjYWNoZWQuc2VsZWN0b3IgPSBzZWxlY3Rvcjtcblx0fVxuXHRyZXR1cm4gY2FjaGVkO1xufTtcblxuLyoqXG4gKiBBIGxvdy1sZXZlbCBzZWxlY3Rpb24gZnVuY3Rpb24gdGhhdCB3b3JrcyB3aXRoIFNpenpsZSdzIGNvbXBpbGVkXG4gKiAgc2VsZWN0b3IgZnVuY3Rpb25zXG4gKiBAcGFyYW0ge1N0cmluZ3xGdW5jdGlvbn0gc2VsZWN0b3IgQSBzZWxlY3RvciBvciBhIHByZS1jb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uIGJ1aWx0IHdpdGggU2l6emxlLmNvbXBpbGVcbiAqIEBwYXJhbSB7RWxlbWVudH0gY29udGV4dFxuICogQHBhcmFtIHtBcnJheX0gW3Jlc3VsdHNdXG4gKiBAcGFyYW0ge0FycmF5fSBbc2VlZF0gQSBzZXQgb2YgZWxlbWVudHMgdG8gbWF0Y2ggYWdhaW5zdFxuICovXG5zZWxlY3QgPSBTaXp6bGUuc2VsZWN0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICkge1xuXHR2YXIgaSwgdG9rZW5zLCB0b2tlbiwgdHlwZSwgZmluZCxcblx0XHRjb21waWxlZCA9IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICYmIHNlbGVjdG9yLFxuXHRcdG1hdGNoID0gIXNlZWQgJiYgdG9rZW5pemUoIChzZWxlY3RvciA9IGNvbXBpbGVkLnNlbGVjdG9yIHx8IHNlbGVjdG9yKSApO1xuXG5cdHJlc3VsdHMgPSByZXN1bHRzIHx8IFtdO1xuXG5cdC8vIFRyeSB0byBtaW5pbWl6ZSBvcGVyYXRpb25zIGlmIHRoZXJlIGlzIG9ubHkgb25lIHNlbGVjdG9yIGluIHRoZSBsaXN0IGFuZCBubyBzZWVkXG5cdC8vICh0aGUgbGF0dGVyIG9mIHdoaWNoIGd1YXJhbnRlZXMgdXMgY29udGV4dClcblx0aWYgKCBtYXRjaC5sZW5ndGggPT09IDEgKSB7XG5cblx0XHQvLyBSZWR1Y2UgY29udGV4dCBpZiB0aGUgbGVhZGluZyBjb21wb3VuZCBzZWxlY3RvciBpcyBhbiBJRFxuXHRcdHRva2VucyA9IG1hdGNoWzBdID0gbWF0Y2hbMF0uc2xpY2UoIDAgKTtcblx0XHRpZiAoIHRva2Vucy5sZW5ndGggPiAyICYmICh0b2tlbiA9IHRva2Vuc1swXSkudHlwZSA9PT0gXCJJRFwiICYmXG5cdFx0XHRcdGNvbnRleHQubm9kZVR5cGUgPT09IDkgJiYgZG9jdW1lbnRJc0hUTUwgJiYgRXhwci5yZWxhdGl2ZVsgdG9rZW5zWzFdLnR5cGUgXSApIHtcblxuXHRcdFx0Y29udGV4dCA9ICggRXhwci5maW5kW1wiSURcIl0oIHRva2VuLm1hdGNoZXNbMF0ucmVwbGFjZShydW5lc2NhcGUsIGZ1bmVzY2FwZSksIGNvbnRleHQgKSB8fCBbXSApWzBdO1xuXHRcdFx0aWYgKCAhY29udGV4dCApIHtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdC8vIFByZWNvbXBpbGVkIG1hdGNoZXJzIHdpbGwgc3RpbGwgdmVyaWZ5IGFuY2VzdHJ5LCBzbyBzdGVwIHVwIGEgbGV2ZWxcblx0XHRcdH0gZWxzZSBpZiAoIGNvbXBpbGVkICkge1xuXHRcdFx0XHRjb250ZXh0ID0gY29udGV4dC5wYXJlbnROb2RlO1xuXHRcdFx0fVxuXG5cdFx0XHRzZWxlY3RvciA9IHNlbGVjdG9yLnNsaWNlKCB0b2tlbnMuc2hpZnQoKS52YWx1ZS5sZW5ndGggKTtcblx0XHR9XG5cblx0XHQvLyBGZXRjaCBhIHNlZWQgc2V0IGZvciByaWdodC10by1sZWZ0IG1hdGNoaW5nXG5cdFx0aSA9IG1hdGNoRXhwcltcIm5lZWRzQ29udGV4dFwiXS50ZXN0KCBzZWxlY3RvciApID8gMCA6IHRva2Vucy5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHR0b2tlbiA9IHRva2Vuc1tpXTtcblxuXHRcdFx0Ly8gQWJvcnQgaWYgd2UgaGl0IGEgY29tYmluYXRvclxuXHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyAodHlwZSA9IHRva2VuLnR5cGUpIF0gKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAoZmluZCA9IEV4cHIuZmluZFsgdHlwZSBdKSApIHtcblx0XHRcdFx0Ly8gU2VhcmNoLCBleHBhbmRpbmcgY29udGV4dCBmb3IgbGVhZGluZyBzaWJsaW5nIGNvbWJpbmF0b3JzXG5cdFx0XHRcdGlmICggKHNlZWQgPSBmaW5kKFxuXHRcdFx0XHRcdHRva2VuLm1hdGNoZXNbMF0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKSxcblx0XHRcdFx0XHRyc2libGluZy50ZXN0KCB0b2tlbnNbMF0udHlwZSApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fCBjb250ZXh0XG5cdFx0XHRcdCkpICkge1xuXG5cdFx0XHRcdFx0Ly8gSWYgc2VlZCBpcyBlbXB0eSBvciBubyB0b2tlbnMgcmVtYWluLCB3ZSBjYW4gcmV0dXJuIGVhcmx5XG5cdFx0XHRcdFx0dG9rZW5zLnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdHNlbGVjdG9yID0gc2VlZC5sZW5ndGggJiYgdG9TZWxlY3RvciggdG9rZW5zICk7XG5cdFx0XHRcdFx0aWYgKCAhc2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBzZWVkICk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIENvbXBpbGUgYW5kIGV4ZWN1dGUgYSBmaWx0ZXJpbmcgZnVuY3Rpb24gaWYgb25lIGlzIG5vdCBwcm92aWRlZFxuXHQvLyBQcm92aWRlIGBtYXRjaGAgdG8gYXZvaWQgcmV0b2tlbml6YXRpb24gaWYgd2UgbW9kaWZpZWQgdGhlIHNlbGVjdG9yIGFib3ZlXG5cdCggY29tcGlsZWQgfHwgY29tcGlsZSggc2VsZWN0b3IsIG1hdGNoICkgKShcblx0XHRzZWVkLFxuXHRcdGNvbnRleHQsXG5cdFx0IWRvY3VtZW50SXNIVE1MLFxuXHRcdHJlc3VsdHMsXG5cdFx0IWNvbnRleHQgfHwgcnNpYmxpbmcudGVzdCggc2VsZWN0b3IgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHQpO1xuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8vIE9uZS10aW1lIGFzc2lnbm1lbnRzXG5cbi8vIFNvcnQgc3RhYmlsaXR5XG5zdXBwb3J0LnNvcnRTdGFibGUgPSBleHBhbmRvLnNwbGl0KFwiXCIpLnNvcnQoIHNvcnRPcmRlciApLmpvaW4oXCJcIikgPT09IGV4cGFuZG87XG5cbi8vIFN1cHBvcnQ6IENocm9tZSAxNC0zNStcbi8vIEFsd2F5cyBhc3N1bWUgZHVwbGljYXRlcyBpZiB0aGV5IGFyZW4ndCBwYXNzZWQgdG8gdGhlIGNvbXBhcmlzb24gZnVuY3Rpb25cbnN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcyA9ICEhaGFzRHVwbGljYXRlO1xuXG4vLyBJbml0aWFsaXplIGFnYWluc3QgdGhlIGRlZmF1bHQgZG9jdW1lbnRcbnNldERvY3VtZW50KCk7XG5cbi8vIFN1cHBvcnQ6IFdlYmtpdDw1MzcuMzIgLSBTYWZhcmkgNi4wLjMvQ2hyb21lIDI1IChmaXhlZCBpbiBDaHJvbWUgMjcpXG4vLyBEZXRhY2hlZCBub2RlcyBjb25mb3VuZGluZ2x5IGZvbGxvdyAqZWFjaCBvdGhlcipcbnN1cHBvcnQuc29ydERldGFjaGVkID0gYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0Ly8gU2hvdWxkIHJldHVybiAxLCBidXQgcmV0dXJucyA0IChmb2xsb3dpbmcpXG5cdHJldHVybiBlbC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiggZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImZpZWxkc2V0XCIpICkgJiAxO1xufSk7XG5cbi8vIFN1cHBvcnQ6IElFPDhcbi8vIFByZXZlbnQgYXR0cmlidXRlL3Byb3BlcnR5IFwiaW50ZXJwb2xhdGlvblwiXG4vLyBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM2NDI5JTI4VlMuODUlMjkuYXNweFxuaWYgKCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0ZWwuaW5uZXJIVE1MID0gXCI8YSBocmVmPScjJz48L2E+XCI7XG5cdHJldHVybiBlbC5maXJzdENoaWxkLmdldEF0dHJpYnV0ZShcImhyZWZcIikgPT09IFwiI1wiIDtcbn0pICkge1xuXHRhZGRIYW5kbGUoIFwidHlwZXxocmVmfGhlaWdodHx3aWR0aFwiLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGUoIG5hbWUsIG5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJ0eXBlXCIgPyAxIDogMiApO1xuXHRcdH1cblx0fSk7XG59XG5cbi8vIFN1cHBvcnQ6IElFPDlcbi8vIFVzZSBkZWZhdWx0VmFsdWUgaW4gcGxhY2Ugb2YgZ2V0QXR0cmlidXRlKFwidmFsdWVcIilcbmlmICggIXN1cHBvcnQuYXR0cmlidXRlcyB8fCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0ZWwuaW5uZXJIVE1MID0gXCI8aW5wdXQvPlwiO1xuXHRlbC5maXJzdENoaWxkLnNldEF0dHJpYnV0ZSggXCJ2YWx1ZVwiLCBcIlwiICk7XG5cdHJldHVybiBlbC5maXJzdENoaWxkLmdldEF0dHJpYnV0ZSggXCJ2YWx1ZVwiICkgPT09IFwiXCI7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInZhbHVlXCIsIGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBpc1hNTCApIHtcblx0XHRpZiAoICFpc1hNTCAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaW5wdXRcIiApIHtcblx0XHRcdHJldHVybiBlbGVtLmRlZmF1bHRWYWx1ZTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZ2V0QXR0cmlidXRlTm9kZSB0byBmZXRjaCBib29sZWFucyB3aGVuIGdldEF0dHJpYnV0ZSBsaWVzXG5pZiAoICFhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRyZXR1cm4gZWwuZ2V0QXR0cmlidXRlKFwiZGlzYWJsZWRcIikgPT0gbnVsbDtcbn0pICkge1xuXHRhZGRIYW5kbGUoIGJvb2xlYW5zLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0dmFyIHZhbDtcblx0XHRpZiAoICFpc1hNTCApIHtcblx0XHRcdHJldHVybiBlbGVtWyBuYW1lIF0gPT09IHRydWUgPyBuYW1lLnRvTG93ZXJDYXNlKCkgOlxuXHRcdFx0XHRcdCh2YWwgPSBlbGVtLmdldEF0dHJpYnV0ZU5vZGUoIG5hbWUgKSkgJiYgdmFsLnNwZWNpZmllZCA/XG5cdFx0XHRcdFx0dmFsLnZhbHVlIDpcblx0XHRcdFx0bnVsbDtcblx0XHR9XG5cdH0pO1xufVxuXG5yZXR1cm4gU2l6emxlO1xuXG59KSggd2luZG93ICk7XG5cblxuXG5qUXVlcnkuZmluZCA9IFNpenpsZTtcbmpRdWVyeS5leHByID0gU2l6emxlLnNlbGVjdG9ycztcblxuLy8gRGVwcmVjYXRlZFxualF1ZXJ5LmV4cHJbIFwiOlwiIF0gPSBqUXVlcnkuZXhwci5wc2V1ZG9zO1xualF1ZXJ5LnVuaXF1ZVNvcnQgPSBqUXVlcnkudW5pcXVlID0gU2l6emxlLnVuaXF1ZVNvcnQ7XG5qUXVlcnkudGV4dCA9IFNpenpsZS5nZXRUZXh0O1xualF1ZXJ5LmlzWE1MRG9jID0gU2l6emxlLmlzWE1MO1xualF1ZXJ5LmNvbnRhaW5zID0gU2l6emxlLmNvbnRhaW5zO1xualF1ZXJ5LmVzY2FwZVNlbGVjdG9yID0gU2l6emxlLmVzY2FwZTtcblxuXG5cblxudmFyIGRpciA9IGZ1bmN0aW9uKCBlbGVtLCBkaXIsIHVudGlsICkge1xuXHR2YXIgbWF0Y2hlZCA9IFtdLFxuXHRcdHRydW5jYXRlID0gdW50aWwgIT09IHVuZGVmaW5lZDtcblxuXHR3aGlsZSAoICggZWxlbSA9IGVsZW1bIGRpciBdICkgJiYgZWxlbS5ub2RlVHlwZSAhPT0gOSApIHtcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRpZiAoIHRydW5jYXRlICYmIGpRdWVyeSggZWxlbSApLmlzKCB1bnRpbCApICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdG1hdGNoZWQucHVzaCggZWxlbSApO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbWF0Y2hlZDtcbn07XG5cblxudmFyIHNpYmxpbmdzID0gZnVuY3Rpb24oIG4sIGVsZW0gKSB7XG5cdHZhciBtYXRjaGVkID0gW107XG5cblx0Zm9yICggOyBuOyBuID0gbi5uZXh0U2libGluZyApIHtcblx0XHRpZiAoIG4ubm9kZVR5cGUgPT09IDEgJiYgbiAhPT0gZWxlbSApIHtcblx0XHRcdG1hdGNoZWQucHVzaCggbiApO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBtYXRjaGVkO1xufTtcblxuXG52YXIgcm5lZWRzQ29udGV4dCA9IGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dDtcblxuXG5cbmZ1bmN0aW9uIG5vZGVOYW1lKCBlbGVtLCBuYW1lICkge1xuXG4gIHJldHVybiBlbGVtLm5vZGVOYW1lICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXG59O1xudmFyIHJzaW5nbGVUYWcgPSAoIC9ePChbYS16XVteXFwvXFwwPjpcXHgyMFxcdFxcclxcblxcZl0qKVtcXHgyMFxcdFxcclxcblxcZl0qXFwvPz4oPzo8XFwvXFwxPnwpJC9pICk7XG5cblxuXG52YXIgcmlzU2ltcGxlID0gL14uW146I1xcW1xcLixdKiQvO1xuXG4vLyBJbXBsZW1lbnQgdGhlIGlkZW50aWNhbCBmdW5jdGlvbmFsaXR5IGZvciBmaWx0ZXIgYW5kIG5vdFxuZnVuY3Rpb24gd2lubm93KCBlbGVtZW50cywgcXVhbGlmaWVyLCBub3QgKSB7XG5cdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHF1YWxpZmllciApICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtLCBpICkge1xuXHRcdFx0cmV0dXJuICEhcXVhbGlmaWVyLmNhbGwoIGVsZW0sIGksIGVsZW0gKSAhPT0gbm90O1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIFNpbmdsZSBlbGVtZW50XG5cdGlmICggcXVhbGlmaWVyLm5vZGVUeXBlICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICggZWxlbSA9PT0gcXVhbGlmaWVyICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBBcnJheWxpa2Ugb2YgZWxlbWVudHMgKGpRdWVyeSwgYXJndW1lbnRzLCBBcnJheSlcblx0aWYgKCB0eXBlb2YgcXVhbGlmaWVyICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICggaW5kZXhPZi5jYWxsKCBxdWFsaWZpZXIsIGVsZW0gKSA+IC0xICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBTaW1wbGUgc2VsZWN0b3IgdGhhdCBjYW4gYmUgZmlsdGVyZWQgZGlyZWN0bHksIHJlbW92aW5nIG5vbi1FbGVtZW50c1xuXHRpZiAoIHJpc1NpbXBsZS50ZXN0KCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmZpbHRlciggcXVhbGlmaWVyLCBlbGVtZW50cywgbm90ICk7XG5cdH1cblxuXHQvLyBDb21wbGV4IHNlbGVjdG9yLCBjb21wYXJlIHRoZSB0d28gc2V0cywgcmVtb3Zpbmcgbm9uLUVsZW1lbnRzXG5cdHF1YWxpZmllciA9IGpRdWVyeS5maWx0ZXIoIHF1YWxpZmllciwgZWxlbWVudHMgKTtcblx0cmV0dXJuIGpRdWVyeS5ncmVwKCBlbGVtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuICggaW5kZXhPZi5jYWxsKCBxdWFsaWZpZXIsIGVsZW0gKSA+IC0xICkgIT09IG5vdCAmJiBlbGVtLm5vZGVUeXBlID09PSAxO1xuXHR9ICk7XG59XG5cbmpRdWVyeS5maWx0ZXIgPSBmdW5jdGlvbiggZXhwciwgZWxlbXMsIG5vdCApIHtcblx0dmFyIGVsZW0gPSBlbGVtc1sgMCBdO1xuXG5cdGlmICggbm90ICkge1xuXHRcdGV4cHIgPSBcIjpub3QoXCIgKyBleHByICsgXCIpXCI7XG5cdH1cblxuXHRpZiAoIGVsZW1zLmxlbmd0aCA9PT0gMSAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdHJldHVybiBqUXVlcnkuZmluZC5tYXRjaGVzU2VsZWN0b3IoIGVsZW0sIGV4cHIgKSA/IFsgZWxlbSBdIDogW107XG5cdH1cblxuXHRyZXR1cm4galF1ZXJ5LmZpbmQubWF0Y2hlcyggZXhwciwgalF1ZXJ5LmdyZXAoIGVsZW1zLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gZWxlbS5ub2RlVHlwZSA9PT0gMTtcblx0fSApICk7XG59O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGZpbmQ6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgaSwgcmV0LFxuXHRcdFx0bGVuID0gdGhpcy5sZW5ndGgsXG5cdFx0XHRzZWxmID0gdGhpcztcblxuXHRcdGlmICggdHlwZW9mIHNlbGVjdG9yICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkoIHNlbGVjdG9yICkuZmlsdGVyKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0Zm9yICggaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHRpZiAoIGpRdWVyeS5jb250YWlucyggc2VsZlsgaSBdLCB0aGlzICkgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gKSApO1xuXHRcdH1cblxuXHRcdHJldCA9IHRoaXMucHVzaFN0YWNrKCBbXSApO1xuXG5cdFx0Zm9yICggaSA9IDA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGpRdWVyeS5maW5kKCBzZWxlY3Rvciwgc2VsZlsgaSBdLCByZXQgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbGVuID4gMSA/IGpRdWVyeS51bmlxdWVTb3J0KCByZXQgKSA6IHJldDtcblx0fSxcblx0ZmlsdGVyOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCB3aW5ub3coIHRoaXMsIHNlbGVjdG9yIHx8IFtdLCBmYWxzZSApICk7XG5cdH0sXG5cdG5vdDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KCB0aGlzLCBzZWxlY3RvciB8fCBbXSwgdHJ1ZSApICk7XG5cdH0sXG5cdGlzOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuICEhd2lubm93KFxuXHRcdFx0dGhpcyxcblxuXHRcdFx0Ly8gSWYgdGhpcyBpcyBhIHBvc2l0aW9uYWwvcmVsYXRpdmUgc2VsZWN0b3IsIGNoZWNrIG1lbWJlcnNoaXAgaW4gdGhlIHJldHVybmVkIHNldFxuXHRcdFx0Ly8gc28gJChcInA6Zmlyc3RcIikuaXMoXCJwOmxhc3RcIikgd29uJ3QgcmV0dXJuIHRydWUgZm9yIGEgZG9jIHdpdGggdHdvIFwicFwiLlxuXHRcdFx0dHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiICYmIHJuZWVkc0NvbnRleHQudGVzdCggc2VsZWN0b3IgKSA/XG5cdFx0XHRcdGpRdWVyeSggc2VsZWN0b3IgKSA6XG5cdFx0XHRcdHNlbGVjdG9yIHx8IFtdLFxuXHRcdFx0ZmFsc2Vcblx0XHQpLmxlbmd0aDtcblx0fVxufSApO1xuXG5cbi8vIEluaXRpYWxpemUgYSBqUXVlcnkgb2JqZWN0XG5cblxuLy8gQSBjZW50cmFsIHJlZmVyZW5jZSB0byB0aGUgcm9vdCBqUXVlcnkoZG9jdW1lbnQpXG52YXIgcm9vdGpRdWVyeSxcblxuXHQvLyBBIHNpbXBsZSB3YXkgdG8gY2hlY2sgZm9yIEhUTUwgc3RyaW5nc1xuXHQvLyBQcmlvcml0aXplICNpZCBvdmVyIDx0YWc+IHRvIGF2b2lkIFhTUyB2aWEgbG9jYXRpb24uaGFzaCAoIzk1MjEpXG5cdC8vIFN0cmljdCBIVE1MIHJlY29nbml0aW9uICgjMTEyOTA6IG11c3Qgc3RhcnQgd2l0aCA8KVxuXHQvLyBTaG9ydGN1dCBzaW1wbGUgI2lkIGNhc2UgZm9yIHNwZWVkXG5cdHJxdWlja0V4cHIgPSAvXig/OlxccyooPFtcXHdcXFddKz4pW14+XSp8IyhbXFx3LV0rKSkkLyxcblxuXHRpbml0ID0galF1ZXJ5LmZuLmluaXQgPSBmdW5jdGlvbiggc2VsZWN0b3IsIGNvbnRleHQsIHJvb3QgKSB7XG5cdFx0dmFyIG1hdGNoLCBlbGVtO1xuXG5cdFx0Ly8gSEFORExFOiAkKFwiXCIpLCAkKG51bGwpLCAkKHVuZGVmaW5lZCksICQoZmFsc2UpXG5cdFx0aWYgKCAhc2VsZWN0b3IgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9XG5cblx0XHQvLyBNZXRob2QgaW5pdCgpIGFjY2VwdHMgYW4gYWx0ZXJuYXRlIHJvb3RqUXVlcnlcblx0XHQvLyBzbyBtaWdyYXRlIGNhbiBzdXBwb3J0IGpRdWVyeS5zdWIgKGdoLTIxMDEpXG5cdFx0cm9vdCA9IHJvb3QgfHwgcm9vdGpRdWVyeTtcblxuXHRcdC8vIEhhbmRsZSBIVE1MIHN0cmluZ3Ncblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGlmICggc2VsZWN0b3JbIDAgXSA9PT0gXCI8XCIgJiZcblx0XHRcdFx0c2VsZWN0b3JbIHNlbGVjdG9yLmxlbmd0aCAtIDEgXSA9PT0gXCI+XCIgJiZcblx0XHRcdFx0c2VsZWN0b3IubGVuZ3RoID49IDMgKSB7XG5cblx0XHRcdFx0Ly8gQXNzdW1lIHRoYXQgc3RyaW5ncyB0aGF0IHN0YXJ0IGFuZCBlbmQgd2l0aCA8PiBhcmUgSFRNTCBhbmQgc2tpcCB0aGUgcmVnZXggY2hlY2tcblx0XHRcdFx0bWF0Y2ggPSBbIG51bGwsIHNlbGVjdG9yLCBudWxsIF07XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYXRjaCBodG1sIG9yIG1ha2Ugc3VyZSBubyBjb250ZXh0IGlzIHNwZWNpZmllZCBmb3IgI2lkXG5cdFx0XHRpZiAoIG1hdGNoICYmICggbWF0Y2hbIDEgXSB8fCAhY29udGV4dCApICkge1xuXG5cdFx0XHRcdC8vIEhBTkRMRTogJChodG1sKSAtPiAkKGFycmF5KVxuXHRcdFx0XHRpZiAoIG1hdGNoWyAxIF0gKSB7XG5cdFx0XHRcdFx0Y29udGV4dCA9IGNvbnRleHQgaW5zdGFuY2VvZiBqUXVlcnkgPyBjb250ZXh0WyAwIF0gOiBjb250ZXh0O1xuXG5cdFx0XHRcdFx0Ly8gT3B0aW9uIHRvIHJ1biBzY3JpcHRzIGlzIHRydWUgZm9yIGJhY2stY29tcGF0XG5cdFx0XHRcdFx0Ly8gSW50ZW50aW9uYWxseSBsZXQgdGhlIGVycm9yIGJlIHRocm93biBpZiBwYXJzZUhUTUwgaXMgbm90IHByZXNlbnRcblx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIHRoaXMsIGpRdWVyeS5wYXJzZUhUTUwoXG5cdFx0XHRcdFx0XHRtYXRjaFsgMSBdLFxuXHRcdFx0XHRcdFx0Y29udGV4dCAmJiBjb250ZXh0Lm5vZGVUeXBlID8gY29udGV4dC5vd25lckRvY3VtZW50IHx8IGNvbnRleHQgOiBkb2N1bWVudCxcblx0XHRcdFx0XHRcdHRydWVcblx0XHRcdFx0XHQpICk7XG5cblx0XHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCwgcHJvcHMpXG5cdFx0XHRcdFx0aWYgKCByc2luZ2xlVGFnLnRlc3QoIG1hdGNoWyAxIF0gKSAmJiBqUXVlcnkuaXNQbGFpbk9iamVjdCggY29udGV4dCApICkge1xuXHRcdFx0XHRcdFx0Zm9yICggbWF0Y2ggaW4gY29udGV4dCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBQcm9wZXJ0aWVzIG9mIGNvbnRleHQgYXJlIGNhbGxlZCBhcyBtZXRob2RzIGlmIHBvc3NpYmxlXG5cdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHRoaXNbIG1hdGNoIF0gKSApIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzWyBtYXRjaCBdKCBjb250ZXh0WyBtYXRjaCBdICk7XG5cblx0XHRcdFx0XHRcdFx0Ly8gLi4uYW5kIG90aGVyd2lzZSBzZXQgYXMgYXR0cmlidXRlc1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuYXR0ciggbWF0Y2gsIGNvbnRleHRbIG1hdGNoIF0gKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0XHRcdC8vIEhBTkRMRTogJCgjaWQpXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCBtYXRjaFsgMiBdICk7XG5cblx0XHRcdFx0XHRpZiAoIGVsZW0gKSB7XG5cblx0XHRcdFx0XHRcdC8vIEluamVjdCB0aGUgZWxlbWVudCBkaXJlY3RseSBpbnRvIHRoZSBqUXVlcnkgb2JqZWN0XG5cdFx0XHRcdFx0XHR0aGlzWyAwIF0gPSBlbGVtO1xuXHRcdFx0XHRcdFx0dGhpcy5sZW5ndGggPSAxO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgJCguLi4pKVxuXHRcdFx0fSBlbHNlIGlmICggIWNvbnRleHQgfHwgY29udGV4dC5qcXVlcnkgKSB7XG5cdFx0XHRcdHJldHVybiAoIGNvbnRleHQgfHwgcm9vdCApLmZpbmQoIHNlbGVjdG9yICk7XG5cblx0XHRcdC8vIEhBTkRMRTogJChleHByLCBjb250ZXh0KVxuXHRcdFx0Ly8gKHdoaWNoIGlzIGp1c3QgZXF1aXZhbGVudCB0bzogJChjb250ZXh0KS5maW5kKGV4cHIpXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5jb25zdHJ1Y3RvciggY29udGV4dCApLmZpbmQoIHNlbGVjdG9yICk7XG5cdFx0XHR9XG5cblx0XHQvLyBIQU5ETEU6ICQoRE9NRWxlbWVudClcblx0XHR9IGVsc2UgaWYgKCBzZWxlY3Rvci5ub2RlVHlwZSApIHtcblx0XHRcdHRoaXNbIDAgXSA9IHNlbGVjdG9yO1xuXHRcdFx0dGhpcy5sZW5ndGggPSAxO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHQvLyBIQU5ETEU6ICQoZnVuY3Rpb24pXG5cdFx0Ly8gU2hvcnRjdXQgZm9yIGRvY3VtZW50IHJlYWR5XG5cdFx0fSBlbHNlIGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHNlbGVjdG9yICkgKSB7XG5cdFx0XHRyZXR1cm4gcm9vdC5yZWFkeSAhPT0gdW5kZWZpbmVkID9cblx0XHRcdFx0cm9vdC5yZWFkeSggc2VsZWN0b3IgKSA6XG5cblx0XHRcdFx0Ly8gRXhlY3V0ZSBpbW1lZGlhdGVseSBpZiByZWFkeSBpcyBub3QgcHJlc2VudFxuXHRcdFx0XHRzZWxlY3RvciggalF1ZXJ5ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGpRdWVyeS5tYWtlQXJyYXkoIHNlbGVjdG9yLCB0aGlzICk7XG5cdH07XG5cbi8vIEdpdmUgdGhlIGluaXQgZnVuY3Rpb24gdGhlIGpRdWVyeSBwcm90b3R5cGUgZm9yIGxhdGVyIGluc3RhbnRpYXRpb25cbmluaXQucHJvdG90eXBlID0galF1ZXJ5LmZuO1xuXG4vLyBJbml0aWFsaXplIGNlbnRyYWwgcmVmZXJlbmNlXG5yb290alF1ZXJ5ID0galF1ZXJ5KCBkb2N1bWVudCApO1xuXG5cbnZhciBycGFyZW50c3ByZXYgPSAvXig/OnBhcmVudHN8cHJldig/OlVudGlsfEFsbCkpLyxcblxuXHQvLyBNZXRob2RzIGd1YXJhbnRlZWQgdG8gcHJvZHVjZSBhIHVuaXF1ZSBzZXQgd2hlbiBzdGFydGluZyBmcm9tIGEgdW5pcXVlIHNldFxuXHRndWFyYW50ZWVkVW5pcXVlID0ge1xuXHRcdGNoaWxkcmVuOiB0cnVlLFxuXHRcdGNvbnRlbnRzOiB0cnVlLFxuXHRcdG5leHQ6IHRydWUsXG5cdFx0cHJldjogdHJ1ZVxuXHR9O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGhhczogZnVuY3Rpb24oIHRhcmdldCApIHtcblx0XHR2YXIgdGFyZ2V0cyA9IGpRdWVyeSggdGFyZ2V0LCB0aGlzICksXG5cdFx0XHRsID0gdGFyZ2V0cy5sZW5ndGg7XG5cblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGkgPSAwO1xuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGpRdWVyeS5jb250YWlucyggdGhpcywgdGFyZ2V0c1sgaSBdICkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0Y2xvc2VzdDogZnVuY3Rpb24oIHNlbGVjdG9ycywgY29udGV4dCApIHtcblx0XHR2YXIgY3VyLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsID0gdGhpcy5sZW5ndGgsXG5cdFx0XHRtYXRjaGVkID0gW10sXG5cdFx0XHR0YXJnZXRzID0gdHlwZW9mIHNlbGVjdG9ycyAhPT0gXCJzdHJpbmdcIiAmJiBqUXVlcnkoIHNlbGVjdG9ycyApO1xuXG5cdFx0Ly8gUG9zaXRpb25hbCBzZWxlY3RvcnMgbmV2ZXIgbWF0Y2gsIHNpbmNlIHRoZXJlJ3Mgbm8gX3NlbGVjdGlvbl8gY29udGV4dFxuXHRcdGlmICggIXJuZWVkc0NvbnRleHQudGVzdCggc2VsZWN0b3JzICkgKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdGZvciAoIGN1ciA9IHRoaXNbIGkgXTsgY3VyICYmIGN1ciAhPT0gY29udGV4dDsgY3VyID0gY3VyLnBhcmVudE5vZGUgKSB7XG5cblx0XHRcdFx0XHQvLyBBbHdheXMgc2tpcCBkb2N1bWVudCBmcmFnbWVudHNcblx0XHRcdFx0XHRpZiAoIGN1ci5ub2RlVHlwZSA8IDExICYmICggdGFyZ2V0cyA/XG5cdFx0XHRcdFx0XHR0YXJnZXRzLmluZGV4KCBjdXIgKSA+IC0xIDpcblxuXHRcdFx0XHRcdFx0Ly8gRG9uJ3QgcGFzcyBub24tZWxlbWVudHMgdG8gU2l6emxlXG5cdFx0XHRcdFx0XHRjdXIubm9kZVR5cGUgPT09IDEgJiZcblx0XHRcdFx0XHRcdFx0alF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBjdXIsIHNlbGVjdG9ycyApICkgKSB7XG5cblx0XHRcdFx0XHRcdG1hdGNoZWQucHVzaCggY3VyICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQubGVuZ3RoID4gMSA/IGpRdWVyeS51bmlxdWVTb3J0KCBtYXRjaGVkICkgOiBtYXRjaGVkICk7XG5cdH0sXG5cblx0Ly8gRGV0ZXJtaW5lIHRoZSBwb3NpdGlvbiBvZiBhbiBlbGVtZW50IHdpdGhpbiB0aGUgc2V0XG5cdGluZGV4OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE5vIGFyZ3VtZW50LCByZXR1cm4gaW5kZXggaW4gcGFyZW50XG5cdFx0aWYgKCAhZWxlbSApIHtcblx0XHRcdHJldHVybiAoIHRoaXNbIDAgXSAmJiB0aGlzWyAwIF0ucGFyZW50Tm9kZSApID8gdGhpcy5maXJzdCgpLnByZXZBbGwoKS5sZW5ndGggOiAtMTtcblx0XHR9XG5cblx0XHQvLyBJbmRleCBpbiBzZWxlY3RvclxuXHRcdGlmICggdHlwZW9mIGVsZW0gPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gaW5kZXhPZi5jYWxsKCBqUXVlcnkoIGVsZW0gKSwgdGhpc1sgMCBdICk7XG5cdFx0fVxuXG5cdFx0Ly8gTG9jYXRlIHRoZSBwb3NpdGlvbiBvZiB0aGUgZGVzaXJlZCBlbGVtZW50XG5cdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggdGhpcyxcblxuXHRcdFx0Ly8gSWYgaXQgcmVjZWl2ZXMgYSBqUXVlcnkgb2JqZWN0LCB0aGUgZmlyc3QgZWxlbWVudCBpcyB1c2VkXG5cdFx0XHRlbGVtLmpxdWVyeSA/IGVsZW1bIDAgXSA6IGVsZW1cblx0XHQpO1xuXHR9LFxuXG5cdGFkZDogZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0ICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayhcblx0XHRcdGpRdWVyeS51bmlxdWVTb3J0KFxuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIHRoaXMuZ2V0KCksIGpRdWVyeSggc2VsZWN0b3IsIGNvbnRleHQgKSApXG5cdFx0XHQpXG5cdFx0KTtcblx0fSxcblxuXHRhZGRCYWNrOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHRoaXMuYWRkKCBzZWxlY3RvciA9PSBudWxsID9cblx0XHRcdHRoaXMucHJldk9iamVjdCA6IHRoaXMucHJldk9iamVjdC5maWx0ZXIoIHNlbGVjdG9yIClcblx0XHQpO1xuXHR9XG59ICk7XG5cbmZ1bmN0aW9uIHNpYmxpbmcoIGN1ciwgZGlyICkge1xuXHR3aGlsZSAoICggY3VyID0gY3VyWyBkaXIgXSApICYmIGN1ci5ub2RlVHlwZSAhPT0gMSApIHt9XG5cdHJldHVybiBjdXI7XG59XG5cbmpRdWVyeS5lYWNoKCB7XG5cdHBhcmVudDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRyZXR1cm4gcGFyZW50ICYmIHBhcmVudC5ub2RlVHlwZSAhPT0gMTEgPyBwYXJlbnQgOiBudWxsO1xuXHR9LFxuXHRwYXJlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInBhcmVudE5vZGVcIiApO1xuXHR9LFxuXHRwYXJlbnRzVW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInBhcmVudE5vZGVcIiwgdW50aWwgKTtcblx0fSxcblx0bmV4dDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmcoIGVsZW0sIFwibmV4dFNpYmxpbmdcIiApO1xuXHR9LFxuXHRwcmV2OiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gc2libGluZyggZWxlbSwgXCJwcmV2aW91c1NpYmxpbmdcIiApO1xuXHR9LFxuXHRuZXh0QWxsOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldkFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwcmV2aW91c1NpYmxpbmdcIiApO1xuXHR9LFxuXHRuZXh0VW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIsIHVudGlsICk7XG5cdH0sXG5cdHByZXZVbnRpbDogZnVuY3Rpb24oIGVsZW0sIGksIHVudGlsICkge1xuXHRcdHJldHVybiBkaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIsIHVudGlsICk7XG5cdH0sXG5cdHNpYmxpbmdzOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gc2libGluZ3MoICggZWxlbS5wYXJlbnROb2RlIHx8IHt9ICkuZmlyc3RDaGlsZCwgZWxlbSApO1xuXHR9LFxuXHRjaGlsZHJlbjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmdzKCBlbGVtLmZpcnN0Q2hpbGQgKTtcblx0fSxcblx0Y29udGVudHM6IGZ1bmN0aW9uKCBlbGVtICkge1xuICAgICAgICBpZiAoIG5vZGVOYW1lKCBlbGVtLCBcImlmcmFtZVwiICkgKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbS5jb250ZW50RG9jdW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdXBwb3J0OiBJRSA5IC0gMTEgb25seSwgaU9TIDcgb25seSwgQW5kcm9pZCBCcm93c2VyIDw9NC4zIG9ubHlcbiAgICAgICAgLy8gVHJlYXQgdGhlIHRlbXBsYXRlIGVsZW1lbnQgYXMgYSByZWd1bGFyIG9uZSBpbiBicm93c2VycyB0aGF0XG4gICAgICAgIC8vIGRvbid0IHN1cHBvcnQgaXQuXG4gICAgICAgIGlmICggbm9kZU5hbWUoIGVsZW0sIFwidGVtcGxhdGVcIiApICkge1xuICAgICAgICAgICAgZWxlbSA9IGVsZW0uY29udGVudCB8fCBlbGVtO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGpRdWVyeS5tZXJnZSggW10sIGVsZW0uY2hpbGROb2RlcyApO1xuXHR9XG59LCBmdW5jdGlvbiggbmFtZSwgZm4gKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHVudGlsLCBzZWxlY3RvciApIHtcblx0XHR2YXIgbWF0Y2hlZCA9IGpRdWVyeS5tYXAoIHRoaXMsIGZuLCB1bnRpbCApO1xuXG5cdFx0aWYgKCBuYW1lLnNsaWNlKCAtNSApICE9PSBcIlVudGlsXCIgKSB7XG5cdFx0XHRzZWxlY3RvciA9IHVudGlsO1xuXHRcdH1cblxuXHRcdGlmICggc2VsZWN0b3IgJiYgdHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0bWF0Y2hlZCA9IGpRdWVyeS5maWx0ZXIoIHNlbGVjdG9yLCBtYXRjaGVkICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLmxlbmd0aCA+IDEgKSB7XG5cblx0XHRcdC8vIFJlbW92ZSBkdXBsaWNhdGVzXG5cdFx0XHRpZiAoICFndWFyYW50ZWVkVW5pcXVlWyBuYW1lIF0gKSB7XG5cdFx0XHRcdGpRdWVyeS51bmlxdWVTb3J0KCBtYXRjaGVkICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldmVyc2Ugb3JkZXIgZm9yIHBhcmVudHMqIGFuZCBwcmV2LWRlcml2YXRpdmVzXG5cdFx0XHRpZiAoIHJwYXJlbnRzcHJldi50ZXN0KCBuYW1lICkgKSB7XG5cdFx0XHRcdG1hdGNoZWQucmV2ZXJzZSgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggbWF0Y2hlZCApO1xuXHR9O1xufSApO1xudmFyIHJub3RodG1sd2hpdGUgPSAoIC9bXlxceDIwXFx0XFxyXFxuXFxmXSsvZyApO1xuXG5cblxuLy8gQ29udmVydCBTdHJpbmctZm9ybWF0dGVkIG9wdGlvbnMgaW50byBPYmplY3QtZm9ybWF0dGVkIG9uZXNcbmZ1bmN0aW9uIGNyZWF0ZU9wdGlvbnMoIG9wdGlvbnMgKSB7XG5cdHZhciBvYmplY3QgPSB7fTtcblx0alF1ZXJ5LmVhY2goIG9wdGlvbnMubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXSwgZnVuY3Rpb24oIF8sIGZsYWcgKSB7XG5cdFx0b2JqZWN0WyBmbGFnIF0gPSB0cnVlO1xuXHR9ICk7XG5cdHJldHVybiBvYmplY3Q7XG59XG5cbi8qXG4gKiBDcmVhdGUgYSBjYWxsYmFjayBsaXN0IHVzaW5nIHRoZSBmb2xsb3dpbmcgcGFyYW1ldGVyczpcbiAqXG4gKlx0b3B0aW9uczogYW4gb3B0aW9uYWwgbGlzdCBvZiBzcGFjZS1zZXBhcmF0ZWQgb3B0aW9ucyB0aGF0IHdpbGwgY2hhbmdlIGhvd1xuICpcdFx0XHR0aGUgY2FsbGJhY2sgbGlzdCBiZWhhdmVzIG9yIGEgbW9yZSB0cmFkaXRpb25hbCBvcHRpb24gb2JqZWN0XG4gKlxuICogQnkgZGVmYXVsdCBhIGNhbGxiYWNrIGxpc3Qgd2lsbCBhY3QgbGlrZSBhbiBldmVudCBjYWxsYmFjayBsaXN0IGFuZCBjYW4gYmVcbiAqIFwiZmlyZWRcIiBtdWx0aXBsZSB0aW1lcy5cbiAqXG4gKiBQb3NzaWJsZSBvcHRpb25zOlxuICpcbiAqXHRvbmNlOlx0XHRcdHdpbGwgZW5zdXJlIHRoZSBjYWxsYmFjayBsaXN0IGNhbiBvbmx5IGJlIGZpcmVkIG9uY2UgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0bWVtb3J5Olx0XHRcdHdpbGwga2VlcCB0cmFjayBvZiBwcmV2aW91cyB2YWx1ZXMgYW5kIHdpbGwgY2FsbCBhbnkgY2FsbGJhY2sgYWRkZWRcbiAqXHRcdFx0XHRcdGFmdGVyIHRoZSBsaXN0IGhhcyBiZWVuIGZpcmVkIHJpZ2h0IGF3YXkgd2l0aCB0aGUgbGF0ZXN0IFwibWVtb3JpemVkXCJcbiAqXHRcdFx0XHRcdHZhbHVlcyAobGlrZSBhIERlZmVycmVkKVxuICpcbiAqXHR1bmlxdWU6XHRcdFx0d2lsbCBlbnN1cmUgYSBjYWxsYmFjayBjYW4gb25seSBiZSBhZGRlZCBvbmNlIChubyBkdXBsaWNhdGUgaW4gdGhlIGxpc3QpXG4gKlxuICpcdHN0b3BPbkZhbHNlOlx0aW50ZXJydXB0IGNhbGxpbmdzIHdoZW4gYSBjYWxsYmFjayByZXR1cm5zIGZhbHNlXG4gKlxuICovXG5qUXVlcnkuQ2FsbGJhY2tzID0gZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cblx0Ly8gQ29udmVydCBvcHRpb25zIGZyb20gU3RyaW5nLWZvcm1hdHRlZCB0byBPYmplY3QtZm9ybWF0dGVkIGlmIG5lZWRlZFxuXHQvLyAod2UgY2hlY2sgaW4gY2FjaGUgZmlyc3QpXG5cdG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9ucyA9PT0gXCJzdHJpbmdcIiA/XG5cdFx0Y3JlYXRlT3B0aW9ucyggb3B0aW9ucyApIDpcblx0XHRqUXVlcnkuZXh0ZW5kKCB7fSwgb3B0aW9ucyApO1xuXG5cdHZhciAvLyBGbGFnIHRvIGtub3cgaWYgbGlzdCBpcyBjdXJyZW50bHkgZmlyaW5nXG5cdFx0ZmlyaW5nLFxuXG5cdFx0Ly8gTGFzdCBmaXJlIHZhbHVlIGZvciBub24tZm9yZ2V0dGFibGUgbGlzdHNcblx0XHRtZW1vcnksXG5cblx0XHQvLyBGbGFnIHRvIGtub3cgaWYgbGlzdCB3YXMgYWxyZWFkeSBmaXJlZFxuXHRcdGZpcmVkLFxuXG5cdFx0Ly8gRmxhZyB0byBwcmV2ZW50IGZpcmluZ1xuXHRcdGxvY2tlZCxcblxuXHRcdC8vIEFjdHVhbCBjYWxsYmFjayBsaXN0XG5cdFx0bGlzdCA9IFtdLFxuXG5cdFx0Ly8gUXVldWUgb2YgZXhlY3V0aW9uIGRhdGEgZm9yIHJlcGVhdGFibGUgbGlzdHNcblx0XHRxdWV1ZSA9IFtdLFxuXG5cdFx0Ly8gSW5kZXggb2YgY3VycmVudGx5IGZpcmluZyBjYWxsYmFjayAobW9kaWZpZWQgYnkgYWRkL3JlbW92ZSBhcyBuZWVkZWQpXG5cdFx0ZmlyaW5nSW5kZXggPSAtMSxcblxuXHRcdC8vIEZpcmUgY2FsbGJhY2tzXG5cdFx0ZmlyZSA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBFbmZvcmNlIHNpbmdsZS1maXJpbmdcblx0XHRcdGxvY2tlZCA9IGxvY2tlZCB8fCBvcHRpb25zLm9uY2U7XG5cblx0XHRcdC8vIEV4ZWN1dGUgY2FsbGJhY2tzIGZvciBhbGwgcGVuZGluZyBleGVjdXRpb25zLFxuXHRcdFx0Ly8gcmVzcGVjdGluZyBmaXJpbmdJbmRleCBvdmVycmlkZXMgYW5kIHJ1bnRpbWUgY2hhbmdlc1xuXHRcdFx0ZmlyZWQgPSBmaXJpbmcgPSB0cnVlO1xuXHRcdFx0Zm9yICggOyBxdWV1ZS5sZW5ndGg7IGZpcmluZ0luZGV4ID0gLTEgKSB7XG5cdFx0XHRcdG1lbW9yeSA9IHF1ZXVlLnNoaWZ0KCk7XG5cdFx0XHRcdHdoaWxlICggKytmaXJpbmdJbmRleCA8IGxpc3QubGVuZ3RoICkge1xuXG5cdFx0XHRcdFx0Ly8gUnVuIGNhbGxiYWNrIGFuZCBjaGVjayBmb3IgZWFybHkgdGVybWluYXRpb25cblx0XHRcdFx0XHRpZiAoIGxpc3RbIGZpcmluZ0luZGV4IF0uYXBwbHkoIG1lbW9yeVsgMCBdLCBtZW1vcnlbIDEgXSApID09PSBmYWxzZSAmJlxuXHRcdFx0XHRcdFx0b3B0aW9ucy5zdG9wT25GYWxzZSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gSnVtcCB0byBlbmQgYW5kIGZvcmdldCB0aGUgZGF0YSBzbyAuYWRkIGRvZXNuJ3QgcmUtZmlyZVxuXHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXggPSBsaXN0Lmxlbmd0aDtcblx0XHRcdFx0XHRcdG1lbW9yeSA9IGZhbHNlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBGb3JnZXQgdGhlIGRhdGEgaWYgd2UncmUgZG9uZSB3aXRoIGl0XG5cdFx0XHRpZiAoICFvcHRpb25zLm1lbW9yeSApIHtcblx0XHRcdFx0bWVtb3J5ID0gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGZpcmluZyA9IGZhbHNlO1xuXG5cdFx0XHQvLyBDbGVhbiB1cCBpZiB3ZSdyZSBkb25lIGZpcmluZyBmb3IgZ29vZFxuXHRcdFx0aWYgKCBsb2NrZWQgKSB7XG5cblx0XHRcdFx0Ly8gS2VlcCBhbiBlbXB0eSBsaXN0IGlmIHdlIGhhdmUgZGF0YSBmb3IgZnV0dXJlIGFkZCBjYWxsc1xuXHRcdFx0XHRpZiAoIG1lbW9yeSApIHtcblx0XHRcdFx0XHRsaXN0ID0gW107XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlLCB0aGlzIG9iamVjdCBpcyBzcGVudFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGxpc3QgPSBcIlwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8vIEFjdHVhbCBDYWxsYmFja3Mgb2JqZWN0XG5cdFx0c2VsZiA9IHtcblxuXHRcdFx0Ly8gQWRkIGEgY2FsbGJhY2sgb3IgYSBjb2xsZWN0aW9uIG9mIGNhbGxiYWNrcyB0byB0aGUgbGlzdFxuXHRcdFx0YWRkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCBsaXN0ICkge1xuXG5cdFx0XHRcdFx0Ly8gSWYgd2UgaGF2ZSBtZW1vcnkgZnJvbSBhIHBhc3QgcnVuLCB3ZSBzaG91bGQgZmlyZSBhZnRlciBhZGRpbmdcblx0XHRcdFx0XHRpZiAoIG1lbW9yeSAmJiAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXggPSBsaXN0Lmxlbmd0aCAtIDE7XG5cdFx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBtZW1vcnkgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQoIGZ1bmN0aW9uIGFkZCggYXJncyApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmdzLCBmdW5jdGlvbiggXywgYXJnICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoICFvcHRpb25zLnVuaXF1ZSB8fCAhc2VsZi5oYXMoIGFyZyApICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0bGlzdC5wdXNoKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIGFyZyAmJiBhcmcubGVuZ3RoICYmIGpRdWVyeS50eXBlKCBhcmcgKSAhPT0gXCJzdHJpbmdcIiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEluc3BlY3QgcmVjdXJzaXZlbHlcblx0XHRcdFx0XHRcdFx0XHRhZGQoIGFyZyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0fSApKCBhcmd1bWVudHMgKTtcblxuXHRcdFx0XHRcdGlmICggbWVtb3J5ICYmICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0XHRmaXJlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gUmVtb3ZlIGEgY2FsbGJhY2sgZnJvbSB0aGUgbGlzdFxuXHRcdFx0cmVtb3ZlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0alF1ZXJ5LmVhY2goIGFyZ3VtZW50cywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHR2YXIgaW5kZXg7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGluZGV4ID0galF1ZXJ5LmluQXJyYXkoIGFyZywgbGlzdCwgaW5kZXggKSApID4gLTEgKSB7XG5cdFx0XHRcdFx0XHRsaXN0LnNwbGljZSggaW5kZXgsIDEgKTtcblxuXHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGZpcmluZyBpbmRleGVzXG5cdFx0XHRcdFx0XHRpZiAoIGluZGV4IDw9IGZpcmluZ0luZGV4ICkge1xuXHRcdFx0XHRcdFx0XHRmaXJpbmdJbmRleC0tO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIENoZWNrIGlmIGEgZ2l2ZW4gY2FsbGJhY2sgaXMgaW4gdGhlIGxpc3QuXG5cdFx0XHQvLyBJZiBubyBhcmd1bWVudCBpcyBnaXZlbiwgcmV0dXJuIHdoZXRoZXIgb3Igbm90IGxpc3QgaGFzIGNhbGxiYWNrcyBhdHRhY2hlZC5cblx0XHRcdGhhczogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRyZXR1cm4gZm4gP1xuXHRcdFx0XHRcdGpRdWVyeS5pbkFycmF5KCBmbiwgbGlzdCApID4gLTEgOlxuXHRcdFx0XHRcdGxpc3QubGVuZ3RoID4gMDtcblx0XHRcdH0sXG5cblx0XHRcdC8vIFJlbW92ZSBhbGwgY2FsbGJhY2tzIGZyb20gdGhlIGxpc3Rcblx0XHRcdGVtcHR5OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCBsaXN0ICkge1xuXHRcdFx0XHRcdGxpc3QgPSBbXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIERpc2FibGUgLmZpcmUgYW5kIC5hZGRcblx0XHRcdC8vIEFib3J0IGFueSBjdXJyZW50L3BlbmRpbmcgZXhlY3V0aW9uc1xuXHRcdFx0Ly8gQ2xlYXIgYWxsIGNhbGxiYWNrcyBhbmQgdmFsdWVzXG5cdFx0XHRkaXNhYmxlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0bG9ja2VkID0gcXVldWUgPSBbXTtcblx0XHRcdFx0bGlzdCA9IG1lbW9yeSA9IFwiXCI7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblx0XHRcdGRpc2FibGVkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICFsaXN0O1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gRGlzYWJsZSAuZmlyZVxuXHRcdFx0Ly8gQWxzbyBkaXNhYmxlIC5hZGQgdW5sZXNzIHdlIGhhdmUgbWVtb3J5IChzaW5jZSBpdCB3b3VsZCBoYXZlIG5vIGVmZmVjdClcblx0XHRcdC8vIEFib3J0IGFueSBwZW5kaW5nIGV4ZWN1dGlvbnNcblx0XHRcdGxvY2s6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRsb2NrZWQgPSBxdWV1ZSA9IFtdO1xuXHRcdFx0XHRpZiAoICFtZW1vcnkgJiYgIWZpcmluZyApIHtcblx0XHRcdFx0XHRsaXN0ID0gbWVtb3J5ID0gXCJcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHRsb2NrZWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gISFsb2NrZWQ7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDYWxsIGFsbCBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gY29udGV4dCBhbmQgYXJndW1lbnRzXG5cdFx0XHRmaXJlV2l0aDogZnVuY3Rpb24oIGNvbnRleHQsIGFyZ3MgKSB7XG5cdFx0XHRcdGlmICggIWxvY2tlZCApIHtcblx0XHRcdFx0XHRhcmdzID0gYXJncyB8fCBbXTtcblx0XHRcdFx0XHRhcmdzID0gWyBjb250ZXh0LCBhcmdzLnNsaWNlID8gYXJncy5zbGljZSgpIDogYXJncyBdO1xuXHRcdFx0XHRcdHF1ZXVlLnB1c2goIGFyZ3MgKTtcblx0XHRcdFx0XHRpZiAoICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0XHRmaXJlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhbGwgdGhlIGNhbGxiYWNrcyB3aXRoIHRoZSBnaXZlbiBhcmd1bWVudHNcblx0XHRcdGZpcmU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRzZWxmLmZpcmVXaXRoKCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBUbyBrbm93IGlmIHRoZSBjYWxsYmFja3MgaGF2ZSBhbHJlYWR5IGJlZW4gY2FsbGVkIGF0IGxlYXN0IG9uY2Vcblx0XHRcdGZpcmVkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICEhZmlyZWQ7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRyZXR1cm4gc2VsZjtcbn07XG5cblxuZnVuY3Rpb24gSWRlbnRpdHkoIHYgKSB7XG5cdHJldHVybiB2O1xufVxuZnVuY3Rpb24gVGhyb3dlciggZXggKSB7XG5cdHRocm93IGV4O1xufVxuXG5mdW5jdGlvbiBhZG9wdFZhbHVlKCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0LCBub1ZhbHVlICkge1xuXHR2YXIgbWV0aG9kO1xuXG5cdHRyeSB7XG5cblx0XHQvLyBDaGVjayBmb3IgcHJvbWlzZSBhc3BlY3QgZmlyc3QgdG8gcHJpdmlsZWdlIHN5bmNocm9ub3VzIGJlaGF2aW9yXG5cdFx0aWYgKCB2YWx1ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggKCBtZXRob2QgPSB2YWx1ZS5wcm9taXNlICkgKSApIHtcblx0XHRcdG1ldGhvZC5jYWxsKCB2YWx1ZSApLmRvbmUoIHJlc29sdmUgKS5mYWlsKCByZWplY3QgKTtcblxuXHRcdC8vIE90aGVyIHRoZW5hYmxlc1xuXHRcdH0gZWxzZSBpZiAoIHZhbHVlICYmIGpRdWVyeS5pc0Z1bmN0aW9uKCAoIG1ldGhvZCA9IHZhbHVlLnRoZW4gKSApICkge1xuXHRcdFx0bWV0aG9kLmNhbGwoIHZhbHVlLCByZXNvbHZlLCByZWplY3QgKTtcblxuXHRcdC8vIE90aGVyIG5vbi10aGVuYWJsZXNcblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBDb250cm9sIGByZXNvbHZlYCBhcmd1bWVudHMgYnkgbGV0dGluZyBBcnJheSNzbGljZSBjYXN0IGJvb2xlYW4gYG5vVmFsdWVgIHRvIGludGVnZXI6XG5cdFx0XHQvLyAqIGZhbHNlOiBbIHZhbHVlIF0uc2xpY2UoIDAgKSA9PiByZXNvbHZlKCB2YWx1ZSApXG5cdFx0XHQvLyAqIHRydWU6IFsgdmFsdWUgXS5zbGljZSggMSApID0+IHJlc29sdmUoKVxuXHRcdFx0cmVzb2x2ZS5hcHBseSggdW5kZWZpbmVkLCBbIHZhbHVlIF0uc2xpY2UoIG5vVmFsdWUgKSApO1xuXHRcdH1cblxuXHQvLyBGb3IgUHJvbWlzZXMvQSssIGNvbnZlcnQgZXhjZXB0aW9ucyBpbnRvIHJlamVjdGlvbnNcblx0Ly8gU2luY2UgalF1ZXJ5LndoZW4gZG9lc24ndCB1bndyYXAgdGhlbmFibGVzLCB3ZSBjYW4gc2tpcCB0aGUgZXh0cmEgY2hlY2tzIGFwcGVhcmluZyBpblxuXHQvLyBEZWZlcnJlZCN0aGVuIHRvIGNvbmRpdGlvbmFsbHkgc3VwcHJlc3MgcmVqZWN0aW9uLlxuXHR9IGNhdGNoICggdmFsdWUgKSB7XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCBvbmx5XG5cdFx0Ly8gU3RyaWN0IG1vZGUgZnVuY3Rpb25zIGludm9rZWQgd2l0aG91dCAuY2FsbC8uYXBwbHkgZ2V0IGdsb2JhbC1vYmplY3QgY29udGV4dFxuXHRcdHJlamVjdC5hcHBseSggdW5kZWZpbmVkLCBbIHZhbHVlIF0gKTtcblx0fVxufVxuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0RGVmZXJyZWQ6IGZ1bmN0aW9uKCBmdW5jICkge1xuXHRcdHZhciB0dXBsZXMgPSBbXG5cblx0XHRcdFx0Ly8gYWN0aW9uLCBhZGQgbGlzdGVuZXIsIGNhbGxiYWNrcyxcblx0XHRcdFx0Ly8gLi4uIC50aGVuIGhhbmRsZXJzLCBhcmd1bWVudCBpbmRleCwgW2ZpbmFsIHN0YXRlXVxuXHRcdFx0XHRbIFwibm90aWZ5XCIsIFwicHJvZ3Jlc3NcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJtZW1vcnlcIiApLFxuXHRcdFx0XHRcdGpRdWVyeS5DYWxsYmFja3MoIFwibWVtb3J5XCIgKSwgMiBdLFxuXHRcdFx0XHRbIFwicmVzb2x2ZVwiLCBcImRvbmVcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cdFx0XHRcdFx0alF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksIDAsIFwicmVzb2x2ZWRcIiBdLFxuXHRcdFx0XHRbIFwicmVqZWN0XCIsIFwiZmFpbFwiLCBqUXVlcnkuQ2FsbGJhY2tzKCBcIm9uY2UgbWVtb3J5XCIgKSxcblx0XHRcdFx0XHRqUXVlcnkuQ2FsbGJhY2tzKCBcIm9uY2UgbWVtb3J5XCIgKSwgMSwgXCJyZWplY3RlZFwiIF1cblx0XHRcdF0sXG5cdFx0XHRzdGF0ZSA9IFwicGVuZGluZ1wiLFxuXHRcdFx0cHJvbWlzZSA9IHtcblx0XHRcdFx0c3RhdGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiBzdGF0ZTtcblx0XHRcdFx0fSxcblx0XHRcdFx0YWx3YXlzOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRkZWZlcnJlZC5kb25lKCBhcmd1bWVudHMgKS5mYWlsKCBhcmd1bWVudHMgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblx0XHRcdFx0XCJjYXRjaFwiOiBmdW5jdGlvbiggZm4gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHByb21pc2UudGhlbiggbnVsbCwgZm4gKTtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBLZWVwIHBpcGUgZm9yIGJhY2stY29tcGF0XG5cdFx0XHRcdHBpcGU6IGZ1bmN0aW9uKCAvKiBmbkRvbmUsIGZuRmFpbCwgZm5Qcm9ncmVzcyAqLyApIHtcblx0XHRcdFx0XHR2YXIgZm5zID0gYXJndW1lbnRzO1xuXG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZCggZnVuY3Rpb24oIG5ld0RlZmVyICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5LmVhY2goIHR1cGxlcywgZnVuY3Rpb24oIGksIHR1cGxlICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIE1hcCB0dXBsZXMgKHByb2dyZXNzLCBkb25lLCBmYWlsKSB0byBhcmd1bWVudHMgKGRvbmUsIGZhaWwsIHByb2dyZXNzKVxuXHRcdFx0XHRcdFx0XHR2YXIgZm4gPSBqUXVlcnkuaXNGdW5jdGlvbiggZm5zWyB0dXBsZVsgNCBdIF0gKSAmJiBmbnNbIHR1cGxlWyA0IF0gXTtcblxuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZC5wcm9ncmVzcyhmdW5jdGlvbigpIHsgYmluZCB0byBuZXdEZWZlciBvciBuZXdEZWZlci5ub3RpZnkgfSlcblx0XHRcdFx0XHRcdFx0Ly8gZGVmZXJyZWQuZG9uZShmdW5jdGlvbigpIHsgYmluZCB0byBuZXdEZWZlciBvciBuZXdEZWZlci5yZXNvbHZlIH0pXG5cdFx0XHRcdFx0XHRcdC8vIGRlZmVycmVkLmZhaWwoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIucmVqZWN0IH0pXG5cdFx0XHRcdFx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMSBdIF0oIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciByZXR1cm5lZCA9IGZuICYmIGZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIHJldHVybmVkICYmIGpRdWVyeS5pc0Z1bmN0aW9uKCByZXR1cm5lZC5wcm9taXNlICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZC5wcm9taXNlKClcblx0XHRcdFx0XHRcdFx0XHRcdFx0LnByb2dyZXNzKCBuZXdEZWZlci5ub3RpZnkgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZG9uZSggbmV3RGVmZXIucmVzb2x2ZSApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5mYWlsKCBuZXdEZWZlci5yZWplY3QgKTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXJbIHR1cGxlWyAwIF0gKyBcIldpdGhcIiBdKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRmbiA/IFsgcmV0dXJuZWQgXSA6IGFyZ3VtZW50c1xuXHRcdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdGZucyA9IG51bGw7XG5cdFx0XHRcdFx0fSApLnByb21pc2UoKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0dGhlbjogZnVuY3Rpb24oIG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBvblByb2dyZXNzICkge1xuXHRcdFx0XHRcdHZhciBtYXhEZXB0aCA9IDA7XG5cdFx0XHRcdFx0ZnVuY3Rpb24gcmVzb2x2ZSggZGVwdGgsIGRlZmVycmVkLCBoYW5kbGVyLCBzcGVjaWFsICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHR2YXIgdGhhdCA9IHRoaXMsXG5cdFx0XHRcdFx0XHRcdFx0YXJncyA9IGFyZ3VtZW50cyxcblx0XHRcdFx0XHRcdFx0XHRtaWdodFRocm93ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgcmV0dXJuZWQsIHRoZW47XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy4zXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC01OVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSWdub3JlIGRvdWJsZS1yZXNvbHV0aW9uIGF0dGVtcHRzXG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGRlcHRoIDwgbWF4RGVwdGggKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQgPSBoYW5kbGVyLmFwcGx5KCB0aGF0LCBhcmdzICk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjFcblx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTQ4XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHJldHVybmVkID09PSBkZWZlcnJlZC5wcm9taXNlKCkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoIFwiVGhlbmFibGUgc2VsZi1yZXNvbHV0aW9uXCIgKTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogUHJvbWlzZXMvQSsgc2VjdGlvbnMgMi4zLjMuMSwgMy41XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC01NFxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNzVcblx0XHRcdFx0XHRcdFx0XHRcdC8vIFJldHJpZXZlIGB0aGVuYCBvbmx5IG9uY2Vcblx0XHRcdFx0XHRcdFx0XHRcdHRoZW4gPSByZXR1cm5lZCAmJlxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjRcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNjRcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gT25seSBjaGVjayBvYmplY3RzIGFuZCBmdW5jdGlvbnMgZm9yIHRoZW5hYmlsaXR5XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCggdHlwZW9mIHJldHVybmVkID09PSBcIm9iamVjdFwiIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dHlwZW9mIHJldHVybmVkID09PSBcImZ1bmN0aW9uXCIgKSAmJlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZC50aGVuO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBIYW5kbGUgYSByZXR1cm5lZCB0aGVuYWJsZVxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdGhlbiApICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFNwZWNpYWwgcHJvY2Vzc29ycyAobm90aWZ5KSBqdXN0IHdhaXQgZm9yIHJlc29sdXRpb25cblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBzcGVjaWFsICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHRoZW4uY2FsbChcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmVzb2x2ZSggbWF4RGVwdGgsIGRlZmVycmVkLCBJZGVudGl0eSwgc3BlY2lhbCApLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmVzb2x2ZSggbWF4RGVwdGgsIGRlZmVycmVkLCBUaHJvd2VyLCBzcGVjaWFsIClcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQpO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE5vcm1hbCBwcm9jZXNzb3JzIChyZXNvbHZlKSBhbHNvIGhvb2sgaW50byBwcm9ncmVzc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gLi4uYW5kIGRpc3JlZ2FyZCBvbGRlciByZXNvbHV0aW9uIHZhbHVlc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1heERlcHRoKys7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGVuLmNhbGwoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgVGhyb3dlciwgc3BlY2lhbCApLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmVzb2x2ZSggbWF4RGVwdGgsIGRlZmVycmVkLCBJZGVudGl0eSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBIYW5kbGUgYWxsIG90aGVyIHJldHVybmVkIHZhbHVlc1xuXHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IHN1YnN0aXR1dGUgaGFuZGxlcnMgcGFzcyBvbiBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGFuZCBtdWx0aXBsZSB2YWx1ZXMgKG5vbi1zcGVjIGJlaGF2aW9yKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGhhbmRsZXIgIT09IElkZW50aXR5ICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHRoYXQgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0YXJncyA9IFsgcmV0dXJuZWQgXTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFByb2Nlc3MgdGhlIHZhbHVlKHMpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIERlZmF1bHQgcHJvY2VzcyBpcyByZXNvbHZlXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCggc3BlY2lhbCB8fCBkZWZlcnJlZC5yZXNvbHZlV2l0aCApKCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fSxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgbm9ybWFsIHByb2Nlc3NvcnMgKHJlc29sdmUpIGNhdGNoIGFuZCByZWplY3QgZXhjZXB0aW9uc1xuXHRcdFx0XHRcdFx0XHRcdHByb2Nlc3MgPSBzcGVjaWFsID9cblx0XHRcdFx0XHRcdFx0XHRcdG1pZ2h0VGhyb3cgOlxuXHRcdFx0XHRcdFx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0bWlnaHRUaHJvdygpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LkRlZmVycmVkLmV4Y2VwdGlvbkhvb2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRqUXVlcnkuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayggZSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cHJvY2Vzcy5zdGFja1RyYWNlICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogUHJvbWlzZXMvQSsgc2VjdGlvbiAyLjMuMy4zLjQuMVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTYxXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gSWdub3JlIHBvc3QtcmVzb2x1dGlvbiBleGNlcHRpb25zXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCArIDEgPj0gbWF4RGVwdGggKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgc3Vic3RpdHV0ZSBoYW5kbGVycyBwYXNzIG9uIGNvbnRleHRcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGFuZCBtdWx0aXBsZSB2YWx1ZXMgKG5vbi1zcGVjIGJlaGF2aW9yKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBoYW5kbGVyICE9PSBUaHJvd2VyICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGF0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRhcmdzID0gWyBlIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRlZmVycmVkLnJlamVjdFdpdGgoIHRoYXQsIGFyZ3MgKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogUHJvbWlzZXMvQSsgc2VjdGlvbiAyLjMuMy4zLjFcblx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTdcblx0XHRcdFx0XHRcdFx0Ly8gUmUtcmVzb2x2ZSBwcm9taXNlcyBpbW1lZGlhdGVseSB0byBkb2RnZSBmYWxzZSByZWplY3Rpb24gZnJvbVxuXHRcdFx0XHRcdFx0XHQvLyBzdWJzZXF1ZW50IGVycm9yc1xuXHRcdFx0XHRcdFx0XHRpZiAoIGRlcHRoICkge1xuXHRcdFx0XHRcdFx0XHRcdHByb2Nlc3MoKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIENhbGwgYW4gb3B0aW9uYWwgaG9vayB0byByZWNvcmQgdGhlIHN0YWNrLCBpbiBjYXNlIG9mIGV4Y2VwdGlvblxuXHRcdFx0XHRcdFx0XHRcdC8vIHNpbmNlIGl0J3Mgb3RoZXJ3aXNlIGxvc3Qgd2hlbiBleGVjdXRpb24gZ29lcyBhc3luY1xuXHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LkRlZmVycmVkLmdldFN0YWNrSG9vayApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHByb2Nlc3Muc3RhY2tUcmFjZSA9IGpRdWVyeS5EZWZlcnJlZC5nZXRTdGFja0hvb2soKTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0d2luZG93LnNldFRpbWVvdXQoIHByb2Nlc3MgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4galF1ZXJ5LkRlZmVycmVkKCBmdW5jdGlvbiggbmV3RGVmZXIgKSB7XG5cblx0XHRcdFx0XHRcdC8vIHByb2dyZXNzX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMCBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uUHJvZ3Jlc3MgKSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRvblByb2dyZXNzIDpcblx0XHRcdFx0XHRcdFx0XHRcdElkZW50aXR5LFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLm5vdGlmeVdpdGhcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0Ly8gZnVsZmlsbGVkX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMSBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uRnVsZmlsbGVkICkgP1xuXHRcdFx0XHRcdFx0XHRcdFx0b25GdWxmaWxsZWQgOlxuXHRcdFx0XHRcdFx0XHRcdFx0SWRlbnRpdHlcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0Ly8gcmVqZWN0ZWRfaGFuZGxlcnMuYWRkKCAuLi4gKVxuXHRcdFx0XHRcdFx0dHVwbGVzWyAyIF1bIDMgXS5hZGQoXG5cdFx0XHRcdFx0XHRcdHJlc29sdmUoXG5cdFx0XHRcdFx0XHRcdFx0MCxcblx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlcixcblx0XHRcdFx0XHRcdFx0XHRqUXVlcnkuaXNGdW5jdGlvbiggb25SZWplY3RlZCApID9cblx0XHRcdFx0XHRcdFx0XHRcdG9uUmVqZWN0ZWQgOlxuXHRcdFx0XHRcdFx0XHRcdFx0VGhyb3dlclxuXHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0gKS5wcm9taXNlKCk7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gR2V0IGEgcHJvbWlzZSBmb3IgdGhpcyBkZWZlcnJlZFxuXHRcdFx0XHQvLyBJZiBvYmogaXMgcHJvdmlkZWQsIHRoZSBwcm9taXNlIGFzcGVjdCBpcyBhZGRlZCB0byB0aGUgb2JqZWN0XG5cdFx0XHRcdHByb21pc2U6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG9iaiAhPSBudWxsID8galF1ZXJ5LmV4dGVuZCggb2JqLCBwcm9taXNlICkgOiBwcm9taXNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVmZXJyZWQgPSB7fTtcblxuXHRcdC8vIEFkZCBsaXN0LXNwZWNpZmljIG1ldGhvZHNcblx0XHRqUXVlcnkuZWFjaCggdHVwbGVzLCBmdW5jdGlvbiggaSwgdHVwbGUgKSB7XG5cdFx0XHR2YXIgbGlzdCA9IHR1cGxlWyAyIF0sXG5cdFx0XHRcdHN0YXRlU3RyaW5nID0gdHVwbGVbIDUgXTtcblxuXHRcdFx0Ly8gcHJvbWlzZS5wcm9ncmVzcyA9IGxpc3QuYWRkXG5cdFx0XHQvLyBwcm9taXNlLmRvbmUgPSBsaXN0LmFkZFxuXHRcdFx0Ly8gcHJvbWlzZS5mYWlsID0gbGlzdC5hZGRcblx0XHRcdHByb21pc2VbIHR1cGxlWyAxIF0gXSA9IGxpc3QuYWRkO1xuXG5cdFx0XHQvLyBIYW5kbGUgc3RhdGVcblx0XHRcdGlmICggc3RhdGVTdHJpbmcgKSB7XG5cdFx0XHRcdGxpc3QuYWRkKFxuXHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0XHQvLyBzdGF0ZSA9IFwicmVzb2x2ZWRcIiAoaS5lLiwgZnVsZmlsbGVkKVxuXHRcdFx0XHRcdFx0Ly8gc3RhdGUgPSBcInJlamVjdGVkXCJcblx0XHRcdFx0XHRcdHN0YXRlID0gc3RhdGVTdHJpbmc7XG5cdFx0XHRcdFx0fSxcblxuXHRcdFx0XHRcdC8vIHJlamVjdGVkX2NhbGxiYWNrcy5kaXNhYmxlXG5cdFx0XHRcdFx0Ly8gZnVsZmlsbGVkX2NhbGxiYWNrcy5kaXNhYmxlXG5cdFx0XHRcdFx0dHVwbGVzWyAzIC0gaSBdWyAyIF0uZGlzYWJsZSxcblxuXHRcdFx0XHRcdC8vIHByb2dyZXNzX2NhbGxiYWNrcy5sb2NrXG5cdFx0XHRcdFx0dHVwbGVzWyAwIF1bIDIgXS5sb2NrXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIHByb2dyZXNzX2hhbmRsZXJzLmZpcmVcblx0XHRcdC8vIGZ1bGZpbGxlZF9oYW5kbGVycy5maXJlXG5cdFx0XHQvLyByZWplY3RlZF9oYW5kbGVycy5maXJlXG5cdFx0XHRsaXN0LmFkZCggdHVwbGVbIDMgXS5maXJlICk7XG5cblx0XHRcdC8vIGRlZmVycmVkLm5vdGlmeSA9IGZ1bmN0aW9uKCkgeyBkZWZlcnJlZC5ub3RpZnlXaXRoKC4uLikgfVxuXHRcdFx0Ly8gZGVmZXJyZWQucmVzb2x2ZSA9IGZ1bmN0aW9uKCkgeyBkZWZlcnJlZC5yZXNvbHZlV2l0aCguLi4pIH1cblx0XHRcdC8vIGRlZmVycmVkLnJlamVjdCA9IGZ1bmN0aW9uKCkgeyBkZWZlcnJlZC5yZWplY3RXaXRoKC4uLikgfVxuXHRcdFx0ZGVmZXJyZWRbIHR1cGxlWyAwIF0gXSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0oIHRoaXMgPT09IGRlZmVycmVkID8gdW5kZWZpbmVkIDogdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fTtcblxuXHRcdFx0Ly8gZGVmZXJyZWQubm90aWZ5V2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdC8vIGRlZmVycmVkLnJlc29sdmVXaXRoID0gbGlzdC5maXJlV2l0aFxuXHRcdFx0Ly8gZGVmZXJyZWQucmVqZWN0V2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMCBdICsgXCJXaXRoXCIgXSA9IGxpc3QuZmlyZVdpdGg7XG5cdFx0fSApO1xuXG5cdFx0Ly8gTWFrZSB0aGUgZGVmZXJyZWQgYSBwcm9taXNlXG5cdFx0cHJvbWlzZS5wcm9taXNlKCBkZWZlcnJlZCApO1xuXG5cdFx0Ly8gQ2FsbCBnaXZlbiBmdW5jIGlmIGFueVxuXHRcdGlmICggZnVuYyApIHtcblx0XHRcdGZ1bmMuY2FsbCggZGVmZXJyZWQsIGRlZmVycmVkICk7XG5cdFx0fVxuXG5cdFx0Ly8gQWxsIGRvbmUhXG5cdFx0cmV0dXJuIGRlZmVycmVkO1xuXHR9LFxuXG5cdC8vIERlZmVycmVkIGhlbHBlclxuXHR3aGVuOiBmdW5jdGlvbiggc2luZ2xlVmFsdWUgKSB7XG5cdFx0dmFyXG5cblx0XHRcdC8vIGNvdW50IG9mIHVuY29tcGxldGVkIHN1Ym9yZGluYXRlc1xuXHRcdFx0cmVtYWluaW5nID0gYXJndW1lbnRzLmxlbmd0aCxcblxuXHRcdFx0Ly8gY291bnQgb2YgdW5wcm9jZXNzZWQgYXJndW1lbnRzXG5cdFx0XHRpID0gcmVtYWluaW5nLFxuXG5cdFx0XHQvLyBzdWJvcmRpbmF0ZSBmdWxmaWxsbWVudCBkYXRhXG5cdFx0XHRyZXNvbHZlQ29udGV4dHMgPSBBcnJheSggaSApLFxuXHRcdFx0cmVzb2x2ZVZhbHVlcyA9IHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApLFxuXG5cdFx0XHQvLyB0aGUgbWFzdGVyIERlZmVycmVkXG5cdFx0XHRtYXN0ZXIgPSBqUXVlcnkuRGVmZXJyZWQoKSxcblxuXHRcdFx0Ly8gc3Vib3JkaW5hdGUgY2FsbGJhY2sgZmFjdG9yeVxuXHRcdFx0dXBkYXRlRnVuYyA9IGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRcdHJlc29sdmVDb250ZXh0c1sgaSBdID0gdGhpcztcblx0XHRcdFx0XHRyZXNvbHZlVmFsdWVzWyBpIF0gPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApIDogdmFsdWU7XG5cdFx0XHRcdFx0aWYgKCAhKCAtLXJlbWFpbmluZyApICkge1xuXHRcdFx0XHRcdFx0bWFzdGVyLnJlc29sdmVXaXRoKCByZXNvbHZlQ29udGV4dHMsIHJlc29sdmVWYWx1ZXMgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHR9O1xuXG5cdFx0Ly8gU2luZ2xlLSBhbmQgZW1wdHkgYXJndW1lbnRzIGFyZSBhZG9wdGVkIGxpa2UgUHJvbWlzZS5yZXNvbHZlXG5cdFx0aWYgKCByZW1haW5pbmcgPD0gMSApIHtcblx0XHRcdGFkb3B0VmFsdWUoIHNpbmdsZVZhbHVlLCBtYXN0ZXIuZG9uZSggdXBkYXRlRnVuYyggaSApICkucmVzb2x2ZSwgbWFzdGVyLnJlamVjdCxcblx0XHRcdFx0IXJlbWFpbmluZyApO1xuXG5cdFx0XHQvLyBVc2UgLnRoZW4oKSB0byB1bndyYXAgc2Vjb25kYXJ5IHRoZW5hYmxlcyAoY2YuIGdoLTMwMDApXG5cdFx0XHRpZiAoIG1hc3Rlci5zdGF0ZSgpID09PSBcInBlbmRpbmdcIiB8fFxuXHRcdFx0XHRqUXVlcnkuaXNGdW5jdGlvbiggcmVzb2x2ZVZhbHVlc1sgaSBdICYmIHJlc29sdmVWYWx1ZXNbIGkgXS50aGVuICkgKSB7XG5cblx0XHRcdFx0cmV0dXJuIG1hc3Rlci50aGVuKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gTXVsdGlwbGUgYXJndW1lbnRzIGFyZSBhZ2dyZWdhdGVkIGxpa2UgUHJvbWlzZS5hbGwgYXJyYXkgZWxlbWVudHNcblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdGFkb3B0VmFsdWUoIHJlc29sdmVWYWx1ZXNbIGkgXSwgdXBkYXRlRnVuYyggaSApLCBtYXN0ZXIucmVqZWN0ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG1hc3Rlci5wcm9taXNlKCk7XG5cdH1cbn0gKTtcblxuXG4vLyBUaGVzZSB1c3VhbGx5IGluZGljYXRlIGEgcHJvZ3JhbW1lciBtaXN0YWtlIGR1cmluZyBkZXZlbG9wbWVudCxcbi8vIHdhcm4gYWJvdXQgdGhlbSBBU0FQIHJhdGhlciB0aGFuIHN3YWxsb3dpbmcgdGhlbSBieSBkZWZhdWx0LlxudmFyIHJlcnJvck5hbWVzID0gL14oRXZhbHxJbnRlcm5hbHxSYW5nZXxSZWZlcmVuY2V8U3ludGF4fFR5cGV8VVJJKUVycm9yJC87XG5cbmpRdWVyeS5EZWZlcnJlZC5leGNlcHRpb25Ib29rID0gZnVuY3Rpb24oIGVycm9yLCBzdGFjayApIHtcblxuXHQvLyBTdXBwb3J0OiBJRSA4IC0gOSBvbmx5XG5cdC8vIENvbnNvbGUgZXhpc3RzIHdoZW4gZGV2IHRvb2xzIGFyZSBvcGVuLCB3aGljaCBjYW4gaGFwcGVuIGF0IGFueSB0aW1lXG5cdGlmICggd2luZG93LmNvbnNvbGUgJiYgd2luZG93LmNvbnNvbGUud2FybiAmJiBlcnJvciAmJiByZXJyb3JOYW1lcy50ZXN0KCBlcnJvci5uYW1lICkgKSB7XG5cdFx0d2luZG93LmNvbnNvbGUud2FybiggXCJqUXVlcnkuRGVmZXJyZWQgZXhjZXB0aW9uOiBcIiArIGVycm9yLm1lc3NhZ2UsIGVycm9yLnN0YWNrLCBzdGFjayApO1xuXHR9XG59O1xuXG5cblxuXG5qUXVlcnkucmVhZHlFeGNlcHRpb24gPSBmdW5jdGlvbiggZXJyb3IgKSB7XG5cdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHR0aHJvdyBlcnJvcjtcblx0fSApO1xufTtcblxuXG5cblxuLy8gVGhlIGRlZmVycmVkIHVzZWQgb24gRE9NIHJlYWR5XG52YXIgcmVhZHlMaXN0ID0galF1ZXJ5LkRlZmVycmVkKCk7XG5cbmpRdWVyeS5mbi5yZWFkeSA9IGZ1bmN0aW9uKCBmbiApIHtcblxuXHRyZWFkeUxpc3Rcblx0XHQudGhlbiggZm4gKVxuXG5cdFx0Ly8gV3JhcCBqUXVlcnkucmVhZHlFeGNlcHRpb24gaW4gYSBmdW5jdGlvbiBzbyB0aGF0IHRoZSBsb29rdXBcblx0XHQvLyBoYXBwZW5zIGF0IHRoZSB0aW1lIG9mIGVycm9yIGhhbmRsaW5nIGluc3RlYWQgb2YgY2FsbGJhY2tcblx0XHQvLyByZWdpc3RyYXRpb24uXG5cdFx0LmNhdGNoKCBmdW5jdGlvbiggZXJyb3IgKSB7XG5cdFx0XHRqUXVlcnkucmVhZHlFeGNlcHRpb24oIGVycm9yICk7XG5cdFx0fSApO1xuXG5cdHJldHVybiB0aGlzO1xufTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIElzIHRoZSBET00gcmVhZHkgdG8gYmUgdXNlZD8gU2V0IHRvIHRydWUgb25jZSBpdCBvY2N1cnMuXG5cdGlzUmVhZHk6IGZhbHNlLFxuXG5cdC8vIEEgY291bnRlciB0byB0cmFjayBob3cgbWFueSBpdGVtcyB0byB3YWl0IGZvciBiZWZvcmVcblx0Ly8gdGhlIHJlYWR5IGV2ZW50IGZpcmVzLiBTZWUgIzY3ODFcblx0cmVhZHlXYWl0OiAxLFxuXG5cdC8vIEhhbmRsZSB3aGVuIHRoZSBET00gaXMgcmVhZHlcblx0cmVhZHk6IGZ1bmN0aW9uKCB3YWl0ICkge1xuXG5cdFx0Ly8gQWJvcnQgaWYgdGhlcmUgYXJlIHBlbmRpbmcgaG9sZHMgb3Igd2UncmUgYWxyZWFkeSByZWFkeVxuXHRcdGlmICggd2FpdCA9PT0gdHJ1ZSA/IC0talF1ZXJ5LnJlYWR5V2FpdCA6IGpRdWVyeS5pc1JlYWR5ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFJlbWVtYmVyIHRoYXQgdGhlIERPTSBpcyByZWFkeVxuXHRcdGpRdWVyeS5pc1JlYWR5ID0gdHJ1ZTtcblxuXHRcdC8vIElmIGEgbm9ybWFsIERPTSBSZWFkeSBldmVudCBmaXJlZCwgZGVjcmVtZW50LCBhbmQgd2FpdCBpZiBuZWVkIGJlXG5cdFx0aWYgKCB3YWl0ICE9PSB0cnVlICYmIC0talF1ZXJ5LnJlYWR5V2FpdCA+IDAgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlcmUgYXJlIGZ1bmN0aW9ucyBib3VuZCwgdG8gZXhlY3V0ZVxuXHRcdHJlYWR5TGlzdC5yZXNvbHZlV2l0aCggZG9jdW1lbnQsIFsgalF1ZXJ5IF0gKTtcblx0fVxufSApO1xuXG5qUXVlcnkucmVhZHkudGhlbiA9IHJlYWR5TGlzdC50aGVuO1xuXG4vLyBUaGUgcmVhZHkgZXZlbnQgaGFuZGxlciBhbmQgc2VsZiBjbGVhbnVwIG1ldGhvZFxuZnVuY3Rpb24gY29tcGxldGVkKCkge1xuXHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCBcIkRPTUNvbnRlbnRMb2FkZWRcIiwgY29tcGxldGVkICk7XG5cdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkICk7XG5cdGpRdWVyeS5yZWFkeSgpO1xufVxuXG4vLyBDYXRjaCBjYXNlcyB3aGVyZSAkKGRvY3VtZW50KS5yZWFkeSgpIGlzIGNhbGxlZFxuLy8gYWZ0ZXIgdGhlIGJyb3dzZXIgZXZlbnQgaGFzIGFscmVhZHkgb2NjdXJyZWQuXG4vLyBTdXBwb3J0OiBJRSA8PTkgLSAxMCBvbmx5XG4vLyBPbGRlciBJRSBzb21ldGltZXMgc2lnbmFscyBcImludGVyYWN0aXZlXCIgdG9vIHNvb25cbmlmICggZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gXCJjb21wbGV0ZVwiIHx8XG5cdCggZG9jdW1lbnQucmVhZHlTdGF0ZSAhPT0gXCJsb2FkaW5nXCIgJiYgIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5kb1Njcm9sbCApICkge1xuXG5cdC8vIEhhbmRsZSBpdCBhc3luY2hyb25vdXNseSB0byBhbGxvdyBzY3JpcHRzIHRoZSBvcHBvcnR1bml0eSB0byBkZWxheSByZWFkeVxuXHR3aW5kb3cuc2V0VGltZW91dCggalF1ZXJ5LnJlYWR5ICk7XG5cbn0gZWxzZSB7XG5cblx0Ly8gVXNlIHRoZSBoYW5keSBldmVudCBjYWxsYmFja1xuXHRkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCBcIkRPTUNvbnRlbnRMb2FkZWRcIiwgY29tcGxldGVkICk7XG5cblx0Ly8gQSBmYWxsYmFjayB0byB3aW5kb3cub25sb2FkLCB0aGF0IHdpbGwgYWx3YXlzIHdvcmtcblx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIFwibG9hZFwiLCBjb21wbGV0ZWQgKTtcbn1cblxuXG5cblxuLy8gTXVsdGlmdW5jdGlvbmFsIG1ldGhvZCB0byBnZXQgYW5kIHNldCB2YWx1ZXMgb2YgYSBjb2xsZWN0aW9uXG4vLyBUaGUgdmFsdWUvcyBjYW4gb3B0aW9uYWxseSBiZSBleGVjdXRlZCBpZiBpdCdzIGEgZnVuY3Rpb25cbnZhciBhY2Nlc3MgPSBmdW5jdGlvbiggZWxlbXMsIGZuLCBrZXksIHZhbHVlLCBjaGFpbmFibGUsIGVtcHR5R2V0LCByYXcgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBlbGVtcy5sZW5ndGgsXG5cdFx0YnVsayA9IGtleSA9PSBudWxsO1xuXG5cdC8vIFNldHMgbWFueSB2YWx1ZXNcblx0aWYgKCBqUXVlcnkudHlwZSgga2V5ICkgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0Y2hhaW5hYmxlID0gdHJ1ZTtcblx0XHRmb3IgKCBpIGluIGtleSApIHtcblx0XHRcdGFjY2VzcyggZWxlbXMsIGZuLCBpLCBrZXlbIGkgXSwgdHJ1ZSwgZW1wdHlHZXQsIHJhdyApO1xuXHRcdH1cblxuXHQvLyBTZXRzIG9uZSB2YWx1ZVxuXHR9IGVsc2UgaWYgKCB2YWx1ZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdGNoYWluYWJsZSA9IHRydWU7XG5cblx0XHRpZiAoICFqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJhdyA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCBidWxrICkge1xuXG5cdFx0XHQvLyBCdWxrIG9wZXJhdGlvbnMgcnVuIGFnYWluc3QgdGhlIGVudGlyZSBzZXRcblx0XHRcdGlmICggcmF3ICkge1xuXHRcdFx0XHRmbi5jYWxsKCBlbGVtcywgdmFsdWUgKTtcblx0XHRcdFx0Zm4gPSBudWxsO1xuXG5cdFx0XHQvLyAuLi5leGNlcHQgd2hlbiBleGVjdXRpbmcgZnVuY3Rpb24gdmFsdWVzXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRidWxrID0gZm47XG5cdFx0XHRcdGZuID0gZnVuY3Rpb24oIGVsZW0sIGtleSwgdmFsdWUgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGJ1bGsuY2FsbCggalF1ZXJ5KCBlbGVtICksIHZhbHVlICk7XG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBmbiApIHtcblx0XHRcdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRmbihcblx0XHRcdFx0XHRlbGVtc1sgaSBdLCBrZXksIHJhdyA/XG5cdFx0XHRcdFx0dmFsdWUgOlxuXHRcdFx0XHRcdHZhbHVlLmNhbGwoIGVsZW1zWyBpIF0sIGksIGZuKCBlbGVtc1sgaSBdLCBrZXkgKSApXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aWYgKCBjaGFpbmFibGUgKSB7XG5cdFx0cmV0dXJuIGVsZW1zO1xuXHR9XG5cblx0Ly8gR2V0c1xuXHRpZiAoIGJ1bGsgKSB7XG5cdFx0cmV0dXJuIGZuLmNhbGwoIGVsZW1zICk7XG5cdH1cblxuXHRyZXR1cm4gbGVuID8gZm4oIGVsZW1zWyAwIF0sIGtleSApIDogZW1wdHlHZXQ7XG59O1xudmFyIGFjY2VwdERhdGEgPSBmdW5jdGlvbiggb3duZXIgKSB7XG5cblx0Ly8gQWNjZXB0cyBvbmx5OlxuXHQvLyAgLSBOb2RlXG5cdC8vICAgIC0gTm9kZS5FTEVNRU5UX05PREVcblx0Ly8gICAgLSBOb2RlLkRPQ1VNRU5UX05PREVcblx0Ly8gIC0gT2JqZWN0XG5cdC8vICAgIC0gQW55XG5cdHJldHVybiBvd25lci5ub2RlVHlwZSA9PT0gMSB8fCBvd25lci5ub2RlVHlwZSA9PT0gOSB8fCAhKCArb3duZXIubm9kZVR5cGUgKTtcbn07XG5cblxuXG5cbmZ1bmN0aW9uIERhdGEoKSB7XG5cdHRoaXMuZXhwYW5kbyA9IGpRdWVyeS5leHBhbmRvICsgRGF0YS51aWQrKztcbn1cblxuRGF0YS51aWQgPSAxO1xuXG5EYXRhLnByb3RvdHlwZSA9IHtcblxuXHRjYWNoZTogZnVuY3Rpb24oIG93bmVyICkge1xuXG5cdFx0Ly8gQ2hlY2sgaWYgdGhlIG93bmVyIG9iamVjdCBhbHJlYWR5IGhhcyBhIGNhY2hlXG5cdFx0dmFyIHZhbHVlID0gb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXG5cdFx0Ly8gSWYgbm90LCBjcmVhdGUgb25lXG5cdFx0aWYgKCAhdmFsdWUgKSB7XG5cdFx0XHR2YWx1ZSA9IHt9O1xuXG5cdFx0XHQvLyBXZSBjYW4gYWNjZXB0IGRhdGEgZm9yIG5vbi1lbGVtZW50IG5vZGVzIGluIG1vZGVybiBicm93c2Vycyxcblx0XHRcdC8vIGJ1dCB3ZSBzaG91bGQgbm90LCBzZWUgIzgzMzUuXG5cdFx0XHQvLyBBbHdheXMgcmV0dXJuIGFuIGVtcHR5IG9iamVjdC5cblx0XHRcdGlmICggYWNjZXB0RGF0YSggb3duZXIgKSApIHtcblxuXHRcdFx0XHQvLyBJZiBpdCBpcyBhIG5vZGUgdW5saWtlbHkgdG8gYmUgc3RyaW5naWZ5LWVkIG9yIGxvb3BlZCBvdmVyXG5cdFx0XHRcdC8vIHVzZSBwbGFpbiBhc3NpZ25tZW50XG5cdFx0XHRcdGlmICggb3duZXIubm9kZVR5cGUgKSB7XG5cdFx0XHRcdFx0b3duZXJbIHRoaXMuZXhwYW5kbyBdID0gdmFsdWU7XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlIHNlY3VyZSBpdCBpbiBhIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5XG5cdFx0XHRcdC8vIGNvbmZpZ3VyYWJsZSBtdXN0IGJlIHRydWUgdG8gYWxsb3cgdGhlIHByb3BlcnR5IHRvIGJlXG5cdFx0XHRcdC8vIGRlbGV0ZWQgd2hlbiBkYXRhIGlzIHJlbW92ZWRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIG93bmVyLCB0aGlzLmV4cGFuZG8sIHtcblx0XHRcdFx0XHRcdHZhbHVlOiB2YWx1ZSxcblx0XHRcdFx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZVxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB2YWx1ZTtcblx0fSxcblx0c2V0OiBmdW5jdGlvbiggb3duZXIsIGRhdGEsIHZhbHVlICkge1xuXHRcdHZhciBwcm9wLFxuXHRcdFx0Y2FjaGUgPSB0aGlzLmNhY2hlKCBvd25lciApO1xuXG5cdFx0Ly8gSGFuZGxlOiBbIG93bmVyLCBrZXksIHZhbHVlIF0gYXJnc1xuXHRcdC8vIEFsd2F5cyB1c2UgY2FtZWxDYXNlIGtleSAoZ2gtMjI1Nylcblx0XHRpZiAoIHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0Y2FjaGVbIGpRdWVyeS5jYW1lbENhc2UoIGRhdGEgKSBdID0gdmFsdWU7XG5cblx0XHQvLyBIYW5kbGU6IFsgb3duZXIsIHsgcHJvcGVydGllcyB9IF0gYXJnc1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIENvcHkgdGhlIHByb3BlcnRpZXMgb25lLWJ5LW9uZSB0byB0aGUgY2FjaGUgb2JqZWN0XG5cdFx0XHRmb3IgKCBwcm9wIGluIGRhdGEgKSB7XG5cdFx0XHRcdGNhY2hlWyBqUXVlcnkuY2FtZWxDYXNlKCBwcm9wICkgXSA9IGRhdGFbIHByb3AgXTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGNhY2hlO1xuXHR9LFxuXHRnZXQ6IGZ1bmN0aW9uKCBvd25lciwga2V5ICkge1xuXHRcdHJldHVybiBrZXkgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHR0aGlzLmNhY2hlKCBvd25lciApIDpcblxuXHRcdFx0Ly8gQWx3YXlzIHVzZSBjYW1lbENhc2Uga2V5IChnaC0yMjU3KVxuXHRcdFx0b3duZXJbIHRoaXMuZXhwYW5kbyBdICYmIG93bmVyWyB0aGlzLmV4cGFuZG8gXVsgalF1ZXJ5LmNhbWVsQ2FzZSgga2V5ICkgXTtcblx0fSxcblx0YWNjZXNzOiBmdW5jdGlvbiggb3duZXIsIGtleSwgdmFsdWUgKSB7XG5cblx0XHQvLyBJbiBjYXNlcyB3aGVyZSBlaXRoZXI6XG5cdFx0Ly9cblx0XHQvLyAgIDEuIE5vIGtleSB3YXMgc3BlY2lmaWVkXG5cdFx0Ly8gICAyLiBBIHN0cmluZyBrZXkgd2FzIHNwZWNpZmllZCwgYnV0IG5vIHZhbHVlIHByb3ZpZGVkXG5cdFx0Ly9cblx0XHQvLyBUYWtlIHRoZSBcInJlYWRcIiBwYXRoIGFuZCBhbGxvdyB0aGUgZ2V0IG1ldGhvZCB0byBkZXRlcm1pbmVcblx0XHQvLyB3aGljaCB2YWx1ZSB0byByZXR1cm4sIHJlc3BlY3RpdmVseSBlaXRoZXI6XG5cdFx0Ly9cblx0XHQvLyAgIDEuIFRoZSBlbnRpcmUgY2FjaGUgb2JqZWN0XG5cdFx0Ly8gICAyLiBUaGUgZGF0YSBzdG9yZWQgYXQgdGhlIGtleVxuXHRcdC8vXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fFxuXHRcdFx0XHQoICgga2V5ICYmIHR5cGVvZiBrZXkgPT09IFwic3RyaW5nXCIgKSAmJiB2YWx1ZSA9PT0gdW5kZWZpbmVkICkgKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLmdldCggb3duZXIsIGtleSApO1xuXHRcdH1cblxuXHRcdC8vIFdoZW4gdGhlIGtleSBpcyBub3QgYSBzdHJpbmcsIG9yIGJvdGggYSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly8gYXJlIHNwZWNpZmllZCwgc2V0IG9yIGV4dGVuZCAoZXhpc3Rpbmcgb2JqZWN0cykgd2l0aCBlaXRoZXI6XG5cdFx0Ly9cblx0XHQvLyAgIDEuIEFuIG9iamVjdCBvZiBwcm9wZXJ0aWVzXG5cdFx0Ly8gICAyLiBBIGtleSBhbmQgdmFsdWVcblx0XHQvL1xuXHRcdHRoaXMuc2V0KCBvd25lciwga2V5LCB2YWx1ZSApO1xuXG5cdFx0Ly8gU2luY2UgdGhlIFwic2V0XCIgcGF0aCBjYW4gaGF2ZSB0d28gcG9zc2libGUgZW50cnkgcG9pbnRzXG5cdFx0Ly8gcmV0dXJuIHRoZSBleHBlY3RlZCBkYXRhIGJhc2VkIG9uIHdoaWNoIHBhdGggd2FzIHRha2VuWypdXG5cdFx0cmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgPyB2YWx1ZSA6IGtleTtcblx0fSxcblx0cmVtb3ZlOiBmdW5jdGlvbiggb3duZXIsIGtleSApIHtcblx0XHR2YXIgaSxcblx0XHRcdGNhY2hlID0gb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXG5cdFx0aWYgKCBjYWNoZSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICgga2V5ICE9PSB1bmRlZmluZWQgKSB7XG5cblx0XHRcdC8vIFN1cHBvcnQgYXJyYXkgb3Igc3BhY2Ugc2VwYXJhdGVkIHN0cmluZyBvZiBrZXlzXG5cdFx0XHRpZiAoIEFycmF5LmlzQXJyYXkoIGtleSApICkge1xuXG5cdFx0XHRcdC8vIElmIGtleSBpcyBhbiBhcnJheSBvZiBrZXlzLi4uXG5cdFx0XHRcdC8vIFdlIGFsd2F5cyBzZXQgY2FtZWxDYXNlIGtleXMsIHNvIHJlbW92ZSB0aGF0LlxuXHRcdFx0XHRrZXkgPSBrZXkubWFwKCBqUXVlcnkuY2FtZWxDYXNlICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRrZXkgPSBqUXVlcnkuY2FtZWxDYXNlKCBrZXkgKTtcblxuXHRcdFx0XHQvLyBJZiBhIGtleSB3aXRoIHRoZSBzcGFjZXMgZXhpc3RzLCB1c2UgaXQuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSwgY3JlYXRlIGFuIGFycmF5IGJ5IG1hdGNoaW5nIG5vbi13aGl0ZXNwYWNlXG5cdFx0XHRcdGtleSA9IGtleSBpbiBjYWNoZSA/XG5cdFx0XHRcdFx0WyBrZXkgXSA6XG5cdFx0XHRcdFx0KCBrZXkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpID0ga2V5Lmxlbmd0aDtcblxuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGRlbGV0ZSBjYWNoZVsga2V5WyBpIF0gXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgdGhlIGV4cGFuZG8gaWYgdGhlcmUncyBubyBtb3JlIGRhdGFcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkIHx8IGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBjYWNoZSApICkge1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1XG5cdFx0XHQvLyBXZWJraXQgJiBCbGluayBwZXJmb3JtYW5jZSBzdWZmZXJzIHdoZW4gZGVsZXRpbmcgcHJvcGVydGllc1xuXHRcdFx0Ly8gZnJvbSBET00gbm9kZXMsIHNvIHNldCB0byB1bmRlZmluZWQgaW5zdGVhZFxuXHRcdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9Mzc4NjA3IChidWcgcmVzdHJpY3RlZClcblx0XHRcdGlmICggb3duZXIubm9kZVR5cGUgKSB7XG5cdFx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRlbGV0ZSBvd25lclsgdGhpcy5leHBhbmRvIF07XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRoYXNEYXRhOiBmdW5jdGlvbiggb3duZXIgKSB7XG5cdFx0dmFyIGNhY2hlID0gb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXHRcdHJldHVybiBjYWNoZSAhPT0gdW5kZWZpbmVkICYmICFqUXVlcnkuaXNFbXB0eU9iamVjdCggY2FjaGUgKTtcblx0fVxufTtcbnZhciBkYXRhUHJpdiA9IG5ldyBEYXRhKCk7XG5cbnZhciBkYXRhVXNlciA9IG5ldyBEYXRhKCk7XG5cblxuXG4vL1x0SW1wbGVtZW50YXRpb24gU3VtbWFyeVxuLy9cbi8vXHQxLiBFbmZvcmNlIEFQSSBzdXJmYWNlIGFuZCBzZW1hbnRpYyBjb21wYXRpYmlsaXR5IHdpdGggMS45LnggYnJhbmNoXG4vL1x0Mi4gSW1wcm92ZSB0aGUgbW9kdWxlJ3MgbWFpbnRhaW5hYmlsaXR5IGJ5IHJlZHVjaW5nIHRoZSBzdG9yYWdlXG4vL1x0XHRwYXRocyB0byBhIHNpbmdsZSBtZWNoYW5pc20uXG4vL1x0My4gVXNlIHRoZSBzYW1lIHNpbmdsZSBtZWNoYW5pc20gdG8gc3VwcG9ydCBcInByaXZhdGVcIiBhbmQgXCJ1c2VyXCIgZGF0YS5cbi8vXHQ0LiBfTmV2ZXJfIGV4cG9zZSBcInByaXZhdGVcIiBkYXRhIHRvIHVzZXIgY29kZSAoVE9ETzogRHJvcCBfZGF0YSwgX3JlbW92ZURhdGEpXG4vL1x0NS4gQXZvaWQgZXhwb3NpbmcgaW1wbGVtZW50YXRpb24gZGV0YWlscyBvbiB1c2VyIG9iamVjdHMgKGVnLiBleHBhbmRvIHByb3BlcnRpZXMpXG4vL1x0Ni4gUHJvdmlkZSBhIGNsZWFyIHBhdGggZm9yIGltcGxlbWVudGF0aW9uIHVwZ3JhZGUgdG8gV2Vha01hcCBpbiAyMDE0XG5cbnZhciByYnJhY2UgPSAvXig/Olxce1tcXHdcXFddKlxcfXxcXFtbXFx3XFxXXSpcXF0pJC8sXG5cdHJtdWx0aURhc2ggPSAvW0EtWl0vZztcblxuZnVuY3Rpb24gZ2V0RGF0YSggZGF0YSApIHtcblx0aWYgKCBkYXRhID09PSBcInRydWVcIiApIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdGlmICggZGF0YSA9PT0gXCJmYWxzZVwiICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlmICggZGF0YSA9PT0gXCJudWxsXCIgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvLyBPbmx5IGNvbnZlcnQgdG8gYSBudW1iZXIgaWYgaXQgZG9lc24ndCBjaGFuZ2UgdGhlIHN0cmluZ1xuXHRpZiAoIGRhdGEgPT09ICtkYXRhICsgXCJcIiApIHtcblx0XHRyZXR1cm4gK2RhdGE7XG5cdH1cblxuXHRpZiAoIHJicmFjZS50ZXN0KCBkYXRhICkgKSB7XG5cdFx0cmV0dXJuIEpTT04ucGFyc2UoIGRhdGEgKTtcblx0fVxuXG5cdHJldHVybiBkYXRhO1xufVxuXG5mdW5jdGlvbiBkYXRhQXR0ciggZWxlbSwga2V5LCBkYXRhICkge1xuXHR2YXIgbmFtZTtcblxuXHQvLyBJZiBub3RoaW5nIHdhcyBmb3VuZCBpbnRlcm5hbGx5LCB0cnkgdG8gZmV0Y2ggYW55XG5cdC8vIGRhdGEgZnJvbSB0aGUgSFRNTDUgZGF0YS0qIGF0dHJpYnV0ZVxuXHRpZiAoIGRhdGEgPT09IHVuZGVmaW5lZCAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdG5hbWUgPSBcImRhdGEtXCIgKyBrZXkucmVwbGFjZSggcm11bHRpRGFzaCwgXCItJCZcIiApLnRvTG93ZXJDYXNlKCk7XG5cdFx0ZGF0YSA9IGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICk7XG5cblx0XHRpZiAoIHR5cGVvZiBkYXRhID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0ZGF0YSA9IGdldERhdGEoIGRhdGEgKTtcblx0XHRcdH0gY2F0Y2ggKCBlICkge31cblxuXHRcdFx0Ly8gTWFrZSBzdXJlIHdlIHNldCB0aGUgZGF0YSBzbyBpdCBpc24ndCBjaGFuZ2VkIGxhdGVyXG5cdFx0XHRkYXRhVXNlci5zZXQoIGVsZW0sIGtleSwgZGF0YSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gZGF0YTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRoYXNEYXRhOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRyZXR1cm4gZGF0YVVzZXIuaGFzRGF0YSggZWxlbSApIHx8IGRhdGFQcml2Lmhhc0RhdGEoIGVsZW0gKTtcblx0fSxcblxuXHRkYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gZGF0YVVzZXIuYWNjZXNzKCBlbGVtLCBuYW1lLCBkYXRhICk7XG5cdH0sXG5cblx0cmVtb3ZlRGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUgKSB7XG5cdFx0ZGF0YVVzZXIucmVtb3ZlKCBlbGVtLCBuYW1lICk7XG5cdH0sXG5cblx0Ly8gVE9ETzogTm93IHRoYXQgYWxsIGNhbGxzIHRvIF9kYXRhIGFuZCBfcmVtb3ZlRGF0YSBoYXZlIGJlZW4gcmVwbGFjZWRcblx0Ly8gd2l0aCBkaXJlY3QgY2FsbHMgdG8gZGF0YVByaXYgbWV0aG9kcywgdGhlc2UgY2FuIGJlIGRlcHJlY2F0ZWQuXG5cdF9kYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCBuYW1lLCBkYXRhICk7XG5cdH0sXG5cblx0X3JlbW92ZURhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0ZGF0YTogZnVuY3Rpb24oIGtleSwgdmFsdWUgKSB7XG5cdFx0dmFyIGksIG5hbWUsIGRhdGEsXG5cdFx0XHRlbGVtID0gdGhpc1sgMCBdLFxuXHRcdFx0YXR0cnMgPSBlbGVtICYmIGVsZW0uYXR0cmlidXRlcztcblxuXHRcdC8vIEdldHMgYWxsIHZhbHVlc1xuXHRcdGlmICgga2V5ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIHRoaXMubGVuZ3RoICkge1xuXHRcdFx0XHRkYXRhID0gZGF0YVVzZXIuZ2V0KCBlbGVtICk7XG5cblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmICFkYXRhUHJpdi5nZXQoIGVsZW0sIFwiaGFzRGF0YUF0dHJzXCIgKSApIHtcblx0XHRcdFx0XHRpID0gYXR0cnMubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSAxMSBvbmx5XG5cdFx0XHRcdFx0XHQvLyBUaGUgYXR0cnMgZWxlbWVudHMgY2FuIGJlIG51bGwgKCMxNDg5NClcblx0XHRcdFx0XHRcdGlmICggYXR0cnNbIGkgXSApIHtcblx0XHRcdFx0XHRcdFx0bmFtZSA9IGF0dHJzWyBpIF0ubmFtZTtcblx0XHRcdFx0XHRcdFx0aWYgKCBuYW1lLmluZGV4T2YoIFwiZGF0YS1cIiApID09PSAwICkge1xuXHRcdFx0XHRcdFx0XHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBuYW1lLnNsaWNlKCA1ICkgKTtcblx0XHRcdFx0XHRcdFx0XHRkYXRhQXR0ciggZWxlbSwgbmFtZSwgZGF0YVsgbmFtZSBdICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZGF0YVByaXYuc2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiLCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0cyBtdWx0aXBsZSB2YWx1ZXNcblx0XHRpZiAoIHR5cGVvZiBrZXkgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGF0YVVzZXIuc2V0KCB0aGlzLCBrZXkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZGF0YTtcblxuXHRcdFx0Ly8gVGhlIGNhbGxpbmcgalF1ZXJ5IG9iamVjdCAoZWxlbWVudCBtYXRjaGVzKSBpcyBub3QgZW1wdHlcblx0XHRcdC8vIChhbmQgdGhlcmVmb3JlIGhhcyBhbiBlbGVtZW50IGFwcGVhcnMgYXQgdGhpc1sgMCBdKSBhbmQgdGhlXG5cdFx0XHQvLyBgdmFsdWVgIHBhcmFtZXRlciB3YXMgbm90IHVuZGVmaW5lZC4gQW4gZW1wdHkgalF1ZXJ5IG9iamVjdFxuXHRcdFx0Ly8gd2lsbCByZXN1bHQgaW4gYHVuZGVmaW5lZGAgZm9yIGVsZW0gPSB0aGlzWyAwIF0gd2hpY2ggd2lsbFxuXHRcdFx0Ly8gdGhyb3cgYW4gZXhjZXB0aW9uIGlmIGFuIGF0dGVtcHQgdG8gcmVhZCBhIGRhdGEgY2FjaGUgaXMgbWFkZS5cblx0XHRcdGlmICggZWxlbSAmJiB2YWx1ZSA9PT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gZ2V0IGRhdGEgZnJvbSB0aGUgY2FjaGVcblx0XHRcdFx0Ly8gVGhlIGtleSB3aWxsIGFsd2F5cyBiZSBjYW1lbENhc2VkIGluIERhdGFcblx0XHRcdFx0ZGF0YSA9IGRhdGFVc2VyLmdldCggZWxlbSwga2V5ICk7XG5cdFx0XHRcdGlmICggZGF0YSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQXR0ZW1wdCB0byBcImRpc2NvdmVyXCIgdGhlIGRhdGEgaW5cblx0XHRcdFx0Ly8gSFRNTDUgY3VzdG9tIGRhdGEtKiBhdHRyc1xuXHRcdFx0XHRkYXRhID0gZGF0YUF0dHIoIGVsZW0sIGtleSApO1xuXHRcdFx0XHRpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFdlIHRyaWVkIHJlYWxseSBoYXJkLCBidXQgdGhlIGRhdGEgZG9lc24ndCBleGlzdC5cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTZXQgdGhlIGRhdGEuLi5cblx0XHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0Ly8gV2UgYWx3YXlzIHN0b3JlIHRoZSBjYW1lbENhc2VkIGtleVxuXHRcdFx0XHRkYXRhVXNlci5zZXQoIHRoaXMsIGtleSwgdmFsdWUgKTtcblx0XHRcdH0gKTtcblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEsIG51bGwsIHRydWUgKTtcblx0fSxcblxuXHRyZW1vdmVEYXRhOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0ZGF0YVVzZXIucmVtb3ZlKCB0aGlzLCBrZXkgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cdHF1ZXVlOiBmdW5jdGlvbiggZWxlbSwgdHlwZSwgZGF0YSApIHtcblx0XHR2YXIgcXVldWU7XG5cblx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHR0eXBlID0gKCB0eXBlIHx8IFwiZnhcIiApICsgXCJxdWV1ZVwiO1xuXHRcdFx0cXVldWUgPSBkYXRhUHJpdi5nZXQoIGVsZW0sIHR5cGUgKTtcblxuXHRcdFx0Ly8gU3BlZWQgdXAgZGVxdWV1ZSBieSBnZXR0aW5nIG91dCBxdWlja2x5IGlmIHRoaXMgaXMganVzdCBhIGxvb2t1cFxuXHRcdFx0aWYgKCBkYXRhICkge1xuXHRcdFx0XHRpZiAoICFxdWV1ZSB8fCBBcnJheS5pc0FycmF5KCBkYXRhICkgKSB7XG5cdFx0XHRcdFx0cXVldWUgPSBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIHR5cGUsIGpRdWVyeS5tYWtlQXJyYXkoIGRhdGEgKSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHF1ZXVlLnB1c2goIGRhdGEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHF1ZXVlIHx8IFtdO1xuXHRcdH1cblx0fSxcblxuXHRkZXF1ZXVlOiBmdW5jdGlvbiggZWxlbSwgdHlwZSApIHtcblx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0XHR2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIGVsZW0sIHR5cGUgKSxcblx0XHRcdHN0YXJ0TGVuZ3RoID0gcXVldWUubGVuZ3RoLFxuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpLFxuXHRcdFx0aG9va3MgPSBqUXVlcnkuX3F1ZXVlSG9va3MoIGVsZW0sIHR5cGUgKSxcblx0XHRcdG5leHQgPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0alF1ZXJ5LmRlcXVldWUoIGVsZW0sIHR5cGUgKTtcblx0XHRcdH07XG5cblx0XHQvLyBJZiB0aGUgZnggcXVldWUgaXMgZGVxdWV1ZWQsIGFsd2F5cyByZW1vdmUgdGhlIHByb2dyZXNzIHNlbnRpbmVsXG5cdFx0aWYgKCBmbiA9PT0gXCJpbnByb2dyZXNzXCIgKSB7XG5cdFx0XHRmbiA9IHF1ZXVlLnNoaWZ0KCk7XG5cdFx0XHRzdGFydExlbmd0aC0tO1xuXHRcdH1cblxuXHRcdGlmICggZm4gKSB7XG5cblx0XHRcdC8vIEFkZCBhIHByb2dyZXNzIHNlbnRpbmVsIHRvIHByZXZlbnQgdGhlIGZ4IHF1ZXVlIGZyb20gYmVpbmdcblx0XHRcdC8vIGF1dG9tYXRpY2FsbHkgZGVxdWV1ZWRcblx0XHRcdGlmICggdHlwZSA9PT0gXCJmeFwiICkge1xuXHRcdFx0XHRxdWV1ZS51bnNoaWZ0KCBcImlucHJvZ3Jlc3NcIiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDbGVhciB1cCB0aGUgbGFzdCBxdWV1ZSBzdG9wIGZ1bmN0aW9uXG5cdFx0XHRkZWxldGUgaG9va3Muc3RvcDtcblx0XHRcdGZuLmNhbGwoIGVsZW0sIG5leHQsIGhvb2tzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhc3RhcnRMZW5ndGggJiYgaG9va3MgKSB7XG5cdFx0XHRob29rcy5lbXB0eS5maXJlKCk7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIE5vdCBwdWJsaWMgLSBnZW5lcmF0ZSBhIHF1ZXVlSG9va3Mgb2JqZWN0LCBvciByZXR1cm4gdGhlIGN1cnJlbnQgb25lXG5cdF9xdWV1ZUhvb2tzOiBmdW5jdGlvbiggZWxlbSwgdHlwZSApIHtcblx0XHR2YXIga2V5ID0gdHlwZSArIFwicXVldWVIb29rc1wiO1xuXHRcdHJldHVybiBkYXRhUHJpdi5nZXQoIGVsZW0sIGtleSApIHx8IGRhdGFQcml2LmFjY2VzcyggZWxlbSwga2V5LCB7XG5cdFx0XHRlbXB0eTogalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICkuYWRkKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBlbGVtLCBbIHR5cGUgKyBcInF1ZXVlXCIsIGtleSBdICk7XG5cdFx0XHR9IClcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRxdWV1ZTogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHNldHRlciA9IDI7XG5cblx0XHRpZiAoIHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZGF0YSA9IHR5cGU7XG5cdFx0XHR0eXBlID0gXCJmeFwiO1xuXHRcdFx0c2V0dGVyLS07XG5cdFx0fVxuXG5cdFx0aWYgKCBhcmd1bWVudHMubGVuZ3RoIDwgc2V0dGVyICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5xdWV1ZSggdGhpc1sgMCBdLCB0eXBlICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGRhdGEgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHR0aGlzIDpcblx0XHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBxdWV1ZSA9IGpRdWVyeS5xdWV1ZSggdGhpcywgdHlwZSwgZGF0YSApO1xuXG5cdFx0XHRcdC8vIEVuc3VyZSBhIGhvb2tzIGZvciB0aGlzIHF1ZXVlXG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggdGhpcywgdHlwZSApO1xuXG5cdFx0XHRcdGlmICggdHlwZSA9PT0gXCJmeFwiICYmIHF1ZXVlWyAwIF0gIT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCB0aGlzLCB0eXBlICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0fSxcblx0ZGVxdWV1ZTogZnVuY3Rpb24oIHR5cGUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdH0gKTtcblx0fSxcblx0Y2xlYXJRdWV1ZTogZnVuY3Rpb24oIHR5cGUgKSB7XG5cdFx0cmV0dXJuIHRoaXMucXVldWUoIHR5cGUgfHwgXCJmeFwiLCBbXSApO1xuXHR9LFxuXG5cdC8vIEdldCBhIHByb21pc2UgcmVzb2x2ZWQgd2hlbiBxdWV1ZXMgb2YgYSBjZXJ0YWluIHR5cGVcblx0Ly8gYXJlIGVtcHRpZWQgKGZ4IGlzIHRoZSB0eXBlIGJ5IGRlZmF1bHQpXG5cdHByb21pc2U6IGZ1bmN0aW9uKCB0eXBlLCBvYmogKSB7XG5cdFx0dmFyIHRtcCxcblx0XHRcdGNvdW50ID0gMSxcblx0XHRcdGRlZmVyID0galF1ZXJ5LkRlZmVycmVkKCksXG5cdFx0XHRlbGVtZW50cyA9IHRoaXMsXG5cdFx0XHRpID0gdGhpcy5sZW5ndGgsXG5cdFx0XHRyZXNvbHZlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggISggLS1jb3VudCApICkge1xuXHRcdFx0XHRcdGRlZmVyLnJlc29sdmVXaXRoKCBlbGVtZW50cywgWyBlbGVtZW50cyBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRpZiAoIHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0b2JqID0gdHlwZTtcblx0XHRcdHR5cGUgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdHR5cGUgPSB0eXBlIHx8IFwiZnhcIjtcblxuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG1wID0gZGF0YVByaXYuZ2V0KCBlbGVtZW50c1sgaSBdLCB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgKTtcblx0XHRcdGlmICggdG1wICYmIHRtcC5lbXB0eSApIHtcblx0XHRcdFx0Y291bnQrKztcblx0XHRcdFx0dG1wLmVtcHR5LmFkZCggcmVzb2x2ZSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXNvbHZlKCk7XG5cdFx0cmV0dXJuIGRlZmVyLnByb21pc2UoIG9iaiApO1xuXHR9XG59ICk7XG52YXIgcG51bSA9ICggL1srLV0/KD86XFxkKlxcLnwpXFxkKyg/OltlRV1bKy1dP1xcZCt8KS8gKS5zb3VyY2U7XG5cbnZhciByY3NzTnVtID0gbmV3IFJlZ0V4cCggXCJeKD86KFsrLV0pPXwpKFwiICsgcG51bSArIFwiKShbYS16JV0qKSRcIiwgXCJpXCIgKTtcblxuXG52YXIgY3NzRXhwYW5kID0gWyBcIlRvcFwiLCBcIlJpZ2h0XCIsIFwiQm90dG9tXCIsIFwiTGVmdFwiIF07XG5cbnZhciBpc0hpZGRlbldpdGhpblRyZWUgPSBmdW5jdGlvbiggZWxlbSwgZWwgKSB7XG5cblx0XHQvLyBpc0hpZGRlbldpdGhpblRyZWUgbWlnaHQgYmUgY2FsbGVkIGZyb20galF1ZXJ5I2ZpbHRlciBmdW5jdGlvbjtcblx0XHQvLyBpbiB0aGF0IGNhc2UsIGVsZW1lbnQgd2lsbCBiZSBzZWNvbmQgYXJndW1lbnRcblx0XHRlbGVtID0gZWwgfHwgZWxlbTtcblxuXHRcdC8vIElubGluZSBzdHlsZSB0cnVtcHMgYWxsXG5cdFx0cmV0dXJuIGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJub25lXCIgfHxcblx0XHRcdGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJcIiAmJlxuXG5cdFx0XHQvLyBPdGhlcndpc2UsIGNoZWNrIGNvbXB1dGVkIHN0eWxlXG5cdFx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDw9NDMgLSA0NVxuXHRcdFx0Ly8gRGlzY29ubmVjdGVkIGVsZW1lbnRzIGNhbiBoYXZlIGNvbXB1dGVkIGRpc3BsYXk6IG5vbmUsIHNvIGZpcnN0IGNvbmZpcm0gdGhhdCBlbGVtIGlzXG5cdFx0XHQvLyBpbiB0aGUgZG9jdW1lbnQuXG5cdFx0XHRqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICYmXG5cblx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICkgPT09IFwibm9uZVwiO1xuXHR9O1xuXG52YXIgc3dhcCA9IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBjYWxsYmFjaywgYXJncyApIHtcblx0dmFyIHJldCwgbmFtZSxcblx0XHRvbGQgPSB7fTtcblxuXHQvLyBSZW1lbWJlciB0aGUgb2xkIHZhbHVlcywgYW5kIGluc2VydCB0aGUgbmV3IG9uZXNcblx0Zm9yICggbmFtZSBpbiBvcHRpb25zICkge1xuXHRcdG9sZFsgbmFtZSBdID0gZWxlbS5zdHlsZVsgbmFtZSBdO1xuXHRcdGVsZW0uc3R5bGVbIG5hbWUgXSA9IG9wdGlvbnNbIG5hbWUgXTtcblx0fVxuXG5cdHJldCA9IGNhbGxiYWNrLmFwcGx5KCBlbGVtLCBhcmdzIHx8IFtdICk7XG5cblx0Ly8gUmV2ZXJ0IHRoZSBvbGQgdmFsdWVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvbGRbIG5hbWUgXTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59O1xuXG5cblxuXG5mdW5jdGlvbiBhZGp1c3RDU1MoIGVsZW0sIHByb3AsIHZhbHVlUGFydHMsIHR3ZWVuICkge1xuXHR2YXIgYWRqdXN0ZWQsXG5cdFx0c2NhbGUgPSAxLFxuXHRcdG1heEl0ZXJhdGlvbnMgPSAyMCxcblx0XHRjdXJyZW50VmFsdWUgPSB0d2VlbiA/XG5cdFx0XHRmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuLmN1cigpO1xuXHRcdFx0fSA6XG5cdFx0XHRmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuIGpRdWVyeS5jc3MoIGVsZW0sIHByb3AsIFwiXCIgKTtcblx0XHRcdH0sXG5cdFx0aW5pdGlhbCA9IGN1cnJlbnRWYWx1ZSgpLFxuXHRcdHVuaXQgPSB2YWx1ZVBhcnRzICYmIHZhbHVlUGFydHNbIDMgXSB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKSxcblxuXHRcdC8vIFN0YXJ0aW5nIHZhbHVlIGNvbXB1dGF0aW9uIGlzIHJlcXVpcmVkIGZvciBwb3RlbnRpYWwgdW5pdCBtaXNtYXRjaGVzXG5cdFx0aW5pdGlhbEluVW5pdCA9ICggalF1ZXJ5LmNzc051bWJlclsgcHJvcCBdIHx8IHVuaXQgIT09IFwicHhcIiAmJiAraW5pdGlhbCApICYmXG5cdFx0XHRyY3NzTnVtLmV4ZWMoIGpRdWVyeS5jc3MoIGVsZW0sIHByb3AgKSApO1xuXG5cdGlmICggaW5pdGlhbEluVW5pdCAmJiBpbml0aWFsSW5Vbml0WyAzIF0gIT09IHVuaXQgKSB7XG5cblx0XHQvLyBUcnVzdCB1bml0cyByZXBvcnRlZCBieSBqUXVlcnkuY3NzXG5cdFx0dW5pdCA9IHVuaXQgfHwgaW5pdGlhbEluVW5pdFsgMyBdO1xuXG5cdFx0Ly8gTWFrZSBzdXJlIHdlIHVwZGF0ZSB0aGUgdHdlZW4gcHJvcGVydGllcyBsYXRlciBvblxuXHRcdHZhbHVlUGFydHMgPSB2YWx1ZVBhcnRzIHx8IFtdO1xuXG5cdFx0Ly8gSXRlcmF0aXZlbHkgYXBwcm94aW1hdGUgZnJvbSBhIG5vbnplcm8gc3RhcnRpbmcgcG9pbnRcblx0XHRpbml0aWFsSW5Vbml0ID0gK2luaXRpYWwgfHwgMTtcblxuXHRcdGRvIHtcblxuXHRcdFx0Ly8gSWYgcHJldmlvdXMgaXRlcmF0aW9uIHplcm9lZCBvdXQsIGRvdWJsZSB1bnRpbCB3ZSBnZXQgKnNvbWV0aGluZyouXG5cdFx0XHQvLyBVc2Ugc3RyaW5nIGZvciBkb3VibGluZyBzbyB3ZSBkb24ndCBhY2NpZGVudGFsbHkgc2VlIHNjYWxlIGFzIHVuY2hhbmdlZCBiZWxvd1xuXHRcdFx0c2NhbGUgPSBzY2FsZSB8fCBcIi41XCI7XG5cblx0XHRcdC8vIEFkanVzdCBhbmQgYXBwbHlcblx0XHRcdGluaXRpYWxJblVuaXQgPSBpbml0aWFsSW5Vbml0IC8gc2NhbGU7XG5cdFx0XHRqUXVlcnkuc3R5bGUoIGVsZW0sIHByb3AsIGluaXRpYWxJblVuaXQgKyB1bml0ICk7XG5cblx0XHQvLyBVcGRhdGUgc2NhbGUsIHRvbGVyYXRpbmcgemVybyBvciBOYU4gZnJvbSB0d2Vlbi5jdXIoKVxuXHRcdC8vIEJyZWFrIHRoZSBsb29wIGlmIHNjYWxlIGlzIHVuY2hhbmdlZCBvciBwZXJmZWN0LCBvciBpZiB3ZSd2ZSBqdXN0IGhhZCBlbm91Z2guXG5cdFx0fSB3aGlsZSAoXG5cdFx0XHRzY2FsZSAhPT0gKCBzY2FsZSA9IGN1cnJlbnRWYWx1ZSgpIC8gaW5pdGlhbCApICYmIHNjYWxlICE9PSAxICYmIC0tbWF4SXRlcmF0aW9uc1xuXHRcdCk7XG5cdH1cblxuXHRpZiAoIHZhbHVlUGFydHMgKSB7XG5cdFx0aW5pdGlhbEluVW5pdCA9ICtpbml0aWFsSW5Vbml0IHx8ICtpbml0aWFsIHx8IDA7XG5cblx0XHQvLyBBcHBseSByZWxhdGl2ZSBvZmZzZXQgKCs9Ly09KSBpZiBzcGVjaWZpZWRcblx0XHRhZGp1c3RlZCA9IHZhbHVlUGFydHNbIDEgXSA/XG5cdFx0XHRpbml0aWFsSW5Vbml0ICsgKCB2YWx1ZVBhcnRzWyAxIF0gKyAxICkgKiB2YWx1ZVBhcnRzWyAyIF0gOlxuXHRcdFx0K3ZhbHVlUGFydHNbIDIgXTtcblx0XHRpZiAoIHR3ZWVuICkge1xuXHRcdFx0dHdlZW4udW5pdCA9IHVuaXQ7XG5cdFx0XHR0d2Vlbi5zdGFydCA9IGluaXRpYWxJblVuaXQ7XG5cdFx0XHR0d2Vlbi5lbmQgPSBhZGp1c3RlZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGFkanVzdGVkO1xufVxuXG5cbnZhciBkZWZhdWx0RGlzcGxheU1hcCA9IHt9O1xuXG5mdW5jdGlvbiBnZXREZWZhdWx0RGlzcGxheSggZWxlbSApIHtcblx0dmFyIHRlbXAsXG5cdFx0ZG9jID0gZWxlbS5vd25lckRvY3VtZW50LFxuXHRcdG5vZGVOYW1lID0gZWxlbS5ub2RlTmFtZSxcblx0XHRkaXNwbGF5ID0gZGVmYXVsdERpc3BsYXlNYXBbIG5vZGVOYW1lIF07XG5cblx0aWYgKCBkaXNwbGF5ICkge1xuXHRcdHJldHVybiBkaXNwbGF5O1xuXHR9XG5cblx0dGVtcCA9IGRvYy5ib2R5LmFwcGVuZENoaWxkKCBkb2MuY3JlYXRlRWxlbWVudCggbm9kZU5hbWUgKSApO1xuXHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggdGVtcCwgXCJkaXNwbGF5XCIgKTtcblxuXHR0ZW1wLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHRlbXAgKTtcblxuXHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdGRpc3BsYXkgPSBcImJsb2NrXCI7XG5cdH1cblx0ZGVmYXVsdERpc3BsYXlNYXBbIG5vZGVOYW1lIF0gPSBkaXNwbGF5O1xuXG5cdHJldHVybiBkaXNwbGF5O1xufVxuXG5mdW5jdGlvbiBzaG93SGlkZSggZWxlbWVudHMsIHNob3cgKSB7XG5cdHZhciBkaXNwbGF5LCBlbGVtLFxuXHRcdHZhbHVlcyA9IFtdLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBlbGVtZW50cy5sZW5ndGg7XG5cblx0Ly8gRGV0ZXJtaW5lIG5ldyBkaXNwbGF5IHZhbHVlIGZvciBlbGVtZW50cyB0aGF0IG5lZWQgdG8gY2hhbmdlXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0ZWxlbSA9IGVsZW1lbnRzWyBpbmRleCBdO1xuXHRcdGlmICggIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cblx0XHRkaXNwbGF5ID0gZWxlbS5zdHlsZS5kaXNwbGF5O1xuXHRcdGlmICggc2hvdyApIHtcblxuXHRcdFx0Ly8gU2luY2Ugd2UgZm9yY2UgdmlzaWJpbGl0eSB1cG9uIGNhc2NhZGUtaGlkZGVuIGVsZW1lbnRzLCBhbiBpbW1lZGlhdGUgKGFuZCBzbG93KVxuXHRcdFx0Ly8gY2hlY2sgaXMgcmVxdWlyZWQgaW4gdGhpcyBmaXJzdCBsb29wIHVubGVzcyB3ZSBoYXZlIGEgbm9uZW1wdHkgZGlzcGxheSB2YWx1ZSAoZWl0aGVyXG5cdFx0XHQvLyBpbmxpbmUgb3IgYWJvdXQtdG8tYmUtcmVzdG9yZWQpXG5cdFx0XHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdFx0XHR2YWx1ZXNbIGluZGV4IF0gPSBkYXRhUHJpdi5nZXQoIGVsZW0sIFwiZGlzcGxheVwiICkgfHwgbnVsbDtcblx0XHRcdFx0aWYgKCAhdmFsdWVzWyBpbmRleCBdICkge1xuXHRcdFx0XHRcdGVsZW0uc3R5bGUuZGlzcGxheSA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGlmICggZWxlbS5zdHlsZS5kaXNwbGF5ID09PSBcIlwiICYmIGlzSGlkZGVuV2l0aGluVHJlZSggZWxlbSApICkge1xuXHRcdFx0XHR2YWx1ZXNbIGluZGV4IF0gPSBnZXREZWZhdWx0RGlzcGxheSggZWxlbSApO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIGRpc3BsYXkgIT09IFwibm9uZVwiICkge1xuXHRcdFx0XHR2YWx1ZXNbIGluZGV4IF0gPSBcIm5vbmVcIjtcblxuXHRcdFx0XHQvLyBSZW1lbWJlciB3aGF0IHdlJ3JlIG92ZXJ3cml0aW5nXG5cdFx0XHRcdGRhdGFQcml2LnNldCggZWxlbSwgXCJkaXNwbGF5XCIsIGRpc3BsYXkgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBTZXQgdGhlIGRpc3BsYXkgb2YgdGhlIGVsZW1lbnRzIGluIGEgc2Vjb25kIGxvb3AgdG8gYXZvaWQgY29uc3RhbnQgcmVmbG93XG5cdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0aWYgKCB2YWx1ZXNbIGluZGV4IF0gIT0gbnVsbCApIHtcblx0XHRcdGVsZW1lbnRzWyBpbmRleCBdLnN0eWxlLmRpc3BsYXkgPSB2YWx1ZXNbIGluZGV4IF07XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRzO1xufVxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHNob3c6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBzaG93SGlkZSggdGhpcywgdHJ1ZSApO1xuXHR9LFxuXHRoaWRlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMgKTtcblx0fSxcblx0dG9nZ2xlOiBmdW5jdGlvbiggc3RhdGUgKSB7XG5cdFx0aWYgKCB0eXBlb2Ygc3RhdGUgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlID8gdGhpcy5zaG93KCkgOiB0aGlzLmhpZGUoKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggaXNIaWRkZW5XaXRoaW5UcmVlKCB0aGlzICkgKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLnNob3coKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmhpZGUoKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cbn0gKTtcbnZhciByY2hlY2thYmxlVHlwZSA9ICggL14oPzpjaGVja2JveHxyYWRpbykkL2kgKTtcblxudmFyIHJ0YWdOYW1lID0gKCAvPChbYS16XVteXFwvXFwwPlxceDIwXFx0XFxyXFxuXFxmXSspL2kgKTtcblxudmFyIHJzY3JpcHRUeXBlID0gKCAvXiR8XFwvKD86amF2YXxlY21hKXNjcmlwdC9pICk7XG5cblxuXG4vLyBXZSBoYXZlIHRvIGNsb3NlIHRoZXNlIHRhZ3MgdG8gc3VwcG9ydCBYSFRNTCAoIzEzMjAwKVxudmFyIHdyYXBNYXAgPSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0b3B0aW9uOiBbIDEsIFwiPHNlbGVjdCBtdWx0aXBsZT0nbXVsdGlwbGUnPlwiLCBcIjwvc2VsZWN0PlwiIF0sXG5cblx0Ly8gWEhUTUwgcGFyc2VycyBkbyBub3QgbWFnaWNhbGx5IGluc2VydCBlbGVtZW50cyBpbiB0aGVcblx0Ly8gc2FtZSB3YXkgdGhhdCB0YWcgc291cCBwYXJzZXJzIGRvLiBTbyB3ZSBjYW5ub3Qgc2hvcnRlblxuXHQvLyB0aGlzIGJ5IG9taXR0aW5nIDx0Ym9keT4gb3Igb3RoZXIgcmVxdWlyZWQgZWxlbWVudHMuXG5cdHRoZWFkOiBbIDEsIFwiPHRhYmxlPlwiLCBcIjwvdGFibGU+XCIgXSxcblx0Y29sOiBbIDIsIFwiPHRhYmxlPjxjb2xncm91cD5cIiwgXCI8L2NvbGdyb3VwPjwvdGFibGU+XCIgXSxcblx0dHI6IFsgMiwgXCI8dGFibGU+PHRib2R5PlwiLCBcIjwvdGJvZHk+PC90YWJsZT5cIiBdLFxuXHR0ZDogWyAzLCBcIjx0YWJsZT48dGJvZHk+PHRyPlwiLCBcIjwvdHI+PC90Ym9keT48L3RhYmxlPlwiIF0sXG5cblx0X2RlZmF1bHQ6IFsgMCwgXCJcIiwgXCJcIiBdXG59O1xuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxud3JhcE1hcC5vcHRncm91cCA9IHdyYXBNYXAub3B0aW9uO1xuXG53cmFwTWFwLnRib2R5ID0gd3JhcE1hcC50Zm9vdCA9IHdyYXBNYXAuY29sZ3JvdXAgPSB3cmFwTWFwLmNhcHRpb24gPSB3cmFwTWFwLnRoZWFkO1xud3JhcE1hcC50aCA9IHdyYXBNYXAudGQ7XG5cblxuZnVuY3Rpb24gZ2V0QWxsKCBjb250ZXh0LCB0YWcgKSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHQvLyBVc2UgdHlwZW9mIHRvIGF2b2lkIHplcm8tYXJndW1lbnQgbWV0aG9kIGludm9jYXRpb24gb24gaG9zdCBvYmplY3RzICgjMTUxNTEpXG5cdHZhciByZXQ7XG5cblx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRyZXQgPSBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgfHwgXCIqXCIgKTtcblxuXHR9IGVsc2UgaWYgKCB0eXBlb2YgY29udGV4dC5xdWVyeVNlbGVjdG9yQWxsICE9PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdHJldCA9IGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCggdGFnIHx8IFwiKlwiICk7XG5cblx0fSBlbHNlIHtcblx0XHRyZXQgPSBbXTtcblx0fVxuXG5cdGlmICggdGFnID09PSB1bmRlZmluZWQgfHwgdGFnICYmIG5vZGVOYW1lKCBjb250ZXh0LCB0YWcgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5Lm1lcmdlKCBbIGNvbnRleHQgXSwgcmV0ICk7XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufVxuXG5cbi8vIE1hcmsgc2NyaXB0cyBhcyBoYXZpbmcgYWxyZWFkeSBiZWVuIGV2YWx1YXRlZFxuZnVuY3Rpb24gc2V0R2xvYmFsRXZhbCggZWxlbXMsIHJlZkVsZW1lbnRzICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bCA9IGVsZW1zLmxlbmd0aDtcblxuXHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0ZGF0YVByaXYuc2V0KFxuXHRcdFx0ZWxlbXNbIGkgXSxcblx0XHRcdFwiZ2xvYmFsRXZhbFwiLFxuXHRcdFx0IXJlZkVsZW1lbnRzIHx8IGRhdGFQcml2LmdldCggcmVmRWxlbWVudHNbIGkgXSwgXCJnbG9iYWxFdmFsXCIgKVxuXHRcdCk7XG5cdH1cbn1cblxuXG52YXIgcmh0bWwgPSAvPHwmIz9cXHcrOy87XG5cbmZ1bmN0aW9uIGJ1aWxkRnJhZ21lbnQoIGVsZW1zLCBjb250ZXh0LCBzY3JpcHRzLCBzZWxlY3Rpb24sIGlnbm9yZWQgKSB7XG5cdHZhciBlbGVtLCB0bXAsIHRhZywgd3JhcCwgY29udGFpbnMsIGosXG5cdFx0ZnJhZ21lbnQgPSBjb250ZXh0LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRub2RlcyA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdGVsZW0gPSBlbGVtc1sgaSBdO1xuXG5cdFx0aWYgKCBlbGVtIHx8IGVsZW0gPT09IDAgKSB7XG5cblx0XHRcdC8vIEFkZCBub2RlcyBkaXJlY3RseVxuXHRcdFx0aWYgKCBqUXVlcnkudHlwZSggZWxlbSApID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIGVsZW0ubm9kZVR5cGUgPyBbIGVsZW0gXSA6IGVsZW0gKTtcblxuXHRcdFx0Ly8gQ29udmVydCBub24taHRtbCBpbnRvIGEgdGV4dCBub2RlXG5cdFx0XHR9IGVsc2UgaWYgKCAhcmh0bWwudGVzdCggZWxlbSApICkge1xuXHRcdFx0XHRub2Rlcy5wdXNoKCBjb250ZXh0LmNyZWF0ZVRleHROb2RlKCBlbGVtICkgKTtcblxuXHRcdFx0Ly8gQ29udmVydCBodG1sIGludG8gRE9NIG5vZGVzXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0bXAgPSB0bXAgfHwgZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGNvbnRleHQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApICk7XG5cblx0XHRcdFx0Ly8gRGVzZXJpYWxpemUgYSBzdGFuZGFyZCByZXByZXNlbnRhdGlvblxuXHRcdFx0XHR0YWcgPSAoIHJ0YWdOYW1lLmV4ZWMoIGVsZW0gKSB8fCBbIFwiXCIsIFwiXCIgXSApWyAxIF0udG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0d3JhcCA9IHdyYXBNYXBbIHRhZyBdIHx8IHdyYXBNYXAuX2RlZmF1bHQ7XG5cdFx0XHRcdHRtcC5pbm5lckhUTUwgPSB3cmFwWyAxIF0gKyBqUXVlcnkuaHRtbFByZWZpbHRlciggZWxlbSApICsgd3JhcFsgMiBdO1xuXG5cdFx0XHRcdC8vIERlc2NlbmQgdGhyb3VnaCB3cmFwcGVycyB0byB0aGUgcmlnaHQgY29udGVudFxuXHRcdFx0XHRqID0gd3JhcFsgMCBdO1xuXHRcdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0XHR0bXAgPSB0bXAubGFzdENoaWxkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHRcdC8vIHB1c2guYXBwbHkoXywgYXJyYXlsaWtlKSB0aHJvd3Mgb24gYW5jaWVudCBXZWJLaXRcblx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCBub2RlcywgdG1wLmNoaWxkTm9kZXMgKTtcblxuXHRcdFx0XHQvLyBSZW1lbWJlciB0aGUgdG9wLWxldmVsIGNvbnRhaW5lclxuXHRcdFx0XHR0bXAgPSBmcmFnbWVudC5maXJzdENoaWxkO1xuXG5cdFx0XHRcdC8vIEVuc3VyZSB0aGUgY3JlYXRlZCBub2RlcyBhcmUgb3JwaGFuZWQgKCMxMjM5Milcblx0XHRcdFx0dG1wLnRleHRDb250ZW50ID0gXCJcIjtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBSZW1vdmUgd3JhcHBlciBmcm9tIGZyYWdtZW50XG5cdGZyYWdtZW50LnRleHRDb250ZW50ID0gXCJcIjtcblxuXHRpID0gMDtcblx0d2hpbGUgKCAoIGVsZW0gPSBub2Rlc1sgaSsrIF0gKSApIHtcblxuXHRcdC8vIFNraXAgZWxlbWVudHMgYWxyZWFkeSBpbiB0aGUgY29udGV4dCBjb2xsZWN0aW9uICh0cmFjLTQwODcpXG5cdFx0aWYgKCBzZWxlY3Rpb24gJiYgalF1ZXJ5LmluQXJyYXkoIGVsZW0sIHNlbGVjdGlvbiApID4gLTEgKSB7XG5cdFx0XHRpZiAoIGlnbm9yZWQgKSB7XG5cdFx0XHRcdGlnbm9yZWQucHVzaCggZWxlbSApO1xuXHRcdFx0fVxuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0Y29udGFpbnMgPSBqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApO1xuXG5cdFx0Ly8gQXBwZW5kIHRvIGZyYWdtZW50XG5cdFx0dG1wID0gZ2V0QWxsKCBmcmFnbWVudC5hcHBlbmRDaGlsZCggZWxlbSApLCBcInNjcmlwdFwiICk7XG5cblx0XHQvLyBQcmVzZXJ2ZSBzY3JpcHQgZXZhbHVhdGlvbiBoaXN0b3J5XG5cdFx0aWYgKCBjb250YWlucyApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIHRtcCApO1xuXHRcdH1cblxuXHRcdC8vIENhcHR1cmUgZXhlY3V0YWJsZXNcblx0XHRpZiAoIHNjcmlwdHMgKSB7XG5cdFx0XHRqID0gMDtcblx0XHRcdHdoaWxlICggKCBlbGVtID0gdG1wWyBqKysgXSApICkge1xuXHRcdFx0XHRpZiAoIHJzY3JpcHRUeXBlLnRlc3QoIGVsZW0udHlwZSB8fCBcIlwiICkgKSB7XG5cdFx0XHRcdFx0c2NyaXB0cy5wdXNoKCBlbGVtICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZnJhZ21lbnQ7XG59XG5cblxuKCBmdW5jdGlvbigpIHtcblx0dmFyIGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpLFxuXHRcdGRpdiA9IGZyYWdtZW50LmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkgKSxcblx0XHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApO1xuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgNC4wIC0gNC4zIG9ubHlcblx0Ly8gQ2hlY2sgc3RhdGUgbG9zdCBpZiB0aGUgbmFtZSBpcyBzZXQgKCMxMTIxNylcblx0Ly8gU3VwcG9ydDogV2luZG93cyBXZWIgQXBwcyAoV1dBKVxuXHQvLyBgbmFtZWAgYW5kIGB0eXBlYCBtdXN0IHVzZSAuc2V0QXR0cmlidXRlIGZvciBXV0EgKCMxNDkwMSlcblx0aW5wdXQuc2V0QXR0cmlidXRlKCBcInR5cGVcIiwgXCJyYWRpb1wiICk7XG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJjaGVja2VkXCIsIFwiY2hlY2tlZFwiICk7XG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJuYW1lXCIsIFwidFwiICk7XG5cblx0ZGl2LmFwcGVuZENoaWxkKCBpbnB1dCApO1xuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjEgb25seVxuXHQvLyBPbGRlciBXZWJLaXQgZG9lc24ndCBjbG9uZSBjaGVja2VkIHN0YXRlIGNvcnJlY3RseSBpbiBmcmFnbWVudHNcblx0c3VwcG9ydC5jaGVja0Nsb25lID0gZGl2LmNsb25lTm9kZSggdHJ1ZSApLmNsb25lTm9kZSggdHJ1ZSApLmxhc3RDaGlsZC5jaGVja2VkO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuXHQvLyBNYWtlIHN1cmUgdGV4dGFyZWEgKGFuZCBjaGVja2JveCkgZGVmYXVsdFZhbHVlIGlzIHByb3Blcmx5IGNsb25lZFxuXHRkaXYuaW5uZXJIVE1MID0gXCI8dGV4dGFyZWE+eDwvdGV4dGFyZWE+XCI7XG5cdHN1cHBvcnQubm9DbG9uZUNoZWNrZWQgPSAhIWRpdi5jbG9uZU5vZGUoIHRydWUgKS5sYXN0Q2hpbGQuZGVmYXVsdFZhbHVlO1xufSApKCk7XG52YXIgZG9jdW1lbnRFbGVtZW50ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuXG5cblxudmFyXG5cdHJrZXlFdmVudCA9IC9ea2V5Lyxcblx0cm1vdXNlRXZlbnQgPSAvXig/Om1vdXNlfHBvaW50ZXJ8Y29udGV4dG1lbnV8ZHJhZ3xkcm9wKXxjbGljay8sXG5cdHJ0eXBlbmFtZXNwYWNlID0gL14oW14uXSopKD86XFwuKC4rKXwpLztcblxuZnVuY3Rpb24gcmV0dXJuVHJ1ZSgpIHtcblx0cmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHJldHVybkZhbHNlKCkge1xuXHRyZXR1cm4gZmFsc2U7XG59XG5cbi8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG4vLyBTZWUgIzEzMzkzIGZvciBtb3JlIGluZm9cbmZ1bmN0aW9uIHNhZmVBY3RpdmVFbGVtZW50KCkge1xuXHR0cnkge1xuXHRcdHJldHVybiBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuXHR9IGNhdGNoICggZXJyICkgeyB9XG59XG5cbmZ1bmN0aW9uIG9uKCBlbGVtLCB0eXBlcywgc2VsZWN0b3IsIGRhdGEsIGZuLCBvbmUgKSB7XG5cdHZhciBvcmlnRm4sIHR5cGU7XG5cblx0Ly8gVHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXG5cdGlmICggdHlwZW9mIHR5cGVzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0Ly8gKCB0eXBlcy1PYmplY3QsIHNlbGVjdG9yLCBkYXRhIClcblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcy1PYmplY3QsIGRhdGEgKVxuXHRcdFx0ZGF0YSA9IGRhdGEgfHwgc2VsZWN0b3I7XG5cdFx0XHRzZWxlY3RvciA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0Zm9yICggdHlwZSBpbiB0eXBlcyApIHtcblx0XHRcdG9uKCBlbGVtLCB0eXBlLCBzZWxlY3RvciwgZGF0YSwgdHlwZXNbIHR5cGUgXSwgb25lICk7XG5cdFx0fVxuXHRcdHJldHVybiBlbGVtO1xuXHR9XG5cblx0aWYgKCBkYXRhID09IG51bGwgJiYgZm4gPT0gbnVsbCApIHtcblxuXHRcdC8vICggdHlwZXMsIGZuIClcblx0XHRmbiA9IHNlbGVjdG9yO1xuXHRcdGRhdGEgPSBzZWxlY3RvciA9IHVuZGVmaW5lZDtcblx0fSBlbHNlIGlmICggZm4gPT0gbnVsbCApIHtcblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcywgc2VsZWN0b3IsIGZuIClcblx0XHRcdGZuID0gZGF0YTtcblx0XHRcdGRhdGEgPSB1bmRlZmluZWQ7XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gKCB0eXBlcywgZGF0YSwgZm4gKVxuXHRcdFx0Zm4gPSBkYXRhO1xuXHRcdFx0ZGF0YSA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHR9XG5cdGlmICggZm4gPT09IGZhbHNlICkge1xuXHRcdGZuID0gcmV0dXJuRmFsc2U7XG5cdH0gZWxzZSBpZiAoICFmbiApIHtcblx0XHRyZXR1cm4gZWxlbTtcblx0fVxuXG5cdGlmICggb25lID09PSAxICkge1xuXHRcdG9yaWdGbiA9IGZuO1xuXHRcdGZuID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHQvLyBDYW4gdXNlIGFuIGVtcHR5IHNldCwgc2luY2UgZXZlbnQgY29udGFpbnMgdGhlIGluZm9cblx0XHRcdGpRdWVyeSgpLm9mZiggZXZlbnQgKTtcblx0XHRcdHJldHVybiBvcmlnRm4uYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH07XG5cblx0XHQvLyBVc2Ugc2FtZSBndWlkIHNvIGNhbGxlciBjYW4gcmVtb3ZlIHVzaW5nIG9yaWdGblxuXHRcdGZuLmd1aWQgPSBvcmlnRm4uZ3VpZCB8fCAoIG9yaWdGbi5ndWlkID0galF1ZXJ5Lmd1aWQrKyApO1xuXHR9XG5cdHJldHVybiBlbGVtLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdGpRdWVyeS5ldmVudC5hZGQoIHRoaXMsIHR5cGVzLCBmbiwgZGF0YSwgc2VsZWN0b3IgKTtcblx0fSApO1xufVxuXG4vKlxuICogSGVscGVyIGZ1bmN0aW9ucyBmb3IgbWFuYWdpbmcgZXZlbnRzIC0tIG5vdCBwYXJ0IG9mIHRoZSBwdWJsaWMgaW50ZXJmYWNlLlxuICogUHJvcHMgdG8gRGVhbiBFZHdhcmRzJyBhZGRFdmVudCBsaWJyYXJ5IGZvciBtYW55IG9mIHRoZSBpZGVhcy5cbiAqL1xualF1ZXJ5LmV2ZW50ID0ge1xuXG5cdGdsb2JhbDoge30sXG5cblx0YWRkOiBmdW5jdGlvbiggZWxlbSwgdHlwZXMsIGhhbmRsZXIsIGRhdGEsIHNlbGVjdG9yICkge1xuXG5cdFx0dmFyIGhhbmRsZU9iakluLCBldmVudEhhbmRsZSwgdG1wLFxuXHRcdFx0ZXZlbnRzLCB0LCBoYW5kbGVPYmosXG5cdFx0XHRzcGVjaWFsLCBoYW5kbGVycywgdHlwZSwgbmFtZXNwYWNlcywgb3JpZ1R5cGUsXG5cdFx0XHRlbGVtRGF0YSA9IGRhdGFQcml2LmdldCggZWxlbSApO1xuXG5cdFx0Ly8gRG9uJ3QgYXR0YWNoIGV2ZW50cyB0byBub0RhdGEgb3IgdGV4dC9jb21tZW50IG5vZGVzIChidXQgYWxsb3cgcGxhaW4gb2JqZWN0cylcblx0XHRpZiAoICFlbGVtRGF0YSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBDYWxsZXIgY2FuIHBhc3MgaW4gYW4gb2JqZWN0IG9mIGN1c3RvbSBkYXRhIGluIGxpZXUgb2YgdGhlIGhhbmRsZXJcblx0XHRpZiAoIGhhbmRsZXIuaGFuZGxlciApIHtcblx0XHRcdGhhbmRsZU9iakluID0gaGFuZGxlcjtcblx0XHRcdGhhbmRsZXIgPSBoYW5kbGVPYmpJbi5oYW5kbGVyO1xuXHRcdFx0c2VsZWN0b3IgPSBoYW5kbGVPYmpJbi5zZWxlY3Rvcjtcblx0XHR9XG5cblx0XHQvLyBFbnN1cmUgdGhhdCBpbnZhbGlkIHNlbGVjdG9ycyB0aHJvdyBleGNlcHRpb25zIGF0IGF0dGFjaCB0aW1lXG5cdFx0Ly8gRXZhbHVhdGUgYWdhaW5zdCBkb2N1bWVudEVsZW1lbnQgaW4gY2FzZSBlbGVtIGlzIGEgbm9uLWVsZW1lbnQgbm9kZSAoZS5nLiwgZG9jdW1lbnQpXG5cdFx0aWYgKCBzZWxlY3RvciApIHtcblx0XHRcdGpRdWVyeS5maW5kLm1hdGNoZXNTZWxlY3RvciggZG9jdW1lbnRFbGVtZW50LCBzZWxlY3RvciApO1xuXHRcdH1cblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBoYW5kbGVyIGhhcyBhIHVuaXF1ZSBJRCwgdXNlZCB0byBmaW5kL3JlbW92ZSBpdCBsYXRlclxuXHRcdGlmICggIWhhbmRsZXIuZ3VpZCApIHtcblx0XHRcdGhhbmRsZXIuZ3VpZCA9IGpRdWVyeS5ndWlkKys7XG5cdFx0fVxuXG5cdFx0Ly8gSW5pdCB0aGUgZWxlbWVudCdzIGV2ZW50IHN0cnVjdHVyZSBhbmQgbWFpbiBoYW5kbGVyLCBpZiB0aGlzIGlzIHRoZSBmaXJzdFxuXHRcdGlmICggISggZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzICkgKSB7XG5cdFx0XHRldmVudHMgPSBlbGVtRGF0YS5ldmVudHMgPSB7fTtcblx0XHR9XG5cdFx0aWYgKCAhKCBldmVudEhhbmRsZSA9IGVsZW1EYXRhLmhhbmRsZSApICkge1xuXHRcdFx0ZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgPSBmdW5jdGlvbiggZSApIHtcblxuXHRcdFx0XHQvLyBEaXNjYXJkIHRoZSBzZWNvbmQgZXZlbnQgb2YgYSBqUXVlcnkuZXZlbnQudHJpZ2dlcigpIGFuZFxuXHRcdFx0XHQvLyB3aGVuIGFuIGV2ZW50IGlzIGNhbGxlZCBhZnRlciBhIHBhZ2UgaGFzIHVubG9hZGVkXG5cdFx0XHRcdHJldHVybiB0eXBlb2YgalF1ZXJ5ICE9PSBcInVuZGVmaW5lZFwiICYmIGpRdWVyeS5ldmVudC50cmlnZ2VyZWQgIT09IGUudHlwZSA/XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LmRpc3BhdGNoLmFwcGx5KCBlbGVtLCBhcmd1bWVudHMgKSA6IHVuZGVmaW5lZDtcblx0XHRcdH07XG5cdFx0fVxuXG5cdFx0Ly8gSGFuZGxlIG11bHRpcGxlIGV2ZW50cyBzZXBhcmF0ZWQgYnkgYSBzcGFjZVxuXHRcdHR5cGVzID0gKCB0eXBlcyB8fCBcIlwiICkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblx0XHR0ID0gdHlwZXMubGVuZ3RoO1xuXHRcdHdoaWxlICggdC0tICkge1xuXHRcdFx0dG1wID0gcnR5cGVuYW1lc3BhY2UuZXhlYyggdHlwZXNbIHQgXSApIHx8IFtdO1xuXHRcdFx0dHlwZSA9IG9yaWdUeXBlID0gdG1wWyAxIF07XG5cdFx0XHRuYW1lc3BhY2VzID0gKCB0bXBbIDIgXSB8fCBcIlwiICkuc3BsaXQoIFwiLlwiICkuc29ydCgpO1xuXG5cdFx0XHQvLyBUaGVyZSAqbXVzdCogYmUgYSB0eXBlLCBubyBhdHRhY2hpbmcgbmFtZXNwYWNlLW9ubHkgaGFuZGxlcnNcblx0XHRcdGlmICggIXR5cGUgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBldmVudCBjaGFuZ2VzIGl0cyB0eXBlLCB1c2UgdGhlIHNwZWNpYWwgZXZlbnQgaGFuZGxlcnMgZm9yIHRoZSBjaGFuZ2VkIHR5cGVcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXG5cdFx0XHQvLyBJZiBzZWxlY3RvciBkZWZpbmVkLCBkZXRlcm1pbmUgc3BlY2lhbCBldmVudCBhcGkgdHlwZSwgb3RoZXJ3aXNlIGdpdmVuIHR5cGVcblx0XHRcdHR5cGUgPSAoIHNlbGVjdG9yID8gc3BlY2lhbC5kZWxlZ2F0ZVR5cGUgOiBzcGVjaWFsLmJpbmRUeXBlICkgfHwgdHlwZTtcblxuXHRcdFx0Ly8gVXBkYXRlIHNwZWNpYWwgYmFzZWQgb24gbmV3bHkgcmVzZXQgdHlwZVxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cblx0XHRcdC8vIGhhbmRsZU9iaiBpcyBwYXNzZWQgdG8gYWxsIGV2ZW50IGhhbmRsZXJzXG5cdFx0XHRoYW5kbGVPYmogPSBqUXVlcnkuZXh0ZW5kKCB7XG5cdFx0XHRcdHR5cGU6IHR5cGUsXG5cdFx0XHRcdG9yaWdUeXBlOiBvcmlnVHlwZSxcblx0XHRcdFx0ZGF0YTogZGF0YSxcblx0XHRcdFx0aGFuZGxlcjogaGFuZGxlcixcblx0XHRcdFx0Z3VpZDogaGFuZGxlci5ndWlkLFxuXHRcdFx0XHRzZWxlY3Rvcjogc2VsZWN0b3IsXG5cdFx0XHRcdG5lZWRzQ29udGV4dDogc2VsZWN0b3IgJiYgalF1ZXJ5LmV4cHIubWF0Y2gubmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICksXG5cdFx0XHRcdG5hbWVzcGFjZTogbmFtZXNwYWNlcy5qb2luKCBcIi5cIiApXG5cdFx0XHR9LCBoYW5kbGVPYmpJbiApO1xuXG5cdFx0XHQvLyBJbml0IHRoZSBldmVudCBoYW5kbGVyIHF1ZXVlIGlmIHdlJ3JlIHRoZSBmaXJzdFxuXHRcdFx0aWYgKCAhKCBoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdICkgKSB7XG5cdFx0XHRcdGhhbmRsZXJzID0gZXZlbnRzWyB0eXBlIF0gPSBbXTtcblx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudCA9IDA7XG5cblx0XHRcdFx0Ly8gT25seSB1c2UgYWRkRXZlbnRMaXN0ZW5lciBpZiB0aGUgc3BlY2lhbCBldmVudHMgaGFuZGxlciByZXR1cm5zIGZhbHNlXG5cdFx0XHRcdGlmICggIXNwZWNpYWwuc2V0dXAgfHxcblx0XHRcdFx0XHRzcGVjaWFsLnNldHVwLmNhbGwoIGVsZW0sIGRhdGEsIG5hbWVzcGFjZXMsIGV2ZW50SGFuZGxlICkgPT09IGZhbHNlICkge1xuXG5cdFx0XHRcdFx0aWYgKCBlbGVtLmFkZEV2ZW50TGlzdGVuZXIgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLmFkZEV2ZW50TGlzdGVuZXIoIHR5cGUsIGV2ZW50SGFuZGxlICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggc3BlY2lhbC5hZGQgKSB7XG5cdFx0XHRcdHNwZWNpYWwuYWRkLmNhbGwoIGVsZW0sIGhhbmRsZU9iaiApO1xuXG5cdFx0XHRcdGlmICggIWhhbmRsZU9iai5oYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIuZ3VpZCA9IGhhbmRsZXIuZ3VpZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgdG8gdGhlIGVsZW1lbnQncyBoYW5kbGVyIGxpc3QsIGRlbGVnYXRlcyBpbiBmcm9udFxuXHRcdFx0aWYgKCBzZWxlY3RvciApIHtcblx0XHRcdFx0aGFuZGxlcnMuc3BsaWNlKCBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50KyssIDAsIGhhbmRsZU9iaiApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEtlZXAgdHJhY2sgb2Ygd2hpY2ggZXZlbnRzIGhhdmUgZXZlciBiZWVuIHVzZWQsIGZvciBldmVudCBvcHRpbWl6YXRpb25cblx0XHRcdGpRdWVyeS5ldmVudC5nbG9iYWxbIHR5cGUgXSA9IHRydWU7XG5cdFx0fVxuXG5cdH0sXG5cblx0Ly8gRGV0YWNoIGFuIGV2ZW50IG9yIHNldCBvZiBldmVudHMgZnJvbSBhbiBlbGVtZW50XG5cdHJlbW92ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBzZWxlY3RvciwgbWFwcGVkVHlwZXMgKSB7XG5cblx0XHR2YXIgaiwgb3JpZ0NvdW50LCB0bXAsXG5cdFx0XHRldmVudHMsIHQsIGhhbmRsZU9iaixcblx0XHRcdHNwZWNpYWwsIGhhbmRsZXJzLCB0eXBlLCBuYW1lc3BhY2VzLCBvcmlnVHlwZSxcblx0XHRcdGVsZW1EYXRhID0gZGF0YVByaXYuaGFzRGF0YSggZWxlbSApICYmIGRhdGFQcml2LmdldCggZWxlbSApO1xuXG5cdFx0aWYgKCAhZWxlbURhdGEgfHwgISggZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gT25jZSBmb3IgZWFjaCB0eXBlLm5hbWVzcGFjZSBpbiB0eXBlczsgdHlwZSBtYXkgYmUgb21pdHRlZFxuXHRcdHR5cGVzID0gKCB0eXBlcyB8fCBcIlwiICkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblx0XHR0ID0gdHlwZXMubGVuZ3RoO1xuXHRcdHdoaWxlICggdC0tICkge1xuXHRcdFx0dG1wID0gcnR5cGVuYW1lc3BhY2UuZXhlYyggdHlwZXNbIHQgXSApIHx8IFtdO1xuXHRcdFx0dHlwZSA9IG9yaWdUeXBlID0gdG1wWyAxIF07XG5cdFx0XHRuYW1lc3BhY2VzID0gKCB0bXBbIDIgXSB8fCBcIlwiICkuc3BsaXQoIFwiLlwiICkuc29ydCgpO1xuXG5cdFx0XHQvLyBVbmJpbmQgYWxsIGV2ZW50cyAob24gdGhpcyBuYW1lc3BhY2UsIGlmIHByb3ZpZGVkKSBmb3IgdGhlIGVsZW1lbnRcblx0XHRcdGlmICggIXR5cGUgKSB7XG5cdFx0XHRcdGZvciAoIHR5cGUgaW4gZXZlbnRzICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIGVsZW0sIHR5cGUgKyB0eXBlc1sgdCBdLCBoYW5kbGVyLCBzZWxlY3RvciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblx0XHRcdHR5cGUgPSAoIHNlbGVjdG9yID8gc3BlY2lhbC5kZWxlZ2F0ZVR5cGUgOiBzcGVjaWFsLmJpbmRUeXBlICkgfHwgdHlwZTtcblx0XHRcdGhhbmRsZXJzID0gZXZlbnRzWyB0eXBlIF0gfHwgW107XG5cdFx0XHR0bXAgPSB0bXBbIDIgXSAmJlxuXHRcdFx0XHRuZXcgUmVnRXhwKCBcIihefFxcXFwuKVwiICsgbmFtZXNwYWNlcy5qb2luKCBcIlxcXFwuKD86LipcXFxcLnwpXCIgKSArIFwiKFxcXFwufCQpXCIgKTtcblxuXHRcdFx0Ly8gUmVtb3ZlIG1hdGNoaW5nIGV2ZW50c1xuXHRcdFx0b3JpZ0NvdW50ID0gaiA9IGhhbmRsZXJzLmxlbmd0aDtcblx0XHRcdHdoaWxlICggai0tICkge1xuXHRcdFx0XHRoYW5kbGVPYmogPSBoYW5kbGVyc1sgaiBdO1xuXG5cdFx0XHRcdGlmICggKCBtYXBwZWRUeXBlcyB8fCBvcmlnVHlwZSA9PT0gaGFuZGxlT2JqLm9yaWdUeXBlICkgJiZcblx0XHRcdFx0XHQoICFoYW5kbGVyIHx8IGhhbmRsZXIuZ3VpZCA9PT0gaGFuZGxlT2JqLmd1aWQgKSAmJlxuXHRcdFx0XHRcdCggIXRtcCB8fCB0bXAudGVzdCggaGFuZGxlT2JqLm5hbWVzcGFjZSApICkgJiZcblx0XHRcdFx0XHQoICFzZWxlY3RvciB8fCBzZWxlY3RvciA9PT0gaGFuZGxlT2JqLnNlbGVjdG9yIHx8XG5cdFx0XHRcdFx0XHRzZWxlY3RvciA9PT0gXCIqKlwiICYmIGhhbmRsZU9iai5zZWxlY3RvciApICkge1xuXHRcdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaiwgMSApO1xuXG5cdFx0XHRcdFx0aWYgKCBoYW5kbGVPYmouc2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LS07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggc3BlY2lhbC5yZW1vdmUgKSB7XG5cdFx0XHRcdFx0XHRzcGVjaWFsLnJlbW92ZS5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVtb3ZlIGdlbmVyaWMgZXZlbnQgaGFuZGxlciBpZiB3ZSByZW1vdmVkIHNvbWV0aGluZyBhbmQgbm8gbW9yZSBoYW5kbGVycyBleGlzdFxuXHRcdFx0Ly8gKGF2b2lkcyBwb3RlbnRpYWwgZm9yIGVuZGxlc3MgcmVjdXJzaW9uIGR1cmluZyByZW1vdmFsIG9mIHNwZWNpYWwgZXZlbnQgaGFuZGxlcnMpXG5cdFx0XHRpZiAoIG9yaWdDb3VudCAmJiAhaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnRlYXJkb3duIHx8XG5cdFx0XHRcdFx0c3BlY2lhbC50ZWFyZG93bi5jYWxsKCBlbGVtLCBuYW1lc3BhY2VzLCBlbGVtRGF0YS5oYW5kbGUgKSA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdFx0XHRqUXVlcnkucmVtb3ZlRXZlbnQoIGVsZW0sIHR5cGUsIGVsZW1EYXRhLmhhbmRsZSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZGVsZXRlIGV2ZW50c1sgdHlwZSBdO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFJlbW92ZSBkYXRhIGFuZCB0aGUgZXhwYW5kbyBpZiBpdCdzIG5vIGxvbmdlciB1c2VkXG5cdFx0aWYgKCBqUXVlcnkuaXNFbXB0eU9iamVjdCggZXZlbnRzICkgKSB7XG5cdFx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIFwiaGFuZGxlIGV2ZW50c1wiICk7XG5cdFx0fVxuXHR9LFxuXG5cdGRpc3BhdGNoOiBmdW5jdGlvbiggbmF0aXZlRXZlbnQgKSB7XG5cblx0XHQvLyBNYWtlIGEgd3JpdGFibGUgalF1ZXJ5LkV2ZW50IGZyb20gdGhlIG5hdGl2ZSBldmVudCBvYmplY3Rcblx0XHR2YXIgZXZlbnQgPSBqUXVlcnkuZXZlbnQuZml4KCBuYXRpdmVFdmVudCApO1xuXG5cdFx0dmFyIGksIGosIHJldCwgbWF0Y2hlZCwgaGFuZGxlT2JqLCBoYW5kbGVyUXVldWUsXG5cdFx0XHRhcmdzID0gbmV3IEFycmF5KCBhcmd1bWVudHMubGVuZ3RoICksXG5cdFx0XHRoYW5kbGVycyA9ICggZGF0YVByaXYuZ2V0KCB0aGlzLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdIHx8IFtdLFxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyBldmVudC50eXBlIF0gfHwge307XG5cblx0XHQvLyBVc2UgdGhlIGZpeC1lZCBqUXVlcnkuRXZlbnQgcmF0aGVyIHRoYW4gdGhlIChyZWFkLW9ubHkpIG5hdGl2ZSBldmVudFxuXHRcdGFyZ3NbIDAgXSA9IGV2ZW50O1xuXG5cdFx0Zm9yICggaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRhcmdzWyBpIF0gPSBhcmd1bWVudHNbIGkgXTtcblx0XHR9XG5cblx0XHRldmVudC5kZWxlZ2F0ZVRhcmdldCA9IHRoaXM7XG5cblx0XHQvLyBDYWxsIHRoZSBwcmVEaXNwYXRjaCBob29rIGZvciB0aGUgbWFwcGVkIHR5cGUsIGFuZCBsZXQgaXQgYmFpbCBpZiBkZXNpcmVkXG5cdFx0aWYgKCBzcGVjaWFsLnByZURpc3BhdGNoICYmIHNwZWNpYWwucHJlRGlzcGF0Y2guY2FsbCggdGhpcywgZXZlbnQgKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gRGV0ZXJtaW5lIGhhbmRsZXJzXG5cdFx0aGFuZGxlclF1ZXVlID0galF1ZXJ5LmV2ZW50LmhhbmRsZXJzLmNhbGwoIHRoaXMsIGV2ZW50LCBoYW5kbGVycyApO1xuXG5cdFx0Ly8gUnVuIGRlbGVnYXRlcyBmaXJzdDsgdGhleSBtYXkgd2FudCB0byBzdG9wIHByb3BhZ2F0aW9uIGJlbmVhdGggdXNcblx0XHRpID0gMDtcblx0XHR3aGlsZSAoICggbWF0Y2hlZCA9IGhhbmRsZXJRdWV1ZVsgaSsrIF0gKSAmJiAhZXZlbnQuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSApIHtcblx0XHRcdGV2ZW50LmN1cnJlbnRUYXJnZXQgPSBtYXRjaGVkLmVsZW07XG5cblx0XHRcdGogPSAwO1xuXHRcdFx0d2hpbGUgKCAoIGhhbmRsZU9iaiA9IG1hdGNoZWQuaGFuZGxlcnNbIGorKyBdICkgJiZcblx0XHRcdFx0IWV2ZW50LmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdFx0Ly8gVHJpZ2dlcmVkIGV2ZW50IG11c3QgZWl0aGVyIDEpIGhhdmUgbm8gbmFtZXNwYWNlLCBvciAyKSBoYXZlIG5hbWVzcGFjZShzKVxuXHRcdFx0XHQvLyBhIHN1YnNldCBvciBlcXVhbCB0byB0aG9zZSBpbiB0aGUgYm91bmQgZXZlbnQgKGJvdGggY2FuIGhhdmUgbm8gbmFtZXNwYWNlKS5cblx0XHRcdFx0aWYgKCAhZXZlbnQucm5hbWVzcGFjZSB8fCBldmVudC5ybmFtZXNwYWNlLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApIHtcblxuXHRcdFx0XHRcdGV2ZW50LmhhbmRsZU9iaiA9IGhhbmRsZU9iajtcblx0XHRcdFx0XHRldmVudC5kYXRhID0gaGFuZGxlT2JqLmRhdGE7XG5cblx0XHRcdFx0XHRyZXQgPSAoICggalF1ZXJ5LmV2ZW50LnNwZWNpYWxbIGhhbmRsZU9iai5vcmlnVHlwZSBdIHx8IHt9ICkuaGFuZGxlIHx8XG5cdFx0XHRcdFx0XHRoYW5kbGVPYmouaGFuZGxlciApLmFwcGx5KCBtYXRjaGVkLmVsZW0sIGFyZ3MgKTtcblxuXHRcdFx0XHRcdGlmICggcmV0ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0XHRpZiAoICggZXZlbnQucmVzdWx0ID0gcmV0ICkgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDYWxsIHRoZSBwb3N0RGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlXG5cdFx0aWYgKCBzcGVjaWFsLnBvc3REaXNwYXRjaCApIHtcblx0XHRcdHNwZWNpYWwucG9zdERpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHRoYW5kbGVyczogZnVuY3Rpb24oIGV2ZW50LCBoYW5kbGVycyApIHtcblx0XHR2YXIgaSwgaGFuZGxlT2JqLCBzZWwsIG1hdGNoZWRIYW5kbGVycywgbWF0Y2hlZFNlbGVjdG9ycyxcblx0XHRcdGhhbmRsZXJRdWV1ZSA9IFtdLFxuXHRcdFx0ZGVsZWdhdGVDb3VudCA9IGhhbmRsZXJzLmRlbGVnYXRlQ291bnQsXG5cdFx0XHRjdXIgPSBldmVudC50YXJnZXQ7XG5cblx0XHQvLyBGaW5kIGRlbGVnYXRlIGhhbmRsZXJzXG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50ICYmXG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OVxuXHRcdFx0Ly8gQmxhY2staG9sZSBTVkcgPHVzZT4gaW5zdGFuY2UgdHJlZXMgKHRyYWMtMTMxODApXG5cdFx0XHRjdXIubm9kZVR5cGUgJiZcblxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCA8PTQyXG5cdFx0XHQvLyBTdXBwcmVzcyBzcGVjLXZpb2xhdGluZyBjbGlja3MgaW5kaWNhdGluZyBhIG5vbi1wcmltYXJ5IHBvaW50ZXIgYnV0dG9uICh0cmFjLTM4NjEpXG5cdFx0XHQvLyBodHRwczovL3d3dy53My5vcmcvVFIvRE9NLUxldmVsLTMtRXZlbnRzLyNldmVudC10eXBlLWNsaWNrXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSAxMSBvbmx5XG5cdFx0XHQvLyAuLi5idXQgbm90IGFycm93IGtleSBcImNsaWNrc1wiIG9mIHJhZGlvIGlucHV0cywgd2hpY2ggY2FuIGhhdmUgYGJ1dHRvbmAgLTEgKGdoLTIzNDMpXG5cdFx0XHQhKCBldmVudC50eXBlID09PSBcImNsaWNrXCIgJiYgZXZlbnQuYnV0dG9uID49IDEgKSApIHtcblxuXHRcdFx0Zm9yICggOyBjdXIgIT09IHRoaXM7IGN1ciA9IGN1ci5wYXJlbnROb2RlIHx8IHRoaXMgKSB7XG5cblx0XHRcdFx0Ly8gRG9uJ3QgY2hlY2sgbm9uLWVsZW1lbnRzICgjMTMyMDgpXG5cdFx0XHRcdC8vIERvbid0IHByb2Nlc3MgY2xpY2tzIG9uIGRpc2FibGVkIGVsZW1lbnRzICgjNjkxMSwgIzgxNjUsICMxMTM4MiwgIzExNzY0KVxuXHRcdFx0XHRpZiAoIGN1ci5ub2RlVHlwZSA9PT0gMSAmJiAhKCBldmVudC50eXBlID09PSBcImNsaWNrXCIgJiYgY3VyLmRpc2FibGVkID09PSB0cnVlICkgKSB7XG5cdFx0XHRcdFx0bWF0Y2hlZEhhbmRsZXJzID0gW107XG5cdFx0XHRcdFx0bWF0Y2hlZFNlbGVjdG9ycyA9IHt9O1xuXHRcdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgZGVsZWdhdGVDb3VudDsgaSsrICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGkgXTtcblxuXHRcdFx0XHRcdFx0Ly8gRG9uJ3QgY29uZmxpY3Qgd2l0aCBPYmplY3QucHJvdG90eXBlIHByb3BlcnRpZXMgKCMxMzIwMylcblx0XHRcdFx0XHRcdHNlbCA9IGhhbmRsZU9iai5zZWxlY3RvciArIFwiIFwiO1xuXG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0XHRcdG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdID0gaGFuZGxlT2JqLm5lZWRzQ29udGV4dCA/XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5KCBzZWwsIHRoaXMgKS5pbmRleCggY3VyICkgPiAtMSA6XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmZpbmQoIHNlbCwgdGhpcywgbnVsbCwgWyBjdXIgXSApLmxlbmd0aDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmICggbWF0Y2hlZFNlbGVjdG9yc1sgc2VsIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG1hdGNoZWRIYW5kbGVycy5wdXNoKCBoYW5kbGVPYmogKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKCBtYXRjaGVkSGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goIHsgZWxlbTogY3VyLCBoYW5kbGVyczogbWF0Y2hlZEhhbmRsZXJzIH0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBBZGQgdGhlIHJlbWFpbmluZyAoZGlyZWN0bHktYm91bmQpIGhhbmRsZXJzXG5cdFx0Y3VyID0gdGhpcztcblx0XHRpZiAoIGRlbGVnYXRlQ291bnQgPCBoYW5kbGVycy5sZW5ndGggKSB7XG5cdFx0XHRoYW5kbGVyUXVldWUucHVzaCggeyBlbGVtOiBjdXIsIGhhbmRsZXJzOiBoYW5kbGVycy5zbGljZSggZGVsZWdhdGVDb3VudCApIH0gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gaGFuZGxlclF1ZXVlO1xuXHR9LFxuXG5cdGFkZFByb3A6IGZ1bmN0aW9uKCBuYW1lLCBob29rICkge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSggalF1ZXJ5LkV2ZW50LnByb3RvdHlwZSwgbmFtZSwge1xuXHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcblx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblxuXHRcdFx0Z2V0OiBqUXVlcnkuaXNGdW5jdGlvbiggaG9vayApID9cblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBob29rKCB0aGlzLm9yaWdpbmFsRXZlbnQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gOlxuXHRcdFx0XHRmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRpZiAoIHRoaXMub3JpZ2luYWxFdmVudCApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRoaXMub3JpZ2luYWxFdmVudFsgbmFtZSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblxuXHRcdFx0c2V0OiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSggdGhpcywgbmFtZSwge1xuXHRcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRcdFx0Y29uZmlndXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHdyaXRhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHZhbHVlOiB2YWx1ZVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGZpeDogZnVuY3Rpb24oIG9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0cmV0dXJuIG9yaWdpbmFsRXZlbnRbIGpRdWVyeS5leHBhbmRvIF0gP1xuXHRcdFx0b3JpZ2luYWxFdmVudCA6XG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCBvcmlnaW5hbEV2ZW50ICk7XG5cdH0sXG5cblx0c3BlY2lhbDoge1xuXHRcdGxvYWQ6IHtcblxuXHRcdFx0Ly8gUHJldmVudCB0cmlnZ2VyZWQgaW1hZ2UubG9hZCBldmVudHMgZnJvbSBidWJibGluZyB0byB3aW5kb3cubG9hZFxuXHRcdFx0bm9CdWJibGU6IHRydWVcblx0XHR9LFxuXHRcdGZvY3VzOiB7XG5cblx0XHRcdC8vIEZpcmUgbmF0aXZlIGV2ZW50IGlmIHBvc3NpYmxlIHNvIGJsdXIvZm9jdXMgc2VxdWVuY2UgaXMgY29ycmVjdFxuXHRcdFx0dHJpZ2dlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdGhpcyAhPT0gc2FmZUFjdGl2ZUVsZW1lbnQoKSAmJiB0aGlzLmZvY3VzICkge1xuXHRcdFx0XHRcdHRoaXMuZm9jdXMoKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRkZWxlZ2F0ZVR5cGU6IFwiZm9jdXNpblwiXG5cdFx0fSxcblx0XHRibHVyOiB7XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzID09PSBzYWZlQWN0aXZlRWxlbWVudCgpICYmIHRoaXMuYmx1ciApIHtcblx0XHRcdFx0XHR0aGlzLmJsdXIoKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRkZWxlZ2F0ZVR5cGU6IFwiZm9jdXNvdXRcIlxuXHRcdH0sXG5cdFx0Y2xpY2s6IHtcblxuXHRcdFx0Ly8gRm9yIGNoZWNrYm94LCBmaXJlIG5hdGl2ZSBldmVudCBzbyBjaGVja2VkIHN0YXRlIHdpbGwgYmUgcmlnaHRcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMudHlwZSA9PT0gXCJjaGVja2JveFwiICYmIHRoaXMuY2xpY2sgJiYgbm9kZU5hbWUoIHRoaXMsIFwiaW5wdXRcIiApICkge1xuXHRcdFx0XHRcdHRoaXMuY2xpY2soKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cblx0XHRcdC8vIEZvciBjcm9zcy1icm93c2VyIGNvbnNpc3RlbmN5LCBkb24ndCBmaXJlIG5hdGl2ZSAuY2xpY2soKSBvbiBsaW5rc1xuXHRcdFx0X2RlZmF1bHQ6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0cmV0dXJuIG5vZGVOYW1lKCBldmVudC50YXJnZXQsIFwiYVwiICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdGJlZm9yZXVubG9hZDoge1xuXHRcdFx0cG9zdERpc3BhdGNoOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCAyMCtcblx0XHRcdFx0Ly8gRmlyZWZveCBkb2Vzbid0IGFsZXJ0IGlmIHRoZSByZXR1cm5WYWx1ZSBmaWVsZCBpcyBub3Qgc2V0LlxuXHRcdFx0XHRpZiAoIGV2ZW50LnJlc3VsdCAhPT0gdW5kZWZpbmVkICYmIGV2ZW50Lm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0ZXZlbnQub3JpZ2luYWxFdmVudC5yZXR1cm5WYWx1ZSA9IGV2ZW50LnJlc3VsdDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGhhbmRsZSApIHtcblxuXHQvLyBUaGlzIFwiaWZcIiBpcyBuZWVkZWQgZm9yIHBsYWluIG9iamVjdHNcblx0aWYgKCBlbGVtLnJlbW92ZUV2ZW50TGlzdGVuZXIgKSB7XG5cdFx0ZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyKCB0eXBlLCBoYW5kbGUgKTtcblx0fVxufTtcblxualF1ZXJ5LkV2ZW50ID0gZnVuY3Rpb24oIHNyYywgcHJvcHMgKSB7XG5cblx0Ly8gQWxsb3cgaW5zdGFudGlhdGlvbiB3aXRob3V0IHRoZSAnbmV3JyBrZXl3b3JkXG5cdGlmICggISggdGhpcyBpbnN0YW5jZW9mIGpRdWVyeS5FdmVudCApICkge1xuXHRcdHJldHVybiBuZXcgalF1ZXJ5LkV2ZW50KCBzcmMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBFdmVudCBvYmplY3Rcblx0aWYgKCBzcmMgJiYgc3JjLnR5cGUgKSB7XG5cdFx0dGhpcy5vcmlnaW5hbEV2ZW50ID0gc3JjO1xuXHRcdHRoaXMudHlwZSA9IHNyYy50eXBlO1xuXG5cdFx0Ly8gRXZlbnRzIGJ1YmJsaW5nIHVwIHRoZSBkb2N1bWVudCBtYXkgaGF2ZSBiZWVuIG1hcmtlZCBhcyBwcmV2ZW50ZWRcblx0XHQvLyBieSBhIGhhbmRsZXIgbG93ZXIgZG93biB0aGUgdHJlZTsgcmVmbGVjdCB0aGUgY29ycmVjdCB2YWx1ZS5cblx0XHR0aGlzLmlzRGVmYXVsdFByZXZlbnRlZCA9IHNyYy5kZWZhdWx0UHJldmVudGVkIHx8XG5cdFx0XHRcdHNyYy5kZWZhdWx0UHJldmVudGVkID09PSB1bmRlZmluZWQgJiZcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9Mi4zIG9ubHlcblx0XHRcdFx0c3JjLnJldHVyblZhbHVlID09PSBmYWxzZSA/XG5cdFx0XHRyZXR1cm5UcnVlIDpcblx0XHRcdHJldHVybkZhbHNlO1xuXG5cdFx0Ly8gQ3JlYXRlIHRhcmdldCBwcm9wZXJ0aWVzXG5cdFx0Ly8gU3VwcG9ydDogU2FmYXJpIDw9NiAtIDcgb25seVxuXHRcdC8vIFRhcmdldCBzaG91bGQgbm90IGJlIGEgdGV4dCBub2RlICgjNTA0LCAjMTMxNDMpXG5cdFx0dGhpcy50YXJnZXQgPSAoIHNyYy50YXJnZXQgJiYgc3JjLnRhcmdldC5ub2RlVHlwZSA9PT0gMyApID9cblx0XHRcdHNyYy50YXJnZXQucGFyZW50Tm9kZSA6XG5cdFx0XHRzcmMudGFyZ2V0O1xuXG5cdFx0dGhpcy5jdXJyZW50VGFyZ2V0ID0gc3JjLmN1cnJlbnRUYXJnZXQ7XG5cdFx0dGhpcy5yZWxhdGVkVGFyZ2V0ID0gc3JjLnJlbGF0ZWRUYXJnZXQ7XG5cblx0Ly8gRXZlbnQgdHlwZVxuXHR9IGVsc2Uge1xuXHRcdHRoaXMudHlwZSA9IHNyYztcblx0fVxuXG5cdC8vIFB1dCBleHBsaWNpdGx5IHByb3ZpZGVkIHByb3BlcnRpZXMgb250byB0aGUgZXZlbnQgb2JqZWN0XG5cdGlmICggcHJvcHMgKSB7XG5cdFx0alF1ZXJ5LmV4dGVuZCggdGhpcywgcHJvcHMgKTtcblx0fVxuXG5cdC8vIENyZWF0ZSBhIHRpbWVzdGFtcCBpZiBpbmNvbWluZyBldmVudCBkb2Vzbid0IGhhdmUgb25lXG5cdHRoaXMudGltZVN0YW1wID0gc3JjICYmIHNyYy50aW1lU3RhbXAgfHwgalF1ZXJ5Lm5vdygpO1xuXG5cdC8vIE1hcmsgaXQgYXMgZml4ZWRcblx0dGhpc1sgalF1ZXJ5LmV4cGFuZG8gXSA9IHRydWU7XG59O1xuXG4vLyBqUXVlcnkuRXZlbnQgaXMgYmFzZWQgb24gRE9NMyBFdmVudHMgYXMgc3BlY2lmaWVkIGJ5IHRoZSBFQ01BU2NyaXB0IExhbmd1YWdlIEJpbmRpbmdcbi8vIGh0dHBzOi8vd3d3LnczLm9yZy9UUi8yMDAzL1dELURPTS1MZXZlbC0zLUV2ZW50cy0yMDAzMDMzMS9lY21hLXNjcmlwdC1iaW5kaW5nLmh0bWxcbmpRdWVyeS5FdmVudC5wcm90b3R5cGUgPSB7XG5cdGNvbnN0cnVjdG9yOiBqUXVlcnkuRXZlbnQsXG5cdGlzRGVmYXVsdFByZXZlbnRlZDogcmV0dXJuRmFsc2UsXG5cdGlzUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ6IHJldHVybkZhbHNlLFxuXHRpc1NpbXVsYXRlZDogZmFsc2UsXG5cblx0cHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0dGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSByZXR1cm5UcnVlO1xuXG5cdFx0aWYgKCBlICYmICF0aGlzLmlzU2ltdWxhdGVkICkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblx0fSxcblx0c3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNQcm9wYWdhdGlvblN0b3BwZWQgPSByZXR1cm5UcnVlO1xuXG5cdFx0aWYgKCBlICYmICF0aGlzLmlzU2ltdWxhdGVkICkge1xuXHRcdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zdG9wUHJvcGFnYXRpb24oKTtcblx0fVxufTtcblxuLy8gSW5jbHVkZXMgYWxsIGNvbW1vbiBldmVudCBwcm9wcyBpbmNsdWRpbmcgS2V5RXZlbnQgYW5kIE1vdXNlRXZlbnQgc3BlY2lmaWMgcHJvcHNcbmpRdWVyeS5lYWNoKCB7XG5cdGFsdEtleTogdHJ1ZSxcblx0YnViYmxlczogdHJ1ZSxcblx0Y2FuY2VsYWJsZTogdHJ1ZSxcblx0Y2hhbmdlZFRvdWNoZXM6IHRydWUsXG5cdGN0cmxLZXk6IHRydWUsXG5cdGRldGFpbDogdHJ1ZSxcblx0ZXZlbnRQaGFzZTogdHJ1ZSxcblx0bWV0YUtleTogdHJ1ZSxcblx0cGFnZVg6IHRydWUsXG5cdHBhZ2VZOiB0cnVlLFxuXHRzaGlmdEtleTogdHJ1ZSxcblx0dmlldzogdHJ1ZSxcblx0XCJjaGFyXCI6IHRydWUsXG5cdGNoYXJDb2RlOiB0cnVlLFxuXHRrZXk6IHRydWUsXG5cdGtleUNvZGU6IHRydWUsXG5cdGJ1dHRvbjogdHJ1ZSxcblx0YnV0dG9uczogdHJ1ZSxcblx0Y2xpZW50WDogdHJ1ZSxcblx0Y2xpZW50WTogdHJ1ZSxcblx0b2Zmc2V0WDogdHJ1ZSxcblx0b2Zmc2V0WTogdHJ1ZSxcblx0cG9pbnRlcklkOiB0cnVlLFxuXHRwb2ludGVyVHlwZTogdHJ1ZSxcblx0c2NyZWVuWDogdHJ1ZSxcblx0c2NyZWVuWTogdHJ1ZSxcblx0dGFyZ2V0VG91Y2hlczogdHJ1ZSxcblx0dG9FbGVtZW50OiB0cnVlLFxuXHR0b3VjaGVzOiB0cnVlLFxuXG5cdHdoaWNoOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0dmFyIGJ1dHRvbiA9IGV2ZW50LmJ1dHRvbjtcblxuXHRcdC8vIEFkZCB3aGljaCBmb3Iga2V5IGV2ZW50c1xuXHRcdGlmICggZXZlbnQud2hpY2ggPT0gbnVsbCAmJiBya2V5RXZlbnQudGVzdCggZXZlbnQudHlwZSApICkge1xuXHRcdFx0cmV0dXJuIGV2ZW50LmNoYXJDb2RlICE9IG51bGwgPyBldmVudC5jaGFyQ29kZSA6IGV2ZW50LmtleUNvZGU7XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIHdoaWNoIGZvciBjbGljazogMSA9PT0gbGVmdDsgMiA9PT0gbWlkZGxlOyAzID09PSByaWdodFxuXHRcdGlmICggIWV2ZW50LndoaWNoICYmIGJ1dHRvbiAhPT0gdW5kZWZpbmVkICYmIHJtb3VzZUV2ZW50LnRlc3QoIGV2ZW50LnR5cGUgKSApIHtcblx0XHRcdGlmICggYnV0dG9uICYgMSApIHtcblx0XHRcdFx0cmV0dXJuIDE7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggYnV0dG9uICYgMiApIHtcblx0XHRcdFx0cmV0dXJuIDM7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggYnV0dG9uICYgNCApIHtcblx0XHRcdFx0cmV0dXJuIDI7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHJldHVybiBldmVudC53aGljaDtcblx0fVxufSwgalF1ZXJ5LmV2ZW50LmFkZFByb3AgKTtcblxuLy8gQ3JlYXRlIG1vdXNlZW50ZXIvbGVhdmUgZXZlbnRzIHVzaW5nIG1vdXNlb3Zlci9vdXQgYW5kIGV2ZW50LXRpbWUgY2hlY2tzXG4vLyBzbyB0aGF0IGV2ZW50IGRlbGVnYXRpb24gd29ya3MgaW4galF1ZXJ5LlxuLy8gRG8gdGhlIHNhbWUgZm9yIHBvaW50ZXJlbnRlci9wb2ludGVybGVhdmUgYW5kIHBvaW50ZXJvdmVyL3BvaW50ZXJvdXRcbi8vXG4vLyBTdXBwb3J0OiBTYWZhcmkgNyBvbmx5XG4vLyBTYWZhcmkgc2VuZHMgbW91c2VlbnRlciB0b28gb2Z0ZW47IHNlZTpcbi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTQ3MDI1OFxuLy8gZm9yIHRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgYnVnIChpdCBleGlzdGVkIGluIG9sZGVyIENocm9tZSB2ZXJzaW9ucyBhcyB3ZWxsKS5cbmpRdWVyeS5lYWNoKCB7XG5cdG1vdXNlZW50ZXI6IFwibW91c2VvdmVyXCIsXG5cdG1vdXNlbGVhdmU6IFwibW91c2VvdXRcIixcblx0cG9pbnRlcmVudGVyOiBcInBvaW50ZXJvdmVyXCIsXG5cdHBvaW50ZXJsZWF2ZTogXCJwb2ludGVyb3V0XCJcbn0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cdGpRdWVyeS5ldmVudC5zcGVjaWFsWyBvcmlnIF0gPSB7XG5cdFx0ZGVsZWdhdGVUeXBlOiBmaXgsXG5cdFx0YmluZFR5cGU6IGZpeCxcblxuXHRcdGhhbmRsZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0dmFyIHJldCxcblx0XHRcdFx0dGFyZ2V0ID0gdGhpcyxcblx0XHRcdFx0cmVsYXRlZCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQsXG5cdFx0XHRcdGhhbmRsZU9iaiA9IGV2ZW50LmhhbmRsZU9iajtcblxuXHRcdFx0Ly8gRm9yIG1vdXNlZW50ZXIvbGVhdmUgY2FsbCB0aGUgaGFuZGxlciBpZiByZWxhdGVkIGlzIG91dHNpZGUgdGhlIHRhcmdldC5cblx0XHRcdC8vIE5COiBObyByZWxhdGVkVGFyZ2V0IGlmIHRoZSBtb3VzZSBsZWZ0L2VudGVyZWQgdGhlIGJyb3dzZXIgd2luZG93XG5cdFx0XHRpZiAoICFyZWxhdGVkIHx8ICggcmVsYXRlZCAhPT0gdGFyZ2V0ICYmICFqUXVlcnkuY29udGFpbnMoIHRhcmdldCwgcmVsYXRlZCApICkgKSB7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBoYW5kbGVPYmoub3JpZ1R5cGU7XG5cdFx0XHRcdHJldCA9IGhhbmRsZU9iai5oYW5kbGVyLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHRcdFx0ZXZlbnQudHlwZSA9IGZpeDtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fVxuXHR9O1xufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cblx0b246IGZ1bmN0aW9uKCB0eXBlcywgc2VsZWN0b3IsIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiBvbiggdGhpcywgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHRvbmU6IGZ1bmN0aW9uKCB0eXBlcywgc2VsZWN0b3IsIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiBvbiggdGhpcywgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgMSApO1xuXHR9LFxuXHRvZmY6IGZ1bmN0aW9uKCB0eXBlcywgc2VsZWN0b3IsIGZuICkge1xuXHRcdHZhciBoYW5kbGVPYmosIHR5cGU7XG5cdFx0aWYgKCB0eXBlcyAmJiB0eXBlcy5wcmV2ZW50RGVmYXVsdCAmJiB0eXBlcy5oYW5kbGVPYmogKSB7XG5cblx0XHRcdC8vICggZXZlbnQgKSAgZGlzcGF0Y2hlZCBqUXVlcnkuRXZlbnRcblx0XHRcdGhhbmRsZU9iaiA9IHR5cGVzLmhhbmRsZU9iajtcblx0XHRcdGpRdWVyeSggdHlwZXMuZGVsZWdhdGVUYXJnZXQgKS5vZmYoXG5cdFx0XHRcdGhhbmRsZU9iai5uYW1lc3BhY2UgP1xuXHRcdFx0XHRcdGhhbmRsZU9iai5vcmlnVHlwZSArIFwiLlwiICsgaGFuZGxlT2JqLm5hbWVzcGFjZSA6XG5cdFx0XHRcdFx0aGFuZGxlT2JqLm9yaWdUeXBlLFxuXHRcdFx0XHRoYW5kbGVPYmouc2VsZWN0b3IsXG5cdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyXG5cdFx0XHQpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggdHlwZW9mIHR5cGVzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0XHQvLyAoIHR5cGVzLW9iamVjdCBbLCBzZWxlY3Rvcl0gKVxuXHRcdFx0Zm9yICggdHlwZSBpbiB0eXBlcyApIHtcblx0XHRcdFx0dGhpcy5vZmYoIHR5cGUsIHNlbGVjdG9yLCB0eXBlc1sgdHlwZSBdICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9XG5cdFx0aWYgKCBzZWxlY3RvciA9PT0gZmFsc2UgfHwgdHlwZW9mIHNlbGVjdG9yID09PSBcImZ1bmN0aW9uXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMgWywgZm5dIClcblx0XHRcdGZuID0gc2VsZWN0b3I7XG5cdFx0XHRzZWxlY3RvciA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKCBmbiA9PT0gZmFsc2UgKSB7XG5cdFx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIHRoaXMsIHR5cGVzLCBmbiwgc2VsZWN0b3IgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxuXG52YXJcblxuXHQvKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5cblx0Ly8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lc2xpbnQvZXNsaW50L2lzc3Vlcy8zMjI5XG5cdHJ4aHRtbFRhZyA9IC88KD8hYXJlYXxicnxjb2x8ZW1iZWR8aHJ8aW1nfGlucHV0fGxpbmt8bWV0YXxwYXJhbSkoKFthLXpdW15cXC9cXDA+XFx4MjBcXHRcXHJcXG5cXGZdKilbXj5dKilcXC8+L2dpLFxuXG5cdC8qIGVzbGludC1lbmFibGUgKi9cblxuXHQvLyBTdXBwb3J0OiBJRSA8PTEwIC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHQvLyBJbiBJRS9FZGdlIHVzaW5nIHJlZ2V4IGdyb3VwcyBoZXJlIGNhdXNlcyBzZXZlcmUgc2xvd2Rvd25zLlxuXHQvLyBTZWUgaHR0cHM6Ly9jb25uZWN0Lm1pY3Jvc29mdC5jb20vSUUvZmVlZGJhY2svZGV0YWlscy8xNzM2NTEyL1xuXHRybm9Jbm5lcmh0bWwgPSAvPHNjcmlwdHw8c3R5bGV8PGxpbmsvaSxcblxuXHQvLyBjaGVja2VkPVwiY2hlY2tlZFwiIG9yIGNoZWNrZWRcblx0cmNoZWNrZWQgPSAvY2hlY2tlZFxccyooPzpbXj1dfD1cXHMqLmNoZWNrZWQuKS9pLFxuXHRyc2NyaXB0VHlwZU1hc2tlZCA9IC9edHJ1ZVxcLyguKikvLFxuXHRyY2xlYW5TY3JpcHQgPSAvXlxccyo8ISg/OlxcW0NEQVRBXFxbfC0tKXwoPzpcXF1cXF18LS0pPlxccyokL2c7XG5cbi8vIFByZWZlciBhIHRib2R5IG92ZXIgaXRzIHBhcmVudCB0YWJsZSBmb3IgY29udGFpbmluZyBuZXcgcm93c1xuZnVuY3Rpb24gbWFuaXB1bGF0aW9uVGFyZ2V0KCBlbGVtLCBjb250ZW50ICkge1xuXHRpZiAoIG5vZGVOYW1lKCBlbGVtLCBcInRhYmxlXCIgKSAmJlxuXHRcdG5vZGVOYW1lKCBjb250ZW50Lm5vZGVUeXBlICE9PSAxMSA/IGNvbnRlbnQgOiBjb250ZW50LmZpcnN0Q2hpbGQsIFwidHJcIiApICkge1xuXG5cdFx0cmV0dXJuIGpRdWVyeSggXCI+dGJvZHlcIiwgZWxlbSApWyAwIF0gfHwgZWxlbTtcblx0fVxuXG5cdHJldHVybiBlbGVtO1xufVxuXG4vLyBSZXBsYWNlL3Jlc3RvcmUgdGhlIHR5cGUgYXR0cmlidXRlIG9mIHNjcmlwdCBlbGVtZW50cyBmb3Igc2FmZSBET00gbWFuaXB1bGF0aW9uXG5mdW5jdGlvbiBkaXNhYmxlU2NyaXB0KCBlbGVtICkge1xuXHRlbGVtLnR5cGUgPSAoIGVsZW0uZ2V0QXR0cmlidXRlKCBcInR5cGVcIiApICE9PSBudWxsICkgKyBcIi9cIiArIGVsZW0udHlwZTtcblx0cmV0dXJuIGVsZW07XG59XG5mdW5jdGlvbiByZXN0b3JlU2NyaXB0KCBlbGVtICkge1xuXHR2YXIgbWF0Y2ggPSByc2NyaXB0VHlwZU1hc2tlZC5leGVjKCBlbGVtLnR5cGUgKTtcblxuXHRpZiAoIG1hdGNoICkge1xuXHRcdGVsZW0udHlwZSA9IG1hdGNoWyAxIF07XG5cdH0gZWxzZSB7XG5cdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIFwidHlwZVwiICk7XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxuZnVuY3Rpb24gY2xvbmVDb3B5RXZlbnQoIHNyYywgZGVzdCApIHtcblx0dmFyIGksIGwsIHR5cGUsIHBkYXRhT2xkLCBwZGF0YUN1ciwgdWRhdGFPbGQsIHVkYXRhQ3VyLCBldmVudHM7XG5cblx0aWYgKCBkZXN0Lm5vZGVUeXBlICE9PSAxICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdC8vIDEuIENvcHkgcHJpdmF0ZSBkYXRhOiBldmVudHMsIGhhbmRsZXJzLCBldGMuXG5cdGlmICggZGF0YVByaXYuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0cGRhdGFPbGQgPSBkYXRhUHJpdi5hY2Nlc3MoIHNyYyApO1xuXHRcdHBkYXRhQ3VyID0gZGF0YVByaXYuc2V0KCBkZXN0LCBwZGF0YU9sZCApO1xuXHRcdGV2ZW50cyA9IHBkYXRhT2xkLmV2ZW50cztcblxuXHRcdGlmICggZXZlbnRzICkge1xuXHRcdFx0ZGVsZXRlIHBkYXRhQ3VyLmhhbmRsZTtcblx0XHRcdHBkYXRhQ3VyLmV2ZW50cyA9IHt9O1xuXG5cdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBldmVudHNbIHR5cGUgXS5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LmFkZCggZGVzdCwgdHlwZSwgZXZlbnRzWyB0eXBlIF1bIGkgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gMi4gQ29weSB1c2VyIGRhdGFcblx0aWYgKCBkYXRhVXNlci5oYXNEYXRhKCBzcmMgKSApIHtcblx0XHR1ZGF0YU9sZCA9IGRhdGFVc2VyLmFjY2Vzcyggc3JjICk7XG5cdFx0dWRhdGFDdXIgPSBqUXVlcnkuZXh0ZW5kKCB7fSwgdWRhdGFPbGQgKTtcblxuXHRcdGRhdGFVc2VyLnNldCggZGVzdCwgdWRhdGFDdXIgKTtcblx0fVxufVxuXG4vLyBGaXggSUUgYnVncywgc2VlIHN1cHBvcnQgdGVzdHNcbmZ1bmN0aW9uIGZpeElucHV0KCBzcmMsIGRlc3QgKSB7XG5cdHZhciBub2RlTmFtZSA9IGRlc3Qubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblxuXHQvLyBGYWlscyB0byBwZXJzaXN0IHRoZSBjaGVja2VkIHN0YXRlIG9mIGEgY2xvbmVkIGNoZWNrYm94IG9yIHJhZGlvIGJ1dHRvbi5cblx0aWYgKCBub2RlTmFtZSA9PT0gXCJpbnB1dFwiICYmIHJjaGVja2FibGVUeXBlLnRlc3QoIHNyYy50eXBlICkgKSB7XG5cdFx0ZGVzdC5jaGVja2VkID0gc3JjLmNoZWNrZWQ7XG5cblx0Ly8gRmFpbHMgdG8gcmV0dXJuIHRoZSBzZWxlY3RlZCBvcHRpb24gdG8gdGhlIGRlZmF1bHQgc2VsZWN0ZWQgc3RhdGUgd2hlbiBjbG9uaW5nIG9wdGlvbnNcblx0fSBlbHNlIGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiB8fCBub2RlTmFtZSA9PT0gXCJ0ZXh0YXJlYVwiICkge1xuXHRcdGRlc3QuZGVmYXVsdFZhbHVlID0gc3JjLmRlZmF1bHRWYWx1ZTtcblx0fVxufVxuXG5mdW5jdGlvbiBkb21NYW5pcCggY29sbGVjdGlvbiwgYXJncywgY2FsbGJhY2ssIGlnbm9yZWQgKSB7XG5cblx0Ly8gRmxhdHRlbiBhbnkgbmVzdGVkIGFycmF5c1xuXHRhcmdzID0gY29uY2F0LmFwcGx5KCBbXSwgYXJncyApO1xuXG5cdHZhciBmcmFnbWVudCwgZmlyc3QsIHNjcmlwdHMsIGhhc1NjcmlwdHMsIG5vZGUsIGRvYyxcblx0XHRpID0gMCxcblx0XHRsID0gY29sbGVjdGlvbi5sZW5ndGgsXG5cdFx0aU5vQ2xvbmUgPSBsIC0gMSxcblx0XHR2YWx1ZSA9IGFyZ3NbIDAgXSxcblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0Ly8gV2UgY2FuJ3QgY2xvbmVOb2RlIGZyYWdtZW50cyB0aGF0IGNvbnRhaW4gY2hlY2tlZCwgaW4gV2ViS2l0XG5cdGlmICggaXNGdW5jdGlvbiB8fFxuXHRcdFx0KCBsID4gMSAmJiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiZcblx0XHRcdFx0IXN1cHBvcnQuY2hlY2tDbG9uZSAmJiByY2hlY2tlZC50ZXN0KCB2YWx1ZSApICkgKSB7XG5cdFx0cmV0dXJuIGNvbGxlY3Rpb24uZWFjaCggZnVuY3Rpb24oIGluZGV4ICkge1xuXHRcdFx0dmFyIHNlbGYgPSBjb2xsZWN0aW9uLmVxKCBpbmRleCApO1xuXHRcdFx0aWYgKCBpc0Z1bmN0aW9uICkge1xuXHRcdFx0XHRhcmdzWyAwIF0gPSB2YWx1ZS5jYWxsKCB0aGlzLCBpbmRleCwgc2VsZi5odG1sKCkgKTtcblx0XHRcdH1cblx0XHRcdGRvbU1hbmlwKCBzZWxmLCBhcmdzLCBjYWxsYmFjaywgaWdub3JlZCApO1xuXHRcdH0gKTtcblx0fVxuXG5cdGlmICggbCApIHtcblx0XHRmcmFnbWVudCA9IGJ1aWxkRnJhZ21lbnQoIGFyZ3MsIGNvbGxlY3Rpb25bIDAgXS5vd25lckRvY3VtZW50LCBmYWxzZSwgY29sbGVjdGlvbiwgaWdub3JlZCApO1xuXHRcdGZpcnN0ID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuXHRcdGlmICggZnJhZ21lbnQuY2hpbGROb2Rlcy5sZW5ndGggPT09IDEgKSB7XG5cdFx0XHRmcmFnbWVudCA9IGZpcnN0O1xuXHRcdH1cblxuXHRcdC8vIFJlcXVpcmUgZWl0aGVyIG5ldyBjb250ZW50IG9yIGFuIGludGVyZXN0IGluIGlnbm9yZWQgZWxlbWVudHMgdG8gaW52b2tlIHRoZSBjYWxsYmFja1xuXHRcdGlmICggZmlyc3QgfHwgaWdub3JlZCApIHtcblx0XHRcdHNjcmlwdHMgPSBqUXVlcnkubWFwKCBnZXRBbGwoIGZyYWdtZW50LCBcInNjcmlwdFwiICksIGRpc2FibGVTY3JpcHQgKTtcblx0XHRcdGhhc1NjcmlwdHMgPSBzY3JpcHRzLmxlbmd0aDtcblxuXHRcdFx0Ly8gVXNlIHRoZSBvcmlnaW5hbCBmcmFnbWVudCBmb3IgdGhlIGxhc3QgaXRlbVxuXHRcdFx0Ly8gaW5zdGVhZCBvZiB0aGUgZmlyc3QgYmVjYXVzZSBpdCBjYW4gZW5kIHVwXG5cdFx0XHQvLyBiZWluZyBlbXB0aWVkIGluY29ycmVjdGx5IGluIGNlcnRhaW4gc2l0dWF0aW9ucyAoIzgwNzApLlxuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRub2RlID0gZnJhZ21lbnQ7XG5cblx0XHRcdFx0aWYgKCBpICE9PSBpTm9DbG9uZSApIHtcblx0XHRcdFx0XHRub2RlID0galF1ZXJ5LmNsb25lKCBub2RlLCB0cnVlLCB0cnVlICk7XG5cblx0XHRcdFx0XHQvLyBLZWVwIHJlZmVyZW5jZXMgdG8gY2xvbmVkIHNjcmlwdHMgZm9yIGxhdGVyIHJlc3RvcmF0aW9uXG5cdFx0XHRcdFx0aWYgKCBoYXNTY3JpcHRzICkge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0XHRcdFx0XHRcdC8vIHB1c2guYXBwbHkoXywgYXJyYXlsaWtlKSB0aHJvd3Mgb24gYW5jaWVudCBXZWJLaXRcblx0XHRcdFx0XHRcdGpRdWVyeS5tZXJnZSggc2NyaXB0cywgZ2V0QWxsKCBub2RlLCBcInNjcmlwdFwiICkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjYWxsYmFjay5jYWxsKCBjb2xsZWN0aW9uWyBpIF0sIG5vZGUsIGkgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBoYXNTY3JpcHRzICkge1xuXHRcdFx0XHRkb2MgPSBzY3JpcHRzWyBzY3JpcHRzLmxlbmd0aCAtIDEgXS5vd25lckRvY3VtZW50O1xuXG5cdFx0XHRcdC8vIFJlZW5hYmxlIHNjcmlwdHNcblx0XHRcdFx0alF1ZXJ5Lm1hcCggc2NyaXB0cywgcmVzdG9yZVNjcmlwdCApO1xuXG5cdFx0XHRcdC8vIEV2YWx1YXRlIGV4ZWN1dGFibGUgc2NyaXB0cyBvbiBmaXJzdCBkb2N1bWVudCBpbnNlcnRpb25cblx0XHRcdFx0Zm9yICggaSA9IDA7IGkgPCBoYXNTY3JpcHRzOyBpKysgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IHNjcmlwdHNbIGkgXTtcblx0XHRcdFx0XHRpZiAoIHJzY3JpcHRUeXBlLnRlc3QoIG5vZGUudHlwZSB8fCBcIlwiICkgJiZcblx0XHRcdFx0XHRcdCFkYXRhUHJpdi5hY2Nlc3MoIG5vZGUsIFwiZ2xvYmFsRXZhbFwiICkgJiZcblx0XHRcdFx0XHRcdGpRdWVyeS5jb250YWlucyggZG9jLCBub2RlICkgKSB7XG5cblx0XHRcdFx0XHRcdGlmICggbm9kZS5zcmMgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gT3B0aW9uYWwgQUpBWCBkZXBlbmRlbmN5LCBidXQgd29uJ3QgcnVuIHNjcmlwdHMgaWYgbm90IHByZXNlbnRcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuX2V2YWxVcmwgKSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5Ll9ldmFsVXJsKCBub2RlLnNyYyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRET01FdmFsKCBub2RlLnRleHRDb250ZW50LnJlcGxhY2UoIHJjbGVhblNjcmlwdCwgXCJcIiApLCBkb2MgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gY29sbGVjdGlvbjtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKCBlbGVtLCBzZWxlY3Rvciwga2VlcERhdGEgKSB7XG5cdHZhciBub2RlLFxuXHRcdG5vZGVzID0gc2VsZWN0b3IgPyBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgZWxlbSApIDogZWxlbSxcblx0XHRpID0gMDtcblxuXHRmb3IgKCA7ICggbm9kZSA9IG5vZGVzWyBpIF0gKSAhPSBudWxsOyBpKysgKSB7XG5cdFx0aWYgKCAha2VlcERhdGEgJiYgbm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggbm9kZSApICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBub2RlLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRpZiAoIGtlZXBEYXRhICYmIGpRdWVyeS5jb250YWlucyggbm9kZS5vd25lckRvY3VtZW50LCBub2RlICkgKSB7XG5cdFx0XHRcdHNldEdsb2JhbEV2YWwoIGdldEFsbCggbm9kZSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHR9XG5cdFx0XHRub2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIG5vZGUgKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRodG1sUHJlZmlsdGVyOiBmdW5jdGlvbiggaHRtbCApIHtcblx0XHRyZXR1cm4gaHRtbC5yZXBsYWNlKCByeGh0bWxUYWcsIFwiPCQxPjwvJDI+XCIgKTtcblx0fSxcblxuXHRjbG9uZTogZnVuY3Rpb24oIGVsZW0sIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICkge1xuXHRcdHZhciBpLCBsLCBzcmNFbGVtZW50cywgZGVzdEVsZW1lbnRzLFxuXHRcdFx0Y2xvbmUgPSBlbGVtLmNsb25lTm9kZSggdHJ1ZSApLFxuXHRcdFx0aW5QYWdlID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdC8vIEZpeCBJRSBjbG9uaW5nIGlzc3Vlc1xuXHRcdGlmICggIXN1cHBvcnQubm9DbG9uZUNoZWNrZWQgJiYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGVsZW0ubm9kZVR5cGUgPT09IDExICkgJiZcblx0XHRcdFx0IWpRdWVyeS5pc1hNTERvYyggZWxlbSApICkge1xuXG5cdFx0XHQvLyBXZSBlc2NoZXcgU2l6emxlIGhlcmUgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnM6IGh0dHBzOi8vanNwZXJmLmNvbS9nZXRhbGwtdnMtc2l6emxlLzJcblx0XHRcdGRlc3RFbGVtZW50cyA9IGdldEFsbCggY2xvbmUgKTtcblx0XHRcdHNyY0VsZW1lbnRzID0gZ2V0QWxsKCBlbGVtICk7XG5cblx0XHRcdGZvciAoIGkgPSAwLCBsID0gc3JjRWxlbWVudHMubGVuZ3RoOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRmaXhJbnB1dCggc3JjRWxlbWVudHNbIGkgXSwgZGVzdEVsZW1lbnRzWyBpIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDb3B5IHRoZSBldmVudHMgZnJvbSB0aGUgb3JpZ2luYWwgdG8gdGhlIGNsb25lXG5cdFx0aWYgKCBkYXRhQW5kRXZlbnRzICkge1xuXHRcdFx0aWYgKCBkZWVwRGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdFx0c3JjRWxlbWVudHMgPSBzcmNFbGVtZW50cyB8fCBnZXRBbGwoIGVsZW0gKTtcblx0XHRcdFx0ZGVzdEVsZW1lbnRzID0gZGVzdEVsZW1lbnRzIHx8IGdldEFsbCggY2xvbmUgKTtcblxuXHRcdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0XHRjbG9uZUNvcHlFdmVudCggc3JjRWxlbWVudHNbIGkgXSwgZGVzdEVsZW1lbnRzWyBpIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIGVsZW0sIGNsb25lICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdGRlc3RFbGVtZW50cyA9IGdldEFsbCggY2xvbmUsIFwic2NyaXB0XCIgKTtcblx0XHRpZiAoIGRlc3RFbGVtZW50cy5sZW5ndGggPiAwICkge1xuXHRcdFx0c2V0R2xvYmFsRXZhbCggZGVzdEVsZW1lbnRzLCAhaW5QYWdlICYmIGdldEFsbCggZWxlbSwgXCJzY3JpcHRcIiApICk7XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHRoZSBjbG9uZWQgc2V0XG5cdFx0cmV0dXJuIGNsb25lO1xuXHR9LFxuXG5cdGNsZWFuRGF0YTogZnVuY3Rpb24oIGVsZW1zICkge1xuXHRcdHZhciBkYXRhLCBlbGVtLCB0eXBlLFxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7ICggZWxlbSA9IGVsZW1zWyBpIF0gKSAhPT0gdW5kZWZpbmVkOyBpKysgKSB7XG5cdFx0XHRpZiAoIGFjY2VwdERhdGEoIGVsZW0gKSApIHtcblx0XHRcdFx0aWYgKCAoIGRhdGEgPSBlbGVtWyBkYXRhUHJpdi5leHBhbmRvIF0gKSApIHtcblx0XHRcdFx0XHRpZiAoIGRhdGEuZXZlbnRzICkge1xuXHRcdFx0XHRcdFx0Zm9yICggdHlwZSBpbiBkYXRhLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBzcGVjaWFsWyB0eXBlIF0gKSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnJlbW92ZSggZWxlbSwgdHlwZSApO1xuXG5cdFx0XHRcdFx0XHRcdC8vIFRoaXMgaXMgYSBzaG9ydGN1dCB0byBhdm9pZCBqUXVlcnkuZXZlbnQucmVtb3ZlJ3Mgb3ZlcmhlYWRcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRqUXVlcnkucmVtb3ZlRXZlbnQoIGVsZW0sIHR5cGUsIGRhdGEuaGFuZGxlICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1K1xuXHRcdFx0XHRcdC8vIEFzc2lnbiB1bmRlZmluZWQgaW5zdGVhZCBvZiB1c2luZyBkZWxldGUsIHNlZSBEYXRhI3JlbW92ZVxuXHRcdFx0XHRcdGVsZW1bIGRhdGFQcml2LmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIGVsZW1bIGRhdGFVc2VyLmV4cGFuZG8gXSApIHtcblxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IENocm9tZSA8PTM1IC0gNDUrXG5cdFx0XHRcdFx0Ly8gQXNzaWduIHVuZGVmaW5lZCBpbnN0ZWFkIG9mIHVzaW5nIGRlbGV0ZSwgc2VlIERhdGEjcmVtb3ZlXG5cdFx0XHRcdFx0ZWxlbVsgZGF0YVVzZXIuZXhwYW5kbyBdID0gdW5kZWZpbmVkO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0ZGV0YWNoOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHJlbW92ZSggdGhpcywgc2VsZWN0b3IsIHRydWUgKTtcblx0fSxcblxuXHRyZW1vdmU6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gcmVtb3ZlKCB0aGlzLCBzZWxlY3RvciApO1xuXHR9LFxuXG5cdHRleHQ6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHRyZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdGpRdWVyeS50ZXh0KCB0aGlzICkgOlxuXHRcdFx0XHR0aGlzLmVtcHR5KCkuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnRleHRDb250ZW50ID0gdmFsdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0fSwgbnVsbCwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggKTtcblx0fSxcblxuXHRhcHBlbmQ6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBkb21NYW5pcCggdGhpcywgYXJndW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHR2YXIgdGFyZ2V0ID0gbWFuaXB1bGF0aW9uVGFyZ2V0KCB0aGlzLCBlbGVtICk7XG5cdFx0XHRcdHRhcmdldC5hcHBlbmRDaGlsZCggZWxlbSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRwcmVwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0dmFyIHRhcmdldCA9IG1hbmlwdWxhdGlvblRhcmdldCggdGhpcywgZWxlbSApO1xuXHRcdFx0XHR0YXJnZXQuaW5zZXJ0QmVmb3JlKCBlbGVtLCB0YXJnZXQuZmlyc3RDaGlsZCApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRiZWZvcmU6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBkb21NYW5pcCggdGhpcywgYXJndW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdGlmICggdGhpcy5wYXJlbnROb2RlICkge1xuXHRcdFx0XHR0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKCBlbGVtLCB0aGlzICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGFmdGVyOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcy5uZXh0U2libGluZyApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGVsZW0sXG5cdFx0XHRpID0gMDtcblxuXHRcdGZvciAoIDsgKCBlbGVtID0gdGhpc1sgaSBdICkgIT0gbnVsbDsgaSsrICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSBhbnkgcmVtYWluaW5nIG5vZGVzXG5cdFx0XHRcdGVsZW0udGV4dENvbnRlbnQgPSBcIlwiO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdGNsb25lOiBmdW5jdGlvbiggZGF0YUFuZEV2ZW50cywgZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0ZGF0YUFuZEV2ZW50cyA9IGRhdGFBbmRFdmVudHMgPT0gbnVsbCA/IGZhbHNlIDogZGF0YUFuZEV2ZW50cztcblx0XHRkZWVwRGF0YUFuZEV2ZW50cyA9IGRlZXBEYXRhQW5kRXZlbnRzID09IG51bGwgPyBkYXRhQW5kRXZlbnRzIDogZGVlcERhdGFBbmRFdmVudHM7XG5cblx0XHRyZXR1cm4gdGhpcy5tYXAoIGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5jbG9uZSggdGhpcywgZGF0YUFuZEV2ZW50cywgZGVlcERhdGFBbmRFdmVudHMgKTtcblx0XHR9ICk7XG5cdH0sXG5cblx0aHRtbDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdHZhciBlbGVtID0gdGhpc1sgMCBdIHx8IHt9LFxuXHRcdFx0XHRpID0gMCxcblx0XHRcdFx0bCA9IHRoaXMubGVuZ3RoO1xuXG5cdFx0XHRpZiAoIHZhbHVlID09PSB1bmRlZmluZWQgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdFx0cmV0dXJuIGVsZW0uaW5uZXJIVE1MO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTZWUgaWYgd2UgY2FuIHRha2UgYSBzaG9ydGN1dCBhbmQganVzdCB1c2UgaW5uZXJIVE1MXG5cdFx0XHRpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiAhcm5vSW5uZXJodG1sLnRlc3QoIHZhbHVlICkgJiZcblx0XHRcdFx0IXdyYXBNYXBbICggcnRhZ05hbWUuZXhlYyggdmFsdWUgKSB8fCBbIFwiXCIsIFwiXCIgXSApWyAxIF0udG9Mb3dlckNhc2UoKSBdICkge1xuXG5cdFx0XHRcdHZhbHVlID0galF1ZXJ5Lmh0bWxQcmVmaWx0ZXIoIHZhbHVlICk7XG5cblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRlbGVtID0gdGhpc1sgaSBdIHx8IHt9O1xuXG5cdFx0XHRcdFx0XHQvLyBSZW1vdmUgZWxlbWVudCBub2RlcyBhbmQgcHJldmVudCBtZW1vcnkgbGVha3Ncblx0XHRcdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdFx0XHRcdFx0alF1ZXJ5LmNsZWFuRGF0YSggZ2V0QWxsKCBlbGVtLCBmYWxzZSApICk7XG5cdFx0XHRcdFx0XHRcdGVsZW0uaW5uZXJIVE1MID0gdmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0ZWxlbSA9IDA7XG5cblx0XHRcdFx0Ly8gSWYgdXNpbmcgaW5uZXJIVE1MIHRocm93cyBhbiBleGNlcHRpb24sIHVzZSB0aGUgZmFsbGJhY2sgbWV0aG9kXG5cdFx0XHRcdH0gY2F0Y2ggKCBlICkge31cblx0XHRcdH1cblxuXHRcdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0XHR0aGlzLmVtcHR5KCkuYXBwZW5kKCB2YWx1ZSApO1xuXHRcdFx0fVxuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0cmVwbGFjZVdpdGg6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBpZ25vcmVkID0gW107XG5cblx0XHQvLyBNYWtlIHRoZSBjaGFuZ2VzLCByZXBsYWNpbmcgZWFjaCBub24taWdub3JlZCBjb250ZXh0IGVsZW1lbnQgd2l0aCB0aGUgbmV3IGNvbnRlbnRcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgcGFyZW50ID0gdGhpcy5wYXJlbnROb2RlO1xuXG5cdFx0XHRpZiAoIGpRdWVyeS5pbkFycmF5KCB0aGlzLCBpZ25vcmVkICkgPCAwICkge1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIHRoaXMgKSApO1xuXHRcdFx0XHRpZiAoIHBhcmVudCApIHtcblx0XHRcdFx0XHRwYXJlbnQucmVwbGFjZUNoaWxkKCBlbGVtLCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdC8vIEZvcmNlIGNhbGxiYWNrIGludm9jYXRpb25cblx0XHR9LCBpZ25vcmVkICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmVhY2goIHtcblx0YXBwZW5kVG86IFwiYXBwZW5kXCIsXG5cdHByZXBlbmRUbzogXCJwcmVwZW5kXCIsXG5cdGluc2VydEJlZm9yZTogXCJiZWZvcmVcIixcblx0aW5zZXJ0QWZ0ZXI6IFwiYWZ0ZXJcIixcblx0cmVwbGFjZUFsbDogXCJyZXBsYWNlV2l0aFwiXG59LCBmdW5jdGlvbiggbmFtZSwgb3JpZ2luYWwgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHZhciBlbGVtcyxcblx0XHRcdHJldCA9IFtdLFxuXHRcdFx0aW5zZXJ0ID0galF1ZXJ5KCBzZWxlY3RvciApLFxuXHRcdFx0bGFzdCA9IGluc2VydC5sZW5ndGggLSAxLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7IGkgPD0gbGFzdDsgaSsrICkge1xuXHRcdFx0ZWxlbXMgPSBpID09PSBsYXN0ID8gdGhpcyA6IHRoaXMuY2xvbmUoIHRydWUgKTtcblx0XHRcdGpRdWVyeSggaW5zZXJ0WyBpIF0gKVsgb3JpZ2luYWwgXSggZWxlbXMgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHQvLyAuZ2V0KCkgYmVjYXVzZSBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRwdXNoLmFwcGx5KCByZXQsIGVsZW1zLmdldCgpICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCByZXQgKTtcblx0fTtcbn0gKTtcbnZhciBybWFyZ2luID0gKCAvXm1hcmdpbi8gKTtcblxudmFyIHJudW1ub25weCA9IG5ldyBSZWdFeHAoIFwiXihcIiArIHBudW0gKyBcIikoPyFweClbYS16JV0rJFwiLCBcImlcIiApO1xuXG52YXIgZ2V0U3R5bGVzID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHksIEZpcmVmb3ggPD0zMCAoIzE1MDk4LCAjMTQxNTApXG5cdFx0Ly8gSUUgdGhyb3dzIG9uIGVsZW1lbnRzIGNyZWF0ZWQgaW4gcG9wdXBzXG5cdFx0Ly8gRkYgbWVhbndoaWxlIHRocm93cyBvbiBmcmFtZSBlbGVtZW50cyB0aHJvdWdoIFwiZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZVwiXG5cdFx0dmFyIHZpZXcgPSBlbGVtLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXc7XG5cblx0XHRpZiAoICF2aWV3IHx8ICF2aWV3Lm9wZW5lciApIHtcblx0XHRcdHZpZXcgPSB3aW5kb3c7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZpZXcuZ2V0Q29tcHV0ZWRTdHlsZSggZWxlbSApO1xuXHR9O1xuXG5cblxuKCBmdW5jdGlvbigpIHtcblxuXHQvLyBFeGVjdXRpbmcgYm90aCBwaXhlbFBvc2l0aW9uICYgYm94U2l6aW5nUmVsaWFibGUgdGVzdHMgcmVxdWlyZSBvbmx5IG9uZSBsYXlvdXRcblx0Ly8gc28gdGhleSdyZSBleGVjdXRlZCBhdCB0aGUgc2FtZSB0aW1lIHRvIHNhdmUgdGhlIHNlY29uZCBjb21wdXRhdGlvbi5cblx0ZnVuY3Rpb24gY29tcHV0ZVN0eWxlVGVzdHMoKSB7XG5cblx0XHQvLyBUaGlzIGlzIGEgc2luZ2xldG9uLCB3ZSBuZWVkIHRvIGV4ZWN1dGUgaXQgb25seSBvbmNlXG5cdFx0aWYgKCAhZGl2ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGRpdi5zdHlsZS5jc3NUZXh0ID1cblx0XHRcdFwiYm94LXNpemluZzpib3JkZXItYm94O1wiICtcblx0XHRcdFwicG9zaXRpb246cmVsYXRpdmU7ZGlzcGxheTpibG9jaztcIiArXG5cdFx0XHRcIm1hcmdpbjphdXRvO2JvcmRlcjoxcHg7cGFkZGluZzoxcHg7XCIgK1xuXHRcdFx0XCJ0b3A6MSU7d2lkdGg6NTAlXCI7XG5cdFx0ZGl2LmlubmVySFRNTCA9IFwiXCI7XG5cdFx0ZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKCBjb250YWluZXIgKTtcblxuXHRcdHZhciBkaXZTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKCBkaXYgKTtcblx0XHRwaXhlbFBvc2l0aW9uVmFsID0gZGl2U3R5bGUudG9wICE9PSBcIjElXCI7XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCAtIDQuMyBvbmx5LCBGaXJlZm94IDw9MyAtIDQ0XG5cdFx0cmVsaWFibGVNYXJnaW5MZWZ0VmFsID0gZGl2U3R5bGUubWFyZ2luTGVmdCA9PT0gXCIycHhcIjtcblx0XHRib3hTaXppbmdSZWxpYWJsZVZhbCA9IGRpdlN0eWxlLndpZHRoID09PSBcIjRweFwiO1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgLSA0LjMgb25seVxuXHRcdC8vIFNvbWUgc3R5bGVzIGNvbWUgYmFjayB3aXRoIHBlcmNlbnRhZ2UgdmFsdWVzLCBldmVuIHRob3VnaCB0aGV5IHNob3VsZG4ndFxuXHRcdGRpdi5zdHlsZS5tYXJnaW5SaWdodCA9IFwiNTAlXCI7XG5cdFx0cGl4ZWxNYXJnaW5SaWdodFZhbCA9IGRpdlN0eWxlLm1hcmdpblJpZ2h0ID09PSBcIjRweFwiO1xuXG5cdFx0ZG9jdW1lbnRFbGVtZW50LnJlbW92ZUNoaWxkKCBjb250YWluZXIgKTtcblxuXHRcdC8vIE51bGxpZnkgdGhlIGRpdiBzbyBpdCB3b3VsZG4ndCBiZSBzdG9yZWQgaW4gdGhlIG1lbW9yeSBhbmRcblx0XHQvLyBpdCB3aWxsIGFsc28gYmUgYSBzaWduIHRoYXQgY2hlY2tzIGFscmVhZHkgcGVyZm9ybWVkXG5cdFx0ZGl2ID0gbnVsbDtcblx0fVxuXG5cdHZhciBwaXhlbFBvc2l0aW9uVmFsLCBib3hTaXppbmdSZWxpYWJsZVZhbCwgcGl4ZWxNYXJnaW5SaWdodFZhbCwgcmVsaWFibGVNYXJnaW5MZWZ0VmFsLFxuXHRcdGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSxcblx0XHRkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICk7XG5cblx0Ly8gRmluaXNoIGVhcmx5IGluIGxpbWl0ZWQgKG5vbi1icm93c2VyKSBlbnZpcm9ubWVudHNcblx0aWYgKCAhZGl2LnN0eWxlICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0Ly8gU3R5bGUgb2YgY2xvbmVkIGVsZW1lbnQgYWZmZWN0cyBzb3VyY2UgZWxlbWVudCBjbG9uZWQgKCM4OTA4KVxuXHRkaXYuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcImNvbnRlbnQtYm94XCI7XG5cdGRpdi5jbG9uZU5vZGUoIHRydWUgKS5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9IFwiXCI7XG5cdHN1cHBvcnQuY2xlYXJDbG9uZVN0eWxlID0gZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID09PSBcImNvbnRlbnQtYm94XCI7XG5cblx0Y29udGFpbmVyLnN0eWxlLmNzc1RleHQgPSBcImJvcmRlcjowO3dpZHRoOjhweDtoZWlnaHQ6MDt0b3A6MDtsZWZ0Oi05OTk5cHg7XCIgK1xuXHRcdFwicGFkZGluZzowO21hcmdpbi10b3A6MXB4O3Bvc2l0aW9uOmFic29sdXRlXCI7XG5cdGNvbnRhaW5lci5hcHBlbmRDaGlsZCggZGl2ICk7XG5cblx0alF1ZXJ5LmV4dGVuZCggc3VwcG9ydCwge1xuXHRcdHBpeGVsUG9zaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0Y29tcHV0ZVN0eWxlVGVzdHMoKTtcblx0XHRcdHJldHVybiBwaXhlbFBvc2l0aW9uVmFsO1xuXHRcdH0sXG5cdFx0Ym94U2l6aW5nUmVsaWFibGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0Y29tcHV0ZVN0eWxlVGVzdHMoKTtcblx0XHRcdHJldHVybiBib3hTaXppbmdSZWxpYWJsZVZhbDtcblx0XHR9LFxuXHRcdHBpeGVsTWFyZ2luUmlnaHQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0Y29tcHV0ZVN0eWxlVGVzdHMoKTtcblx0XHRcdHJldHVybiBwaXhlbE1hcmdpblJpZ2h0VmFsO1xuXHRcdH0sXG5cdFx0cmVsaWFibGVNYXJnaW5MZWZ0OiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcmVsaWFibGVNYXJnaW5MZWZ0VmFsO1xuXHRcdH1cblx0fSApO1xufSApKCk7XG5cblxuZnVuY3Rpb24gY3VyQ1NTKCBlbGVtLCBuYW1lLCBjb21wdXRlZCApIHtcblx0dmFyIHdpZHRoLCBtaW5XaWR0aCwgbWF4V2lkdGgsIHJldCxcblxuXHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggNTErXG5cdFx0Ly8gUmV0cmlldmluZyBzdHlsZSBiZWZvcmUgY29tcHV0ZWQgc29tZWhvd1xuXHRcdC8vIGZpeGVzIGFuIGlzc3VlIHdpdGggZ2V0dGluZyB3cm9uZyB2YWx1ZXNcblx0XHQvLyBvbiBkZXRhY2hlZCBlbGVtZW50c1xuXHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRjb21wdXRlZCA9IGNvbXB1dGVkIHx8IGdldFN0eWxlcyggZWxlbSApO1xuXG5cdC8vIGdldFByb3BlcnR5VmFsdWUgaXMgbmVlZGVkIGZvcjpcblx0Ly8gICAuY3NzKCdmaWx0ZXInKSAoSUUgOSBvbmx5LCAjMTI1MzcpXG5cdC8vICAgLmNzcygnLS1jdXN0b21Qcm9wZXJ0eSkgKCMzMTQ0KVxuXHRpZiAoIGNvbXB1dGVkICkge1xuXHRcdHJldCA9IGNvbXB1dGVkLmdldFByb3BlcnR5VmFsdWUoIG5hbWUgKSB8fCBjb21wdXRlZFsgbmFtZSBdO1xuXG5cdFx0aWYgKCByZXQgPT09IFwiXCIgJiYgIWpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICkgKSB7XG5cdFx0XHRyZXQgPSBqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUgKTtcblx0XHR9XG5cblx0XHQvLyBBIHRyaWJ1dGUgdG8gdGhlIFwiYXdlc29tZSBoYWNrIGJ5IERlYW4gRWR3YXJkc1wiXG5cdFx0Ly8gQW5kcm9pZCBCcm93c2VyIHJldHVybnMgcGVyY2VudGFnZSBmb3Igc29tZSB2YWx1ZXMsXG5cdFx0Ly8gYnV0IHdpZHRoIHNlZW1zIHRvIGJlIHJlbGlhYmx5IHBpeGVscy5cblx0XHQvLyBUaGlzIGlzIGFnYWluc3QgdGhlIENTU09NIGRyYWZ0IHNwZWM6XG5cdFx0Ly8gaHR0cHM6Ly9kcmFmdHMuY3Nzd2cub3JnL2Nzc29tLyNyZXNvbHZlZC12YWx1ZXNcblx0XHRpZiAoICFzdXBwb3J0LnBpeGVsTWFyZ2luUmlnaHQoKSAmJiBybnVtbm9ucHgudGVzdCggcmV0ICkgJiYgcm1hcmdpbi50ZXN0KCBuYW1lICkgKSB7XG5cblx0XHRcdC8vIFJlbWVtYmVyIHRoZSBvcmlnaW5hbCB2YWx1ZXNcblx0XHRcdHdpZHRoID0gc3R5bGUud2lkdGg7XG5cdFx0XHRtaW5XaWR0aCA9IHN0eWxlLm1pbldpZHRoO1xuXHRcdFx0bWF4V2lkdGggPSBzdHlsZS5tYXhXaWR0aDtcblxuXHRcdFx0Ly8gUHV0IGluIHRoZSBuZXcgdmFsdWVzIHRvIGdldCBhIGNvbXB1dGVkIHZhbHVlIG91dFxuXHRcdFx0c3R5bGUubWluV2lkdGggPSBzdHlsZS5tYXhXaWR0aCA9IHN0eWxlLndpZHRoID0gcmV0O1xuXHRcdFx0cmV0ID0gY29tcHV0ZWQud2lkdGg7XG5cblx0XHRcdC8vIFJldmVydCB0aGUgY2hhbmdlZCB2YWx1ZXNcblx0XHRcdHN0eWxlLndpZHRoID0gd2lkdGg7XG5cdFx0XHRzdHlsZS5taW5XaWR0aCA9IG1pbldpZHRoO1xuXHRcdFx0c3R5bGUubWF4V2lkdGggPSBtYXhXaWR0aDtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gcmV0ICE9PSB1bmRlZmluZWQgP1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHRcdC8vIElFIHJldHVybnMgekluZGV4IHZhbHVlIGFzIGFuIGludGVnZXIuXG5cdFx0cmV0ICsgXCJcIiA6XG5cdFx0cmV0O1xufVxuXG5cbmZ1bmN0aW9uIGFkZEdldEhvb2tJZiggY29uZGl0aW9uRm4sIGhvb2tGbiApIHtcblxuXHQvLyBEZWZpbmUgdGhlIGhvb2ssIHdlJ2xsIGNoZWNrIG9uIHRoZSBmaXJzdCBydW4gaWYgaXQncyByZWFsbHkgbmVlZGVkLlxuXHRyZXR1cm4ge1xuXHRcdGdldDogZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGNvbmRpdGlvbkZuKCkgKSB7XG5cblx0XHRcdFx0Ly8gSG9vayBub3QgbmVlZGVkIChvciBpdCdzIG5vdCBwb3NzaWJsZSB0byB1c2UgaXQgZHVlXG5cdFx0XHRcdC8vIHRvIG1pc3NpbmcgZGVwZW5kZW5jeSksIHJlbW92ZSBpdC5cblx0XHRcdFx0ZGVsZXRlIHRoaXMuZ2V0O1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIEhvb2sgbmVlZGVkOyByZWRlZmluZSBpdCBzbyB0aGF0IHRoZSBzdXBwb3J0IHRlc3QgaXMgbm90IGV4ZWN1dGVkIGFnYWluLlxuXHRcdFx0cmV0dXJuICggdGhpcy5nZXQgPSBob29rRm4gKS5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0fVxuXHR9O1xufVxuXG5cbnZhclxuXG5cdC8vIFN3YXBwYWJsZSBpZiBkaXNwbGF5IGlzIG5vbmUgb3Igc3RhcnRzIHdpdGggdGFibGVcblx0Ly8gZXhjZXB0IFwidGFibGVcIiwgXCJ0YWJsZS1jZWxsXCIsIG9yIFwidGFibGUtY2FwdGlvblwiXG5cdC8vIFNlZSBoZXJlIGZvciBkaXNwbGF5IHZhbHVlczogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9DU1MvZGlzcGxheVxuXHRyZGlzcGxheXN3YXAgPSAvXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sXG5cdHJjdXN0b21Qcm9wID0gL14tLS8sXG5cdGNzc1Nob3cgPSB7IHBvc2l0aW9uOiBcImFic29sdXRlXCIsIHZpc2liaWxpdHk6IFwiaGlkZGVuXCIsIGRpc3BsYXk6IFwiYmxvY2tcIiB9LFxuXHRjc3NOb3JtYWxUcmFuc2Zvcm0gPSB7XG5cdFx0bGV0dGVyU3BhY2luZzogXCIwXCIsXG5cdFx0Zm9udFdlaWdodDogXCI0MDBcIlxuXHR9LFxuXG5cdGNzc1ByZWZpeGVzID0gWyBcIldlYmtpdFwiLCBcIk1velwiLCBcIm1zXCIgXSxcblx0ZW1wdHlTdHlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKS5zdHlsZTtcblxuLy8gUmV0dXJuIGEgY3NzIHByb3BlcnR5IG1hcHBlZCB0byBhIHBvdGVudGlhbGx5IHZlbmRvciBwcmVmaXhlZCBwcm9wZXJ0eVxuZnVuY3Rpb24gdmVuZG9yUHJvcE5hbWUoIG5hbWUgKSB7XG5cblx0Ly8gU2hvcnRjdXQgZm9yIG5hbWVzIHRoYXQgYXJlIG5vdCB2ZW5kb3IgcHJlZml4ZWRcblx0aWYgKCBuYW1lIGluIGVtcHR5U3R5bGUgKSB7XG5cdFx0cmV0dXJuIG5hbWU7XG5cdH1cblxuXHQvLyBDaGVjayBmb3IgdmVuZG9yIHByZWZpeGVkIG5hbWVzXG5cdHZhciBjYXBOYW1lID0gbmFtZVsgMCBdLnRvVXBwZXJDYXNlKCkgKyBuYW1lLnNsaWNlKCAxICksXG5cdFx0aSA9IGNzc1ByZWZpeGVzLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRuYW1lID0gY3NzUHJlZml4ZXNbIGkgXSArIGNhcE5hbWU7XG5cdFx0aWYgKCBuYW1lIGluIGVtcHR5U3R5bGUgKSB7XG5cdFx0XHRyZXR1cm4gbmFtZTtcblx0XHR9XG5cdH1cbn1cblxuLy8gUmV0dXJuIGEgcHJvcGVydHkgbWFwcGVkIGFsb25nIHdoYXQgalF1ZXJ5LmNzc1Byb3BzIHN1Z2dlc3RzIG9yIHRvXG4vLyBhIHZlbmRvciBwcmVmaXhlZCBwcm9wZXJ0eS5cbmZ1bmN0aW9uIGZpbmFsUHJvcE5hbWUoIG5hbWUgKSB7XG5cdHZhciByZXQgPSBqUXVlcnkuY3NzUHJvcHNbIG5hbWUgXTtcblx0aWYgKCAhcmV0ICkge1xuXHRcdHJldCA9IGpRdWVyeS5jc3NQcm9wc1sgbmFtZSBdID0gdmVuZG9yUHJvcE5hbWUoIG5hbWUgKSB8fCBuYW1lO1xuXHR9XG5cdHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIHNldFBvc2l0aXZlTnVtYmVyKCBlbGVtLCB2YWx1ZSwgc3VidHJhY3QgKSB7XG5cblx0Ly8gQW55IHJlbGF0aXZlICgrLy0pIHZhbHVlcyBoYXZlIGFscmVhZHkgYmVlblxuXHQvLyBub3JtYWxpemVkIGF0IHRoaXMgcG9pbnRcblx0dmFyIG1hdGNoZXMgPSByY3NzTnVtLmV4ZWMoIHZhbHVlICk7XG5cdHJldHVybiBtYXRjaGVzID9cblxuXHRcdC8vIEd1YXJkIGFnYWluc3QgdW5kZWZpbmVkIFwic3VidHJhY3RcIiwgZS5nLiwgd2hlbiB1c2VkIGFzIGluIGNzc0hvb2tzXG5cdFx0TWF0aC5tYXgoIDAsIG1hdGNoZXNbIDIgXSAtICggc3VidHJhY3QgfHwgMCApICkgKyAoIG1hdGNoZXNbIDMgXSB8fCBcInB4XCIgKSA6XG5cdFx0dmFsdWU7XG59XG5cbmZ1bmN0aW9uIGF1Z21lbnRXaWR0aE9ySGVpZ2h0KCBlbGVtLCBuYW1lLCBleHRyYSwgaXNCb3JkZXJCb3gsIHN0eWxlcyApIHtcblx0dmFyIGksXG5cdFx0dmFsID0gMDtcblxuXHQvLyBJZiB3ZSBhbHJlYWR5IGhhdmUgdGhlIHJpZ2h0IG1lYXN1cmVtZW50LCBhdm9pZCBhdWdtZW50YXRpb25cblx0aWYgKCBleHRyYSA9PT0gKCBpc0JvcmRlckJveCA/IFwiYm9yZGVyXCIgOiBcImNvbnRlbnRcIiApICkge1xuXHRcdGkgPSA0O1xuXG5cdC8vIE90aGVyd2lzZSBpbml0aWFsaXplIGZvciBob3Jpem9udGFsIG9yIHZlcnRpY2FsIHByb3BlcnRpZXNcblx0fSBlbHNlIHtcblx0XHRpID0gbmFtZSA9PT0gXCJ3aWR0aFwiID8gMSA6IDA7XG5cdH1cblxuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgKSB7XG5cblx0XHQvLyBCb3RoIGJveCBtb2RlbHMgZXhjbHVkZSBtYXJnaW4sIHNvIGFkZCBpdCBpZiB3ZSB3YW50IGl0XG5cdFx0aWYgKCBleHRyYSA9PT0gXCJtYXJnaW5cIiApIHtcblx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBleHRyYSArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblx0XHR9XG5cblx0XHRpZiAoIGlzQm9yZGVyQm94ICkge1xuXG5cdFx0XHQvLyBib3JkZXItYm94IGluY2x1ZGVzIHBhZGRpbmcsIHNvIHJlbW92ZSBpdCBpZiB3ZSB3YW50IGNvbnRlbnRcblx0XHRcdGlmICggZXh0cmEgPT09IFwiY29udGVudFwiICkge1xuXHRcdFx0XHR2YWwgLT0galF1ZXJ5LmNzcyggZWxlbSwgXCJwYWRkaW5nXCIgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEF0IHRoaXMgcG9pbnQsIGV4dHJhIGlzbid0IGJvcmRlciBub3IgbWFyZ2luLCBzbyByZW1vdmUgYm9yZGVyXG5cdFx0XHRpZiAoIGV4dHJhICE9PSBcIm1hcmdpblwiICkge1xuXHRcdFx0XHR2YWwgLT0galF1ZXJ5LmNzcyggZWxlbSwgXCJib3JkZXJcIiArIGNzc0V4cGFuZFsgaSBdICsgXCJXaWR0aFwiLCB0cnVlLCBzdHlsZXMgKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBjb250ZW50LCBzbyBhZGQgcGFkZGluZ1xuXHRcdFx0dmFsICs9IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBjb250ZW50IG5vciBwYWRkaW5nLCBzbyBhZGQgYm9yZGVyXG5cdFx0XHRpZiAoIGV4dHJhICE9PSBcInBhZGRpbmdcIiApIHtcblx0XHRcdFx0dmFsICs9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHZhbDtcbn1cblxuZnVuY3Rpb24gZ2V0V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEgKSB7XG5cblx0Ly8gU3RhcnQgd2l0aCBjb21wdXRlZCBzdHlsZVxuXHR2YXIgdmFsdWVJc0JvcmRlckJveCxcblx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHR2YWwgPSBjdXJDU1MoIGVsZW0sIG5hbWUsIHN0eWxlcyApLFxuXHRcdGlzQm9yZGVyQm94ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIjtcblxuXHQvLyBDb21wdXRlZCB1bml0IGlzIG5vdCBwaXhlbHMuIFN0b3AgaGVyZSBhbmQgcmV0dXJuLlxuXHRpZiAoIHJudW1ub25weC50ZXN0KCB2YWwgKSApIHtcblx0XHRyZXR1cm4gdmFsO1xuXHR9XG5cblx0Ly8gQ2hlY2sgZm9yIHN0eWxlIGluIGNhc2UgYSBicm93c2VyIHdoaWNoIHJldHVybnMgdW5yZWxpYWJsZSB2YWx1ZXNcblx0Ly8gZm9yIGdldENvbXB1dGVkU3R5bGUgc2lsZW50bHkgZmFsbHMgYmFjayB0byB0aGUgcmVsaWFibGUgZWxlbS5zdHlsZVxuXHR2YWx1ZUlzQm9yZGVyQm94ID0gaXNCb3JkZXJCb3ggJiZcblx0XHQoIHN1cHBvcnQuYm94U2l6aW5nUmVsaWFibGUoKSB8fCB2YWwgPT09IGVsZW0uc3R5bGVbIG5hbWUgXSApO1xuXG5cdC8vIEZhbGwgYmFjayB0byBvZmZzZXRXaWR0aC9IZWlnaHQgd2hlbiB2YWx1ZSBpcyBcImF1dG9cIlxuXHQvLyBUaGlzIGhhcHBlbnMgZm9yIGlubGluZSBlbGVtZW50cyB3aXRoIG5vIGV4cGxpY2l0IHNldHRpbmcgKGdoLTM1NzEpXG5cdGlmICggdmFsID09PSBcImF1dG9cIiApIHtcblx0XHR2YWwgPSBlbGVtWyBcIm9mZnNldFwiICsgbmFtZVsgMCBdLnRvVXBwZXJDYXNlKCkgKyBuYW1lLnNsaWNlKCAxICkgXTtcblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBcIlwiLCBhdXRvLCBhbmQgcHJlcGFyZSBmb3IgZXh0cmFcblx0dmFsID0gcGFyc2VGbG9hdCggdmFsICkgfHwgMDtcblxuXHQvLyBVc2UgdGhlIGFjdGl2ZSBib3gtc2l6aW5nIG1vZGVsIHRvIGFkZC9zdWJ0cmFjdCBpcnJlbGV2YW50IHN0eWxlc1xuXHRyZXR1cm4gKCB2YWwgK1xuXHRcdGF1Z21lbnRXaWR0aE9ySGVpZ2h0KFxuXHRcdFx0ZWxlbSxcblx0XHRcdG5hbWUsXG5cdFx0XHRleHRyYSB8fCAoIGlzQm9yZGVyQm94ID8gXCJib3JkZXJcIiA6IFwiY29udGVudFwiICksXG5cdFx0XHR2YWx1ZUlzQm9yZGVyQm94LFxuXHRcdFx0c3R5bGVzXG5cdFx0KVxuXHQpICsgXCJweFwiO1xufVxuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gQWRkIGluIHN0eWxlIHByb3BlcnR5IGhvb2tzIGZvciBvdmVycmlkaW5nIHRoZSBkZWZhdWx0XG5cdC8vIGJlaGF2aW9yIG9mIGdldHRpbmcgYW5kIHNldHRpbmcgYSBzdHlsZSBwcm9wZXJ0eVxuXHRjc3NIb29rczoge1xuXHRcdG9wYWNpdHk6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkICkge1xuXHRcdFx0XHRpZiAoIGNvbXB1dGVkICkge1xuXG5cdFx0XHRcdFx0Ly8gV2Ugc2hvdWxkIGFsd2F5cyBnZXQgYSBudW1iZXIgYmFjayBmcm9tIG9wYWNpdHlcblx0XHRcdFx0XHR2YXIgcmV0ID0gY3VyQ1NTKCBlbGVtLCBcIm9wYWNpdHlcIiApO1xuXHRcdFx0XHRcdHJldHVybiByZXQgPT09IFwiXCIgPyBcIjFcIiA6IHJldDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvLyBEb24ndCBhdXRvbWF0aWNhbGx5IGFkZCBcInB4XCIgdG8gdGhlc2UgcG9zc2libHktdW5pdGxlc3MgcHJvcGVydGllc1xuXHRjc3NOdW1iZXI6IHtcblx0XHRcImFuaW1hdGlvbkl0ZXJhdGlvbkNvdW50XCI6IHRydWUsXG5cdFx0XCJjb2x1bW5Db3VudFwiOiB0cnVlLFxuXHRcdFwiZmlsbE9wYWNpdHlcIjogdHJ1ZSxcblx0XHRcImZsZXhHcm93XCI6IHRydWUsXG5cdFx0XCJmbGV4U2hyaW5rXCI6IHRydWUsXG5cdFx0XCJmb250V2VpZ2h0XCI6IHRydWUsXG5cdFx0XCJsaW5lSGVpZ2h0XCI6IHRydWUsXG5cdFx0XCJvcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJvcmRlclwiOiB0cnVlLFxuXHRcdFwib3JwaGFuc1wiOiB0cnVlLFxuXHRcdFwid2lkb3dzXCI6IHRydWUsXG5cdFx0XCJ6SW5kZXhcIjogdHJ1ZSxcblx0XHRcInpvb21cIjogdHJ1ZVxuXHR9LFxuXG5cdC8vIEFkZCBpbiBwcm9wZXJ0aWVzIHdob3NlIG5hbWVzIHlvdSB3aXNoIHRvIGZpeCBiZWZvcmVcblx0Ly8gc2V0dGluZyBvciBnZXR0aW5nIHRoZSB2YWx1ZVxuXHRjc3NQcm9wczoge1xuXHRcdFwiZmxvYXRcIjogXCJjc3NGbG9hdFwiXG5cdH0sXG5cblx0Ly8gR2V0IGFuZCBzZXQgdGhlIHN0eWxlIHByb3BlcnR5IG9uIGEgRE9NIE5vZGVcblx0c3R5bGU6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCB2YWx1ZSwgZXh0cmEgKSB7XG5cblx0XHQvLyBEb24ndCBzZXQgc3R5bGVzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoICFlbGVtIHx8IGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCB8fCAhZWxlbS5zdHlsZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB3ZSdyZSB3b3JraW5nIHdpdGggdGhlIHJpZ2h0IG5hbWVcblx0XHR2YXIgcmV0LCB0eXBlLCBob29rcyxcblx0XHRcdG9yaWdOYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZSApLFxuXHRcdFx0aXNDdXN0b21Qcm9wID0gcmN1c3RvbVByb3AudGVzdCggbmFtZSApLFxuXHRcdFx0c3R5bGUgPSBlbGVtLnN0eWxlO1xuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lLiBXZSBkb24ndFxuXHRcdC8vIHdhbnQgdG8gcXVlcnkgdGhlIHZhbHVlIGlmIGl0IGlzIGEgQ1NTIGN1c3RvbSBwcm9wZXJ0eVxuXHRcdC8vIHNpbmNlIHRoZXkgYXJlIHVzZXItZGVmaW5lZC5cblx0XHRpZiAoICFpc0N1c3RvbVByb3AgKSB7XG5cdFx0XHRuYW1lID0gZmluYWxQcm9wTmFtZSggb3JpZ05hbWUgKTtcblx0XHR9XG5cblx0XHQvLyBHZXRzIGhvb2sgZm9yIHRoZSBwcmVmaXhlZCB2ZXJzaW9uLCB0aGVuIHVucHJlZml4ZWQgdmVyc2lvblxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF0gfHwgalF1ZXJ5LmNzc0hvb2tzWyBvcmlnTmFtZSBdO1xuXG5cdFx0Ly8gQ2hlY2sgaWYgd2UncmUgc2V0dGluZyBhIHZhbHVlXG5cdFx0aWYgKCB2YWx1ZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdFx0Ly8gQ29udmVydCBcIis9XCIgb3IgXCItPVwiIHRvIHJlbGF0aXZlIG51bWJlcnMgKCM3MzQ1KVxuXHRcdFx0aWYgKCB0eXBlID09PSBcInN0cmluZ1wiICYmICggcmV0ID0gcmNzc051bS5leGVjKCB2YWx1ZSApICkgJiYgcmV0WyAxIF0gKSB7XG5cdFx0XHRcdHZhbHVlID0gYWRqdXN0Q1NTKCBlbGVtLCBuYW1lLCByZXQgKTtcblxuXHRcdFx0XHQvLyBGaXhlcyBidWcgIzkyMzdcblx0XHRcdFx0dHlwZSA9IFwibnVtYmVyXCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE1ha2Ugc3VyZSB0aGF0IG51bGwgYW5kIE5hTiB2YWx1ZXMgYXJlbid0IHNldCAoIzcxMTYpXG5cdFx0XHRpZiAoIHZhbHVlID09IG51bGwgfHwgdmFsdWUgIT09IHZhbHVlICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgbnVtYmVyIHdhcyBwYXNzZWQgaW4sIGFkZCB0aGUgdW5pdCAoZXhjZXB0IGZvciBjZXJ0YWluIENTUyBwcm9wZXJ0aWVzKVxuXHRcdFx0aWYgKCB0eXBlID09PSBcIm51bWJlclwiICkge1xuXHRcdFx0XHR2YWx1ZSArPSByZXQgJiYgcmV0WyAzIF0gfHwgKCBqUXVlcnkuY3NzTnVtYmVyWyBvcmlnTmFtZSBdID8gXCJcIiA6IFwicHhcIiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBiYWNrZ3JvdW5kLSogcHJvcHMgYWZmZWN0IG9yaWdpbmFsIGNsb25lJ3MgdmFsdWVzXG5cdFx0XHRpZiAoICFzdXBwb3J0LmNsZWFyQ2xvbmVTdHlsZSAmJiB2YWx1ZSA9PT0gXCJcIiAmJiBuYW1lLmluZGV4T2YoIFwiYmFja2dyb3VuZFwiICkgPT09IDAgKSB7XG5cdFx0XHRcdHN0eWxlWyBuYW1lIF0gPSBcImluaGVyaXRcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgYSBob29rIHdhcyBwcm92aWRlZCwgdXNlIHRoYXQgdmFsdWUsIG90aGVyd2lzZSBqdXN0IHNldCB0aGUgc3BlY2lmaWVkIHZhbHVlXG5cdFx0XHRpZiAoICFob29rcyB8fCAhKCBcInNldFwiIGluIGhvb2tzICkgfHxcblx0XHRcdFx0KCB2YWx1ZSA9IGhvb2tzLnNldCggZWxlbSwgdmFsdWUsIGV4dHJhICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHRcdGlmICggaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0XHRcdHN0eWxlLnNldFByb3BlcnR5KCBuYW1lLCB2YWx1ZSApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHN0eWxlWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gSWYgYSBob29rIHdhcyBwcm92aWRlZCBnZXQgdGhlIG5vbi1jb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0XHRpZiAoIGhvb2tzICYmIFwiZ2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5nZXQoIGVsZW0sIGZhbHNlLCBleHRyYSApICkgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPdGhlcndpc2UganVzdCBnZXQgdGhlIHZhbHVlIGZyb20gdGhlIHN0eWxlIG9iamVjdFxuXHRcdFx0cmV0dXJuIHN0eWxlWyBuYW1lIF07XG5cdFx0fVxuXHR9LFxuXG5cdGNzczogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGV4dHJhLCBzdHlsZXMgKSB7XG5cdFx0dmFyIHZhbCwgbnVtLCBob29rcyxcblx0XHRcdG9yaWdOYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZSApLFxuXHRcdFx0aXNDdXN0b21Qcm9wID0gcmN1c3RvbVByb3AudGVzdCggbmFtZSApO1xuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lLiBXZSBkb24ndFxuXHRcdC8vIHdhbnQgdG8gbW9kaWZ5IHRoZSB2YWx1ZSBpZiBpdCBpcyBhIENTUyBjdXN0b20gcHJvcGVydHlcblx0XHQvLyBzaW5jZSB0aGV5IGFyZSB1c2VyLWRlZmluZWQuXG5cdFx0aWYgKCAhaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0bmFtZSA9IGZpbmFsUHJvcE5hbWUoIG9yaWdOYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gVHJ5IHByZWZpeGVkIG5hbWUgZm9sbG93ZWQgYnkgdGhlIHVucHJlZml4ZWQgbmFtZVxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF0gfHwgalF1ZXJ5LmNzc0hvb2tzWyBvcmlnTmFtZSBdO1xuXG5cdFx0Ly8gSWYgYSBob29rIHdhcyBwcm92aWRlZCBnZXQgdGhlIGNvbXB1dGVkIHZhbHVlIGZyb20gdGhlcmVcblx0XHRpZiAoIGhvb2tzICYmIFwiZ2V0XCIgaW4gaG9va3MgKSB7XG5cdFx0XHR2YWwgPSBob29rcy5nZXQoIGVsZW0sIHRydWUsIGV4dHJhICk7XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXJ3aXNlLCBpZiBhIHdheSB0byBnZXQgdGhlIGNvbXB1dGVkIHZhbHVlIGV4aXN0cywgdXNlIHRoYXRcblx0XHRpZiAoIHZhbCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dmFsID0gY3VyQ1NTKCBlbGVtLCBuYW1lLCBzdHlsZXMgKTtcblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IFwibm9ybWFsXCIgdG8gY29tcHV0ZWQgdmFsdWVcblx0XHRpZiAoIHZhbCA9PT0gXCJub3JtYWxcIiAmJiBuYW1lIGluIGNzc05vcm1hbFRyYW5zZm9ybSApIHtcblx0XHRcdHZhbCA9IGNzc05vcm1hbFRyYW5zZm9ybVsgbmFtZSBdO1xuXHRcdH1cblxuXHRcdC8vIE1ha2UgbnVtZXJpYyBpZiBmb3JjZWQgb3IgYSBxdWFsaWZpZXIgd2FzIHByb3ZpZGVkIGFuZCB2YWwgbG9va3MgbnVtZXJpY1xuXHRcdGlmICggZXh0cmEgPT09IFwiXCIgfHwgZXh0cmEgKSB7XG5cdFx0XHRudW0gPSBwYXJzZUZsb2F0KCB2YWwgKTtcblx0XHRcdHJldHVybiBleHRyYSA9PT0gdHJ1ZSB8fCBpc0Zpbml0ZSggbnVtICkgPyBudW0gfHwgMCA6IHZhbDtcblx0XHR9XG5cblx0XHRyZXR1cm4gdmFsO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCBbIFwiaGVpZ2h0XCIsIFwid2lkdGhcIiBdLCBmdW5jdGlvbiggaSwgbmFtZSApIHtcblx0alF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF0gPSB7XG5cdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSwgY29tcHV0ZWQsIGV4dHJhICkge1xuXHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblxuXHRcdFx0XHQvLyBDZXJ0YWluIGVsZW1lbnRzIGNhbiBoYXZlIGRpbWVuc2lvbiBpbmZvIGlmIHdlIGludmlzaWJseSBzaG93IHRoZW1cblx0XHRcdFx0Ly8gYnV0IGl0IG11c3QgaGF2ZSBhIGN1cnJlbnQgZGlzcGxheSBzdHlsZSB0aGF0IHdvdWxkIGJlbmVmaXRcblx0XHRcdFx0cmV0dXJuIHJkaXNwbGF5c3dhcC50ZXN0KCBqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApICkgJiZcblxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFNhZmFyaSA4K1xuXHRcdFx0XHRcdC8vIFRhYmxlIGNvbHVtbnMgaW4gU2FmYXJpIGhhdmUgbm9uLXplcm8gb2Zmc2V0V2lkdGggJiB6ZXJvXG5cdFx0XHRcdFx0Ly8gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggdW5sZXNzIGRpc3BsYXkgaXMgY2hhbmdlZC5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0XHRcdFx0XHQvLyBSdW5uaW5nIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBvbiBhIGRpc2Nvbm5lY3RlZCBub2RlXG5cdFx0XHRcdFx0Ly8gaW4gSUUgdGhyb3dzIGFuIGVycm9yLlxuXHRcdFx0XHRcdCggIWVsZW0uZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGggfHwgIWVsZW0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggKSA/XG5cdFx0XHRcdFx0XHRzd2FwKCBlbGVtLCBjc3NTaG93LCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICk7XG5cdFx0XHRcdFx0XHR9ICkgOlxuXHRcdFx0XHRcdFx0Z2V0V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEgKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUsIGV4dHJhICkge1xuXHRcdFx0dmFyIG1hdGNoZXMsXG5cdFx0XHRcdHN0eWxlcyA9IGV4dHJhICYmIGdldFN0eWxlcyggZWxlbSApLFxuXHRcdFx0XHRzdWJ0cmFjdCA9IGV4dHJhICYmIGF1Z21lbnRXaWR0aE9ySGVpZ2h0KFxuXHRcdFx0XHRcdGVsZW0sXG5cdFx0XHRcdFx0bmFtZSxcblx0XHRcdFx0XHRleHRyYSxcblx0XHRcdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBcImJveFNpemluZ1wiLCBmYWxzZSwgc3R5bGVzICkgPT09IFwiYm9yZGVyLWJveFwiLFxuXHRcdFx0XHRcdHN0eWxlc1xuXHRcdFx0XHQpO1xuXG5cdFx0XHQvLyBDb252ZXJ0IHRvIHBpeGVscyBpZiB2YWx1ZSBhZGp1c3RtZW50IGlzIG5lZWRlZFxuXHRcdFx0aWYgKCBzdWJ0cmFjdCAmJiAoIG1hdGNoZXMgPSByY3NzTnVtLmV4ZWMoIHZhbHVlICkgKSAmJlxuXHRcdFx0XHQoIG1hdGNoZXNbIDMgXSB8fCBcInB4XCIgKSAhPT0gXCJweFwiICkge1xuXG5cdFx0XHRcdGVsZW0uc3R5bGVbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0XHR2YWx1ZSA9IGpRdWVyeS5jc3MoIGVsZW0sIG5hbWUgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHNldFBvc2l0aXZlTnVtYmVyKCBlbGVtLCB2YWx1ZSwgc3VidHJhY3QgKTtcblx0XHR9XG5cdH07XG59ICk7XG5cbmpRdWVyeS5jc3NIb29rcy5tYXJnaW5MZWZ0ID0gYWRkR2V0SG9va0lmKCBzdXBwb3J0LnJlbGlhYmxlTWFyZ2luTGVmdCxcblx0ZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkICkge1xuXHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4gKCBwYXJzZUZsb2F0KCBjdXJDU1MoIGVsZW0sIFwibWFyZ2luTGVmdFwiICkgKSB8fFxuXHRcdFx0XHRlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLVxuXHRcdFx0XHRcdHN3YXAoIGVsZW0sIHsgbWFyZ2luTGVmdDogMCB9LCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQ7XG5cdFx0XHRcdFx0fSApXG5cdFx0XHRcdCkgKyBcInB4XCI7XG5cdFx0fVxuXHR9XG4pO1xuXG4vLyBUaGVzZSBob29rcyBhcmUgdXNlZCBieSBhbmltYXRlIHRvIGV4cGFuZCBwcm9wZXJ0aWVzXG5qUXVlcnkuZWFjaCgge1xuXHRtYXJnaW46IFwiXCIsXG5cdHBhZGRpbmc6IFwiXCIsXG5cdGJvcmRlcjogXCJXaWR0aFwiXG59LCBmdW5jdGlvbiggcHJlZml4LCBzdWZmaXggKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgcHJlZml4ICsgc3VmZml4IF0gPSB7XG5cdFx0ZXhwYW5kOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgaSA9IDAsXG5cdFx0XHRcdGV4cGFuZGVkID0ge30sXG5cblx0XHRcdFx0Ly8gQXNzdW1lcyBhIHNpbmdsZSBudW1iZXIgaWYgbm90IGEgc3RyaW5nXG5cdFx0XHRcdHBhcnRzID0gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiID8gdmFsdWUuc3BsaXQoIFwiIFwiICkgOiBbIHZhbHVlIF07XG5cblx0XHRcdGZvciAoIDsgaSA8IDQ7IGkrKyApIHtcblx0XHRcdFx0ZXhwYW5kZWRbIHByZWZpeCArIGNzc0V4cGFuZFsgaSBdICsgc3VmZml4IF0gPVxuXHRcdFx0XHRcdHBhcnRzWyBpIF0gfHwgcGFydHNbIGkgLSAyIF0gfHwgcGFydHNbIDAgXTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGV4cGFuZGVkO1xuXHRcdH1cblx0fTtcblxuXHRpZiAoICFybWFyZ2luLnRlc3QoIHByZWZpeCApICkge1xuXHRcdGpRdWVyeS5jc3NIb29rc1sgcHJlZml4ICsgc3VmZml4IF0uc2V0ID0gc2V0UG9zaXRpdmVOdW1iZXI7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRjc3M6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgc3R5bGVzLCBsZW4sXG5cdFx0XHRcdG1hcCA9IHt9LFxuXHRcdFx0XHRpID0gMDtcblxuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBuYW1lICkgKSB7XG5cdFx0XHRcdHN0eWxlcyA9IGdldFN0eWxlcyggZWxlbSApO1xuXHRcdFx0XHRsZW4gPSBuYW1lLmxlbmd0aDtcblxuXHRcdFx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0XHRtYXBbIG5hbWVbIGkgXSBdID0galF1ZXJ5LmNzcyggZWxlbSwgbmFtZVsgaSBdLCBmYWxzZSwgc3R5bGVzICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gbWFwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdmFsdWUgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgbmFtZSwgdmFsdWUgKSA6XG5cdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIG5hbWUgKTtcblx0XHR9LCBuYW1lLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEgKTtcblx0fVxufSApO1xuXG5cbmZ1bmN0aW9uIFR3ZWVuKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZyApIHtcblx0cmV0dXJuIG5ldyBUd2Vlbi5wcm90b3R5cGUuaW5pdCggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKTtcbn1cbmpRdWVyeS5Ud2VlbiA9IFR3ZWVuO1xuXG5Ud2Vlbi5wcm90b3R5cGUgPSB7XG5cdGNvbnN0cnVjdG9yOiBUd2Vlbixcblx0aW5pdDogZnVuY3Rpb24oIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nLCB1bml0ICkge1xuXHRcdHRoaXMuZWxlbSA9IGVsZW07XG5cdFx0dGhpcy5wcm9wID0gcHJvcDtcblx0XHR0aGlzLmVhc2luZyA9IGVhc2luZyB8fCBqUXVlcnkuZWFzaW5nLl9kZWZhdWx0O1xuXHRcdHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cdFx0dGhpcy5zdGFydCA9IHRoaXMubm93ID0gdGhpcy5jdXIoKTtcblx0XHR0aGlzLmVuZCA9IGVuZDtcblx0XHR0aGlzLnVuaXQgPSB1bml0IHx8ICggalF1ZXJ5LmNzc051bWJlclsgcHJvcCBdID8gXCJcIiA6IFwicHhcIiApO1xuXHR9LFxuXHRjdXI6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBob29rcyA9IFR3ZWVuLnByb3BIb29rc1sgdGhpcy5wcm9wIF07XG5cblx0XHRyZXR1cm4gaG9va3MgJiYgaG9va3MuZ2V0ID9cblx0XHRcdGhvb2tzLmdldCggdGhpcyApIDpcblx0XHRcdFR3ZWVuLnByb3BIb29rcy5fZGVmYXVsdC5nZXQoIHRoaXMgKTtcblx0fSxcblx0cnVuOiBmdW5jdGlvbiggcGVyY2VudCApIHtcblx0XHR2YXIgZWFzZWQsXG5cdFx0XHRob29rcyA9IFR3ZWVuLnByb3BIb29rc1sgdGhpcy5wcm9wIF07XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5kdXJhdGlvbiApIHtcblx0XHRcdHRoaXMucG9zID0gZWFzZWQgPSBqUXVlcnkuZWFzaW5nWyB0aGlzLmVhc2luZyBdKFxuXHRcdFx0XHRwZXJjZW50LCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKiBwZXJjZW50LCAwLCAxLCB0aGlzLm9wdGlvbnMuZHVyYXRpb25cblx0XHRcdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucG9zID0gZWFzZWQgPSBwZXJjZW50O1xuXHRcdH1cblx0XHR0aGlzLm5vdyA9ICggdGhpcy5lbmQgLSB0aGlzLnN0YXJ0ICkgKiBlYXNlZCArIHRoaXMuc3RhcnQ7XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5zdGVwICkge1xuXHRcdFx0dGhpcy5vcHRpb25zLnN0ZXAuY2FsbCggdGhpcy5lbGVtLCB0aGlzLm5vdywgdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgaG9va3Muc2V0ICkge1xuXHRcdFx0aG9va3Muc2V0KCB0aGlzICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdFR3ZWVuLnByb3BIb29rcy5fZGVmYXVsdC5zZXQoIHRoaXMgKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn07XG5cblR3ZWVuLnByb3RvdHlwZS5pbml0LnByb3RvdHlwZSA9IFR3ZWVuLnByb3RvdHlwZTtcblxuVHdlZW4ucHJvcEhvb2tzID0ge1xuXHRfZGVmYXVsdDoge1xuXHRcdGdldDogZnVuY3Rpb24oIHR3ZWVuICkge1xuXHRcdFx0dmFyIHJlc3VsdDtcblxuXHRcdFx0Ly8gVXNlIGEgcHJvcGVydHkgb24gdGhlIGVsZW1lbnQgZGlyZWN0bHkgd2hlbiBpdCBpcyBub3QgYSBET00gZWxlbWVudCxcblx0XHRcdC8vIG9yIHdoZW4gdGhlcmUgaXMgbm8gbWF0Y2hpbmcgc3R5bGUgcHJvcGVydHkgdGhhdCBleGlzdHMuXG5cdFx0XHRpZiAoIHR3ZWVuLmVsZW0ubm9kZVR5cGUgIT09IDEgfHxcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdICE9IG51bGwgJiYgdHdlZW4uZWxlbS5zdHlsZVsgdHdlZW4ucHJvcCBdID09IG51bGwgKSB7XG5cdFx0XHRcdHJldHVybiB0d2Vlbi5lbGVtWyB0d2Vlbi5wcm9wIF07XG5cdFx0XHR9XG5cblx0XHRcdC8vIFBhc3NpbmcgYW4gZW1wdHkgc3RyaW5nIGFzIGEgM3JkIHBhcmFtZXRlciB0byAuY3NzIHdpbGwgYXV0b21hdGljYWxseVxuXHRcdFx0Ly8gYXR0ZW1wdCBhIHBhcnNlRmxvYXQgYW5kIGZhbGxiYWNrIHRvIGEgc3RyaW5nIGlmIHRoZSBwYXJzZSBmYWlscy5cblx0XHRcdC8vIFNpbXBsZSB2YWx1ZXMgc3VjaCBhcyBcIjEwcHhcIiBhcmUgcGFyc2VkIHRvIEZsb2F0O1xuXHRcdFx0Ly8gY29tcGxleCB2YWx1ZXMgc3VjaCBhcyBcInJvdGF0ZSgxcmFkKVwiIGFyZSByZXR1cm5lZCBhcy1pcy5cblx0XHRcdHJlc3VsdCA9IGpRdWVyeS5jc3MoIHR3ZWVuLmVsZW0sIHR3ZWVuLnByb3AsIFwiXCIgKTtcblxuXHRcdFx0Ly8gRW1wdHkgc3RyaW5ncywgbnVsbCwgdW5kZWZpbmVkIGFuZCBcImF1dG9cIiBhcmUgY29udmVydGVkIHRvIDAuXG5cdFx0XHRyZXR1cm4gIXJlc3VsdCB8fCByZXN1bHQgPT09IFwiYXV0b1wiID8gMCA6IHJlc3VsdDtcblx0XHR9LFxuXHRcdHNldDogZnVuY3Rpb24oIHR3ZWVuICkge1xuXG5cdFx0XHQvLyBVc2Ugc3RlcCBob29rIGZvciBiYWNrIGNvbXBhdC5cblx0XHRcdC8vIFVzZSBjc3NIb29rIGlmIGl0cyB0aGVyZS5cblx0XHRcdC8vIFVzZSAuc3R5bGUgaWYgYXZhaWxhYmxlIGFuZCB1c2UgcGxhaW4gcHJvcGVydGllcyB3aGVyZSBhdmFpbGFibGUuXG5cdFx0XHRpZiAoIGpRdWVyeS5meC5zdGVwWyB0d2Vlbi5wcm9wIF0gKSB7XG5cdFx0XHRcdGpRdWVyeS5meC5zdGVwWyB0d2Vlbi5wcm9wIF0oIHR3ZWVuICk7XG5cdFx0XHR9IGVsc2UgaWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdCggdHdlZW4uZWxlbS5zdHlsZVsgalF1ZXJ5LmNzc1Byb3BzWyB0d2Vlbi5wcm9wIF0gXSAhPSBudWxsIHx8XG5cdFx0XHRcdFx0alF1ZXJ5LmNzc0hvb2tzWyB0d2Vlbi5wcm9wIF0gKSApIHtcblx0XHRcdFx0alF1ZXJ5LnN0eWxlKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCB0d2Vlbi5ub3cgKyB0d2Vlbi51bml0ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0d2Vlbi5lbGVtWyB0d2Vlbi5wcm9wIF0gPSB0d2Vlbi5ub3c7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59O1xuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuLy8gUGFuaWMgYmFzZWQgYXBwcm9hY2ggdG8gc2V0dGluZyB0aGluZ3Mgb24gZGlzY29ubmVjdGVkIG5vZGVzXG5Ud2Vlbi5wcm9wSG9va3Muc2Nyb2xsVG9wID0gVHdlZW4ucHJvcEhvb2tzLnNjcm9sbExlZnQgPSB7XG5cdHNldDogZnVuY3Rpb24oIHR3ZWVuICkge1xuXHRcdGlmICggdHdlZW4uZWxlbS5ub2RlVHlwZSAmJiB0d2Vlbi5lbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHR0d2Vlbi5lbGVtWyB0d2Vlbi5wcm9wIF0gPSB0d2Vlbi5ub3c7XG5cdFx0fVxuXHR9XG59O1xuXG5qUXVlcnkuZWFzaW5nID0ge1xuXHRsaW5lYXI6IGZ1bmN0aW9uKCBwICkge1xuXHRcdHJldHVybiBwO1xuXHR9LFxuXHRzd2luZzogZnVuY3Rpb24oIHAgKSB7XG5cdFx0cmV0dXJuIDAuNSAtIE1hdGguY29zKCBwICogTWF0aC5QSSApIC8gMjtcblx0fSxcblx0X2RlZmF1bHQ6IFwic3dpbmdcIlxufTtcblxualF1ZXJ5LmZ4ID0gVHdlZW4ucHJvdG90eXBlLmluaXQ7XG5cbi8vIEJhY2sgY29tcGF0IDwxLjggZXh0ZW5zaW9uIHBvaW50XG5qUXVlcnkuZnguc3RlcCA9IHt9O1xuXG5cblxuXG52YXJcblx0ZnhOb3csIGluUHJvZ3Jlc3MsXG5cdHJmeHR5cGVzID0gL14oPzp0b2dnbGV8c2hvd3xoaWRlKSQvLFxuXHRycnVuID0gL3F1ZXVlSG9va3MkLztcblxuZnVuY3Rpb24gc2NoZWR1bGUoKSB7XG5cdGlmICggaW5Qcm9ncmVzcyApIHtcblx0XHRpZiAoIGRvY3VtZW50LmhpZGRlbiA9PT0gZmFsc2UgJiYgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSApIHtcblx0XHRcdHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoIHNjaGVkdWxlICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBzY2hlZHVsZSwgalF1ZXJ5LmZ4LmludGVydmFsICk7XG5cdFx0fVxuXG5cdFx0alF1ZXJ5LmZ4LnRpY2soKTtcblx0fVxufVxuXG4vLyBBbmltYXRpb25zIGNyZWF0ZWQgc3luY2hyb25vdXNseSB3aWxsIHJ1biBzeW5jaHJvbm91c2x5XG5mdW5jdGlvbiBjcmVhdGVGeE5vdygpIHtcblx0d2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdGZ4Tm93ID0gdW5kZWZpbmVkO1xuXHR9ICk7XG5cdHJldHVybiAoIGZ4Tm93ID0galF1ZXJ5Lm5vdygpICk7XG59XG5cbi8vIEdlbmVyYXRlIHBhcmFtZXRlcnMgdG8gY3JlYXRlIGEgc3RhbmRhcmQgYW5pbWF0aW9uXG5mdW5jdGlvbiBnZW5GeCggdHlwZSwgaW5jbHVkZVdpZHRoICkge1xuXHR2YXIgd2hpY2gsXG5cdFx0aSA9IDAsXG5cdFx0YXR0cnMgPSB7IGhlaWdodDogdHlwZSB9O1xuXG5cdC8vIElmIHdlIGluY2x1ZGUgd2lkdGgsIHN0ZXAgdmFsdWUgaXMgMSB0byBkbyBhbGwgY3NzRXhwYW5kIHZhbHVlcyxcblx0Ly8gb3RoZXJ3aXNlIHN0ZXAgdmFsdWUgaXMgMiB0byBza2lwIG92ZXIgTGVmdCBhbmQgUmlnaHRcblx0aW5jbHVkZVdpZHRoID0gaW5jbHVkZVdpZHRoID8gMSA6IDA7XG5cdGZvciAoIDsgaSA8IDQ7IGkgKz0gMiAtIGluY2x1ZGVXaWR0aCApIHtcblx0XHR3aGljaCA9IGNzc0V4cGFuZFsgaSBdO1xuXHRcdGF0dHJzWyBcIm1hcmdpblwiICsgd2hpY2ggXSA9IGF0dHJzWyBcInBhZGRpbmdcIiArIHdoaWNoIF0gPSB0eXBlO1xuXHR9XG5cblx0aWYgKCBpbmNsdWRlV2lkdGggKSB7XG5cdFx0YXR0cnMub3BhY2l0eSA9IGF0dHJzLndpZHRoID0gdHlwZTtcblx0fVxuXG5cdHJldHVybiBhdHRycztcbn1cblxuZnVuY3Rpb24gY3JlYXRlVHdlZW4oIHZhbHVlLCBwcm9wLCBhbmltYXRpb24gKSB7XG5cdHZhciB0d2Vlbixcblx0XHRjb2xsZWN0aW9uID0gKCBBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXSB8fCBbXSApLmNvbmNhdCggQW5pbWF0aW9uLnR3ZWVuZXJzWyBcIipcIiBdICksXG5cdFx0aW5kZXggPSAwLFxuXHRcdGxlbmd0aCA9IGNvbGxlY3Rpb24ubGVuZ3RoO1xuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGlmICggKCB0d2VlbiA9IGNvbGxlY3Rpb25bIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBwcm9wLCB2YWx1ZSApICkgKSB7XG5cblx0XHRcdC8vIFdlJ3JlIGRvbmUgd2l0aCB0aGlzIHByb3BlcnR5XG5cdFx0XHRyZXR1cm4gdHdlZW47XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRQcmVmaWx0ZXIoIGVsZW0sIHByb3BzLCBvcHRzICkge1xuXHR2YXIgcHJvcCwgdmFsdWUsIHRvZ2dsZSwgaG9va3MsIG9sZGZpcmUsIHByb3BUd2VlbiwgcmVzdG9yZURpc3BsYXksIGRpc3BsYXksXG5cdFx0aXNCb3ggPSBcIndpZHRoXCIgaW4gcHJvcHMgfHwgXCJoZWlnaHRcIiBpbiBwcm9wcyxcblx0XHRhbmltID0gdGhpcyxcblx0XHRvcmlnID0ge30sXG5cdFx0c3R5bGUgPSBlbGVtLnN0eWxlLFxuXHRcdGhpZGRlbiA9IGVsZW0ubm9kZVR5cGUgJiYgaXNIaWRkZW5XaXRoaW5UcmVlKCBlbGVtICksXG5cdFx0ZGF0YVNob3cgPSBkYXRhUHJpdi5nZXQoIGVsZW0sIFwiZnhzaG93XCIgKTtcblxuXHQvLyBRdWV1ZS1za2lwcGluZyBhbmltYXRpb25zIGhpamFjayB0aGUgZnggaG9va3Ncblx0aWYgKCAhb3B0cy5xdWV1ZSApIHtcblx0XHRob29rcyA9IGpRdWVyeS5fcXVldWVIb29rcyggZWxlbSwgXCJmeFwiICk7XG5cdFx0aWYgKCBob29rcy51bnF1ZXVlZCA9PSBudWxsICkge1xuXHRcdFx0aG9va3MudW5xdWV1ZWQgPSAwO1xuXHRcdFx0b2xkZmlyZSA9IGhvb2tzLmVtcHR5LmZpcmU7XG5cdFx0XHRob29rcy5lbXB0eS5maXJlID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggIWhvb2tzLnVucXVldWVkICkge1xuXHRcdFx0XHRcdG9sZGZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9XG5cdFx0aG9va3MudW5xdWV1ZWQrKztcblxuXHRcdGFuaW0uYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRW5zdXJlIHRoZSBjb21wbGV0ZSBoYW5kbGVyIGlzIGNhbGxlZCBiZWZvcmUgdGhpcyBjb21wbGV0ZXNcblx0XHRcdGFuaW0uYWx3YXlzKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aG9va3MudW5xdWV1ZWQtLTtcblx0XHRcdFx0aWYgKCAhalF1ZXJ5LnF1ZXVlKCBlbGVtLCBcImZ4XCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gRGV0ZWN0IHNob3cvaGlkZSBhbmltYXRpb25zXG5cdGZvciAoIHByb3AgaW4gcHJvcHMgKSB7XG5cdFx0dmFsdWUgPSBwcm9wc1sgcHJvcCBdO1xuXHRcdGlmICggcmZ4dHlwZXMudGVzdCggdmFsdWUgKSApIHtcblx0XHRcdGRlbGV0ZSBwcm9wc1sgcHJvcCBdO1xuXHRcdFx0dG9nZ2xlID0gdG9nZ2xlIHx8IHZhbHVlID09PSBcInRvZ2dsZVwiO1xuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gKCBoaWRkZW4gPyBcImhpZGVcIiA6IFwic2hvd1wiICkgKSB7XG5cblx0XHRcdFx0Ly8gUHJldGVuZCB0byBiZSBoaWRkZW4gaWYgdGhpcyBpcyBhIFwic2hvd1wiIGFuZFxuXHRcdFx0XHQvLyB0aGVyZSBpcyBzdGlsbCBkYXRhIGZyb20gYSBzdG9wcGVkIHNob3cvaGlkZVxuXHRcdFx0XHRpZiAoIHZhbHVlID09PSBcInNob3dcIiAmJiBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0aGlkZGVuID0gdHJ1ZTtcblxuXHRcdFx0XHQvLyBJZ25vcmUgYWxsIG90aGVyIG5vLW9wIHNob3cvaGlkZSBkYXRhXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdG9yaWdbIHByb3AgXSA9IGRhdGFTaG93ICYmIGRhdGFTaG93WyBwcm9wIF0gfHwgalF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wICk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQmFpbCBvdXQgaWYgdGhpcyBpcyBhIG5vLW9wIGxpa2UgLmhpZGUoKS5oaWRlKClcblx0cHJvcFR3ZWVuID0gIWpRdWVyeS5pc0VtcHR5T2JqZWN0KCBwcm9wcyApO1xuXHRpZiAoICFwcm9wVHdlZW4gJiYgalF1ZXJ5LmlzRW1wdHlPYmplY3QoIG9yaWcgKSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBSZXN0cmljdCBcIm92ZXJmbG93XCIgYW5kIFwiZGlzcGxheVwiIHN0eWxlcyBkdXJpbmcgYm94IGFuaW1hdGlvbnNcblx0aWYgKCBpc0JveCAmJiBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHRcdC8vIFJlY29yZCBhbGwgMyBvdmVyZmxvdyBhdHRyaWJ1dGVzIGJlY2F1c2UgSUUgZG9lcyBub3QgaW5mZXIgdGhlIHNob3J0aGFuZFxuXHRcdC8vIGZyb20gaWRlbnRpY2FsbHktdmFsdWVkIG92ZXJmbG93WCBhbmQgb3ZlcmZsb3dZXG5cdFx0b3B0cy5vdmVyZmxvdyA9IFsgc3R5bGUub3ZlcmZsb3csIHN0eWxlLm92ZXJmbG93WCwgc3R5bGUub3ZlcmZsb3dZIF07XG5cblx0XHQvLyBJZGVudGlmeSBhIGRpc3BsYXkgdHlwZSwgcHJlZmVycmluZyBvbGQgc2hvdy9oaWRlIGRhdGEgb3ZlciB0aGUgQ1NTIGNhc2NhZGVcblx0XHRyZXN0b3JlRGlzcGxheSA9IGRhdGFTaG93ICYmIGRhdGFTaG93LmRpc3BsYXk7XG5cdFx0aWYgKCByZXN0b3JlRGlzcGxheSA9PSBudWxsICkge1xuXHRcdFx0cmVzdG9yZURpc3BsYXkgPSBkYXRhUHJpdi5nZXQoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cdFx0fVxuXHRcdGRpc3BsYXkgPSBqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApO1xuXHRcdGlmICggZGlzcGxheSA9PT0gXCJub25lXCIgKSB7XG5cdFx0XHRpZiAoIHJlc3RvcmVEaXNwbGF5ICkge1xuXHRcdFx0XHRkaXNwbGF5ID0gcmVzdG9yZURpc3BsYXk7XG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIEdldCBub25lbXB0eSB2YWx1ZShzKSBieSB0ZW1wb3JhcmlseSBmb3JjaW5nIHZpc2liaWxpdHlcblx0XHRcdFx0c2hvd0hpZGUoIFsgZWxlbSBdLCB0cnVlICk7XG5cdFx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZWxlbS5zdHlsZS5kaXNwbGF5IHx8IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0XHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKTtcblx0XHRcdFx0c2hvd0hpZGUoIFsgZWxlbSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQW5pbWF0ZSBpbmxpbmUgZWxlbWVudHMgYXMgaW5saW5lLWJsb2NrXG5cdFx0aWYgKCBkaXNwbGF5ID09PSBcImlubGluZVwiIHx8IGRpc3BsYXkgPT09IFwiaW5saW5lLWJsb2NrXCIgJiYgcmVzdG9yZURpc3BsYXkgIT0gbnVsbCApIHtcblx0XHRcdGlmICggalF1ZXJ5LmNzcyggZWxlbSwgXCJmbG9hdFwiICkgPT09IFwibm9uZVwiICkge1xuXG5cdFx0XHRcdC8vIFJlc3RvcmUgdGhlIG9yaWdpbmFsIGRpc3BsYXkgdmFsdWUgYXQgdGhlIGVuZCBvZiBwdXJlIHNob3cvaGlkZSBhbmltYXRpb25zXG5cdFx0XHRcdGlmICggIXByb3BUd2VlbiApIHtcblx0XHRcdFx0XHRhbmltLmRvbmUoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0c3R5bGUuZGlzcGxheSA9IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRpZiAoIHJlc3RvcmVEaXNwbGF5ID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRkaXNwbGF5ID0gc3R5bGUuZGlzcGxheTtcblx0XHRcdFx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZGlzcGxheSA9PT0gXCJub25lXCIgPyBcIlwiIDogZGlzcGxheTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0c3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0aWYgKCBvcHRzLm92ZXJmbG93ICkge1xuXHRcdHN0eWxlLm92ZXJmbG93ID0gXCJoaWRkZW5cIjtcblx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cdFx0XHRzdHlsZS5vdmVyZmxvdyA9IG9wdHMub3ZlcmZsb3dbIDAgXTtcblx0XHRcdHN0eWxlLm92ZXJmbG93WCA9IG9wdHMub3ZlcmZsb3dbIDEgXTtcblx0XHRcdHN0eWxlLm92ZXJmbG93WSA9IG9wdHMub3ZlcmZsb3dbIDIgXTtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBJbXBsZW1lbnQgc2hvdy9oaWRlIGFuaW1hdGlvbnNcblx0cHJvcFR3ZWVuID0gZmFsc2U7XG5cdGZvciAoIHByb3AgaW4gb3JpZyApIHtcblxuXHRcdC8vIEdlbmVyYWwgc2hvdy9oaWRlIHNldHVwIGZvciB0aGlzIGVsZW1lbnQgYW5pbWF0aW9uXG5cdFx0aWYgKCAhcHJvcFR3ZWVuICkge1xuXHRcdFx0aWYgKCBkYXRhU2hvdyApIHtcblx0XHRcdFx0aWYgKCBcImhpZGRlblwiIGluIGRhdGFTaG93ICkge1xuXHRcdFx0XHRcdGhpZGRlbiA9IGRhdGFTaG93LmhpZGRlbjtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGF0YVNob3cgPSBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIFwiZnhzaG93XCIsIHsgZGlzcGxheTogcmVzdG9yZURpc3BsYXkgfSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdG9yZSBoaWRkZW4vdmlzaWJsZSBmb3IgdG9nZ2xlIHNvIGAuc3RvcCgpLnRvZ2dsZSgpYCBcInJldmVyc2VzXCJcblx0XHRcdGlmICggdG9nZ2xlICkge1xuXHRcdFx0XHRkYXRhU2hvdy5oaWRkZW4gPSAhaGlkZGVuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTaG93IGVsZW1lbnRzIGJlZm9yZSBhbmltYXRpbmcgdGhlbVxuXHRcdFx0aWYgKCBoaWRkZW4gKSB7XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSwgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvKiBlc2xpbnQtZGlzYWJsZSBuby1sb29wLWZ1bmMgKi9cblxuXHRcdFx0YW5pbS5kb25lKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0LyogZXNsaW50LWVuYWJsZSBuby1sb29wLWZ1bmMgKi9cblxuXHRcdFx0XHQvLyBUaGUgZmluYWwgc3RlcCBvZiBhIFwiaGlkZVwiIGFuaW1hdGlvbiBpcyBhY3R1YWxseSBoaWRpbmcgdGhlIGVsZW1lbnRcblx0XHRcdFx0aWYgKCAhaGlkZGVuICkge1xuXHRcdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgXCJmeHNob3dcIiApO1xuXHRcdFx0XHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wLCBvcmlnWyBwcm9wIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdC8vIFBlci1wcm9wZXJ0eSBzZXR1cFxuXHRcdHByb3BUd2VlbiA9IGNyZWF0ZVR3ZWVuKCBoaWRkZW4gPyBkYXRhU2hvd1sgcHJvcCBdIDogMCwgcHJvcCwgYW5pbSApO1xuXHRcdGlmICggISggcHJvcCBpbiBkYXRhU2hvdyApICkge1xuXHRcdFx0ZGF0YVNob3dbIHByb3AgXSA9IHByb3BUd2Vlbi5zdGFydDtcblx0XHRcdGlmICggaGlkZGVuICkge1xuXHRcdFx0XHRwcm9wVHdlZW4uZW5kID0gcHJvcFR3ZWVuLnN0YXJ0O1xuXHRcdFx0XHRwcm9wVHdlZW4uc3RhcnQgPSAwO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBwcm9wRmlsdGVyKCBwcm9wcywgc3BlY2lhbEVhc2luZyApIHtcblx0dmFyIGluZGV4LCBuYW1lLCBlYXNpbmcsIHZhbHVlLCBob29rcztcblxuXHQvLyBjYW1lbENhc2UsIHNwZWNpYWxFYXNpbmcgYW5kIGV4cGFuZCBjc3NIb29rIHBhc3Ncblx0Zm9yICggaW5kZXggaW4gcHJvcHMgKSB7XG5cdFx0bmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIGluZGV4ICk7XG5cdFx0ZWFzaW5nID0gc3BlY2lhbEVhc2luZ1sgbmFtZSBdO1xuXHRcdHZhbHVlID0gcHJvcHNbIGluZGV4IF07XG5cdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWx1ZSApICkge1xuXHRcdFx0ZWFzaW5nID0gdmFsdWVbIDEgXTtcblx0XHRcdHZhbHVlID0gcHJvcHNbIGluZGV4IF0gPSB2YWx1ZVsgMCBdO1xuXHRcdH1cblxuXHRcdGlmICggaW5kZXggIT09IG5hbWUgKSB7XG5cdFx0XHRwcm9wc1sgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRkZWxldGUgcHJvcHNbIGluZGV4IF07XG5cdFx0fVxuXG5cdFx0aG9va3MgPSBqUXVlcnkuY3NzSG9va3NbIG5hbWUgXTtcblx0XHRpZiAoIGhvb2tzICYmIFwiZXhwYW5kXCIgaW4gaG9va3MgKSB7XG5cdFx0XHR2YWx1ZSA9IGhvb2tzLmV4cGFuZCggdmFsdWUgKTtcblx0XHRcdGRlbGV0ZSBwcm9wc1sgbmFtZSBdO1xuXG5cdFx0XHQvLyBOb3QgcXVpdGUgJC5leHRlbmQsIHRoaXMgd29uJ3Qgb3ZlcndyaXRlIGV4aXN0aW5nIGtleXMuXG5cdFx0XHQvLyBSZXVzaW5nICdpbmRleCcgYmVjYXVzZSB3ZSBoYXZlIHRoZSBjb3JyZWN0IFwibmFtZVwiXG5cdFx0XHRmb3IgKCBpbmRleCBpbiB2YWx1ZSApIHtcblx0XHRcdFx0aWYgKCAhKCBpbmRleCBpbiBwcm9wcyApICkge1xuXHRcdFx0XHRcdHByb3BzWyBpbmRleCBdID0gdmFsdWVbIGluZGV4IF07XG5cdFx0XHRcdFx0c3BlY2lhbEVhc2luZ1sgaW5kZXggXSA9IGVhc2luZztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRzcGVjaWFsRWFzaW5nWyBuYW1lIF0gPSBlYXNpbmc7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIEFuaW1hdGlvbiggZWxlbSwgcHJvcGVydGllcywgb3B0aW9ucyApIHtcblx0dmFyIHJlc3VsdCxcblx0XHRzdG9wcGVkLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBBbmltYXRpb24ucHJlZmlsdGVycy5sZW5ndGgsXG5cdFx0ZGVmZXJyZWQgPSBqUXVlcnkuRGVmZXJyZWQoKS5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBEb24ndCBtYXRjaCBlbGVtIGluIHRoZSA6YW5pbWF0ZWQgc2VsZWN0b3Jcblx0XHRcdGRlbGV0ZSB0aWNrLmVsZW07XG5cdFx0fSApLFxuXHRcdHRpY2sgPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggc3RvcHBlZCApIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGN1cnJlbnRUaW1lID0gZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdFx0cmVtYWluaW5nID0gTWF0aC5tYXgoIDAsIGFuaW1hdGlvbi5zdGFydFRpbWUgKyBhbmltYXRpb24uZHVyYXRpb24gLSBjdXJyZW50VGltZSApLFxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgMi4zIG9ubHlcblx0XHRcdFx0Ly8gQXJjaGFpYyBjcmFzaCBidWcgd29uJ3QgYWxsb3cgdXMgdG8gdXNlIGAxIC0gKCAwLjUgfHwgMCApYCAoIzEyNDk3KVxuXHRcdFx0XHR0ZW1wID0gcmVtYWluaW5nIC8gYW5pbWF0aW9uLmR1cmF0aW9uIHx8IDAsXG5cdFx0XHRcdHBlcmNlbnQgPSAxIC0gdGVtcCxcblx0XHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0XHRsZW5ndGggPSBhbmltYXRpb24udHdlZW5zLmxlbmd0aDtcblxuXHRcdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdFx0YW5pbWF0aW9uLnR3ZWVuc1sgaW5kZXggXS5ydW4oIHBlcmNlbnQgKTtcblx0XHRcdH1cblxuXHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIHBlcmNlbnQsIHJlbWFpbmluZyBdICk7XG5cblx0XHRcdC8vIElmIHRoZXJlJ3MgbW9yZSB0byBkbywgeWllbGRcblx0XHRcdGlmICggcGVyY2VudCA8IDEgJiYgbGVuZ3RoICkge1xuXHRcdFx0XHRyZXR1cm4gcmVtYWluaW5nO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiB0aGlzIHdhcyBhbiBlbXB0eSBhbmltYXRpb24sIHN5bnRoZXNpemUgYSBmaW5hbCBwcm9ncmVzcyBub3RpZmljYXRpb25cblx0XHRcdGlmICggIWxlbmd0aCApIHtcblx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIDEsIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXNvbHZlIHRoZSBhbmltYXRpb24gYW5kIHJlcG9ydCBpdHMgY29uY2x1c2lvblxuXHRcdFx0ZGVmZXJyZWQucmVzb2x2ZVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uIF0gKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9LFxuXHRcdGFuaW1hdGlvbiA9IGRlZmVycmVkLnByb21pc2UoIHtcblx0XHRcdGVsZW06IGVsZW0sXG5cdFx0XHRwcm9wczogalF1ZXJ5LmV4dGVuZCgge30sIHByb3BlcnRpZXMgKSxcblx0XHRcdG9wdHM6IGpRdWVyeS5leHRlbmQoIHRydWUsIHtcblx0XHRcdFx0c3BlY2lhbEVhc2luZzoge30sXG5cdFx0XHRcdGVhc2luZzogalF1ZXJ5LmVhc2luZy5fZGVmYXVsdFxuXHRcdFx0fSwgb3B0aW9ucyApLFxuXHRcdFx0b3JpZ2luYWxQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLFxuXHRcdFx0b3JpZ2luYWxPcHRpb25zOiBvcHRpb25zLFxuXHRcdFx0c3RhcnRUaW1lOiBmeE5vdyB8fCBjcmVhdGVGeE5vdygpLFxuXHRcdFx0ZHVyYXRpb246IG9wdGlvbnMuZHVyYXRpb24sXG5cdFx0XHR0d2VlbnM6IFtdLFxuXHRcdFx0Y3JlYXRlVHdlZW46IGZ1bmN0aW9uKCBwcm9wLCBlbmQgKSB7XG5cdFx0XHRcdHZhciB0d2VlbiA9IGpRdWVyeS5Ud2VlbiggZWxlbSwgYW5pbWF0aW9uLm9wdHMsIHByb3AsIGVuZCxcblx0XHRcdFx0XHRcdGFuaW1hdGlvbi5vcHRzLnNwZWNpYWxFYXNpbmdbIHByb3AgXSB8fCBhbmltYXRpb24ub3B0cy5lYXNpbmcgKTtcblx0XHRcdFx0YW5pbWF0aW9uLnR3ZWVucy5wdXNoKCB0d2VlbiApO1xuXHRcdFx0XHRyZXR1cm4gdHdlZW47XG5cdFx0XHR9LFxuXHRcdFx0c3RvcDogZnVuY3Rpb24oIGdvdG9FbmQgKSB7XG5cdFx0XHRcdHZhciBpbmRleCA9IDAsXG5cblx0XHRcdFx0XHQvLyBJZiB3ZSBhcmUgZ29pbmcgdG8gdGhlIGVuZCwgd2Ugd2FudCB0byBydW4gYWxsIHRoZSB0d2VlbnNcblx0XHRcdFx0XHQvLyBvdGhlcndpc2Ugd2Ugc2tpcCB0aGlzIHBhcnRcblx0XHRcdFx0XHRsZW5ndGggPSBnb3RvRW5kID8gYW5pbWF0aW9uLnR3ZWVucy5sZW5ndGggOiAwO1xuXHRcdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblx0XHRcdFx0c3RvcHBlZCA9IHRydWU7XG5cdFx0XHRcdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdFx0YW5pbWF0aW9uLnR3ZWVuc1sgaW5kZXggXS5ydW4oIDEgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFJlc29sdmUgd2hlbiB3ZSBwbGF5ZWQgdGhlIGxhc3QgZnJhbWU7IG90aGVyd2lzZSwgcmVqZWN0XG5cdFx0XHRcdGlmICggZ290b0VuZCApIHtcblx0XHRcdFx0XHRkZWZlcnJlZC5ub3RpZnlXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgMSwgMCBdICk7XG5cdFx0XHRcdFx0ZGVmZXJyZWQucmVzb2x2ZVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBnb3RvRW5kIF0gKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgZ290b0VuZCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9XG5cdFx0fSApLFxuXHRcdHByb3BzID0gYW5pbWF0aW9uLnByb3BzO1xuXG5cdHByb3BGaWx0ZXIoIHByb3BzLCBhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nICk7XG5cblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRyZXN1bHQgPSBBbmltYXRpb24ucHJlZmlsdGVyc1sgaW5kZXggXS5jYWxsKCBhbmltYXRpb24sIGVsZW0sIHByb3BzLCBhbmltYXRpb24ub3B0cyApO1xuXHRcdGlmICggcmVzdWx0ICkge1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcmVzdWx0LnN0b3AgKSApIHtcblx0XHRcdFx0alF1ZXJ5Ll9xdWV1ZUhvb2tzKCBhbmltYXRpb24uZWxlbSwgYW5pbWF0aW9uLm9wdHMucXVldWUgKS5zdG9wID1cblx0XHRcdFx0XHRqUXVlcnkucHJveHkoIHJlc3VsdC5zdG9wLCByZXN1bHQgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXN1bHQ7XG5cdFx0fVxuXHR9XG5cblx0alF1ZXJ5Lm1hcCggcHJvcHMsIGNyZWF0ZVR3ZWVuLCBhbmltYXRpb24gKTtcblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBhbmltYXRpb24ub3B0cy5zdGFydCApICkge1xuXHRcdGFuaW1hdGlvbi5vcHRzLnN0YXJ0LmNhbGwoIGVsZW0sIGFuaW1hdGlvbiApO1xuXHR9XG5cblx0Ly8gQXR0YWNoIGNhbGxiYWNrcyBmcm9tIG9wdGlvbnNcblx0YW5pbWF0aW9uXG5cdFx0LnByb2dyZXNzKCBhbmltYXRpb24ub3B0cy5wcm9ncmVzcyApXG5cdFx0LmRvbmUoIGFuaW1hdGlvbi5vcHRzLmRvbmUsIGFuaW1hdGlvbi5vcHRzLmNvbXBsZXRlIClcblx0XHQuZmFpbCggYW5pbWF0aW9uLm9wdHMuZmFpbCApXG5cdFx0LmFsd2F5cyggYW5pbWF0aW9uLm9wdHMuYWx3YXlzICk7XG5cblx0alF1ZXJ5LmZ4LnRpbWVyKFxuXHRcdGpRdWVyeS5leHRlbmQoIHRpY2ssIHtcblx0XHRcdGVsZW06IGVsZW0sXG5cdFx0XHRhbmltOiBhbmltYXRpb24sXG5cdFx0XHRxdWV1ZTogYW5pbWF0aW9uLm9wdHMucXVldWVcblx0XHR9IClcblx0KTtcblxuXHRyZXR1cm4gYW5pbWF0aW9uO1xufVxuXG5qUXVlcnkuQW5pbWF0aW9uID0galF1ZXJ5LmV4dGVuZCggQW5pbWF0aW9uLCB7XG5cblx0dHdlZW5lcnM6IHtcblx0XHRcIipcIjogWyBmdW5jdGlvbiggcHJvcCwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgdHdlZW4gPSB0aGlzLmNyZWF0ZVR3ZWVuKCBwcm9wLCB2YWx1ZSApO1xuXHRcdFx0YWRqdXN0Q1NTKCB0d2Vlbi5lbGVtLCBwcm9wLCByY3NzTnVtLmV4ZWMoIHZhbHVlICksIHR3ZWVuICk7XG5cdFx0XHRyZXR1cm4gdHdlZW47XG5cdFx0fSBdXG5cdH0sXG5cblx0dHdlZW5lcjogZnVuY3Rpb24oIHByb3BzLCBjYWxsYmFjayApIHtcblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwcm9wcyApICkge1xuXHRcdFx0Y2FsbGJhY2sgPSBwcm9wcztcblx0XHRcdHByb3BzID0gWyBcIipcIiBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwcm9wcyA9IHByb3BzLm1hdGNoKCBybm90aHRtbHdoaXRlICk7XG5cdFx0fVxuXG5cdFx0dmFyIHByb3AsXG5cdFx0XHRpbmRleCA9IDAsXG5cdFx0XHRsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG5cblx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdFx0cHJvcCA9IHByb3BzWyBpbmRleCBdO1xuXHRcdFx0QW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gPSBBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXSB8fCBbXTtcblx0XHRcdEFuaW1hdGlvbi50d2VlbmVyc1sgcHJvcCBdLnVuc2hpZnQoIGNhbGxiYWNrICk7XG5cdFx0fVxuXHR9LFxuXG5cdHByZWZpbHRlcnM6IFsgZGVmYXVsdFByZWZpbHRlciBdLFxuXG5cdHByZWZpbHRlcjogZnVuY3Rpb24oIGNhbGxiYWNrLCBwcmVwZW5kICkge1xuXHRcdGlmICggcHJlcGVuZCApIHtcblx0XHRcdEFuaW1hdGlvbi5wcmVmaWx0ZXJzLnVuc2hpZnQoIGNhbGxiYWNrICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdEFuaW1hdGlvbi5wcmVmaWx0ZXJzLnB1c2goIGNhbGxiYWNrICk7XG5cdFx0fVxuXHR9XG59ICk7XG5cbmpRdWVyeS5zcGVlZCA9IGZ1bmN0aW9uKCBzcGVlZCwgZWFzaW5nLCBmbiApIHtcblx0dmFyIG9wdCA9IHNwZWVkICYmIHR5cGVvZiBzcGVlZCA9PT0gXCJvYmplY3RcIiA/IGpRdWVyeS5leHRlbmQoIHt9LCBzcGVlZCApIDoge1xuXHRcdGNvbXBsZXRlOiBmbiB8fCAhZm4gJiYgZWFzaW5nIHx8XG5cdFx0XHRqUXVlcnkuaXNGdW5jdGlvbiggc3BlZWQgKSAmJiBzcGVlZCxcblx0XHRkdXJhdGlvbjogc3BlZWQsXG5cdFx0ZWFzaW5nOiBmbiAmJiBlYXNpbmcgfHwgZWFzaW5nICYmICFqUXVlcnkuaXNGdW5jdGlvbiggZWFzaW5nICkgJiYgZWFzaW5nXG5cdH07XG5cblx0Ly8gR28gdG8gdGhlIGVuZCBzdGF0ZSBpZiBmeCBhcmUgb2ZmXG5cdGlmICggalF1ZXJ5LmZ4Lm9mZiApIHtcblx0XHRvcHQuZHVyYXRpb24gPSAwO1xuXG5cdH0gZWxzZSB7XG5cdFx0aWYgKCB0eXBlb2Ygb3B0LmR1cmF0aW9uICE9PSBcIm51bWJlclwiICkge1xuXHRcdFx0aWYgKCBvcHQuZHVyYXRpb24gaW4galF1ZXJ5LmZ4LnNwZWVkcyApIHtcblx0XHRcdFx0b3B0LmR1cmF0aW9uID0galF1ZXJ5LmZ4LnNwZWVkc1sgb3B0LmR1cmF0aW9uIF07XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5zcGVlZHMuX2RlZmF1bHQ7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gTm9ybWFsaXplIG9wdC5xdWV1ZSAtIHRydWUvdW5kZWZpbmVkL251bGwgLT4gXCJmeFwiXG5cdGlmICggb3B0LnF1ZXVlID09IG51bGwgfHwgb3B0LnF1ZXVlID09PSB0cnVlICkge1xuXHRcdG9wdC5xdWV1ZSA9IFwiZnhcIjtcblx0fVxuXG5cdC8vIFF1ZXVlaW5nXG5cdG9wdC5vbGQgPSBvcHQuY29tcGxldGU7XG5cblx0b3B0LmNvbXBsZXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0Lm9sZCApICkge1xuXHRcdFx0b3B0Lm9sZC5jYWxsKCB0aGlzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHQucXVldWUgKSB7XG5cdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgb3B0LnF1ZXVlICk7XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiBvcHQ7XG59O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGZhZGVUbzogZnVuY3Rpb24oIHNwZWVkLCB0bywgZWFzaW5nLCBjYWxsYmFjayApIHtcblxuXHRcdC8vIFNob3cgYW55IGhpZGRlbiBlbGVtZW50cyBhZnRlciBzZXR0aW5nIG9wYWNpdHkgdG8gMFxuXHRcdHJldHVybiB0aGlzLmZpbHRlciggaXNIaWRkZW5XaXRoaW5UcmVlICkuY3NzKCBcIm9wYWNpdHlcIiwgMCApLnNob3coKVxuXG5cdFx0XHQvLyBBbmltYXRlIHRvIHRoZSB2YWx1ZSBzcGVjaWZpZWRcblx0XHRcdC5lbmQoKS5hbmltYXRlKCB7IG9wYWNpdHk6IHRvIH0sIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICk7XG5cdH0sXG5cdGFuaW1hdGU6IGZ1bmN0aW9uKCBwcm9wLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApIHtcblx0XHR2YXIgZW1wdHkgPSBqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcCApLFxuXHRcdFx0b3B0YWxsID0galF1ZXJ5LnNwZWVkKCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApLFxuXHRcdFx0ZG9BbmltYXRpb24gPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHQvLyBPcGVyYXRlIG9uIGEgY29weSBvZiBwcm9wIHNvIHBlci1wcm9wZXJ0eSBlYXNpbmcgd29uJ3QgYmUgbG9zdFxuXHRcdFx0XHR2YXIgYW5pbSA9IEFuaW1hdGlvbiggdGhpcywgalF1ZXJ5LmV4dGVuZCgge30sIHByb3AgKSwgb3B0YWxsICk7XG5cblx0XHRcdFx0Ly8gRW1wdHkgYW5pbWF0aW9ucywgb3IgZmluaXNoaW5nIHJlc29sdmVzIGltbWVkaWF0ZWx5XG5cdFx0XHRcdGlmICggZW1wdHkgfHwgZGF0YVByaXYuZ2V0KCB0aGlzLCBcImZpbmlzaFwiICkgKSB7XG5cdFx0XHRcdFx0YW5pbS5zdG9wKCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0XHRkb0FuaW1hdGlvbi5maW5pc2ggPSBkb0FuaW1hdGlvbjtcblxuXHRcdHJldHVybiBlbXB0eSB8fCBvcHRhbGwucXVldWUgPT09IGZhbHNlID9cblx0XHRcdHRoaXMuZWFjaCggZG9BbmltYXRpb24gKSA6XG5cdFx0XHR0aGlzLnF1ZXVlKCBvcHRhbGwucXVldWUsIGRvQW5pbWF0aW9uICk7XG5cdH0sXG5cdHN0b3A6IGZ1bmN0aW9uKCB0eXBlLCBjbGVhclF1ZXVlLCBnb3RvRW5kICkge1xuXHRcdHZhciBzdG9wUXVldWUgPSBmdW5jdGlvbiggaG9va3MgKSB7XG5cdFx0XHR2YXIgc3RvcCA9IGhvb2tzLnN0b3A7XG5cdFx0XHRkZWxldGUgaG9va3Muc3RvcDtcblx0XHRcdHN0b3AoIGdvdG9FbmQgKTtcblx0XHR9O1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGdvdG9FbmQgPSBjbGVhclF1ZXVlO1xuXHRcdFx0Y2xlYXJRdWV1ZSA9IHR5cGU7XG5cdFx0XHR0eXBlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHRpZiAoIGNsZWFyUXVldWUgJiYgdHlwZSAhPT0gZmFsc2UgKSB7XG5cdFx0XHR0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBkZXF1ZXVlID0gdHJ1ZSxcblx0XHRcdFx0aW5kZXggPSB0eXBlICE9IG51bGwgJiYgdHlwZSArIFwicXVldWVIb29rc1wiLFxuXHRcdFx0XHR0aW1lcnMgPSBqUXVlcnkudGltZXJzLFxuXHRcdFx0XHRkYXRhID0gZGF0YVByaXYuZ2V0KCB0aGlzICk7XG5cblx0XHRcdGlmICggaW5kZXggKSB7XG5cdFx0XHRcdGlmICggZGF0YVsgaW5kZXggXSAmJiBkYXRhWyBpbmRleCBdLnN0b3AgKSB7XG5cdFx0XHRcdFx0c3RvcFF1ZXVlKCBkYXRhWyBpbmRleCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGZvciAoIGluZGV4IGluIGRhdGEgKSB7XG5cdFx0XHRcdFx0aWYgKCBkYXRhWyBpbmRleCBdICYmIGRhdGFbIGluZGV4IF0uc3RvcCAmJiBycnVuLnRlc3QoIGluZGV4ICkgKSB7XG5cdFx0XHRcdFx0XHRzdG9wUXVldWUoIGRhdGFbIGluZGV4IF0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJlxuXHRcdFx0XHRcdCggdHlwZSA9PSBudWxsIHx8IHRpbWVyc1sgaW5kZXggXS5xdWV1ZSA9PT0gdHlwZSApICkge1xuXG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggZ290b0VuZCApO1xuXHRcdFx0XHRcdGRlcXVldWUgPSBmYWxzZTtcblx0XHRcdFx0XHR0aW1lcnMuc3BsaWNlKCBpbmRleCwgMSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXJ0IHRoZSBuZXh0IGluIHRoZSBxdWV1ZSBpZiB0aGUgbGFzdCBzdGVwIHdhc24ndCBmb3JjZWQuXG5cdFx0XHQvLyBUaW1lcnMgY3VycmVudGx5IHdpbGwgY2FsbCB0aGVpciBjb21wbGV0ZSBjYWxsYmFja3MsIHdoaWNoXG5cdFx0XHQvLyB3aWxsIGRlcXVldWUgYnV0IG9ubHkgaWYgdGhleSB3ZXJlIGdvdG9FbmQuXG5cdFx0XHRpZiAoIGRlcXVldWUgfHwgIWdvdG9FbmQgKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCB0aGlzLCB0eXBlICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXHRmaW5pc2g6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdGlmICggdHlwZSAhPT0gZmFsc2UgKSB7XG5cdFx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGluZGV4LFxuXHRcdFx0XHRkYXRhID0gZGF0YVByaXYuZ2V0KCB0aGlzICksXG5cdFx0XHRcdHF1ZXVlID0gZGF0YVsgdHlwZSArIFwicXVldWVcIiBdLFxuXHRcdFx0XHRob29rcyA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlSG9va3NcIiBdLFxuXHRcdFx0XHR0aW1lcnMgPSBqUXVlcnkudGltZXJzLFxuXHRcdFx0XHRsZW5ndGggPSBxdWV1ZSA/IHF1ZXVlLmxlbmd0aCA6IDA7XG5cblx0XHRcdC8vIEVuYWJsZSBmaW5pc2hpbmcgZmxhZyBvbiBwcml2YXRlIGRhdGFcblx0XHRcdGRhdGEuZmluaXNoID0gdHJ1ZTtcblxuXHRcdFx0Ly8gRW1wdHkgdGhlIHF1ZXVlIGZpcnN0XG5cdFx0XHRqUXVlcnkucXVldWUoIHRoaXMsIHR5cGUsIFtdICk7XG5cblx0XHRcdGlmICggaG9va3MgJiYgaG9va3Muc3RvcCApIHtcblx0XHRcdFx0aG9va3Muc3RvcC5jYWxsKCB0aGlzLCB0cnVlICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIExvb2sgZm9yIGFueSBhY3RpdmUgYW5pbWF0aW9ucywgYW5kIGZpbmlzaCB0aGVtXG5cdFx0XHRmb3IgKCBpbmRleCA9IHRpbWVycy5sZW5ndGg7IGluZGV4LS07ICkge1xuXHRcdFx0XHRpZiAoIHRpbWVyc1sgaW5kZXggXS5lbGVtID09PSB0aGlzICYmIHRpbWVyc1sgaW5kZXggXS5xdWV1ZSA9PT0gdHlwZSApIHtcblx0XHRcdFx0XHR0aW1lcnNbIGluZGV4IF0uYW5pbS5zdG9wKCB0cnVlICk7XG5cdFx0XHRcdFx0dGltZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYW5pbWF0aW9ucyBpbiB0aGUgb2xkIHF1ZXVlIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdFx0aWYgKCBxdWV1ZVsgaW5kZXggXSAmJiBxdWV1ZVsgaW5kZXggXS5maW5pc2ggKSB7XG5cdFx0XHRcdFx0cXVldWVbIGluZGV4IF0uZmluaXNoLmNhbGwoIHRoaXMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUdXJuIG9mZiBmaW5pc2hpbmcgZmxhZ1xuXHRcdFx0ZGVsZXRlIGRhdGEuZmluaXNoO1xuXHRcdH0gKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcInRvZ2dsZVwiLCBcInNob3dcIiwgXCJoaWRlXCIgXSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdHZhciBjc3NGbiA9IGpRdWVyeS5mblsgbmFtZSBdO1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4gc3BlZWQgPT0gbnVsbCB8fCB0eXBlb2Ygc3BlZWQgPT09IFwiYm9vbGVhblwiID9cblx0XHRcdGNzc0ZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKSA6XG5cdFx0XHR0aGlzLmFuaW1hdGUoIGdlbkZ4KCBuYW1lLCB0cnVlICksIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICk7XG5cdH07XG59ICk7XG5cbi8vIEdlbmVyYXRlIHNob3J0Y3V0cyBmb3IgY3VzdG9tIGFuaW1hdGlvbnNcbmpRdWVyeS5lYWNoKCB7XG5cdHNsaWRlRG93bjogZ2VuRngoIFwic2hvd1wiICksXG5cdHNsaWRlVXA6IGdlbkZ4KCBcImhpZGVcIiApLFxuXHRzbGlkZVRvZ2dsZTogZ2VuRngoIFwidG9nZ2xlXCIgKSxcblx0ZmFkZUluOiB7IG9wYWNpdHk6IFwic2hvd1wiIH0sXG5cdGZhZGVPdXQ6IHsgb3BhY2l0eTogXCJoaWRlXCIgfSxcblx0ZmFkZVRvZ2dsZTogeyBvcGFjaXR5OiBcInRvZ2dsZVwiIH1cbn0sIGZ1bmN0aW9uKCBuYW1lLCBwcm9wcyApIHtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHRoaXMuYW5pbWF0ZSggcHJvcHMsIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICk7XG5cdH07XG59ICk7XG5cbmpRdWVyeS50aW1lcnMgPSBbXTtcbmpRdWVyeS5meC50aWNrID0gZnVuY3Rpb24oKSB7XG5cdHZhciB0aW1lcixcblx0XHRpID0gMCxcblx0XHR0aW1lcnMgPSBqUXVlcnkudGltZXJzO1xuXG5cdGZ4Tm93ID0galF1ZXJ5Lm5vdygpO1xuXG5cdGZvciAoIDsgaSA8IHRpbWVycy5sZW5ndGg7IGkrKyApIHtcblx0XHR0aW1lciA9IHRpbWVyc1sgaSBdO1xuXG5cdFx0Ly8gUnVuIHRoZSB0aW1lciBhbmQgc2FmZWx5IHJlbW92ZSBpdCB3aGVuIGRvbmUgKGFsbG93aW5nIGZvciBleHRlcm5hbCByZW1vdmFsKVxuXHRcdGlmICggIXRpbWVyKCkgJiYgdGltZXJzWyBpIF0gPT09IHRpbWVyICkge1xuXHRcdFx0dGltZXJzLnNwbGljZSggaS0tLCAxICk7XG5cdFx0fVxuXHR9XG5cblx0aWYgKCAhdGltZXJzLmxlbmd0aCApIHtcblx0XHRqUXVlcnkuZnguc3RvcCgpO1xuXHR9XG5cdGZ4Tm93ID0gdW5kZWZpbmVkO1xufTtcblxualF1ZXJ5LmZ4LnRpbWVyID0gZnVuY3Rpb24oIHRpbWVyICkge1xuXHRqUXVlcnkudGltZXJzLnB1c2goIHRpbWVyICk7XG5cdGpRdWVyeS5meC5zdGFydCgpO1xufTtcblxualF1ZXJ5LmZ4LmludGVydmFsID0gMTM7XG5qUXVlcnkuZnguc3RhcnQgPSBmdW5jdGlvbigpIHtcblx0aWYgKCBpblByb2dyZXNzICkge1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGluUHJvZ3Jlc3MgPSB0cnVlO1xuXHRzY2hlZHVsZSgpO1xufTtcblxualF1ZXJ5LmZ4LnN0b3AgPSBmdW5jdGlvbigpIHtcblx0aW5Qcm9ncmVzcyA9IG51bGw7XG59O1xuXG5qUXVlcnkuZnguc3BlZWRzID0ge1xuXHRzbG93OiA2MDAsXG5cdGZhc3Q6IDIwMCxcblxuXHQvLyBEZWZhdWx0IHNwZWVkXG5cdF9kZWZhdWx0OiA0MDBcbn07XG5cblxuLy8gQmFzZWQgb2ZmIG9mIHRoZSBwbHVnaW4gYnkgQ2xpbnQgSGVsZmVycywgd2l0aCBwZXJtaXNzaW9uLlxuLy8gaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTAwMzI0MDE0NzQ3L2h0dHA6Ly9ibGluZHNpZ25hbHMuY29tL2luZGV4LnBocC8yMDA5LzA3L2pxdWVyeS1kZWxheS9cbmpRdWVyeS5mbi5kZWxheSA9IGZ1bmN0aW9uKCB0aW1lLCB0eXBlICkge1xuXHR0aW1lID0galF1ZXJ5LmZ4ID8galF1ZXJ5LmZ4LnNwZWVkc1sgdGltZSBdIHx8IHRpbWUgOiB0aW1lO1xuXHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0cmV0dXJuIHRoaXMucXVldWUoIHR5cGUsIGZ1bmN0aW9uKCBuZXh0LCBob29rcyApIHtcblx0XHR2YXIgdGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KCBuZXh0LCB0aW1lICk7XG5cdFx0aG9va3Muc3RvcCA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0d2luZG93LmNsZWFyVGltZW91dCggdGltZW91dCApO1xuXHRcdH07XG5cdH0gKTtcbn07XG5cblxuKCBmdW5jdGlvbigpIHtcblx0dmFyIGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJpbnB1dFwiICksXG5cdFx0c2VsZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJzZWxlY3RcIiApLFxuXHRcdG9wdCA9IHNlbGVjdC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJvcHRpb25cIiApICk7XG5cblx0aW5wdXQudHlwZSA9IFwiY2hlY2tib3hcIjtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4zIG9ubHlcblx0Ly8gRGVmYXVsdCB2YWx1ZSBmb3IgYSBjaGVja2JveCBzaG91bGQgYmUgXCJvblwiXG5cdHN1cHBvcnQuY2hlY2tPbiA9IGlucHV0LnZhbHVlICE9PSBcIlwiO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuXHQvLyBNdXN0IGFjY2VzcyBzZWxlY3RlZEluZGV4IHRvIG1ha2UgZGVmYXVsdCBvcHRpb25zIHNlbGVjdFxuXHRzdXBwb3J0Lm9wdFNlbGVjdGVkID0gb3B0LnNlbGVjdGVkO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuXHQvLyBBbiBpbnB1dCBsb3NlcyBpdHMgdmFsdWUgYWZ0ZXIgYmVjb21pbmcgYSByYWRpb1xuXHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApO1xuXHRpbnB1dC52YWx1ZSA9IFwidFwiO1xuXHRpbnB1dC50eXBlID0gXCJyYWRpb1wiO1xuXHRzdXBwb3J0LnJhZGlvVmFsdWUgPSBpbnB1dC52YWx1ZSA9PT0gXCJ0XCI7XG59ICkoKTtcblxuXG52YXIgYm9vbEhvb2ssXG5cdGF0dHJIYW5kbGUgPSBqUXVlcnkuZXhwci5hdHRySGFuZGxlO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGF0dHI6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBqUXVlcnkuYXR0ciwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH0sXG5cblx0cmVtb3ZlQXR0cjogZnVuY3Rpb24oIG5hbWUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggdGhpcywgbmFtZSApO1xuXHRcdH0gKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cdGF0dHI6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCB2YWx1ZSApIHtcblx0XHR2YXIgcmV0LCBob29rcyxcblx0XHRcdG5UeXBlID0gZWxlbS5ub2RlVHlwZTtcblxuXHRcdC8vIERvbid0IGdldC9zZXQgYXR0cmlidXRlcyBvbiB0ZXh0LCBjb21tZW50IGFuZCBhdHRyaWJ1dGUgbm9kZXNcblx0XHRpZiAoIG5UeXBlID09PSAzIHx8IG5UeXBlID09PSA4IHx8IG5UeXBlID09PSAyICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIEZhbGxiYWNrIHRvIHByb3Agd2hlbiBhdHRyaWJ1dGVzIGFyZSBub3Qgc3VwcG9ydGVkXG5cdFx0aWYgKCB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGUgPT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0XHRyZXR1cm4galF1ZXJ5LnByb3AoIGVsZW0sIG5hbWUsIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXR0cmlidXRlIGhvb2tzIGFyZSBkZXRlcm1pbmVkIGJ5IHRoZSBsb3dlcmNhc2UgdmVyc2lvblxuXHRcdC8vIEdyYWIgbmVjZXNzYXJ5IGhvb2sgaWYgb25lIGlzIGRlZmluZWRcblx0XHRpZiAoIG5UeXBlICE9PSAxIHx8ICFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblx0XHRcdGhvb2tzID0galF1ZXJ5LmF0dHJIb29rc1sgbmFtZS50b0xvd2VyQ2FzZSgpIF0gfHxcblx0XHRcdFx0KCBqUXVlcnkuZXhwci5tYXRjaC5ib29sLnRlc3QoIG5hbWUgKSA/IGJvb2xIb29rIDogdW5kZWZpbmVkICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB2YWx1ZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gbnVsbCApIHtcblx0XHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIGVsZW0sIG5hbWUgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGhvb2tzICYmIFwic2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgdmFsdWUgKyBcIlwiICk7XG5cdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0fVxuXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmICggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBuYW1lICkgKSAhPT0gbnVsbCApIHtcblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fVxuXG5cdFx0cmV0ID0galF1ZXJ5LmZpbmQuYXR0ciggZWxlbSwgbmFtZSApO1xuXG5cdFx0Ly8gTm9uLWV4aXN0ZW50IGF0dHJpYnV0ZXMgcmV0dXJuIG51bGwsIHdlIG5vcm1hbGl6ZSB0byB1bmRlZmluZWRcblx0XHRyZXR1cm4gcmV0ID09IG51bGwgPyB1bmRlZmluZWQgOiByZXQ7XG5cdH0sXG5cblx0YXR0ckhvb2tzOiB7XG5cdFx0dHlwZToge1xuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggIXN1cHBvcnQucmFkaW9WYWx1ZSAmJiB2YWx1ZSA9PT0gXCJyYWRpb1wiICYmXG5cdFx0XHRcdFx0bm9kZU5hbWUoIGVsZW0sIFwiaW5wdXRcIiApICkge1xuXHRcdFx0XHRcdHZhciB2YWwgPSBlbGVtLnZhbHVlO1xuXHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcInR5cGVcIiwgdmFsdWUgKTtcblx0XHRcdFx0XHRpZiAoIHZhbCApIHtcblx0XHRcdFx0XHRcdGVsZW0udmFsdWUgPSB2YWw7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRyZW1vdmVBdHRyOiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0dmFyIG5hbWUsXG5cdFx0XHRpID0gMCxcblxuXHRcdFx0Ly8gQXR0cmlidXRlIG5hbWVzIGNhbiBjb250YWluIG5vbi1IVE1MIHdoaXRlc3BhY2UgY2hhcmFjdGVyc1xuXHRcdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjYXR0cmlidXRlcy0yXG5cdFx0XHRhdHRyTmFtZXMgPSB2YWx1ZSAmJiB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApO1xuXG5cdFx0aWYgKCBhdHRyTmFtZXMgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdHdoaWxlICggKCBuYW1lID0gYXR0ck5hbWVzWyBpKysgXSApICkge1xuXHRcdFx0XHRlbGVtLnJlbW92ZUF0dHJpYnV0ZSggbmFtZSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG4vLyBIb29rcyBmb3IgYm9vbGVhbiBhdHRyaWJ1dGVzXG5ib29sSG9vayA9IHtcblx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUsIG5hbWUgKSB7XG5cdFx0aWYgKCB2YWx1ZSA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdC8vIFJlbW92ZSBib29sZWFuIGF0dHJpYnV0ZXMgd2hlbiBzZXQgdG8gZmFsc2Vcblx0XHRcdGpRdWVyeS5yZW1vdmVBdHRyKCBlbGVtLCBuYW1lICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lICk7XG5cdFx0fVxuXHRcdHJldHVybiBuYW1lO1xuXHR9XG59O1xuXG5qUXVlcnkuZWFjaCggalF1ZXJ5LmV4cHIubWF0Y2guYm9vbC5zb3VyY2UubWF0Y2goIC9cXHcrL2cgKSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdHZhciBnZXR0ZXIgPSBhdHRySGFuZGxlWyBuYW1lIF0gfHwgalF1ZXJ5LmZpbmQuYXR0cjtcblxuXHRhdHRySGFuZGxlWyBuYW1lIF0gPSBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0dmFyIHJldCwgaGFuZGxlLFxuXHRcdFx0bG93ZXJjYXNlTmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcblxuXHRcdGlmICggIWlzWE1MICkge1xuXG5cdFx0XHQvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wIGJ5IHRlbXBvcmFyaWx5IHJlbW92aW5nIHRoaXMgZnVuY3Rpb24gZnJvbSB0aGUgZ2V0dGVyXG5cdFx0XHRoYW5kbGUgPSBhdHRySGFuZGxlWyBsb3dlcmNhc2VOYW1lIF07XG5cdFx0XHRhdHRySGFuZGxlWyBsb3dlcmNhc2VOYW1lIF0gPSByZXQ7XG5cdFx0XHRyZXQgPSBnZXR0ZXIoIGVsZW0sIG5hbWUsIGlzWE1MICkgIT0gbnVsbCA/XG5cdFx0XHRcdGxvd2VyY2FzZU5hbWUgOlxuXHRcdFx0XHRudWxsO1xuXHRcdFx0YXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdID0gaGFuZGxlO1xuXHRcdH1cblx0XHRyZXR1cm4gcmV0O1xuXHR9O1xufSApO1xuXG5cblxuXG52YXIgcmZvY3VzYWJsZSA9IC9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGJ1dHRvbikkL2ksXG5cdHJjbGlja2FibGUgPSAvXig/OmF8YXJlYSkkL2k7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0cHJvcDogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGpRdWVyeS5wcm9wLCBuYW1lLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCA+IDEgKTtcblx0fSxcblxuXHRyZW1vdmVQcm9wOiBmdW5jdGlvbiggbmFtZSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGRlbGV0ZSB0aGlzWyBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWUgXTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHRwcm9wOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBEb24ndCBnZXQvc2V0IHByb3BlcnRpZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIG5UeXBlICE9PSAxIHx8ICFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblxuXHRcdFx0Ly8gRml4IG5hbWUgYW5kIGF0dGFjaCBob29rc1xuXHRcdFx0bmFtZSA9IGpRdWVyeS5wcm9wRml4WyBuYW1lIF0gfHwgbmFtZTtcblx0XHRcdGhvb2tzID0galF1ZXJ5LnByb3BIb29rc1sgbmFtZSBdO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGlmICggaG9va3MgJiYgXCJzZXRcIiBpbiBob29rcyAmJlxuXHRcdFx0XHQoIHJldCA9IGhvb2tzLnNldCggZWxlbSwgdmFsdWUsIG5hbWUgKSApICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiAoIGVsZW1bIG5hbWUgXSA9IHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmICggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBuYW1lICkgKSAhPT0gbnVsbCApIHtcblx0XHRcdHJldHVybiByZXQ7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGVsZW1bIG5hbWUgXTtcblx0fSxcblxuXHRwcm9wSG9va3M6IHtcblx0XHR0YWJJbmRleDoge1xuXHRcdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSBvbmx5XG5cdFx0XHRcdC8vIGVsZW0udGFiSW5kZXggZG9lc24ndCBhbHdheXMgcmV0dXJuIHRoZVxuXHRcdFx0XHQvLyBjb3JyZWN0IHZhbHVlIHdoZW4gaXQgaGFzbid0IGJlZW4gZXhwbGljaXRseSBzZXRcblx0XHRcdFx0Ly8gaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTQxMTE2MjMzMzQ3L2h0dHA6Ly9mbHVpZHByb2plY3Qub3JnL2Jsb2cvMjAwOC8wMS8wOS9nZXR0aW5nLXNldHRpbmctYW5kLXJlbW92aW5nLXRhYmluZGV4LXZhbHVlcy13aXRoLWphdmFzY3JpcHQvXG5cdFx0XHRcdC8vIFVzZSBwcm9wZXIgYXR0cmlidXRlIHJldHJpZXZhbCgjMTIwNzIpXG5cdFx0XHRcdHZhciB0YWJpbmRleCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIFwidGFiaW5kZXhcIiApO1xuXG5cdFx0XHRcdGlmICggdGFiaW5kZXggKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHBhcnNlSW50KCB0YWJpbmRleCwgMTAgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChcblx0XHRcdFx0XHRyZm9jdXNhYmxlLnRlc3QoIGVsZW0ubm9kZU5hbWUgKSB8fFxuXHRcdFx0XHRcdHJjbGlja2FibGUudGVzdCggZWxlbS5ub2RlTmFtZSApICYmXG5cdFx0XHRcdFx0ZWxlbS5ocmVmXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHJldHVybiAwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIC0xO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRwcm9wRml4OiB7XG5cdFx0XCJmb3JcIjogXCJodG1sRm9yXCIsXG5cdFx0XCJjbGFzc1wiOiBcImNsYXNzTmFtZVwiXG5cdH1cbn0gKTtcblxuLy8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG4vLyBBY2Nlc3NpbmcgdGhlIHNlbGVjdGVkSW5kZXggcHJvcGVydHlcbi8vIGZvcmNlcyB0aGUgYnJvd3NlciB0byByZXNwZWN0IHNldHRpbmcgc2VsZWN0ZWRcbi8vIG9uIHRoZSBvcHRpb25cbi8vIFRoZSBnZXR0ZXIgZW5zdXJlcyBhIGRlZmF1bHQgb3B0aW9uIGlzIHNlbGVjdGVkXG4vLyB3aGVuIGluIGFuIG9wdGdyb3VwXG4vLyBlc2xpbnQgcnVsZSBcIm5vLXVudXNlZC1leHByZXNzaW9uc1wiIGlzIGRpc2FibGVkIGZvciB0aGlzIGNvZGVcbi8vIHNpbmNlIGl0IGNvbnNpZGVycyBzdWNoIGFjY2Vzc2lvbnMgbm9vcFxuaWYgKCAhc3VwcG9ydC5vcHRTZWxlY3RlZCApIHtcblx0alF1ZXJ5LnByb3BIb29rcy5zZWxlY3RlZCA9IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0XHQvKiBlc2xpbnQgbm8tdW51c2VkLWV4cHJlc3Npb25zOiBcIm9mZlwiICovXG5cblx0XHRcdHZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGU7XG5cdFx0XHRpZiAoIHBhcmVudCAmJiBwYXJlbnQucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0cGFyZW50LnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleDtcblx0XHRcdH1cblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH0sXG5cdFx0c2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0LyogZXNsaW50IG5vLXVudXNlZC1leHByZXNzaW9uczogXCJvZmZcIiAqL1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cdFx0XHRcdHBhcmVudC5zZWxlY3RlZEluZGV4O1xuXG5cdFx0XHRcdGlmICggcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0cGFyZW50LnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxualF1ZXJ5LmVhY2goIFtcblx0XCJ0YWJJbmRleFwiLFxuXHRcInJlYWRPbmx5XCIsXG5cdFwibWF4TGVuZ3RoXCIsXG5cdFwiY2VsbFNwYWNpbmdcIixcblx0XCJjZWxsUGFkZGluZ1wiLFxuXHRcInJvd1NwYW5cIixcblx0XCJjb2xTcGFuXCIsXG5cdFwidXNlTWFwXCIsXG5cdFwiZnJhbWVCb3JkZXJcIixcblx0XCJjb250ZW50RWRpdGFibGVcIlxuXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS5wcm9wRml4WyB0aGlzLnRvTG93ZXJDYXNlKCkgXSA9IHRoaXM7XG59ICk7XG5cblxuXG5cblx0Ly8gU3RyaXAgYW5kIGNvbGxhcHNlIHdoaXRlc3BhY2UgYWNjb3JkaW5nIHRvIEhUTUwgc3BlY1xuXHQvLyBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9pbmZyYXN0cnVjdHVyZS5odG1sI3N0cmlwLWFuZC1jb2xsYXBzZS13aGl0ZXNwYWNlXG5cdGZ1bmN0aW9uIHN0cmlwQW5kQ29sbGFwc2UoIHZhbHVlICkge1xuXHRcdHZhciB0b2tlbnMgPSB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXHRcdHJldHVybiB0b2tlbnMuam9pbiggXCIgXCIgKTtcblx0fVxuXG5cbmZ1bmN0aW9uIGdldENsYXNzKCBlbGVtICkge1xuXHRyZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGUgJiYgZWxlbS5nZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIiApIHx8IFwiXCI7XG59XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0YWRkQ2xhc3M6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHR2YXIgY2xhc3NlcywgZWxlbSwgY3VyLCBjdXJWYWx1ZSwgY2xhenosIGosIGZpbmFsVmFsdWUsXG5cdFx0XHRpID0gMDtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaiApIHtcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkuYWRkQ2xhc3MoIHZhbHVlLmNhbGwoIHRoaXMsIGosIGdldENsYXNzKCB0aGlzICkgKSApO1xuXHRcdFx0fSApO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlICkge1xuXHRcdFx0Y2xhc3NlcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdHdoaWxlICggKCBlbGVtID0gdGhpc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0Y3VyVmFsdWUgPSBnZXRDbGFzcyggZWxlbSApO1xuXHRcdFx0XHRjdXIgPSBlbGVtLm5vZGVUeXBlID09PSAxICYmICggXCIgXCIgKyBzdHJpcEFuZENvbGxhcHNlKCBjdXJWYWx1ZSApICsgXCIgXCIgKTtcblxuXHRcdFx0XHRpZiAoIGN1ciApIHtcblx0XHRcdFx0XHRqID0gMDtcblx0XHRcdFx0XHR3aGlsZSAoICggY2xhenogPSBjbGFzc2VzWyBqKysgXSApICkge1xuXHRcdFx0XHRcdFx0aWYgKCBjdXIuaW5kZXhPZiggXCIgXCIgKyBjbGF6eiArIFwiIFwiICkgPCAwICkge1xuXHRcdFx0XHRcdFx0XHRjdXIgKz0gY2xhenogKyBcIiBcIjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBPbmx5IGFzc2lnbiBpZiBkaWZmZXJlbnQgdG8gYXZvaWQgdW5uZWVkZWQgcmVuZGVyaW5nLlxuXHRcdFx0XHRcdGZpbmFsVmFsdWUgPSBzdHJpcEFuZENvbGxhcHNlKCBjdXIgKTtcblx0XHRcdFx0XHRpZiAoIGN1clZhbHVlICE9PSBmaW5hbFZhbHVlICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIiwgZmluYWxWYWx1ZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdHJlbW92ZUNsYXNzOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGNsYXNzZXMsIGVsZW0sIGN1ciwgY3VyVmFsdWUsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLnJlbW92ZUNsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCBnZXRDbGFzcyggdGhpcyApICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoICFhcmd1bWVudHMubGVuZ3RoICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuYXR0ciggXCJjbGFzc1wiLCBcIlwiICk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgdmFsdWUgKSB7XG5cdFx0XHRjbGFzc2VzID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdFx0d2hpbGUgKCAoIGVsZW0gPSB0aGlzWyBpKysgXSApICkge1xuXHRcdFx0XHRjdXJWYWx1ZSA9IGdldENsYXNzKCBlbGVtICk7XG5cblx0XHRcdFx0Ly8gVGhpcyBleHByZXNzaW9uIGlzIGhlcmUgZm9yIGJldHRlciBjb21wcmVzc2liaWxpdHkgKHNlZSBhZGRDbGFzcylcblx0XHRcdFx0Y3VyID0gZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAoIFwiIFwiICsgc3RyaXBBbmRDb2xsYXBzZSggY3VyVmFsdWUgKSArIFwiIFwiICk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGNsYXp6ID0gY2xhc3Nlc1sgaisrIF0gKSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlICphbGwqIGluc3RhbmNlc1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBjdXIuaW5kZXhPZiggXCIgXCIgKyBjbGF6eiArIFwiIFwiICkgPiAtMSApIHtcblx0XHRcdFx0XHRcdFx0Y3VyID0gY3VyLnJlcGxhY2UoIFwiIFwiICsgY2xhenogKyBcIiBcIiwgXCIgXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBPbmx5IGFzc2lnbiBpZiBkaWZmZXJlbnQgdG8gYXZvaWQgdW5uZWVkZWQgcmVuZGVyaW5nLlxuXHRcdFx0XHRcdGZpbmFsVmFsdWUgPSBzdHJpcEFuZENvbGxhcHNlKCBjdXIgKTtcblx0XHRcdFx0XHRpZiAoIGN1clZhbHVlICE9PSBmaW5hbFZhbHVlICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIiwgZmluYWxWYWx1ZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdHRvZ2dsZUNsYXNzOiBmdW5jdGlvbiggdmFsdWUsIHN0YXRlVmFsICkge1xuXHRcdHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuXG5cdFx0aWYgKCB0eXBlb2Ygc3RhdGVWYWwgPT09IFwiYm9vbGVhblwiICYmIHR5cGUgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gc3RhdGVWYWwgPyB0aGlzLmFkZENsYXNzKCB2YWx1ZSApIDogdGhpcy5yZW1vdmVDbGFzcyggdmFsdWUgKTtcblx0XHR9XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLnRvZ2dsZUNsYXNzKFxuXHRcdFx0XHRcdHZhbHVlLmNhbGwoIHRoaXMsIGksIGdldENsYXNzKCB0aGlzICksIHN0YXRlVmFsICksXG5cdFx0XHRcdFx0c3RhdGVWYWxcblx0XHRcdFx0KTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBjbGFzc05hbWUsIGksIHNlbGYsIGNsYXNzTmFtZXM7XG5cblx0XHRcdGlmICggdHlwZSA9PT0gXCJzdHJpbmdcIiApIHtcblxuXHRcdFx0XHQvLyBUb2dnbGUgaW5kaXZpZHVhbCBjbGFzcyBuYW1lc1xuXHRcdFx0XHRpID0gMDtcblx0XHRcdFx0c2VsZiA9IGpRdWVyeSggdGhpcyApO1xuXHRcdFx0XHRjbGFzc05hbWVzID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdFx0XHR3aGlsZSAoICggY2xhc3NOYW1lID0gY2xhc3NOYW1lc1sgaSsrIF0gKSApIHtcblxuXHRcdFx0XHRcdC8vIENoZWNrIGVhY2ggY2xhc3NOYW1lIGdpdmVuLCBzcGFjZSBzZXBhcmF0ZWQgbGlzdFxuXHRcdFx0XHRcdGlmICggc2VsZi5oYXNDbGFzcyggY2xhc3NOYW1lICkgKSB7XG5cdFx0XHRcdFx0XHRzZWxmLnJlbW92ZUNsYXNzKCBjbGFzc05hbWUgKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0c2VsZi5hZGRDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdC8vIFRvZ2dsZSB3aG9sZSBjbGFzcyBuYW1lXG5cdFx0XHR9IGVsc2UgaWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHR5cGUgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdFx0XHRjbGFzc05hbWUgPSBnZXRDbGFzcyggdGhpcyApO1xuXHRcdFx0XHRpZiAoIGNsYXNzTmFtZSApIHtcblxuXHRcdFx0XHRcdC8vIFN0b3JlIGNsYXNzTmFtZSBpZiBzZXRcblx0XHRcdFx0XHRkYXRhUHJpdi5zZXQoIHRoaXMsIFwiX19jbGFzc05hbWVfX1wiLCBjbGFzc05hbWUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIElmIHRoZSBlbGVtZW50IGhhcyBhIGNsYXNzIG5hbWUgb3IgaWYgd2UncmUgcGFzc2VkIGBmYWxzZWAsXG5cdFx0XHRcdC8vIHRoZW4gcmVtb3ZlIHRoZSB3aG9sZSBjbGFzc25hbWUgKGlmIHRoZXJlIHdhcyBvbmUsIHRoZSBhYm92ZSBzYXZlZCBpdCkuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBicmluZyBiYWNrIHdoYXRldmVyIHdhcyBwcmV2aW91c2x5IHNhdmVkIChpZiBhbnl0aGluZyksXG5cdFx0XHRcdC8vIGZhbGxpbmcgYmFjayB0byB0aGUgZW1wdHkgc3RyaW5nIGlmIG5vdGhpbmcgd2FzIHN0b3JlZC5cblx0XHRcdFx0aWYgKCB0aGlzLnNldEF0dHJpYnV0ZSApIHtcblx0XHRcdFx0XHR0aGlzLnNldEF0dHJpYnV0ZSggXCJjbGFzc1wiLFxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lIHx8IHZhbHVlID09PSBmYWxzZSA/XG5cdFx0XHRcdFx0XHRcIlwiIDpcblx0XHRcdFx0XHRcdGRhdGFQcml2LmdldCggdGhpcywgXCJfX2NsYXNzTmFtZV9fXCIgKSB8fCBcIlwiXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRoYXNDbGFzczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHZhciBjbGFzc05hbWUsIGVsZW0sXG5cdFx0XHRpID0gMDtcblxuXHRcdGNsYXNzTmFtZSA9IFwiIFwiICsgc2VsZWN0b3IgKyBcIiBcIjtcblx0XHR3aGlsZSAoICggZWxlbSA9IHRoaXNbIGkrKyBdICkgKSB7XG5cdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgJiZcblx0XHRcdFx0KCBcIiBcIiArIHN0cmlwQW5kQ29sbGFwc2UoIGdldENsYXNzKCBlbGVtICkgKSArIFwiIFwiICkuaW5kZXhPZiggY2xhc3NOYW1lICkgPiAtMSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn0gKTtcblxuXG5cblxudmFyIHJyZXR1cm4gPSAvXFxyL2c7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0dmFsOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGhvb2tzLCByZXQsIGlzRnVuY3Rpb24sXG5cdFx0XHRlbGVtID0gdGhpc1sgMCBdO1xuXG5cdFx0aWYgKCAhYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdGlmICggZWxlbSApIHtcblx0XHRcdFx0aG9va3MgPSBqUXVlcnkudmFsSG9va3NbIGVsZW0udHlwZSBdIHx8XG5cdFx0XHRcdFx0alF1ZXJ5LnZhbEhvb2tzWyBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgXTtcblxuXHRcdFx0XHRpZiAoIGhvb2tzICYmXG5cdFx0XHRcdFx0XCJnZXRcIiBpbiBob29rcyAmJlxuXHRcdFx0XHRcdCggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBcInZhbHVlXCIgKSApICE9PSB1bmRlZmluZWRcblx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldCA9IGVsZW0udmFsdWU7XG5cblx0XHRcdFx0Ly8gSGFuZGxlIG1vc3QgY29tbW9uIHN0cmluZyBjYXNlc1xuXHRcdFx0XHRpZiAoIHR5cGVvZiByZXQgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHJldC5yZXBsYWNlKCBycmV0dXJuLCBcIlwiICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBIYW5kbGUgY2FzZXMgd2hlcmUgdmFsdWUgaXMgbnVsbC91bmRlZiBvciBudW1iZXJcblx0XHRcdFx0cmV0dXJuIHJldCA9PSBudWxsID8gXCJcIiA6IHJldDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKTtcblxuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0dmFyIHZhbDtcblxuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0dmFsID0gdmFsdWUuY2FsbCggdGhpcywgaSwgalF1ZXJ5KCB0aGlzICkudmFsKCkgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUcmVhdCBudWxsL3VuZGVmaW5lZCBhcyBcIlwiOyBjb252ZXJ0IG51bWJlcnMgdG8gc3RyaW5nXG5cdFx0XHRpZiAoIHZhbCA9PSBudWxsICkge1xuXHRcdFx0XHR2YWwgPSBcIlwiO1xuXG5cdFx0XHR9IGVsc2UgaWYgKCB0eXBlb2YgdmFsID09PSBcIm51bWJlclwiICkge1xuXHRcdFx0XHR2YWwgKz0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggQXJyYXkuaXNBcnJheSggdmFsICkgKSB7XG5cdFx0XHRcdHZhbCA9IGpRdWVyeS5tYXAoIHZhbCwgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRcdHJldHVybiB2YWx1ZSA9PSBudWxsID8gXCJcIiA6IHZhbHVlICsgXCJcIjtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRob29rcyA9IGpRdWVyeS52YWxIb29rc1sgdGhpcy50eXBlIF0gfHwgalF1ZXJ5LnZhbEhvb2tzWyB0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgXTtcblxuXHRcdFx0Ly8gSWYgc2V0IHJldHVybnMgdW5kZWZpbmVkLCBmYWxsIGJhY2sgdG8gbm9ybWFsIHNldHRpbmdcblx0XHRcdGlmICggIWhvb2tzIHx8ICEoIFwic2V0XCIgaW4gaG9va3MgKSB8fCBob29rcy5zZXQoIHRoaXMsIHZhbCwgXCJ2YWx1ZVwiICkgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0dGhpcy52YWx1ZSA9IHZhbDtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHR2YWxIb29rczoge1xuXHRcdG9wdGlvbjoge1xuXHRcdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0XHR2YXIgdmFsID0galF1ZXJ5LmZpbmQuYXR0ciggZWxlbSwgXCJ2YWx1ZVwiICk7XG5cdFx0XHRcdHJldHVybiB2YWwgIT0gbnVsbCA/XG5cdFx0XHRcdFx0dmFsIDpcblxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9MTAgLSAxMSBvbmx5XG5cdFx0XHRcdFx0Ly8gb3B0aW9uLnRleHQgdGhyb3dzIGV4Y2VwdGlvbnMgKCMxNDY4NiwgIzE0ODU4KVxuXHRcdFx0XHRcdC8vIFN0cmlwIGFuZCBjb2xsYXBzZSB3aGl0ZXNwYWNlXG5cdFx0XHRcdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy8jc3RyaXAtYW5kLWNvbGxhcHNlLXdoaXRlc3BhY2Vcblx0XHRcdFx0XHRzdHJpcEFuZENvbGxhcHNlKCBqUXVlcnkudGV4dCggZWxlbSApICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzZWxlY3Q6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciB2YWx1ZSwgb3B0aW9uLCBpLFxuXHRcdFx0XHRcdG9wdGlvbnMgPSBlbGVtLm9wdGlvbnMsXG5cdFx0XHRcdFx0aW5kZXggPSBlbGVtLnNlbGVjdGVkSW5kZXgsXG5cdFx0XHRcdFx0b25lID0gZWxlbS50eXBlID09PSBcInNlbGVjdC1vbmVcIixcblx0XHRcdFx0XHR2YWx1ZXMgPSBvbmUgPyBudWxsIDogW10sXG5cdFx0XHRcdFx0bWF4ID0gb25lID8gaW5kZXggKyAxIDogb3B0aW9ucy5sZW5ndGg7XG5cblx0XHRcdFx0aWYgKCBpbmRleCA8IDAgKSB7XG5cdFx0XHRcdFx0aSA9IG1heDtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGkgPSBvbmUgPyBpbmRleCA6IDA7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBMb29wIHRocm91Z2ggYWxsIHRoZSBzZWxlY3RlZCBvcHRpb25zXG5cdFx0XHRcdGZvciAoIDsgaSA8IG1heDsgaSsrICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0Ly8gSUU4LTkgZG9lc24ndCB1cGRhdGUgc2VsZWN0ZWQgYWZ0ZXIgZm9ybSByZXNldCAoIzI1NTEpXG5cdFx0XHRcdFx0aWYgKCAoIG9wdGlvbi5zZWxlY3RlZCB8fCBpID09PSBpbmRleCApICYmXG5cblx0XHRcdFx0XHRcdFx0Ly8gRG9uJ3QgcmV0dXJuIG9wdGlvbnMgdGhhdCBhcmUgZGlzYWJsZWQgb3IgaW4gYSBkaXNhYmxlZCBvcHRncm91cFxuXHRcdFx0XHRcdFx0XHQhb3B0aW9uLmRpc2FibGVkICYmXG5cdFx0XHRcdFx0XHRcdCggIW9wdGlvbi5wYXJlbnROb2RlLmRpc2FibGVkIHx8XG5cdFx0XHRcdFx0XHRcdFx0IW5vZGVOYW1lKCBvcHRpb24ucGFyZW50Tm9kZSwgXCJvcHRncm91cFwiICkgKSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gR2V0IHRoZSBzcGVjaWZpYyB2YWx1ZSBmb3IgdGhlIG9wdGlvblxuXHRcdFx0XHRcdFx0dmFsdWUgPSBqUXVlcnkoIG9wdGlvbiApLnZhbCgpO1xuXG5cdFx0XHRcdFx0XHQvLyBXZSBkb24ndCBuZWVkIGFuIGFycmF5IGZvciBvbmUgc2VsZWN0c1xuXHRcdFx0XHRcdFx0aWYgKCBvbmUgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8gTXVsdGktU2VsZWN0cyByZXR1cm4gYW4gYXJyYXlcblx0XHRcdFx0XHRcdHZhbHVlcy5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiB2YWx1ZXM7XG5cdFx0XHR9LFxuXG5cdFx0XHRzZXQ6IGZ1bmN0aW9uKCBlbGVtLCB2YWx1ZSApIHtcblx0XHRcdFx0dmFyIG9wdGlvblNldCwgb3B0aW9uLFxuXHRcdFx0XHRcdG9wdGlvbnMgPSBlbGVtLm9wdGlvbnMsXG5cdFx0XHRcdFx0dmFsdWVzID0galF1ZXJ5Lm1ha2VBcnJheSggdmFsdWUgKSxcblx0XHRcdFx0XHRpID0gb3B0aW9ucy5sZW5ndGg7XG5cblx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0b3B0aW9uID0gb3B0aW9uc1sgaSBdO1xuXG5cdFx0XHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8tY29uZC1hc3NpZ24gKi9cblxuXHRcdFx0XHRcdGlmICggb3B0aW9uLnNlbGVjdGVkID1cblx0XHRcdFx0XHRcdGpRdWVyeS5pbkFycmF5KCBqUXVlcnkudmFsSG9va3Mub3B0aW9uLmdldCggb3B0aW9uICksIHZhbHVlcyApID4gLTFcblx0XHRcdFx0XHQpIHtcblx0XHRcdFx0XHRcdG9wdGlvblNldCA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0LyogZXNsaW50LWVuYWJsZSBuby1jb25kLWFzc2lnbiAqL1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gRm9yY2UgYnJvd3NlcnMgdG8gYmVoYXZlIGNvbnNpc3RlbnRseSB3aGVuIG5vbi1tYXRjaGluZyB2YWx1ZSBpcyBzZXRcblx0XHRcdFx0aWYgKCAhb3B0aW9uU2V0ICkge1xuXHRcdFx0XHRcdGVsZW0uc2VsZWN0ZWRJbmRleCA9IC0xO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB2YWx1ZXM7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59ICk7XG5cbi8vIFJhZGlvcyBhbmQgY2hlY2tib3hlcyBnZXR0ZXIvc2V0dGVyXG5qUXVlcnkuZWFjaCggWyBcInJhZGlvXCIsIFwiY2hlY2tib3hcIiBdLCBmdW5jdGlvbigpIHtcblx0alF1ZXJ5LnZhbEhvb2tzWyB0aGlzIF0gPSB7XG5cdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRpZiAoIEFycmF5LmlzQXJyYXkoIHZhbHVlICkgKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0uY2hlY2tlZCA9IGpRdWVyeS5pbkFycmF5KCBqUXVlcnkoIGVsZW0gKS52YWwoKSwgdmFsdWUgKSA+IC0xICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXHRpZiAoICFzdXBwb3J0LmNoZWNrT24gKSB7XG5cdFx0alF1ZXJ5LnZhbEhvb2tzWyB0aGlzIF0uZ2V0ID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiApID09PSBudWxsID8gXCJvblwiIDogZWxlbS52YWx1ZTtcblx0XHR9O1xuXHR9XG59ICk7XG5cblxuXG5cbi8vIFJldHVybiBqUXVlcnkgZm9yIGF0dHJpYnV0ZXMtb25seSBpbmNsdXNpb25cblxuXG52YXIgcmZvY3VzTW9ycGggPSAvXig/OmZvY3VzaW5mb2N1c3xmb2N1c291dGJsdXIpJC87XG5cbmpRdWVyeS5leHRlbmQoIGpRdWVyeS5ldmVudCwge1xuXG5cdHRyaWdnZXI6IGZ1bmN0aW9uKCBldmVudCwgZGF0YSwgZWxlbSwgb25seUhhbmRsZXJzICkge1xuXG5cdFx0dmFyIGksIGN1ciwgdG1wLCBidWJibGVUeXBlLCBvbnR5cGUsIGhhbmRsZSwgc3BlY2lhbCxcblx0XHRcdGV2ZW50UGF0aCA9IFsgZWxlbSB8fCBkb2N1bWVudCBdLFxuXHRcdFx0dHlwZSA9IGhhc093bi5jYWxsKCBldmVudCwgXCJ0eXBlXCIgKSA/IGV2ZW50LnR5cGUgOiBldmVudCxcblx0XHRcdG5hbWVzcGFjZXMgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwibmFtZXNwYWNlXCIgKSA/IGV2ZW50Lm5hbWVzcGFjZS5zcGxpdCggXCIuXCIgKSA6IFtdO1xuXG5cdFx0Y3VyID0gdG1wID0gZWxlbSA9IGVsZW0gfHwgZG9jdW1lbnQ7XG5cblx0XHQvLyBEb24ndCBkbyBldmVudHMgb24gdGV4dCBhbmQgY29tbWVudCBub2Rlc1xuXHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMyB8fCBlbGVtLm5vZGVUeXBlID09PSA4ICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIGZvY3VzL2JsdXIgbW9ycGhzIHRvIGZvY3VzaW4vb3V0OyBlbnN1cmUgd2UncmUgbm90IGZpcmluZyB0aGVtIHJpZ2h0IG5vd1xuXHRcdGlmICggcmZvY3VzTW9ycGgudGVzdCggdHlwZSArIGpRdWVyeS5ldmVudC50cmlnZ2VyZWQgKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGUuaW5kZXhPZiggXCIuXCIgKSA+IC0xICkge1xuXG5cdFx0XHQvLyBOYW1lc3BhY2VkIHRyaWdnZXI7IGNyZWF0ZSBhIHJlZ2V4cCB0byBtYXRjaCBldmVudCB0eXBlIGluIGhhbmRsZSgpXG5cdFx0XHRuYW1lc3BhY2VzID0gdHlwZS5zcGxpdCggXCIuXCIgKTtcblx0XHRcdHR5cGUgPSBuYW1lc3BhY2VzLnNoaWZ0KCk7XG5cdFx0XHRuYW1lc3BhY2VzLnNvcnQoKTtcblx0XHR9XG5cdFx0b250eXBlID0gdHlwZS5pbmRleE9mKCBcIjpcIiApIDwgMCAmJiBcIm9uXCIgKyB0eXBlO1xuXG5cdFx0Ly8gQ2FsbGVyIGNhbiBwYXNzIGluIGEgalF1ZXJ5LkV2ZW50IG9iamVjdCwgT2JqZWN0LCBvciBqdXN0IGFuIGV2ZW50IHR5cGUgc3RyaW5nXG5cdFx0ZXZlbnQgPSBldmVudFsgalF1ZXJ5LmV4cGFuZG8gXSA/XG5cdFx0XHRldmVudCA6XG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCB0eXBlLCB0eXBlb2YgZXZlbnQgPT09IFwib2JqZWN0XCIgJiYgZXZlbnQgKTtcblxuXHRcdC8vIFRyaWdnZXIgYml0bWFzazogJiAxIGZvciBuYXRpdmUgaGFuZGxlcnM7ICYgMiBmb3IgalF1ZXJ5IChhbHdheXMgdHJ1ZSlcblx0XHRldmVudC5pc1RyaWdnZXIgPSBvbmx5SGFuZGxlcnMgPyAyIDogMztcblx0XHRldmVudC5uYW1lc3BhY2UgPSBuYW1lc3BhY2VzLmpvaW4oIFwiLlwiICk7XG5cdFx0ZXZlbnQucm5hbWVzcGFjZSA9IGV2ZW50Lm5hbWVzcGFjZSA/XG5cdFx0XHRuZXcgUmVnRXhwKCBcIihefFxcXFwuKVwiICsgbmFtZXNwYWNlcy5qb2luKCBcIlxcXFwuKD86LipcXFxcLnwpXCIgKSArIFwiKFxcXFwufCQpXCIgKSA6XG5cdFx0XHRudWxsO1xuXG5cdFx0Ly8gQ2xlYW4gdXAgdGhlIGV2ZW50IGluIGNhc2UgaXQgaXMgYmVpbmcgcmV1c2VkXG5cdFx0ZXZlbnQucmVzdWx0ID0gdW5kZWZpbmVkO1xuXHRcdGlmICggIWV2ZW50LnRhcmdldCApIHtcblx0XHRcdGV2ZW50LnRhcmdldCA9IGVsZW07XG5cdFx0fVxuXG5cdFx0Ly8gQ2xvbmUgYW55IGluY29taW5nIGRhdGEgYW5kIHByZXBlbmQgdGhlIGV2ZW50LCBjcmVhdGluZyB0aGUgaGFuZGxlciBhcmcgbGlzdFxuXHRcdGRhdGEgPSBkYXRhID09IG51bGwgP1xuXHRcdFx0WyBldmVudCBdIDpcblx0XHRcdGpRdWVyeS5tYWtlQXJyYXkoIGRhdGEsIFsgZXZlbnQgXSApO1xuXG5cdFx0Ly8gQWxsb3cgc3BlY2lhbCBldmVudHMgdG8gZHJhdyBvdXRzaWRlIHRoZSBsaW5lc1xuXHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiBzcGVjaWFsLnRyaWdnZXIgJiYgc3BlY2lhbC50cmlnZ2VyLmFwcGx5KCBlbGVtLCBkYXRhICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBldmVudCBwcm9wYWdhdGlvbiBwYXRoIGluIGFkdmFuY2UsIHBlciBXM0MgZXZlbnRzIHNwZWMgKCM5OTUxKVxuXHRcdC8vIEJ1YmJsZSB1cCB0byBkb2N1bWVudCwgdGhlbiB0byB3aW5kb3c7IHdhdGNoIGZvciBhIGdsb2JhbCBvd25lckRvY3VtZW50IHZhciAoIzk3MjQpXG5cdFx0aWYgKCAhb25seUhhbmRsZXJzICYmICFzcGVjaWFsLm5vQnViYmxlICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0YnViYmxlVHlwZSA9IHNwZWNpYWwuZGVsZWdhdGVUeXBlIHx8IHR5cGU7XG5cdFx0XHRpZiAoICFyZm9jdXNNb3JwaC50ZXN0KCBidWJibGVUeXBlICsgdHlwZSApICkge1xuXHRcdFx0XHRjdXIgPSBjdXIucGFyZW50Tm9kZTtcblx0XHRcdH1cblx0XHRcdGZvciAoIDsgY3VyOyBjdXIgPSBjdXIucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZXZlbnRQYXRoLnB1c2goIGN1ciApO1xuXHRcdFx0XHR0bXAgPSBjdXI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9ubHkgYWRkIHdpbmRvdyBpZiB3ZSBnb3QgdG8gZG9jdW1lbnQgKGUuZy4sIG5vdCBwbGFpbiBvYmogb3IgZGV0YWNoZWQgRE9NKVxuXHRcdFx0aWYgKCB0bXAgPT09ICggZWxlbS5vd25lckRvY3VtZW50IHx8IGRvY3VtZW50ICkgKSB7XG5cdFx0XHRcdGV2ZW50UGF0aC5wdXNoKCB0bXAuZGVmYXVsdFZpZXcgfHwgdG1wLnBhcmVudFdpbmRvdyB8fCB3aW5kb3cgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBGaXJlIGhhbmRsZXJzIG9uIHRoZSBldmVudCBwYXRoXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoIGN1ciA9IGV2ZW50UGF0aFsgaSsrIF0gKSAmJiAhZXZlbnQuaXNQcm9wYWdhdGlvblN0b3BwZWQoKSApIHtcblxuXHRcdFx0ZXZlbnQudHlwZSA9IGkgPiAxID9cblx0XHRcdFx0YnViYmxlVHlwZSA6XG5cdFx0XHRcdHNwZWNpYWwuYmluZFR5cGUgfHwgdHlwZTtcblxuXHRcdFx0Ly8galF1ZXJ5IGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9ICggZGF0YVByaXYuZ2V0KCBjdXIsIFwiZXZlbnRzXCIgKSB8fCB7fSApWyBldmVudC50eXBlIF0gJiZcblx0XHRcdFx0ZGF0YVByaXYuZ2V0KCBjdXIsIFwiaGFuZGxlXCIgKTtcblx0XHRcdGlmICggaGFuZGxlICkge1xuXHRcdFx0XHRoYW5kbGUuYXBwbHkoIGN1ciwgZGF0YSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBOYXRpdmUgaGFuZGxlclxuXHRcdFx0aGFuZGxlID0gb250eXBlICYmIGN1clsgb250eXBlIF07XG5cdFx0XHRpZiAoIGhhbmRsZSAmJiBoYW5kbGUuYXBwbHkgJiYgYWNjZXB0RGF0YSggY3VyICkgKSB7XG5cdFx0XHRcdGV2ZW50LnJlc3VsdCA9IGhhbmRsZS5hcHBseSggY3VyLCBkYXRhICk7XG5cdFx0XHRcdGlmICggZXZlbnQucmVzdWx0ID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGV2ZW50LnR5cGUgPSB0eXBlO1xuXG5cdFx0Ly8gSWYgbm9ib2R5IHByZXZlbnRlZCB0aGUgZGVmYXVsdCBhY3Rpb24sIGRvIGl0IG5vd1xuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhZXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgKSB7XG5cblx0XHRcdGlmICggKCAhc3BlY2lhbC5fZGVmYXVsdCB8fFxuXHRcdFx0XHRzcGVjaWFsLl9kZWZhdWx0LmFwcGx5KCBldmVudFBhdGgucG9wKCksIGRhdGEgKSA9PT0gZmFsc2UgKSAmJlxuXHRcdFx0XHRhY2NlcHREYXRhKCBlbGVtICkgKSB7XG5cblx0XHRcdFx0Ly8gQ2FsbCBhIG5hdGl2ZSBET00gbWV0aG9kIG9uIHRoZSB0YXJnZXQgd2l0aCB0aGUgc2FtZSBuYW1lIGFzIHRoZSBldmVudC5cblx0XHRcdFx0Ly8gRG9uJ3QgZG8gZGVmYXVsdCBhY3Rpb25zIG9uIHdpbmRvdywgdGhhdCdzIHdoZXJlIGdsb2JhbCB2YXJpYWJsZXMgYmUgKCM2MTcwKVxuXHRcdFx0XHRpZiAoIG9udHlwZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggZWxlbVsgdHlwZSBdICkgJiYgIWpRdWVyeS5pc1dpbmRvdyggZWxlbSApICkge1xuXG5cdFx0XHRcdFx0Ly8gRG9uJ3QgcmUtdHJpZ2dlciBhbiBvbkZPTyBldmVudCB3aGVuIHdlIGNhbGwgaXRzIEZPTygpIG1ldGhvZFxuXHRcdFx0XHRcdHRtcCA9IGVsZW1bIG9udHlwZSBdO1xuXG5cdFx0XHRcdFx0aWYgKCB0bXAgKSB7XG5cdFx0XHRcdFx0XHRlbGVtWyBvbnR5cGUgXSA9IG51bGw7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gUHJldmVudCByZS10cmlnZ2VyaW5nIG9mIHRoZSBzYW1lIGV2ZW50LCBzaW5jZSB3ZSBhbHJlYWR5IGJ1YmJsZWQgaXQgYWJvdmVcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlcmVkID0gdHlwZTtcblx0XHRcdFx0XHRlbGVtWyB0eXBlIF0oKTtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlcmVkID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRcdFx0aWYgKCB0bXAgKSB7XG5cdFx0XHRcdFx0XHRlbGVtWyBvbnR5cGUgXSA9IHRtcDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnQucmVzdWx0O1xuXHR9LFxuXG5cdC8vIFBpZ2d5YmFjayBvbiBhIGRvbm9yIGV2ZW50IHRvIHNpbXVsYXRlIGEgZGlmZmVyZW50IG9uZVxuXHQvLyBVc2VkIG9ubHkgZm9yIGBmb2N1cyhpbiB8IG91dClgIGV2ZW50c1xuXHRzaW11bGF0ZTogZnVuY3Rpb24oIHR5cGUsIGVsZW0sIGV2ZW50ICkge1xuXHRcdHZhciBlID0galF1ZXJ5LmV4dGVuZChcblx0XHRcdG5ldyBqUXVlcnkuRXZlbnQoKSxcblx0XHRcdGV2ZW50LFxuXHRcdFx0e1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRpc1NpbXVsYXRlZDogdHJ1ZVxuXHRcdFx0fVxuXHRcdCk7XG5cblx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlciggZSwgbnVsbCwgZWxlbSApO1xuXHR9XG5cbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXG5cdHRyaWdnZXI6IGZ1bmN0aW9uKCB0eXBlLCBkYXRhICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIHR5cGUsIGRhdGEsIHRoaXMgKTtcblx0XHR9ICk7XG5cdH0sXG5cdHRyaWdnZXJIYW5kbGVyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXTtcblx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4galF1ZXJ5LmV2ZW50LnRyaWdnZXIoIHR5cGUsIGRhdGEsIGVsZW0sIHRydWUgKTtcblx0XHR9XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZWFjaCggKCBcImJsdXIgZm9jdXMgZm9jdXNpbiBmb2N1c291dCByZXNpemUgc2Nyb2xsIGNsaWNrIGRibGNsaWNrIFwiICtcblx0XCJtb3VzZWRvd24gbW91c2V1cCBtb3VzZW1vdmUgbW91c2VvdmVyIG1vdXNlb3V0IG1vdXNlZW50ZXIgbW91c2VsZWF2ZSBcIiArXG5cdFwiY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBjb250ZXh0bWVudVwiICkuc3BsaXQoIFwiIFwiICksXG5cdGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXG5cdC8vIEhhbmRsZSBldmVudCBiaW5kaW5nXG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiBhcmd1bWVudHMubGVuZ3RoID4gMCA/XG5cdFx0XHR0aGlzLm9uKCBuYW1lLCBudWxsLCBkYXRhLCBmbiApIDpcblx0XHRcdHRoaXMudHJpZ2dlciggbmFtZSApO1xuXHR9O1xufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGhvdmVyOiBmdW5jdGlvbiggZm5PdmVyLCBmbk91dCApIHtcblx0XHRyZXR1cm4gdGhpcy5tb3VzZWVudGVyKCBmbk92ZXIgKS5tb3VzZWxlYXZlKCBmbk91dCB8fCBmbk92ZXIgKTtcblx0fVxufSApO1xuXG5cblxuXG5zdXBwb3J0LmZvY3VzaW4gPSBcIm9uZm9jdXNpblwiIGluIHdpbmRvdztcblxuXG4vLyBTdXBwb3J0OiBGaXJlZm94IDw9NDRcbi8vIEZpcmVmb3ggZG9lc24ndCBoYXZlIGZvY3VzKGluIHwgb3V0KSBldmVudHNcbi8vIFJlbGF0ZWQgdGlja2V0IC0gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njg3Nzg3XG4vL1xuLy8gU3VwcG9ydDogQ2hyb21lIDw9NDggLSA0OSwgU2FmYXJpIDw9OS4wIC0gOS4xXG4vLyBmb2N1cyhpbiB8IG91dCkgZXZlbnRzIGZpcmUgYWZ0ZXIgZm9jdXMgJiBibHVyIGV2ZW50cyxcbi8vIHdoaWNoIGlzIHNwZWMgdmlvbGF0aW9uIC0gaHR0cDovL3d3dy53My5vcmcvVFIvRE9NLUxldmVsLTMtRXZlbnRzLyNldmVudHMtZm9jdXNldmVudC1ldmVudC1vcmRlclxuLy8gUmVsYXRlZCB0aWNrZXQgLSBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDk4NTdcbmlmICggIXN1cHBvcnQuZm9jdXNpbiApIHtcblx0alF1ZXJ5LmVhY2goIHsgZm9jdXM6IFwiZm9jdXNpblwiLCBibHVyOiBcImZvY3Vzb3V0XCIgfSwgZnVuY3Rpb24oIG9yaWcsIGZpeCApIHtcblxuXHRcdC8vIEF0dGFjaCBhIHNpbmdsZSBjYXB0dXJpbmcgaGFuZGxlciBvbiB0aGUgZG9jdW1lbnQgd2hpbGUgc29tZW9uZSB3YW50cyBmb2N1c2luL2ZvY3Vzb3V0XG5cdFx0dmFyIGhhbmRsZXIgPSBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQuc2ltdWxhdGUoIGZpeCwgZXZlbnQudGFyZ2V0LCBqUXVlcnkuZXZlbnQuZml4KCBldmVudCApICk7XG5cdFx0fTtcblxuXHRcdGpRdWVyeS5ldmVudC5zcGVjaWFsWyBmaXggXSA9IHtcblx0XHRcdHNldHVwOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCApO1xuXG5cdFx0XHRcdGlmICggIWF0dGFjaGVzICkge1xuXHRcdFx0XHRcdGRvYy5hZGRFdmVudExpc3RlbmVyKCBvcmlnLCBoYW5kbGVyLCB0cnVlICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCwgKCBhdHRhY2hlcyB8fCAwICkgKyAxICk7XG5cdFx0XHR9LFxuXHRcdFx0dGVhcmRvd246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgZG9jID0gdGhpcy5vd25lckRvY3VtZW50IHx8IHRoaXMsXG5cdFx0XHRcdFx0YXR0YWNoZXMgPSBkYXRhUHJpdi5hY2Nlc3MoIGRvYywgZml4ICkgLSAxO1xuXG5cdFx0XHRcdGlmICggIWF0dGFjaGVzICkge1xuXHRcdFx0XHRcdGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCBvcmlnLCBoYW5kbGVyLCB0cnVlICk7XG5cdFx0XHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBkb2MsIGZpeCApO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCwgYXR0YWNoZXMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH0gKTtcbn1cbnZhciBsb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbjtcblxudmFyIG5vbmNlID0galF1ZXJ5Lm5vdygpO1xuXG52YXIgcnF1ZXJ5ID0gKCAvXFw/LyApO1xuXG5cblxuLy8gQ3Jvc3MtYnJvd3NlciB4bWwgcGFyc2luZ1xualF1ZXJ5LnBhcnNlWE1MID0gZnVuY3Rpb24oIGRhdGEgKSB7XG5cdHZhciB4bWw7XG5cdGlmICggIWRhdGEgfHwgdHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRSA5IC0gMTEgb25seVxuXHQvLyBJRSB0aHJvd3Mgb24gcGFyc2VGcm9tU3RyaW5nIHdpdGggaW52YWxpZCBpbnB1dC5cblx0dHJ5IHtcblx0XHR4bWwgPSAoIG5ldyB3aW5kb3cuRE9NUGFyc2VyKCkgKS5wYXJzZUZyb21TdHJpbmcoIGRhdGEsIFwidGV4dC94bWxcIiApO1xuXHR9IGNhdGNoICggZSApIHtcblx0XHR4bWwgPSB1bmRlZmluZWQ7XG5cdH1cblxuXHRpZiAoICF4bWwgfHwgeG1sLmdldEVsZW1lbnRzQnlUYWdOYW1lKCBcInBhcnNlcmVycm9yXCIgKS5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmVycm9yKCBcIkludmFsaWQgWE1MOiBcIiArIGRhdGEgKTtcblx0fVxuXHRyZXR1cm4geG1sO1xufTtcblxuXG52YXJcblx0cmJyYWNrZXQgPSAvXFxbXFxdJC8sXG5cdHJDUkxGID0gL1xccj9cXG4vZyxcblx0cnN1Ym1pdHRlclR5cGVzID0gL14oPzpzdWJtaXR8YnV0dG9ufGltYWdlfHJlc2V0fGZpbGUpJC9pLFxuXHRyc3VibWl0dGFibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxrZXlnZW4pL2k7XG5cbmZ1bmN0aW9uIGJ1aWxkUGFyYW1zKCBwcmVmaXgsIG9iaiwgdHJhZGl0aW9uYWwsIGFkZCApIHtcblx0dmFyIG5hbWU7XG5cblx0aWYgKCBBcnJheS5pc0FycmF5KCBvYmogKSApIHtcblxuXHRcdC8vIFNlcmlhbGl6ZSBhcnJheSBpdGVtLlxuXHRcdGpRdWVyeS5lYWNoKCBvYmosIGZ1bmN0aW9uKCBpLCB2ICkge1xuXHRcdFx0aWYgKCB0cmFkaXRpb25hbCB8fCByYnJhY2tldC50ZXN0KCBwcmVmaXggKSApIHtcblxuXHRcdFx0XHQvLyBUcmVhdCBlYWNoIGFycmF5IGl0ZW0gYXMgYSBzY2FsYXIuXG5cdFx0XHRcdGFkZCggcHJlZml4LCB2ICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gSXRlbSBpcyBub24tc2NhbGFyIChhcnJheSBvciBvYmplY3QpLCBlbmNvZGUgaXRzIG51bWVyaWMgaW5kZXguXG5cdFx0XHRcdGJ1aWxkUGFyYW1zKFxuXHRcdFx0XHRcdHByZWZpeCArIFwiW1wiICsgKCB0eXBlb2YgdiA9PT0gXCJvYmplY3RcIiAmJiB2ICE9IG51bGwgPyBpIDogXCJcIiApICsgXCJdXCIsXG5cdFx0XHRcdFx0dixcblx0XHRcdFx0XHR0cmFkaXRpb25hbCxcblx0XHRcdFx0XHRhZGRcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9ICk7XG5cblx0fSBlbHNlIGlmICggIXRyYWRpdGlvbmFsICYmIGpRdWVyeS50eXBlKCBvYmogKSA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdC8vIFNlcmlhbGl6ZSBvYmplY3QgaXRlbS5cblx0XHRmb3IgKCBuYW1lIGluIG9iaiApIHtcblx0XHRcdGJ1aWxkUGFyYW1zKCBwcmVmaXggKyBcIltcIiArIG5hbWUgKyBcIl1cIiwgb2JqWyBuYW1lIF0sIHRyYWRpdGlvbmFsLCBhZGQgKTtcblx0XHR9XG5cblx0fSBlbHNlIHtcblxuXHRcdC8vIFNlcmlhbGl6ZSBzY2FsYXIgaXRlbS5cblx0XHRhZGQoIHByZWZpeCwgb2JqICk7XG5cdH1cbn1cblxuLy8gU2VyaWFsaXplIGFuIGFycmF5IG9mIGZvcm0gZWxlbWVudHMgb3IgYSBzZXQgb2Zcbi8vIGtleS92YWx1ZXMgaW50byBhIHF1ZXJ5IHN0cmluZ1xualF1ZXJ5LnBhcmFtID0gZnVuY3Rpb24oIGEsIHRyYWRpdGlvbmFsICkge1xuXHR2YXIgcHJlZml4LFxuXHRcdHMgPSBbXSxcblx0XHRhZGQgPSBmdW5jdGlvbigga2V5LCB2YWx1ZU9yRnVuY3Rpb24gKSB7XG5cblx0XHRcdC8vIElmIHZhbHVlIGlzIGEgZnVuY3Rpb24sIGludm9rZSBpdCBhbmQgdXNlIGl0cyByZXR1cm4gdmFsdWVcblx0XHRcdHZhciB2YWx1ZSA9IGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZU9yRnVuY3Rpb24gKSA/XG5cdFx0XHRcdHZhbHVlT3JGdW5jdGlvbigpIDpcblx0XHRcdFx0dmFsdWVPckZ1bmN0aW9uO1xuXG5cdFx0XHRzWyBzLmxlbmd0aCBdID0gZW5jb2RlVVJJQ29tcG9uZW50KCBrZXkgKSArIFwiPVwiICtcblx0XHRcdFx0ZW5jb2RlVVJJQ29tcG9uZW50KCB2YWx1ZSA9PSBudWxsID8gXCJcIiA6IHZhbHVlICk7XG5cdFx0fTtcblxuXHQvLyBJZiBhbiBhcnJheSB3YXMgcGFzc2VkIGluLCBhc3N1bWUgdGhhdCBpdCBpcyBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzLlxuXHRpZiAoIEFycmF5LmlzQXJyYXkoIGEgKSB8fCAoIGEuanF1ZXJ5ICYmICFqUXVlcnkuaXNQbGFpbk9iamVjdCggYSApICkgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgdGhlIGZvcm0gZWxlbWVudHNcblx0XHRqUXVlcnkuZWFjaCggYSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRhZGQoIHRoaXMubmFtZSwgdGhpcy52YWx1ZSApO1xuXHRcdH0gKTtcblxuXHR9IGVsc2Uge1xuXG5cdFx0Ly8gSWYgdHJhZGl0aW9uYWwsIGVuY29kZSB0aGUgXCJvbGRcIiB3YXkgKHRoZSB3YXkgMS4zLjIgb3Igb2xkZXJcblx0XHQvLyBkaWQgaXQpLCBvdGhlcndpc2UgZW5jb2RlIHBhcmFtcyByZWN1cnNpdmVseS5cblx0XHRmb3IgKCBwcmVmaXggaW4gYSApIHtcblx0XHRcdGJ1aWxkUGFyYW1zKCBwcmVmaXgsIGFbIHByZWZpeCBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmV0dXJuIHRoZSByZXN1bHRpbmcgc2VyaWFsaXphdGlvblxuXHRyZXR1cm4gcy5qb2luKCBcIiZcIiApO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRzZXJpYWxpemU6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiBqUXVlcnkucGFyYW0oIHRoaXMuc2VyaWFsaXplQXJyYXkoKSApO1xuXHR9LFxuXHRzZXJpYWxpemVBcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gQ2FuIGFkZCBwcm9wSG9vayBmb3IgXCJlbGVtZW50c1wiIHRvIGZpbHRlciBvciBhZGQgZm9ybSBlbGVtZW50c1xuXHRcdFx0dmFyIGVsZW1lbnRzID0galF1ZXJ5LnByb3AoIHRoaXMsIFwiZWxlbWVudHNcIiApO1xuXHRcdFx0cmV0dXJuIGVsZW1lbnRzID8galF1ZXJ5Lm1ha2VBcnJheSggZWxlbWVudHMgKSA6IHRoaXM7XG5cdFx0fSApXG5cdFx0LmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgdHlwZSA9IHRoaXMudHlwZTtcblxuXHRcdFx0Ly8gVXNlIC5pcyggXCI6ZGlzYWJsZWRcIiApIHNvIHRoYXQgZmllbGRzZXRbZGlzYWJsZWRdIHdvcmtzXG5cdFx0XHRyZXR1cm4gdGhpcy5uYW1lICYmICFqUXVlcnkoIHRoaXMgKS5pcyggXCI6ZGlzYWJsZWRcIiApICYmXG5cdFx0XHRcdHJzdWJtaXR0YWJsZS50ZXN0KCB0aGlzLm5vZGVOYW1lICkgJiYgIXJzdWJtaXR0ZXJUeXBlcy50ZXN0KCB0eXBlICkgJiZcblx0XHRcdFx0KCB0aGlzLmNoZWNrZWQgfHwgIXJjaGVja2FibGVUeXBlLnRlc3QoIHR5cGUgKSApO1xuXHRcdH0gKVxuXHRcdC5tYXAoIGZ1bmN0aW9uKCBpLCBlbGVtICkge1xuXHRcdFx0dmFyIHZhbCA9IGpRdWVyeSggdGhpcyApLnZhbCgpO1xuXG5cdFx0XHRpZiAoIHZhbCA9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWwgKSApIHtcblx0XHRcdFx0cmV0dXJuIGpRdWVyeS5tYXAoIHZhbCwgZnVuY3Rpb24oIHZhbCApIHtcblx0XHRcdFx0XHRyZXR1cm4geyBuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWwucmVwbGFjZSggckNSTEYsIFwiXFxyXFxuXCIgKSB9O1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB7IG5hbWU6IGVsZW0ubmFtZSwgdmFsdWU6IHZhbC5yZXBsYWNlKCByQ1JMRiwgXCJcXHJcXG5cIiApIH07XG5cdFx0fSApLmdldCgpO1xuXHR9XG59ICk7XG5cblxudmFyXG5cdHIyMCA9IC8lMjAvZyxcblx0cmhhc2ggPSAvIy4qJC8sXG5cdHJhbnRpQ2FjaGUgPSAvKFs/Jl0pXz1bXiZdKi8sXG5cdHJoZWFkZXJzID0gL14oLio/KTpbIFxcdF0qKFteXFxyXFxuXSopJC9tZyxcblxuXHQvLyAjNzY1MywgIzgxMjUsICM4MTUyOiBsb2NhbCBwcm90b2NvbCBkZXRlY3Rpb25cblx0cmxvY2FsUHJvdG9jb2wgPSAvXig/OmFib3V0fGFwcHxhcHAtc3RvcmFnZXwuKy1leHRlbnNpb258ZmlsZXxyZXN8d2lkZ2V0KTokLyxcblx0cm5vQ29udGVudCA9IC9eKD86R0VUfEhFQUQpJC8sXG5cdHJwcm90b2NvbCA9IC9eXFwvXFwvLyxcblxuXHQvKiBQcmVmaWx0ZXJzXG5cdCAqIDEpIFRoZXkgYXJlIHVzZWZ1bCB0byBpbnRyb2R1Y2UgY3VzdG9tIGRhdGFUeXBlcyAoc2VlIGFqYXgvanNvbnAuanMgZm9yIGFuIGV4YW1wbGUpXG5cdCAqIDIpIFRoZXNlIGFyZSBjYWxsZWQ6XG5cdCAqICAgIC0gQkVGT1JFIGFza2luZyBmb3IgYSB0cmFuc3BvcnRcblx0ICogICAgLSBBRlRFUiBwYXJhbSBzZXJpYWxpemF0aW9uIChzLmRhdGEgaXMgYSBzdHJpbmcgaWYgcy5wcm9jZXNzRGF0YSBpcyB0cnVlKVxuXHQgKiAzKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDQpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogNSkgZXhlY3V0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gY29udGludWUgZG93biB0byBcIipcIiBpZiBuZWVkZWRcblx0ICovXG5cdHByZWZpbHRlcnMgPSB7fSxcblxuXHQvKiBUcmFuc3BvcnRzIGJpbmRpbmdzXG5cdCAqIDEpIGtleSBpcyB0aGUgZGF0YVR5cGVcblx0ICogMikgdGhlIGNhdGNoYWxsIHN5bWJvbCBcIipcIiBjYW4gYmUgdXNlZFxuXHQgKiAzKSBzZWxlY3Rpb24gd2lsbCBzdGFydCB3aXRoIHRyYW5zcG9ydCBkYXRhVHlwZSBhbmQgVEhFTiBnbyB0byBcIipcIiBpZiBuZWVkZWRcblx0ICovXG5cdHRyYW5zcG9ydHMgPSB7fSxcblxuXHQvLyBBdm9pZCBjb21tZW50LXByb2xvZyBjaGFyIHNlcXVlbmNlICgjMTAwOTgpOyBtdXN0IGFwcGVhc2UgbGludCBhbmQgZXZhZGUgY29tcHJlc3Npb25cblx0YWxsVHlwZXMgPSBcIiovXCIuY29uY2F0KCBcIipcIiApLFxuXG5cdC8vIEFuY2hvciB0YWcgZm9yIHBhcnNpbmcgdGhlIGRvY3VtZW50IG9yaWdpblxuXHRvcmlnaW5BbmNob3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImFcIiApO1xuXHRvcmlnaW5BbmNob3IuaHJlZiA9IGxvY2F0aW9uLmhyZWY7XG5cbi8vIEJhc2UgXCJjb25zdHJ1Y3RvclwiIGZvciBqUXVlcnkuYWpheFByZWZpbHRlciBhbmQgalF1ZXJ5LmFqYXhUcmFuc3BvcnRcbmZ1bmN0aW9uIGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlICkge1xuXG5cdC8vIGRhdGFUeXBlRXhwcmVzc2lvbiBpcyBvcHRpb25hbCBhbmQgZGVmYXVsdHMgdG8gXCIqXCJcblx0cmV0dXJuIGZ1bmN0aW9uKCBkYXRhVHlwZUV4cHJlc3Npb24sIGZ1bmMgKSB7XG5cblx0XHRpZiAoIHR5cGVvZiBkYXRhVHlwZUV4cHJlc3Npb24gIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRmdW5jID0gZGF0YVR5cGVFeHByZXNzaW9uO1xuXHRcdFx0ZGF0YVR5cGVFeHByZXNzaW9uID0gXCIqXCI7XG5cdFx0fVxuXG5cdFx0dmFyIGRhdGFUeXBlLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRkYXRhVHlwZXMgPSBkYXRhVHlwZUV4cHJlc3Npb24udG9Mb3dlckNhc2UoKS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggZnVuYyApICkge1xuXG5cdFx0XHQvLyBGb3IgZWFjaCBkYXRhVHlwZSBpbiB0aGUgZGF0YVR5cGVFeHByZXNzaW9uXG5cdFx0XHR3aGlsZSAoICggZGF0YVR5cGUgPSBkYXRhVHlwZXNbIGkrKyBdICkgKSB7XG5cblx0XHRcdFx0Ly8gUHJlcGVuZCBpZiByZXF1ZXN0ZWRcblx0XHRcdFx0aWYgKCBkYXRhVHlwZVsgMCBdID09PSBcIitcIiApIHtcblx0XHRcdFx0XHRkYXRhVHlwZSA9IGRhdGFUeXBlLnNsaWNlKCAxICkgfHwgXCIqXCI7XG5cdFx0XHRcdFx0KCBzdHJ1Y3R1cmVbIGRhdGFUeXBlIF0gPSBzdHJ1Y3R1cmVbIGRhdGFUeXBlIF0gfHwgW10gKS51bnNoaWZ0KCBmdW5jICk7XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlIGFwcGVuZFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdCggc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdICkucHVzaCggZnVuYyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xufVxuXG4vLyBCYXNlIGluc3BlY3Rpb24gZnVuY3Rpb24gZm9yIHByZWZpbHRlcnMgYW5kIHRyYW5zcG9ydHNcbmZ1bmN0aW9uIGluc3BlY3RQcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBzdHJ1Y3R1cmUsIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKSB7XG5cblx0dmFyIGluc3BlY3RlZCA9IHt9LFxuXHRcdHNlZWtpbmdUcmFuc3BvcnQgPSAoIHN0cnVjdHVyZSA9PT0gdHJhbnNwb3J0cyApO1xuXG5cdGZ1bmN0aW9uIGluc3BlY3QoIGRhdGFUeXBlICkge1xuXHRcdHZhciBzZWxlY3RlZDtcblx0XHRpbnNwZWN0ZWRbIGRhdGFUeXBlIF0gPSB0cnVlO1xuXHRcdGpRdWVyeS5lYWNoKCBzdHJ1Y3R1cmVbIGRhdGFUeXBlIF0gfHwgW10sIGZ1bmN0aW9uKCBfLCBwcmVmaWx0ZXJPckZhY3RvcnkgKSB7XG5cdFx0XHR2YXIgZGF0YVR5cGVPclRyYW5zcG9ydCA9IHByZWZpbHRlck9yRmFjdG9yeSggb3B0aW9ucywgb3JpZ2luYWxPcHRpb25zLCBqcVhIUiApO1xuXHRcdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVPclRyYW5zcG9ydCA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHQhc2Vla2luZ1RyYW5zcG9ydCAmJiAhaW5zcGVjdGVkWyBkYXRhVHlwZU9yVHJhbnNwb3J0IF0gKSB7XG5cblx0XHRcdFx0b3B0aW9ucy5kYXRhVHlwZXMudW5zaGlmdCggZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0XHRpbnNwZWN0KCBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH0gZWxzZSBpZiAoIHNlZWtpbmdUcmFuc3BvcnQgKSB7XG5cdFx0XHRcdHJldHVybiAhKCBzZWxlY3RlZCA9IGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdFx0cmV0dXJuIHNlbGVjdGVkO1xuXHR9XG5cblx0cmV0dXJuIGluc3BlY3QoIG9wdGlvbnMuZGF0YVR5cGVzWyAwIF0gKSB8fCAhaW5zcGVjdGVkWyBcIipcIiBdICYmIGluc3BlY3QoIFwiKlwiICk7XG59XG5cbi8vIEEgc3BlY2lhbCBleHRlbmQgZm9yIGFqYXggb3B0aW9uc1xuLy8gdGhhdCB0YWtlcyBcImZsYXRcIiBvcHRpb25zIChub3QgdG8gYmUgZGVlcCBleHRlbmRlZClcbi8vIEZpeGVzICM5ODg3XG5mdW5jdGlvbiBhamF4RXh0ZW5kKCB0YXJnZXQsIHNyYyApIHtcblx0dmFyIGtleSwgZGVlcCxcblx0XHRmbGF0T3B0aW9ucyA9IGpRdWVyeS5hamF4U2V0dGluZ3MuZmxhdE9wdGlvbnMgfHwge307XG5cblx0Zm9yICgga2V5IGluIHNyYyApIHtcblx0XHRpZiAoIHNyY1sga2V5IF0gIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdCggZmxhdE9wdGlvbnNbIGtleSBdID8gdGFyZ2V0IDogKCBkZWVwIHx8ICggZGVlcCA9IHt9ICkgKSApWyBrZXkgXSA9IHNyY1sga2V5IF07XG5cdFx0fVxuXHR9XG5cdGlmICggZGVlcCApIHtcblx0XHRqUXVlcnkuZXh0ZW5kKCB0cnVlLCB0YXJnZXQsIGRlZXAgKTtcblx0fVxuXG5cdHJldHVybiB0YXJnZXQ7XG59XG5cbi8qIEhhbmRsZXMgcmVzcG9uc2VzIHRvIGFuIGFqYXggcmVxdWVzdDpcbiAqIC0gZmluZHMgdGhlIHJpZ2h0IGRhdGFUeXBlIChtZWRpYXRlcyBiZXR3ZWVuIGNvbnRlbnQtdHlwZSBhbmQgZXhwZWN0ZWQgZGF0YVR5cGUpXG4gKiAtIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcmVzcG9uc2VcbiAqL1xuZnVuY3Rpb24gYWpheEhhbmRsZVJlc3BvbnNlcyggcywganFYSFIsIHJlc3BvbnNlcyApIHtcblxuXHR2YXIgY3QsIHR5cGUsIGZpbmFsRGF0YVR5cGUsIGZpcnN0RGF0YVR5cGUsXG5cdFx0Y29udGVudHMgPSBzLmNvbnRlbnRzLFxuXHRcdGRhdGFUeXBlcyA9IHMuZGF0YVR5cGVzO1xuXG5cdC8vIFJlbW92ZSBhdXRvIGRhdGFUeXBlIGFuZCBnZXQgY29udGVudC10eXBlIGluIHRoZSBwcm9jZXNzXG5cdHdoaWxlICggZGF0YVR5cGVzWyAwIF0gPT09IFwiKlwiICkge1xuXHRcdGRhdGFUeXBlcy5zaGlmdCgpO1xuXHRcdGlmICggY3QgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGN0ID0gcy5taW1lVHlwZSB8fCBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJDb250ZW50LVR5cGVcIiApO1xuXHRcdH1cblx0fVxuXG5cdC8vIENoZWNrIGlmIHdlJ3JlIGRlYWxpbmcgd2l0aCBhIGtub3duIGNvbnRlbnQtdHlwZVxuXHRpZiAoIGN0ICkge1xuXHRcdGZvciAoIHR5cGUgaW4gY29udGVudHMgKSB7XG5cdFx0XHRpZiAoIGNvbnRlbnRzWyB0eXBlIF0gJiYgY29udGVudHNbIHR5cGUgXS50ZXN0KCBjdCApICkge1xuXHRcdFx0XHRkYXRhVHlwZXMudW5zaGlmdCggdHlwZSApO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayB0byBzZWUgaWYgd2UgaGF2ZSBhIHJlc3BvbnNlIGZvciB0aGUgZXhwZWN0ZWQgZGF0YVR5cGVcblx0aWYgKCBkYXRhVHlwZXNbIDAgXSBpbiByZXNwb25zZXMgKSB7XG5cdFx0ZmluYWxEYXRhVHlwZSA9IGRhdGFUeXBlc1sgMCBdO1xuXHR9IGVsc2Uge1xuXG5cdFx0Ly8gVHJ5IGNvbnZlcnRpYmxlIGRhdGFUeXBlc1xuXHRcdGZvciAoIHR5cGUgaW4gcmVzcG9uc2VzICkge1xuXHRcdFx0aWYgKCAhZGF0YVR5cGVzWyAwIF0gfHwgcy5jb252ZXJ0ZXJzWyB0eXBlICsgXCIgXCIgKyBkYXRhVHlwZXNbIDAgXSBdICkge1xuXHRcdFx0XHRmaW5hbERhdGFUeXBlID0gdHlwZTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRpZiAoICFmaXJzdERhdGFUeXBlICkge1xuXHRcdFx0XHRmaXJzdERhdGFUeXBlID0gdHlwZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBPciBqdXN0IHVzZSBmaXJzdCBvbmVcblx0XHRmaW5hbERhdGFUeXBlID0gZmluYWxEYXRhVHlwZSB8fCBmaXJzdERhdGFUeXBlO1xuXHR9XG5cblx0Ly8gSWYgd2UgZm91bmQgYSBkYXRhVHlwZVxuXHQvLyBXZSBhZGQgdGhlIGRhdGFUeXBlIHRvIHRoZSBsaXN0IGlmIG5lZWRlZFxuXHQvLyBhbmQgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG5cdGlmICggZmluYWxEYXRhVHlwZSApIHtcblx0XHRpZiAoIGZpbmFsRGF0YVR5cGUgIT09IGRhdGFUeXBlc1sgMCBdICkge1xuXHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIGZpbmFsRGF0YVR5cGUgKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlc3BvbnNlc1sgZmluYWxEYXRhVHlwZSBdO1xuXHR9XG59XG5cbi8qIENoYWluIGNvbnZlcnNpb25zIGdpdmVuIHRoZSByZXF1ZXN0IGFuZCB0aGUgb3JpZ2luYWwgcmVzcG9uc2VcbiAqIEFsc28gc2V0cyB0aGUgcmVzcG9uc2VYWFggZmllbGRzIG9uIHRoZSBqcVhIUiBpbnN0YW5jZVxuICovXG5mdW5jdGlvbiBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKSB7XG5cdHZhciBjb252MiwgY3VycmVudCwgY29udiwgdG1wLCBwcmV2LFxuXHRcdGNvbnZlcnRlcnMgPSB7fSxcblxuXHRcdC8vIFdvcmsgd2l0aCBhIGNvcHkgb2YgZGF0YVR5cGVzIGluIGNhc2Ugd2UgbmVlZCB0byBtb2RpZnkgaXQgZm9yIGNvbnZlcnNpb25cblx0XHRkYXRhVHlwZXMgPSBzLmRhdGFUeXBlcy5zbGljZSgpO1xuXG5cdC8vIENyZWF0ZSBjb252ZXJ0ZXJzIG1hcCB3aXRoIGxvd2VyY2FzZWQga2V5c1xuXHRpZiAoIGRhdGFUeXBlc1sgMSBdICkge1xuXHRcdGZvciAoIGNvbnYgaW4gcy5jb252ZXJ0ZXJzICkge1xuXHRcdFx0Y29udmVydGVyc1sgY29udi50b0xvd2VyQ2FzZSgpIF0gPSBzLmNvbnZlcnRlcnNbIGNvbnYgXTtcblx0XHR9XG5cdH1cblxuXHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0Ly8gQ29udmVydCB0byBlYWNoIHNlcXVlbnRpYWwgZGF0YVR5cGVcblx0d2hpbGUgKCBjdXJyZW50ICkge1xuXG5cdFx0aWYgKCBzLnJlc3BvbnNlRmllbGRzWyBjdXJyZW50IF0gKSB7XG5cdFx0XHRqcVhIUlsgcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdIF0gPSByZXNwb25zZTtcblx0XHR9XG5cblx0XHQvLyBBcHBseSB0aGUgZGF0YUZpbHRlciBpZiBwcm92aWRlZFxuXHRcdGlmICggIXByZXYgJiYgaXNTdWNjZXNzICYmIHMuZGF0YUZpbHRlciApIHtcblx0XHRcdHJlc3BvbnNlID0gcy5kYXRhRmlsdGVyKCByZXNwb25zZSwgcy5kYXRhVHlwZSApO1xuXHRcdH1cblxuXHRcdHByZXYgPSBjdXJyZW50O1xuXHRcdGN1cnJlbnQgPSBkYXRhVHlwZXMuc2hpZnQoKTtcblxuXHRcdGlmICggY3VycmVudCApIHtcblxuXHRcdFx0Ly8gVGhlcmUncyBvbmx5IHdvcmsgdG8gZG8gaWYgY3VycmVudCBkYXRhVHlwZSBpcyBub24tYXV0b1xuXHRcdFx0aWYgKCBjdXJyZW50ID09PSBcIipcIiApIHtcblxuXHRcdFx0XHRjdXJyZW50ID0gcHJldjtcblxuXHRcdFx0Ly8gQ29udmVydCByZXNwb25zZSBpZiBwcmV2IGRhdGFUeXBlIGlzIG5vbi1hdXRvIGFuZCBkaWZmZXJzIGZyb20gY3VycmVudFxuXHRcdFx0fSBlbHNlIGlmICggcHJldiAhPT0gXCIqXCIgJiYgcHJldiAhPT0gY3VycmVudCApIHtcblxuXHRcdFx0XHQvLyBTZWVrIGEgZGlyZWN0IGNvbnZlcnRlclxuXHRcdFx0XHRjb252ID0gY29udmVydGVyc1sgcHJldiArIFwiIFwiICsgY3VycmVudCBdIHx8IGNvbnZlcnRlcnNbIFwiKiBcIiArIGN1cnJlbnQgXTtcblxuXHRcdFx0XHQvLyBJZiBub25lIGZvdW5kLCBzZWVrIGEgcGFpclxuXHRcdFx0XHRpZiAoICFjb252ICkge1xuXHRcdFx0XHRcdGZvciAoIGNvbnYyIGluIGNvbnZlcnRlcnMgKSB7XG5cblx0XHRcdFx0XHRcdC8vIElmIGNvbnYyIG91dHB1dHMgY3VycmVudFxuXHRcdFx0XHRcdFx0dG1wID0gY29udjIuc3BsaXQoIFwiIFwiICk7XG5cdFx0XHRcdFx0XHRpZiAoIHRtcFsgMSBdID09PSBjdXJyZW50ICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIElmIHByZXYgY2FuIGJlIGNvbnZlcnRlZCB0byBhY2NlcHRlZCBpbnB1dFxuXHRcdFx0XHRcdFx0XHRjb252ID0gY29udmVydGVyc1sgcHJldiArIFwiIFwiICsgdG1wWyAwIF0gXSB8fFxuXHRcdFx0XHRcdFx0XHRcdGNvbnZlcnRlcnNbIFwiKiBcIiArIHRtcFsgMCBdIF07XG5cdFx0XHRcdFx0XHRcdGlmICggY29udiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIENvbmRlbnNlIGVxdWl2YWxlbmNlIGNvbnZlcnRlcnNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgPT09IHRydWUgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb252ID0gY29udmVydGVyc1sgY29udjIgXTtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIE90aGVyd2lzZSwgaW5zZXJ0IHRoZSBpbnRlcm1lZGlhdGUgZGF0YVR5cGVcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBjb252ZXJ0ZXJzWyBjb252MiBdICE9PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y3VycmVudCA9IHRtcFsgMCBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHRtcFsgMSBdICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQXBwbHkgY29udmVydGVyIChpZiBub3QgYW4gZXF1aXZhbGVuY2UpXG5cdFx0XHRcdGlmICggY29udiAhPT0gdHJ1ZSApIHtcblxuXHRcdFx0XHRcdC8vIFVubGVzcyBlcnJvcnMgYXJlIGFsbG93ZWQgdG8gYnViYmxlLCBjYXRjaCBhbmQgcmV0dXJuIHRoZW1cblx0XHRcdFx0XHRpZiAoIGNvbnYgJiYgcy50aHJvd3MgKSB7XG5cdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdHJlc3BvbnNlID0gY29udiggcmVzcG9uc2UgKTtcblx0XHRcdFx0XHRcdH0gY2F0Y2ggKCBlICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXRlOiBcInBhcnNlcmVycm9yXCIsXG5cdFx0XHRcdFx0XHRcdFx0ZXJyb3I6IGNvbnYgPyBlIDogXCJObyBjb252ZXJzaW9uIGZyb20gXCIgKyBwcmV2ICsgXCIgdG8gXCIgKyBjdXJyZW50XG5cdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHsgc3RhdGU6IFwic3VjY2Vzc1wiLCBkYXRhOiByZXNwb25zZSB9O1xufVxuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gQ291bnRlciBmb3IgaG9sZGluZyB0aGUgbnVtYmVyIG9mIGFjdGl2ZSBxdWVyaWVzXG5cdGFjdGl2ZTogMCxcblxuXHQvLyBMYXN0LU1vZGlmaWVkIGhlYWRlciBjYWNoZSBmb3IgbmV4dCByZXF1ZXN0XG5cdGxhc3RNb2RpZmllZDoge30sXG5cdGV0YWc6IHt9LFxuXG5cdGFqYXhTZXR0aW5nczoge1xuXHRcdHVybDogbG9jYXRpb24uaHJlZixcblx0XHR0eXBlOiBcIkdFVFwiLFxuXHRcdGlzTG9jYWw6IHJsb2NhbFByb3RvY29sLnRlc3QoIGxvY2F0aW9uLnByb3RvY29sICksXG5cdFx0Z2xvYmFsOiB0cnVlLFxuXHRcdHByb2Nlc3NEYXRhOiB0cnVlLFxuXHRcdGFzeW5jOiB0cnVlLFxuXHRcdGNvbnRlbnRUeXBlOiBcImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDsgY2hhcnNldD1VVEYtOFwiLFxuXG5cdFx0Lypcblx0XHR0aW1lb3V0OiAwLFxuXHRcdGRhdGE6IG51bGwsXG5cdFx0ZGF0YVR5cGU6IG51bGwsXG5cdFx0dXNlcm5hbWU6IG51bGwsXG5cdFx0cGFzc3dvcmQ6IG51bGwsXG5cdFx0Y2FjaGU6IG51bGwsXG5cdFx0dGhyb3dzOiBmYWxzZSxcblx0XHR0cmFkaXRpb25hbDogZmFsc2UsXG5cdFx0aGVhZGVyczoge30sXG5cdFx0Ki9cblxuXHRcdGFjY2VwdHM6IHtcblx0XHRcdFwiKlwiOiBhbGxUeXBlcyxcblx0XHRcdHRleHQ6IFwidGV4dC9wbGFpblwiLFxuXHRcdFx0aHRtbDogXCJ0ZXh0L2h0bWxcIixcblx0XHRcdHhtbDogXCJhcHBsaWNhdGlvbi94bWwsIHRleHQveG1sXCIsXG5cdFx0XHRqc29uOiBcImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdFwiXG5cdFx0fSxcblxuXHRcdGNvbnRlbnRzOiB7XG5cdFx0XHR4bWw6IC9cXGJ4bWxcXGIvLFxuXHRcdFx0aHRtbDogL1xcYmh0bWwvLFxuXHRcdFx0anNvbjogL1xcYmpzb25cXGIvXG5cdFx0fSxcblxuXHRcdHJlc3BvbnNlRmllbGRzOiB7XG5cdFx0XHR4bWw6IFwicmVzcG9uc2VYTUxcIixcblx0XHRcdHRleHQ6IFwicmVzcG9uc2VUZXh0XCIsXG5cdFx0XHRqc29uOiBcInJlc3BvbnNlSlNPTlwiXG5cdFx0fSxcblxuXHRcdC8vIERhdGEgY29udmVydGVyc1xuXHRcdC8vIEtleXMgc2VwYXJhdGUgc291cmNlIChvciBjYXRjaGFsbCBcIipcIikgYW5kIGRlc3RpbmF0aW9uIHR5cGVzIHdpdGggYSBzaW5nbGUgc3BhY2Vcblx0XHRjb252ZXJ0ZXJzOiB7XG5cblx0XHRcdC8vIENvbnZlcnQgYW55dGhpbmcgdG8gdGV4dFxuXHRcdFx0XCIqIHRleHRcIjogU3RyaW5nLFxuXG5cdFx0XHQvLyBUZXh0IHRvIGh0bWwgKHRydWUgPSBubyB0cmFuc2Zvcm1hdGlvbilcblx0XHRcdFwidGV4dCBodG1sXCI6IHRydWUsXG5cblx0XHRcdC8vIEV2YWx1YXRlIHRleHQgYXMgYSBqc29uIGV4cHJlc3Npb25cblx0XHRcdFwidGV4dCBqc29uXCI6IEpTT04ucGFyc2UsXG5cblx0XHRcdC8vIFBhcnNlIHRleHQgYXMgeG1sXG5cdFx0XHRcInRleHQgeG1sXCI6IGpRdWVyeS5wYXJzZVhNTFxuXHRcdH0sXG5cblx0XHQvLyBGb3Igb3B0aW9ucyB0aGF0IHNob3VsZG4ndCBiZSBkZWVwIGV4dGVuZGVkOlxuXHRcdC8vIHlvdSBjYW4gYWRkIHlvdXIgb3duIGN1c3RvbSBvcHRpb25zIGhlcmUgaWZcblx0XHQvLyBhbmQgd2hlbiB5b3UgY3JlYXRlIG9uZSB0aGF0IHNob3VsZG4ndCBiZVxuXHRcdC8vIGRlZXAgZXh0ZW5kZWQgKHNlZSBhamF4RXh0ZW5kKVxuXHRcdGZsYXRPcHRpb25zOiB7XG5cdFx0XHR1cmw6IHRydWUsXG5cdFx0XHRjb250ZXh0OiB0cnVlXG5cdFx0fVxuXHR9LFxuXG5cdC8vIENyZWF0ZXMgYSBmdWxsIGZsZWRnZWQgc2V0dGluZ3Mgb2JqZWN0IGludG8gdGFyZ2V0XG5cdC8vIHdpdGggYm90aCBhamF4U2V0dGluZ3MgYW5kIHNldHRpbmdzIGZpZWxkcy5cblx0Ly8gSWYgdGFyZ2V0IGlzIG9taXR0ZWQsIHdyaXRlcyBpbnRvIGFqYXhTZXR0aW5ncy5cblx0YWpheFNldHVwOiBmdW5jdGlvbiggdGFyZ2V0LCBzZXR0aW5ncyApIHtcblx0XHRyZXR1cm4gc2V0dGluZ3MgP1xuXG5cdFx0XHQvLyBCdWlsZGluZyBhIHNldHRpbmdzIG9iamVjdFxuXHRcdFx0YWpheEV4dGVuZCggYWpheEV4dGVuZCggdGFyZ2V0LCBqUXVlcnkuYWpheFNldHRpbmdzICksIHNldHRpbmdzICkgOlxuXG5cdFx0XHQvLyBFeHRlbmRpbmcgYWpheFNldHRpbmdzXG5cdFx0XHRhamF4RXh0ZW5kKCBqUXVlcnkuYWpheFNldHRpbmdzLCB0YXJnZXQgKTtcblx0fSxcblxuXHRhamF4UHJlZmlsdGVyOiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHByZWZpbHRlcnMgKSxcblx0YWpheFRyYW5zcG9ydDogYWRkVG9QcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCB0cmFuc3BvcnRzICksXG5cblx0Ly8gTWFpbiBtZXRob2Rcblx0YWpheDogZnVuY3Rpb24oIHVybCwgb3B0aW9ucyApIHtcblxuXHRcdC8vIElmIHVybCBpcyBhbiBvYmplY3QsIHNpbXVsYXRlIHByZS0xLjUgc2lnbmF0dXJlXG5cdFx0aWYgKCB0eXBlb2YgdXJsID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0b3B0aW9ucyA9IHVybDtcblx0XHRcdHVybCA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBGb3JjZSBvcHRpb25zIHRvIGJlIGFuIG9iamVjdFxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cdFx0dmFyIHRyYW5zcG9ydCxcblxuXHRcdFx0Ly8gVVJMIHdpdGhvdXQgYW50aS1jYWNoZSBwYXJhbVxuXHRcdFx0Y2FjaGVVUkwsXG5cblx0XHRcdC8vIFJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyxcblx0XHRcdHJlc3BvbnNlSGVhZGVycyxcblxuXHRcdFx0Ly8gdGltZW91dCBoYW5kbGVcblx0XHRcdHRpbWVvdXRUaW1lcixcblxuXHRcdFx0Ly8gVXJsIGNsZWFudXAgdmFyXG5cdFx0XHR1cmxBbmNob3IsXG5cblx0XHRcdC8vIFJlcXVlc3Qgc3RhdGUgKGJlY29tZXMgZmFsc2UgdXBvbiBzZW5kIGFuZCB0cnVlIHVwb24gY29tcGxldGlvbilcblx0XHRcdGNvbXBsZXRlZCxcblxuXHRcdFx0Ly8gVG8ga25vdyBpZiBnbG9iYWwgZXZlbnRzIGFyZSB0byBiZSBkaXNwYXRjaGVkXG5cdFx0XHRmaXJlR2xvYmFscyxcblxuXHRcdFx0Ly8gTG9vcCB2YXJpYWJsZVxuXHRcdFx0aSxcblxuXHRcdFx0Ly8gdW5jYWNoZWQgcGFydCBvZiB0aGUgdXJsXG5cdFx0XHR1bmNhY2hlZCxcblxuXHRcdFx0Ly8gQ3JlYXRlIHRoZSBmaW5hbCBvcHRpb25zIG9iamVjdFxuXHRcdFx0cyA9IGpRdWVyeS5hamF4U2V0dXAoIHt9LCBvcHRpb25zICksXG5cblx0XHRcdC8vIENhbGxiYWNrcyBjb250ZXh0XG5cdFx0XHRjYWxsYmFja0NvbnRleHQgPSBzLmNvbnRleHQgfHwgcyxcblxuXHRcdFx0Ly8gQ29udGV4dCBmb3IgZ2xvYmFsIGV2ZW50cyBpcyBjYWxsYmFja0NvbnRleHQgaWYgaXQgaXMgYSBET00gbm9kZSBvciBqUXVlcnkgY29sbGVjdGlvblxuXHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0ID0gcy5jb250ZXh0ICYmXG5cdFx0XHRcdCggY2FsbGJhY2tDb250ZXh0Lm5vZGVUeXBlIHx8IGNhbGxiYWNrQ29udGV4dC5qcXVlcnkgKSA/XG5cdFx0XHRcdFx0alF1ZXJ5KCBjYWxsYmFja0NvbnRleHQgKSA6XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LFxuXG5cdFx0XHQvLyBEZWZlcnJlZHNcblx0XHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCksXG5cdFx0XHRjb21wbGV0ZURlZmVycmVkID0galF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRzdGF0dXNDb2RlID0gcy5zdGF0dXNDb2RlIHx8IHt9LFxuXG5cdFx0XHQvLyBIZWFkZXJzICh0aGV5IGFyZSBzZW50IGFsbCBhdCBvbmNlKVxuXHRcdFx0cmVxdWVzdEhlYWRlcnMgPSB7fSxcblx0XHRcdHJlcXVlc3RIZWFkZXJzTmFtZXMgPSB7fSxcblxuXHRcdFx0Ly8gRGVmYXVsdCBhYm9ydCBtZXNzYWdlXG5cdFx0XHRzdHJBYm9ydCA9IFwiY2FuY2VsZWRcIixcblxuXHRcdFx0Ly8gRmFrZSB4aHJcblx0XHRcdGpxWEhSID0ge1xuXHRcdFx0XHRyZWFkeVN0YXRlOiAwLFxuXG5cdFx0XHRcdC8vIEJ1aWxkcyBoZWFkZXJzIGhhc2h0YWJsZSBpZiBuZWVkZWRcblx0XHRcdFx0Z2V0UmVzcG9uc2VIZWFkZXI6IGZ1bmN0aW9uKCBrZXkgKSB7XG5cdFx0XHRcdFx0dmFyIG1hdGNoO1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkICkge1xuXHRcdFx0XHRcdFx0aWYgKCAhcmVzcG9uc2VIZWFkZXJzICkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZUhlYWRlcnMgPSB7fTtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAoIG1hdGNoID0gcmhlYWRlcnMuZXhlYyggcmVzcG9uc2VIZWFkZXJzU3RyaW5nICkgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXNwb25zZUhlYWRlcnNbIG1hdGNoWyAxIF0udG9Mb3dlckNhc2UoKSBdID0gbWF0Y2hbIDIgXTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0bWF0Y2ggPSByZXNwb25zZUhlYWRlcnNbIGtleS50b0xvd2VyQ2FzZSgpIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiBtYXRjaCA9PSBudWxsID8gbnVsbCA6IG1hdGNoO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFJhdyBzdHJpbmdcblx0XHRcdFx0Z2V0QWxsUmVzcG9uc2VIZWFkZXJzOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gY29tcGxldGVkID8gcmVzcG9uc2VIZWFkZXJzU3RyaW5nIDogbnVsbDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBDYWNoZXMgdGhlIGhlYWRlclxuXHRcdFx0XHRzZXRSZXF1ZXN0SGVhZGVyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0XHRcdFx0aWYgKCBjb21wbGV0ZWQgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRcdG5hbWUgPSByZXF1ZXN0SGVhZGVyc05hbWVzWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSA9XG5cdFx0XHRcdFx0XHRcdHJlcXVlc3RIZWFkZXJzTmFtZXNbIG5hbWUudG9Mb3dlckNhc2UoKSBdIHx8IG5hbWU7XG5cdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc1sgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIE92ZXJyaWRlcyByZXNwb25zZSBjb250ZW50LXR5cGUgaGVhZGVyXG5cdFx0XHRcdG92ZXJyaWRlTWltZVR5cGU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRzLm1pbWVUeXBlID0gdHlwZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gU3RhdHVzLWRlcGVuZGVudCBjYWxsYmFja3Ncblx0XHRcdFx0c3RhdHVzQ29kZTogZnVuY3Rpb24oIG1hcCApIHtcblx0XHRcdFx0XHR2YXIgY29kZTtcblx0XHRcdFx0XHRpZiAoIG1hcCApIHtcblx0XHRcdFx0XHRcdGlmICggY29tcGxldGVkICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIEV4ZWN1dGUgdGhlIGFwcHJvcHJpYXRlIGNhbGxiYWNrc1xuXHRcdFx0XHRcdFx0XHRqcVhIUi5hbHdheXMoIG1hcFsganFYSFIuc3RhdHVzIF0gKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gTGF6eS1hZGQgdGhlIG5ldyBjYWxsYmFja3MgaW4gYSB3YXkgdGhhdCBwcmVzZXJ2ZXMgb2xkIG9uZXNcblx0XHRcdFx0XHRcdFx0Zm9yICggY29kZSBpbiBtYXAgKSB7XG5cdFx0XHRcdFx0XHRcdFx0c3RhdHVzQ29kZVsgY29kZSBdID0gWyBzdGF0dXNDb2RlWyBjb2RlIF0sIG1hcFsgY29kZSBdIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gQ2FuY2VsIHRoZSByZXF1ZXN0XG5cdFx0XHRcdGFib3J0OiBmdW5jdGlvbiggc3RhdHVzVGV4dCApIHtcblx0XHRcdFx0XHR2YXIgZmluYWxUZXh0ID0gc3RhdHVzVGV4dCB8fCBzdHJBYm9ydDtcblx0XHRcdFx0XHRpZiAoIHRyYW5zcG9ydCApIHtcblx0XHRcdFx0XHRcdHRyYW5zcG9ydC5hYm9ydCggZmluYWxUZXh0ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRvbmUoIDAsIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0Ly8gQXR0YWNoIGRlZmVycmVkc1xuXHRcdGRlZmVycmVkLnByb21pc2UoIGpxWEhSICk7XG5cblx0XHQvLyBBZGQgcHJvdG9jb2wgaWYgbm90IHByb3ZpZGVkIChwcmVmaWx0ZXJzIG1pZ2h0IGV4cGVjdCBpdClcblx0XHQvLyBIYW5kbGUgZmFsc3kgdXJsIGluIHRoZSBzZXR0aW5ncyBvYmplY3QgKCMxMDA5MzogY29uc2lzdGVuY3kgd2l0aCBvbGQgc2lnbmF0dXJlKVxuXHRcdC8vIFdlIGFsc28gdXNlIHRoZSB1cmwgcGFyYW1ldGVyIGlmIGF2YWlsYWJsZVxuXHRcdHMudXJsID0gKCAoIHVybCB8fCBzLnVybCB8fCBsb2NhdGlvbi5ocmVmICkgKyBcIlwiIClcblx0XHRcdC5yZXBsYWNlKCBycHJvdG9jb2wsIGxvY2F0aW9uLnByb3RvY29sICsgXCIvL1wiICk7XG5cblx0XHQvLyBBbGlhcyBtZXRob2Qgb3B0aW9uIHRvIHR5cGUgYXMgcGVyIHRpY2tldCAjMTIwMDRcblx0XHRzLnR5cGUgPSBvcHRpb25zLm1ldGhvZCB8fCBvcHRpb25zLnR5cGUgfHwgcy5tZXRob2QgfHwgcy50eXBlO1xuXG5cdFx0Ly8gRXh0cmFjdCBkYXRhVHlwZXMgbGlzdFxuXHRcdHMuZGF0YVR5cGVzID0gKCBzLmRhdGFUeXBlIHx8IFwiKlwiICkudG9Mb3dlckNhc2UoKS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFsgXCJcIiBdO1xuXG5cdFx0Ly8gQSBjcm9zcy1kb21haW4gcmVxdWVzdCBpcyBpbiBvcmRlciB3aGVuIHRoZSBvcmlnaW4gZG9lc24ndCBtYXRjaCB0aGUgY3VycmVudCBvcmlnaW4uXG5cdFx0aWYgKCBzLmNyb3NzRG9tYWluID09IG51bGwgKSB7XG5cdFx0XHR1cmxBbmNob3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImFcIiApO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTggLSAxMSwgRWRnZSAxMiAtIDEzXG5cdFx0XHQvLyBJRSB0aHJvd3MgZXhjZXB0aW9uIG9uIGFjY2Vzc2luZyB0aGUgaHJlZiBwcm9wZXJ0eSBpZiB1cmwgaXMgbWFsZm9ybWVkLFxuXHRcdFx0Ly8gZS5nLiBodHRwOi8vZXhhbXBsZS5jb206ODB4L1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0dXJsQW5jaG9yLmhyZWYgPSBzLnVybDtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTggLSAxMSBvbmx5XG5cdFx0XHRcdC8vIEFuY2hvcidzIGhvc3QgcHJvcGVydHkgaXNuJ3QgY29ycmVjdGx5IHNldCB3aGVuIHMudXJsIGlzIHJlbGF0aXZlXG5cdFx0XHRcdHVybEFuY2hvci5ocmVmID0gdXJsQW5jaG9yLmhyZWY7XG5cdFx0XHRcdHMuY3Jvc3NEb21haW4gPSBvcmlnaW5BbmNob3IucHJvdG9jb2wgKyBcIi8vXCIgKyBvcmlnaW5BbmNob3IuaG9zdCAhPT1cblx0XHRcdFx0XHR1cmxBbmNob3IucHJvdG9jb2wgKyBcIi8vXCIgKyB1cmxBbmNob3IuaG9zdDtcblx0XHRcdH0gY2F0Y2ggKCBlICkge1xuXG5cdFx0XHRcdC8vIElmIHRoZXJlIGlzIGFuIGVycm9yIHBhcnNpbmcgdGhlIFVSTCwgYXNzdW1lIGl0IGlzIGNyb3NzRG9tYWluLFxuXHRcdFx0XHQvLyBpdCBjYW4gYmUgcmVqZWN0ZWQgYnkgdGhlIHRyYW5zcG9ydCBpZiBpdCBpcyBpbnZhbGlkXG5cdFx0XHRcdHMuY3Jvc3NEb21haW4gPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENvbnZlcnQgZGF0YSBpZiBub3QgYWxyZWFkeSBhIHN0cmluZ1xuXHRcdGlmICggcy5kYXRhICYmIHMucHJvY2Vzc0RhdGEgJiYgdHlwZW9mIHMuZGF0YSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHMuZGF0YSA9IGpRdWVyeS5wYXJhbSggcy5kYXRhLCBzLnRyYWRpdGlvbmFsICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgcHJlZmlsdGVyc1xuXHRcdGluc3BlY3RQcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBwcmVmaWx0ZXJzLCBzLCBvcHRpb25zLCBqcVhIUiApO1xuXG5cdFx0Ly8gSWYgcmVxdWVzdCB3YXMgYWJvcnRlZCBpbnNpZGUgYSBwcmVmaWx0ZXIsIHN0b3AgdGhlcmVcblx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdHJldHVybiBqcVhIUjtcblx0XHR9XG5cblx0XHQvLyBXZSBjYW4gZmlyZSBnbG9iYWwgZXZlbnRzIGFzIG9mIG5vdyBpZiBhc2tlZCB0b1xuXHRcdC8vIERvbid0IGZpcmUgZXZlbnRzIGlmIGpRdWVyeS5ldmVudCBpcyB1bmRlZmluZWQgaW4gYW4gQU1ELXVzYWdlIHNjZW5hcmlvICgjMTUxMTgpXG5cdFx0ZmlyZUdsb2JhbHMgPSBqUXVlcnkuZXZlbnQgJiYgcy5nbG9iYWw7XG5cblx0XHQvLyBXYXRjaCBmb3IgYSBuZXcgc2V0IG9mIHJlcXVlc3RzXG5cdFx0aWYgKCBmaXJlR2xvYmFscyAmJiBqUXVlcnkuYWN0aXZlKysgPT09IDAgKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQudHJpZ2dlciggXCJhamF4U3RhcnRcIiApO1xuXHRcdH1cblxuXHRcdC8vIFVwcGVyY2FzZSB0aGUgdHlwZVxuXHRcdHMudHlwZSA9IHMudHlwZS50b1VwcGVyQ2FzZSgpO1xuXG5cdFx0Ly8gRGV0ZXJtaW5lIGlmIHJlcXVlc3QgaGFzIGNvbnRlbnRcblx0XHRzLmhhc0NvbnRlbnQgPSAhcm5vQ29udGVudC50ZXN0KCBzLnR5cGUgKTtcblxuXHRcdC8vIFNhdmUgdGhlIFVSTCBpbiBjYXNlIHdlJ3JlIHRveWluZyB3aXRoIHRoZSBJZi1Nb2RpZmllZC1TaW5jZVxuXHRcdC8vIGFuZC9vciBJZi1Ob25lLU1hdGNoIGhlYWRlciBsYXRlciBvblxuXHRcdC8vIFJlbW92ZSBoYXNoIHRvIHNpbXBsaWZ5IHVybCBtYW5pcHVsYXRpb25cblx0XHRjYWNoZVVSTCA9IHMudXJsLnJlcGxhY2UoIHJoYXNoLCBcIlwiICk7XG5cblx0XHQvLyBNb3JlIG9wdGlvbnMgaGFuZGxpbmcgZm9yIHJlcXVlc3RzIHdpdGggbm8gY29udGVudFxuXHRcdGlmICggIXMuaGFzQ29udGVudCApIHtcblxuXHRcdFx0Ly8gUmVtZW1iZXIgdGhlIGhhc2ggc28gd2UgY2FuIHB1dCBpdCBiYWNrXG5cdFx0XHR1bmNhY2hlZCA9IHMudXJsLnNsaWNlKCBjYWNoZVVSTC5sZW5ndGggKTtcblxuXHRcdFx0Ly8gSWYgZGF0YSBpcyBhdmFpbGFibGUsIGFwcGVuZCBkYXRhIHRvIHVybFxuXHRcdFx0aWYgKCBzLmRhdGEgKSB7XG5cdFx0XHRcdGNhY2hlVVJMICs9ICggcnF1ZXJ5LnRlc3QoIGNhY2hlVVJMICkgPyBcIiZcIiA6IFwiP1wiICkgKyBzLmRhdGE7XG5cblx0XHRcdFx0Ly8gIzk2ODI6IHJlbW92ZSBkYXRhIHNvIHRoYXQgaXQncyBub3QgdXNlZCBpbiBhbiBldmVudHVhbCByZXRyeVxuXHRcdFx0XHRkZWxldGUgcy5kYXRhO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgb3IgdXBkYXRlIGFudGktY2FjaGUgcGFyYW0gaWYgbmVlZGVkXG5cdFx0XHRpZiAoIHMuY2FjaGUgPT09IGZhbHNlICkge1xuXHRcdFx0XHRjYWNoZVVSTCA9IGNhY2hlVVJMLnJlcGxhY2UoIHJhbnRpQ2FjaGUsIFwiJDFcIiApO1xuXHRcdFx0XHR1bmNhY2hlZCA9ICggcnF1ZXJ5LnRlc3QoIGNhY2hlVVJMICkgPyBcIiZcIiA6IFwiP1wiICkgKyBcIl89XCIgKyAoIG5vbmNlKysgKSArIHVuY2FjaGVkO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQdXQgaGFzaCBhbmQgYW50aS1jYWNoZSBvbiB0aGUgVVJMIHRoYXQgd2lsbCBiZSByZXF1ZXN0ZWQgKGdoLTE3MzIpXG5cdFx0XHRzLnVybCA9IGNhY2hlVVJMICsgdW5jYWNoZWQ7XG5cblx0XHQvLyBDaGFuZ2UgJyUyMCcgdG8gJysnIGlmIHRoaXMgaXMgZW5jb2RlZCBmb3JtIGJvZHkgY29udGVudCAoZ2gtMjY1OClcblx0XHR9IGVsc2UgaWYgKCBzLmRhdGEgJiYgcy5wcm9jZXNzRGF0YSAmJlxuXHRcdFx0KCBzLmNvbnRlbnRUeXBlIHx8IFwiXCIgKS5pbmRleE9mKCBcImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZFwiICkgPT09IDAgKSB7XG5cdFx0XHRzLmRhdGEgPSBzLmRhdGEucmVwbGFjZSggcjIwLCBcIitcIiApO1xuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0aWYgKCBzLmlmTW9kaWZpZWQgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTW9kaWZpZWQtU2luY2VcIiwgalF1ZXJ5Lmxhc3RNb2RpZmllZFsgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApIHtcblx0XHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJJZi1Ob25lLU1hdGNoXCIsIGpRdWVyeS5ldGFnWyBjYWNoZVVSTCBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IHRoZSBjb3JyZWN0IGhlYWRlciwgaWYgZGF0YSBpcyBiZWluZyBzZW50XG5cdFx0aWYgKCBzLmRhdGEgJiYgcy5oYXNDb250ZW50ICYmIHMuY29udGVudFR5cGUgIT09IGZhbHNlIHx8IG9wdGlvbnMuY29udGVudFR5cGUgKSB7XG5cdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIkNvbnRlbnQtVHlwZVwiLCBzLmNvbnRlbnRUeXBlICk7XG5cdFx0fVxuXG5cdFx0Ly8gU2V0IHRoZSBBY2NlcHRzIGhlYWRlciBmb3IgdGhlIHNlcnZlciwgZGVwZW5kaW5nIG9uIHRoZSBkYXRhVHlwZVxuXHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoXG5cdFx0XHRcIkFjY2VwdFwiLFxuXHRcdFx0cy5kYXRhVHlwZXNbIDAgXSAmJiBzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWyAwIF0gXSA/XG5cdFx0XHRcdHMuYWNjZXB0c1sgcy5kYXRhVHlwZXNbIDAgXSBdICtcblx0XHRcdFx0XHQoIHMuZGF0YVR5cGVzWyAwIF0gIT09IFwiKlwiID8gXCIsIFwiICsgYWxsVHlwZXMgKyBcIjsgcT0wLjAxXCIgOiBcIlwiICkgOlxuXHRcdFx0XHRzLmFjY2VwdHNbIFwiKlwiIF1cblx0XHQpO1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIGhlYWRlcnMgb3B0aW9uXG5cdFx0Zm9yICggaSBpbiBzLmhlYWRlcnMgKSB7XG5cdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBpLCBzLmhlYWRlcnNbIGkgXSApO1xuXHRcdH1cblxuXHRcdC8vIEFsbG93IGN1c3RvbSBoZWFkZXJzL21pbWV0eXBlcyBhbmQgZWFybHkgYWJvcnRcblx0XHRpZiAoIHMuYmVmb3JlU2VuZCAmJlxuXHRcdFx0KCBzLmJlZm9yZVNlbmQuY2FsbCggY2FsbGJhY2tDb250ZXh0LCBqcVhIUiwgcyApID09PSBmYWxzZSB8fCBjb21wbGV0ZWQgKSApIHtcblxuXHRcdFx0Ly8gQWJvcnQgaWYgbm90IGRvbmUgYWxyZWFkeSBhbmQgcmV0dXJuXG5cdFx0XHRyZXR1cm4ganFYSFIuYWJvcnQoKTtcblx0XHR9XG5cblx0XHQvLyBBYm9ydGluZyBpcyBubyBsb25nZXIgYSBjYW5jZWxsYXRpb25cblx0XHRzdHJBYm9ydCA9IFwiYWJvcnRcIjtcblxuXHRcdC8vIEluc3RhbGwgY2FsbGJhY2tzIG9uIGRlZmVycmVkc1xuXHRcdGNvbXBsZXRlRGVmZXJyZWQuYWRkKCBzLmNvbXBsZXRlICk7XG5cdFx0anFYSFIuZG9uZSggcy5zdWNjZXNzICk7XG5cdFx0anFYSFIuZmFpbCggcy5lcnJvciApO1xuXG5cdFx0Ly8gR2V0IHRyYW5zcG9ydFxuXHRcdHRyYW5zcG9ydCA9IGluc3BlY3RQcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCB0cmFuc3BvcnRzLCBzLCBvcHRpb25zLCBqcVhIUiApO1xuXG5cdFx0Ly8gSWYgbm8gdHJhbnNwb3J0LCB3ZSBhdXRvLWFib3J0XG5cdFx0aWYgKCAhdHJhbnNwb3J0ICkge1xuXHRcdFx0ZG9uZSggLTEsIFwiTm8gVHJhbnNwb3J0XCIgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0anFYSFIucmVhZHlTdGF0ZSA9IDE7XG5cblx0XHRcdC8vIFNlbmQgZ2xvYmFsIGV2ZW50XG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggXCJhamF4U2VuZFwiLCBbIGpxWEhSLCBzIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgcmVxdWVzdCB3YXMgYWJvcnRlZCBpbnNpZGUgYWpheFNlbmQsIHN0b3AgdGhlcmVcblx0XHRcdGlmICggY29tcGxldGVkICkge1xuXHRcdFx0XHRyZXR1cm4ganFYSFI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRpbWVvdXRcblx0XHRcdGlmICggcy5hc3luYyAmJiBzLnRpbWVvdXQgPiAwICkge1xuXHRcdFx0XHR0aW1lb3V0VGltZXIgPSB3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0anFYSFIuYWJvcnQoIFwidGltZW91dFwiICk7XG5cdFx0XHRcdH0sIHMudGltZW91dCApO1xuXHRcdFx0fVxuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb21wbGV0ZWQgPSBmYWxzZTtcblx0XHRcdFx0dHJhbnNwb3J0LnNlbmQoIHJlcXVlc3RIZWFkZXJzLCBkb25lICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHQvLyBSZXRocm93IHBvc3QtY29tcGxldGlvbiBleGNlcHRpb25zXG5cdFx0XHRcdGlmICggY29tcGxldGVkICkge1xuXHRcdFx0XHRcdHRocm93IGU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBQcm9wYWdhdGUgb3RoZXJzIGFzIHJlc3VsdHNcblx0XHRcdFx0ZG9uZSggLTEsIGUgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDYWxsYmFjayBmb3Igd2hlbiBldmVyeXRoaW5nIGlzIGRvbmVcblx0XHRmdW5jdGlvbiBkb25lKCBzdGF0dXMsIG5hdGl2ZVN0YXR1c1RleHQsIHJlc3BvbnNlcywgaGVhZGVycyApIHtcblx0XHRcdHZhciBpc1N1Y2Nlc3MsIHN1Y2Nlc3MsIGVycm9yLCByZXNwb25zZSwgbW9kaWZpZWQsXG5cdFx0XHRcdHN0YXR1c1RleHQgPSBuYXRpdmVTdGF0dXNUZXh0O1xuXG5cdFx0XHQvLyBJZ25vcmUgcmVwZWF0IGludm9jYXRpb25zXG5cdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRjb21wbGV0ZWQgPSB0cnVlO1xuXG5cdFx0XHQvLyBDbGVhciB0aW1lb3V0IGlmIGl0IGV4aXN0c1xuXHRcdFx0aWYgKCB0aW1lb3V0VGltZXIgKSB7XG5cdFx0XHRcdHdpbmRvdy5jbGVhclRpbWVvdXQoIHRpbWVvdXRUaW1lciApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBEZXJlZmVyZW5jZSB0cmFuc3BvcnQgZm9yIGVhcmx5IGdhcmJhZ2UgY29sbGVjdGlvblxuXHRcdFx0Ly8gKG5vIG1hdHRlciBob3cgbG9uZyB0aGUganFYSFIgb2JqZWN0IHdpbGwgYmUgdXNlZClcblx0XHRcdHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0Ly8gQ2FjaGUgcmVzcG9uc2UgaGVhZGVyc1xuXHRcdFx0cmVzcG9uc2VIZWFkZXJzU3RyaW5nID0gaGVhZGVycyB8fCBcIlwiO1xuXG5cdFx0XHQvLyBTZXQgcmVhZHlTdGF0ZVxuXHRcdFx0anFYSFIucmVhZHlTdGF0ZSA9IHN0YXR1cyA+IDAgPyA0IDogMDtcblxuXHRcdFx0Ly8gRGV0ZXJtaW5lIGlmIHN1Y2Nlc3NmdWxcblx0XHRcdGlzU3VjY2VzcyA9IHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwIHx8IHN0YXR1cyA9PT0gMzA0O1xuXG5cdFx0XHQvLyBHZXQgcmVzcG9uc2UgZGF0YVxuXHRcdFx0aWYgKCByZXNwb25zZXMgKSB7XG5cdFx0XHRcdHJlc3BvbnNlID0gYWpheEhhbmRsZVJlc3BvbnNlcyggcywganFYSFIsIHJlc3BvbnNlcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb252ZXJ0IG5vIG1hdHRlciB3aGF0ICh0aGF0IHdheSByZXNwb25zZVhYWCBmaWVsZHMgYXJlIGFsd2F5cyBzZXQpXG5cdFx0XHRyZXNwb25zZSA9IGFqYXhDb252ZXJ0KCBzLCByZXNwb25zZSwganFYSFIsIGlzU3VjY2VzcyApO1xuXG5cdFx0XHQvLyBJZiBzdWNjZXNzZnVsLCBoYW5kbGUgdHlwZSBjaGFpbmluZ1xuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cblx0XHRcdFx0Ly8gU2V0IHRoZSBJZi1Nb2RpZmllZC1TaW5jZSBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIsIGlmIGluIGlmTW9kaWZpZWQgbW9kZS5cblx0XHRcdFx0aWYgKCBzLmlmTW9kaWZpZWQgKSB7XG5cdFx0XHRcdFx0bW9kaWZpZWQgPSBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJMYXN0LU1vZGlmaWVkXCIgKTtcblx0XHRcdFx0XHRpZiAoIG1vZGlmaWVkICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5Lmxhc3RNb2RpZmllZFsgY2FjaGVVUkwgXSA9IG1vZGlmaWVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRtb2RpZmllZCA9IGpxWEhSLmdldFJlc3BvbnNlSGVhZGVyKCBcImV0YWdcIiApO1xuXHRcdFx0XHRcdGlmICggbW9kaWZpZWQgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSA9IG1vZGlmaWVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlmIG5vIGNvbnRlbnRcblx0XHRcdFx0aWYgKCBzdGF0dXMgPT09IDIwNCB8fCBzLnR5cGUgPT09IFwiSEVBRFwiICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcIm5vY29udGVudFwiO1xuXG5cdFx0XHRcdC8vIGlmIG5vdCBtb2RpZmllZFxuXHRcdFx0XHR9IGVsc2UgaWYgKCBzdGF0dXMgPT09IDMwNCApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub3Rtb2RpZmllZFwiO1xuXG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgZGF0YSwgbGV0J3MgY29udmVydCBpdFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSByZXNwb25zZS5zdGF0ZTtcblx0XHRcdFx0XHRzdWNjZXNzID0gcmVzcG9uc2UuZGF0YTtcblx0XHRcdFx0XHRlcnJvciA9IHJlc3BvbnNlLmVycm9yO1xuXHRcdFx0XHRcdGlzU3VjY2VzcyA9ICFlcnJvcjtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHQvLyBFeHRyYWN0IGVycm9yIGZyb20gc3RhdHVzVGV4dCBhbmQgbm9ybWFsaXplIGZvciBub24tYWJvcnRzXG5cdFx0XHRcdGVycm9yID0gc3RhdHVzVGV4dDtcblx0XHRcdFx0aWYgKCBzdGF0dXMgfHwgIXN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0c3RhdHVzVGV4dCA9IFwiZXJyb3JcIjtcblx0XHRcdFx0XHRpZiAoIHN0YXR1cyA8IDAgKSB7XG5cdFx0XHRcdFx0XHRzdGF0dXMgPSAwO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTZXQgZGF0YSBmb3IgdGhlIGZha2UgeGhyIG9iamVjdFxuXHRcdFx0anFYSFIuc3RhdHVzID0gc3RhdHVzO1xuXHRcdFx0anFYSFIuc3RhdHVzVGV4dCA9ICggbmF0aXZlU3RhdHVzVGV4dCB8fCBzdGF0dXNUZXh0ICkgKyBcIlwiO1xuXG5cdFx0XHQvLyBTdWNjZXNzL0Vycm9yXG5cdFx0XHRpZiAoIGlzU3VjY2VzcyApIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVzb2x2ZVdpdGgoIGNhbGxiYWNrQ29udGV4dCwgWyBzdWNjZXNzLCBzdGF0dXNUZXh0LCBqcVhIUiBdICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsganFYSFIsIHN0YXR1c1RleHQsIGVycm9yIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RhdHVzLWRlcGVuZGVudCBjYWxsYmFja3Ncblx0XHRcdGpxWEhSLnN0YXR1c0NvZGUoIHN0YXR1c0NvZGUgKTtcblx0XHRcdHN0YXR1c0NvZGUgPSB1bmRlZmluZWQ7XG5cblx0XHRcdGlmICggZmlyZUdsb2JhbHMgKSB7XG5cdFx0XHRcdGdsb2JhbEV2ZW50Q29udGV4dC50cmlnZ2VyKCBpc1N1Y2Nlc3MgPyBcImFqYXhTdWNjZXNzXCIgOiBcImFqYXhFcnJvclwiLFxuXHRcdFx0XHRcdFsganFYSFIsIHMsIGlzU3VjY2VzcyA/IHN1Y2Nlc3MgOiBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENvbXBsZXRlXG5cdFx0XHRjb21wbGV0ZURlZmVycmVkLmZpcmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsganFYSFIsIHN0YXR1c1RleHQgXSApO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggXCJhamF4Q29tcGxldGVcIiwgWyBqcVhIUiwgcyBdICk7XG5cblx0XHRcdFx0Ly8gSGFuZGxlIHRoZSBnbG9iYWwgQUpBWCBjb3VudGVyXG5cdFx0XHRcdGlmICggISggLS1qUXVlcnkuYWN0aXZlICkgKSB7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIFwiYWpheFN0b3BcIiApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGpxWEhSO1xuXHR9LFxuXG5cdGdldEpTT046IGZ1bmN0aW9uKCB1cmwsIGRhdGEsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIGRhdGEsIGNhbGxiYWNrLCBcImpzb25cIiApO1xuXHR9LFxuXG5cdGdldFNjcmlwdDogZnVuY3Rpb24oIHVybCwgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5nZXQoIHVybCwgdW5kZWZpbmVkLCBjYWxsYmFjaywgXCJzY3JpcHRcIiApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCBbIFwiZ2V0XCIsIFwicG9zdFwiIF0sIGZ1bmN0aW9uKCBpLCBtZXRob2QgKSB7XG5cdGpRdWVyeVsgbWV0aG9kIF0gPSBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjaywgdHlwZSApIHtcblxuXHRcdC8vIFNoaWZ0IGFyZ3VtZW50cyBpZiBkYXRhIGFyZ3VtZW50IHdhcyBvbWl0dGVkXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggZGF0YSApICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgY2FsbGJhY2s7XG5cdFx0XHRjYWxsYmFjayA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIFRoZSB1cmwgY2FuIGJlIGFuIG9wdGlvbnMgb2JqZWN0ICh3aGljaCB0aGVuIG11c3QgaGF2ZSAudXJsKVxuXHRcdHJldHVybiBqUXVlcnkuYWpheCggalF1ZXJ5LmV4dGVuZCgge1xuXHRcdFx0dXJsOiB1cmwsXG5cdFx0XHR0eXBlOiBtZXRob2QsXG5cdFx0XHRkYXRhVHlwZTogdHlwZSxcblx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRzdWNjZXNzOiBjYWxsYmFja1xuXHRcdH0sIGpRdWVyeS5pc1BsYWluT2JqZWN0KCB1cmwgKSAmJiB1cmwgKSApO1xuXHR9O1xufSApO1xuXG5cbmpRdWVyeS5fZXZhbFVybCA9IGZ1bmN0aW9uKCB1cmwgKSB7XG5cdHJldHVybiBqUXVlcnkuYWpheCgge1xuXHRcdHVybDogdXJsLFxuXG5cdFx0Ly8gTWFrZSB0aGlzIGV4cGxpY2l0LCBzaW5jZSB1c2VyIGNhbiBvdmVycmlkZSB0aGlzIHRocm91Z2ggYWpheFNldHVwICgjMTEyNjQpXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRkYXRhVHlwZTogXCJzY3JpcHRcIixcblx0XHRjYWNoZTogdHJ1ZSxcblx0XHRhc3luYzogZmFsc2UsXG5cdFx0Z2xvYmFsOiBmYWxzZSxcblx0XHRcInRocm93c1wiOiB0cnVlXG5cdH0gKTtcbn07XG5cblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHR3cmFwQWxsOiBmdW5jdGlvbiggaHRtbCApIHtcblx0XHR2YXIgd3JhcDtcblxuXHRcdGlmICggdGhpc1sgMCBdICkge1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApICkge1xuXHRcdFx0XHRodG1sID0gaHRtbC5jYWxsKCB0aGlzWyAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVGhlIGVsZW1lbnRzIHRvIHdyYXAgdGhlIHRhcmdldCBhcm91bmRcblx0XHRcdHdyYXAgPSBqUXVlcnkoIGh0bWwsIHRoaXNbIDAgXS5vd25lckRvY3VtZW50ICkuZXEoIDAgKS5jbG9uZSggdHJ1ZSApO1xuXG5cdFx0XHRpZiAoIHRoaXNbIDAgXS5wYXJlbnROb2RlICkge1xuXHRcdFx0XHR3cmFwLmluc2VydEJlZm9yZSggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHdyYXAubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGVsZW0gPSB0aGlzO1xuXG5cdFx0XHRcdHdoaWxlICggZWxlbS5maXJzdEVsZW1lbnRDaGlsZCApIHtcblx0XHRcdFx0XHRlbGVtID0gZWxlbS5maXJzdEVsZW1lbnRDaGlsZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiBlbGVtO1xuXHRcdFx0fSApLmFwcGVuZCggdGhpcyApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdHdyYXBJbm5lcjogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLndyYXBJbm5lciggaHRtbC5jYWxsKCB0aGlzLCBpICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBzZWxmID0galF1ZXJ5KCB0aGlzICksXG5cdFx0XHRcdGNvbnRlbnRzID0gc2VsZi5jb250ZW50cygpO1xuXG5cdFx0XHRpZiAoIGNvbnRlbnRzLmxlbmd0aCApIHtcblx0XHRcdFx0Y29udGVudHMud3JhcEFsbCggaHRtbCApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWxmLmFwcGVuZCggaHRtbCApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHR3cmFwOiBmdW5jdGlvbiggaHRtbCApIHtcblx0XHR2YXIgaXNGdW5jdGlvbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCBodG1sICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLndyYXBBbGwoIGlzRnVuY3Rpb24gPyBodG1sLmNhbGwoIHRoaXMsIGkgKSA6IGh0bWwgKTtcblx0XHR9ICk7XG5cdH0sXG5cblx0dW53cmFwOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dGhpcy5wYXJlbnQoIHNlbGVjdG9yICkubm90KCBcImJvZHlcIiApLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5KCB0aGlzICkucmVwbGFjZVdpdGgoIHRoaXMuY2hpbGROb2RlcyApO1xuXHRcdH0gKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxufSApO1xuXG5cbmpRdWVyeS5leHByLnBzZXVkb3MuaGlkZGVuID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiAhalF1ZXJ5LmV4cHIucHNldWRvcy52aXNpYmxlKCBlbGVtICk7XG59O1xualF1ZXJ5LmV4cHIucHNldWRvcy52aXNpYmxlID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiAhISggZWxlbS5vZmZzZXRXaWR0aCB8fCBlbGVtLm9mZnNldEhlaWdodCB8fCBlbGVtLmdldENsaWVudFJlY3RzKCkubGVuZ3RoICk7XG59O1xuXG5cblxuXG5qUXVlcnkuYWpheFNldHRpbmdzLnhociA9IGZ1bmN0aW9uKCkge1xuXHR0cnkge1xuXHRcdHJldHVybiBuZXcgd2luZG93LlhNTEh0dHBSZXF1ZXN0KCk7XG5cdH0gY2F0Y2ggKCBlICkge31cbn07XG5cbnZhciB4aHJTdWNjZXNzU3RhdHVzID0ge1xuXG5cdFx0Ly8gRmlsZSBwcm90b2NvbCBhbHdheXMgeWllbGRzIHN0YXR1cyBjb2RlIDAsIGFzc3VtZSAyMDBcblx0XHQwOiAyMDAsXG5cblx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuXHRcdC8vICMxNDUwOiBzb21ldGltZXMgSUUgcmV0dXJucyAxMjIzIHdoZW4gaXQgc2hvdWxkIGJlIDIwNFxuXHRcdDEyMjM6IDIwNFxuXHR9LFxuXHR4aHJTdXBwb3J0ZWQgPSBqUXVlcnkuYWpheFNldHRpbmdzLnhocigpO1xuXG5zdXBwb3J0LmNvcnMgPSAhIXhoclN1cHBvcnRlZCAmJiAoIFwid2l0aENyZWRlbnRpYWxzXCIgaW4geGhyU3VwcG9ydGVkICk7XG5zdXBwb3J0LmFqYXggPSB4aHJTdXBwb3J0ZWQgPSAhIXhoclN1cHBvcnRlZDtcblxualF1ZXJ5LmFqYXhUcmFuc3BvcnQoIGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHR2YXIgY2FsbGJhY2ssIGVycm9yQ2FsbGJhY2s7XG5cblx0Ly8gQ3Jvc3MgZG9tYWluIG9ubHkgYWxsb3dlZCBpZiBzdXBwb3J0ZWQgdGhyb3VnaCBYTUxIdHRwUmVxdWVzdFxuXHRpZiAoIHN1cHBvcnQuY29ycyB8fCB4aHJTdXBwb3J0ZWQgJiYgIW9wdGlvbnMuY3Jvc3NEb21haW4gKSB7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBoZWFkZXJzLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0dmFyIGksXG5cdFx0XHRcdFx0eGhyID0gb3B0aW9ucy54aHIoKTtcblxuXHRcdFx0XHR4aHIub3Blbihcblx0XHRcdFx0XHRvcHRpb25zLnR5cGUsXG5cdFx0XHRcdFx0b3B0aW9ucy51cmwsXG5cdFx0XHRcdFx0b3B0aW9ucy5hc3luYyxcblx0XHRcdFx0XHRvcHRpb25zLnVzZXJuYW1lLFxuXHRcdFx0XHRcdG9wdGlvbnMucGFzc3dvcmRcblx0XHRcdFx0KTtcblxuXHRcdFx0XHQvLyBBcHBseSBjdXN0b20gZmllbGRzIGlmIHByb3ZpZGVkXG5cdFx0XHRcdGlmICggb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0Zm9yICggaSBpbiBvcHRpb25zLnhockZpZWxkcyApIHtcblx0XHRcdFx0XHRcdHhoclsgaSBdID0gb3B0aW9ucy54aHJGaWVsZHNbIGkgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBPdmVycmlkZSBtaW1lIHR5cGUgaWYgbmVlZGVkXG5cdFx0XHRcdGlmICggb3B0aW9ucy5taW1lVHlwZSAmJiB4aHIub3ZlcnJpZGVNaW1lVHlwZSApIHtcblx0XHRcdFx0XHR4aHIub3ZlcnJpZGVNaW1lVHlwZSggb3B0aW9ucy5taW1lVHlwZSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gWC1SZXF1ZXN0ZWQtV2l0aCBoZWFkZXJcblx0XHRcdFx0Ly8gRm9yIGNyb3NzLWRvbWFpbiByZXF1ZXN0cywgc2VlaW5nIGFzIGNvbmRpdGlvbnMgZm9yIGEgcHJlZmxpZ2h0IGFyZVxuXHRcdFx0XHQvLyBha2luIHRvIGEgamlnc2F3IHB1enpsZSwgd2Ugc2ltcGx5IG5ldmVyIHNldCBpdCB0byBiZSBzdXJlLlxuXHRcdFx0XHQvLyAoaXQgY2FuIGFsd2F5cyBiZSBzZXQgb24gYSBwZXItcmVxdWVzdCBiYXNpcyBvciBldmVuIHVzaW5nIGFqYXhTZXR1cClcblx0XHRcdFx0Ly8gRm9yIHNhbWUtZG9tYWluIHJlcXVlc3RzLCB3b24ndCBjaGFuZ2UgaGVhZGVyIGlmIGFscmVhZHkgcHJvdmlkZWQuXG5cdFx0XHRcdGlmICggIW9wdGlvbnMuY3Jvc3NEb21haW4gJiYgIWhlYWRlcnNbIFwiWC1SZXF1ZXN0ZWQtV2l0aFwiIF0gKSB7XG5cdFx0XHRcdFx0aGVhZGVyc1sgXCJYLVJlcXVlc3RlZC1XaXRoXCIgXSA9IFwiWE1MSHR0cFJlcXVlc3RcIjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFNldCBoZWFkZXJzXG5cdFx0XHRcdGZvciAoIGkgaW4gaGVhZGVycyApIHtcblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlciggaSwgaGVhZGVyc1sgaSBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDYWxsYmFja1xuXHRcdFx0XHRjYWxsYmFjayA9IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0XHRcdGNhbGxiYWNrID0gZXJyb3JDYWxsYmFjayA9IHhoci5vbmxvYWQgPVxuXHRcdFx0XHRcdFx0XHRcdHhoci5vbmVycm9yID0geGhyLm9uYWJvcnQgPSB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcblxuXHRcdFx0XHRcdFx0XHRpZiAoIHR5cGUgPT09IFwiYWJvcnRcIiApIHtcblx0XHRcdFx0XHRcdFx0XHR4aHIuYWJvcnQoKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggdHlwZSA9PT0gXCJlcnJvclwiICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHRcdFx0XHRcdFx0XHQvLyBPbiBhIG1hbnVhbCBuYXRpdmUgYWJvcnQsIElFOSB0aHJvd3Ncblx0XHRcdFx0XHRcdFx0XHQvLyBlcnJvcnMgb24gYW55IHByb3BlcnR5IGFjY2VzcyB0aGF0IGlzIG5vdCByZWFkeVN0YXRlXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlb2YgeGhyLnN0YXR1cyAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKCAwLCBcImVycm9yXCIgKTtcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29tcGxldGUoXG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRmlsZTogcHJvdG9jb2wgYWx3YXlzIHlpZWxkcyBzdGF0dXMgMDsgc2VlICM4NjA1LCAjMTQyMDdcblx0XHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1cyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHRcblx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyU3VjY2Vzc1N0YXR1c1sgeGhyLnN0YXR1cyBdIHx8IHhoci5zdGF0dXMsXG5cdFx0XHRcdFx0XHRcdFx0XHR4aHIuc3RhdHVzVGV4dCxcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIElFOSBoYXMgbm8gWEhSMiBidXQgdGhyb3dzIG9uIGJpbmFyeSAodHJhYy0xMTQyNilcblx0XHRcdFx0XHRcdFx0XHRcdC8vIEZvciBYSFIyIG5vbi10ZXh0LCBsZXQgdGhlIGNhbGxlciBoYW5kbGUgaXQgKGdoLTI0OTgpXG5cdFx0XHRcdFx0XHRcdFx0XHQoIHhoci5yZXNwb25zZVR5cGUgfHwgXCJ0ZXh0XCIgKSAhPT0gXCJ0ZXh0XCIgIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHR0eXBlb2YgeGhyLnJlc3BvbnNlVGV4dCAhPT0gXCJzdHJpbmdcIiA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHsgYmluYXJ5OiB4aHIucmVzcG9uc2UgfSA6XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHsgdGV4dDogeGhyLnJlc3BvbnNlVGV4dCB9LFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycygpXG5cdFx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH07XG5cblx0XHRcdFx0Ly8gTGlzdGVuIHRvIGV2ZW50c1xuXHRcdFx0XHR4aHIub25sb2FkID0gY2FsbGJhY2soKTtcblx0XHRcdFx0ZXJyb3JDYWxsYmFjayA9IHhoci5vbmVycm9yID0gY2FsbGJhY2soIFwiZXJyb3JcIiApO1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDkgb25seVxuXHRcdFx0XHQvLyBVc2Ugb25yZWFkeXN0YXRlY2hhbmdlIHRvIHJlcGxhY2Ugb25hYm9ydFxuXHRcdFx0XHQvLyB0byBoYW5kbGUgdW5jYXVnaHQgYWJvcnRzXG5cdFx0XHRcdGlmICggeGhyLm9uYWJvcnQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHR4aHIub25hYm9ydCA9IGVycm9yQ2FsbGJhY2s7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0eGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0XHQvLyBDaGVjayByZWFkeVN0YXRlIGJlZm9yZSB0aW1lb3V0IGFzIGl0IGNoYW5nZXNcblx0XHRcdFx0XHRcdGlmICggeGhyLnJlYWR5U3RhdGUgPT09IDQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQWxsb3cgb25lcnJvciB0byBiZSBjYWxsZWQgZmlyc3QsXG5cdFx0XHRcdFx0XHRcdC8vIGJ1dCB0aGF0IHdpbGwgbm90IGhhbmRsZSBhIG5hdGl2ZSBhYm9ydFxuXHRcdFx0XHRcdFx0XHQvLyBBbHNvLCBzYXZlIGVycm9yQ2FsbGJhY2sgdG8gYSB2YXJpYWJsZVxuXHRcdFx0XHRcdFx0XHQvLyBhcyB4aHIub25lcnJvciBjYW5ub3QgYmUgYWNjZXNzZWRcblx0XHRcdFx0XHRcdFx0d2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRlcnJvckNhbGxiYWNrKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIENyZWF0ZSB0aGUgYWJvcnQgY2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSBjYWxsYmFjayggXCJhYm9ydFwiICk7XG5cblx0XHRcdFx0dHJ5IHtcblxuXHRcdFx0XHRcdC8vIERvIHNlbmQgdGhlIHJlcXVlc3QgKHRoaXMgbWF5IHJhaXNlIGFuIGV4Y2VwdGlvbilcblx0XHRcdFx0XHR4aHIuc2VuZCggb3B0aW9ucy5oYXNDb250ZW50ICYmIG9wdGlvbnMuZGF0YSB8fCBudWxsICk7XG5cdFx0XHRcdH0gY2F0Y2ggKCBlICkge1xuXG5cdFx0XHRcdFx0Ly8gIzE0NjgzOiBPbmx5IHJldGhyb3cgaWYgdGhpcyBoYXNuJ3QgYmVlbiBub3RpZmllZCBhcyBhbiBlcnJvciB5ZXRcblx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0dGhyb3cgZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cblx0XHRcdGFib3J0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRjYWxsYmFjaygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxufSApO1xuXG5cblxuXG4vLyBQcmV2ZW50IGF1dG8tZXhlY3V0aW9uIG9mIHNjcmlwdHMgd2hlbiBubyBleHBsaWNpdCBkYXRhVHlwZSB3YXMgcHJvdmlkZWQgKFNlZSBnaC0yNDMyKVxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0cy5jb250ZW50cy5zY3JpcHQgPSBmYWxzZTtcblx0fVxufSApO1xuXG4vLyBJbnN0YWxsIHNjcmlwdCBkYXRhVHlwZVxualF1ZXJ5LmFqYXhTZXR1cCgge1xuXHRhY2NlcHRzOiB7XG5cdFx0c2NyaXB0OiBcInRleHQvamF2YXNjcmlwdCwgYXBwbGljYXRpb24vamF2YXNjcmlwdCwgXCIgK1xuXHRcdFx0XCJhcHBsaWNhdGlvbi9lY21hc2NyaXB0LCBhcHBsaWNhdGlvbi94LWVjbWFzY3JpcHRcIlxuXHR9LFxuXHRjb250ZW50czoge1xuXHRcdHNjcmlwdDogL1xcYig/OmphdmF8ZWNtYSlzY3JpcHRcXGIvXG5cdH0sXG5cdGNvbnZlcnRlcnM6IHtcblx0XHRcInRleHQgc2NyaXB0XCI6IGZ1bmN0aW9uKCB0ZXh0ICkge1xuXHRcdFx0alF1ZXJ5Lmdsb2JhbEV2YWwoIHRleHQgKTtcblx0XHRcdHJldHVybiB0ZXh0O1xuXHRcdH1cblx0fVxufSApO1xuXG4vLyBIYW5kbGUgY2FjaGUncyBzcGVjaWFsIGNhc2UgYW5kIGNyb3NzRG9tYWluXG5qUXVlcnkuYWpheFByZWZpbHRlciggXCJzY3JpcHRcIiwgZnVuY3Rpb24oIHMgKSB7XG5cdGlmICggcy5jYWNoZSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdHMuY2FjaGUgPSBmYWxzZTtcblx0fVxuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0cy50eXBlID0gXCJHRVRcIjtcblx0fVxufSApO1xuXG4vLyBCaW5kIHNjcmlwdCB0YWcgaGFjayB0cmFuc3BvcnRcbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBcInNjcmlwdFwiLCBmdW5jdGlvbiggcyApIHtcblxuXHQvLyBUaGlzIHRyYW5zcG9ydCBvbmx5IGRlYWxzIHdpdGggY3Jvc3MgZG9tYWluIHJlcXVlc3RzXG5cdGlmICggcy5jcm9zc0RvbWFpbiApIHtcblx0XHR2YXIgc2NyaXB0LCBjYWxsYmFjaztcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VuZDogZnVuY3Rpb24oIF8sIGNvbXBsZXRlICkge1xuXHRcdFx0XHRzY3JpcHQgPSBqUXVlcnkoIFwiPHNjcmlwdD5cIiApLnByb3AoIHtcblx0XHRcdFx0XHRjaGFyc2V0OiBzLnNjcmlwdENoYXJzZXQsXG5cdFx0XHRcdFx0c3JjOiBzLnVybFxuXHRcdFx0XHR9ICkub24oXG5cdFx0XHRcdFx0XCJsb2FkIGVycm9yXCIsXG5cdFx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggZXZ0ICkge1xuXHRcdFx0XHRcdFx0c2NyaXB0LnJlbW92ZSgpO1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2sgPSBudWxsO1xuXHRcdFx0XHRcdFx0aWYgKCBldnQgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbXBsZXRlKCBldnQudHlwZSA9PT0gXCJlcnJvclwiID8gNDA0IDogMjAwLCBldnQudHlwZSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0KTtcblxuXHRcdFx0XHQvLyBVc2UgbmF0aXZlIERPTSBtYW5pcHVsYXRpb24gdG8gYXZvaWQgb3VyIGRvbU1hbmlwIEFKQVggdHJpY2tlcnlcblx0XHRcdFx0ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZCggc2NyaXB0WyAwIF0gKTtcblx0XHRcdH0sXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0gKTtcblxuXG5cblxudmFyIG9sZENhbGxiYWNrcyA9IFtdLFxuXHRyanNvbnAgPSAvKD0pXFw/KD89JnwkKXxcXD9cXD8vO1xuXG4vLyBEZWZhdWx0IGpzb25wIHNldHRpbmdzXG5qUXVlcnkuYWpheFNldHVwKCB7XG5cdGpzb25wOiBcImNhbGxiYWNrXCIsXG5cdGpzb25wQ2FsbGJhY2s6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBjYWxsYmFjayA9IG9sZENhbGxiYWNrcy5wb3AoKSB8fCAoIGpRdWVyeS5leHBhbmRvICsgXCJfXCIgKyAoIG5vbmNlKysgKSApO1xuXHRcdHRoaXNbIGNhbGxiYWNrIF0gPSB0cnVlO1xuXHRcdHJldHVybiBjYWxsYmFjaztcblx0fVxufSApO1xuXG4vLyBEZXRlY3QsIG5vcm1hbGl6ZSBvcHRpb25zIGFuZCBpbnN0YWxsIGNhbGxiYWNrcyBmb3IganNvbnAgcmVxdWVzdHNcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBcImpzb24ganNvbnBcIiwgZnVuY3Rpb24oIHMsIG9yaWdpbmFsU2V0dGluZ3MsIGpxWEhSICkge1xuXG5cdHZhciBjYWxsYmFja05hbWUsIG92ZXJ3cml0dGVuLCByZXNwb25zZUNvbnRhaW5lcixcblx0XHRqc29uUHJvcCA9IHMuanNvbnAgIT09IGZhbHNlICYmICggcmpzb25wLnRlc3QoIHMudXJsICkgP1xuXHRcdFx0XCJ1cmxcIiA6XG5cdFx0XHR0eXBlb2Ygcy5kYXRhID09PSBcInN0cmluZ1wiICYmXG5cdFx0XHRcdCggcy5jb250ZW50VHlwZSB8fCBcIlwiIClcblx0XHRcdFx0XHQuaW5kZXhPZiggXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiApID09PSAwICYmXG5cdFx0XHRcdHJqc29ucC50ZXN0KCBzLmRhdGEgKSAmJiBcImRhdGFcIlxuXHRcdCk7XG5cblx0Ly8gSGFuZGxlIGlmZiB0aGUgZXhwZWN0ZWQgZGF0YSB0eXBlIGlzIFwianNvbnBcIiBvciB3ZSBoYXZlIGEgcGFyYW1ldGVyIHRvIHNldFxuXHRpZiAoIGpzb25Qcm9wIHx8IHMuZGF0YVR5cGVzWyAwIF0gPT09IFwianNvbnBcIiApIHtcblxuXHRcdC8vIEdldCBjYWxsYmFjayBuYW1lLCByZW1lbWJlcmluZyBwcmVleGlzdGluZyB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggaXRcblx0XHRjYWxsYmFja05hbWUgPSBzLmpzb25wQ2FsbGJhY2sgPSBqUXVlcnkuaXNGdW5jdGlvbiggcy5qc29ucENhbGxiYWNrICkgP1xuXHRcdFx0cy5qc29ucENhbGxiYWNrKCkgOlxuXHRcdFx0cy5qc29ucENhbGxiYWNrO1xuXG5cdFx0Ly8gSW5zZXJ0IGNhbGxiYWNrIGludG8gdXJsIG9yIGZvcm0gZGF0YVxuXHRcdGlmICgganNvblByb3AgKSB7XG5cdFx0XHRzWyBqc29uUHJvcCBdID0gc1sganNvblByb3AgXS5yZXBsYWNlKCByanNvbnAsIFwiJDFcIiArIGNhbGxiYWNrTmFtZSApO1xuXHRcdH0gZWxzZSBpZiAoIHMuanNvbnAgIT09IGZhbHNlICkge1xuXHRcdFx0cy51cmwgKz0gKCBycXVlcnkudGVzdCggcy51cmwgKSA/IFwiJlwiIDogXCI/XCIgKSArIHMuanNvbnAgKyBcIj1cIiArIGNhbGxiYWNrTmFtZTtcblx0XHR9XG5cblx0XHQvLyBVc2UgZGF0YSBjb252ZXJ0ZXIgdG8gcmV0cmlldmUganNvbiBhZnRlciBzY3JpcHQgZXhlY3V0aW9uXG5cdFx0cy5jb252ZXJ0ZXJzWyBcInNjcmlwdCBqc29uXCIgXSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCAhcmVzcG9uc2VDb250YWluZXIgKSB7XG5cdFx0XHRcdGpRdWVyeS5lcnJvciggY2FsbGJhY2tOYW1lICsgXCIgd2FzIG5vdCBjYWxsZWRcIiApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3BvbnNlQ29udGFpbmVyWyAwIF07XG5cdFx0fTtcblxuXHRcdC8vIEZvcmNlIGpzb24gZGF0YVR5cGVcblx0XHRzLmRhdGFUeXBlc1sgMCBdID0gXCJqc29uXCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrXG5cdFx0b3ZlcndyaXR0ZW4gPSB3aW5kb3dbIGNhbGxiYWNrTmFtZSBdO1xuXHRcdHdpbmRvd1sgY2FsbGJhY2tOYW1lIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdHJlc3BvbnNlQ29udGFpbmVyID0gYXJndW1lbnRzO1xuXHRcdH07XG5cblx0XHQvLyBDbGVhbi11cCBmdW5jdGlvbiAoZmlyZXMgYWZ0ZXIgY29udmVydGVycylcblx0XHRqcVhIUi5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBJZiBwcmV2aW91cyB2YWx1ZSBkaWRuJ3QgZXhpc3QgLSByZW1vdmUgaXRcblx0XHRcdGlmICggb3ZlcndyaXR0ZW4gPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0alF1ZXJ5KCB3aW5kb3cgKS5yZW1vdmVQcm9wKCBjYWxsYmFja05hbWUgKTtcblxuXHRcdFx0Ly8gT3RoZXJ3aXNlIHJlc3RvcmUgcHJlZXhpc3RpbmcgdmFsdWVcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdpbmRvd1sgY2FsbGJhY2tOYW1lIF0gPSBvdmVyd3JpdHRlbjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2F2ZSBiYWNrIGFzIGZyZWVcblx0XHRcdGlmICggc1sgY2FsbGJhY2tOYW1lIF0gKSB7XG5cblx0XHRcdFx0Ly8gTWFrZSBzdXJlIHRoYXQgcmUtdXNpbmcgdGhlIG9wdGlvbnMgZG9lc24ndCBzY3JldyB0aGluZ3MgYXJvdW5kXG5cdFx0XHRcdHMuanNvbnBDYWxsYmFjayA9IG9yaWdpbmFsU2V0dGluZ3MuanNvbnBDYWxsYmFjaztcblxuXHRcdFx0XHQvLyBTYXZlIHRoZSBjYWxsYmFjayBuYW1lIGZvciBmdXR1cmUgdXNlXG5cdFx0XHRcdG9sZENhbGxiYWNrcy5wdXNoKCBjYWxsYmFja05hbWUgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2FsbCBpZiBpdCB3YXMgYSBmdW5jdGlvbiBhbmQgd2UgaGF2ZSBhIHJlc3BvbnNlXG5cdFx0XHRpZiAoIHJlc3BvbnNlQ29udGFpbmVyICYmIGpRdWVyeS5pc0Z1bmN0aW9uKCBvdmVyd3JpdHRlbiApICkge1xuXHRcdFx0XHRvdmVyd3JpdHRlbiggcmVzcG9uc2VDb250YWluZXJbIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXNwb25zZUNvbnRhaW5lciA9IG92ZXJ3cml0dGVuID0gdW5kZWZpbmVkO1xuXHRcdH0gKTtcblxuXHRcdC8vIERlbGVnYXRlIHRvIHNjcmlwdFxuXHRcdHJldHVybiBcInNjcmlwdFwiO1xuXHR9XG59ICk7XG5cblxuXG5cbi8vIFN1cHBvcnQ6IFNhZmFyaSA4IG9ubHlcbi8vIEluIFNhZmFyaSA4IGRvY3VtZW50cyBjcmVhdGVkIHZpYSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnRcbi8vIGNvbGxhcHNlIHNpYmxpbmcgZm9ybXM6IHRoZSBzZWNvbmQgb25lIGJlY29tZXMgYSBjaGlsZCBvZiB0aGUgZmlyc3Qgb25lLlxuLy8gQmVjYXVzZSBvZiB0aGF0LCB0aGlzIHNlY3VyaXR5IG1lYXN1cmUgaGFzIHRvIGJlIGRpc2FibGVkIGluIFNhZmFyaSA4LlxuLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEzNzMzN1xuc3VwcG9ydC5jcmVhdGVIVE1MRG9jdW1lbnQgPSAoIGZ1bmN0aW9uKCkge1xuXHR2YXIgYm9keSA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCggXCJcIiApLmJvZHk7XG5cdGJvZHkuaW5uZXJIVE1MID0gXCI8Zm9ybT48L2Zvcm0+PGZvcm0+PC9mb3JtPlwiO1xuXHRyZXR1cm4gYm9keS5jaGlsZE5vZGVzLmxlbmd0aCA9PT0gMjtcbn0gKSgpO1xuXG5cbi8vIEFyZ3VtZW50IFwiZGF0YVwiIHNob3VsZCBiZSBzdHJpbmcgb2YgaHRtbFxuLy8gY29udGV4dCAob3B0aW9uYWwpOiBJZiBzcGVjaWZpZWQsIHRoZSBmcmFnbWVudCB3aWxsIGJlIGNyZWF0ZWQgaW4gdGhpcyBjb250ZXh0LFxuLy8gZGVmYXVsdHMgdG8gZG9jdW1lbnRcbi8vIGtlZXBTY3JpcHRzIChvcHRpb25hbCk6IElmIHRydWUsIHdpbGwgaW5jbHVkZSBzY3JpcHRzIHBhc3NlZCBpbiB0aGUgaHRtbCBzdHJpbmdcbmpRdWVyeS5wYXJzZUhUTUwgPSBmdW5jdGlvbiggZGF0YSwgY29udGV4dCwga2VlcFNjcmlwdHMgKSB7XG5cdGlmICggdHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0cmV0dXJuIFtdO1xuXHR9XG5cdGlmICggdHlwZW9mIGNvbnRleHQgPT09IFwiYm9vbGVhblwiICkge1xuXHRcdGtlZXBTY3JpcHRzID0gY29udGV4dDtcblx0XHRjb250ZXh0ID0gZmFsc2U7XG5cdH1cblxuXHR2YXIgYmFzZSwgcGFyc2VkLCBzY3JpcHRzO1xuXG5cdGlmICggIWNvbnRleHQgKSB7XG5cblx0XHQvLyBTdG9wIHNjcmlwdHMgb3IgaW5saW5lIGV2ZW50IGhhbmRsZXJzIGZyb20gYmVpbmcgZXhlY3V0ZWQgaW1tZWRpYXRlbHlcblx0XHQvLyBieSB1c2luZyBkb2N1bWVudC5pbXBsZW1lbnRhdGlvblxuXHRcdGlmICggc3VwcG9ydC5jcmVhdGVIVE1MRG9jdW1lbnQgKSB7XG5cdFx0XHRjb250ZXh0ID0gZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50KCBcIlwiICk7XG5cblx0XHRcdC8vIFNldCB0aGUgYmFzZSBocmVmIGZvciB0aGUgY3JlYXRlZCBkb2N1bWVudFxuXHRcdFx0Ly8gc28gYW55IHBhcnNlZCBlbGVtZW50cyB3aXRoIFVSTHNcblx0XHRcdC8vIGFyZSBiYXNlZCBvbiB0aGUgZG9jdW1lbnQncyBVUkwgKGdoLTI5NjUpXG5cdFx0XHRiYXNlID0gY29udGV4dC5jcmVhdGVFbGVtZW50KCBcImJhc2VcIiApO1xuXHRcdFx0YmFzZS5ocmVmID0gZG9jdW1lbnQubG9jYXRpb24uaHJlZjtcblx0XHRcdGNvbnRleHQuaGVhZC5hcHBlbmRDaGlsZCggYmFzZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb250ZXh0ID0gZG9jdW1lbnQ7XG5cdFx0fVxuXHR9XG5cblx0cGFyc2VkID0gcnNpbmdsZVRhZy5leGVjKCBkYXRhICk7XG5cdHNjcmlwdHMgPSAha2VlcFNjcmlwdHMgJiYgW107XG5cblx0Ly8gU2luZ2xlIHRhZ1xuXHRpZiAoIHBhcnNlZCApIHtcblx0XHRyZXR1cm4gWyBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIHBhcnNlZFsgMSBdICkgXTtcblx0fVxuXG5cdHBhcnNlZCA9IGJ1aWxkRnJhZ21lbnQoIFsgZGF0YSBdLCBjb250ZXh0LCBzY3JpcHRzICk7XG5cblx0aWYgKCBzY3JpcHRzICYmIHNjcmlwdHMubGVuZ3RoICkge1xuXHRcdGpRdWVyeSggc2NyaXB0cyApLnJlbW92ZSgpO1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeS5tZXJnZSggW10sIHBhcnNlZC5jaGlsZE5vZGVzICk7XG59O1xuXG5cbi8qKlxuICogTG9hZCBhIHVybCBpbnRvIGEgcGFnZVxuICovXG5qUXVlcnkuZm4ubG9hZCA9IGZ1bmN0aW9uKCB1cmwsIHBhcmFtcywgY2FsbGJhY2sgKSB7XG5cdHZhciBzZWxlY3RvciwgdHlwZSwgcmVzcG9uc2UsXG5cdFx0c2VsZiA9IHRoaXMsXG5cdFx0b2ZmID0gdXJsLmluZGV4T2YoIFwiIFwiICk7XG5cblx0aWYgKCBvZmYgPiAtMSApIHtcblx0XHRzZWxlY3RvciA9IHN0cmlwQW5kQ29sbGFwc2UoIHVybC5zbGljZSggb2ZmICkgKTtcblx0XHR1cmwgPSB1cmwuc2xpY2UoIDAsIG9mZiApO1xuXHR9XG5cblx0Ly8gSWYgaXQncyBhIGZ1bmN0aW9uXG5cdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHBhcmFtcyApICkge1xuXG5cdFx0Ly8gV2UgYXNzdW1lIHRoYXQgaXQncyB0aGUgY2FsbGJhY2tcblx0XHRjYWxsYmFjayA9IHBhcmFtcztcblx0XHRwYXJhbXMgPSB1bmRlZmluZWQ7XG5cblx0Ly8gT3RoZXJ3aXNlLCBidWlsZCBhIHBhcmFtIHN0cmluZ1xuXHR9IGVsc2UgaWYgKCBwYXJhbXMgJiYgdHlwZW9mIHBhcmFtcyA9PT0gXCJvYmplY3RcIiApIHtcblx0XHR0eXBlID0gXCJQT1NUXCI7XG5cdH1cblxuXHQvLyBJZiB3ZSBoYXZlIGVsZW1lbnRzIHRvIG1vZGlmeSwgbWFrZSB0aGUgcmVxdWVzdFxuXHRpZiAoIHNlbGYubGVuZ3RoID4gMCApIHtcblx0XHRqUXVlcnkuYWpheCgge1xuXHRcdFx0dXJsOiB1cmwsXG5cblx0XHRcdC8vIElmIFwidHlwZVwiIHZhcmlhYmxlIGlzIHVuZGVmaW5lZCwgdGhlbiBcIkdFVFwiIG1ldGhvZCB3aWxsIGJlIHVzZWQuXG5cdFx0XHQvLyBNYWtlIHZhbHVlIG9mIHRoaXMgZmllbGQgZXhwbGljaXQgc2luY2Vcblx0XHRcdC8vIHVzZXIgY2FuIG92ZXJyaWRlIGl0IHRocm91Z2ggYWpheFNldHVwIG1ldGhvZFxuXHRcdFx0dHlwZTogdHlwZSB8fCBcIkdFVFwiLFxuXHRcdFx0ZGF0YVR5cGU6IFwiaHRtbFwiLFxuXHRcdFx0ZGF0YTogcGFyYW1zXG5cdFx0fSApLmRvbmUoIGZ1bmN0aW9uKCByZXNwb25zZVRleHQgKSB7XG5cblx0XHRcdC8vIFNhdmUgcmVzcG9uc2UgZm9yIHVzZSBpbiBjb21wbGV0ZSBjYWxsYmFja1xuXHRcdFx0cmVzcG9uc2UgPSBhcmd1bWVudHM7XG5cblx0XHRcdHNlbGYuaHRtbCggc2VsZWN0b3IgP1xuXG5cdFx0XHRcdC8vIElmIGEgc2VsZWN0b3Igd2FzIHNwZWNpZmllZCwgbG9jYXRlIHRoZSByaWdodCBlbGVtZW50cyBpbiBhIGR1bW15IGRpdlxuXHRcdFx0XHQvLyBFeGNsdWRlIHNjcmlwdHMgdG8gYXZvaWQgSUUgJ1Blcm1pc3Npb24gRGVuaWVkJyBlcnJvcnNcblx0XHRcdFx0alF1ZXJ5KCBcIjxkaXY+XCIgKS5hcHBlbmQoIGpRdWVyeS5wYXJzZUhUTUwoIHJlc3BvbnNlVGV4dCApICkuZmluZCggc2VsZWN0b3IgKSA6XG5cblx0XHRcdFx0Ly8gT3RoZXJ3aXNlIHVzZSB0aGUgZnVsbCByZXN1bHRcblx0XHRcdFx0cmVzcG9uc2VUZXh0ICk7XG5cblx0XHQvLyBJZiB0aGUgcmVxdWVzdCBzdWNjZWVkcywgdGhpcyBmdW5jdGlvbiBnZXRzIFwiZGF0YVwiLCBcInN0YXR1c1wiLCBcImpxWEhSXCJcblx0XHQvLyBidXQgdGhleSBhcmUgaWdub3JlZCBiZWNhdXNlIHJlc3BvbnNlIHdhcyBzZXQgYWJvdmUuXG5cdFx0Ly8gSWYgaXQgZmFpbHMsIHRoaXMgZnVuY3Rpb24gZ2V0cyBcImpxWEhSXCIsIFwic3RhdHVzXCIsIFwiZXJyb3JcIlxuXHRcdH0gKS5hbHdheXMoIGNhbGxiYWNrICYmIGZ1bmN0aW9uKCBqcVhIUiwgc3RhdHVzICkge1xuXHRcdFx0c2VsZi5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0Y2FsbGJhY2suYXBwbHkoIHRoaXMsIHJlc3BvbnNlIHx8IFsganFYSFIucmVzcG9uc2VUZXh0LCBzdGF0dXMsIGpxWEhSIF0gKTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cdH1cblxuXHRyZXR1cm4gdGhpcztcbn07XG5cblxuXG5cbi8vIEF0dGFjaCBhIGJ1bmNoIG9mIGZ1bmN0aW9ucyBmb3IgaGFuZGxpbmcgY29tbW9uIEFKQVggZXZlbnRzXG5qUXVlcnkuZWFjaCggW1xuXHRcImFqYXhTdGFydFwiLFxuXHRcImFqYXhTdG9wXCIsXG5cdFwiYWpheENvbXBsZXRlXCIsXG5cdFwiYWpheEVycm9yXCIsXG5cdFwiYWpheFN1Y2Nlc3NcIixcblx0XCJhamF4U2VuZFwiXG5dLCBmdW5jdGlvbiggaSwgdHlwZSApIHtcblx0alF1ZXJ5LmZuWyB0eXBlIF0gPSBmdW5jdGlvbiggZm4gKSB7XG5cdFx0cmV0dXJuIHRoaXMub24oIHR5cGUsIGZuICk7XG5cdH07XG59ICk7XG5cblxuXG5cbmpRdWVyeS5leHByLnBzZXVkb3MuYW5pbWF0ZWQgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0cmV0dXJuIGpRdWVyeS5ncmVwKCBqUXVlcnkudGltZXJzLCBmdW5jdGlvbiggZm4gKSB7XG5cdFx0cmV0dXJuIGVsZW0gPT09IGZuLmVsZW07XG5cdH0gKS5sZW5ndGg7XG59O1xuXG5cblxuXG5qUXVlcnkub2Zmc2V0ID0ge1xuXHRzZXRPZmZzZXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBpICkge1xuXHRcdHZhciBjdXJQb3NpdGlvbiwgY3VyTGVmdCwgY3VyQ1NTVG9wLCBjdXJUb3AsIGN1ck9mZnNldCwgY3VyQ1NTTGVmdCwgY2FsY3VsYXRlUG9zaXRpb24sXG5cdFx0XHRwb3NpdGlvbiA9IGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApLFxuXHRcdFx0Y3VyRWxlbSA9IGpRdWVyeSggZWxlbSApLFxuXHRcdFx0cHJvcHMgPSB7fTtcblxuXHRcdC8vIFNldCBwb3NpdGlvbiBmaXJzdCwgaW4tY2FzZSB0b3AvbGVmdCBhcmUgc2V0IGV2ZW4gb24gc3RhdGljIGVsZW1cblx0XHRpZiAoIHBvc2l0aW9uID09PSBcInN0YXRpY1wiICkge1xuXHRcdFx0ZWxlbS5zdHlsZS5wb3NpdGlvbiA9IFwicmVsYXRpdmVcIjtcblx0XHR9XG5cblx0XHRjdXJPZmZzZXQgPSBjdXJFbGVtLm9mZnNldCgpO1xuXHRcdGN1ckNTU1RvcCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwidG9wXCIgKTtcblx0XHRjdXJDU1NMZWZ0ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJsZWZ0XCIgKTtcblx0XHRjYWxjdWxhdGVQb3NpdGlvbiA9ICggcG9zaXRpb24gPT09IFwiYWJzb2x1dGVcIiB8fCBwb3NpdGlvbiA9PT0gXCJmaXhlZFwiICkgJiZcblx0XHRcdCggY3VyQ1NTVG9wICsgY3VyQ1NTTGVmdCApLmluZGV4T2YoIFwiYXV0b1wiICkgPiAtMTtcblxuXHRcdC8vIE5lZWQgdG8gYmUgYWJsZSB0byBjYWxjdWxhdGUgcG9zaXRpb24gaWYgZWl0aGVyXG5cdFx0Ly8gdG9wIG9yIGxlZnQgaXMgYXV0byBhbmQgcG9zaXRpb24gaXMgZWl0aGVyIGFic29sdXRlIG9yIGZpeGVkXG5cdFx0aWYgKCBjYWxjdWxhdGVQb3NpdGlvbiApIHtcblx0XHRcdGN1clBvc2l0aW9uID0gY3VyRWxlbS5wb3NpdGlvbigpO1xuXHRcdFx0Y3VyVG9wID0gY3VyUG9zaXRpb24udG9wO1xuXHRcdFx0Y3VyTGVmdCA9IGN1clBvc2l0aW9uLmxlZnQ7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3VyVG9wID0gcGFyc2VGbG9hdCggY3VyQ1NTVG9wICkgfHwgMDtcblx0XHRcdGN1ckxlZnQgPSBwYXJzZUZsb2F0KCBjdXJDU1NMZWZ0ICkgfHwgMDtcblx0XHR9XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBvcHRpb25zICkgKSB7XG5cblx0XHRcdC8vIFVzZSBqUXVlcnkuZXh0ZW5kIGhlcmUgdG8gYWxsb3cgbW9kaWZpY2F0aW9uIG9mIGNvb3JkaW5hdGVzIGFyZ3VtZW50IChnaC0xODQ4KVxuXHRcdFx0b3B0aW9ucyA9IG9wdGlvbnMuY2FsbCggZWxlbSwgaSwgalF1ZXJ5LmV4dGVuZCgge30sIGN1ck9mZnNldCApICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBvcHRpb25zLnRvcCAhPSBudWxsICkge1xuXHRcdFx0cHJvcHMudG9wID0gKCBvcHRpb25zLnRvcCAtIGN1ck9mZnNldC50b3AgKSArIGN1clRvcDtcblx0XHR9XG5cdFx0aWYgKCBvcHRpb25zLmxlZnQgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLmxlZnQgPSAoIG9wdGlvbnMubGVmdCAtIGN1ck9mZnNldC5sZWZ0ICkgKyBjdXJMZWZ0O1xuXHRcdH1cblxuXHRcdGlmICggXCJ1c2luZ1wiIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRvcHRpb25zLnVzaW5nLmNhbGwoIGVsZW0sIHByb3BzICk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3VyRWxlbS5jc3MoIHByb3BzICk7XG5cdFx0fVxuXHR9XG59O1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdG9mZnNldDogZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cblx0XHQvLyBQcmVzZXJ2ZSBjaGFpbmluZyBmb3Igc2V0dGVyXG5cdFx0aWYgKCBhcmd1bWVudHMubGVuZ3RoICkge1xuXHRcdFx0cmV0dXJuIG9wdGlvbnMgPT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdHRoaXMgOlxuXHRcdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRcdGpRdWVyeS5vZmZzZXQuc2V0T2Zmc2V0KCB0aGlzLCBvcHRpb25zLCBpICk7XG5cdFx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHR2YXIgZG9jLCBkb2NFbGVtLCByZWN0LCB3aW4sXG5cdFx0XHRlbGVtID0gdGhpc1sgMCBdO1xuXG5cdFx0aWYgKCAhZWxlbSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4gemVyb3MgZm9yIGRpc2Nvbm5lY3RlZCBhbmQgaGlkZGVuIChkaXNwbGF5OiBub25lKSBlbGVtZW50cyAoZ2gtMjMxMClcblx0XHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0XHQvLyBSdW5uaW5nIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBvbiBhXG5cdFx0Ly8gZGlzY29ubmVjdGVkIG5vZGUgaW4gSUUgdGhyb3dzIGFuIGVycm9yXG5cdFx0aWYgKCAhZWxlbS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiB7IHRvcDogMCwgbGVmdDogMCB9O1xuXHRcdH1cblxuXHRcdHJlY3QgPSBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG5cdFx0ZG9jID0gZWxlbS5vd25lckRvY3VtZW50O1xuXHRcdGRvY0VsZW0gPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuXHRcdHdpbiA9IGRvYy5kZWZhdWx0VmlldztcblxuXHRcdHJldHVybiB7XG5cdFx0XHR0b3A6IHJlY3QudG9wICsgd2luLnBhZ2VZT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRUb3AsXG5cdFx0XHRsZWZ0OiByZWN0LmxlZnQgKyB3aW4ucGFnZVhPZmZzZXQgLSBkb2NFbGVtLmNsaWVudExlZnRcblx0XHR9O1xuXHR9LFxuXG5cdHBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRpZiAoICF0aGlzWyAwIF0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIG9mZnNldFBhcmVudCwgb2Zmc2V0LFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdHBhcmVudE9mZnNldCA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XG5cblx0XHQvLyBGaXhlZCBlbGVtZW50cyBhcmUgb2Zmc2V0IGZyb20gd2luZG93IChwYXJlbnRPZmZzZXQgPSB7dG9wOjAsIGxlZnQ6IDB9LFxuXHRcdC8vIGJlY2F1c2UgaXQgaXMgaXRzIG9ubHkgb2Zmc2V0IHBhcmVudFxuXHRcdGlmICggalF1ZXJ5LmNzcyggZWxlbSwgXCJwb3NpdGlvblwiICkgPT09IFwiZml4ZWRcIiApIHtcblxuXHRcdFx0Ly8gQXNzdW1lIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBpcyB0aGVyZSB3aGVuIGNvbXB1dGVkIHBvc2l0aW9uIGlzIGZpeGVkXG5cdFx0XHRvZmZzZXQgPSBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gR2V0ICpyZWFsKiBvZmZzZXRQYXJlbnRcblx0XHRcdG9mZnNldFBhcmVudCA9IHRoaXMub2Zmc2V0UGFyZW50KCk7XG5cblx0XHRcdC8vIEdldCBjb3JyZWN0IG9mZnNldHNcblx0XHRcdG9mZnNldCA9IHRoaXMub2Zmc2V0KCk7XG5cdFx0XHRpZiAoICFub2RlTmFtZSggb2Zmc2V0UGFyZW50WyAwIF0sIFwiaHRtbFwiICkgKSB7XG5cdFx0XHRcdHBhcmVudE9mZnNldCA9IG9mZnNldFBhcmVudC5vZmZzZXQoKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9mZnNldFBhcmVudCBib3JkZXJzXG5cdFx0XHRwYXJlbnRPZmZzZXQgPSB7XG5cdFx0XHRcdHRvcDogcGFyZW50T2Zmc2V0LnRvcCArIGpRdWVyeS5jc3MoIG9mZnNldFBhcmVudFsgMCBdLCBcImJvcmRlclRvcFdpZHRoXCIsIHRydWUgKSxcblx0XHRcdFx0bGVmdDogcGFyZW50T2Zmc2V0LmxlZnQgKyBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnRbIDAgXSwgXCJib3JkZXJMZWZ0V2lkdGhcIiwgdHJ1ZSApXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIFN1YnRyYWN0IHBhcmVudCBvZmZzZXRzIGFuZCBlbGVtZW50IG1hcmdpbnNcblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiBvZmZzZXQudG9wIC0gcGFyZW50T2Zmc2V0LnRvcCAtIGpRdWVyeS5jc3MoIGVsZW0sIFwibWFyZ2luVG9wXCIsIHRydWUgKSxcblx0XHRcdGxlZnQ6IG9mZnNldC5sZWZ0IC0gcGFyZW50T2Zmc2V0LmxlZnQgLSBqUXVlcnkuY3NzKCBlbGVtLCBcIm1hcmdpbkxlZnRcIiwgdHJ1ZSApXG5cdFx0fTtcblx0fSxcblxuXHQvLyBUaGlzIG1ldGhvZCB3aWxsIHJldHVybiBkb2N1bWVudEVsZW1lbnQgaW4gdGhlIGZvbGxvd2luZyBjYXNlczpcblx0Ly8gMSkgRm9yIHRoZSBlbGVtZW50IGluc2lkZSB0aGUgaWZyYW1lIHdpdGhvdXQgb2Zmc2V0UGFyZW50LCB0aGlzIG1ldGhvZCB3aWxsIHJldHVyblxuXHQvLyAgICBkb2N1bWVudEVsZW1lbnQgb2YgdGhlIHBhcmVudCB3aW5kb3dcblx0Ly8gMikgRm9yIHRoZSBoaWRkZW4gb3IgZGV0YWNoZWQgZWxlbWVudFxuXHQvLyAzKSBGb3IgYm9keSBvciBodG1sIGVsZW1lbnQsIGkuZS4gaW4gY2FzZSBvZiB0aGUgaHRtbCBub2RlIC0gaXQgd2lsbCByZXR1cm4gaXRzZWxmXG5cdC8vXG5cdC8vIGJ1dCB0aG9zZSBleGNlcHRpb25zIHdlcmUgbmV2ZXIgcHJlc2VudGVkIGFzIGEgcmVhbCBsaWZlIHVzZS1jYXNlc1xuXHQvLyBhbmQgbWlnaHQgYmUgY29uc2lkZXJlZCBhcyBtb3JlIHByZWZlcmFibGUgcmVzdWx0cy5cblx0Ly9cblx0Ly8gVGhpcyBsb2dpYywgaG93ZXZlciwgaXMgbm90IGd1YXJhbnRlZWQgYW5kIGNhbiBjaGFuZ2UgYXQgYW55IHBvaW50IGluIHRoZSBmdXR1cmVcblx0b2Zmc2V0UGFyZW50OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5tYXAoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIG9mZnNldFBhcmVudCA9IHRoaXMub2Zmc2V0UGFyZW50O1xuXG5cdFx0XHR3aGlsZSAoIG9mZnNldFBhcmVudCAmJiBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnQsIFwicG9zaXRpb25cIiApID09PSBcInN0YXRpY1wiICkge1xuXHRcdFx0XHRvZmZzZXRQYXJlbnQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0UGFyZW50O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gb2Zmc2V0UGFyZW50IHx8IGRvY3VtZW50RWxlbWVudDtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxuLy8gQ3JlYXRlIHNjcm9sbExlZnQgYW5kIHNjcm9sbFRvcCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBzY3JvbGxMZWZ0OiBcInBhZ2VYT2Zmc2V0XCIsIHNjcm9sbFRvcDogXCJwYWdlWU9mZnNldFwiIH0sIGZ1bmN0aW9uKCBtZXRob2QsIHByb3AgKSB7XG5cdHZhciB0b3AgPSBcInBhZ2VZT2Zmc2V0XCIgPT09IHByb3A7XG5cblx0alF1ZXJ5LmZuWyBtZXRob2QgXSA9IGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG1ldGhvZCwgdmFsICkge1xuXG5cdFx0XHQvLyBDb2FsZXNjZSBkb2N1bWVudHMgYW5kIHdpbmRvd3Ncblx0XHRcdHZhciB3aW47XG5cdFx0XHRpZiAoIGpRdWVyeS5pc1dpbmRvdyggZWxlbSApICkge1xuXHRcdFx0XHR3aW4gPSBlbGVtO1xuXHRcdFx0fSBlbHNlIGlmICggZWxlbS5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0d2luID0gZWxlbS5kZWZhdWx0Vmlldztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHdpbiA/IHdpblsgcHJvcCBdIDogZWxlbVsgbWV0aG9kIF07XG5cdFx0XHR9XG5cblx0XHRcdGlmICggd2luICkge1xuXHRcdFx0XHR3aW4uc2Nyb2xsVG8oXG5cdFx0XHRcdFx0IXRvcCA/IHZhbCA6IHdpbi5wYWdlWE9mZnNldCxcblx0XHRcdFx0XHR0b3AgPyB2YWwgOiB3aW4ucGFnZVlPZmZzZXRcblx0XHRcdFx0KTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbVsgbWV0aG9kIF0gPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSwgbWV0aG9kLCB2YWwsIGFyZ3VtZW50cy5sZW5ndGggKTtcblx0fTtcbn0gKTtcblxuLy8gU3VwcG9ydDogU2FmYXJpIDw9NyAtIDkuMSwgQ2hyb21lIDw9MzcgLSA0OVxuLy8gQWRkIHRoZSB0b3AvbGVmdCBjc3NIb29rcyB1c2luZyBqUXVlcnkuZm4ucG9zaXRpb25cbi8vIFdlYmtpdCBidWc6IGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0yOTA4NFxuLy8gQmxpbmsgYnVnOiBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD01ODkzNDdcbi8vIGdldENvbXB1dGVkU3R5bGUgcmV0dXJucyBwZXJjZW50IHdoZW4gc3BlY2lmaWVkIGZvciB0b3AvbGVmdC9ib3R0b20vcmlnaHQ7XG4vLyByYXRoZXIgdGhhbiBtYWtlIHRoZSBjc3MgbW9kdWxlIGRlcGVuZCBvbiB0aGUgb2Zmc2V0IG1vZHVsZSwganVzdCBjaGVjayBmb3IgaXQgaGVyZVxualF1ZXJ5LmVhY2goIFsgXCJ0b3BcIiwgXCJsZWZ0XCIgXSwgZnVuY3Rpb24oIGksIHByb3AgKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgcHJvcCBdID0gYWRkR2V0SG9va0lmKCBzdXBwb3J0LnBpeGVsUG9zaXRpb24sXG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkICkge1xuXHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblx0XHRcdFx0Y29tcHV0ZWQgPSBjdXJDU1MoIGVsZW0sIHByb3AgKTtcblxuXHRcdFx0XHQvLyBJZiBjdXJDU1MgcmV0dXJucyBwZXJjZW50YWdlLCBmYWxsYmFjayB0byBvZmZzZXRcblx0XHRcdFx0cmV0dXJuIHJudW1ub25weC50ZXN0KCBjb21wdXRlZCApID9cblx0XHRcdFx0XHRqUXVlcnkoIGVsZW0gKS5wb3NpdGlvbigpWyBwcm9wIF0gKyBcInB4XCIgOlxuXHRcdFx0XHRcdGNvbXB1dGVkO1xuXHRcdFx0fVxuXHRcdH1cblx0KTtcbn0gKTtcblxuXG4vLyBDcmVhdGUgaW5uZXJIZWlnaHQsIGlubmVyV2lkdGgsIGhlaWdodCwgd2lkdGgsIG91dGVySGVpZ2h0IGFuZCBvdXRlcldpZHRoIG1ldGhvZHNcbmpRdWVyeS5lYWNoKCB7IEhlaWdodDogXCJoZWlnaHRcIiwgV2lkdGg6IFwid2lkdGhcIiB9LCBmdW5jdGlvbiggbmFtZSwgdHlwZSApIHtcblx0alF1ZXJ5LmVhY2goIHsgcGFkZGluZzogXCJpbm5lclwiICsgbmFtZSwgY29udGVudDogdHlwZSwgXCJcIjogXCJvdXRlclwiICsgbmFtZSB9LFxuXHRcdGZ1bmN0aW9uKCBkZWZhdWx0RXh0cmEsIGZ1bmNOYW1lICkge1xuXG5cdFx0Ly8gTWFyZ2luIGlzIG9ubHkgZm9yIG91dGVySGVpZ2h0LCBvdXRlcldpZHRoXG5cdFx0alF1ZXJ5LmZuWyBmdW5jTmFtZSBdID0gZnVuY3Rpb24oIG1hcmdpbiwgdmFsdWUgKSB7XG5cdFx0XHR2YXIgY2hhaW5hYmxlID0gYXJndW1lbnRzLmxlbmd0aCAmJiAoIGRlZmF1bHRFeHRyYSB8fCB0eXBlb2YgbWFyZ2luICE9PSBcImJvb2xlYW5cIiApLFxuXHRcdFx0XHRleHRyYSA9IGRlZmF1bHRFeHRyYSB8fCAoIG1hcmdpbiA9PT0gdHJ1ZSB8fCB2YWx1ZSA9PT0gdHJ1ZSA/IFwibWFyZ2luXCIgOiBcImJvcmRlclwiICk7XG5cblx0XHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCB2YWx1ZSApIHtcblx0XHRcdFx0dmFyIGRvYztcblxuXHRcdFx0XHRpZiAoIGpRdWVyeS5pc1dpbmRvdyggZWxlbSApICkge1xuXG5cdFx0XHRcdFx0Ly8gJCggd2luZG93ICkub3V0ZXJXaWR0aC9IZWlnaHQgcmV0dXJuIHcvaCBpbmNsdWRpbmcgc2Nyb2xsYmFycyAoZ2gtMTcyOSlcblx0XHRcdFx0XHRyZXR1cm4gZnVuY05hbWUuaW5kZXhPZiggXCJvdXRlclwiICkgPT09IDAgP1xuXHRcdFx0XHRcdFx0ZWxlbVsgXCJpbm5lclwiICsgbmFtZSBdIDpcblx0XHRcdFx0XHRcdGVsZW0uZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyBcImNsaWVudFwiICsgbmFtZSBdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gR2V0IGRvY3VtZW50IHdpZHRoIG9yIGhlaWdodFxuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0ZG9jID0gZWxlbS5kb2N1bWVudEVsZW1lbnQ7XG5cblx0XHRcdFx0XHQvLyBFaXRoZXIgc2Nyb2xsW1dpZHRoL0hlaWdodF0gb3Igb2Zmc2V0W1dpZHRoL0hlaWdodF0gb3IgY2xpZW50W1dpZHRoL0hlaWdodF0sXG5cdFx0XHRcdFx0Ly8gd2hpY2hldmVyIGlzIGdyZWF0ZXN0XG5cdFx0XHRcdFx0cmV0dXJuIE1hdGgubWF4KFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcInNjcm9sbFwiICsgbmFtZSBdLCBkb2NbIFwic2Nyb2xsXCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRlbGVtLmJvZHlbIFwib2Zmc2V0XCIgKyBuYW1lIF0sIGRvY1sgXCJvZmZzZXRcIiArIG5hbWUgXSxcblx0XHRcdFx0XHRcdGRvY1sgXCJjbGllbnRcIiArIG5hbWUgXVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZCA/XG5cblx0XHRcdFx0XHQvLyBHZXQgd2lkdGggb3IgaGVpZ2h0IG9uIHRoZSBlbGVtZW50LCByZXF1ZXN0aW5nIGJ1dCBub3QgZm9yY2luZyBwYXJzZUZsb2F0XG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgdHlwZSwgZXh0cmEgKSA6XG5cblx0XHRcdFx0XHQvLyBTZXQgd2lkdGggb3IgaGVpZ2h0IG9uIHRoZSBlbGVtZW50XG5cdFx0XHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCB0eXBlLCB2YWx1ZSwgZXh0cmEgKTtcblx0XHRcdH0sIHR5cGUsIGNoYWluYWJsZSA/IG1hcmdpbiA6IHVuZGVmaW5lZCwgY2hhaW5hYmxlICk7XG5cdFx0fTtcblx0fSApO1xufSApO1xuXG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblxuXHRiaW5kOiBmdW5jdGlvbiggdHlwZXMsIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlcywgbnVsbCwgZGF0YSwgZm4gKTtcblx0fSxcblx0dW5iaW5kOiBmdW5jdGlvbiggdHlwZXMsIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9mZiggdHlwZXMsIG51bGwsIGZuICk7XG5cdH0sXG5cblx0ZGVsZWdhdGU6IGZ1bmN0aW9uKCBzZWxlY3RvciwgdHlwZXMsIGRhdGEsIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlcywgc2VsZWN0b3IsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuZGVsZWdhdGU6IGZ1bmN0aW9uKCBzZWxlY3RvciwgdHlwZXMsIGZuICkge1xuXG5cdFx0Ly8gKCBuYW1lc3BhY2UgKSBvciAoIHNlbGVjdG9yLCB0eXBlcyBbLCBmbl0gKVxuXHRcdHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09PSAxID9cblx0XHRcdHRoaXMub2ZmKCBzZWxlY3RvciwgXCIqKlwiICkgOlxuXHRcdFx0dGhpcy5vZmYoIHR5cGVzLCBzZWxlY3RvciB8fCBcIioqXCIsIGZuICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmhvbGRSZWFkeSA9IGZ1bmN0aW9uKCBob2xkICkge1xuXHRpZiAoIGhvbGQgKSB7XG5cdFx0alF1ZXJ5LnJlYWR5V2FpdCsrO1xuXHR9IGVsc2Uge1xuXHRcdGpRdWVyeS5yZWFkeSggdHJ1ZSApO1xuXHR9XG59O1xualF1ZXJ5LmlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xualF1ZXJ5LnBhcnNlSlNPTiA9IEpTT04ucGFyc2U7XG5qUXVlcnkubm9kZU5hbWUgPSBub2RlTmFtZTtcblxuXG5cblxuLy8gUmVnaXN0ZXIgYXMgYSBuYW1lZCBBTUQgbW9kdWxlLCBzaW5jZSBqUXVlcnkgY2FuIGJlIGNvbmNhdGVuYXRlZCB3aXRoIG90aGVyXG4vLyBmaWxlcyB0aGF0IG1heSB1c2UgZGVmaW5lLCBidXQgbm90IHZpYSBhIHByb3BlciBjb25jYXRlbmF0aW9uIHNjcmlwdCB0aGF0XG4vLyB1bmRlcnN0YW5kcyBhbm9ueW1vdXMgQU1EIG1vZHVsZXMuIEEgbmFtZWQgQU1EIGlzIHNhZmVzdCBhbmQgbW9zdCByb2J1c3Rcbi8vIHdheSB0byByZWdpc3Rlci4gTG93ZXJjYXNlIGpxdWVyeSBpcyB1c2VkIGJlY2F1c2UgQU1EIG1vZHVsZSBuYW1lcyBhcmVcbi8vIGRlcml2ZWQgZnJvbSBmaWxlIG5hbWVzLCBhbmQgalF1ZXJ5IGlzIG5vcm1hbGx5IGRlbGl2ZXJlZCBpbiBhIGxvd2VyY2FzZVxuLy8gZmlsZSBuYW1lLiBEbyB0aGlzIGFmdGVyIGNyZWF0aW5nIHRoZSBnbG9iYWwgc28gdGhhdCBpZiBhbiBBTUQgbW9kdWxlIHdhbnRzXG4vLyB0byBjYWxsIG5vQ29uZmxpY3QgdG8gaGlkZSB0aGlzIHZlcnNpb24gb2YgalF1ZXJ5LCBpdCB3aWxsIHdvcmsuXG5cbi8vIE5vdGUgdGhhdCBmb3IgbWF4aW11bSBwb3J0YWJpbGl0eSwgbGlicmFyaWVzIHRoYXQgYXJlIG5vdCBqUXVlcnkgc2hvdWxkXG4vLyBkZWNsYXJlIHRoZW1zZWx2ZXMgYXMgYW5vbnltb3VzIG1vZHVsZXMsIGFuZCBhdm9pZCBzZXR0aW5nIGEgZ2xvYmFsIGlmIGFuXG4vLyBBTUQgbG9hZGVyIGlzIHByZXNlbnQuIGpRdWVyeSBpcyBhIHNwZWNpYWwgY2FzZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZVxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2pyYnVya2UvcmVxdWlyZWpzL3dpa2kvVXBkYXRpbmctZXhpc3RpbmctbGlicmFyaWVzI3dpa2ktYW5vblxuXG5pZiAoIHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICkge1xuXHRkZWZpbmUoIFwianF1ZXJ5XCIsIFtdLCBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4galF1ZXJ5O1xuXHR9ICk7XG59XG5cblxuXG5cbnZhclxuXG5cdC8vIE1hcCBvdmVyIGpRdWVyeSBpbiBjYXNlIG9mIG92ZXJ3cml0ZVxuXHRfalF1ZXJ5ID0gd2luZG93LmpRdWVyeSxcblxuXHQvLyBNYXAgb3ZlciB0aGUgJCBpbiBjYXNlIG9mIG92ZXJ3cml0ZVxuXHRfJCA9IHdpbmRvdy4kO1xuXG5qUXVlcnkubm9Db25mbGljdCA9IGZ1bmN0aW9uKCBkZWVwICkge1xuXHRpZiAoIHdpbmRvdy4kID09PSBqUXVlcnkgKSB7XG5cdFx0d2luZG93LiQgPSBfJDtcblx0fVxuXG5cdGlmICggZGVlcCAmJiB3aW5kb3cualF1ZXJ5ID09PSBqUXVlcnkgKSB7XG5cdFx0d2luZG93LmpRdWVyeSA9IF9qUXVlcnk7XG5cdH1cblxuXHRyZXR1cm4galF1ZXJ5O1xufTtcblxuLy8gRXhwb3NlIGpRdWVyeSBhbmQgJCBpZGVudGlmaWVycywgZXZlbiBpbiBBTURcbi8vICgjNzEwMiNjb21tZW50OjEwLCBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L2pxdWVyeS9wdWxsLzU1Nylcbi8vIGFuZCBDb21tb25KUyBmb3IgYnJvd3NlciBlbXVsYXRvcnMgKCMxMzU2NilcbmlmICggIW5vR2xvYmFsICkge1xuXHR3aW5kb3cualF1ZXJ5ID0gd2luZG93LiQgPSBqUXVlcnk7XG59XG5cblxuXG5cbnJldHVybiBqUXVlcnk7XG59ICk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9qcXVlcnkvZGlzdC9qcXVlcnkuanNcbi8vIG1vZHVsZSBpZCA9IDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gSmF2YXNjcmlwdFxuXG5pbXBvcnQgJCBmcm9tICdqcXVlcnknXG5pbXBvcnQgJ2Jvb3RzdHJhcCc7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1zZWxlY3QnO1xuaW1wb3J0ICdib290c3RyYXAtdmFsaWRhdG9yJztcbmltcG9ydCAnYm9vdHN0cmFwLWZpbGVpbnB1dCc7XG5cblxuLy8gQ1NTXG5cbmltcG9ydCAnYm9vdHN0cmFwL2Rpc3QvY3NzL2Jvb3RzdHJhcC5jc3MnO1xuaW1wb3J0ICdib290c3RyYXAtc2VsZWN0L2Rpc3QvY3NzL2Jvb3RzdHJhcC1zZWxlY3QuY3NzJztcbmltcG9ydCAnYm9vdHN0cmFwLWZpbGVpbnB1dC9jc3MvZmlsZWlucHV0LmNzcyc7XG5cbmltcG9ydCAnQGZvcnRhd2Vzb21lL2ZvbnRhd2Vzb21lLWZyZWUvY3NzL2FsbC5jc3MnO1xuXG5pbXBvcnQgJy4vc3R5bGUuY3NzJ1xuXG4kKGZ1bmN0aW9uICgpIHtcbiAgXG4gICQoXCIjbXlJbnB1dFwiKS5vbihcImtleXVwXCIsIGZ1bmN0aW9uKGV2ZW50T2JqZWN0KSB7XG4gICAgXG4gICAgdmFyIGlucHV0LCBmaWx0ZXIsIHVsLCBsaSwgYSwgaTtcblxuICAgIGlucHV0ID0gZXZlbnRPYmplY3QuY3VycmVudFRhcmdldDtcbiAgICBmaWx0ZXIgPSBpbnB1dC52YWx1ZS50b1VwcGVyQ2FzZSgpO1xuICAgIHVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJteVVMXCIpO1xuICAgIGxpID0gdWwuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2EnKTtcblxuICAgIC8vIExvb3AgdGhyb3VnaCBhbGwgbGlzdCBpdGVtcywgYW5kIGhpZGUgdGhvc2Ugd2hvIGRvbid0IG1hdGNoIHRoZSBzZWFyY2ggcXVlcnlcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGEgPSBsaVtpXTsgLy9saVtpXS5nZXRFbGVtZW50c0J5VGFnTmFtZShcImFcIilbMF07XG4gICAgICBpZiAoYS5pbm5lckhUTUwudG9VcHBlckNhc2UoKS5pbmRleE9mKGZpbHRlcikgPiAtMSkge1xuXHRsaVtpXS5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcbiAgICAgIH0gZWxzZSB7XG5cdGxpW2ldLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgIH1cbiAgICB9XG5cbiAgfSk7XG5cbiAgZnVuY3Rpb24gY2hlY2tVc2VybmFtZUlucHV0SGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciBpbnB1dF9lbCA9ICQoZXZlbnRPYmplY3QuY3VycmVudFRhcmdldCk7XG4gICAgdmFyIGRhdGEgPSBKU09OLnN0cmluZ2lmeSh7XCJ1c2VybmFtZVwiOiBpbnB1dF9lbC52YWwoKX0pO1xuICAgIHZhciB1cmwgPSBgL3RlYWNoZXJzL2NoZWNrX3VzZXJuYW1lLyR7aW5wdXRfZWwudmFsKCl9YFxuICAgICAgICBcbiAgICAkLnBvc3QoXG4gICAgICB1cmwsXG4gICAgICBkYXRhLFxuICAgICAgZnVuY3Rpb24ocmVzdWx0KSB7XG5cdGlmIChyZXN1bHQuZXhpc3RzKSB7XG5cdCAgY29uc29sZS5sb2coXCJVc2VybmFtZSBleGlzdHNcIik7XG5cdH1cbiAgICAgIH0sXG4gICAgICBcImpzb25cIlxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiB1c2VybmFtZUdlbmVyYXRvcihldmVudE9iamVjdCwgZmlyc3RuYW1lLCBzdXJuYW1lKSB7XG4gICAgdmFyIGlucHV0X2VsID0gJChldmVudE9iamVjdC5jdXJyZW50VGFyZ2V0KTtcbiAgICBpbnB1dF9lbC52YWwoZmlyc3RuYW1lK1wiLlwiK3N1cm5hbWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVsZXRlUmVsYXRpb25IYW5kbGVyKGV2ZW50T2JqZWN0KSB7XG4gICAgdmFyIHVybCA9IHRoaXMuZGF0YXNldC51cmw7XG4gICAgdmFyIG1vZGFsRWwgPSAkKCcja2FybWVuLW1vZGFsLXJlbW92ZScpO1xuICAgIFxuICAgIHZhciBlbCA9ICQodGhpcyk7XG5cbiAgICBtb2RhbEVsLm1vZGFsKHtiYWNrZHJvcDogJ3N0YXRpYyd9KS5vbmUoJ2NsaWNrJywgJyNrYXJtZW4tbW9kYWwtYnRuLWNvbmZpcm0nLCBmdW5jdGlvbigpIHtcbiAgICBcbiAgICAgICQuYWpheCh7XG5cdHVybDogdXJsLFxuXHR0eXBlOiAnREVMRVRFJyxcblx0c3VjY2VzczogZnVuY3Rpb24ocmVzdWx0KSB7XG5cdCAgZWwuY2xvc2VzdChcIi5saXN0LWdyb3VwLWl0ZW1cIikucmVtb3ZlKCk7XG5cdCAgbW9kYWxFbC5tb2RhbCgnaGlkZScpO1xuXHR9XG4gICAgICB9KTtcbiAgICAgIFxuICAgIH0pO1xuICAgIFxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICBmdW5jdGlvbiBkZWxldGVIYW5kbGVyKGV2ZW50T2JqZWN0KSB7XG4gICAgdmFyIHVybCA9IHRoaXMuZGF0YXNldC51cmw7XG4gICAgdmFyIG1vZGFsRWwgPSAkKCcja2FybWVuLW1vZGFsLXJlbW92ZScpO1xuICAgIFxuICAgIHZhciBlbCA9ICQodGhpcyk7XG5cbiAgICBtb2RhbEVsLm1vZGFsKHtiYWNrZHJvcDogJ3N0YXRpYyd9KS5vbmUoJ2NsaWNrJywgJyNrYXJtZW4tbW9kYWwtYnRuLWNvbmZpcm0nLCBmdW5jdGlvbigpIHtcbiAgICAgIFxuICAgICAgJC5hamF4KHtcblx0dXJsOiB1cmwsXG5cdHR5cGU6ICdERUxFVEUnLFxuXHRzdWNjZXNzOiBmdW5jdGlvbihyZXN1bHQpIHtcblx0ICBtb2RhbEVsLm1vZGFsKCdoaWRlJyk7XG5cdCAgd2luZG93LmxvY2F0aW9uLnJlcGxhY2UocmVzdWx0LnJlZGlyZWN0X3VybCk7XG5cdH1cbiAgICAgIH0pO1xuICAgICAgXG4gICAgfSk7XG4gICAgXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICBcbiAgJChcIi5hamF4LXBvc3RcIikub24oXCJjbGlja1wiLCBmdW5jdGlvbihldmVudE9iamVjdCkge1xuICAgIHZhciBzZWxlY3RfZWwgPSAkKFwiI1wiK3RoaXMuZGF0YXNldC5zZWxlY3QpLmZpcnN0KCk7XG4gICAgdmFyIGxpc3Rncm91cF9lbCA9ICQoXCIjXCIrdGhpcy5kYXRhc2V0Lmxpc3Rncm91cCkuZmlyc3QoKTtcbiAgICB2YXIgdXJsID0gdGhpcy5kYXRhc2V0LnVybDtcbiAgICB2YXIgZGF0YSA9IEpTT04uc3RyaW5naWZ5KHtcImlkc1wiOiBzZWxlY3RfZWwudmFsKCl9KTtcbiAgICBcbiAgICAkLnBvc3QoXG4gICAgICB1cmwsXG4gICAgICBkYXRhLFxuICAgICAgZnVuY3Rpb24ocmVzdWx0KSB7XG5cdHZhciBpO1xuXHRpZiAocmVzdWx0LmVsZW1lbnRzICE9IG51bGwpIHtcblx0ICBmb3IgKGkgPSAwOyBpIDwgcmVzdWx0LmVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cdCAgICB2YXIgbmV3SXRlbSA9IGBcblx0XHQ8YSBocmVmPVwiI1wiIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGNsZWFyZml4XCI+XG5cdFx0PHNwYW4gY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWJvb2tcIj48L3NwYW4+XG5cdFx0JHtyZXN1bHQuZWxlbWVudHNbaV0uTmFtZX1cblx0XHQ8c3BhbiBjbGFzcz1cInB1bGwtcmlnaHRcIj5cblx0XHQ8YnV0dG9uIGRhdGEtdXJsPVwiLyR7cmVzdWx0Lm5hbWUxfS8ke3Jlc3VsdC5pZDF9LyR7cmVzdWx0Lm5hbWUyfS8ke3Jlc3VsdC5pZDJbaV19L2RlbGV0ZVwiIGNsYXNzPVwiYnRuIGJ0bi14cyBidG4td2FybmluZyBrYXJtZW4tYWpheC1kZWxldGVcIj5cblx0XHQ8c3BhbiBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJhc2hcIj48L3NwYW4+XG5cdFx0PC9idXR0b24+XG5cdCAgICAgIDwvc3Bhbj5cblx0ICAgICAgYDtcblx0ICAgICQobGlzdGdyb3VwX2VsKS5hcHBlbmQobmV3SXRlbSk7XG5cdCAgICAkKFwiLmthcm1lbi1hamF4LWRlbGV0ZVwiKS5vbihcImNsaWNrXCIsIGRlbGV0ZUhhbmRsZXIpO1xuXHQgIH1cblx0fVxuICAgICAgXG4gICAgICB9LFxuICAgICAgXCJqc29uXCJcbiAgICApO1xuXG4gICAgc2VsZWN0X2VsLnZhbCgnZGVmYXVsdCcpO1xuICAgIHNlbGVjdF9lbC5zZWxlY3RwaWNrZXIoXCJyZWZyZXNoXCIpO1xuICAgIFxuICAgIHJldHVybiBmYWxzZTtcbiAgICBcbiAgfSk7XG5cbiAgJChcIi5rYXJtZW4tYWpheC1kZWxldGUtcmVsYXRpb25cIikub24oXCJjbGlja1wiLCBkZWxldGVSZWxhdGlvbkhhbmRsZXIpO1xuICAkKFwiLmthcm1lbi1hamF4LWRlbGV0ZVwiKS5vbihcImNsaWNrXCIsIGRlbGV0ZUhhbmRsZXIpO1xuXG59KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vc3JjL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxuICAqIEJvb3RzdHJhcCB2NC4xLjMgKGh0dHBzOi8vZ2V0Ym9vdHN0cmFwLmNvbS8pXG4gICogQ29weXJpZ2h0IDIwMTEtMjAxOCBUaGUgQm9vdHN0cmFwIEF1dGhvcnMgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ncmFwaHMvY29udHJpYnV0b3JzKVxuICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICovXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2pxdWVyeScpLCByZXF1aXJlKCdwb3BwZXIuanMnKSkgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2pxdWVyeScsICdwb3BwZXIuanMnXSwgZmFjdG9yeSkgOlxuICAoZmFjdG9yeSgoZ2xvYmFsLmJvb3RzdHJhcCA9IHt9KSxnbG9iYWwualF1ZXJ5LGdsb2JhbC5Qb3BwZXIpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLCQsUG9wcGVyKSB7ICd1c2Ugc3RyaWN0JztcblxuICAkID0gJCAmJiAkLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykgPyAkWydkZWZhdWx0J10gOiAkO1xuICBQb3BwZXIgPSBQb3BwZXIgJiYgUG9wcGVyLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykgPyBQb3BwZXJbJ2RlZmF1bHQnXSA6IFBvcHBlcjtcblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gX2NyZWF0ZUNsYXNzKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykge1xuICAgIGlmIChwcm90b1Byb3BzKSBfZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpO1xuICAgIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH1cblxuICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHZhbHVlKSB7XG4gICAgaWYgKGtleSBpbiBvYmopIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba2V5XSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICBmdW5jdGlvbiBfb2JqZWN0U3ByZWFkKHRhcmdldCkge1xuICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldICE9IG51bGwgPyBhcmd1bWVudHNbaV0gOiB7fTtcbiAgICAgIHZhciBvd25LZXlzID0gT2JqZWN0LmtleXMoc291cmNlKTtcblxuICAgICAgaWYgKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIG93bktleXMgPSBvd25LZXlzLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHNvdXJjZSkuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHtcbiAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIHN5bSkuZW51bWVyYWJsZTtcbiAgICAgICAgfSkpO1xuICAgICAgfVxuXG4gICAgICBvd25LZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBfZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cblxuICBmdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykge1xuICAgIHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcy5wcm90b3R5cGUpO1xuICAgIHN1YkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IHN1YkNsYXNzO1xuICAgIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7XG4gIH1cblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiB1dGlsLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBVdGlsID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBQcml2YXRlIFRyYW5zaXRpb25FbmQgSGVscGVyc1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBUUkFOU0lUSU9OX0VORCA9ICd0cmFuc2l0aW9uZW5kJztcbiAgICB2YXIgTUFYX1VJRCA9IDEwMDAwMDA7XG4gICAgdmFyIE1JTExJU0VDT05EU19NVUxUSVBMSUVSID0gMTAwMDsgLy8gU2hvdXRvdXQgQW5ndXNDcm9sbCAoaHR0cHM6Ly9nb28uZ2wvcHh3UUdwKVxuXG4gICAgZnVuY3Rpb24gdG9UeXBlKG9iaikge1xuICAgICAgcmV0dXJuIHt9LnRvU3RyaW5nLmNhbGwob2JqKS5tYXRjaCgvXFxzKFthLXpdKykvaSlbMV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTcGVjaWFsVHJhbnNpdGlvbkVuZEV2ZW50KCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYmluZFR5cGU6IFRSQU5TSVRJT05fRU5ELFxuICAgICAgICBkZWxlZ2F0ZVR5cGU6IFRSQU5TSVRJT05fRU5ELFxuICAgICAgICBoYW5kbGU6IGZ1bmN0aW9uIGhhbmRsZShldmVudCkge1xuICAgICAgICAgIGlmICgkJCQxKGV2ZW50LnRhcmdldCkuaXModGhpcykpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudC5oYW5kbGVPYmouaGFuZGxlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHByZWZlci1yZXN0LXBhcmFtc1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZpbmVkXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbkVuZEVtdWxhdG9yKGR1cmF0aW9uKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgY2FsbGVkID0gZmFsc2U7XG4gICAgICAkJCQxKHRoaXMpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICB9KTtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICAgIFV0aWwudHJpZ2dlclRyYW5zaXRpb25FbmQoX3RoaXMpO1xuICAgICAgICB9XG4gICAgICB9LCBkdXJhdGlvbik7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRUcmFuc2l0aW9uRW5kU3VwcG9ydCgpIHtcbiAgICAgICQkJDEuZm4uZW11bGF0ZVRyYW5zaXRpb25FbmQgPSB0cmFuc2l0aW9uRW5kRW11bGF0b3I7XG4gICAgICAkJCQxLmV2ZW50LnNwZWNpYWxbVXRpbC5UUkFOU0lUSU9OX0VORF0gPSBnZXRTcGVjaWFsVHJhbnNpdGlvbkVuZEV2ZW50KCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogUHVibGljIFV0aWwgQXBpXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgdmFyIFV0aWwgPSB7XG4gICAgICBUUkFOU0lUSU9OX0VORDogJ2JzVHJhbnNpdGlvbkVuZCcsXG4gICAgICBnZXRVSUQ6IGZ1bmN0aW9uIGdldFVJRChwcmVmaXgpIHtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgICAgcHJlZml4ICs9IH5+KE1hdGgucmFuZG9tKCkgKiBNQVhfVUlEKTsgLy8gXCJ+flwiIGFjdHMgbGlrZSBhIGZhc3RlciBNYXRoLmZsb29yKCkgaGVyZVxuICAgICAgICB9IHdoaWxlIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwcmVmaXgpKTtcblxuICAgICAgICByZXR1cm4gcHJlZml4O1xuICAgICAgfSxcbiAgICAgIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQ6IGZ1bmN0aW9uIGdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS10YXJnZXQnKTtcblxuICAgICAgICBpZiAoIXNlbGVjdG9yIHx8IHNlbGVjdG9yID09PSAnIycpIHtcbiAgICAgICAgICBzZWxlY3RvciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdocmVmJykgfHwgJyc7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKSA/IHNlbGVjdG9yIDogbnVsbDtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBnZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudDogZnVuY3Rpb24gZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSAvLyBHZXQgdHJhbnNpdGlvbi1kdXJhdGlvbiBvZiB0aGUgZWxlbWVudFxuXG5cbiAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9ICQkJDEoZWxlbWVudCkuY3NzKCd0cmFuc2l0aW9uLWR1cmF0aW9uJyk7XG4gICAgICAgIHZhciBmbG9hdFRyYW5zaXRpb25EdXJhdGlvbiA9IHBhcnNlRmxvYXQodHJhbnNpdGlvbkR1cmF0aW9uKTsgLy8gUmV0dXJuIDAgaWYgZWxlbWVudCBvciB0cmFuc2l0aW9uIGR1cmF0aW9uIGlzIG5vdCBmb3VuZFxuXG4gICAgICAgIGlmICghZmxvYXRUcmFuc2l0aW9uRHVyYXRpb24pIHtcbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSAvLyBJZiBtdWx0aXBsZSBkdXJhdGlvbnMgYXJlIGRlZmluZWQsIHRha2UgdGhlIGZpcnN0XG5cblxuICAgICAgICB0cmFuc2l0aW9uRHVyYXRpb24gPSB0cmFuc2l0aW9uRHVyYXRpb24uc3BsaXQoJywnKVswXTtcbiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQodHJhbnNpdGlvbkR1cmF0aW9uKSAqIE1JTExJU0VDT05EU19NVUxUSVBMSUVSO1xuICAgICAgfSxcbiAgICAgIHJlZmxvdzogZnVuY3Rpb24gcmVmbG93KGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgfSxcbiAgICAgIHRyaWdnZXJUcmFuc2l0aW9uRW5kOiBmdW5jdGlvbiB0cmlnZ2VyVHJhbnNpdGlvbkVuZChlbGVtZW50KSB7XG4gICAgICAgICQkJDEoZWxlbWVudCkudHJpZ2dlcihUUkFOU0lUSU9OX0VORCk7XG4gICAgICB9LFxuICAgICAgLy8gVE9ETzogUmVtb3ZlIGluIHY1XG4gICAgICBzdXBwb3J0c1RyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uIHN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oVFJBTlNJVElPTl9FTkQpO1xuICAgICAgfSxcbiAgICAgIGlzRWxlbWVudDogZnVuY3Rpb24gaXNFbGVtZW50KG9iaikge1xuICAgICAgICByZXR1cm4gKG9ialswXSB8fCBvYmopLm5vZGVUeXBlO1xuICAgICAgfSxcbiAgICAgIHR5cGVDaGVja0NvbmZpZzogZnVuY3Rpb24gdHlwZUNoZWNrQ29uZmlnKGNvbXBvbmVudE5hbWUsIGNvbmZpZywgY29uZmlnVHlwZXMpIHtcbiAgICAgICAgZm9yICh2YXIgcHJvcGVydHkgaW4gY29uZmlnVHlwZXMpIHtcbiAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGNvbmZpZ1R5cGVzLCBwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgIHZhciBleHBlY3RlZFR5cGVzID0gY29uZmlnVHlwZXNbcHJvcGVydHldO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gY29uZmlnW3Byb3BlcnR5XTtcbiAgICAgICAgICAgIHZhciB2YWx1ZVR5cGUgPSB2YWx1ZSAmJiBVdGlsLmlzRWxlbWVudCh2YWx1ZSkgPyAnZWxlbWVudCcgOiB0b1R5cGUodmFsdWUpO1xuXG4gICAgICAgICAgICBpZiAoIW5ldyBSZWdFeHAoZXhwZWN0ZWRUeXBlcykudGVzdCh2YWx1ZVR5cGUpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihjb21wb25lbnROYW1lLnRvVXBwZXJDYXNlKCkgKyBcIjogXCIgKyAoXCJPcHRpb24gXFxcIlwiICsgcHJvcGVydHkgKyBcIlxcXCIgcHJvdmlkZWQgdHlwZSBcXFwiXCIgKyB2YWx1ZVR5cGUgKyBcIlxcXCIgXCIpICsgKFwiYnV0IGV4cGVjdGVkIHR5cGUgXFxcIlwiICsgZXhwZWN0ZWRUeXBlcyArIFwiXFxcIi5cIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgc2V0VHJhbnNpdGlvbkVuZFN1cHBvcnQoKTtcbiAgICByZXR1cm4gVXRpbDtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBhbGVydC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICB2YXIgQWxlcnQgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ2FsZXJ0JztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLmFsZXJ0JztcbiAgICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgRElTTUlTUzogJ1tkYXRhLWRpc21pc3M9XCJhbGVydFwiXSdcbiAgICB9O1xuICAgIHZhciBFdmVudCA9IHtcbiAgICAgIENMT1NFOiBcImNsb3NlXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTE9TRUQ6IFwiY2xvc2VkXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gICAgfTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgQUxFUlQ6ICdhbGVydCcsXG4gICAgICBGQURFOiAnZmFkZScsXG4gICAgICBTSE9XOiAnc2hvdydcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBBbGVydCA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIEFsZXJ0KGVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gQWxlcnQucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by5jbG9zZSA9IGZ1bmN0aW9uIGNsb3NlKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHJvb3RFbGVtZW50ID0gdGhpcy5fZWxlbWVudDtcblxuICAgICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICAgIHJvb3RFbGVtZW50ID0gdGhpcy5fZ2V0Um9vdEVsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY3VzdG9tRXZlbnQgPSB0aGlzLl90cmlnZ2VyQ2xvc2VFdmVudChyb290RWxlbWVudCk7XG5cbiAgICAgICAgaWYgKGN1c3RvbUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcmVtb3ZlRWxlbWVudChyb290RWxlbWVudCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0Um9vdEVsZW1lbnQgPSBmdW5jdGlvbiBfZ2V0Um9vdEVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgIHZhciBwYXJlbnQgPSBmYWxzZTtcblxuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICBwYXJlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcGFyZW50KSB7XG4gICAgICAgICAgcGFyZW50ID0gJCQkMShlbGVtZW50KS5jbG9zZXN0KFwiLlwiICsgQ2xhc3NOYW1lLkFMRVJUKVswXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXJlbnQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3RyaWdnZXJDbG9zZUV2ZW50ID0gZnVuY3Rpb24gX3RyaWdnZXJDbG9zZUV2ZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGNsb3NlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkNMT1NFKTtcbiAgICAgICAgJCQkMShlbGVtZW50KS50cmlnZ2VyKGNsb3NlRXZlbnQpO1xuICAgICAgICByZXR1cm4gY2xvc2VFdmVudDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fcmVtb3ZlRWxlbWVudCA9IGZ1bmN0aW9uIF9yZW1vdmVFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICAkJCQxKGVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgICBpZiAoISQkJDEoZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpKSB7XG4gICAgICAgICAgdGhpcy5fZGVzdHJveUVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgJCQkMShlbGVtZW50KS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzLl9kZXN0cm95RWxlbWVudChlbGVtZW50LCBldmVudCk7XG4gICAgICAgIH0pLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2Rlc3Ryb3lFbGVtZW50ID0gZnVuY3Rpb24gX2Rlc3Ryb3lFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgJCQkMShlbGVtZW50KS5kZXRhY2goKS50cmlnZ2VyKEV2ZW50LkNMT1NFRCkucmVtb3ZlKCk7XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBBbGVydC5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyICRlbGVtZW50ID0gJCQkMSh0aGlzKTtcbiAgICAgICAgICB2YXIgZGF0YSA9ICRlbGVtZW50LmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IEFsZXJ0KHRoaXMpO1xuICAgICAgICAgICAgJGVsZW1lbnQuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNvbmZpZyA9PT0gJ2Nsb3NlJykge1xuICAgICAgICAgICAgZGF0YVtjb25maWddKHRoaXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBBbGVydC5faGFuZGxlRGlzbWlzcyA9IGZ1bmN0aW9uIF9oYW5kbGVEaXNtaXNzKGFsZXJ0SW5zdGFuY2UpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhbGVydEluc3RhbmNlLmNsb3NlKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKEFsZXJ0LCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gQWxlcnQ7XG4gICAgfSgpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5ESVNNSVNTLCBBbGVydC5faGFuZGxlRGlzbWlzcyhuZXcgQWxlcnQoKSkpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IEFsZXJ0Ll9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IEFsZXJ0O1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBBbGVydC5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gQWxlcnQ7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogYnV0dG9uLmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIHZhciBCdXR0b24gPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ2J1dHRvbic7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5idXR0b24nO1xuICAgIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICAgIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgQUNUSVZFOiAnYWN0aXZlJyxcbiAgICAgIEJVVFRPTjogJ2J0bicsXG4gICAgICBGT0NVUzogJ2ZvY3VzJ1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgREFUQV9UT0dHTEVfQ0FSUk9UOiAnW2RhdGEtdG9nZ2xlXj1cImJ1dHRvblwiXScsXG4gICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cImJ1dHRvbnNcIl0nLFxuICAgICAgSU5QVVQ6ICdpbnB1dCcsXG4gICAgICBBQ1RJVkU6ICcuYWN0aXZlJyxcbiAgICAgIEJVVFRPTjogJy5idG4nXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZLFxuICAgICAgRk9DVVNfQkxVUl9EQVRBX0FQSTogXCJmb2N1c1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZICsgXCIgXCIgKyAoXCJibHVyXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVkpXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgQnV0dG9uID1cbiAgICAvKiNfX1BVUkVfXyovXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgZnVuY3Rpb24gQnV0dG9uKGVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gQnV0dG9uLnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgICB2YXIgdHJpZ2dlckNoYW5nZUV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgdmFyIGFkZEFyaWFQcmVzc2VkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHJvb3RFbGVtZW50ID0gJCQkMSh0aGlzLl9lbGVtZW50KS5jbG9zZXN0KFNlbGVjdG9yLkRBVEFfVE9HR0xFKVswXTtcblxuICAgICAgICBpZiAocm9vdEVsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLl9lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuSU5QVVQpO1xuXG4gICAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICBpZiAoaW5wdXQudHlwZSA9PT0gJ3JhZGlvJykge1xuICAgICAgICAgICAgICBpZiAoaW5wdXQuY2hlY2tlZCAmJiB0aGlzLl9lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhDbGFzc05hbWUuQUNUSVZFKSkge1xuICAgICAgICAgICAgICAgIHRyaWdnZXJDaGFuZ2VFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBhY3RpdmVFbGVtZW50ID0gcm9vdEVsZW1lbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5BQ1RJVkUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICQkJDEoYWN0aXZlRWxlbWVudCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlRXZlbnQpIHtcbiAgICAgICAgICAgICAgaWYgKGlucHV0Lmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSB8fCByb290RWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgfHwgaW5wdXQuY2xhc3NMaXN0LmNvbnRhaW5zKCdkaXNhYmxlZCcpIHx8IHJvb3RFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSAhdGhpcy5fZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgICAgICQkJDEoaW5wdXQpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpbnB1dC5mb2N1cygpO1xuICAgICAgICAgICAgYWRkQXJpYVByZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWRkQXJpYVByZXNzZWQpIHtcbiAgICAgICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1wcmVzc2VkJywgIXRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKENsYXNzTmFtZS5BQ1RJVkUpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlRXZlbnQpIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRvZ2dsZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgQnV0dG9uLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgQnV0dG9uKHRoaXMpO1xuICAgICAgICAgICAgJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY29uZmlnID09PSAndG9nZ2xlJykge1xuICAgICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIF9jcmVhdGVDbGFzcyhCdXR0b24sIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBCdXR0b247XG4gICAgfSgpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRV9DQVJST1QsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHZhciBidXR0b24gPSBldmVudC50YXJnZXQ7XG5cbiAgICAgIGlmICghJCQkMShidXR0b24pLmhhc0NsYXNzKENsYXNzTmFtZS5CVVRUT04pKSB7XG4gICAgICAgIGJ1dHRvbiA9ICQkJDEoYnV0dG9uKS5jbG9zZXN0KFNlbGVjdG9yLkJVVFRPTik7XG4gICAgICB9XG5cbiAgICAgIEJ1dHRvbi5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMShidXR0b24pLCAndG9nZ2xlJyk7XG4gICAgfSkub24oRXZlbnQuRk9DVVNfQkxVUl9EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEVfQ0FSUk9ULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIHZhciBidXR0b24gPSAkJCQxKGV2ZW50LnRhcmdldCkuY2xvc2VzdChTZWxlY3Rvci5CVVRUT04pWzBdO1xuICAgICAgJCQkMShidXR0b24pLnRvZ2dsZUNsYXNzKENsYXNzTmFtZS5GT0NVUywgL15mb2N1cyhpbik/JC8udGVzdChldmVudC50eXBlKSk7XG4gICAgfSk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgICAkJCQxLmZuW05BTUVdID0gQnV0dG9uLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IEJ1dHRvbjtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gQnV0dG9uLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBCdXR0b247XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogY2Fyb3VzZWwuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIENhcm91c2VsID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdjYXJvdXNlbCc7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5jYXJvdXNlbCc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBBUlJPV19MRUZUX0tFWUNPREUgPSAzNzsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgbGVmdCBhcnJvdyBrZXlcblxuICAgIHZhciBBUlJPV19SSUdIVF9LRVlDT0RFID0gMzk7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIHJpZ2h0IGFycm93IGtleVxuXG4gICAgdmFyIFRPVUNIRVZFTlRfQ09NUEFUX1dBSVQgPSA1MDA7IC8vIFRpbWUgZm9yIG1vdXNlIGNvbXBhdCBldmVudHMgdG8gZmlyZSBhZnRlciB0b3VjaFxuXG4gICAgdmFyIERlZmF1bHQgPSB7XG4gICAgICBpbnRlcnZhbDogNTAwMCxcbiAgICAgIGtleWJvYXJkOiB0cnVlLFxuICAgICAgc2xpZGU6IGZhbHNlLFxuICAgICAgcGF1c2U6ICdob3ZlcicsXG4gICAgICB3cmFwOiB0cnVlXG4gICAgfTtcbiAgICB2YXIgRGVmYXVsdFR5cGUgPSB7XG4gICAgICBpbnRlcnZhbDogJyhudW1iZXJ8Ym9vbGVhbiknLFxuICAgICAga2V5Ym9hcmQ6ICdib29sZWFuJyxcbiAgICAgIHNsaWRlOiAnKGJvb2xlYW58c3RyaW5nKScsXG4gICAgICBwYXVzZTogJyhzdHJpbmd8Ym9vbGVhbiknLFxuICAgICAgd3JhcDogJ2Jvb2xlYW4nXG4gICAgfTtcbiAgICB2YXIgRGlyZWN0aW9uID0ge1xuICAgICAgTkVYVDogJ25leHQnLFxuICAgICAgUFJFVjogJ3ByZXYnLFxuICAgICAgTEVGVDogJ2xlZnQnLFxuICAgICAgUklHSFQ6ICdyaWdodCdcbiAgICB9O1xuICAgIHZhciBFdmVudCA9IHtcbiAgICAgIFNMSURFOiBcInNsaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgICBTTElEOiBcInNsaWRcIiArIEVWRU5UX0tFWSxcbiAgICAgIEtFWURPV046IFwia2V5ZG93blwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VFTlRFUjogXCJtb3VzZWVudGVyXCIgKyBFVkVOVF9LRVksXG4gICAgICBNT1VTRUxFQVZFOiBcIm1vdXNlbGVhdmVcIiArIEVWRU5UX0tFWSxcbiAgICAgIFRPVUNIRU5EOiBcInRvdWNoZW5kXCIgKyBFVkVOVF9LRVksXG4gICAgICBMT0FEX0RBVEFfQVBJOiBcImxvYWRcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICAgIENMSUNLX0RBVEFfQVBJOiBcImNsaWNrXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVlcbiAgICB9O1xuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBDQVJPVVNFTDogJ2Nhcm91c2VsJyxcbiAgICAgIEFDVElWRTogJ2FjdGl2ZScsXG4gICAgICBTTElERTogJ3NsaWRlJyxcbiAgICAgIFJJR0hUOiAnY2Fyb3VzZWwtaXRlbS1yaWdodCcsXG4gICAgICBMRUZUOiAnY2Fyb3VzZWwtaXRlbS1sZWZ0JyxcbiAgICAgIE5FWFQ6ICdjYXJvdXNlbC1pdGVtLW5leHQnLFxuICAgICAgUFJFVjogJ2Nhcm91c2VsLWl0ZW0tcHJldicsXG4gICAgICBJVEVNOiAnY2Fyb3VzZWwtaXRlbSdcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIEFDVElWRTogJy5hY3RpdmUnLFxuICAgICAgQUNUSVZFX0lURU06ICcuYWN0aXZlLmNhcm91c2VsLWl0ZW0nLFxuICAgICAgSVRFTTogJy5jYXJvdXNlbC1pdGVtJyxcbiAgICAgIE5FWFRfUFJFVjogJy5jYXJvdXNlbC1pdGVtLW5leHQsIC5jYXJvdXNlbC1pdGVtLXByZXYnLFxuICAgICAgSU5ESUNBVE9SUzogJy5jYXJvdXNlbC1pbmRpY2F0b3JzJyxcbiAgICAgIERBVEFfU0xJREU6ICdbZGF0YS1zbGlkZV0sIFtkYXRhLXNsaWRlLXRvXScsXG4gICAgICBEQVRBX1JJREU6ICdbZGF0YS1yaWRlPVwiY2Fyb3VzZWxcIl0nXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgQ2Fyb3VzZWwgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBDYXJvdXNlbChlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgdGhpcy5faXRlbXMgPSBudWxsO1xuICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2FjdGl2ZUVsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9pc1BhdXNlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy50b3VjaFRpbWVvdXQgPSBudWxsO1xuICAgICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9ICQkJDEoZWxlbWVudClbMF07XG4gICAgICAgIHRoaXMuX2luZGljYXRvcnNFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLklORElDQVRPUlMpO1xuXG4gICAgICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gQ2Fyb3VzZWwucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by5uZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1NsaWRpbmcpIHtcbiAgICAgICAgICB0aGlzLl9zbGlkZShEaXJlY3Rpb24uTkVYVCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5uZXh0V2hlblZpc2libGUgPSBmdW5jdGlvbiBuZXh0V2hlblZpc2libGUoKSB7XG4gICAgICAgIC8vIERvbid0IGNhbGwgbmV4dCB3aGVuIHRoZSBwYWdlIGlzbid0IHZpc2libGVcbiAgICAgICAgLy8gb3IgdGhlIGNhcm91c2VsIG9yIGl0cyBwYXJlbnQgaXNuJ3QgdmlzaWJsZVxuICAgICAgICBpZiAoIWRvY3VtZW50LmhpZGRlbiAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmlzKCc6dmlzaWJsZScpICYmICQkJDEodGhpcy5fZWxlbWVudCkuY3NzKCd2aXNpYmlsaXR5JykgIT09ICdoaWRkZW4nKSB7XG4gICAgICAgICAgdGhpcy5uZXh0KCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5wcmV2ID0gZnVuY3Rpb24gcHJldigpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9pc1NsaWRpbmcpIHtcbiAgICAgICAgICB0aGlzLl9zbGlkZShEaXJlY3Rpb24uUFJFVik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5wYXVzZSA9IGZ1bmN0aW9uIHBhdXNlKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgICB0aGlzLl9pc1BhdXNlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLk5FWFRfUFJFVikpIHtcbiAgICAgICAgICBVdGlsLnRyaWdnZXJUcmFuc2l0aW9uRW5kKHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICAgIHRoaXMuY3ljbGUodHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKTtcbiAgICAgICAgdGhpcy5faW50ZXJ2YWwgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmN5Y2xlID0gZnVuY3Rpb24gY3ljbGUoZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICAgIHRoaXMuX2lzUGF1c2VkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5faW50ZXJ2YWwpIHtcbiAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKTtcbiAgICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmludGVydmFsICYmICF0aGlzLl9pc1BhdXNlZCkge1xuICAgICAgICAgIHRoaXMuX2ludGVydmFsID0gc2V0SW50ZXJ2YWwoKGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZSA/IHRoaXMubmV4dFdoZW5WaXNpYmxlIDogdGhpcy5uZXh0KS5iaW5kKHRoaXMpLCB0aGlzLl9jb25maWcuaW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8udG8gPSBmdW5jdGlvbiB0byhpbmRleCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIHRoaXMuX2FjdGl2ZUVsZW1lbnQgPSB0aGlzLl9lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuQUNUSVZFX0lURU0pO1xuXG4gICAgICAgIHZhciBhY3RpdmVJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleCh0aGlzLl9hY3RpdmVFbGVtZW50KTtcblxuICAgICAgICBpZiAoaW5kZXggPiB0aGlzLl9pdGVtcy5sZW5ndGggLSAxIHx8IGluZGV4IDwgMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9pc1NsaWRpbmcpIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uZShFdmVudC5TTElELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMudG8oaW5kZXgpO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhY3RpdmVJbmRleCA9PT0gaW5kZXgpIHtcbiAgICAgICAgICB0aGlzLnBhdXNlKCk7XG4gICAgICAgICAgdGhpcy5jeWNsZSgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkaXJlY3Rpb24gPSBpbmRleCA+IGFjdGl2ZUluZGV4ID8gRGlyZWN0aW9uLk5FWFQgOiBEaXJlY3Rpb24uUFJFVjtcblxuICAgICAgICB0aGlzLl9zbGlkZShkaXJlY3Rpb24sIHRoaXMuX2l0ZW1zW2luZGV4XSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub2ZmKEVWRU5UX0tFWSk7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgIHRoaXMuX2l0ZW1zID0gbnVsbDtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2ludGVydmFsID0gbnVsbDtcbiAgICAgICAgdGhpcy5faXNQYXVzZWQgPSBudWxsO1xuICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBudWxsO1xuICAgICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5faW5kaWNhdG9yc0VsZW1lbnQgPSBudWxsO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0Q29uZmlnID0gZnVuY3Rpb24gX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgRGVmYXVsdCwgY29uZmlnKTtcbiAgICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCBEZWZhdWx0VHlwZSk7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2FkZEV2ZW50TGlzdGVuZXJzID0gZnVuY3Rpb24gX2FkZEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmtleWJvYXJkKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5LRVlET1dOLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczIuX2tleWRvd24oZXZlbnQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2NvbmZpZy5wYXVzZSA9PT0gJ2hvdmVyJykge1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuTU9VU0VFTlRFUiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMyLnBhdXNlKGV2ZW50KTtcbiAgICAgICAgICB9KS5vbihFdmVudC5NT1VTRUxFQVZFLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczIuY3ljbGUoZXZlbnQpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKCdvbnRvdWNoc3RhcnQnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICAgICAgLy8gSWYgaXQncyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlLCBtb3VzZWVudGVyL2xlYXZlIGFyZSBmaXJlZCBhc1xuICAgICAgICAgICAgLy8gcGFydCBvZiB0aGUgbW91c2UgY29tcGF0aWJpbGl0eSBldmVudHMgb24gZmlyc3QgdGFwIC0gdGhlIGNhcm91c2VsXG4gICAgICAgICAgICAvLyB3b3VsZCBzdG9wIGN5Y2xpbmcgdW50aWwgdXNlciB0YXBwZWQgb3V0IG9mIGl0O1xuICAgICAgICAgICAgLy8gaGVyZSwgd2UgbGlzdGVuIGZvciB0b3VjaGVuZCwgZXhwbGljaXRseSBwYXVzZSB0aGUgY2Fyb3VzZWxcbiAgICAgICAgICAgIC8vIChhcyBpZiBpdCdzIHRoZSBzZWNvbmQgdGltZSB3ZSB0YXAgb24gaXQsIG1vdXNlZW50ZXIgY29tcGF0IGV2ZW50XG4gICAgICAgICAgICAvLyBpcyBOT1QgZmlyZWQpIGFuZCBhZnRlciBhIHRpbWVvdXQgKHRvIGFsbG93IGZvciBtb3VzZSBjb21wYXRpYmlsaXR5XG4gICAgICAgICAgICAvLyBldmVudHMgdG8gZmlyZSkgd2UgZXhwbGljaXRseSByZXN0YXJ0IGN5Y2xpbmdcbiAgICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuVE9VQ0hFTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgX3RoaXMyLnBhdXNlKCk7XG5cbiAgICAgICAgICAgICAgaWYgKF90aGlzMi50b3VjaFRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoX3RoaXMyLnRvdWNoVGltZW91dCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBfdGhpczIudG91Y2hUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMyLmN5Y2xlKGV2ZW50KTtcbiAgICAgICAgICAgICAgfSwgVE9VQ0hFVkVOVF9DT01QQVRfV0FJVCArIF90aGlzMi5fY29uZmlnLmludGVydmFsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9rZXlkb3duID0gZnVuY3Rpb24gX2tleWRvd24oZXZlbnQpIHtcbiAgICAgICAgaWYgKC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZXZlbnQudGFyZ2V0LnRhZ05hbWUpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChldmVudC53aGljaCkge1xuICAgICAgICAgIGNhc2UgQVJST1dfTEVGVF9LRVlDT0RFOlxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHRoaXMucHJldigpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlIEFSUk9XX1JJR0hUX0tFWUNPREU6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5uZXh0KCk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0SXRlbUluZGV4ID0gZnVuY3Rpb24gX2dldEl0ZW1JbmRleChlbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX2l0ZW1zID0gZWxlbWVudCAmJiBlbGVtZW50LnBhcmVudE5vZGUgPyBbXS5zbGljZS5jYWxsKGVsZW1lbnQucGFyZW50Tm9kZS5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLklURU0pKSA6IFtdO1xuICAgICAgICByZXR1cm4gdGhpcy5faXRlbXMuaW5kZXhPZihlbGVtZW50KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0SXRlbUJ5RGlyZWN0aW9uID0gZnVuY3Rpb24gX2dldEl0ZW1CeURpcmVjdGlvbihkaXJlY3Rpb24sIGFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGlzTmV4dERpcmVjdGlvbiA9IGRpcmVjdGlvbiA9PT0gRGlyZWN0aW9uLk5FWFQ7XG4gICAgICAgIHZhciBpc1ByZXZEaXJlY3Rpb24gPSBkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5QUkVWO1xuXG4gICAgICAgIHZhciBhY3RpdmVJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleChhY3RpdmVFbGVtZW50KTtcblxuICAgICAgICB2YXIgbGFzdEl0ZW1JbmRleCA9IHRoaXMuX2l0ZW1zLmxlbmd0aCAtIDE7XG4gICAgICAgIHZhciBpc0dvaW5nVG9XcmFwID0gaXNQcmV2RGlyZWN0aW9uICYmIGFjdGl2ZUluZGV4ID09PSAwIHx8IGlzTmV4dERpcmVjdGlvbiAmJiBhY3RpdmVJbmRleCA9PT0gbGFzdEl0ZW1JbmRleDtcblxuICAgICAgICBpZiAoaXNHb2luZ1RvV3JhcCAmJiAhdGhpcy5fY29uZmlnLndyYXApIHtcbiAgICAgICAgICByZXR1cm4gYWN0aXZlRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkZWx0YSA9IGRpcmVjdGlvbiA9PT0gRGlyZWN0aW9uLlBSRVYgPyAtMSA6IDE7XG4gICAgICAgIHZhciBpdGVtSW5kZXggPSAoYWN0aXZlSW5kZXggKyBkZWx0YSkgJSB0aGlzLl9pdGVtcy5sZW5ndGg7XG4gICAgICAgIHJldHVybiBpdGVtSW5kZXggPT09IC0xID8gdGhpcy5faXRlbXNbdGhpcy5faXRlbXMubGVuZ3RoIC0gMV0gOiB0aGlzLl9pdGVtc1tpdGVtSW5kZXhdO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl90cmlnZ2VyU2xpZGVFdmVudCA9IGZ1bmN0aW9uIF90cmlnZ2VyU2xpZGVFdmVudChyZWxhdGVkVGFyZ2V0LCBldmVudERpcmVjdGlvbk5hbWUpIHtcbiAgICAgICAgdmFyIHRhcmdldEluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KHJlbGF0ZWRUYXJnZXQpO1xuXG4gICAgICAgIHZhciBmcm9tSW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgodGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKFNlbGVjdG9yLkFDVElWRV9JVEVNKSk7XG5cbiAgICAgICAgdmFyIHNsaWRlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNMSURFLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldCxcbiAgICAgICAgICBkaXJlY3Rpb246IGV2ZW50RGlyZWN0aW9uTmFtZSxcbiAgICAgICAgICBmcm9tOiBmcm9tSW5kZXgsXG4gICAgICAgICAgdG86IHRhcmdldEluZGV4XG4gICAgICAgIH0pO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc2xpZGVFdmVudCk7XG4gICAgICAgIHJldHVybiBzbGlkZUV2ZW50O1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zZXRBY3RpdmVJbmRpY2F0b3JFbGVtZW50ID0gZnVuY3Rpb24gX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgICBpZiAodGhpcy5faW5kaWNhdG9yc0VsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgaW5kaWNhdG9ycyA9IFtdLnNsaWNlLmNhbGwodGhpcy5faW5kaWNhdG9yc0VsZW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5BQ1RJVkUpKTtcbiAgICAgICAgICAkJCQxKGluZGljYXRvcnMpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuXG4gICAgICAgICAgdmFyIG5leHRJbmRpY2F0b3IgPSB0aGlzLl9pbmRpY2F0b3JzRWxlbWVudC5jaGlsZHJlblt0aGlzLl9nZXRJdGVtSW5kZXgoZWxlbWVudCldO1xuXG4gICAgICAgICAgaWYgKG5leHRJbmRpY2F0b3IpIHtcbiAgICAgICAgICAgICQkJDEobmV4dEluZGljYXRvcikuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3NsaWRlID0gZnVuY3Rpb24gX3NsaWRlKGRpcmVjdGlvbiwgZWxlbWVudCkge1xuICAgICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgICB2YXIgYWN0aXZlRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5BQ1RJVkVfSVRFTSk7XG5cbiAgICAgICAgdmFyIGFjdGl2ZUVsZW1lbnRJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleChhY3RpdmVFbGVtZW50KTtcblxuICAgICAgICB2YXIgbmV4dEVsZW1lbnQgPSBlbGVtZW50IHx8IGFjdGl2ZUVsZW1lbnQgJiYgdGhpcy5fZ2V0SXRlbUJ5RGlyZWN0aW9uKGRpcmVjdGlvbiwgYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgdmFyIG5leHRFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgobmV4dEVsZW1lbnQpO1xuXG4gICAgICAgIHZhciBpc0N5Y2xpbmcgPSBCb29sZWFuKHRoaXMuX2ludGVydmFsKTtcbiAgICAgICAgdmFyIGRpcmVjdGlvbmFsQ2xhc3NOYW1lO1xuICAgICAgICB2YXIgb3JkZXJDbGFzc05hbWU7XG4gICAgICAgIHZhciBldmVudERpcmVjdGlvbk5hbWU7XG5cbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gRGlyZWN0aW9uLk5FWFQpIHtcbiAgICAgICAgICBkaXJlY3Rpb25hbENsYXNzTmFtZSA9IENsYXNzTmFtZS5MRUZUO1xuICAgICAgICAgIG9yZGVyQ2xhc3NOYW1lID0gQ2xhc3NOYW1lLk5FWFQ7XG4gICAgICAgICAgZXZlbnREaXJlY3Rpb25OYW1lID0gRGlyZWN0aW9uLkxFRlQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGlyZWN0aW9uYWxDbGFzc05hbWUgPSBDbGFzc05hbWUuUklHSFQ7XG4gICAgICAgICAgb3JkZXJDbGFzc05hbWUgPSBDbGFzc05hbWUuUFJFVjtcbiAgICAgICAgICBldmVudERpcmVjdGlvbk5hbWUgPSBEaXJlY3Rpb24uUklHSFQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmV4dEVsZW1lbnQgJiYgJCQkMShuZXh0RWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSkpIHtcbiAgICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2xpZGVFdmVudCA9IHRoaXMuX3RyaWdnZXJTbGlkZUV2ZW50KG5leHRFbGVtZW50LCBldmVudERpcmVjdGlvbk5hbWUpO1xuXG4gICAgICAgIGlmIChzbGlkZUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFhY3RpdmVFbGVtZW50IHx8ICFuZXh0RWxlbWVudCkge1xuICAgICAgICAgIC8vIFNvbWUgd2VpcmRuZXNzIGlzIGhhcHBlbmluZywgc28gd2UgYmFpbFxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2lzU2xpZGluZyA9IHRydWU7XG5cbiAgICAgICAgaWYgKGlzQ3ljbGluZykge1xuICAgICAgICAgIHRoaXMucGF1c2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQobmV4dEVsZW1lbnQpO1xuXG4gICAgICAgIHZhciBzbGlkRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNMSUQsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBuZXh0RWxlbWVudCxcbiAgICAgICAgICBkaXJlY3Rpb246IGV2ZW50RGlyZWN0aW9uTmFtZSxcbiAgICAgICAgICBmcm9tOiBhY3RpdmVFbGVtZW50SW5kZXgsXG4gICAgICAgICAgdG86IG5leHRFbGVtZW50SW5kZXhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNMSURFKSkge1xuICAgICAgICAgICQkJDEobmV4dEVsZW1lbnQpLmFkZENsYXNzKG9yZGVyQ2xhc3NOYW1lKTtcbiAgICAgICAgICBVdGlsLnJlZmxvdyhuZXh0RWxlbWVudCk7XG4gICAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5hZGRDbGFzcyhkaXJlY3Rpb25hbENsYXNzTmFtZSk7XG4gICAgICAgICAgJCQkMShuZXh0RWxlbWVudCkuYWRkQ2xhc3MoZGlyZWN0aW9uYWxDbGFzc05hbWUpO1xuICAgICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KGFjdGl2ZUVsZW1lbnQpO1xuICAgICAgICAgICQkJDEoYWN0aXZlRWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICQkJDEobmV4dEVsZW1lbnQpLnJlbW92ZUNsYXNzKGRpcmVjdGlvbmFsQ2xhc3NOYW1lICsgXCIgXCIgKyBvcmRlckNsYXNzTmFtZSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgICAkJCQxKGFjdGl2ZUVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUgKyBcIiBcIiArIG9yZGVyQ2xhc3NOYW1lICsgXCIgXCIgKyBkaXJlY3Rpb25hbENsYXNzTmFtZSk7XG4gICAgICAgICAgICBfdGhpczMuX2lzU2xpZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHJldHVybiAkJCQxKF90aGlzMy5fZWxlbWVudCkudHJpZ2dlcihzbGlkRXZlbnQpO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgfSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAkJCQxKGFjdGl2ZUVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgICQkJDEobmV4dEVsZW1lbnQpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAgIHRoaXMuX2lzU2xpZGluZyA9IGZhbHNlO1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzbGlkRXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzQ3ljbGluZykge1xuICAgICAgICAgIHRoaXMuY3ljbGUoKTtcbiAgICAgICAgfVxuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciBkYXRhID0gJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICAgIHZhciBfY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgRGVmYXVsdCwgJCQkMSh0aGlzKS5kYXRhKCkpO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBfY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgX2NvbmZpZywgY29uZmlnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgYWN0aW9uID0gdHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycgPyBjb25maWcgOiBfY29uZmlnLnNsaWRlO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IENhcm91c2VsKHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICAgJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGRhdGEudG8oY29uZmlnKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbYWN0aW9uXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBhY3Rpb24gKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbYWN0aW9uXSgpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoX2NvbmZpZy5pbnRlcnZhbCkge1xuICAgICAgICAgICAgZGF0YS5wYXVzZSgpO1xuICAgICAgICAgICAgZGF0YS5jeWNsZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBDYXJvdXNlbC5fZGF0YUFwaUNsaWNrSGFuZGxlciA9IGZ1bmN0aW9uIF9kYXRhQXBpQ2xpY2tIYW5kbGVyKGV2ZW50KSB7XG4gICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0aGlzKTtcblxuICAgICAgICBpZiAoIXNlbGVjdG9yKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRhcmdldCA9ICQkJDEoc2VsZWN0b3IpWzBdO1xuXG4gICAgICAgIGlmICghdGFyZ2V0IHx8ICEkJCQxKHRhcmdldCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkNBUk9VU0VMKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCAkJCQxKHRhcmdldCkuZGF0YSgpLCAkJCQxKHRoaXMpLmRhdGEoKSk7XG5cbiAgICAgICAgdmFyIHNsaWRlSW5kZXggPSB0aGlzLmdldEF0dHJpYnV0ZSgnZGF0YS1zbGlkZS10bycpO1xuXG4gICAgICAgIGlmIChzbGlkZUluZGV4KSB7XG4gICAgICAgICAgY29uZmlnLmludGVydmFsID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBDYXJvdXNlbC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMSh0YXJnZXQpLCBjb25maWcpO1xuXG4gICAgICAgIGlmIChzbGlkZUluZGV4KSB7XG4gICAgICAgICAgJCQkMSh0YXJnZXQpLmRhdGEoREFUQV9LRVkpLnRvKHNsaWRlSW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH07XG5cbiAgICAgIF9jcmVhdGVDbGFzcyhDYXJvdXNlbCwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIENhcm91c2VsO1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9TTElERSwgQ2Fyb3VzZWwuX2RhdGFBcGlDbGlja0hhbmRsZXIpO1xuICAgICQkJDEod2luZG93KS5vbihFdmVudC5MT0FEX0RBVEFfQVBJLCBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY2Fyb3VzZWxzID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLkRBVEFfUklERSkpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gY2Fyb3VzZWxzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciAkY2Fyb3VzZWwgPSAkJCQxKGNhcm91c2Vsc1tpXSk7XG5cbiAgICAgICAgQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZS5jYWxsKCRjYXJvdXNlbCwgJGNhcm91c2VsLmRhdGEoKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogalF1ZXJ5XG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgICAkJCQxLmZuW05BTUVdID0gQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gQ2Fyb3VzZWw7XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIENhcm91c2VsLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgfTtcblxuICAgIHJldHVybiBDYXJvdXNlbDtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBjb2xsYXBzZS5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICB2YXIgQ29sbGFwc2UgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ2NvbGxhcHNlJztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLmNvbGxhcHNlJztcbiAgICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIERlZmF1bHQgPSB7XG4gICAgICB0b2dnbGU6IHRydWUsXG4gICAgICBwYXJlbnQ6ICcnXG4gICAgfTtcbiAgICB2YXIgRGVmYXVsdFR5cGUgPSB7XG4gICAgICB0b2dnbGU6ICdib29sZWFuJyxcbiAgICAgIHBhcmVudDogJyhzdHJpbmd8ZWxlbWVudCknXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIENMSUNLX0RBVEFfQVBJOiBcImNsaWNrXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVlcbiAgICB9O1xuICAgIHZhciBDbGFzc05hbWUgPSB7XG4gICAgICBTSE9XOiAnc2hvdycsXG4gICAgICBDT0xMQVBTRTogJ2NvbGxhcHNlJyxcbiAgICAgIENPTExBUFNJTkc6ICdjb2xsYXBzaW5nJyxcbiAgICAgIENPTExBUFNFRDogJ2NvbGxhcHNlZCdcbiAgICB9O1xuICAgIHZhciBEaW1lbnNpb24gPSB7XG4gICAgICBXSURUSDogJ3dpZHRoJyxcbiAgICAgIEhFSUdIVDogJ2hlaWdodCdcbiAgICB9O1xuICAgIHZhciBTZWxlY3RvciA9IHtcbiAgICAgIEFDVElWRVM6ICcuc2hvdywgLmNvbGxhcHNpbmcnLFxuICAgICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXSdcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBDb2xsYXBzZSA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIENvbGxhcHNlKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLl90cmlnZ2VyQXJyYXkgPSAkJCQxLm1ha2VBcnJheShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFwiW2RhdGEtdG9nZ2xlPVxcXCJjb2xsYXBzZVxcXCJdW2hyZWY9XFxcIiNcIiArIGVsZW1lbnQuaWQgKyBcIlxcXCJdLFwiICsgKFwiW2RhdGEtdG9nZ2xlPVxcXCJjb2xsYXBzZVxcXCJdW2RhdGEtdGFyZ2V0PVxcXCIjXCIgKyBlbGVtZW50LmlkICsgXCJcXFwiXVwiKSkpO1xuICAgICAgICB2YXIgdG9nZ2xlTGlzdCA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5EQVRBX1RPR0dMRSkpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSB0b2dnbGVMaXN0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgdmFyIGVsZW0gPSB0b2dnbGVMaXN0W2ldO1xuICAgICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtKTtcbiAgICAgICAgICB2YXIgZmlsdGVyRWxlbWVudCA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpLmZpbHRlcihmdW5jdGlvbiAoZm91bmRFbGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gZm91bmRFbGVtID09PSBlbGVtZW50O1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHNlbGVjdG9yICE9PSBudWxsICYmIGZpbHRlckVsZW1lbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5fc2VsZWN0b3IgPSBzZWxlY3RvcjtcblxuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckFycmF5LnB1c2goZWxlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcGFyZW50ID0gdGhpcy5fY29uZmlnLnBhcmVudCA/IHRoaXMuX2dldFBhcmVudCgpIDogbnVsbDtcblxuICAgICAgICBpZiAoIXRoaXMuX2NvbmZpZy5wYXJlbnQpIHtcbiAgICAgICAgICB0aGlzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3ModGhpcy5fZWxlbWVudCwgdGhpcy5fdHJpZ2dlckFycmF5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9jb25maWcudG9nZ2xlKSB7XG4gICAgICAgICAgdGhpcy50b2dnbGUoKTtcbiAgICAgICAgfVxuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IENvbGxhcHNlLnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgICBpZiAoJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNob3coKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNob3cgPSBmdW5jdGlvbiBzaG93KCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9pc1RyYW5zaXRpb25pbmcgfHwgJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWN0aXZlcztcbiAgICAgICAgdmFyIGFjdGl2ZXNEYXRhO1xuXG4gICAgICAgIGlmICh0aGlzLl9wYXJlbnQpIHtcbiAgICAgICAgICBhY3RpdmVzID0gW10uc2xpY2UuY2FsbCh0aGlzLl9wYXJlbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5BQ1RJVkVTKSkuZmlsdGVyKGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbS5nZXRBdHRyaWJ1dGUoJ2RhdGEtcGFyZW50JykgPT09IF90aGlzLl9jb25maWcucGFyZW50O1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKGFjdGl2ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBhY3RpdmVzID0gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWN0aXZlcykge1xuICAgICAgICAgIGFjdGl2ZXNEYXRhID0gJCQkMShhY3RpdmVzKS5ub3QodGhpcy5fc2VsZWN0b3IpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgaWYgKGFjdGl2ZXNEYXRhICYmIGFjdGl2ZXNEYXRhLl9pc1RyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3RhcnRFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPVyk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzdGFydEV2ZW50KTtcblxuICAgICAgICBpZiAoc3RhcnRFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhY3RpdmVzKSB7XG4gICAgICAgICAgQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEoYWN0aXZlcykubm90KHRoaXMuX3NlbGVjdG9yKSwgJ2hpZGUnKTtcblxuICAgICAgICAgIGlmICghYWN0aXZlc0RhdGEpIHtcbiAgICAgICAgICAgICQkJDEoYWN0aXZlcykuZGF0YShEQVRBX0tFWSwgbnVsbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRpbWVuc2lvbiA9IHRoaXMuX2dldERpbWVuc2lvbigpO1xuXG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS5hZGRDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORyk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbZGltZW5zaW9uXSA9IDA7XG5cbiAgICAgICAgaWYgKHRoaXMuX3RyaWdnZXJBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX3RyaWdnZXJBcnJheSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFRCkuYXR0cignYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRUcmFuc2l0aW9uaW5nKHRydWUpO1xuXG4gICAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTSU5HKS5hZGRDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0UpLmFkZENsYXNzKENsYXNzTmFtZS5TSE9XKTtcbiAgICAgICAgICBfdGhpcy5fZWxlbWVudC5zdHlsZVtkaW1lbnNpb25dID0gJyc7XG5cbiAgICAgICAgICBfdGhpcy5zZXRUcmFuc2l0aW9uaW5nKGZhbHNlKTtcblxuICAgICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLnRyaWdnZXIoRXZlbnQuU0hPV04pO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBjYXBpdGFsaXplZERpbWVuc2lvbiA9IGRpbWVuc2lvblswXS50b1VwcGVyQ2FzZSgpICsgZGltZW5zaW9uLnNsaWNlKDEpO1xuICAgICAgICB2YXIgc2Nyb2xsU2l6ZSA9IFwic2Nyb2xsXCIgKyBjYXBpdGFsaXplZERpbWVuc2lvbjtcbiAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNvbXBsZXRlKS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSB0aGlzLl9lbGVtZW50W3Njcm9sbFNpemVdICsgXCJweFwiO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmhpZGUgPSBmdW5jdGlvbiBoaWRlKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8ICEkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzdGFydEV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5ISURFKTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHN0YXJ0RXZlbnQpO1xuXG4gICAgICAgIGlmIChzdGFydEV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRpbWVuc2lvbiA9IHRoaXMuX2dldERpbWVuc2lvbigpO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbZGltZW5zaW9uXSA9IHRoaXMuX2VsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClbZGltZW5zaW9uXSArIFwicHhcIjtcbiAgICAgICAgVXRpbC5yZWZsb3codGhpcy5fZWxlbWVudCk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNJTkcpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTRSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuICAgICAgICB2YXIgdHJpZ2dlckFycmF5TGVuZ3RoID0gdGhpcy5fdHJpZ2dlckFycmF5Lmxlbmd0aDtcblxuICAgICAgICBpZiAodHJpZ2dlckFycmF5TGVuZ3RoID4gMCkge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJpZ2dlckFycmF5TGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmlnZ2VyID0gdGhpcy5fdHJpZ2dlckFycmF5W2ldO1xuICAgICAgICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRyaWdnZXIpO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0b3IgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgdmFyICRlbGVtID0gJCQkMShbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpKSk7XG5cbiAgICAgICAgICAgICAgaWYgKCEkZWxlbS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgICAgICAgICAkJCQxKHRyaWdnZXIpLmFkZENsYXNzKENsYXNzTmFtZS5DT0xMQVBTRUQpLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFRyYW5zaXRpb25pbmcodHJ1ZSk7XG5cbiAgICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgICAgICAgX3RoaXMyLnNldFRyYW5zaXRpb25pbmcoZmFsc2UpO1xuXG4gICAgICAgICAgJCQkMShfdGhpczIuX2VsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTSU5HKS5hZGRDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0UpLnRyaWdnZXIoRXZlbnQuSElEREVOKTtcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAnJztcbiAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNvbXBsZXRlKS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNldFRyYW5zaXRpb25pbmcgPSBmdW5jdGlvbiBzZXRUcmFuc2l0aW9uaW5nKGlzVHJhbnNpdGlvbmluZykge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBpc1RyYW5zaXRpb25pbmc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IG51bGw7XG4gICAgICAgIHRoaXMuX3BhcmVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl90cmlnZ2VyQXJyYXkgPSBudWxsO1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBudWxsO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0Q29uZmlnID0gZnVuY3Rpb24gX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnID0gX29iamVjdFNwcmVhZCh7fSwgRGVmYXVsdCwgY29uZmlnKTtcbiAgICAgICAgY29uZmlnLnRvZ2dsZSA9IEJvb2xlYW4oY29uZmlnLnRvZ2dsZSk7IC8vIENvZXJjZSBzdHJpbmcgdmFsdWVzXG5cbiAgICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCBEZWZhdWx0VHlwZSk7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldERpbWVuc2lvbiA9IGZ1bmN0aW9uIF9nZXREaW1lbnNpb24oKSB7XG4gICAgICAgIHZhciBoYXNXaWR0aCA9ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoRGltZW5zaW9uLldJRFRIKTtcbiAgICAgICAgcmV0dXJuIGhhc1dpZHRoID8gRGltZW5zaW9uLldJRFRIIDogRGltZW5zaW9uLkhFSUdIVDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0UGFyZW50ID0gZnVuY3Rpb24gX2dldFBhcmVudCgpIHtcbiAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIHBhcmVudCA9IG51bGw7XG5cbiAgICAgICAgaWYgKFV0aWwuaXNFbGVtZW50KHRoaXMuX2NvbmZpZy5wYXJlbnQpKSB7XG4gICAgICAgICAgcGFyZW50ID0gdGhpcy5fY29uZmlnLnBhcmVudDsgLy8gSXQncyBhIGpRdWVyeSBvYmplY3RcblxuICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fY29uZmlnLnBhcmVudC5qcXVlcnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBwYXJlbnQgPSB0aGlzLl9jb25maWcucGFyZW50WzBdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXJlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuX2NvbmZpZy5wYXJlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNlbGVjdG9yID0gXCJbZGF0YS10b2dnbGU9XFxcImNvbGxhcHNlXFxcIl1bZGF0YS1wYXJlbnQ9XFxcIlwiICsgdGhpcy5fY29uZmlnLnBhcmVudCArIFwiXFxcIl1cIjtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gW10uc2xpY2UuY2FsbChwYXJlbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuICAgICAgICAkJCQxKGNoaWxkcmVuKS5lYWNoKGZ1bmN0aW9uIChpLCBlbGVtZW50KSB7XG4gICAgICAgICAgX3RoaXMzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoQ29sbGFwc2UuX2dldFRhcmdldEZyb21FbGVtZW50KGVsZW1lbnQpLCBbZWxlbWVudF0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzID0gZnVuY3Rpb24gX2FkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyhlbGVtZW50LCB0cmlnZ2VyQXJyYXkpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgaXNPcGVuID0gJCQkMShlbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgICBpZiAodHJpZ2dlckFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgICAgJCQkMSh0cmlnZ2VyQXJyYXkpLnRvZ2dsZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTRUQsICFpc09wZW4pLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBpc09wZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgQ29sbGFwc2UuX2dldFRhcmdldEZyb21FbGVtZW50ID0gZnVuY3Rpb24gX2dldFRhcmdldEZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICByZXR1cm4gc2VsZWN0b3IgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKSA6IG51bGw7XG4gICAgICB9O1xuXG4gICAgICBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyICR0aGlzID0gJCQkMSh0aGlzKTtcbiAgICAgICAgICB2YXIgZGF0YSA9ICR0aGlzLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgICAgdmFyIF9jb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCBEZWZhdWx0LCAkdGhpcy5kYXRhKCksIHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZyA/IGNvbmZpZyA6IHt9KTtcblxuICAgICAgICAgIGlmICghZGF0YSAmJiBfY29uZmlnLnRvZ2dsZSAmJiAvc2hvd3xoaWRlLy50ZXN0KGNvbmZpZykpIHtcbiAgICAgICAgICAgIF9jb25maWcudG9nZ2xlID0gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IENvbGxhcHNlKHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICAgJHRoaXMuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoQ29sbGFwc2UsIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJEZWZhdWx0XCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBDb2xsYXBzZTtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfVE9HR0xFLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIC8vIHByZXZlbnREZWZhdWx0IG9ubHkgZm9yIDxhPiBlbGVtZW50cyAod2hpY2ggY2hhbmdlIHRoZSBVUkwpIG5vdCBpbnNpZGUgdGhlIGNvbGxhcHNpYmxlIGVsZW1lbnRcbiAgICAgIGlmIChldmVudC5jdXJyZW50VGFyZ2V0LnRhZ05hbWUgPT09ICdBJykge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuXG4gICAgICB2YXIgJHRyaWdnZXIgPSAkJCQxKHRoaXMpO1xuICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRoaXMpO1xuICAgICAgdmFyIHNlbGVjdG9ycyA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpO1xuICAgICAgJCQkMShzZWxlY3RvcnMpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRhcmdldCA9ICQkJDEodGhpcyk7XG4gICAgICAgIHZhciBkYXRhID0gJHRhcmdldC5kYXRhKERBVEFfS0VZKTtcbiAgICAgICAgdmFyIGNvbmZpZyA9IGRhdGEgPyAndG9nZ2xlJyA6ICR0cmlnZ2VyLmRhdGEoKTtcblxuICAgICAgICBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgY29uZmlnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IENvbGxhcHNlLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IENvbGxhcHNlO1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ29sbGFwc2U7XG4gIH0oJCk7XG5cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIEJvb3RzdHJhcCAodjQuMS4zKTogZHJvcGRvd24uanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIERyb3Bkb3duID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDb25zdGFudHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cbiAgICB2YXIgTkFNRSA9ICdkcm9wZG93bic7XG4gICAgdmFyIFZFUlNJT04gPSAnNC4xLjMnO1xuICAgIHZhciBEQVRBX0tFWSA9ICdicy5kcm9wZG93bic7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBFU0NBUEVfS0VZQ09ERSA9IDI3OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciBFc2NhcGUgKEVzYykga2V5XG5cbiAgICB2YXIgU1BBQ0VfS0VZQ09ERSA9IDMyOyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciBzcGFjZSBrZXlcblxuICAgIHZhciBUQUJfS0VZQ09ERSA9IDk7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIHRhYiBrZXlcblxuICAgIHZhciBBUlJPV19VUF9LRVlDT0RFID0gMzg7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIHVwIGFycm93IGtleVxuXG4gICAgdmFyIEFSUk9XX0RPV05fS0VZQ09ERSA9IDQwOyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciBkb3duIGFycm93IGtleVxuXG4gICAgdmFyIFJJR0hUX01PVVNFX0JVVFRPTl9XSElDSCA9IDM7IC8vIE1vdXNlRXZlbnQud2hpY2ggdmFsdWUgZm9yIHRoZSByaWdodCBidXR0b24gKGFzc3VtaW5nIGEgcmlnaHQtaGFuZGVkIG1vdXNlKVxuXG4gICAgdmFyIFJFR0VYUF9LRVlET1dOID0gbmV3IFJlZ0V4cChBUlJPV19VUF9LRVlDT0RFICsgXCJ8XCIgKyBBUlJPV19ET1dOX0tFWUNPREUgKyBcInxcIiArIEVTQ0FQRV9LRVlDT0RFKTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIENMSUNLOiBcImNsaWNrXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZLFxuICAgICAgS0VZRE9XTl9EQVRBX0FQSTogXCJrZXlkb3duXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgICBLRVlVUF9EQVRBX0FQSTogXCJrZXl1cFwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gICAgfTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgRElTQUJMRUQ6ICdkaXNhYmxlZCcsXG4gICAgICBTSE9XOiAnc2hvdycsXG4gICAgICBEUk9QVVA6ICdkcm9wdXAnLFxuICAgICAgRFJPUFJJR0hUOiAnZHJvcHJpZ2h0JyxcbiAgICAgIERST1BMRUZUOiAnZHJvcGxlZnQnLFxuICAgICAgTUVOVVJJR0hUOiAnZHJvcGRvd24tbWVudS1yaWdodCcsXG4gICAgICBNRU5VTEVGVDogJ2Ryb3Bkb3duLW1lbnUtbGVmdCcsXG4gICAgICBQT1NJVElPTl9TVEFUSUM6ICdwb3NpdGlvbi1zdGF0aWMnXG4gICAgfTtcbiAgICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgICBEQVRBX1RPR0dMRTogJ1tkYXRhLXRvZ2dsZT1cImRyb3Bkb3duXCJdJyxcbiAgICAgIEZPUk1fQ0hJTEQ6ICcuZHJvcGRvd24gZm9ybScsXG4gICAgICBNRU5VOiAnLmRyb3Bkb3duLW1lbnUnLFxuICAgICAgTkFWQkFSX05BVjogJy5uYXZiYXItbmF2JyxcbiAgICAgIFZJU0lCTEVfSVRFTVM6ICcuZHJvcGRvd24tbWVudSAuZHJvcGRvd24taXRlbTpub3QoLmRpc2FibGVkKTpub3QoOmRpc2FibGVkKSdcbiAgICB9O1xuICAgIHZhciBBdHRhY2htZW50TWFwID0ge1xuICAgICAgVE9QOiAndG9wLXN0YXJ0JyxcbiAgICAgIFRPUEVORDogJ3RvcC1lbmQnLFxuICAgICAgQk9UVE9NOiAnYm90dG9tLXN0YXJ0JyxcbiAgICAgIEJPVFRPTUVORDogJ2JvdHRvbS1lbmQnLFxuICAgICAgUklHSFQ6ICdyaWdodC1zdGFydCcsXG4gICAgICBSSUdIVEVORDogJ3JpZ2h0LWVuZCcsXG4gICAgICBMRUZUOiAnbGVmdC1zdGFydCcsXG4gICAgICBMRUZURU5EOiAnbGVmdC1lbmQnXG4gICAgfTtcbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgIG9mZnNldDogMCxcbiAgICAgIGZsaXA6IHRydWUsXG4gICAgICBib3VuZGFyeTogJ3Njcm9sbFBhcmVudCcsXG4gICAgICByZWZlcmVuY2U6ICd0b2dnbGUnLFxuICAgICAgZGlzcGxheTogJ2R5bmFtaWMnXG4gICAgfTtcbiAgICB2YXIgRGVmYXVsdFR5cGUgPSB7XG4gICAgICBvZmZzZXQ6ICcobnVtYmVyfHN0cmluZ3xmdW5jdGlvbiknLFxuICAgICAgZmxpcDogJ2Jvb2xlYW4nLFxuICAgICAgYm91bmRhcnk6ICcoc3RyaW5nfGVsZW1lbnQpJyxcbiAgICAgIHJlZmVyZW5jZTogJyhzdHJpbmd8ZWxlbWVudCknLFxuICAgICAgZGlzcGxheTogJ3N0cmluZydcbiAgICAgIC8qKlxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqL1xuXG4gICAgfTtcblxuICAgIHZhciBEcm9wZG93biA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIERyb3Bkb3duKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5fcG9wcGVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICAgIHRoaXMuX21lbnUgPSB0aGlzLl9nZXRNZW51RWxlbWVudCgpO1xuICAgICAgICB0aGlzLl9pbk5hdmJhciA9IHRoaXMuX2RldGVjdE5hdmJhcigpO1xuXG4gICAgICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gRHJvcGRvd24ucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by50b2dnbGUgPSBmdW5jdGlvbiB0b2dnbGUoKSB7XG4gICAgICAgIGlmICh0aGlzLl9lbGVtZW50LmRpc2FibGVkIHx8ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRJU0FCTEVEKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG5cbiAgICAgICAgdmFyIGlzQWN0aXZlID0gJCQkMSh0aGlzLl9tZW51KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgRHJvcGRvd24uX2NsZWFyTWVudXMoKTtcblxuICAgICAgICBpZiAoaXNBY3RpdmUpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVsYXRlZFRhcmdldCA9IHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiB0aGlzLl9lbGVtZW50XG4gICAgICAgIH07XG4gICAgICAgIHZhciBzaG93RXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNIT1csIHJlbGF0ZWRUYXJnZXQpO1xuICAgICAgICAkJCQxKHBhcmVudCkudHJpZ2dlcihzaG93RXZlbnQpO1xuXG4gICAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gLy8gRGlzYWJsZSB0b3RhbGx5IFBvcHBlci5qcyBmb3IgRHJvcGRvd24gaW4gTmF2YmFyXG5cblxuICAgICAgICBpZiAoIXRoaXMuX2luTmF2YmFyKSB7XG4gICAgICAgICAgLyoqXG4gICAgICAgICAgICogQ2hlY2sgZm9yIFBvcHBlciBkZXBlbmRlbmN5XG4gICAgICAgICAgICogUG9wcGVyIC0gaHR0cHM6Ly9wb3BwZXIuanMub3JnXG4gICAgICAgICAgICovXG4gICAgICAgICAgaWYgKHR5cGVvZiBQb3BwZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb290c3RyYXAgZHJvcGRvd24gcmVxdWlyZSBQb3BwZXIuanMgKGh0dHBzOi8vcG9wcGVyLmpzLm9yZyknKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmVmZXJlbmNlRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgICAgICBpZiAodGhpcy5fY29uZmlnLnJlZmVyZW5jZSA9PT0gJ3BhcmVudCcpIHtcbiAgICAgICAgICAgIHJlZmVyZW5jZUVsZW1lbnQgPSBwYXJlbnQ7XG4gICAgICAgICAgfSBlbHNlIGlmIChVdGlsLmlzRWxlbWVudCh0aGlzLl9jb25maWcucmVmZXJlbmNlKSkge1xuICAgICAgICAgICAgcmVmZXJlbmNlRWxlbWVudCA9IHRoaXMuX2NvbmZpZy5yZWZlcmVuY2U7IC8vIENoZWNrIGlmIGl0J3MgalF1ZXJ5IGVsZW1lbnRcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9jb25maWcucmVmZXJlbmNlLmpxdWVyeSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgcmVmZXJlbmNlRWxlbWVudCA9IHRoaXMuX2NvbmZpZy5yZWZlcmVuY2VbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyBJZiBib3VuZGFyeSBpcyBub3QgYHNjcm9sbFBhcmVudGAsIHRoZW4gc2V0IHBvc2l0aW9uIHRvIGBzdGF0aWNgXG4gICAgICAgICAgLy8gdG8gYWxsb3cgdGhlIG1lbnUgdG8gXCJlc2NhcGVcIiB0aGUgc2Nyb2xsIHBhcmVudCdzIGJvdW5kYXJpZXNcbiAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzI0MjUxXG5cblxuICAgICAgICAgIGlmICh0aGlzLl9jb25maWcuYm91bmRhcnkgIT09ICdzY3JvbGxQYXJlbnQnKSB7XG4gICAgICAgICAgICAkJCQxKHBhcmVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlBPU0lUSU9OX1NUQVRJQyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fcG9wcGVyID0gbmV3IFBvcHBlcihyZWZlcmVuY2VFbGVtZW50LCB0aGlzLl9tZW51LCB0aGlzLl9nZXRQb3BwZXJDb25maWcoKSk7XG4gICAgICAgIH0gLy8gSWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIGFkZCBleHRyYVxuICAgICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHRvIHRoZSBib2R5J3MgaW1tZWRpYXRlIGNoaWxkcmVuO1xuICAgICAgICAvLyBvbmx5IG5lZWRlZCBiZWNhdXNlIG9mIGJyb2tlbiBldmVudCBkZWxlZ2F0aW9uIG9uIGlPU1xuICAgICAgICAvLyBodHRwczovL3d3dy5xdWlya3Ntb2RlLm9yZy9ibG9nL2FyY2hpdmVzLzIwMTQvMDIvbW91c2VfZXZlbnRfYnViLmh0bWxcblxuXG4gICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgJCQkMShwYXJlbnQpLmNsb3Nlc3QoU2VsZWN0b3IuTkFWQkFSX05BVikubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5jaGlsZHJlbigpLm9uKCdtb3VzZW92ZXInLCBudWxsLCAkJCQxLm5vb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5mb2N1cygpO1xuXG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSk7XG5cbiAgICAgICAgJCQkMSh0aGlzLl9tZW51KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAgICQkJDEocGFyZW50KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuU0hPVykudHJpZ2dlcigkJCQxLkV2ZW50KEV2ZW50LlNIT1dOLCByZWxhdGVkVGFyZ2V0KSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub2ZmKEVWRU5UX0tFWSk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9tZW51ID0gbnVsbDtcblxuICAgICAgICBpZiAodGhpcy5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5fcG9wcGVyLmRlc3Ryb3koKTtcblxuICAgICAgICAgIHRoaXMuX3BvcHBlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoKSB7XG4gICAgICAgIHRoaXMuX2luTmF2YmFyID0gdGhpcy5fZGV0ZWN0TmF2YmFyKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMuX3BvcHBlci5zY2hlZHVsZVVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9OyAvLyBQcml2YXRlXG5cblxuICAgICAgX3Byb3RvLl9hZGRFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uIF9hZGRFdmVudExpc3RlbmVycygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50LkNMSUNLLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgX3RoaXMudG9nZ2xlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgICBjb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHQsICQkJDEodGhpcy5fZWxlbWVudCkuZGF0YSgpLCBjb25maWcpO1xuICAgICAgICBVdGlsLnR5cGVDaGVja0NvbmZpZyhOQU1FLCBjb25maWcsIHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdFR5cGUpO1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRNZW51RWxlbWVudCA9IGZ1bmN0aW9uIF9nZXRNZW51RWxlbWVudCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9tZW51KSB7XG4gICAgICAgICAgdmFyIHBhcmVudCA9IERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCh0aGlzLl9lbGVtZW50KTtcblxuICAgICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX21lbnUgPSBwYXJlbnQucXVlcnlTZWxlY3RvcihTZWxlY3Rvci5NRU5VKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5fbWVudTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0UGxhY2VtZW50ID0gZnVuY3Rpb24gX2dldFBsYWNlbWVudCgpIHtcbiAgICAgICAgdmFyICRwYXJlbnREcm9wZG93biA9ICQkJDEodGhpcy5fZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICAgICAgdmFyIHBsYWNlbWVudCA9IEF0dGFjaG1lbnRNYXAuQk9UVE9NOyAvLyBIYW5kbGUgZHJvcHVwXG5cbiAgICAgICAgaWYgKCRwYXJlbnREcm9wZG93bi5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUFVQKSkge1xuICAgICAgICAgIHBsYWNlbWVudCA9IEF0dGFjaG1lbnRNYXAuVE9QO1xuXG4gICAgICAgICAgaWYgKCQkJDEodGhpcy5fbWVudSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLk1FTlVSSUdIVCkpIHtcbiAgICAgICAgICAgIHBsYWNlbWVudCA9IEF0dGFjaG1lbnRNYXAuVE9QRU5EO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICgkcGFyZW50RHJvcGRvd24uaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BSSUdIVCkpIHtcbiAgICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLlJJR0hUO1xuICAgICAgICB9IGVsc2UgaWYgKCRwYXJlbnREcm9wZG93bi5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUExFRlQpKSB7XG4gICAgICAgICAgcGxhY2VtZW50ID0gQXR0YWNobWVudE1hcC5MRUZUO1xuICAgICAgICB9IGVsc2UgaWYgKCQkJDEodGhpcy5fbWVudSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLk1FTlVSSUdIVCkpIHtcbiAgICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLkJPVFRPTUVORDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwbGFjZW1lbnQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2RldGVjdE5hdmJhciA9IGZ1bmN0aW9uIF9kZXRlY3ROYXZiYXIoKSB7XG4gICAgICAgIHJldHVybiAkJCQxKHRoaXMuX2VsZW1lbnQpLmNsb3Nlc3QoJy5uYXZiYXInKS5sZW5ndGggPiAwO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9nZXRQb3BwZXJDb25maWcgPSBmdW5jdGlvbiBfZ2V0UG9wcGVyQ29uZmlnKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICB2YXIgb2Zmc2V0Q29uZiA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5fY29uZmlnLm9mZnNldCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIG9mZnNldENvbmYuZm4gPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgZGF0YS5vZmZzZXRzID0gX29iamVjdFNwcmVhZCh7fSwgZGF0YS5vZmZzZXRzLCBfdGhpczIuX2NvbmZpZy5vZmZzZXQoZGF0YS5vZmZzZXRzKSB8fCB7fSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9mZnNldENvbmYub2Zmc2V0ID0gdGhpcy5fY29uZmlnLm9mZnNldDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwb3BwZXJDb25maWcgPSB7XG4gICAgICAgICAgcGxhY2VtZW50OiB0aGlzLl9nZXRQbGFjZW1lbnQoKSxcbiAgICAgICAgICBtb2RpZmllcnM6IHtcbiAgICAgICAgICAgIG9mZnNldDogb2Zmc2V0Q29uZixcbiAgICAgICAgICAgIGZsaXA6IHtcbiAgICAgICAgICAgICAgZW5hYmxlZDogdGhpcy5fY29uZmlnLmZsaXBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwcmV2ZW50T3ZlcmZsb3c6IHtcbiAgICAgICAgICAgICAgYm91bmRhcmllc0VsZW1lbnQ6IHRoaXMuX2NvbmZpZy5ib3VuZGFyeVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gLy8gRGlzYWJsZSBQb3BwZXIuanMgaWYgd2UgaGF2ZSBhIHN0YXRpYyBkaXNwbGF5XG5cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmRpc3BsYXkgPT09ICdzdGF0aWMnKSB7XG4gICAgICAgICAgcG9wcGVyQ29uZmlnLm1vZGlmaWVycy5hcHBseVN0eWxlID0ge1xuICAgICAgICAgICAgZW5hYmxlZDogZmFsc2VcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvcHBlckNvbmZpZztcbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIERyb3Bkb3duLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnID8gY29uZmlnIDogbnVsbDtcblxuICAgICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgZGF0YSA9IG5ldyBEcm9wZG93bih0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBEcm9wZG93bi5fY2xlYXJNZW51cyA9IGZ1bmN0aW9uIF9jbGVhck1lbnVzKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudCAmJiAoZXZlbnQud2hpY2ggPT09IFJJR0hUX01PVVNFX0JVVFRPTl9XSElDSCB8fCBldmVudC50eXBlID09PSAna2V5dXAnICYmIGV2ZW50LndoaWNoICE9PSBUQUJfS0VZQ09ERSkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdG9nZ2xlcyA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5EQVRBX1RPR0dMRSkpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSB0b2dnbGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgdmFyIHBhcmVudCA9IERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCh0b2dnbGVzW2ldKTtcblxuICAgICAgICAgIHZhciBjb250ZXh0ID0gJCQkMSh0b2dnbGVzW2ldKS5kYXRhKERBVEFfS0VZKTtcbiAgICAgICAgICB2YXIgcmVsYXRlZFRhcmdldCA9IHtcbiAgICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHRvZ2dsZXNbaV1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50LnR5cGUgPT09ICdjbGljaycpIHtcbiAgICAgICAgICAgIHJlbGF0ZWRUYXJnZXQuY2xpY2tFdmVudCA9IGV2ZW50O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGRyb3Bkb3duTWVudSA9IGNvbnRleHQuX21lbnU7XG5cbiAgICAgICAgICBpZiAoISQkJDEocGFyZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChldmVudCAmJiAoZXZlbnQudHlwZSA9PT0gJ2NsaWNrJyAmJiAvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSB8fCBldmVudC50eXBlID09PSAna2V5dXAnICYmIGV2ZW50LndoaWNoID09PSBUQUJfS0VZQ09ERSkgJiYgJCQkMS5jb250YWlucyhwYXJlbnQsIGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBoaWRlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkhJREUsIHJlbGF0ZWRUYXJnZXQpO1xuICAgICAgICAgICQkJDEocGFyZW50KS50cmlnZ2VyKGhpZGVFdmVudCk7XG5cbiAgICAgICAgICBpZiAoaGlkZUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9IC8vIElmIHRoaXMgaXMgYSB0b3VjaC1lbmFibGVkIGRldmljZSB3ZSByZW1vdmUgdGhlIGV4dHJhXG4gICAgICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB3ZSBhZGRlZCBmb3IgaU9TIHN1cHBvcnRcblxuXG4gICAgICAgICAgaWYgKCdvbnRvdWNoc3RhcnQnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5jaGlsZHJlbigpLm9mZignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0b2dnbGVzW2ldLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuICAgICAgICAgICQkJDEoZHJvcGRvd25NZW51KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAgICAgJCQkMShwYXJlbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKS50cmlnZ2VyKCQkJDEuRXZlbnQoRXZlbnQuSElEREVOLCByZWxhdGVkVGFyZ2V0KSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCA9IGZ1bmN0aW9uIF9nZXRQYXJlbnRGcm9tRWxlbWVudChlbGVtZW50KSB7XG4gICAgICAgIHZhciBwYXJlbnQ7XG4gICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtZW50KTtcblxuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICBwYXJlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXJlbnQgfHwgZWxlbWVudC5wYXJlbnROb2RlO1xuICAgICAgfTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcblxuXG4gICAgICBEcm9wZG93bi5fZGF0YUFwaUtleWRvd25IYW5kbGVyID0gZnVuY3Rpb24gX2RhdGFBcGlLZXlkb3duSGFuZGxlcihldmVudCkge1xuICAgICAgICAvLyBJZiBub3QgaW5wdXQvdGV4dGFyZWE6XG4gICAgICAgIC8vICAtIEFuZCBub3QgYSBrZXkgaW4gUkVHRVhQX0tFWURPV04gPT4gbm90IGEgZHJvcGRvd24gY29tbWFuZFxuICAgICAgICAvLyBJZiBpbnB1dC90ZXh0YXJlYTpcbiAgICAgICAgLy8gIC0gSWYgc3BhY2Uga2V5ID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgICAgLy8gIC0gSWYga2V5IGlzIG90aGVyIHRoYW4gZXNjYXBlXG4gICAgICAgIC8vICAgIC0gSWYga2V5IGlzIG5vdCB1cCBvciBkb3duID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgICAgLy8gICAgLSBJZiB0cmlnZ2VyIGluc2lkZSB0aGUgbWVudSA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICAgIGlmICgvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSA/IGV2ZW50LndoaWNoID09PSBTUEFDRV9LRVlDT0RFIHx8IGV2ZW50LndoaWNoICE9PSBFU0NBUEVfS0VZQ09ERSAmJiAoZXZlbnQud2hpY2ggIT09IEFSUk9XX0RPV05fS0VZQ09ERSAmJiBldmVudC53aGljaCAhPT0gQVJST1dfVVBfS0VZQ09ERSB8fCAkJCQxKGV2ZW50LnRhcmdldCkuY2xvc2VzdChTZWxlY3Rvci5NRU5VKS5sZW5ndGgpIDogIVJFR0VYUF9LRVlET1dOLnRlc3QoZXZlbnQud2hpY2gpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgJCQkMSh0aGlzKS5oYXNDbGFzcyhDbGFzc05hbWUuRElTQUJMRUQpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHBhcmVudCA9IERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCh0aGlzKTtcblxuICAgICAgICB2YXIgaXNBY3RpdmUgPSAkJCQxKHBhcmVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIGlmICghaXNBY3RpdmUgJiYgKGV2ZW50LndoaWNoICE9PSBFU0NBUEVfS0VZQ09ERSB8fCBldmVudC53aGljaCAhPT0gU1BBQ0VfS0VZQ09ERSkgfHwgaXNBY3RpdmUgJiYgKGV2ZW50LndoaWNoID09PSBFU0NBUEVfS0VZQ09ERSB8fCBldmVudC53aGljaCA9PT0gU1BBQ0VfS0VZQ09ERSkpIHtcbiAgICAgICAgICBpZiAoZXZlbnQud2hpY2ggPT09IEVTQ0FQRV9LRVlDT0RFKSB7XG4gICAgICAgICAgICB2YXIgdG9nZ2xlID0gcGFyZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuREFUQV9UT0dHTEUpO1xuICAgICAgICAgICAgJCQkMSh0b2dnbGUpLnRyaWdnZXIoJ2ZvY3VzJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJCQkMSh0aGlzKS50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpdGVtcyA9IFtdLnNsaWNlLmNhbGwocGFyZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuVklTSUJMRV9JVEVNUykpO1xuXG4gICAgICAgIGlmIChpdGVtcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaW5kZXggPSBpdGVtcy5pbmRleE9mKGV2ZW50LnRhcmdldCk7XG5cbiAgICAgICAgaWYgKGV2ZW50LndoaWNoID09PSBBUlJPV19VUF9LRVlDT0RFICYmIGluZGV4ID4gMCkge1xuICAgICAgICAgIC8vIFVwXG4gICAgICAgICAgaW5kZXgtLTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC53aGljaCA9PT0gQVJST1dfRE9XTl9LRVlDT0RFICYmIGluZGV4IDwgaXRlbXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgIC8vIERvd25cbiAgICAgICAgICBpbmRleCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICAgIGluZGV4ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGl0ZW1zW2luZGV4XS5mb2N1cygpO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKERyb3Bkb3duLCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFR5cGVcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHRUeXBlO1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBEcm9wZG93bjtcbiAgICB9KCk7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuS0VZRE9XTl9EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIERyb3Bkb3duLl9kYXRhQXBpS2V5ZG93bkhhbmRsZXIpLm9uKEV2ZW50LktFWURPV05fREFUQV9BUEksIFNlbGVjdG9yLk1FTlUsIERyb3Bkb3duLl9kYXRhQXBpS2V5ZG93bkhhbmRsZXIpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJICsgXCIgXCIgKyBFdmVudC5LRVlVUF9EQVRBX0FQSSwgRHJvcGRvd24uX2NsZWFyTWVudXMpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIERyb3Bkb3duLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkJCQxKHRoaXMpLCAndG9nZ2xlJyk7XG4gICAgfSkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkZPUk1fQ0hJTEQsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IERyb3Bkb3duLl9qUXVlcnlJbnRlcmZhY2U7XG4gICAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IERyb3Bkb3duO1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBEcm9wZG93bi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gRHJvcGRvd247XG4gIH0oJCwgUG9wcGVyKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBtb2RhbC5qc1xuICAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICB2YXIgTW9kYWwgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ21vZGFsJztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLm1vZGFsJztcbiAgICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIEVTQ0FQRV9LRVlDT0RFID0gMjc7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIEVzY2FwZSAoRXNjKSBrZXlcblxuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgYmFja2Ryb3A6IHRydWUsXG4gICAgICBrZXlib2FyZDogdHJ1ZSxcbiAgICAgIGZvY3VzOiB0cnVlLFxuICAgICAgc2hvdzogdHJ1ZVxuICAgIH07XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgYmFja2Ryb3A6ICcoYm9vbGVhbnxzdHJpbmcpJyxcbiAgICAgIGtleWJvYXJkOiAnYm9vbGVhbicsXG4gICAgICBmb2N1czogJ2Jvb2xlYW4nLFxuICAgICAgc2hvdzogJ2Jvb2xlYW4nXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIEZPQ1VTSU46IFwiZm9jdXNpblwiICsgRVZFTlRfS0VZLFxuICAgICAgUkVTSVpFOiBcInJlc2l6ZVwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0tfRElTTUlTUzogXCJjbGljay5kaXNtaXNzXCIgKyBFVkVOVF9LRVksXG4gICAgICBLRVlET1dOX0RJU01JU1M6IFwia2V5ZG93bi5kaXNtaXNzXCIgKyBFVkVOVF9LRVksXG4gICAgICBNT1VTRVVQX0RJU01JU1M6IFwibW91c2V1cC5kaXNtaXNzXCIgKyBFVkVOVF9LRVksXG4gICAgICBNT1VTRURPV05fRElTTUlTUzogXCJtb3VzZWRvd24uZGlzbWlzc1wiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIFNDUk9MTEJBUl9NRUFTVVJFUjogJ21vZGFsLXNjcm9sbGJhci1tZWFzdXJlJyxcbiAgICAgIEJBQ0tEUk9QOiAnbW9kYWwtYmFja2Ryb3AnLFxuICAgICAgT1BFTjogJ21vZGFsLW9wZW4nLFxuICAgICAgRkFERTogJ2ZhZGUnLFxuICAgICAgU0hPVzogJ3Nob3cnXG4gICAgfTtcbiAgICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgICBESUFMT0c6ICcubW9kYWwtZGlhbG9nJyxcbiAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwibW9kYWxcIl0nLFxuICAgICAgREFUQV9ESVNNSVNTOiAnW2RhdGEtZGlzbWlzcz1cIm1vZGFsXCJdJyxcbiAgICAgIEZJWEVEX0NPTlRFTlQ6ICcuZml4ZWQtdG9wLCAuZml4ZWQtYm90dG9tLCAuaXMtZml4ZWQsIC5zdGlja3ktdG9wJyxcbiAgICAgIFNUSUNLWV9DT05URU5UOiAnLnN0aWNreS10b3AnXG4gICAgICAvKipcbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgKi9cblxuICAgIH07XG5cbiAgICB2YXIgTW9kYWwgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBNb2RhbChlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLl9kaWFsb2cgPSBlbGVtZW50LnF1ZXJ5U2VsZWN0b3IoU2VsZWN0b3IuRElBTE9HKTtcbiAgICAgICAgdGhpcy5fYmFja2Ryb3AgPSBudWxsO1xuICAgICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lzQm9keU92ZXJmbG93aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyV2lkdGggPSAwO1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IE1vZGFsLnByb3RvdHlwZTtcblxuICAgICAgLy8gUHVibGljXG4gICAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKHJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzU2hvd24gPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdyhyZWxhdGVkVGFyZ2V0KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5zaG93ID0gZnVuY3Rpb24gc2hvdyhyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzVHJhbnNpdGlvbmluZyB8fCB0aGlzLl9pc1Nob3duKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpKSB7XG4gICAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzaG93RXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LlNIT1csIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiByZWxhdGVkVGFyZ2V0XG4gICAgICAgIH0pO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc2hvd0V2ZW50KTtcblxuICAgICAgICBpZiAodGhpcy5faXNTaG93biB8fCBzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9pc1Nob3duID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLl9jaGVja1Njcm9sbGJhcigpO1xuXG4gICAgICAgIHRoaXMuX3NldFNjcm9sbGJhcigpO1xuXG4gICAgICAgIHRoaXMuX2FkanVzdERpYWxvZygpO1xuXG4gICAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLk9QRU4pO1xuXG4gICAgICAgIHRoaXMuX3NldEVzY2FwZUV2ZW50KCk7XG5cbiAgICAgICAgdGhpcy5fc2V0UmVzaXplRXZlbnQoKTtcblxuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RJU01JU1MsIFNlbGVjdG9yLkRBVEFfRElTTUlTUywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzLmhpZGUoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgJCQkMSh0aGlzLl9kaWFsb2cpLm9uKEV2ZW50Lk1PVVNFRE9XTl9ESVNNSVNTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgJCQkMShfdGhpcy5fZWxlbWVudCkub25lKEV2ZW50Lk1PVVNFVVBfRElTTUlTUywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoJCQkMShldmVudC50YXJnZXQpLmlzKF90aGlzLl9lbGVtZW50KSkge1xuICAgICAgICAgICAgICBfdGhpcy5faWdub3JlQmFja2Ryb3BDbGljayA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuX3Nob3dCYWNrZHJvcChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzLl9zaG93RWxlbWVudChyZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uaGlkZSA9IGZ1bmN0aW9uIGhpZGUoZXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9pc1RyYW5zaXRpb25pbmcgfHwgIXRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaGlkZUV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5ISURFKTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKGhpZGVFdmVudCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9pc1Nob3duIHx8IGhpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2lzU2hvd24gPSBmYWxzZTtcbiAgICAgICAgdmFyIHRyYW5zaXRpb24gPSAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKTtcblxuICAgICAgICBpZiAodHJhbnNpdGlvbikge1xuICAgICAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXRFc2NhcGVFdmVudCgpO1xuXG4gICAgICAgIHRoaXMuX3NldFJlc2l6ZUV2ZW50KCk7XG5cbiAgICAgICAgJCQkMShkb2N1bWVudCkub2ZmKEV2ZW50LkZPQ1VTSU4pO1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vZmYoRXZlbnQuQ0xJQ0tfRElTTUlTUyk7XG4gICAgICAgICQkJDEodGhpcy5fZGlhbG9nKS5vZmYoRXZlbnQuTU9VU0VET1dOX0RJU01JU1MpO1xuXG4gICAgICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMyLl9oaWRlTW9kYWwoZXZlbnQpO1xuICAgICAgICAgIH0pLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5faGlkZU1vZGFsKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICAgJCQkMS5yZW1vdmVEYXRhKHRoaXMuX2VsZW1lbnQsIERBVEFfS0VZKTtcbiAgICAgICAgJCQkMSh3aW5kb3csIGRvY3VtZW50LCB0aGlzLl9lbGVtZW50LCB0aGlzLl9iYWNrZHJvcCkub2ZmKEVWRU5UX0tFWSk7XG4gICAgICAgIHRoaXMuX2NvbmZpZyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9kaWFsb2cgPSBudWxsO1xuICAgICAgICB0aGlzLl9iYWNrZHJvcCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2lzU2hvd24gPSBudWxsO1xuICAgICAgICB0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSBudWxsO1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXJXaWR0aCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uaGFuZGxlVXBkYXRlID0gZnVuY3Rpb24gaGFuZGxlVXBkYXRlKCkge1xuICAgICAgICB0aGlzLl9hZGp1c3REaWFsb2coKTtcbiAgICAgIH07IC8vIFByaXZhdGVcblxuXG4gICAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIERlZmF1bHQsIGNvbmZpZyk7XG4gICAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgRGVmYXVsdFR5cGUpO1xuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zaG93RWxlbWVudCA9IGZ1bmN0aW9uIF9zaG93RWxlbWVudChyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgIHZhciB0cmFuc2l0aW9uID0gJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSk7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUgfHwgdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgICAgIC8vIERvbid0IG1vdmUgbW9kYWwncyBET00gcG9zaXRpb25cbiAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnNjcm9sbFRvcCA9IDA7XG5cbiAgICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgICBVdGlsLnJlZmxvdyh0aGlzLl9lbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIGlmICh0aGlzLl9jb25maWcuZm9jdXMpIHtcbiAgICAgICAgICB0aGlzLl9lbmZvcmNlRm9jdXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzaG93bkV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XTiwge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHJlbGF0ZWRUYXJnZXRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIHRyYW5zaXRpb25Db21wbGV0ZSA9IGZ1bmN0aW9uIHRyYW5zaXRpb25Db21wbGV0ZSgpIHtcbiAgICAgICAgICBpZiAoX3RoaXMzLl9jb25maWcuZm9jdXMpIHtcbiAgICAgICAgICAgIF90aGlzMy5fZWxlbWVudC5mb2N1cygpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzMy5faXNUcmFuc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgICAgJCQkMShfdGhpczMuX2VsZW1lbnQpLnRyaWdnZXIoc2hvd25FdmVudCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgICB2YXIgdHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCh0aGlzLl9lbGVtZW50KTtcbiAgICAgICAgICAkJCQxKHRoaXMuX2RpYWxvZykub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIHRyYW5zaXRpb25Db21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0cmFuc2l0aW9uQ29tcGxldGUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9lbmZvcmNlRm9jdXMgPSBmdW5jdGlvbiBfZW5mb3JjZUZvY3VzKCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICAkJCQxKGRvY3VtZW50KS5vZmYoRXZlbnQuRk9DVVNJTikgLy8gR3VhcmQgYWdhaW5zdCBpbmZpbml0ZSBmb2N1cyBsb29wXG4gICAgICAgIC5vbihFdmVudC5GT0NVU0lOLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoZG9jdW1lbnQgIT09IGV2ZW50LnRhcmdldCAmJiBfdGhpczQuX2VsZW1lbnQgIT09IGV2ZW50LnRhcmdldCAmJiAkJCQxKF90aGlzNC5fZWxlbWVudCkuaGFzKGV2ZW50LnRhcmdldCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBfdGhpczQuX2VsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zZXRFc2NhcGVFdmVudCA9IGZ1bmN0aW9uIF9zZXRFc2NhcGVFdmVudCgpIHtcbiAgICAgICAgdmFyIF90aGlzNSA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzU2hvd24gJiYgdGhpcy5fY29uZmlnLmtleWJvYXJkKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5LRVlET1dOX0RJU01JU1MsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LndoaWNoID09PSBFU0NBUEVfS0VZQ09ERSkge1xuICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgIF90aGlzNS5oaWRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFdmVudC5LRVlET1dOX0RJU01JU1MpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3NldFJlc2l6ZUV2ZW50ID0gZnVuY3Rpb24gX3NldFJlc2l6ZUV2ZW50KCkge1xuICAgICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5faXNTaG93bikge1xuICAgICAgICAgICQkJDEod2luZG93KS5vbihFdmVudC5SRVNJWkUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzNi5oYW5kbGVVcGRhdGUoZXZlbnQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICQkJDEod2luZG93KS5vZmYoRXZlbnQuUkVTSVpFKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9oaWRlTW9kYWwgPSBmdW5jdGlvbiBfaGlkZU1vZGFsKCkge1xuICAgICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cbiAgICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgdHJ1ZSk7XG5cbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fc2hvd0JhY2tkcm9wKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAkJCQxKGRvY3VtZW50LmJvZHkpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5PUEVOKTtcblxuICAgICAgICAgIF90aGlzNy5fcmVzZXRBZGp1c3RtZW50cygpO1xuXG4gICAgICAgICAgX3RoaXM3Ll9yZXNldFNjcm9sbGJhcigpO1xuXG4gICAgICAgICAgJCQkMShfdGhpczcuX2VsZW1lbnQpLnRyaWdnZXIoRXZlbnQuSElEREVOKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3JlbW92ZUJhY2tkcm9wID0gZnVuY3Rpb24gX3JlbW92ZUJhY2tkcm9wKCkge1xuICAgICAgICBpZiAodGhpcy5fYmFja2Ryb3ApIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5yZW1vdmUoKTtcbiAgICAgICAgICB0aGlzLl9iYWNrZHJvcCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fc2hvd0JhY2tkcm9wID0gZnVuY3Rpb24gX3Nob3dCYWNrZHJvcChjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXM4ID0gdGhpcztcblxuICAgICAgICB2YXIgYW5pbWF0ZSA9ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpID8gQ2xhc3NOYW1lLkZBREUgOiAnJztcblxuICAgICAgICBpZiAodGhpcy5faXNTaG93biAmJiB0aGlzLl9jb25maWcuYmFja2Ryb3ApIHtcbiAgICAgICAgICB0aGlzLl9iYWNrZHJvcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgIHRoaXMuX2JhY2tkcm9wLmNsYXNzTmFtZSA9IENsYXNzTmFtZS5CQUNLRFJPUDtcblxuICAgICAgICAgIGlmIChhbmltYXRlKSB7XG4gICAgICAgICAgICB0aGlzLl9iYWNrZHJvcC5jbGFzc0xpc3QuYWRkKGFuaW1hdGUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICQkJDEodGhpcy5fYmFja2Ryb3ApLmFwcGVuZFRvKGRvY3VtZW50LmJvZHkpO1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuQ0xJQ0tfRElTTUlTUywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoX3RoaXM4Ll9pZ25vcmVCYWNrZHJvcENsaWNrKSB7XG4gICAgICAgICAgICAgIF90aGlzOC5faWdub3JlQmFja2Ryb3BDbGljayA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChldmVudC50YXJnZXQgIT09IGV2ZW50LmN1cnJlbnRUYXJnZXQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoX3RoaXM4Ll9jb25maWcuYmFja2Ryb3AgPT09ICdzdGF0aWMnKSB7XG4gICAgICAgICAgICAgIF90aGlzOC5fZWxlbWVudC5mb2N1cygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgX3RoaXM4LmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChhbmltYXRlKSB7XG4gICAgICAgICAgICBVdGlsLnJlZmxvdyh0aGlzLl9iYWNrZHJvcCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghYW5pbWF0ZSkge1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgYmFja2Ryb3BUcmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRoaXMuX2JhY2tkcm9wKTtcbiAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY2FsbGJhY2spLmVtdWxhdGVUcmFuc2l0aW9uRW5kKGJhY2tkcm9wVHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgfSBlbHNlIGlmICghdGhpcy5faXNTaG93biAmJiB0aGlzLl9iYWNrZHJvcCkge1xuICAgICAgICAgICQkJDEodGhpcy5fYmFja2Ryb3ApLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgICAgIHZhciBjYWxsYmFja1JlbW92ZSA9IGZ1bmN0aW9uIGNhbGxiYWNrUmVtb3ZlKCkge1xuICAgICAgICAgICAgX3RoaXM4Ll9yZW1vdmVCYWNrZHJvcCgpO1xuXG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgaWYgKCQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpKSB7XG4gICAgICAgICAgICB2YXIgX2JhY2tkcm9wVHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudCh0aGlzLl9iYWNrZHJvcCk7XG5cbiAgICAgICAgICAgICQkJDEodGhpcy5fYmFja2Ryb3ApLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjYWxsYmFja1JlbW92ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoX2JhY2tkcm9wVHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2tSZW1vdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICB9OyAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAvLyB0aGUgZm9sbG93aW5nIG1ldGhvZHMgYXJlIHVzZWQgdG8gaGFuZGxlIG92ZXJmbG93aW5nIG1vZGFsc1xuICAgICAgLy8gdG9kbyAoZmF0KTogdGhlc2Ugc2hvdWxkIHByb2JhYmx5IGJlIHJlZmFjdG9yZWQgb3V0IG9mIG1vZGFsLmpzXG4gICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxuICAgICAgX3Byb3RvLl9hZGp1c3REaWFsb2cgPSBmdW5jdGlvbiBfYWRqdXN0RGlhbG9nKCkge1xuICAgICAgICB2YXIgaXNNb2RhbE92ZXJmbG93aW5nID0gdGhpcy5fZWxlbWVudC5zY3JvbGxIZWlnaHQgPiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuXG4gICAgICAgIGlmICghdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcgJiYgaXNNb2RhbE92ZXJmbG93aW5nKSB7XG4gICAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nTGVmdCA9IHRoaXMuX3Njcm9sbGJhcldpZHRoICsgXCJweFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzQm9keU92ZXJmbG93aW5nICYmICFpc01vZGFsT3ZlcmZsb3dpbmcpIHtcbiAgICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9IHRoaXMuX3Njcm9sbGJhcldpZHRoICsgXCJweFwiO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3Jlc2V0QWRqdXN0bWVudHMgPSBmdW5jdGlvbiBfcmVzZXRBZGp1c3RtZW50cygpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nTGVmdCA9ICcnO1xuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9ICcnO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9jaGVja1Njcm9sbGJhciA9IGZ1bmN0aW9uIF9jaGVja1Njcm9sbGJhcigpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBkb2N1bWVudC5ib2R5LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyA9IHJlY3QubGVmdCArIHJlY3QucmlnaHQgPCB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgdGhpcy5fc2Nyb2xsYmFyV2lkdGggPSB0aGlzLl9nZXRTY3JvbGxiYXJXaWR0aCgpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9zZXRTY3JvbGxiYXIgPSBmdW5jdGlvbiBfc2V0U2Nyb2xsYmFyKCkge1xuICAgICAgICB2YXIgX3RoaXM5ID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcpIHtcbiAgICAgICAgICAvLyBOb3RlOiBET01Ob2RlLnN0eWxlLnBhZGRpbmdSaWdodCByZXR1cm5zIHRoZSBhY3R1YWwgdmFsdWUgb3IgJycgaWYgbm90IHNldFxuICAgICAgICAgIC8vICAgd2hpbGUgJChET01Ob2RlKS5jc3MoJ3BhZGRpbmctcmlnaHQnKSByZXR1cm5zIHRoZSBjYWxjdWxhdGVkIHZhbHVlIG9yIDAgaWYgbm90IHNldFxuICAgICAgICAgIHZhciBmaXhlZENvbnRlbnQgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuRklYRURfQ09OVEVOVCkpO1xuICAgICAgICAgIHZhciBzdGlja3lDb250ZW50ID0gW10uc2xpY2UuY2FsbChkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLlNUSUNLWV9DT05URU5UKSk7IC8vIEFkanVzdCBmaXhlZCBjb250ZW50IHBhZGRpbmdcblxuICAgICAgICAgICQkJDEoZml4ZWRDb250ZW50KS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGFjdHVhbFBhZGRpbmcgPSBlbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodDtcbiAgICAgICAgICAgIHZhciBjYWxjdWxhdGVkUGFkZGluZyA9ICQkJDEoZWxlbWVudCkuY3NzKCdwYWRkaW5nLXJpZ2h0Jyk7XG4gICAgICAgICAgICAkJCQxKGVsZW1lbnQpLmRhdGEoJ3BhZGRpbmctcmlnaHQnLCBhY3R1YWxQYWRkaW5nKS5jc3MoJ3BhZGRpbmctcmlnaHQnLCBwYXJzZUZsb2F0KGNhbGN1bGF0ZWRQYWRkaW5nKSArIF90aGlzOS5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICAgIH0pOyAvLyBBZGp1c3Qgc3RpY2t5IGNvbnRlbnQgbWFyZ2luXG5cbiAgICAgICAgICAkJCQxKHN0aWNreUNvbnRlbnQpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgYWN0dWFsTWFyZ2luID0gZWxlbWVudC5zdHlsZS5tYXJnaW5SaWdodDtcbiAgICAgICAgICAgIHZhciBjYWxjdWxhdGVkTWFyZ2luID0gJCQkMShlbGVtZW50KS5jc3MoJ21hcmdpbi1yaWdodCcpO1xuICAgICAgICAgICAgJCQkMShlbGVtZW50KS5kYXRhKCdtYXJnaW4tcmlnaHQnLCBhY3R1YWxNYXJnaW4pLmNzcygnbWFyZ2luLXJpZ2h0JywgcGFyc2VGbG9hdChjYWxjdWxhdGVkTWFyZ2luKSAtIF90aGlzOS5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICAgIH0pOyAvLyBBZGp1c3QgYm9keSBwYWRkaW5nXG5cbiAgICAgICAgICB2YXIgYWN0dWFsUGFkZGluZyA9IGRvY3VtZW50LmJvZHkuc3R5bGUucGFkZGluZ1JpZ2h0O1xuICAgICAgICAgIHZhciBjYWxjdWxhdGVkUGFkZGluZyA9ICQkJDEoZG9jdW1lbnQuYm9keSkuY3NzKCdwYWRkaW5nLXJpZ2h0Jyk7XG4gICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5kYXRhKCdwYWRkaW5nLXJpZ2h0JywgYWN0dWFsUGFkZGluZykuY3NzKCdwYWRkaW5nLXJpZ2h0JywgcGFyc2VGbG9hdChjYWxjdWxhdGVkUGFkZGluZykgKyB0aGlzLl9zY3JvbGxiYXJXaWR0aCArIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fcmVzZXRTY3JvbGxiYXIgPSBmdW5jdGlvbiBfcmVzZXRTY3JvbGxiYXIoKSB7XG4gICAgICAgIC8vIFJlc3RvcmUgZml4ZWQgY29udGVudCBwYWRkaW5nXG4gICAgICAgIHZhciBmaXhlZENvbnRlbnQgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuRklYRURfQ09OVEVOVCkpO1xuICAgICAgICAkJCQxKGZpeGVkQ29udGVudCkuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcbiAgICAgICAgICB2YXIgcGFkZGluZyA9ICQkJDEoZWxlbWVudCkuZGF0YSgncGFkZGluZy1yaWdodCcpO1xuICAgICAgICAgICQkJDEoZWxlbWVudCkucmVtb3ZlRGF0YSgncGFkZGluZy1yaWdodCcpO1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGUucGFkZGluZ1JpZ2h0ID0gcGFkZGluZyA/IHBhZGRpbmcgOiAnJztcbiAgICAgICAgfSk7IC8vIFJlc3RvcmUgc3RpY2t5IGNvbnRlbnRcblxuICAgICAgICB2YXIgZWxlbWVudHMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoXCJcIiArIFNlbGVjdG9yLlNUSUNLWV9DT05URU5UKSk7XG4gICAgICAgICQkJDEoZWxlbWVudHMpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgdmFyIG1hcmdpbiA9ICQkJDEoZWxlbWVudCkuZGF0YSgnbWFyZ2luLXJpZ2h0Jyk7XG5cbiAgICAgICAgICBpZiAodHlwZW9mIG1hcmdpbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICQkJDEoZWxlbWVudCkuY3NzKCdtYXJnaW4tcmlnaHQnLCBtYXJnaW4pLnJlbW92ZURhdGEoJ21hcmdpbi1yaWdodCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7IC8vIFJlc3RvcmUgYm9keSBwYWRkaW5nXG5cbiAgICAgICAgdmFyIHBhZGRpbmcgPSAkJCQxKGRvY3VtZW50LmJvZHkpLmRhdGEoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5yZW1vdmVEYXRhKCdwYWRkaW5nLXJpZ2h0Jyk7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUucGFkZGluZ1JpZ2h0ID0gcGFkZGluZyA/IHBhZGRpbmcgOiAnJztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0U2Nyb2xsYmFyV2lkdGggPSBmdW5jdGlvbiBfZ2V0U2Nyb2xsYmFyV2lkdGgoKSB7XG4gICAgICAgIC8vIHRoeCBkLndhbHNoXG4gICAgICAgIHZhciBzY3JvbGxEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgc2Nyb2xsRGl2LmNsYXNzTmFtZSA9IENsYXNzTmFtZS5TQ1JPTExCQVJfTUVBU1VSRVI7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2Nyb2xsRGl2KTtcbiAgICAgICAgdmFyIHNjcm9sbGJhcldpZHRoID0gc2Nyb2xsRGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC0gc2Nyb2xsRGl2LmNsaWVudFdpZHRoO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHNjcm9sbERpdik7XG4gICAgICAgIHJldHVybiBzY3JvbGxiYXJXaWR0aDtcbiAgICAgIH07IC8vIFN0YXRpY1xuXG5cbiAgICAgIE1vZGFsLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZywgcmVsYXRlZFRhcmdldCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIERlZmF1bHQsICQkJDEodGhpcykuZGF0YSgpLCB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyAmJiBjb25maWcgPyBjb25maWcgOiB7fSk7XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgTW9kYWwodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRhW2NvbmZpZ10ocmVsYXRlZFRhcmdldCk7XG4gICAgICAgICAgfSBlbHNlIGlmIChfY29uZmlnLnNob3cpIHtcbiAgICAgICAgICAgIGRhdGEuc2hvdyhyZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgX2NyZWF0ZUNsYXNzKE1vZGFsLCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gTW9kYWw7XG4gICAgfSgpO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cblxuICAgICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICB2YXIgX3RoaXMxMCA9IHRoaXM7XG5cbiAgICAgIHZhciB0YXJnZXQ7XG4gICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQodGhpcyk7XG5cbiAgICAgIGlmIChzZWxlY3Rvcikge1xuICAgICAgICB0YXJnZXQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNvbmZpZyA9ICQkJDEodGFyZ2V0KS5kYXRhKERBVEFfS0VZKSA/ICd0b2dnbGUnIDogX29iamVjdFNwcmVhZCh7fSwgJCQkMSh0YXJnZXQpLmRhdGEoKSwgJCQkMSh0aGlzKS5kYXRhKCkpO1xuXG4gICAgICBpZiAodGhpcy50YWdOYW1lID09PSAnQScgfHwgdGhpcy50YWdOYW1lID09PSAnQVJFQScpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIH1cblxuICAgICAgdmFyICR0YXJnZXQgPSAkJCQxKHRhcmdldCkub25lKEV2ZW50LlNIT1csIGZ1bmN0aW9uIChzaG93RXZlbnQpIHtcbiAgICAgICAgaWYgKHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIC8vIE9ubHkgcmVnaXN0ZXIgZm9jdXMgcmVzdG9yZXIgaWYgbW9kYWwgd2lsbCBhY3R1YWxseSBnZXQgc2hvd25cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAkdGFyZ2V0Lm9uZShFdmVudC5ISURERU4sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAoJCQkMShfdGhpczEwKS5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgX3RoaXMxMC5mb2N1cygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgTW9kYWwuX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEodGFyZ2V0KSwgY29uZmlnLCB0aGlzKTtcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBNb2RhbC5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBNb2RhbDtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gTW9kYWwuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIE1vZGFsO1xuICB9KCQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IHRvb2x0aXAuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIFRvb2x0aXAgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ3Rvb2x0aXAnO1xuICAgIHZhciBWRVJTSU9OID0gJzQuMS4zJztcbiAgICB2YXIgREFUQV9LRVkgPSAnYnMudG9vbHRpcCc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIENMQVNTX1BSRUZJWCA9ICdicy10b29sdGlwJztcbiAgICB2YXIgQlNDTFNfUFJFRklYX1JFR0VYID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgQ0xBU1NfUFJFRklYICsgXCJcXFxcUytcIiwgJ2cnKTtcbiAgICB2YXIgRGVmYXVsdFR5cGUgPSB7XG4gICAgICBhbmltYXRpb246ICdib29sZWFuJyxcbiAgICAgIHRlbXBsYXRlOiAnc3RyaW5nJyxcbiAgICAgIHRpdGxlOiAnKHN0cmluZ3xlbGVtZW50fGZ1bmN0aW9uKScsXG4gICAgICB0cmlnZ2VyOiAnc3RyaW5nJyxcbiAgICAgIGRlbGF5OiAnKG51bWJlcnxvYmplY3QpJyxcbiAgICAgIGh0bWw6ICdib29sZWFuJyxcbiAgICAgIHNlbGVjdG9yOiAnKHN0cmluZ3xib29sZWFuKScsXG4gICAgICBwbGFjZW1lbnQ6ICcoc3RyaW5nfGZ1bmN0aW9uKScsXG4gICAgICBvZmZzZXQ6ICcobnVtYmVyfHN0cmluZyknLFxuICAgICAgY29udGFpbmVyOiAnKHN0cmluZ3xlbGVtZW50fGJvb2xlYW4pJyxcbiAgICAgIGZhbGxiYWNrUGxhY2VtZW50OiAnKHN0cmluZ3xhcnJheSknLFxuICAgICAgYm91bmRhcnk6ICcoc3RyaW5nfGVsZW1lbnQpJ1xuICAgIH07XG4gICAgdmFyIEF0dGFjaG1lbnRNYXAgPSB7XG4gICAgICBBVVRPOiAnYXV0bycsXG4gICAgICBUT1A6ICd0b3AnLFxuICAgICAgUklHSFQ6ICdyaWdodCcsXG4gICAgICBCT1RUT006ICdib3R0b20nLFxuICAgICAgTEVGVDogJ2xlZnQnXG4gICAgfTtcbiAgICB2YXIgRGVmYXVsdCA9IHtcbiAgICAgIGFuaW1hdGlvbjogdHJ1ZSxcbiAgICAgIHRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRvb2x0aXBcIiByb2xlPVwidG9vbHRpcFwiPicgKyAnPGRpdiBjbGFzcz1cImFycm93XCI+PC9kaXY+JyArICc8ZGl2IGNsYXNzPVwidG9vbHRpcC1pbm5lclwiPjwvZGl2PjwvZGl2PicsXG4gICAgICB0cmlnZ2VyOiAnaG92ZXIgZm9jdXMnLFxuICAgICAgdGl0bGU6ICcnLFxuICAgICAgZGVsYXk6IDAsXG4gICAgICBodG1sOiBmYWxzZSxcbiAgICAgIHNlbGVjdG9yOiBmYWxzZSxcbiAgICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgICBvZmZzZXQ6IDAsXG4gICAgICBjb250YWluZXI6IGZhbHNlLFxuICAgICAgZmFsbGJhY2tQbGFjZW1lbnQ6ICdmbGlwJyxcbiAgICAgIGJvdW5kYXJ5OiAnc2Nyb2xsUGFyZW50J1xuICAgIH07XG4gICAgdmFyIEhvdmVyU3RhdGUgPSB7XG4gICAgICBTSE9XOiAnc2hvdycsXG4gICAgICBPVVQ6ICdvdXQnXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIElOU0VSVEVEOiBcImluc2VydGVkXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDSzogXCJjbGlja1wiICsgRVZFTlRfS0VZLFxuICAgICAgRk9DVVNJTjogXCJmb2N1c2luXCIgKyBFVkVOVF9LRVksXG4gICAgICBGT0NVU09VVDogXCJmb2N1c291dFwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VFTlRFUjogXCJtb3VzZWVudGVyXCIgKyBFVkVOVF9LRVksXG4gICAgICBNT1VTRUxFQVZFOiBcIm1vdXNlbGVhdmVcIiArIEVWRU5UX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIEZBREU6ICdmYWRlJyxcbiAgICAgIFNIT1c6ICdzaG93J1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgVE9PTFRJUDogJy50b29sdGlwJyxcbiAgICAgIFRPT0xUSVBfSU5ORVI6ICcudG9vbHRpcC1pbm5lcicsXG4gICAgICBBUlJPVzogJy5hcnJvdydcbiAgICB9O1xuICAgIHZhciBUcmlnZ2VyID0ge1xuICAgICAgSE9WRVI6ICdob3ZlcicsXG4gICAgICBGT0NVUzogJ2ZvY3VzJyxcbiAgICAgIENMSUNLOiAnY2xpY2snLFxuICAgICAgTUFOVUFMOiAnbWFudWFsJ1xuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIFRvb2x0aXAgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jdGlvbiBUb29sdGlwKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ2hlY2sgZm9yIFBvcHBlciBkZXBlbmRlbmN5XG4gICAgICAgICAqIFBvcHBlciAtIGh0dHBzOi8vcG9wcGVyLmpzLm9yZ1xuICAgICAgICAgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBQb3BwZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQm9vdHN0cmFwIHRvb2x0aXBzIHJlcXVpcmUgUG9wcGVyLmpzIChodHRwczovL3BvcHBlci5qcy5vcmcpJyk7XG4gICAgICAgIH0gLy8gcHJpdmF0ZVxuXG5cbiAgICAgICAgdGhpcy5faXNFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fdGltZW91dCA9IDA7XG4gICAgICAgIHRoaXMuX2hvdmVyU3RhdGUgPSAnJztcbiAgICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlciA9IHt9O1xuICAgICAgICB0aGlzLl9wb3BwZXIgPSBudWxsOyAvLyBQcm90ZWN0ZWRcblxuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLmNvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgICB0aGlzLnRpcCA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5fc2V0TGlzdGVuZXJzKCk7XG4gICAgICB9IC8vIEdldHRlcnNcblxuXG4gICAgICB2YXIgX3Byb3RvID0gVG9vbHRpcC5wcm90b3R5cGU7XG5cbiAgICAgIC8vIFB1YmxpY1xuICAgICAgX3Byb3RvLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZSgpIHtcbiAgICAgICAgdGhpcy5faXNFbmFibGVkID0gdHJ1ZTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5kaXNhYmxlID0gZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICAgICAgdGhpcy5faXNFbmFibGVkID0gZmFsc2U7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8udG9nZ2xlRW5hYmxlZCA9IGZ1bmN0aW9uIHRvZ2dsZUVuYWJsZWQoKSB7XG4gICAgICAgIHRoaXMuX2lzRW5hYmxlZCA9ICF0aGlzLl9pc0VuYWJsZWQ7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5faXNFbmFibGVkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgdmFyIGRhdGFLZXkgPSB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZO1xuICAgICAgICAgIHZhciBjb250ZXh0ID0gJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXkpO1xuXG4gICAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgICBjb250ZXh0ID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZXZlbnQuY3VycmVudFRhcmdldCwgdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSk7XG4gICAgICAgICAgICAkJCQxKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmRhdGEoZGF0YUtleSwgY29udGV4dCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29udGV4dC5fYWN0aXZlVHJpZ2dlci5jbGljayA9ICFjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyLmNsaWNrO1xuXG4gICAgICAgICAgaWYgKGNvbnRleHQuX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKSkge1xuICAgICAgICAgICAgY29udGV4dC5fZW50ZXIobnVsbCwgY29udGV4dCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRleHQuX2xlYXZlKG51bGwsIGNvbnRleHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoJCQkMSh0aGlzLmdldFRpcEVsZW1lbnQoKSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgICB0aGlzLl9sZWF2ZShudWxsLCB0aGlzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX2VudGVyKG51bGwsIHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl90aW1lb3V0KTtcbiAgICAgICAgJCQkMS5yZW1vdmVEYXRhKHRoaXMuZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSk7XG4gICAgICAgICQkJDEodGhpcy5lbGVtZW50KS5vZmYodGhpcy5jb25zdHJ1Y3Rvci5FVkVOVF9LRVkpO1xuICAgICAgICAkJCQxKHRoaXMuZWxlbWVudCkuY2xvc2VzdCgnLm1vZGFsJykub2ZmKCdoaWRlLmJzLm1vZGFsJyk7XG5cbiAgICAgICAgaWYgKHRoaXMudGlwKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLnRpcCkucmVtb3ZlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9pc0VuYWJsZWQgPSBudWxsO1xuICAgICAgICB0aGlzLl90aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5faG92ZXJTdGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRyaWdnZXIgPSBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLl9wb3BwZXIgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcG9wcGVyID0gbnVsbDtcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb25maWcgPSBudWxsO1xuICAgICAgICB0aGlzLnRpcCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uc2hvdyA9IGZ1bmN0aW9uIHNob3coKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCQkJDEodGhpcy5lbGVtZW50KS5jc3MoJ2Rpc3BsYXknKSA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgdXNlIHNob3cgb24gdmlzaWJsZSBlbGVtZW50cycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNob3dFdmVudCA9ICQkJDEuRXZlbnQodGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5TSE9XKTtcblxuICAgICAgICBpZiAodGhpcy5pc1dpdGhDb250ZW50KCkgJiYgdGhpcy5faXNFbmFibGVkKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLnRyaWdnZXIoc2hvd0V2ZW50KTtcbiAgICAgICAgICB2YXIgaXNJblRoZURvbSA9ICQkJDEuY29udGFpbnModGhpcy5lbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLmVsZW1lbnQpO1xuXG4gICAgICAgICAgaWYgKHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSB8fCAhaXNJblRoZURvbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcbiAgICAgICAgICB2YXIgdGlwSWQgPSBVdGlsLmdldFVJRCh0aGlzLmNvbnN0cnVjdG9yLk5BTUUpO1xuICAgICAgICAgIHRpcC5zZXRBdHRyaWJ1dGUoJ2lkJywgdGlwSWQpO1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtZGVzY3JpYmVkYnknLCB0aXBJZCk7XG4gICAgICAgICAgdGhpcy5zZXRDb250ZW50KCk7XG5cbiAgICAgICAgICBpZiAodGhpcy5jb25maWcuYW5pbWF0aW9uKSB7XG4gICAgICAgICAgICAkJCQxKHRpcCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkZBREUpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBwbGFjZW1lbnQgPSB0eXBlb2YgdGhpcy5jb25maWcucGxhY2VtZW50ID09PSAnZnVuY3Rpb24nID8gdGhpcy5jb25maWcucGxhY2VtZW50LmNhbGwodGhpcywgdGlwLCB0aGlzLmVsZW1lbnQpIDogdGhpcy5jb25maWcucGxhY2VtZW50O1xuXG4gICAgICAgICAgdmFyIGF0dGFjaG1lbnQgPSB0aGlzLl9nZXRBdHRhY2htZW50KHBsYWNlbWVudCk7XG5cbiAgICAgICAgICB0aGlzLmFkZEF0dGFjaG1lbnRDbGFzcyhhdHRhY2htZW50KTtcbiAgICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5jb25maWcuY29udGFpbmVyID09PSBmYWxzZSA/IGRvY3VtZW50LmJvZHkgOiAkJCQxKGRvY3VtZW50KS5maW5kKHRoaXMuY29uZmlnLmNvbnRhaW5lcik7XG4gICAgICAgICAgJCQkMSh0aXApLmRhdGEodGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWSwgdGhpcyk7XG5cbiAgICAgICAgICBpZiAoISQkJDEuY29udGFpbnModGhpcy5lbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLnRpcCkpIHtcbiAgICAgICAgICAgICQkJDEodGlwKS5hcHBlbmRUbyhjb250YWluZXIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICQkJDEodGhpcy5lbGVtZW50KS50cmlnZ2VyKHRoaXMuY29uc3RydWN0b3IuRXZlbnQuSU5TRVJURUQpO1xuICAgICAgICAgIHRoaXMuX3BvcHBlciA9IG5ldyBQb3BwZXIodGhpcy5lbGVtZW50LCB0aXAsIHtcbiAgICAgICAgICAgIHBsYWNlbWVudDogYXR0YWNobWVudCxcbiAgICAgICAgICAgIG1vZGlmaWVyczoge1xuICAgICAgICAgICAgICBvZmZzZXQ6IHtcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IHRoaXMuY29uZmlnLm9mZnNldFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBmbGlwOiB7XG4gICAgICAgICAgICAgICAgYmVoYXZpb3I6IHRoaXMuY29uZmlnLmZhbGxiYWNrUGxhY2VtZW50XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGFycm93OiB7XG4gICAgICAgICAgICAgICAgZWxlbWVudDogU2VsZWN0b3IuQVJST1dcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgcHJldmVudE92ZXJmbG93OiB7XG4gICAgICAgICAgICAgICAgYm91bmRhcmllc0VsZW1lbnQ6IHRoaXMuY29uZmlnLmJvdW5kYXJ5XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkNyZWF0ZTogZnVuY3Rpb24gb25DcmVhdGUoZGF0YSkge1xuICAgICAgICAgICAgICBpZiAoZGF0YS5vcmlnaW5hbFBsYWNlbWVudCAhPT0gZGF0YS5wbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5faGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlKGRhdGEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25VcGRhdGU6IGZ1bmN0aW9uIG9uVXBkYXRlKGRhdGEpIHtcbiAgICAgICAgICAgICAgX3RoaXMuX2hhbmRsZVBvcHBlclBsYWNlbWVudENoYW5nZShkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICAkJCQxKHRpcCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpOyAvLyBJZiB0aGlzIGlzIGEgdG91Y2gtZW5hYmxlZCBkZXZpY2Ugd2UgYWRkIGV4dHJhXG4gICAgICAgICAgLy8gZW1wdHkgbW91c2VvdmVyIGxpc3RlbmVycyB0byB0aGUgYm9keSdzIGltbWVkaWF0ZSBjaGlsZHJlbjtcbiAgICAgICAgICAvLyBvbmx5IG5lZWRlZCBiZWNhdXNlIG9mIGJyb2tlbiBldmVudCBkZWxlZ2F0aW9uIG9uIGlPU1xuICAgICAgICAgIC8vIGh0dHBzOi8vd3d3LnF1aXJrc21vZGUub3JnL2Jsb2cvYXJjaGl2ZXMvMjAxNC8wMi9tb3VzZV9ldmVudF9idWIuaHRtbFxuXG4gICAgICAgICAgaWYgKCdvbnRvdWNoc3RhcnQnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICAgICAgJCQkMShkb2N1bWVudC5ib2R5KS5jaGlsZHJlbigpLm9uKCdtb3VzZW92ZXInLCBudWxsLCAkJCQxLm5vb3ApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmNvbmZpZy5hbmltYXRpb24pIHtcbiAgICAgICAgICAgICAgX3RoaXMuX2ZpeFRyYW5zaXRpb24oKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHByZXZIb3ZlclN0YXRlID0gX3RoaXMuX2hvdmVyU3RhdGU7XG4gICAgICAgICAgICBfdGhpcy5faG92ZXJTdGF0ZSA9IG51bGw7XG4gICAgICAgICAgICAkJCQxKF90aGlzLmVsZW1lbnQpLnRyaWdnZXIoX3RoaXMuY29uc3RydWN0b3IuRXZlbnQuU0hPV04pO1xuXG4gICAgICAgICAgICBpZiAocHJldkhvdmVyU3RhdGUgPT09IEhvdmVyU3RhdGUuT1VUKSB7XG4gICAgICAgICAgICAgIF90aGlzLl9sZWF2ZShudWxsLCBfdGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmICgkJCQxKHRoaXMudGlwKS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSkpIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uRHVyYXRpb24gPSBVdGlsLmdldFRyYW5zaXRpb25EdXJhdGlvbkZyb21FbGVtZW50KHRoaXMudGlwKTtcbiAgICAgICAgICAgICQkJDEodGhpcy50aXApLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQodHJhbnNpdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29tcGxldGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5oaWRlID0gZnVuY3Rpb24gaGlkZShjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICB2YXIgdGlwID0gdGhpcy5nZXRUaXBFbGVtZW50KCk7XG4gICAgICAgIHZhciBoaWRlRXZlbnQgPSAkJCQxLkV2ZW50KHRoaXMuY29uc3RydWN0b3IuRXZlbnQuSElERSk7XG5cbiAgICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgICAgICAgaWYgKF90aGlzMi5faG92ZXJTdGF0ZSAhPT0gSG92ZXJTdGF0ZS5TSE9XICYmIHRpcC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICB0aXAucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aXApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzMi5fY2xlYW5UaXBDbGFzcygpO1xuXG4gICAgICAgICAgX3RoaXMyLmVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWRlc2NyaWJlZGJ5Jyk7XG5cbiAgICAgICAgICAkJCQxKF90aGlzMi5lbGVtZW50KS50cmlnZ2VyKF90aGlzMi5jb25zdHJ1Y3Rvci5FdmVudC5ISURERU4pO1xuXG4gICAgICAgICAgaWYgKF90aGlzMi5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgICBfdGhpczIuX3BvcHBlci5kZXN0cm95KCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAkJCQxKHRoaXMuZWxlbWVudCkudHJpZ2dlcihoaWRlRXZlbnQpO1xuXG4gICAgICAgIGlmIChoaWRlRXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRpcCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpOyAvLyBJZiB0aGlzIGlzIGEgdG91Y2gtZW5hYmxlZCBkZXZpY2Ugd2UgcmVtb3ZlIHRoZSBleHRyYVxuICAgICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHdlIGFkZGVkIGZvciBpT1Mgc3VwcG9ydFxuXG4gICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAkJCQxKGRvY3VtZW50LmJvZHkpLmNoaWxkcmVuKCkub2ZmKCdtb3VzZW92ZXInLCBudWxsLCAkJCQxLm5vb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlcltUcmlnZ2VyLkNMSUNLXSA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyW1RyaWdnZXIuRk9DVVNdID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRyaWdnZXJbVHJpZ2dlci5IT1ZFUl0gPSBmYWxzZTtcblxuICAgICAgICBpZiAoJCQkMSh0aGlzLnRpcCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkZBREUpKSB7XG4gICAgICAgICAgdmFyIHRyYW5zaXRpb25EdXJhdGlvbiA9IFV0aWwuZ2V0VHJhbnNpdGlvbkR1cmF0aW9uRnJvbUVsZW1lbnQodGlwKTtcbiAgICAgICAgICAkJCQxKHRpcCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNvbXBsZXRlKS5lbXVsYXRlVHJhbnNpdGlvbkVuZCh0cmFuc2l0aW9uRHVyYXRpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9ob3ZlclN0YXRlID0gJyc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8udXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKCkge1xuICAgICAgICBpZiAodGhpcy5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5fcG9wcGVyLnNjaGVkdWxlVXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH07IC8vIFByb3RlY3RlZFxuXG5cbiAgICAgIF9wcm90by5pc1dpdGhDb250ZW50ID0gZnVuY3Rpb24gaXNXaXRoQ29udGVudCgpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4odGhpcy5nZXRUaXRsZSgpKTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5hZGRBdHRhY2htZW50Q2xhc3MgPSBmdW5jdGlvbiBhZGRBdHRhY2htZW50Q2xhc3MoYXR0YWNobWVudCkge1xuICAgICAgICAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKS5hZGRDbGFzcyhDTEFTU19QUkVGSVggKyBcIi1cIiArIGF0dGFjaG1lbnQpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLmdldFRpcEVsZW1lbnQgPSBmdW5jdGlvbiBnZXRUaXBFbGVtZW50KCkge1xuICAgICAgICB0aGlzLnRpcCA9IHRoaXMudGlwIHx8ICQkJDEodGhpcy5jb25maWcudGVtcGxhdGUpWzBdO1xuICAgICAgICByZXR1cm4gdGhpcy50aXA7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uc2V0Q29udGVudCA9IGZ1bmN0aW9uIHNldENvbnRlbnQoKSB7XG4gICAgICAgIHZhciB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcbiAgICAgICAgdGhpcy5zZXRFbGVtZW50Q29udGVudCgkJCQxKHRpcC5xdWVyeVNlbGVjdG9yQWxsKFNlbGVjdG9yLlRPT0xUSVBfSU5ORVIpKSwgdGhpcy5nZXRUaXRsZSgpKTtcbiAgICAgICAgJCQkMSh0aXApLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5GQURFICsgXCIgXCIgKyBDbGFzc05hbWUuU0hPVyk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uc2V0RWxlbWVudENvbnRlbnQgPSBmdW5jdGlvbiBzZXRFbGVtZW50Q29udGVudCgkZWxlbWVudCwgY29udGVudCkge1xuICAgICAgICB2YXIgaHRtbCA9IHRoaXMuY29uZmlnLmh0bWw7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnb2JqZWN0JyAmJiAoY29udGVudC5ub2RlVHlwZSB8fCBjb250ZW50LmpxdWVyeSkpIHtcbiAgICAgICAgICAvLyBDb250ZW50IGlzIGEgRE9NIG5vZGUgb3IgYSBqUXVlcnlcbiAgICAgICAgICBpZiAoaHRtbCkge1xuICAgICAgICAgICAgaWYgKCEkJCQxKGNvbnRlbnQpLnBhcmVudCgpLmlzKCRlbGVtZW50KSkge1xuICAgICAgICAgICAgICAkZWxlbWVudC5lbXB0eSgpLmFwcGVuZChjb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJGVsZW1lbnQudGV4dCgkJCQxKGNvbnRlbnQpLnRleHQoKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICRlbGVtZW50W2h0bWwgPyAnaHRtbCcgOiAndGV4dCddKGNvbnRlbnQpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZ2V0VGl0bGUgPSBmdW5jdGlvbiBnZXRUaXRsZSgpIHtcbiAgICAgICAgdmFyIHRpdGxlID0gdGhpcy5lbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC10aXRsZScpO1xuXG4gICAgICAgIGlmICghdGl0bGUpIHtcbiAgICAgICAgICB0aXRsZSA9IHR5cGVvZiB0aGlzLmNvbmZpZy50aXRsZSA9PT0gJ2Z1bmN0aW9uJyA/IHRoaXMuY29uZmlnLnRpdGxlLmNhbGwodGhpcy5lbGVtZW50KSA6IHRoaXMuY29uZmlnLnRpdGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRpdGxlO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0QXR0YWNobWVudCA9IGZ1bmN0aW9uIF9nZXRBdHRhY2htZW50KHBsYWNlbWVudCkge1xuICAgICAgICByZXR1cm4gQXR0YWNobWVudE1hcFtwbGFjZW1lbnQudG9VcHBlckNhc2UoKV07XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX3NldExpc3RlbmVycyA9IGZ1bmN0aW9uIF9zZXRMaXN0ZW5lcnMoKSB7XG4gICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgIHZhciB0cmlnZ2VycyA9IHRoaXMuY29uZmlnLnRyaWdnZXIuc3BsaXQoJyAnKTtcbiAgICAgICAgdHJpZ2dlcnMuZm9yRWFjaChmdW5jdGlvbiAodHJpZ2dlcikge1xuICAgICAgICAgIGlmICh0cmlnZ2VyID09PSAnY2xpY2snKSB7XG4gICAgICAgICAgICAkJCQxKF90aGlzMy5lbGVtZW50KS5vbihfdGhpczMuY29uc3RydWN0b3IuRXZlbnQuQ0xJQ0ssIF90aGlzMy5jb25maWcuc2VsZWN0b3IsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICByZXR1cm4gX3RoaXMzLnRvZ2dsZShldmVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRyaWdnZXIgIT09IFRyaWdnZXIuTUFOVUFMKSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRJbiA9IHRyaWdnZXIgPT09IFRyaWdnZXIuSE9WRVIgPyBfdGhpczMuY29uc3RydWN0b3IuRXZlbnQuTU9VU0VFTlRFUiA6IF90aGlzMy5jb25zdHJ1Y3Rvci5FdmVudC5GT0NVU0lOO1xuICAgICAgICAgICAgdmFyIGV2ZW50T3V0ID0gdHJpZ2dlciA9PT0gVHJpZ2dlci5IT1ZFUiA/IF90aGlzMy5jb25zdHJ1Y3Rvci5FdmVudC5NT1VTRUxFQVZFIDogX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50LkZPQ1VTT1VUO1xuICAgICAgICAgICAgJCQkMShfdGhpczMuZWxlbWVudCkub24oZXZlbnRJbiwgX3RoaXMzLmNvbmZpZy5zZWxlY3RvciwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgIHJldHVybiBfdGhpczMuX2VudGVyKGV2ZW50KTtcbiAgICAgICAgICAgIH0pLm9uKGV2ZW50T3V0LCBfdGhpczMuY29uZmlnLnNlbGVjdG9yLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIF90aGlzMy5fbGVhdmUoZXZlbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJCQkMShfdGhpczMuZWxlbWVudCkuY2xvc2VzdCgnLm1vZGFsJykub24oJ2hpZGUuYnMubW9kYWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMzLmhpZGUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNlbGVjdG9yKSB7XG4gICAgICAgICAgdGhpcy5jb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCB0aGlzLmNvbmZpZywge1xuICAgICAgICAgICAgdHJpZ2dlcjogJ21hbnVhbCcsXG4gICAgICAgICAgICBzZWxlY3RvcjogJydcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLl9maXhUaXRsZSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2ZpeFRpdGxlID0gZnVuY3Rpb24gX2ZpeFRpdGxlKCkge1xuICAgICAgICB2YXIgdGl0bGVUeXBlID0gdHlwZW9mIHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtb3JpZ2luYWwtdGl0bGUnKTtcblxuICAgICAgICBpZiAodGhpcy5lbGVtZW50LmdldEF0dHJpYnV0ZSgndGl0bGUnKSB8fCB0aXRsZVR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5lbGVtZW50LnNldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC10aXRsZScsIHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykgfHwgJycpO1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2VudGVyID0gZnVuY3Rpb24gX2VudGVyKGV2ZW50LCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBkYXRhS2V5ID0gdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTtcbiAgICAgICAgY29udGV4dCA9IGNvbnRleHQgfHwgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXkpO1xuXG4gICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgIGNvbnRleHQgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihldmVudC5jdXJyZW50VGFyZ2V0LCB0aGlzLl9nZXREZWxlZ2F0ZUNvbmZpZygpKTtcbiAgICAgICAgICAkJCQxKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmRhdGEoZGF0YUtleSwgY29udGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICBjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyW2V2ZW50LnR5cGUgPT09ICdmb2N1c2luJyA/IFRyaWdnZXIuRk9DVVMgOiBUcmlnZ2VyLkhPVkVSXSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJCQkMShjb250ZXh0LmdldFRpcEVsZW1lbnQoKSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpIHx8IGNvbnRleHQuX2hvdmVyU3RhdGUgPT09IEhvdmVyU3RhdGUuU0hPVykge1xuICAgICAgICAgIGNvbnRleHQuX2hvdmVyU3RhdGUgPSBIb3ZlclN0YXRlLlNIT1c7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYXJUaW1lb3V0KGNvbnRleHQuX3RpbWVvdXQpO1xuICAgICAgICBjb250ZXh0Ll9ob3ZlclN0YXRlID0gSG92ZXJTdGF0ZS5TSE9XO1xuXG4gICAgICAgIGlmICghY29udGV4dC5jb25maWcuZGVsYXkgfHwgIWNvbnRleHQuY29uZmlnLmRlbGF5LnNob3cpIHtcbiAgICAgICAgICBjb250ZXh0LnNob3coKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0Ll90aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKGNvbnRleHQuX2hvdmVyU3RhdGUgPT09IEhvdmVyU3RhdGUuU0hPVykge1xuICAgICAgICAgICAgY29udGV4dC5zaG93KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCBjb250ZXh0LmNvbmZpZy5kZWxheS5zaG93KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fbGVhdmUgPSBmdW5jdGlvbiBfbGVhdmUoZXZlbnQsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGRhdGFLZXkgPSB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZO1xuICAgICAgICBjb250ZXh0ID0gY29udGV4dCB8fCAkJCQxKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmRhdGEoZGF0YUtleSk7XG5cbiAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgY29udGV4dCA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKGV2ZW50LmN1cnJlbnRUYXJnZXQsIHRoaXMuX2dldERlbGVnYXRlQ29uZmlnKCkpO1xuICAgICAgICAgICQkJDEoZXZlbnQuY3VycmVudFRhcmdldCkuZGF0YShkYXRhS2V5LCBjb250ZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgIGNvbnRleHQuX2FjdGl2ZVRyaWdnZXJbZXZlbnQudHlwZSA9PT0gJ2ZvY3Vzb3V0JyA/IFRyaWdnZXIuRk9DVVMgOiBUcmlnZ2VyLkhPVkVSXSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHQuX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsZWFyVGltZW91dChjb250ZXh0Ll90aW1lb3V0KTtcbiAgICAgICAgY29udGV4dC5faG92ZXJTdGF0ZSA9IEhvdmVyU3RhdGUuT1VUO1xuXG4gICAgICAgIGlmICghY29udGV4dC5jb25maWcuZGVsYXkgfHwgIWNvbnRleHQuY29uZmlnLmRlbGF5LmhpZGUpIHtcbiAgICAgICAgICBjb250ZXh0LmhpZGUoKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0Ll90aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKGNvbnRleHQuX2hvdmVyU3RhdGUgPT09IEhvdmVyU3RhdGUuT1VUKSB7XG4gICAgICAgICAgICBjb250ZXh0LmhpZGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIGNvbnRleHQuY29uZmlnLmRlbGF5LmhpZGUpO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl9pc1dpdGhBY3RpdmVUcmlnZ2VyID0gZnVuY3Rpb24gX2lzV2l0aEFjdGl2ZVRyaWdnZXIoKSB7XG4gICAgICAgIGZvciAodmFyIHRyaWdnZXIgaW4gdGhpcy5fYWN0aXZlVHJpZ2dlcikge1xuICAgICAgICAgIGlmICh0aGlzLl9hY3RpdmVUcmlnZ2VyW3RyaWdnZXJdKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZyA9IF9vYmplY3RTcHJlYWQoe30sIHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdCwgJCQkMSh0aGlzLmVsZW1lbnQpLmRhdGEoKSwgdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnID8gY29uZmlnIDoge30pO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnLmRlbGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGNvbmZpZy5kZWxheSA9IHtcbiAgICAgICAgICAgIHNob3c6IGNvbmZpZy5kZWxheSxcbiAgICAgICAgICAgIGhpZGU6IGNvbmZpZy5kZWxheVxuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZy50aXRsZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb25maWcudGl0bGUgPSBjb25maWcudGl0bGUudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnLmNvbnRlbnQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgY29uZmlnLmNvbnRlbnQgPSBjb25maWcuY29udGVudC50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCB0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRUeXBlKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fZ2V0RGVsZWdhdGVDb25maWcgPSBmdW5jdGlvbiBfZ2V0RGVsZWdhdGVDb25maWcoKSB7XG4gICAgICAgIHZhciBjb25maWcgPSB7fTtcblxuICAgICAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5jb25maWcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLkRlZmF1bHRba2V5XSAhPT0gdGhpcy5jb25maWdba2V5XSkge1xuICAgICAgICAgICAgICBjb25maWdba2V5XSA9IHRoaXMuY29uZmlnW2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fY2xlYW5UaXBDbGFzcyA9IGZ1bmN0aW9uIF9jbGVhblRpcENsYXNzKCkge1xuICAgICAgICB2YXIgJHRpcCA9ICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpO1xuICAgICAgICB2YXIgdGFiQ2xhc3MgPSAkdGlwLmF0dHIoJ2NsYXNzJykubWF0Y2goQlNDTFNfUFJFRklYX1JFR0VYKTtcblxuICAgICAgICBpZiAodGFiQ2xhc3MgIT09IG51bGwgJiYgdGFiQ2xhc3MubGVuZ3RoKSB7XG4gICAgICAgICAgJHRpcC5yZW1vdmVDbGFzcyh0YWJDbGFzcy5qb2luKCcnKSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5faGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlID0gZnVuY3Rpb24gX2hhbmRsZVBvcHBlclBsYWNlbWVudENoYW5nZShwb3BwZXJEYXRhKSB7XG4gICAgICAgIHZhciBwb3BwZXJJbnN0YW5jZSA9IHBvcHBlckRhdGEuaW5zdGFuY2U7XG4gICAgICAgIHRoaXMudGlwID0gcG9wcGVySW5zdGFuY2UucG9wcGVyO1xuXG4gICAgICAgIHRoaXMuX2NsZWFuVGlwQ2xhc3MoKTtcblxuICAgICAgICB0aGlzLmFkZEF0dGFjaG1lbnRDbGFzcyh0aGlzLl9nZXRBdHRhY2htZW50KHBvcHBlckRhdGEucGxhY2VtZW50KSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2ZpeFRyYW5zaXRpb24gPSBmdW5jdGlvbiBfZml4VHJhbnNpdGlvbigpIHtcbiAgICAgICAgdmFyIHRpcCA9IHRoaXMuZ2V0VGlwRWxlbWVudCgpO1xuICAgICAgICB2YXIgaW5pdENvbmZpZ0FuaW1hdGlvbiA9IHRoaXMuY29uZmlnLmFuaW1hdGlvbjtcblxuICAgICAgICBpZiAodGlwLmdldEF0dHJpYnV0ZSgneC1wbGFjZW1lbnQnKSAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgICQkJDEodGlwKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuRkFERSk7XG4gICAgICAgIHRoaXMuY29uZmlnLmFuaW1hdGlvbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgICAgdGhpcy5zaG93KCk7XG4gICAgICAgIHRoaXMuY29uZmlnLmFuaW1hdGlvbiA9IGluaXRDb25maWdBbmltYXRpb247XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBUb29sdGlwLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZztcblxuICAgICAgICAgIGlmICghZGF0YSAmJiAvZGlzcG9zZXxoaWRlLy50ZXN0KGNvbmZpZykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgVG9vbHRpcCh0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoVG9vbHRpcCwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIk5BTUVcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIE5BTUU7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkRBVEFfS0VZXCIsXG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiBEQVRBX0tFWTtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRXZlbnRcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJFVkVOVF9LRVlcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIEVWRU5UX0tFWTtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFR5cGVcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERlZmF1bHRUeXBlO1xuICAgICAgICB9XG4gICAgICB9XSk7XG5cbiAgICAgIHJldHVybiBUb29sdGlwO1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMS5mbltOQU1FXSA9IFRvb2x0aXAuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gVG9vbHRpcDtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gVG9vbHRpcC5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gVG9vbHRpcDtcbiAgfSgkLCBQb3BwZXIpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IHBvcG92ZXIuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIFBvcG92ZXIgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENvbnN0YW50c1xuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuICAgIHZhciBOQU1FID0gJ3BvcG92ZXInO1xuICAgIHZhciBWRVJTSU9OID0gJzQuMS4zJztcbiAgICB2YXIgREFUQV9LRVkgPSAnYnMucG9wb3Zlcic7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gICAgdmFyIENMQVNTX1BSRUZJWCA9ICdicy1wb3BvdmVyJztcbiAgICB2YXIgQlNDTFNfUFJFRklYX1JFR0VYID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgQ0xBU1NfUFJFRklYICsgXCJcXFxcUytcIiwgJ2cnKTtcblxuICAgIHZhciBEZWZhdWx0ID0gX29iamVjdFNwcmVhZCh7fSwgVG9vbHRpcC5EZWZhdWx0LCB7XG4gICAgICBwbGFjZW1lbnQ6ICdyaWdodCcsXG4gICAgICB0cmlnZ2VyOiAnY2xpY2snLFxuICAgICAgY29udGVudDogJycsXG4gICAgICB0ZW1wbGF0ZTogJzxkaXYgY2xhc3M9XCJwb3BvdmVyXCIgcm9sZT1cInRvb2x0aXBcIj4nICsgJzxkaXYgY2xhc3M9XCJhcnJvd1wiPjwvZGl2PicgKyAnPGgzIGNsYXNzPVwicG9wb3Zlci1oZWFkZXJcIj48L2gzPicgKyAnPGRpdiBjbGFzcz1cInBvcG92ZXItYm9keVwiPjwvZGl2PjwvZGl2PidcbiAgICB9KTtcblxuICAgIHZhciBEZWZhdWx0VHlwZSA9IF9vYmplY3RTcHJlYWQoe30sIFRvb2x0aXAuRGVmYXVsdFR5cGUsIHtcbiAgICAgIGNvbnRlbnQ6ICcoc3RyaW5nfGVsZW1lbnR8ZnVuY3Rpb24pJ1xuICAgIH0pO1xuXG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIEZBREU6ICdmYWRlJyxcbiAgICAgIFNIT1c6ICdzaG93J1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgVElUTEU6ICcucG9wb3Zlci1oZWFkZXInLFxuICAgICAgQ09OVEVOVDogJy5wb3BvdmVyLWJvZHknXG4gICAgfTtcbiAgICB2YXIgRXZlbnQgPSB7XG4gICAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICAgIElOU0VSVEVEOiBcImluc2VydGVkXCIgKyBFVkVOVF9LRVksXG4gICAgICBDTElDSzogXCJjbGlja1wiICsgRVZFTlRfS0VZLFxuICAgICAgRk9DVVNJTjogXCJmb2N1c2luXCIgKyBFVkVOVF9LRVksXG4gICAgICBGT0NVU09VVDogXCJmb2N1c291dFwiICsgRVZFTlRfS0VZLFxuICAgICAgTU9VU0VFTlRFUjogXCJtb3VzZWVudGVyXCIgKyBFVkVOVF9LRVksXG4gICAgICBNT1VTRUxFQVZFOiBcIm1vdXNlbGVhdmVcIiArIEVWRU5UX0tFWVxuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIFBvcG92ZXIgPVxuICAgIC8qI19fUFVSRV9fKi9cbiAgICBmdW5jdGlvbiAoX1Rvb2x0aXApIHtcbiAgICAgIF9pbmhlcml0c0xvb3NlKFBvcG92ZXIsIF9Ub29sdGlwKTtcblxuICAgICAgZnVuY3Rpb24gUG9wb3ZlcigpIHtcbiAgICAgICAgcmV0dXJuIF9Ub29sdGlwLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgIH1cblxuICAgICAgdmFyIF9wcm90byA9IFBvcG92ZXIucHJvdG90eXBlO1xuXG4gICAgICAvLyBPdmVycmlkZXNcbiAgICAgIF9wcm90by5pc1dpdGhDb250ZW50ID0gZnVuY3Rpb24gaXNXaXRoQ29udGVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGl0bGUoKSB8fCB0aGlzLl9nZXRDb250ZW50KCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uYWRkQXR0YWNobWVudENsYXNzID0gZnVuY3Rpb24gYWRkQXR0YWNobWVudENsYXNzKGF0dGFjaG1lbnQpIHtcbiAgICAgICAgJCQkMSh0aGlzLmdldFRpcEVsZW1lbnQoKSkuYWRkQ2xhc3MoQ0xBU1NfUFJFRklYICsgXCItXCIgKyBhdHRhY2htZW50KTtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5nZXRUaXBFbGVtZW50ID0gZnVuY3Rpb24gZ2V0VGlwRWxlbWVudCgpIHtcbiAgICAgICAgdGhpcy50aXAgPSB0aGlzLnRpcCB8fCAkJCQxKHRoaXMuY29uZmlnLnRlbXBsYXRlKVswXTtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlwO1xuICAgICAgfTtcblxuICAgICAgX3Byb3RvLnNldENvbnRlbnQgPSBmdW5jdGlvbiBzZXRDb250ZW50KCkge1xuICAgICAgICB2YXIgJHRpcCA9ICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpOyAvLyBXZSB1c2UgYXBwZW5kIGZvciBodG1sIG9iamVjdHMgdG8gbWFpbnRhaW4ganMgZXZlbnRzXG5cbiAgICAgICAgdGhpcy5zZXRFbGVtZW50Q29udGVudCgkdGlwLmZpbmQoU2VsZWN0b3IuVElUTEUpLCB0aGlzLmdldFRpdGxlKCkpO1xuXG4gICAgICAgIHZhciBjb250ZW50ID0gdGhpcy5fZ2V0Q29udGVudCgpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LmNhbGwodGhpcy5lbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0RWxlbWVudENvbnRlbnQoJHRpcC5maW5kKFNlbGVjdG9yLkNPTlRFTlQpLCBjb250ZW50KTtcbiAgICAgICAgJHRpcC5yZW1vdmVDbGFzcyhDbGFzc05hbWUuRkFERSArIFwiIFwiICsgQ2xhc3NOYW1lLlNIT1cpO1xuICAgICAgfTsgLy8gUHJpdmF0ZVxuXG5cbiAgICAgIF9wcm90by5fZ2V0Q29udGVudCA9IGZ1bmN0aW9uIF9nZXRDb250ZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1jb250ZW50JykgfHwgdGhpcy5jb25maWcuY29udGVudDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fY2xlYW5UaXBDbGFzcyA9IGZ1bmN0aW9uIF9jbGVhblRpcENsYXNzKCkge1xuICAgICAgICB2YXIgJHRpcCA9ICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpO1xuICAgICAgICB2YXIgdGFiQ2xhc3MgPSAkdGlwLmF0dHIoJ2NsYXNzJykubWF0Y2goQlNDTFNfUFJFRklYX1JFR0VYKTtcblxuICAgICAgICBpZiAodGFiQ2xhc3MgIT09IG51bGwgJiYgdGFiQ2xhc3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICR0aXAucmVtb3ZlQ2xhc3ModGFiQ2xhc3Muam9pbignJykpO1xuICAgICAgICB9XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBQb3BvdmVyLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICB2YXIgX2NvbmZpZyA9IHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnID8gY29uZmlnIDogbnVsbDtcblxuICAgICAgICAgIGlmICghZGF0YSAmJiAvZGVzdHJveXxoaWRlLy50ZXN0KGNvbmZpZykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgUG9wb3Zlcih0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoUG9wb3ZlciwgbnVsbCwgW3tcbiAgICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgICAgLy8gR2V0dGVyc1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiTkFNRVwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiREFUQV9LRVlcIixcbiAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgcmV0dXJuIERBVEFfS0VZO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJFdmVudFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRXZlbnQ7XG4gICAgICAgIH1cbiAgICAgIH0sIHtcbiAgICAgICAga2V5OiBcIkVWRU5UX0tFWVwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRVZFTlRfS0VZO1xuICAgICAgICB9XG4gICAgICB9LCB7XG4gICAgICAgIGtleTogXCJEZWZhdWx0VHlwZVwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdFR5cGU7XG4gICAgICAgIH1cbiAgICAgIH1dKTtcblxuICAgICAgcmV0dXJuIFBvcG92ZXI7XG4gICAgfShUb29sdGlwKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuXG4gICAgJCQkMS5mbltOQU1FXSA9IFBvcG92ZXIuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gUG9wb3ZlcjtcblxuICAgICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgICByZXR1cm4gUG9wb3Zlci5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gUG9wb3ZlcjtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiBzY3JvbGxzcHkuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIFNjcm9sbFNweSA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ29uc3RhbnRzXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG4gICAgdmFyIE5BTUUgPSAnc2Nyb2xsc3B5JztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLnNjcm9sbHNweSc7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBEZWZhdWx0ID0ge1xuICAgICAgb2Zmc2V0OiAxMCxcbiAgICAgIG1ldGhvZDogJ2F1dG8nLFxuICAgICAgdGFyZ2V0OiAnJ1xuICAgIH07XG4gICAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgICAgb2Zmc2V0OiAnbnVtYmVyJyxcbiAgICAgIG1ldGhvZDogJ3N0cmluZycsXG4gICAgICB0YXJnZXQ6ICcoc3RyaW5nfGVsZW1lbnQpJ1xuICAgIH07XG4gICAgdmFyIEV2ZW50ID0ge1xuICAgICAgQUNUSVZBVEU6IFwiYWN0aXZhdGVcIiArIEVWRU5UX0tFWSxcbiAgICAgIFNDUk9MTDogXCJzY3JvbGxcIiArIEVWRU5UX0tFWSxcbiAgICAgIExPQURfREFUQV9BUEk6IFwibG9hZFwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gICAgfTtcbiAgICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgICAgRFJPUERPV05fSVRFTTogJ2Ryb3Bkb3duLWl0ZW0nLFxuICAgICAgRFJPUERPV05fTUVOVTogJ2Ryb3Bkb3duLW1lbnUnLFxuICAgICAgQUNUSVZFOiAnYWN0aXZlJ1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgREFUQV9TUFk6ICdbZGF0YS1zcHk9XCJzY3JvbGxcIl0nLFxuICAgICAgQUNUSVZFOiAnLmFjdGl2ZScsXG4gICAgICBOQVZfTElTVF9HUk9VUDogJy5uYXYsIC5saXN0LWdyb3VwJyxcbiAgICAgIE5BVl9MSU5LUzogJy5uYXYtbGluaycsXG4gICAgICBOQVZfSVRFTVM6ICcubmF2LWl0ZW0nLFxuICAgICAgTElTVF9JVEVNUzogJy5saXN0LWdyb3VwLWl0ZW0nLFxuICAgICAgRFJPUERPV046ICcuZHJvcGRvd24nLFxuICAgICAgRFJPUERPV05fSVRFTVM6ICcuZHJvcGRvd24taXRlbScsXG4gICAgICBEUk9QRE9XTl9UT0dHTEU6ICcuZHJvcGRvd24tdG9nZ2xlJ1xuICAgIH07XG4gICAgdmFyIE9mZnNldE1ldGhvZCA9IHtcbiAgICAgIE9GRlNFVDogJ29mZnNldCcsXG4gICAgICBQT1NJVElPTjogJ3Bvc2l0aW9uJ1xuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIFNjcm9sbFNweSA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIFNjcm9sbFNweShlbGVtZW50LCBjb25maWcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5fc2Nyb2xsRWxlbWVudCA9IGVsZW1lbnQudGFnTmFtZSA9PT0gJ0JPRFknID8gd2luZG93IDogZWxlbWVudDtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICAgIHRoaXMuX3NlbGVjdG9yID0gdGhpcy5fY29uZmlnLnRhcmdldCArIFwiIFwiICsgU2VsZWN0b3IuTkFWX0xJTktTICsgXCIsXCIgKyAodGhpcy5fY29uZmlnLnRhcmdldCArIFwiIFwiICsgU2VsZWN0b3IuTElTVF9JVEVNUyArIFwiLFwiKSArICh0aGlzLl9jb25maWcudGFyZ2V0ICsgXCIgXCIgKyBTZWxlY3Rvci5EUk9QRE9XTl9JVEVNUyk7XG4gICAgICAgIHRoaXMuX29mZnNldHMgPSBbXTtcbiAgICAgICAgdGhpcy5fdGFyZ2V0cyA9IFtdO1xuICAgICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSBudWxsO1xuICAgICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSAwO1xuICAgICAgICAkJCQxKHRoaXMuX3Njcm9sbEVsZW1lbnQpLm9uKEV2ZW50LlNDUk9MTCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzLl9wcm9jZXNzKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVmcmVzaCgpO1xuXG4gICAgICAgIHRoaXMuX3Byb2Nlc3MoKTtcbiAgICAgIH0gLy8gR2V0dGVyc1xuXG5cbiAgICAgIHZhciBfcHJvdG8gPSBTY3JvbGxTcHkucHJvdG90eXBlO1xuXG4gICAgICAvLyBQdWJsaWNcbiAgICAgIF9wcm90by5yZWZyZXNoID0gZnVuY3Rpb24gcmVmcmVzaCgpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGF1dG9NZXRob2QgPSB0aGlzLl9zY3JvbGxFbGVtZW50ID09PSB0aGlzLl9zY3JvbGxFbGVtZW50LndpbmRvdyA/IE9mZnNldE1ldGhvZC5PRkZTRVQgOiBPZmZzZXRNZXRob2QuUE9TSVRJT047XG4gICAgICAgIHZhciBvZmZzZXRNZXRob2QgPSB0aGlzLl9jb25maWcubWV0aG9kID09PSAnYXV0bycgPyBhdXRvTWV0aG9kIDogdGhpcy5fY29uZmlnLm1ldGhvZDtcbiAgICAgICAgdmFyIG9mZnNldEJhc2UgPSBvZmZzZXRNZXRob2QgPT09IE9mZnNldE1ldGhvZC5QT1NJVElPTiA/IHRoaXMuX2dldFNjcm9sbFRvcCgpIDogMDtcbiAgICAgICAgdGhpcy5fb2Zmc2V0cyA9IFtdO1xuICAgICAgICB0aGlzLl90YXJnZXRzID0gW107XG4gICAgICAgIHRoaXMuX3Njcm9sbEhlaWdodCA9IHRoaXMuX2dldFNjcm9sbEhlaWdodCgpO1xuICAgICAgICB2YXIgdGFyZ2V0cyA9IFtdLnNsaWNlLmNhbGwoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCh0aGlzLl9zZWxlY3RvcikpO1xuICAgICAgICB0YXJnZXRzLm1hcChmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgIHZhciB0YXJnZXQ7XG4gICAgICAgICAgdmFyIHRhcmdldFNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICAgICAgaWYgKHRhcmdldFNlbGVjdG9yKSB7XG4gICAgICAgICAgICB0YXJnZXQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRhcmdldFNlbGVjdG9yKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGFyZ2V0KSB7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0QkNSID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICAgICAgICBpZiAodGFyZ2V0QkNSLndpZHRoIHx8IHRhcmdldEJDUi5oZWlnaHQpIHtcbiAgICAgICAgICAgICAgLy8gVE9ETyAoZmF0KTogcmVtb3ZlIHNrZXRjaCByZWxpYW5jZSBvbiBqUXVlcnkgcG9zaXRpb24vb2Zmc2V0XG4gICAgICAgICAgICAgIHJldHVybiBbJCQkMSh0YXJnZXQpW29mZnNldE1ldGhvZF0oKS50b3AgKyBvZmZzZXRCYXNlLCB0YXJnZXRTZWxlY3Rvcl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0pLmZpbHRlcihmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICB9KS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgcmV0dXJuIGFbMF0gLSBiWzBdO1xuICAgICAgICB9KS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgX3RoaXMyLl9vZmZzZXRzLnB1c2goaXRlbVswXSk7XG5cbiAgICAgICAgICBfdGhpczIuX3RhcmdldHMucHVzaChpdGVtWzFdKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAgICQkJDEodGhpcy5fc2Nyb2xsRWxlbWVudCkub2ZmKEVWRU5UX0tFWSk7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLl9zY3JvbGxFbGVtZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fY29uZmlnID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2VsZWN0b3IgPSBudWxsO1xuICAgICAgICB0aGlzLl9vZmZzZXRzID0gbnVsbDtcbiAgICAgICAgdGhpcy5fdGFyZ2V0cyA9IG51bGw7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG4gICAgICAgIHRoaXMuX3Njcm9sbEhlaWdodCA9IG51bGw7XG4gICAgICB9OyAvLyBQcml2YXRlXG5cblxuICAgICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgICBjb25maWcgPSBfb2JqZWN0U3ByZWFkKHt9LCBEZWZhdWx0LCB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyAmJiBjb25maWcgPyBjb25maWcgOiB7fSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcudGFyZ2V0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIHZhciBpZCA9ICQkJDEoY29uZmlnLnRhcmdldCkuYXR0cignaWQnKTtcblxuICAgICAgICAgIGlmICghaWQpIHtcbiAgICAgICAgICAgIGlkID0gVXRpbC5nZXRVSUQoTkFNRSk7XG4gICAgICAgICAgICAkJCQxKGNvbmZpZy50YXJnZXQpLmF0dHIoJ2lkJywgaWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbmZpZy50YXJnZXQgPSBcIiNcIiArIGlkO1xuICAgICAgICB9XG5cbiAgICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCBEZWZhdWx0VHlwZSk7XG4gICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldFNjcm9sbFRvcCA9IGZ1bmN0aW9uIF9nZXRTY3JvbGxUb3AoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50ID09PSB3aW5kb3cgPyB0aGlzLl9zY3JvbGxFbGVtZW50LnBhZ2VZT2Zmc2V0IDogdGhpcy5fc2Nyb2xsRWxlbWVudC5zY3JvbGxUb3A7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uIF9nZXRTY3JvbGxIZWlnaHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50LnNjcm9sbEhlaWdodCB8fCBNYXRoLm1heChkb2N1bWVudC5ib2R5LnNjcm9sbEhlaWdodCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbEhlaWdodCk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2dldE9mZnNldEhlaWdodCA9IGZ1bmN0aW9uIF9nZXRPZmZzZXRIZWlnaHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zY3JvbGxFbGVtZW50ID09PSB3aW5kb3cgPyB3aW5kb3cuaW5uZXJIZWlnaHQgOiB0aGlzLl9zY3JvbGxFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodDtcbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fcHJvY2VzcyA9IGZ1bmN0aW9uIF9wcm9jZXNzKCkge1xuICAgICAgICB2YXIgc2Nyb2xsVG9wID0gdGhpcy5fZ2V0U2Nyb2xsVG9wKCkgKyB0aGlzLl9jb25maWcub2Zmc2V0O1xuXG4gICAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSB0aGlzLl9nZXRTY3JvbGxIZWlnaHQoKTtcblxuICAgICAgICB2YXIgbWF4U2Nyb2xsID0gdGhpcy5fY29uZmlnLm9mZnNldCArIHNjcm9sbEhlaWdodCAtIHRoaXMuX2dldE9mZnNldEhlaWdodCgpO1xuXG4gICAgICAgIGlmICh0aGlzLl9zY3JvbGxIZWlnaHQgIT09IHNjcm9sbEhlaWdodCkge1xuICAgICAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNjcm9sbFRvcCA+PSBtYXhTY3JvbGwpIHtcbiAgICAgICAgICB2YXIgdGFyZ2V0ID0gdGhpcy5fdGFyZ2V0c1t0aGlzLl90YXJnZXRzLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRhcmdldCAhPT0gdGFyZ2V0KSB7XG4gICAgICAgICAgICB0aGlzLl9hY3RpdmF0ZSh0YXJnZXQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9hY3RpdmVUYXJnZXQgJiYgc2Nyb2xsVG9wIDwgdGhpcy5fb2Zmc2V0c1swXSAmJiB0aGlzLl9vZmZzZXRzWzBdID4gMCkge1xuICAgICAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG5cbiAgICAgICAgICB0aGlzLl9jbGVhcigpO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG9mZnNldExlbmd0aCA9IHRoaXMuX29mZnNldHMubGVuZ3RoO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSBvZmZzZXRMZW5ndGg7IGktLTspIHtcbiAgICAgICAgICB2YXIgaXNBY3RpdmVUYXJnZXQgPSB0aGlzLl9hY3RpdmVUYXJnZXQgIT09IHRoaXMuX3RhcmdldHNbaV0gJiYgc2Nyb2xsVG9wID49IHRoaXMuX29mZnNldHNbaV0gJiYgKHR5cGVvZiB0aGlzLl9vZmZzZXRzW2kgKyAxXSA9PT0gJ3VuZGVmaW5lZCcgfHwgc2Nyb2xsVG9wIDwgdGhpcy5fb2Zmc2V0c1tpICsgMV0pO1xuXG4gICAgICAgICAgaWYgKGlzQWN0aXZlVGFyZ2V0KSB7XG4gICAgICAgICAgICB0aGlzLl9hY3RpdmF0ZSh0aGlzLl90YXJnZXRzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5fYWN0aXZhdGUgPSBmdW5jdGlvbiBfYWN0aXZhdGUodGFyZ2V0KSB7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IHRhcmdldDtcblxuICAgICAgICB0aGlzLl9jbGVhcigpO1xuXG4gICAgICAgIHZhciBxdWVyaWVzID0gdGhpcy5fc2VsZWN0b3Iuc3BsaXQoJywnKTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGFycm93LWJvZHktc3R5bGVcblxuXG4gICAgICAgIHF1ZXJpZXMgPSBxdWVyaWVzLm1hcChmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICByZXR1cm4gc2VsZWN0b3IgKyBcIltkYXRhLXRhcmdldD1cXFwiXCIgKyB0YXJnZXQgKyBcIlxcXCJdLFwiICsgKHNlbGVjdG9yICsgXCJbaHJlZj1cXFwiXCIgKyB0YXJnZXQgKyBcIlxcXCJdXCIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyICRsaW5rID0gJCQkMShbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwocXVlcmllcy5qb2luKCcsJykpKSk7XG5cbiAgICAgICAgaWYgKCRsaW5rLmhhc0NsYXNzKENsYXNzTmFtZS5EUk9QRE9XTl9JVEVNKSkge1xuICAgICAgICAgICRsaW5rLmNsb3Nlc3QoU2VsZWN0b3IuRFJPUERPV04pLmZpbmQoU2VsZWN0b3IuRFJPUERPV05fVE9HR0xFKS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICAkbGluay5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBTZXQgdHJpZ2dlcmVkIGxpbmsgYXMgYWN0aXZlXG4gICAgICAgICAgJGxpbmsuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7IC8vIFNldCB0cmlnZ2VyZWQgbGlua3MgcGFyZW50cyBhcyBhY3RpdmVcbiAgICAgICAgICAvLyBXaXRoIGJvdGggPHVsPiBhbmQgPG5hdj4gbWFya3VwIGEgcGFyZW50IGlzIHRoZSBwcmV2aW91cyBzaWJsaW5nIG9mIGFueSBuYXYgYW5jZXN0b3JcblxuICAgICAgICAgICRsaW5rLnBhcmVudHMoU2VsZWN0b3IuTkFWX0xJU1RfR1JPVVApLnByZXYoU2VsZWN0b3IuTkFWX0xJTktTICsgXCIsIFwiICsgU2VsZWN0b3IuTElTVF9JVEVNUykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7IC8vIEhhbmRsZSBzcGVjaWFsIGNhc2Ugd2hlbiAubmF2LWxpbmsgaXMgaW5zaWRlIC5uYXYtaXRlbVxuXG4gICAgICAgICAgJGxpbmsucGFyZW50cyhTZWxlY3Rvci5OQVZfTElTVF9HUk9VUCkucHJldihTZWxlY3Rvci5OQVZfSVRFTVMpLmNoaWxkcmVuKFNlbGVjdG9yLk5BVl9MSU5LUykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRoaXMuX3Njcm9sbEVsZW1lbnQpLnRyaWdnZXIoRXZlbnQuQUNUSVZBVEUsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiB0YXJnZXRcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfcHJvdG8uX2NsZWFyID0gZnVuY3Rpb24gX2NsZWFyKCkge1xuICAgICAgICB2YXIgbm9kZXMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5fc2VsZWN0b3IpKTtcbiAgICAgICAgJCQkMShub2RlcykuZmlsdGVyKFNlbGVjdG9yLkFDVElWRSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICB9OyAvLyBTdGF0aWNcblxuXG4gICAgICBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHZhciBkYXRhID0gJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICAgIHZhciBfY29uZmlnID0gdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnO1xuXG4gICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICBkYXRhID0gbmV3IFNjcm9sbFNweSh0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoU2Nyb2xsU3B5LCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfSwge1xuICAgICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gU2Nyb2xsU3B5O1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKHdpbmRvdykub24oRXZlbnQuTE9BRF9EQVRBX0FQSSwgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHNjcm9sbFNweXMgPSBbXS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoU2VsZWN0b3IuREFUQV9TUFkpKTtcbiAgICAgIHZhciBzY3JvbGxTcHlzTGVuZ3RoID0gc2Nyb2xsU3B5cy5sZW5ndGg7XG5cbiAgICAgIGZvciAodmFyIGkgPSBzY3JvbGxTcHlzTGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIHZhciAkc3B5ID0gJCQkMShzY3JvbGxTcHlzW2ldKTtcblxuICAgICAgICBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZS5jYWxsKCRzcHksICRzcHkuZGF0YSgpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBqUXVlcnlcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICAgICQkJDEuZm5bTkFNRV0gPSBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZTtcbiAgICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gU2Nyb2xsU3B5O1xuXG4gICAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICAgIHJldHVybiBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFNjcm9sbFNweTtcbiAgfSgkKTtcblxuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQm9vdHN0cmFwICh2NC4xLjMpOiB0YWIuanNcbiAgICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgdmFyIFRhYiA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ29uc3RhbnRzXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG4gICAgdmFyIE5BTUUgPSAndGFiJztcbiAgICB2YXIgVkVSU0lPTiA9ICc0LjEuMyc7XG4gICAgdmFyIERBVEFfS0VZID0gJ2JzLnRhYic7XG4gICAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gICAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICAgIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICAgIHZhciBFdmVudCA9IHtcbiAgICAgIEhJREU6IFwiaGlkZVwiICsgRVZFTlRfS0VZLFxuICAgICAgSElEREVOOiBcImhpZGRlblwiICsgRVZFTlRfS0VZLFxuICAgICAgU0hPVzogXCJzaG93XCIgKyBFVkVOVF9LRVksXG4gICAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICAgIH07XG4gICAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICAgIERST1BET1dOX01FTlU6ICdkcm9wZG93bi1tZW51JyxcbiAgICAgIEFDVElWRTogJ2FjdGl2ZScsXG4gICAgICBESVNBQkxFRDogJ2Rpc2FibGVkJyxcbiAgICAgIEZBREU6ICdmYWRlJyxcbiAgICAgIFNIT1c6ICdzaG93J1xuICAgIH07XG4gICAgdmFyIFNlbGVjdG9yID0ge1xuICAgICAgRFJPUERPV046ICcuZHJvcGRvd24nLFxuICAgICAgTkFWX0xJU1RfR1JPVVA6ICcubmF2LCAubGlzdC1ncm91cCcsXG4gICAgICBBQ1RJVkU6ICcuYWN0aXZlJyxcbiAgICAgIEFDVElWRV9VTDogJz4gbGkgPiAuYWN0aXZlJyxcbiAgICAgIERBVEFfVE9HR0xFOiAnW2RhdGEtdG9nZ2xlPVwidGFiXCJdLCBbZGF0YS10b2dnbGU9XCJwaWxsXCJdLCBbZGF0YS10b2dnbGU9XCJsaXN0XCJdJyxcbiAgICAgIERST1BET1dOX1RPR0dMRTogJy5kcm9wZG93bi10b2dnbGUnLFxuICAgICAgRFJPUERPV05fQUNUSVZFX0NISUxEOiAnPiAuZHJvcGRvd24tbWVudSAuYWN0aXZlJ1xuICAgICAgLyoqXG4gICAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICovXG5cbiAgICB9O1xuXG4gICAgdmFyIFRhYiA9XG4gICAgLyojX19QVVJFX18qL1xuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIFRhYihlbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgfSAvLyBHZXR0ZXJzXG5cblxuICAgICAgdmFyIF9wcm90byA9IFRhYi5wcm90b3R5cGU7XG5cbiAgICAgIC8vIFB1YmxpY1xuICAgICAgX3Byb3RvLnNob3cgPSBmdW5jdGlvbiBzaG93KCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUgJiYgdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5BQ1RJVkUpIHx8ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRJU0FCTEVEKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0YXJnZXQ7XG4gICAgICAgIHZhciBwcmV2aW91cztcbiAgICAgICAgdmFyIGxpc3RFbGVtZW50ID0gJCQkMSh0aGlzLl9lbGVtZW50KS5jbG9zZXN0KFNlbGVjdG9yLk5BVl9MSVNUX0dST1VQKVswXTtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICAgIGlmIChsaXN0RWxlbWVudCkge1xuICAgICAgICAgIHZhciBpdGVtU2VsZWN0b3IgPSBsaXN0RWxlbWVudC5ub2RlTmFtZSA9PT0gJ1VMJyA/IFNlbGVjdG9yLkFDVElWRV9VTCA6IFNlbGVjdG9yLkFDVElWRTtcbiAgICAgICAgICBwcmV2aW91cyA9ICQkJDEubWFrZUFycmF5KCQkJDEobGlzdEVsZW1lbnQpLmZpbmQoaXRlbVNlbGVjdG9yKSk7XG4gICAgICAgICAgcHJldmlvdXMgPSBwcmV2aW91c1twcmV2aW91cy5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBoaWRlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkhJREUsIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiB0aGlzLl9lbGVtZW50XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgc2hvd0V2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XLCB7XG4gICAgICAgICAgcmVsYXRlZFRhcmdldDogcHJldmlvdXNcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgJCQkMShwcmV2aW91cykudHJpZ2dlcihoaWRlRXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHNob3dFdmVudCk7XG5cbiAgICAgICAgaWYgKHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSB8fCBoaWRlRXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICB0YXJnZXQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2FjdGl2YXRlKHRoaXMuX2VsZW1lbnQsIGxpc3RFbGVtZW50KTtcblxuICAgICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgICB2YXIgaGlkZGVuRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkhJRERFTiwge1xuICAgICAgICAgICAgcmVsYXRlZFRhcmdldDogX3RoaXMuX2VsZW1lbnRcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB2YXIgc2hvd25FdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPV04sIHtcbiAgICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHByZXZpb3VzXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgJCQkMShwcmV2aW91cykudHJpZ2dlcihoaWRkZW5FdmVudCk7XG4gICAgICAgICAgJCQkMShfdGhpcy5fZWxlbWVudCkudHJpZ2dlcihzaG93bkV2ZW50KTtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGFyZ2V0KSB7XG4gICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGFyZ2V0LCB0YXJnZXQucGFyZW50Tm9kZSwgY29tcGxldGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICAgJCQkMS5yZW1vdmVEYXRhKHRoaXMuX2VsZW1lbnQsIERBVEFfS0VZKTtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IG51bGw7XG4gICAgICB9OyAvLyBQcml2YXRlXG5cblxuICAgICAgX3Byb3RvLl9hY3RpdmF0ZSA9IGZ1bmN0aW9uIF9hY3RpdmF0ZShlbGVtZW50LCBjb250YWluZXIsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIHZhciBhY3RpdmVFbGVtZW50cztcblxuICAgICAgICBpZiAoY29udGFpbmVyLm5vZGVOYW1lID09PSAnVUwnKSB7XG4gICAgICAgICAgYWN0aXZlRWxlbWVudHMgPSAkJCQxKGNvbnRhaW5lcikuZmluZChTZWxlY3Rvci5BQ1RJVkVfVUwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFjdGl2ZUVsZW1lbnRzID0gJCQkMShjb250YWluZXIpLmNoaWxkcmVuKFNlbGVjdG9yLkFDVElWRSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWN0aXZlID0gYWN0aXZlRWxlbWVudHNbMF07XG4gICAgICAgIHZhciBpc1RyYW5zaXRpb25pbmcgPSBjYWxsYmFjayAmJiBhY3RpdmUgJiYgJCQkMShhY3RpdmUpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKTtcblxuICAgICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLl90cmFuc2l0aW9uQ29tcGxldGUoZWxlbWVudCwgYWN0aXZlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGFjdGl2ZSAmJiBpc1RyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgICB2YXIgdHJhbnNpdGlvbkR1cmF0aW9uID0gVXRpbC5nZXRUcmFuc2l0aW9uRHVyYXRpb25Gcm9tRWxlbWVudChhY3RpdmUpO1xuICAgICAgICAgICQkJDEoYWN0aXZlKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY29tcGxldGUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKHRyYW5zaXRpb25EdXJhdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29tcGxldGUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgX3Byb3RvLl90cmFuc2l0aW9uQ29tcGxldGUgPSBmdW5jdGlvbiBfdHJhbnNpdGlvbkNvbXBsZXRlKGVsZW1lbnQsIGFjdGl2ZSwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKGFjdGl2ZSkge1xuICAgICAgICAgICQkJDEoYWN0aXZlKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyArIFwiIFwiICsgQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgdmFyIGRyb3Bkb3duQ2hpbGQgPSAkJCQxKGFjdGl2ZS5wYXJlbnROb2RlKS5maW5kKFNlbGVjdG9yLkRST1BET1dOX0FDVElWRV9DSElMRClbMF07XG5cbiAgICAgICAgICBpZiAoZHJvcGRvd25DaGlsZCkge1xuICAgICAgICAgICAgJCQkMShkcm9wZG93bkNoaWxkKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYWN0aXZlLmdldEF0dHJpYnV0ZSgncm9sZScpID09PSAndGFiJykge1xuICAgICAgICAgICAgYWN0aXZlLnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsIGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKGVsZW1lbnQpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuXG4gICAgICAgIGlmIChlbGVtZW50LmdldEF0dHJpYnV0ZSgncm9sZScpID09PSAndGFiJykge1xuICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLXNlbGVjdGVkJywgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBVdGlsLnJlZmxvdyhlbGVtZW50KTtcbiAgICAgICAgJCQkMShlbGVtZW50KS5hZGRDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgaWYgKGVsZW1lbnQucGFyZW50Tm9kZSAmJiAkJCQxKGVsZW1lbnQucGFyZW50Tm9kZSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BET1dOX01FTlUpKSB7XG4gICAgICAgICAgdmFyIGRyb3Bkb3duRWxlbWVudCA9ICQkJDEoZWxlbWVudCkuY2xvc2VzdChTZWxlY3Rvci5EUk9QRE9XTilbMF07XG5cbiAgICAgICAgICBpZiAoZHJvcGRvd25FbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgZHJvcGRvd25Ub2dnbGVMaXN0ID0gW10uc2xpY2UuY2FsbChkcm9wZG93bkVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChTZWxlY3Rvci5EUk9QRE9XTl9UT0dHTEUpKTtcbiAgICAgICAgICAgICQkJDEoZHJvcGRvd25Ub2dnbGVMaXN0KS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTsgLy8gU3RhdGljXG5cblxuICAgICAgVGFiLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkJCQxKHRoaXMpO1xuICAgICAgICAgIHZhciBkYXRhID0gJHRoaXMuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIGRhdGEgPSBuZXcgVGFiKHRoaXMpO1xuICAgICAgICAgICAgJHRoaXMuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBfY3JlYXRlQ2xhc3MoVGFiLCBudWxsLCBbe1xuICAgICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgICAgfVxuICAgICAgfV0pO1xuXG4gICAgICByZXR1cm4gVGFiO1xuICAgIH0oKTtcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG5cbiAgICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgVGFiLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkJCQxKHRoaXMpLCAnc2hvdycpO1xuICAgIH0pO1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIGpRdWVyeVxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gICAgJCQkMS5mbltOQU1FXSA9IFRhYi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBUYWI7XG5cbiAgICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgICAgcmV0dXJuIFRhYi5falF1ZXJ5SW50ZXJmYWNlO1xuICAgIH07XG5cbiAgICByZXR1cm4gVGFiO1xuICB9KCQpO1xuXG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBCb290c3RyYXAgKHY0LjEuMyk6IGluZGV4LmpzXG4gICAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gIChmdW5jdGlvbiAoJCQkMSkge1xuICAgIGlmICh0eXBlb2YgJCQkMSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Jvb3RzdHJhcFxcJ3MgSmF2YVNjcmlwdCByZXF1aXJlcyBqUXVlcnkuIGpRdWVyeSBtdXN0IGJlIGluY2x1ZGVkIGJlZm9yZSBCb290c3RyYXBcXCdzIEphdmFTY3JpcHQuJyk7XG4gICAgfVxuXG4gICAgdmFyIHZlcnNpb24gPSAkJCQxLmZuLmpxdWVyeS5zcGxpdCgnICcpWzBdLnNwbGl0KCcuJyk7XG4gICAgdmFyIG1pbk1ham9yID0gMTtcbiAgICB2YXIgbHRNYWpvciA9IDI7XG4gICAgdmFyIG1pbk1pbm9yID0gOTtcbiAgICB2YXIgbWluUGF0Y2ggPSAxO1xuICAgIHZhciBtYXhNYWpvciA9IDQ7XG5cbiAgICBpZiAodmVyc2lvblswXSA8IGx0TWFqb3IgJiYgdmVyc2lvblsxXSA8IG1pbk1pbm9yIHx8IHZlcnNpb25bMF0gPT09IG1pbk1ham9yICYmIHZlcnNpb25bMV0gPT09IG1pbk1pbm9yICYmIHZlcnNpb25bMl0gPCBtaW5QYXRjaCB8fCB2ZXJzaW9uWzBdID49IG1heE1ham9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Jvb3RzdHJhcFxcJ3MgSmF2YVNjcmlwdCByZXF1aXJlcyBhdCBsZWFzdCBqUXVlcnkgdjEuOS4xIGJ1dCBsZXNzIHRoYW4gdjQuMC4wJyk7XG4gICAgfVxuICB9KSgkKTtcblxuICBleHBvcnRzLlV0aWwgPSBVdGlsO1xuICBleHBvcnRzLkFsZXJ0ID0gQWxlcnQ7XG4gIGV4cG9ydHMuQnV0dG9uID0gQnV0dG9uO1xuICBleHBvcnRzLkNhcm91c2VsID0gQ2Fyb3VzZWw7XG4gIGV4cG9ydHMuQ29sbGFwc2UgPSBDb2xsYXBzZTtcbiAgZXhwb3J0cy5Ecm9wZG93biA9IERyb3Bkb3duO1xuICBleHBvcnRzLk1vZGFsID0gTW9kYWw7XG4gIGV4cG9ydHMuUG9wb3ZlciA9IFBvcG92ZXI7XG4gIGV4cG9ydHMuU2Nyb2xsc3B5ID0gU2Nyb2xsU3B5O1xuICBleHBvcnRzLlRhYiA9IFRhYjtcbiAgZXhwb3J0cy5Ub29sdGlwID0gVG9vbHRpcDtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Ym9vdHN0cmFwLmpzLm1hcFxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvanMvYm9vdHN0cmFwLmpzXG4vLyBtb2R1bGUgaWQgPSAyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qKiFcbiAqIEBmaWxlT3ZlcnZpZXcgS2lja2FzcyBsaWJyYXJ5IHRvIGNyZWF0ZSBhbmQgcGxhY2UgcG9wcGVycyBuZWFyIHRoZWlyIHJlZmVyZW5jZSBlbGVtZW50cy5cbiAqIEB2ZXJzaW9uIDEuMTQuNFxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAoYykgMjAxNiBGZWRlcmljbyBaaXZvbG8gYW5kIGNvbnRyaWJ1dG9yc1xuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAqIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAqIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGxcbiAqIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuICogU09GVFdBUkUuXG4gKi9cbnZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xuXG52YXIgbG9uZ2VyVGltZW91dEJyb3dzZXJzID0gWydFZGdlJywgJ1RyaWRlbnQnLCAnRmlyZWZveCddO1xudmFyIHRpbWVvdXREdXJhdGlvbiA9IDA7XG5mb3IgKHZhciBpID0gMDsgaSA8IGxvbmdlclRpbWVvdXRCcm93c2Vycy5sZW5ndGg7IGkgKz0gMSkge1xuICBpZiAoaXNCcm93c2VyICYmIG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZihsb25nZXJUaW1lb3V0QnJvd3NlcnNbaV0pID49IDApIHtcbiAgICB0aW1lb3V0RHVyYXRpb24gPSAxO1xuICAgIGJyZWFrO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1pY3JvdGFza0RlYm91bmNlKGZuKSB7XG4gIHZhciBjYWxsZWQgPSBmYWxzZTtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoY2FsbGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNhbGxlZCA9IHRydWU7XG4gICAgd2luZG93LlByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgY2FsbGVkID0gZmFsc2U7XG4gICAgICBmbigpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiB0YXNrRGVib3VuY2UoZm4pIHtcbiAgdmFyIHNjaGVkdWxlZCA9IGZhbHNlO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGlmICghc2NoZWR1bGVkKSB7XG4gICAgICBzY2hlZHVsZWQgPSB0cnVlO1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgICBmbigpO1xuICAgICAgfSwgdGltZW91dER1cmF0aW9uKTtcbiAgICB9XG4gIH07XG59XG5cbnZhciBzdXBwb3J0c01pY3JvVGFza3MgPSBpc0Jyb3dzZXIgJiYgd2luZG93LlByb21pc2U7XG5cbi8qKlxuKiBDcmVhdGUgYSBkZWJvdW5jZWQgdmVyc2lvbiBvZiBhIG1ldGhvZCwgdGhhdCdzIGFzeW5jaHJvbm91c2x5IGRlZmVycmVkXG4qIGJ1dCBjYWxsZWQgaW4gdGhlIG1pbmltdW0gdGltZSBwb3NzaWJsZS5cbipcbiogQG1ldGhvZFxuKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4qIEBhcmd1bWVudCB7RnVuY3Rpb259IGZuXG4qIEByZXR1cm5zIHtGdW5jdGlvbn1cbiovXG52YXIgZGVib3VuY2UgPSBzdXBwb3J0c01pY3JvVGFza3MgPyBtaWNyb3Rhc2tEZWJvdW5jZSA6IHRhc2tEZWJvdW5jZTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFyaWFibGUgaXMgYSBmdW5jdGlvblxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtBbnl9IGZ1bmN0aW9uVG9DaGVjayAtIHZhcmlhYmxlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gYW5zd2VyIHRvOiBpcyBhIGZ1bmN0aW9uP1xuICovXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGZ1bmN0aW9uVG9DaGVjaykge1xuICB2YXIgZ2V0VHlwZSA9IHt9O1xuICByZXR1cm4gZnVuY3Rpb25Ub0NoZWNrICYmIGdldFR5cGUudG9TdHJpbmcuY2FsbChmdW5jdGlvblRvQ2hlY2spID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIEdldCBDU1MgY29tcHV0ZWQgcHJvcGVydHkgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWVtZW50fSBlbGVtZW50XG4gKiBAYXJndW1lbnQge1N0cmluZ30gcHJvcGVydHlcbiAqL1xuZnVuY3Rpb24gZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQsIHByb3BlcnR5KSB7XG4gIGlmIChlbGVtZW50Lm5vZGVUeXBlICE9PSAxKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIC8vIE5PVEU6IDEgRE9NIGFjY2VzcyBoZXJlXG4gIHZhciBjc3MgPSBnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQsIG51bGwpO1xuICByZXR1cm4gcHJvcGVydHkgPyBjc3NbcHJvcGVydHldIDogY3NzO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHBhcmVudE5vZGUgb3IgdGhlIGhvc3Qgb2YgdGhlIGVsZW1lbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge0VsZW1lbnR9IHBhcmVudFxuICovXG5mdW5jdGlvbiBnZXRQYXJlbnROb2RlKGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQubm9kZU5hbWUgPT09ICdIVE1MJykge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG4gIHJldHVybiBlbGVtZW50LnBhcmVudE5vZGUgfHwgZWxlbWVudC5ob3N0O1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHNjcm9sbGluZyBwYXJlbnQgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge0VsZW1lbnR9IHNjcm9sbCBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gZ2V0U2Nyb2xsUGFyZW50KGVsZW1lbnQpIHtcbiAgLy8gUmV0dXJuIGJvZHksIGBnZXRTY3JvbGxgIHdpbGwgdGFrZSBjYXJlIHRvIGdldCB0aGUgY29ycmVjdCBgc2Nyb2xsVG9wYCBmcm9tIGl0XG4gIGlmICghZWxlbWVudCkge1xuICAgIHJldHVybiBkb2N1bWVudC5ib2R5O1xuICB9XG5cbiAgc3dpdGNoIChlbGVtZW50Lm5vZGVOYW1lKSB7XG4gICAgY2FzZSAnSFRNTCc6XG4gICAgY2FzZSAnQk9EWSc6XG4gICAgICByZXR1cm4gZWxlbWVudC5vd25lckRvY3VtZW50LmJvZHk7XG4gICAgY2FzZSAnI2RvY3VtZW50JzpcbiAgICAgIHJldHVybiBlbGVtZW50LmJvZHk7XG4gIH1cblxuICAvLyBGaXJlZm94IHdhbnQgdXMgdG8gY2hlY2sgYC14YCBhbmQgYC15YCB2YXJpYXRpb25zIGFzIHdlbGxcblxuICB2YXIgX2dldFN0eWxlQ29tcHV0ZWRQcm9wID0gZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQpLFxuICAgICAgb3ZlcmZsb3cgPSBfZ2V0U3R5bGVDb21wdXRlZFByb3Aub3ZlcmZsb3csXG4gICAgICBvdmVyZmxvd1ggPSBfZ2V0U3R5bGVDb21wdXRlZFByb3Aub3ZlcmZsb3dYLFxuICAgICAgb3ZlcmZsb3dZID0gX2dldFN0eWxlQ29tcHV0ZWRQcm9wLm92ZXJmbG93WTtcblxuICBpZiAoLyhhdXRvfHNjcm9sbHxvdmVybGF5KS8udGVzdChvdmVyZmxvdyArIG92ZXJmbG93WSArIG92ZXJmbG93WCkpIHtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHJldHVybiBnZXRTY3JvbGxQYXJlbnQoZ2V0UGFyZW50Tm9kZShlbGVtZW50KSk7XG59XG5cbnZhciBpc0lFMTEgPSBpc0Jyb3dzZXIgJiYgISEod2luZG93Lk1TSW5wdXRNZXRob2RDb250ZXh0ICYmIGRvY3VtZW50LmRvY3VtZW50TW9kZSk7XG52YXIgaXNJRTEwID0gaXNCcm93c2VyICYmIC9NU0lFIDEwLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuXG4vKipcbiAqIERldGVybWluZXMgaWYgdGhlIGJyb3dzZXIgaXMgSW50ZXJuZXQgRXhwbG9yZXJcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7TnVtYmVyfSB2ZXJzaW9uIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gaXNJRVxuICovXG5mdW5jdGlvbiBpc0lFKHZlcnNpb24pIHtcbiAgaWYgKHZlcnNpb24gPT09IDExKSB7XG4gICAgcmV0dXJuIGlzSUUxMTtcbiAgfVxuICBpZiAodmVyc2lvbiA9PT0gMTApIHtcbiAgICByZXR1cm4gaXNJRTEwO1xuICB9XG4gIHJldHVybiBpc0lFMTEgfHwgaXNJRTEwO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG9mZnNldCBwYXJlbnQgb2YgdGhlIGdpdmVuIGVsZW1lbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge0VsZW1lbnR9IG9mZnNldCBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gZ2V0T2Zmc2V0UGFyZW50KGVsZW1lbnQpIHtcbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgfVxuXG4gIHZhciBub09mZnNldFBhcmVudCA9IGlzSUUoMTApID8gZG9jdW1lbnQuYm9keSA6IG51bGw7XG5cbiAgLy8gTk9URTogMSBET00gYWNjZXNzIGhlcmVcbiAgdmFyIG9mZnNldFBhcmVudCA9IGVsZW1lbnQub2Zmc2V0UGFyZW50O1xuICAvLyBTa2lwIGhpZGRlbiBlbGVtZW50cyB3aGljaCBkb24ndCBoYXZlIGFuIG9mZnNldFBhcmVudFxuICB3aGlsZSAob2Zmc2V0UGFyZW50ID09PSBub09mZnNldFBhcmVudCAmJiBlbGVtZW50Lm5leHRFbGVtZW50U2libGluZykge1xuICAgIG9mZnNldFBhcmVudCA9IChlbGVtZW50ID0gZWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmcpLm9mZnNldFBhcmVudDtcbiAgfVxuXG4gIHZhciBub2RlTmFtZSA9IG9mZnNldFBhcmVudCAmJiBvZmZzZXRQYXJlbnQubm9kZU5hbWU7XG5cbiAgaWYgKCFub2RlTmFtZSB8fCBub2RlTmFtZSA9PT0gJ0JPRFknIHx8IG5vZGVOYW1lID09PSAnSFRNTCcpIHtcbiAgICByZXR1cm4gZWxlbWVudCA/IGVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgOiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIH1cblxuICAvLyAub2Zmc2V0UGFyZW50IHdpbGwgcmV0dXJuIHRoZSBjbG9zZXN0IFREIG9yIFRBQkxFIGluIGNhc2VcbiAgLy8gbm8gb2Zmc2V0UGFyZW50IGlzIHByZXNlbnQsIEkgaGF0ZSB0aGlzIGpvYi4uLlxuICBpZiAoWydURCcsICdUQUJMRSddLmluZGV4T2Yob2Zmc2V0UGFyZW50Lm5vZGVOYW1lKSAhPT0gLTEgJiYgZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KG9mZnNldFBhcmVudCwgJ3Bvc2l0aW9uJykgPT09ICdzdGF0aWMnKSB7XG4gICAgcmV0dXJuIGdldE9mZnNldFBhcmVudChvZmZzZXRQYXJlbnQpO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldFBhcmVudDtcbn1cblxuZnVuY3Rpb24gaXNPZmZzZXRDb250YWluZXIoZWxlbWVudCkge1xuICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lO1xuXG4gIGlmIChub2RlTmFtZSA9PT0gJ0JPRFknKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiBub2RlTmFtZSA9PT0gJ0hUTUwnIHx8IGdldE9mZnNldFBhcmVudChlbGVtZW50LmZpcnN0RWxlbWVudENoaWxkKSA9PT0gZWxlbWVudDtcbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgcm9vdCBub2RlIChkb2N1bWVudCwgc2hhZG93RE9NIHJvb3QpIG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IG5vZGVcbiAqIEByZXR1cm5zIHtFbGVtZW50fSByb290IG5vZGVcbiAqL1xuZnVuY3Rpb24gZ2V0Um9vdChub2RlKSB7XG4gIGlmIChub2RlLnBhcmVudE5vZGUgIT09IG51bGwpIHtcbiAgICByZXR1cm4gZ2V0Um9vdChub2RlLnBhcmVudE5vZGUpO1xuICB9XG5cbiAgcmV0dXJuIG5vZGU7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIG9mZnNldCBwYXJlbnQgY29tbW9uIHRvIHRoZSB0d28gcHJvdmlkZWQgbm9kZXNcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudDFcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudDJcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBjb21tb24gb2Zmc2V0IHBhcmVudFxuICovXG5mdW5jdGlvbiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KGVsZW1lbnQxLCBlbGVtZW50Mikge1xuICAvLyBUaGlzIGNoZWNrIGlzIG5lZWRlZCB0byBhdm9pZCBlcnJvcnMgaW4gY2FzZSBvbmUgb2YgdGhlIGVsZW1lbnRzIGlzbid0IGRlZmluZWQgZm9yIGFueSByZWFzb25cbiAgaWYgKCFlbGVtZW50MSB8fCAhZWxlbWVudDEubm9kZVR5cGUgfHwgIWVsZW1lbnQyIHx8ICFlbGVtZW50Mi5ub2RlVHlwZSkge1xuICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIH1cblxuICAvLyBIZXJlIHdlIG1ha2Ugc3VyZSB0byBnaXZlIGFzIFwic3RhcnRcIiB0aGUgZWxlbWVudCB0aGF0IGNvbWVzIGZpcnN0IGluIHRoZSBET01cbiAgdmFyIG9yZGVyID0gZWxlbWVudDEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oZWxlbWVudDIpICYgTm9kZS5ET0NVTUVOVF9QT1NJVElPTl9GT0xMT1dJTkc7XG4gIHZhciBzdGFydCA9IG9yZGVyID8gZWxlbWVudDEgOiBlbGVtZW50MjtcbiAgdmFyIGVuZCA9IG9yZGVyID8gZWxlbWVudDIgOiBlbGVtZW50MTtcblxuICAvLyBHZXQgY29tbW9uIGFuY2VzdG9yIGNvbnRhaW5lclxuICB2YXIgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICByYW5nZS5zZXRTdGFydChzdGFydCwgMCk7XG4gIHJhbmdlLnNldEVuZChlbmQsIDApO1xuICB2YXIgY29tbW9uQW5jZXN0b3JDb250YWluZXIgPSByYW5nZS5jb21tb25BbmNlc3RvckNvbnRhaW5lcjtcblxuICAvLyBCb3RoIG5vZGVzIGFyZSBpbnNpZGUgI2RvY3VtZW50XG5cbiAgaWYgKGVsZW1lbnQxICE9PSBjb21tb25BbmNlc3RvckNvbnRhaW5lciAmJiBlbGVtZW50MiAhPT0gY29tbW9uQW5jZXN0b3JDb250YWluZXIgfHwgc3RhcnQuY29udGFpbnMoZW5kKSkge1xuICAgIGlmIChpc09mZnNldENvbnRhaW5lcihjb21tb25BbmNlc3RvckNvbnRhaW5lcikpIHtcbiAgICAgIHJldHVybiBjb21tb25BbmNlc3RvckNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0T2Zmc2V0UGFyZW50KGNvbW1vbkFuY2VzdG9yQ29udGFpbmVyKTtcbiAgfVxuXG4gIC8vIG9uZSBvZiB0aGUgbm9kZXMgaXMgaW5zaWRlIHNoYWRvd0RPTSwgZmluZCB3aGljaCBvbmVcbiAgdmFyIGVsZW1lbnQxcm9vdCA9IGdldFJvb3QoZWxlbWVudDEpO1xuICBpZiAoZWxlbWVudDFyb290Lmhvc3QpIHtcbiAgICByZXR1cm4gZmluZENvbW1vbk9mZnNldFBhcmVudChlbGVtZW50MXJvb3QuaG9zdCwgZWxlbWVudDIpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KGVsZW1lbnQxLCBnZXRSb290KGVsZW1lbnQyKS5ob3N0KTtcbiAgfVxufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcm9sbCB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudCBpbiB0aGUgZ2l2ZW4gc2lkZSAodG9wIGFuZCBsZWZ0KVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAYXJndW1lbnQge1N0cmluZ30gc2lkZSBgdG9wYCBvciBgbGVmdGBcbiAqIEByZXR1cm5zIHtudW1iZXJ9IGFtb3VudCBvZiBzY3JvbGxlZCBwaXhlbHNcbiAqL1xuZnVuY3Rpb24gZ2V0U2Nyb2xsKGVsZW1lbnQpIHtcbiAgdmFyIHNpZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6ICd0b3AnO1xuXG4gIHZhciB1cHBlclNpZGUgPSBzaWRlID09PSAndG9wJyA/ICdzY3JvbGxUb3AnIDogJ3Njcm9sbExlZnQnO1xuICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lO1xuXG4gIGlmIChub2RlTmFtZSA9PT0gJ0JPRFknIHx8IG5vZGVOYW1lID09PSAnSFRNTCcpIHtcbiAgICB2YXIgaHRtbCA9IGVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgdmFyIHNjcm9sbGluZ0VsZW1lbnQgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuc2Nyb2xsaW5nRWxlbWVudCB8fCBodG1sO1xuICAgIHJldHVybiBzY3JvbGxpbmdFbGVtZW50W3VwcGVyU2lkZV07XG4gIH1cblxuICByZXR1cm4gZWxlbWVudFt1cHBlclNpZGVdO1xufVxuXG4vKlxuICogU3VtIG9yIHN1YnRyYWN0IHRoZSBlbGVtZW50IHNjcm9sbCB2YWx1ZXMgKGxlZnQgYW5kIHRvcCkgZnJvbSBhIGdpdmVuIHJlY3Qgb2JqZWN0XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge09iamVjdH0gcmVjdCAtIFJlY3Qgb2JqZWN0IHlvdSB3YW50IHRvIGNoYW5nZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCAtIFRoZSBlbGVtZW50IGZyb20gdGhlIGZ1bmN0aW9uIHJlYWRzIHRoZSBzY3JvbGwgdmFsdWVzXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHN1YnRyYWN0IC0gc2V0IHRvIHRydWUgaWYgeW91IHdhbnQgdG8gc3VidHJhY3QgdGhlIHNjcm9sbCB2YWx1ZXNcbiAqIEByZXR1cm4ge09iamVjdH0gcmVjdCAtIFRoZSBtb2RpZmllciByZWN0IG9iamVjdFxuICovXG5mdW5jdGlvbiBpbmNsdWRlU2Nyb2xsKHJlY3QsIGVsZW1lbnQpIHtcbiAgdmFyIHN1YnRyYWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcblxuICB2YXIgc2Nyb2xsVG9wID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICd0b3AnKTtcbiAgdmFyIHNjcm9sbExlZnQgPSBnZXRTY3JvbGwoZWxlbWVudCwgJ2xlZnQnKTtcbiAgdmFyIG1vZGlmaWVyID0gc3VidHJhY3QgPyAtMSA6IDE7XG4gIHJlY3QudG9wICs9IHNjcm9sbFRvcCAqIG1vZGlmaWVyO1xuICByZWN0LmJvdHRvbSArPSBzY3JvbGxUb3AgKiBtb2RpZmllcjtcbiAgcmVjdC5sZWZ0ICs9IHNjcm9sbExlZnQgKiBtb2RpZmllcjtcbiAgcmVjdC5yaWdodCArPSBzY3JvbGxMZWZ0ICogbW9kaWZpZXI7XG4gIHJldHVybiByZWN0O1xufVxuXG4vKlxuICogSGVscGVyIHRvIGRldGVjdCBib3JkZXJzIG9mIGEgZ2l2ZW4gZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtDU1NTdHlsZURlY2xhcmF0aW9ufSBzdHlsZXNcbiAqIFJlc3VsdCBvZiBgZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5YCBvbiB0aGUgZ2l2ZW4gZWxlbWVudFxuICogQHBhcmFtIHtTdHJpbmd9IGF4aXMgLSBgeGAgb3IgYHlgXG4gKiBAcmV0dXJuIHtudW1iZXJ9IGJvcmRlcnMgLSBUaGUgYm9yZGVycyBzaXplIG9mIHRoZSBnaXZlbiBheGlzXG4gKi9cblxuZnVuY3Rpb24gZ2V0Qm9yZGVyc1NpemUoc3R5bGVzLCBheGlzKSB7XG4gIHZhciBzaWRlQSA9IGF4aXMgPT09ICd4JyA/ICdMZWZ0JyA6ICdUb3AnO1xuICB2YXIgc2lkZUIgPSBzaWRlQSA9PT0gJ0xlZnQnID8gJ1JpZ2h0JyA6ICdCb3R0b20nO1xuXG4gIHJldHVybiBwYXJzZUZsb2F0KHN0eWxlc1snYm9yZGVyJyArIHNpZGVBICsgJ1dpZHRoJ10sIDEwKSArIHBhcnNlRmxvYXQoc3R5bGVzWydib3JkZXInICsgc2lkZUIgKyAnV2lkdGgnXSwgMTApO1xufVxuXG5mdW5jdGlvbiBnZXRTaXplKGF4aXMsIGJvZHksIGh0bWwsIGNvbXB1dGVkU3R5bGUpIHtcbiAgcmV0dXJuIE1hdGgubWF4KGJvZHlbJ29mZnNldCcgKyBheGlzXSwgYm9keVsnc2Nyb2xsJyArIGF4aXNdLCBodG1sWydjbGllbnQnICsgYXhpc10sIGh0bWxbJ29mZnNldCcgKyBheGlzXSwgaHRtbFsnc2Nyb2xsJyArIGF4aXNdLCBpc0lFKDEwKSA/IHBhcnNlSW50KGh0bWxbJ29mZnNldCcgKyBheGlzXSkgKyBwYXJzZUludChjb21wdXRlZFN0eWxlWydtYXJnaW4nICsgKGF4aXMgPT09ICdIZWlnaHQnID8gJ1RvcCcgOiAnTGVmdCcpXSkgKyBwYXJzZUludChjb21wdXRlZFN0eWxlWydtYXJnaW4nICsgKGF4aXMgPT09ICdIZWlnaHQnID8gJ0JvdHRvbScgOiAnUmlnaHQnKV0pIDogMCk7XG59XG5cbmZ1bmN0aW9uIGdldFdpbmRvd1NpemVzKGRvY3VtZW50KSB7XG4gIHZhciBib2R5ID0gZG9jdW1lbnQuYm9keTtcbiAgdmFyIGh0bWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIHZhciBjb21wdXRlZFN0eWxlID0gaXNJRSgxMCkgJiYgZ2V0Q29tcHV0ZWRTdHlsZShodG1sKTtcblxuICByZXR1cm4ge1xuICAgIGhlaWdodDogZ2V0U2l6ZSgnSGVpZ2h0JywgYm9keSwgaHRtbCwgY29tcHV0ZWRTdHlsZSksXG4gICAgd2lkdGg6IGdldFNpemUoJ1dpZHRoJywgYm9keSwgaHRtbCwgY29tcHV0ZWRTdHlsZSlcbiAgfTtcbn1cblxudmFyIGNsYXNzQ2FsbENoZWNrID0gZnVuY3Rpb24gKGluc3RhbmNlLCBDb25zdHJ1Y3Rvcikge1xuICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7XG4gIH1cbn07XG5cbnZhciBjcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHtcbiAgICBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpO1xuICAgIGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpO1xuICAgIHJldHVybiBDb25zdHJ1Y3RvcjtcbiAgfTtcbn0oKTtcblxuXG5cblxuXG52YXIgZGVmaW5lUHJvcGVydHkgPSBmdW5jdGlvbiAob2JqLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gb2JqKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7XG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgd3JpdGFibGU6IHRydWVcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBvYmpba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn07XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkge1xuICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkge1xuICAgICAgICB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59O1xuXG4vKipcbiAqIEdpdmVuIGVsZW1lbnQgb2Zmc2V0cywgZ2VuZXJhdGUgYW4gb3V0cHV0IHNpbWlsYXIgdG8gZ2V0Qm91bmRpbmdDbGllbnRSZWN0XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge09iamVjdH0gb2Zmc2V0c1xuICogQHJldHVybnMge09iamVjdH0gQ2xpZW50UmVjdCBsaWtlIG91dHB1dFxuICovXG5mdW5jdGlvbiBnZXRDbGllbnRSZWN0KG9mZnNldHMpIHtcbiAgcmV0dXJuIF9leHRlbmRzKHt9LCBvZmZzZXRzLCB7XG4gICAgcmlnaHQ6IG9mZnNldHMubGVmdCArIG9mZnNldHMud2lkdGgsXG4gICAgYm90dG9tOiBvZmZzZXRzLnRvcCArIG9mZnNldHMuaGVpZ2h0XG4gIH0pO1xufVxuXG4vKipcbiAqIEdldCBib3VuZGluZyBjbGllbnQgcmVjdCBvZiBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtPYmplY3R9IGNsaWVudCByZWN0XG4gKi9cbmZ1bmN0aW9uIGdldEJvdW5kaW5nQ2xpZW50UmVjdChlbGVtZW50KSB7XG4gIHZhciByZWN0ID0ge307XG5cbiAgLy8gSUUxMCAxMCBGSVg6IFBsZWFzZSwgZG9uJ3QgYXNrLCB0aGUgZWxlbWVudCBpc24ndFxuICAvLyBjb25zaWRlcmVkIGluIERPTSBpbiBzb21lIGNpcmN1bXN0YW5jZXMuLi5cbiAgLy8gVGhpcyBpc24ndCByZXByb2R1Y2libGUgaW4gSUUxMCBjb21wYXRpYmlsaXR5IG1vZGUgb2YgSUUxMVxuICB0cnkge1xuICAgIGlmIChpc0lFKDEwKSkge1xuICAgICAgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICd0b3AnKTtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICdsZWZ0Jyk7XG4gICAgICByZWN0LnRvcCArPSBzY3JvbGxUb3A7XG4gICAgICByZWN0LmxlZnQgKz0gc2Nyb2xsTGVmdDtcbiAgICAgIHJlY3QuYm90dG9tICs9IHNjcm9sbFRvcDtcbiAgICAgIHJlY3QucmlnaHQgKz0gc2Nyb2xsTGVmdDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7fVxuXG4gIHZhciByZXN1bHQgPSB7XG4gICAgbGVmdDogcmVjdC5sZWZ0LFxuICAgIHRvcDogcmVjdC50b3AsXG4gICAgd2lkdGg6IHJlY3QucmlnaHQgLSByZWN0LmxlZnQsXG4gICAgaGVpZ2h0OiByZWN0LmJvdHRvbSAtIHJlY3QudG9wXG4gIH07XG5cbiAgLy8gc3VidHJhY3Qgc2Nyb2xsYmFyIHNpemUgZnJvbSBzaXplc1xuICB2YXIgc2l6ZXMgPSBlbGVtZW50Lm5vZGVOYW1lID09PSAnSFRNTCcgPyBnZXRXaW5kb3dTaXplcyhlbGVtZW50Lm93bmVyRG9jdW1lbnQpIDoge307XG4gIHZhciB3aWR0aCA9IHNpemVzLndpZHRoIHx8IGVsZW1lbnQuY2xpZW50V2lkdGggfHwgcmVzdWx0LnJpZ2h0IC0gcmVzdWx0LmxlZnQ7XG4gIHZhciBoZWlnaHQgPSBzaXplcy5oZWlnaHQgfHwgZWxlbWVudC5jbGllbnRIZWlnaHQgfHwgcmVzdWx0LmJvdHRvbSAtIHJlc3VsdC50b3A7XG5cbiAgdmFyIGhvcml6U2Nyb2xsYmFyID0gZWxlbWVudC5vZmZzZXRXaWR0aCAtIHdpZHRoO1xuICB2YXIgdmVydFNjcm9sbGJhciA9IGVsZW1lbnQub2Zmc2V0SGVpZ2h0IC0gaGVpZ2h0O1xuXG4gIC8vIGlmIGFuIGh5cG90aGV0aWNhbCBzY3JvbGxiYXIgaXMgZGV0ZWN0ZWQsIHdlIG11c3QgYmUgc3VyZSBpdCdzIG5vdCBhIGBib3JkZXJgXG4gIC8vIHdlIG1ha2UgdGhpcyBjaGVjayBjb25kaXRpb25hbCBmb3IgcGVyZm9ybWFuY2UgcmVhc29uc1xuICBpZiAoaG9yaXpTY3JvbGxiYXIgfHwgdmVydFNjcm9sbGJhcikge1xuICAgIHZhciBzdHlsZXMgPSBnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkoZWxlbWVudCk7XG4gICAgaG9yaXpTY3JvbGxiYXIgLT0gZ2V0Qm9yZGVyc1NpemUoc3R5bGVzLCAneCcpO1xuICAgIHZlcnRTY3JvbGxiYXIgLT0gZ2V0Qm9yZGVyc1NpemUoc3R5bGVzLCAneScpO1xuXG4gICAgcmVzdWx0LndpZHRoIC09IGhvcml6U2Nyb2xsYmFyO1xuICAgIHJlc3VsdC5oZWlnaHQgLT0gdmVydFNjcm9sbGJhcjtcbiAgfVxuXG4gIHJldHVybiBnZXRDbGllbnRSZWN0KHJlc3VsdCk7XG59XG5cbmZ1bmN0aW9uIGdldE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJiaXRyYXJ5Tm9kZShjaGlsZHJlbiwgcGFyZW50KSB7XG4gIHZhciBmaXhlZFBvc2l0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcblxuICB2YXIgaXNJRTEwID0gaXNJRSgxMCk7XG4gIHZhciBpc0hUTUwgPSBwYXJlbnQubm9kZU5hbWUgPT09ICdIVE1MJztcbiAgdmFyIGNoaWxkcmVuUmVjdCA9IGdldEJvdW5kaW5nQ2xpZW50UmVjdChjaGlsZHJlbik7XG4gIHZhciBwYXJlbnRSZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KHBhcmVudCk7XG4gIHZhciBzY3JvbGxQYXJlbnQgPSBnZXRTY3JvbGxQYXJlbnQoY2hpbGRyZW4pO1xuXG4gIHZhciBzdHlsZXMgPSBnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkocGFyZW50KTtcbiAgdmFyIGJvcmRlclRvcFdpZHRoID0gcGFyc2VGbG9hdChzdHlsZXMuYm9yZGVyVG9wV2lkdGgsIDEwKTtcbiAgdmFyIGJvcmRlckxlZnRXaWR0aCA9IHBhcnNlRmxvYXQoc3R5bGVzLmJvcmRlckxlZnRXaWR0aCwgMTApO1xuXG4gIC8vIEluIGNhc2VzIHdoZXJlIHRoZSBwYXJlbnQgaXMgZml4ZWQsIHdlIG11c3QgaWdub3JlIG5lZ2F0aXZlIHNjcm9sbCBpbiBvZmZzZXQgY2FsY1xuICBpZiAoZml4ZWRQb3NpdGlvbiAmJiBpc0hUTUwpIHtcbiAgICBwYXJlbnRSZWN0LnRvcCA9IE1hdGgubWF4KHBhcmVudFJlY3QudG9wLCAwKTtcbiAgICBwYXJlbnRSZWN0LmxlZnQgPSBNYXRoLm1heChwYXJlbnRSZWN0LmxlZnQsIDApO1xuICB9XG4gIHZhciBvZmZzZXRzID0gZ2V0Q2xpZW50UmVjdCh7XG4gICAgdG9wOiBjaGlsZHJlblJlY3QudG9wIC0gcGFyZW50UmVjdC50b3AgLSBib3JkZXJUb3BXaWR0aCxcbiAgICBsZWZ0OiBjaGlsZHJlblJlY3QubGVmdCAtIHBhcmVudFJlY3QubGVmdCAtIGJvcmRlckxlZnRXaWR0aCxcbiAgICB3aWR0aDogY2hpbGRyZW5SZWN0LndpZHRoLFxuICAgIGhlaWdodDogY2hpbGRyZW5SZWN0LmhlaWdodFxuICB9KTtcbiAgb2Zmc2V0cy5tYXJnaW5Ub3AgPSAwO1xuICBvZmZzZXRzLm1hcmdpbkxlZnQgPSAwO1xuXG4gIC8vIFN1YnRyYWN0IG1hcmdpbnMgb2YgZG9jdW1lbnRFbGVtZW50IGluIGNhc2UgaXQncyBiZWluZyB1c2VkIGFzIHBhcmVudFxuICAvLyB3ZSBkbyB0aGlzIG9ubHkgb24gSFRNTCBiZWNhdXNlIGl0J3MgdGhlIG9ubHkgZWxlbWVudCB0aGF0IGJlaGF2ZXNcbiAgLy8gZGlmZmVyZW50bHkgd2hlbiBtYXJnaW5zIGFyZSBhcHBsaWVkIHRvIGl0LiBUaGUgbWFyZ2lucyBhcmUgaW5jbHVkZWQgaW5cbiAgLy8gdGhlIGJveCBvZiB0aGUgZG9jdW1lbnRFbGVtZW50LCBpbiB0aGUgb3RoZXIgY2FzZXMgbm90LlxuICBpZiAoIWlzSUUxMCAmJiBpc0hUTUwpIHtcbiAgICB2YXIgbWFyZ2luVG9wID0gcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luVG9wLCAxMCk7XG4gICAgdmFyIG1hcmdpbkxlZnQgPSBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5MZWZ0LCAxMCk7XG5cbiAgICBvZmZzZXRzLnRvcCAtPSBib3JkZXJUb3BXaWR0aCAtIG1hcmdpblRvcDtcbiAgICBvZmZzZXRzLmJvdHRvbSAtPSBib3JkZXJUb3BXaWR0aCAtIG1hcmdpblRvcDtcbiAgICBvZmZzZXRzLmxlZnQgLT0gYm9yZGVyTGVmdFdpZHRoIC0gbWFyZ2luTGVmdDtcbiAgICBvZmZzZXRzLnJpZ2h0IC09IGJvcmRlckxlZnRXaWR0aCAtIG1hcmdpbkxlZnQ7XG5cbiAgICAvLyBBdHRhY2ggbWFyZ2luVG9wIGFuZCBtYXJnaW5MZWZ0IGJlY2F1c2UgaW4gc29tZSBjaXJjdW1zdGFuY2VzIHdlIG1heSBuZWVkIHRoZW1cbiAgICBvZmZzZXRzLm1hcmdpblRvcCA9IG1hcmdpblRvcDtcbiAgICBvZmZzZXRzLm1hcmdpbkxlZnQgPSBtYXJnaW5MZWZ0O1xuICB9XG5cbiAgaWYgKGlzSUUxMCAmJiAhZml4ZWRQb3NpdGlvbiA/IHBhcmVudC5jb250YWlucyhzY3JvbGxQYXJlbnQpIDogcGFyZW50ID09PSBzY3JvbGxQYXJlbnQgJiYgc2Nyb2xsUGFyZW50Lm5vZGVOYW1lICE9PSAnQk9EWScpIHtcbiAgICBvZmZzZXRzID0gaW5jbHVkZVNjcm9sbChvZmZzZXRzLCBwYXJlbnQpO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldHM7XG59XG5cbmZ1bmN0aW9uIGdldFZpZXdwb3J0T2Zmc2V0UmVjdFJlbGF0aXZlVG9BcnRiaXRyYXJ5Tm9kZShlbGVtZW50KSB7XG4gIHZhciBleGNsdWRlU2Nyb2xsID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTtcblxuICB2YXIgaHRtbCA9IGVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIHZhciByZWxhdGl2ZU9mZnNldCA9IGdldE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJiaXRyYXJ5Tm9kZShlbGVtZW50LCBodG1sKTtcbiAgdmFyIHdpZHRoID0gTWF0aC5tYXgoaHRtbC5jbGllbnRXaWR0aCwgd2luZG93LmlubmVyV2lkdGggfHwgMCk7XG4gIHZhciBoZWlnaHQgPSBNYXRoLm1heChodG1sLmNsaWVudEhlaWdodCwgd2luZG93LmlubmVySGVpZ2h0IHx8IDApO1xuXG4gIHZhciBzY3JvbGxUb3AgPSAhZXhjbHVkZVNjcm9sbCA/IGdldFNjcm9sbChodG1sKSA6IDA7XG4gIHZhciBzY3JvbGxMZWZ0ID0gIWV4Y2x1ZGVTY3JvbGwgPyBnZXRTY3JvbGwoaHRtbCwgJ2xlZnQnKSA6IDA7XG5cbiAgdmFyIG9mZnNldCA9IHtcbiAgICB0b3A6IHNjcm9sbFRvcCAtIHJlbGF0aXZlT2Zmc2V0LnRvcCArIHJlbGF0aXZlT2Zmc2V0Lm1hcmdpblRvcCxcbiAgICBsZWZ0OiBzY3JvbGxMZWZ0IC0gcmVsYXRpdmVPZmZzZXQubGVmdCArIHJlbGF0aXZlT2Zmc2V0Lm1hcmdpbkxlZnQsXG4gICAgd2lkdGg6IHdpZHRoLFxuICAgIGhlaWdodDogaGVpZ2h0XG4gIH07XG5cbiAgcmV0dXJuIGdldENsaWVudFJlY3Qob2Zmc2V0KTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiB0aGUgZ2l2ZW4gZWxlbWVudCBpcyBmaXhlZCBvciBpcyBpbnNpZGUgYSBmaXhlZCBwYXJlbnRcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQGFyZ3VtZW50IHtFbGVtZW50fSBjdXN0b21Db250YWluZXJcbiAqIEByZXR1cm5zIHtCb29sZWFufSBhbnN3ZXIgdG8gXCJpc0ZpeGVkP1wiXG4gKi9cbmZ1bmN0aW9uIGlzRml4ZWQoZWxlbWVudCkge1xuICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lO1xuICBpZiAobm9kZU5hbWUgPT09ICdCT0RZJyB8fCBub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkoZWxlbWVudCwgJ3Bvc2l0aW9uJykgPT09ICdmaXhlZCcpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gaXNGaXhlZChnZXRQYXJlbnROb2RlKGVsZW1lbnQpKTtcbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgZmlyc3QgcGFyZW50IG9mIGFuIGVsZW1lbnQgdGhhdCBoYXMgYSB0cmFuc2Zvcm1lZCBwcm9wZXJ0eSBkZWZpbmVkXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBmaXJzdCB0cmFuc2Zvcm1lZCBwYXJlbnQgb3IgZG9jdW1lbnRFbGVtZW50XG4gKi9cblxuZnVuY3Rpb24gZ2V0Rml4ZWRQb3NpdGlvbk9mZnNldFBhcmVudChlbGVtZW50KSB7XG4gIC8vIFRoaXMgY2hlY2sgaXMgbmVlZGVkIHRvIGF2b2lkIGVycm9ycyBpbiBjYXNlIG9uZSBvZiB0aGUgZWxlbWVudHMgaXNuJ3QgZGVmaW5lZCBmb3IgYW55IHJlYXNvblxuICBpZiAoIWVsZW1lbnQgfHwgIWVsZW1lbnQucGFyZW50RWxlbWVudCB8fCBpc0lFKCkpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB9XG4gIHZhciBlbCA9IGVsZW1lbnQucGFyZW50RWxlbWVudDtcbiAgd2hpbGUgKGVsICYmIGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShlbCwgJ3RyYW5zZm9ybScpID09PSAnbm9uZScpIHtcbiAgICBlbCA9IGVsLnBhcmVudEVsZW1lbnQ7XG4gIH1cbiAgcmV0dXJuIGVsIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbn1cblxuLyoqXG4gKiBDb21wdXRlZCB0aGUgYm91bmRhcmllcyBsaW1pdHMgYW5kIHJldHVybiB0aGVtXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwb3BwZXJcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHJlZmVyZW5jZVxuICogQHBhcmFtIHtudW1iZXJ9IHBhZGRpbmdcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJvdW5kYXJpZXNFbGVtZW50IC0gRWxlbWVudCB1c2VkIHRvIGRlZmluZSB0aGUgYm91bmRhcmllc1xuICogQHBhcmFtIHtCb29sZWFufSBmaXhlZFBvc2l0aW9uIC0gSXMgaW4gZml4ZWQgcG9zaXRpb24gbW9kZVxuICogQHJldHVybnMge09iamVjdH0gQ29vcmRpbmF0ZXMgb2YgdGhlIGJvdW5kYXJpZXNcbiAqL1xuZnVuY3Rpb24gZ2V0Qm91bmRhcmllcyhwb3BwZXIsIHJlZmVyZW5jZSwgcGFkZGluZywgYm91bmRhcmllc0VsZW1lbnQpIHtcbiAgdmFyIGZpeGVkUG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IGZhbHNlO1xuXG4gIC8vIE5PVEU6IDEgRE9NIGFjY2VzcyBoZXJlXG5cbiAgdmFyIGJvdW5kYXJpZXMgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xuICB2YXIgb2Zmc2V0UGFyZW50ID0gZml4ZWRQb3NpdGlvbiA/IGdldEZpeGVkUG9zaXRpb25PZmZzZXRQYXJlbnQocG9wcGVyKSA6IGZpbmRDb21tb25PZmZzZXRQYXJlbnQocG9wcGVyLCByZWZlcmVuY2UpO1xuXG4gIC8vIEhhbmRsZSB2aWV3cG9ydCBjYXNlXG4gIGlmIChib3VuZGFyaWVzRWxlbWVudCA9PT0gJ3ZpZXdwb3J0Jykge1xuICAgIGJvdW5kYXJpZXMgPSBnZXRWaWV3cG9ydE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJ0Yml0cmFyeU5vZGUob2Zmc2V0UGFyZW50LCBmaXhlZFBvc2l0aW9uKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBIYW5kbGUgb3RoZXIgY2FzZXMgYmFzZWQgb24gRE9NIGVsZW1lbnQgdXNlZCBhcyBib3VuZGFyaWVzXG4gICAgdmFyIGJvdW5kYXJpZXNOb2RlID0gdm9pZCAwO1xuICAgIGlmIChib3VuZGFyaWVzRWxlbWVudCA9PT0gJ3Njcm9sbFBhcmVudCcpIHtcbiAgICAgIGJvdW5kYXJpZXNOb2RlID0gZ2V0U2Nyb2xsUGFyZW50KGdldFBhcmVudE5vZGUocmVmZXJlbmNlKSk7XG4gICAgICBpZiAoYm91bmRhcmllc05vZGUubm9kZU5hbWUgPT09ICdCT0RZJykge1xuICAgICAgICBib3VuZGFyaWVzTm9kZSA9IHBvcHBlci5vd25lckRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGJvdW5kYXJpZXNFbGVtZW50ID09PSAnd2luZG93Jykge1xuICAgICAgYm91bmRhcmllc05vZGUgPSBwb3BwZXIub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJvdW5kYXJpZXNOb2RlID0gYm91bmRhcmllc0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgdmFyIG9mZnNldHMgPSBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoYm91bmRhcmllc05vZGUsIG9mZnNldFBhcmVudCwgZml4ZWRQb3NpdGlvbik7XG5cbiAgICAvLyBJbiBjYXNlIG9mIEhUTUwsIHdlIG5lZWQgYSBkaWZmZXJlbnQgY29tcHV0YXRpb25cbiAgICBpZiAoYm91bmRhcmllc05vZGUubm9kZU5hbWUgPT09ICdIVE1MJyAmJiAhaXNGaXhlZChvZmZzZXRQYXJlbnQpKSB7XG4gICAgICB2YXIgX2dldFdpbmRvd1NpemVzID0gZ2V0V2luZG93U2l6ZXMocG9wcGVyLm93bmVyRG9jdW1lbnQpLFxuICAgICAgICAgIGhlaWdodCA9IF9nZXRXaW5kb3dTaXplcy5oZWlnaHQsXG4gICAgICAgICAgd2lkdGggPSBfZ2V0V2luZG93U2l6ZXMud2lkdGg7XG5cbiAgICAgIGJvdW5kYXJpZXMudG9wICs9IG9mZnNldHMudG9wIC0gb2Zmc2V0cy5tYXJnaW5Ub3A7XG4gICAgICBib3VuZGFyaWVzLmJvdHRvbSA9IGhlaWdodCArIG9mZnNldHMudG9wO1xuICAgICAgYm91bmRhcmllcy5sZWZ0ICs9IG9mZnNldHMubGVmdCAtIG9mZnNldHMubWFyZ2luTGVmdDtcbiAgICAgIGJvdW5kYXJpZXMucmlnaHQgPSB3aWR0aCArIG9mZnNldHMubGVmdDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZm9yIGFsbCB0aGUgb3RoZXIgRE9NIGVsZW1lbnRzLCB0aGlzIG9uZSBpcyBnb29kXG4gICAgICBib3VuZGFyaWVzID0gb2Zmc2V0cztcbiAgICB9XG4gIH1cblxuICAvLyBBZGQgcGFkZGluZ3NcbiAgcGFkZGluZyA9IHBhZGRpbmcgfHwgMDtcbiAgdmFyIGlzUGFkZGluZ051bWJlciA9IHR5cGVvZiBwYWRkaW5nID09PSAnbnVtYmVyJztcbiAgYm91bmRhcmllcy5sZWZ0ICs9IGlzUGFkZGluZ051bWJlciA/IHBhZGRpbmcgOiBwYWRkaW5nLmxlZnQgfHwgMDtcbiAgYm91bmRhcmllcy50b3AgKz0gaXNQYWRkaW5nTnVtYmVyID8gcGFkZGluZyA6IHBhZGRpbmcudG9wIHx8IDA7XG4gIGJvdW5kYXJpZXMucmlnaHQgLT0gaXNQYWRkaW5nTnVtYmVyID8gcGFkZGluZyA6IHBhZGRpbmcucmlnaHQgfHwgMDtcbiAgYm91bmRhcmllcy5ib3R0b20gLT0gaXNQYWRkaW5nTnVtYmVyID8gcGFkZGluZyA6IHBhZGRpbmcuYm90dG9tIHx8IDA7XG5cbiAgcmV0dXJuIGJvdW5kYXJpZXM7XG59XG5cbmZ1bmN0aW9uIGdldEFyZWEoX3JlZikge1xuICB2YXIgd2lkdGggPSBfcmVmLndpZHRoLFxuICAgICAgaGVpZ2h0ID0gX3JlZi5oZWlnaHQ7XG5cbiAgcmV0dXJuIHdpZHRoICogaGVpZ2h0O1xufVxuXG4vKipcbiAqIFV0aWxpdHkgdXNlZCB0byB0cmFuc2Zvcm0gdGhlIGBhdXRvYCBwbGFjZW1lbnQgdG8gdGhlIHBsYWNlbWVudCB3aXRoIG1vcmVcbiAqIGF2YWlsYWJsZSBzcGFjZS5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGNvbXB1dGVBdXRvUGxhY2VtZW50KHBsYWNlbWVudCwgcmVmUmVjdCwgcG9wcGVyLCByZWZlcmVuY2UsIGJvdW5kYXJpZXNFbGVtZW50KSB7XG4gIHZhciBwYWRkaW5nID0gYXJndW1lbnRzLmxlbmd0aCA+IDUgJiYgYXJndW1lbnRzWzVdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNV0gOiAwO1xuXG4gIGlmIChwbGFjZW1lbnQuaW5kZXhPZignYXV0bycpID09PSAtMSkge1xuICAgIHJldHVybiBwbGFjZW1lbnQ7XG4gIH1cblxuICB2YXIgYm91bmRhcmllcyA9IGdldEJvdW5kYXJpZXMocG9wcGVyLCByZWZlcmVuY2UsIHBhZGRpbmcsIGJvdW5kYXJpZXNFbGVtZW50KTtcblxuICB2YXIgcmVjdHMgPSB7XG4gICAgdG9wOiB7XG4gICAgICB3aWR0aDogYm91bmRhcmllcy53aWR0aCxcbiAgICAgIGhlaWdodDogcmVmUmVjdC50b3AgLSBib3VuZGFyaWVzLnRvcFxuICAgIH0sXG4gICAgcmlnaHQ6IHtcbiAgICAgIHdpZHRoOiBib3VuZGFyaWVzLnJpZ2h0IC0gcmVmUmVjdC5yaWdodCxcbiAgICAgIGhlaWdodDogYm91bmRhcmllcy5oZWlnaHRcbiAgICB9LFxuICAgIGJvdHRvbToge1xuICAgICAgd2lkdGg6IGJvdW5kYXJpZXMud2lkdGgsXG4gICAgICBoZWlnaHQ6IGJvdW5kYXJpZXMuYm90dG9tIC0gcmVmUmVjdC5ib3R0b21cbiAgICB9LFxuICAgIGxlZnQ6IHtcbiAgICAgIHdpZHRoOiByZWZSZWN0LmxlZnQgLSBib3VuZGFyaWVzLmxlZnQsXG4gICAgICBoZWlnaHQ6IGJvdW5kYXJpZXMuaGVpZ2h0XG4gICAgfVxuICB9O1xuXG4gIHZhciBzb3J0ZWRBcmVhcyA9IE9iamVjdC5rZXlzKHJlY3RzKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiBfZXh0ZW5kcyh7XG4gICAgICBrZXk6IGtleVxuICAgIH0sIHJlY3RzW2tleV0sIHtcbiAgICAgIGFyZWE6IGdldEFyZWEocmVjdHNba2V5XSlcbiAgICB9KTtcbiAgfSkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIHJldHVybiBiLmFyZWEgLSBhLmFyZWE7XG4gIH0pO1xuXG4gIHZhciBmaWx0ZXJlZEFyZWFzID0gc29ydGVkQXJlYXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmMikge1xuICAgIHZhciB3aWR0aCA9IF9yZWYyLndpZHRoLFxuICAgICAgICBoZWlnaHQgPSBfcmVmMi5oZWlnaHQ7XG4gICAgcmV0dXJuIHdpZHRoID49IHBvcHBlci5jbGllbnRXaWR0aCAmJiBoZWlnaHQgPj0gcG9wcGVyLmNsaWVudEhlaWdodDtcbiAgfSk7XG5cbiAgdmFyIGNvbXB1dGVkUGxhY2VtZW50ID0gZmlsdGVyZWRBcmVhcy5sZW5ndGggPiAwID8gZmlsdGVyZWRBcmVhc1swXS5rZXkgOiBzb3J0ZWRBcmVhc1swXS5rZXk7XG5cbiAgdmFyIHZhcmlhdGlvbiA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzFdO1xuXG4gIHJldHVybiBjb21wdXRlZFBsYWNlbWVudCArICh2YXJpYXRpb24gPyAnLScgKyB2YXJpYXRpb24gOiAnJyk7XG59XG5cbi8qKlxuICogR2V0IG9mZnNldHMgdG8gdGhlIHJlZmVyZW5jZSBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGVcbiAqIEBwYXJhbSB7RWxlbWVudH0gcG9wcGVyIC0gdGhlIHBvcHBlciBlbGVtZW50XG4gKiBAcGFyYW0ge0VsZW1lbnR9IHJlZmVyZW5jZSAtIHRoZSByZWZlcmVuY2UgZWxlbWVudCAodGhlIHBvcHBlciB3aWxsIGJlIHJlbGF0aXZlIHRvIHRoaXMpXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGZpeGVkUG9zaXRpb24gLSBpcyBpbiBmaXhlZCBwb3NpdGlvbiBtb2RlXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgb2Zmc2V0cyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlclxuICovXG5mdW5jdGlvbiBnZXRSZWZlcmVuY2VPZmZzZXRzKHN0YXRlLCBwb3BwZXIsIHJlZmVyZW5jZSkge1xuICB2YXIgZml4ZWRQb3NpdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogbnVsbDtcblxuICB2YXIgY29tbW9uT2Zmc2V0UGFyZW50ID0gZml4ZWRQb3NpdGlvbiA/IGdldEZpeGVkUG9zaXRpb25PZmZzZXRQYXJlbnQocG9wcGVyKSA6IGZpbmRDb21tb25PZmZzZXRQYXJlbnQocG9wcGVyLCByZWZlcmVuY2UpO1xuICByZXR1cm4gZ2V0T2Zmc2V0UmVjdFJlbGF0aXZlVG9BcmJpdHJhcnlOb2RlKHJlZmVyZW5jZSwgY29tbW9uT2Zmc2V0UGFyZW50LCBmaXhlZFBvc2l0aW9uKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG91dGVyIHNpemVzIG9mIHRoZSBnaXZlbiBlbGVtZW50IChvZmZzZXQgc2l6ZSArIG1hcmdpbnMpXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtPYmplY3R9IG9iamVjdCBjb250YWluaW5nIHdpZHRoIGFuZCBoZWlnaHQgcHJvcGVydGllc1xuICovXG5mdW5jdGlvbiBnZXRPdXRlclNpemVzKGVsZW1lbnQpIHtcbiAgdmFyIHN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gIHZhciB4ID0gcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luVG9wKSArIHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpbkJvdHRvbSk7XG4gIHZhciB5ID0gcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luTGVmdCkgKyBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5SaWdodCk7XG4gIHZhciByZXN1bHQgPSB7XG4gICAgd2lkdGg6IGVsZW1lbnQub2Zmc2V0V2lkdGggKyB5LFxuICAgIGhlaWdodDogZWxlbWVudC5vZmZzZXRIZWlnaHQgKyB4XG4gIH07XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogR2V0IHRoZSBvcHBvc2l0ZSBwbGFjZW1lbnQgb2YgdGhlIGdpdmVuIG9uZVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IHBsYWNlbWVudFxuICogQHJldHVybnMge1N0cmluZ30gZmxpcHBlZCBwbGFjZW1lbnRcbiAqL1xuZnVuY3Rpb24gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocGxhY2VtZW50KSB7XG4gIHZhciBoYXNoID0geyBsZWZ0OiAncmlnaHQnLCByaWdodDogJ2xlZnQnLCBib3R0b206ICd0b3AnLCB0b3A6ICdib3R0b20nIH07XG4gIHJldHVybiBwbGFjZW1lbnQucmVwbGFjZSgvbGVmdHxyaWdodHxib3R0b218dG9wL2csIGZ1bmN0aW9uIChtYXRjaGVkKSB7XG4gICAgcmV0dXJuIGhhc2hbbWF0Y2hlZF07XG4gIH0pO1xufVxuXG4vKipcbiAqIEdldCBvZmZzZXRzIHRvIHRoZSBwb3BwZXJcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7T2JqZWN0fSBwb3NpdGlvbiAtIENTUyBwb3NpdGlvbiB0aGUgUG9wcGVyIHdpbGwgZ2V0IGFwcGxpZWRcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHBvcHBlciAtIHRoZSBwb3BwZXIgZWxlbWVudFxuICogQHBhcmFtIHtPYmplY3R9IHJlZmVyZW5jZU9mZnNldHMgLSB0aGUgcmVmZXJlbmNlIG9mZnNldHMgKHRoZSBwb3BwZXIgd2lsbCBiZSByZWxhdGl2ZSB0byB0aGlzKVxuICogQHBhcmFtIHtTdHJpbmd9IHBsYWNlbWVudCAtIG9uZSBvZiB0aGUgdmFsaWQgcGxhY2VtZW50IG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IHBvcHBlck9mZnNldHMgLSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgb2Zmc2V0cyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlclxuICovXG5mdW5jdGlvbiBnZXRQb3BwZXJPZmZzZXRzKHBvcHBlciwgcmVmZXJlbmNlT2Zmc2V0cywgcGxhY2VtZW50KSB7XG4gIHBsYWNlbWVudCA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuXG4gIC8vIEdldCBwb3BwZXIgbm9kZSBzaXplc1xuICB2YXIgcG9wcGVyUmVjdCA9IGdldE91dGVyU2l6ZXMocG9wcGVyKTtcblxuICAvLyBBZGQgcG9zaXRpb24sIHdpZHRoIGFuZCBoZWlnaHQgdG8gb3VyIG9mZnNldHMgb2JqZWN0XG4gIHZhciBwb3BwZXJPZmZzZXRzID0ge1xuICAgIHdpZHRoOiBwb3BwZXJSZWN0LndpZHRoLFxuICAgIGhlaWdodDogcG9wcGVyUmVjdC5oZWlnaHRcbiAgfTtcblxuICAvLyBkZXBlbmRpbmcgYnkgdGhlIHBvcHBlciBwbGFjZW1lbnQgd2UgaGF2ZSB0byBjb21wdXRlIGl0cyBvZmZzZXRzIHNsaWdodGx5IGRpZmZlcmVudGx5XG4gIHZhciBpc0hvcml6ID0gWydyaWdodCcsICdsZWZ0J10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcbiAgdmFyIG1haW5TaWRlID0gaXNIb3JpeiA/ICd0b3AnIDogJ2xlZnQnO1xuICB2YXIgc2Vjb25kYXJ5U2lkZSA9IGlzSG9yaXogPyAnbGVmdCcgOiAndG9wJztcbiAgdmFyIG1lYXN1cmVtZW50ID0gaXNIb3JpeiA/ICdoZWlnaHQnIDogJ3dpZHRoJztcbiAgdmFyIHNlY29uZGFyeU1lYXN1cmVtZW50ID0gIWlzSG9yaXogPyAnaGVpZ2h0JyA6ICd3aWR0aCc7XG5cbiAgcG9wcGVyT2Zmc2V0c1ttYWluU2lkZV0gPSByZWZlcmVuY2VPZmZzZXRzW21haW5TaWRlXSArIHJlZmVyZW5jZU9mZnNldHNbbWVhc3VyZW1lbnRdIC8gMiAtIHBvcHBlclJlY3RbbWVhc3VyZW1lbnRdIC8gMjtcbiAgaWYgKHBsYWNlbWVudCA9PT0gc2Vjb25kYXJ5U2lkZSkge1xuICAgIHBvcHBlck9mZnNldHNbc2Vjb25kYXJ5U2lkZV0gPSByZWZlcmVuY2VPZmZzZXRzW3NlY29uZGFyeVNpZGVdIC0gcG9wcGVyUmVjdFtzZWNvbmRhcnlNZWFzdXJlbWVudF07XG4gIH0gZWxzZSB7XG4gICAgcG9wcGVyT2Zmc2V0c1tzZWNvbmRhcnlTaWRlXSA9IHJlZmVyZW5jZU9mZnNldHNbZ2V0T3Bwb3NpdGVQbGFjZW1lbnQoc2Vjb25kYXJ5U2lkZSldO1xuICB9XG5cbiAgcmV0dXJuIHBvcHBlck9mZnNldHM7XG59XG5cbi8qKlxuICogTWltaWNzIHRoZSBgZmluZGAgbWV0aG9kIG9mIEFycmF5XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0FycmF5fSBhcnJcbiAqIEBhcmd1bWVudCBwcm9wXG4gKiBAYXJndW1lbnQgdmFsdWVcbiAqIEByZXR1cm5zIGluZGV4IG9yIC0xXG4gKi9cbmZ1bmN0aW9uIGZpbmQoYXJyLCBjaGVjaykge1xuICAvLyB1c2UgbmF0aXZlIGZpbmQgaWYgc3VwcG9ydGVkXG4gIGlmIChBcnJheS5wcm90b3R5cGUuZmluZCkge1xuICAgIHJldHVybiBhcnIuZmluZChjaGVjayk7XG4gIH1cblxuICAvLyB1c2UgYGZpbHRlcmAgdG8gb2J0YWluIHRoZSBzYW1lIGJlaGF2aW9yIG9mIGBmaW5kYFxuICByZXR1cm4gYXJyLmZpbHRlcihjaGVjaylbMF07XG59XG5cbi8qKlxuICogUmV0dXJuIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hpbmcgb2JqZWN0XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0FycmF5fSBhcnJcbiAqIEBhcmd1bWVudCBwcm9wXG4gKiBAYXJndW1lbnQgdmFsdWVcbiAqIEByZXR1cm5zIGluZGV4IG9yIC0xXG4gKi9cbmZ1bmN0aW9uIGZpbmRJbmRleChhcnIsIHByb3AsIHZhbHVlKSB7XG4gIC8vIHVzZSBuYXRpdmUgZmluZEluZGV4IGlmIHN1cHBvcnRlZFxuICBpZiAoQXJyYXkucHJvdG90eXBlLmZpbmRJbmRleCkge1xuICAgIHJldHVybiBhcnIuZmluZEluZGV4KGZ1bmN0aW9uIChjdXIpIHtcbiAgICAgIHJldHVybiBjdXJbcHJvcF0gPT09IHZhbHVlO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gdXNlIGBmaW5kYCArIGBpbmRleE9mYCBpZiBgZmluZEluZGV4YCBpc24ndCBzdXBwb3J0ZWRcbiAgdmFyIG1hdGNoID0gZmluZChhcnIsIGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gb2JqW3Byb3BdID09PSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiBhcnIuaW5kZXhPZihtYXRjaCk7XG59XG5cbi8qKlxuICogTG9vcCB0cm91Z2ggdGhlIGxpc3Qgb2YgbW9kaWZpZXJzIGFuZCBydW4gdGhlbSBpbiBvcmRlcixcbiAqIGVhY2ggb2YgdGhlbSB3aWxsIHRoZW4gZWRpdCB0aGUgZGF0YSBvYmplY3QuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge2RhdGFPYmplY3R9IGRhdGFcbiAqIEBwYXJhbSB7QXJyYXl9IG1vZGlmaWVyc1xuICogQHBhcmFtIHtTdHJpbmd9IGVuZHMgLSBPcHRpb25hbCBtb2RpZmllciBuYW1lIHVzZWQgYXMgc3RvcHBlclxuICogQHJldHVybnMge2RhdGFPYmplY3R9XG4gKi9cbmZ1bmN0aW9uIHJ1bk1vZGlmaWVycyhtb2RpZmllcnMsIGRhdGEsIGVuZHMpIHtcbiAgdmFyIG1vZGlmaWVyc1RvUnVuID0gZW5kcyA9PT0gdW5kZWZpbmVkID8gbW9kaWZpZXJzIDogbW9kaWZpZXJzLnNsaWNlKDAsIGZpbmRJbmRleChtb2RpZmllcnMsICduYW1lJywgZW5kcykpO1xuXG4gIG1vZGlmaWVyc1RvUnVuLmZvckVhY2goZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgaWYgKG1vZGlmaWVyWydmdW5jdGlvbiddKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGRvdC1ub3RhdGlvblxuICAgICAgY29uc29sZS53YXJuKCdgbW9kaWZpZXIuZnVuY3Rpb25gIGlzIGRlcHJlY2F0ZWQsIHVzZSBgbW9kaWZpZXIuZm5gIScpO1xuICAgIH1cbiAgICB2YXIgZm4gPSBtb2RpZmllclsnZnVuY3Rpb24nXSB8fCBtb2RpZmllci5mbjsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICBpZiAobW9kaWZpZXIuZW5hYmxlZCAmJiBpc0Z1bmN0aW9uKGZuKSkge1xuICAgICAgLy8gQWRkIHByb3BlcnRpZXMgdG8gb2Zmc2V0cyB0byBtYWtlIHRoZW0gYSBjb21wbGV0ZSBjbGllbnRSZWN0IG9iamVjdFxuICAgICAgLy8gd2UgZG8gdGhpcyBiZWZvcmUgZWFjaCBtb2RpZmllciB0byBtYWtlIHN1cmUgdGhlIHByZXZpb3VzIG9uZSBkb2Vzbid0XG4gICAgICAvLyBtZXNzIHdpdGggdGhlc2UgdmFsdWVzXG4gICAgICBkYXRhLm9mZnNldHMucG9wcGVyID0gZ2V0Q2xpZW50UmVjdChkYXRhLm9mZnNldHMucG9wcGVyKTtcbiAgICAgIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UgPSBnZXRDbGllbnRSZWN0KGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UpO1xuXG4gICAgICBkYXRhID0gZm4oZGF0YSwgbW9kaWZpZXIpO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogVXBkYXRlcyB0aGUgcG9zaXRpb24gb2YgdGhlIHBvcHBlciwgY29tcHV0aW5nIHRoZSBuZXcgb2Zmc2V0cyBhbmQgYXBwbHlpbmdcbiAqIHRoZSBuZXcgc3R5bGUuPGJyIC8+XG4gKiBQcmVmZXIgYHNjaGVkdWxlVXBkYXRlYCBvdmVyIGB1cGRhdGVgIGJlY2F1c2Ugb2YgcGVyZm9ybWFuY2UgcmVhc29ucy5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXJcbiAqL1xuZnVuY3Rpb24gdXBkYXRlKCkge1xuICAvLyBpZiBwb3BwZXIgaXMgZGVzdHJveWVkLCBkb24ndCBwZXJmb3JtIGFueSBmdXJ0aGVyIHVwZGF0ZVxuICBpZiAodGhpcy5zdGF0ZS5pc0Rlc3Ryb3llZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBkYXRhID0ge1xuICAgIGluc3RhbmNlOiB0aGlzLFxuICAgIHN0eWxlczoge30sXG4gICAgYXJyb3dTdHlsZXM6IHt9LFxuICAgIGF0dHJpYnV0ZXM6IHt9LFxuICAgIGZsaXBwZWQ6IGZhbHNlLFxuICAgIG9mZnNldHM6IHt9XG4gIH07XG5cbiAgLy8gY29tcHV0ZSByZWZlcmVuY2UgZWxlbWVudCBvZmZzZXRzXG4gIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UgPSBnZXRSZWZlcmVuY2VPZmZzZXRzKHRoaXMuc3RhdGUsIHRoaXMucG9wcGVyLCB0aGlzLnJlZmVyZW5jZSwgdGhpcy5vcHRpb25zLnBvc2l0aW9uRml4ZWQpO1xuXG4gIC8vIGNvbXB1dGUgYXV0byBwbGFjZW1lbnQsIHN0b3JlIHBsYWNlbWVudCBpbnNpZGUgdGhlIGRhdGEgb2JqZWN0LFxuICAvLyBtb2RpZmllcnMgd2lsbCBiZSBhYmxlIHRvIGVkaXQgYHBsYWNlbWVudGAgaWYgbmVlZGVkXG4gIC8vIGFuZCByZWZlciB0byBvcmlnaW5hbFBsYWNlbWVudCB0byBrbm93IHRoZSBvcmlnaW5hbCB2YWx1ZVxuICBkYXRhLnBsYWNlbWVudCA9IGNvbXB1dGVBdXRvUGxhY2VtZW50KHRoaXMub3B0aW9ucy5wbGFjZW1lbnQsIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UsIHRoaXMucG9wcGVyLCB0aGlzLnJlZmVyZW5jZSwgdGhpcy5vcHRpb25zLm1vZGlmaWVycy5mbGlwLmJvdW5kYXJpZXNFbGVtZW50LCB0aGlzLm9wdGlvbnMubW9kaWZpZXJzLmZsaXAucGFkZGluZyk7XG5cbiAgLy8gc3RvcmUgdGhlIGNvbXB1dGVkIHBsYWNlbWVudCBpbnNpZGUgYG9yaWdpbmFsUGxhY2VtZW50YFxuICBkYXRhLm9yaWdpbmFsUGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQ7XG5cbiAgZGF0YS5wb3NpdGlvbkZpeGVkID0gdGhpcy5vcHRpb25zLnBvc2l0aW9uRml4ZWQ7XG5cbiAgLy8gY29tcHV0ZSB0aGUgcG9wcGVyIG9mZnNldHNcbiAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldFBvcHBlck9mZnNldHModGhpcy5wb3BwZXIsIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UsIGRhdGEucGxhY2VtZW50KTtcblxuICBkYXRhLm9mZnNldHMucG9wcGVyLnBvc2l0aW9uID0gdGhpcy5vcHRpb25zLnBvc2l0aW9uRml4ZWQgPyAnZml4ZWQnIDogJ2Fic29sdXRlJztcblxuICAvLyBydW4gdGhlIG1vZGlmaWVyc1xuICBkYXRhID0gcnVuTW9kaWZpZXJzKHRoaXMubW9kaWZpZXJzLCBkYXRhKTtcblxuICAvLyB0aGUgZmlyc3QgYHVwZGF0ZWAgd2lsbCBjYWxsIGBvbkNyZWF0ZWAgY2FsbGJhY2tcbiAgLy8gdGhlIG90aGVyIG9uZXMgd2lsbCBjYWxsIGBvblVwZGF0ZWAgY2FsbGJhY2tcbiAgaWYgKCF0aGlzLnN0YXRlLmlzQ3JlYXRlZCkge1xuICAgIHRoaXMuc3RhdGUuaXNDcmVhdGVkID0gdHJ1ZTtcbiAgICB0aGlzLm9wdGlvbnMub25DcmVhdGUoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5vcHRpb25zLm9uVXBkYXRlKGRhdGEpO1xuICB9XG59XG5cbi8qKlxuICogSGVscGVyIHVzZWQgdG8ga25vdyBpZiB0aGUgZ2l2ZW4gbW9kaWZpZXIgaXMgZW5hYmxlZC5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEByZXR1cm5zIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc01vZGlmaWVyRW5hYmxlZChtb2RpZmllcnMsIG1vZGlmaWVyTmFtZSkge1xuICByZXR1cm4gbW9kaWZpZXJzLnNvbWUoZnVuY3Rpb24gKF9yZWYpIHtcbiAgICB2YXIgbmFtZSA9IF9yZWYubmFtZSxcbiAgICAgICAgZW5hYmxlZCA9IF9yZWYuZW5hYmxlZDtcbiAgICByZXR1cm4gZW5hYmxlZCAmJiBuYW1lID09PSBtb2RpZmllck5hbWU7XG4gIH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgcHJlZml4ZWQgc3VwcG9ydGVkIHByb3BlcnR5IG5hbWVcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBwcm9wZXJ0eSAoY2FtZWxDYXNlKVxuICogQHJldHVybnMge1N0cmluZ30gcHJlZml4ZWQgcHJvcGVydHkgKGNhbWVsQ2FzZSBvciBQYXNjYWxDYXNlLCBkZXBlbmRpbmcgb24gdGhlIHZlbmRvciBwcmVmaXgpXG4gKi9cbmZ1bmN0aW9uIGdldFN1cHBvcnRlZFByb3BlcnR5TmFtZShwcm9wZXJ0eSkge1xuICB2YXIgcHJlZml4ZXMgPSBbZmFsc2UsICdtcycsICdXZWJraXQnLCAnTW96JywgJ08nXTtcbiAgdmFyIHVwcGVyUHJvcCA9IHByb3BlcnR5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcHJvcGVydHkuc2xpY2UoMSk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcmVmaXhlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwcmVmaXggPSBwcmVmaXhlc1tpXTtcbiAgICB2YXIgdG9DaGVjayA9IHByZWZpeCA/ICcnICsgcHJlZml4ICsgdXBwZXJQcm9wIDogcHJvcGVydHk7XG4gICAgaWYgKHR5cGVvZiBkb2N1bWVudC5ib2R5LnN0eWxlW3RvQ2hlY2tdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIHRvQ2hlY2s7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIERlc3Ryb3lzIHRoZSBwb3BwZXIuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbmZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gIHRoaXMuc3RhdGUuaXNEZXN0cm95ZWQgPSB0cnVlO1xuXG4gIC8vIHRvdWNoIERPTSBvbmx5IGlmIGBhcHBseVN0eWxlYCBtb2RpZmllciBpcyBlbmFibGVkXG4gIGlmIChpc01vZGlmaWVyRW5hYmxlZCh0aGlzLm1vZGlmaWVycywgJ2FwcGx5U3R5bGUnKSkge1xuICAgIHRoaXMucG9wcGVyLnJlbW92ZUF0dHJpYnV0ZSgneC1wbGFjZW1lbnQnKTtcbiAgICB0aGlzLnBvcHBlci5zdHlsZS5wb3NpdGlvbiA9ICcnO1xuICAgIHRoaXMucG9wcGVyLnN0eWxlLnRvcCA9ICcnO1xuICAgIHRoaXMucG9wcGVyLnN0eWxlLmxlZnQgPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZS5yaWdodCA9ICcnO1xuICAgIHRoaXMucG9wcGVyLnN0eWxlLmJvdHRvbSA9ICcnO1xuICAgIHRoaXMucG9wcGVyLnN0eWxlLndpbGxDaGFuZ2UgPSAnJztcbiAgICB0aGlzLnBvcHBlci5zdHlsZVtnZXRTdXBwb3J0ZWRQcm9wZXJ0eU5hbWUoJ3RyYW5zZm9ybScpXSA9ICcnO1xuICB9XG5cbiAgdGhpcy5kaXNhYmxlRXZlbnRMaXN0ZW5lcnMoKTtcblxuICAvLyByZW1vdmUgdGhlIHBvcHBlciBpZiB1c2VyIGV4cGxpY2l0eSBhc2tlZCBmb3IgdGhlIGRlbGV0aW9uIG9uIGRlc3Ryb3lcbiAgLy8gZG8gbm90IHVzZSBgcmVtb3ZlYCBiZWNhdXNlIElFMTEgZG9lc24ndCBzdXBwb3J0IGl0XG4gIGlmICh0aGlzLm9wdGlvbnMucmVtb3ZlT25EZXN0cm95KSB7XG4gICAgdGhpcy5wb3BwZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLnBvcHBlcik7XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59XG5cbi8qKlxuICogR2V0IHRoZSB3aW5kb3cgYXNzb2NpYXRlZCB3aXRoIHRoZSBlbGVtZW50XG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtXaW5kb3d9XG4gKi9cbmZ1bmN0aW9uIGdldFdpbmRvdyhlbGVtZW50KSB7XG4gIHZhciBvd25lckRvY3VtZW50ID0gZWxlbWVudC5vd25lckRvY3VtZW50O1xuICByZXR1cm4gb3duZXJEb2N1bWVudCA/IG93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgOiB3aW5kb3c7XG59XG5cbmZ1bmN0aW9uIGF0dGFjaFRvU2Nyb2xsUGFyZW50cyhzY3JvbGxQYXJlbnQsIGV2ZW50LCBjYWxsYmFjaywgc2Nyb2xsUGFyZW50cykge1xuICB2YXIgaXNCb2R5ID0gc2Nyb2xsUGFyZW50Lm5vZGVOYW1lID09PSAnQk9EWSc7XG4gIHZhciB0YXJnZXQgPSBpc0JvZHkgPyBzY3JvbGxQYXJlbnQub3duZXJEb2N1bWVudC5kZWZhdWx0VmlldyA6IHNjcm9sbFBhcmVudDtcbiAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGNhbGxiYWNrLCB7IHBhc3NpdmU6IHRydWUgfSk7XG5cbiAgaWYgKCFpc0JvZHkpIHtcbiAgICBhdHRhY2hUb1Njcm9sbFBhcmVudHMoZ2V0U2Nyb2xsUGFyZW50KHRhcmdldC5wYXJlbnROb2RlKSwgZXZlbnQsIGNhbGxiYWNrLCBzY3JvbGxQYXJlbnRzKTtcbiAgfVxuICBzY3JvbGxQYXJlbnRzLnB1c2godGFyZ2V0KTtcbn1cblxuLyoqXG4gKiBTZXR1cCBuZWVkZWQgZXZlbnQgbGlzdGVuZXJzIHVzZWQgdG8gdXBkYXRlIHRoZSBwb3BwZXIgcG9zaXRpb25cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHNldHVwRXZlbnRMaXN0ZW5lcnMocmVmZXJlbmNlLCBvcHRpb25zLCBzdGF0ZSwgdXBkYXRlQm91bmQpIHtcbiAgLy8gUmVzaXplIGV2ZW50IGxpc3RlbmVyIG9uIHdpbmRvd1xuICBzdGF0ZS51cGRhdGVCb3VuZCA9IHVwZGF0ZUJvdW5kO1xuICBnZXRXaW5kb3cocmVmZXJlbmNlKS5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCBzdGF0ZS51cGRhdGVCb3VuZCwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4gIC8vIFNjcm9sbCBldmVudCBsaXN0ZW5lciBvbiBzY3JvbGwgcGFyZW50c1xuICB2YXIgc2Nyb2xsRWxlbWVudCA9IGdldFNjcm9sbFBhcmVudChyZWZlcmVuY2UpO1xuICBhdHRhY2hUb1Njcm9sbFBhcmVudHMoc2Nyb2xsRWxlbWVudCwgJ3Njcm9sbCcsIHN0YXRlLnVwZGF0ZUJvdW5kLCBzdGF0ZS5zY3JvbGxQYXJlbnRzKTtcbiAgc3RhdGUuc2Nyb2xsRWxlbWVudCA9IHNjcm9sbEVsZW1lbnQ7XG4gIHN0YXRlLmV2ZW50c0VuYWJsZWQgPSB0cnVlO1xuXG4gIHJldHVybiBzdGF0ZTtcbn1cblxuLyoqXG4gKiBJdCB3aWxsIGFkZCByZXNpemUvc2Nyb2xsIGV2ZW50cyBhbmQgc3RhcnQgcmVjYWxjdWxhdGluZ1xuICogcG9zaXRpb24gb2YgdGhlIHBvcHBlciBlbGVtZW50IHdoZW4gdGhleSBhcmUgdHJpZ2dlcmVkLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG5mdW5jdGlvbiBlbmFibGVFdmVudExpc3RlbmVycygpIHtcbiAgaWYgKCF0aGlzLnN0YXRlLmV2ZW50c0VuYWJsZWQpIHtcbiAgICB0aGlzLnN0YXRlID0gc2V0dXBFdmVudExpc3RlbmVycyh0aGlzLnJlZmVyZW5jZSwgdGhpcy5vcHRpb25zLCB0aGlzLnN0YXRlLCB0aGlzLnNjaGVkdWxlVXBkYXRlKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlbW92ZSBldmVudCBsaXN0ZW5lcnMgdXNlZCB0byB1cGRhdGUgdGhlIHBvcHBlciBwb3NpdGlvblxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gcmVtb3ZlRXZlbnRMaXN0ZW5lcnMocmVmZXJlbmNlLCBzdGF0ZSkge1xuICAvLyBSZW1vdmUgcmVzaXplIGV2ZW50IGxpc3RlbmVyIG9uIHdpbmRvd1xuICBnZXRXaW5kb3cocmVmZXJlbmNlKS5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCBzdGF0ZS51cGRhdGVCb3VuZCk7XG5cbiAgLy8gUmVtb3ZlIHNjcm9sbCBldmVudCBsaXN0ZW5lciBvbiBzY3JvbGwgcGFyZW50c1xuICBzdGF0ZS5zY3JvbGxQYXJlbnRzLmZvckVhY2goZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIHRhcmdldC5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzdGF0ZS51cGRhdGVCb3VuZCk7XG4gIH0pO1xuXG4gIC8vIFJlc2V0IHN0YXRlXG4gIHN0YXRlLnVwZGF0ZUJvdW5kID0gbnVsbDtcbiAgc3RhdGUuc2Nyb2xsUGFyZW50cyA9IFtdO1xuICBzdGF0ZS5zY3JvbGxFbGVtZW50ID0gbnVsbDtcbiAgc3RhdGUuZXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qKlxuICogSXQgd2lsbCByZW1vdmUgcmVzaXplL3Njcm9sbCBldmVudHMgYW5kIHdvbid0IHJlY2FsY3VsYXRlIHBvcHBlciBwb3NpdGlvblxuICogd2hlbiB0aGV5IGFyZSB0cmlnZ2VyZWQuIEl0IGFsc28gd29uJ3QgdHJpZ2dlciBgb25VcGRhdGVgIGNhbGxiYWNrIGFueW1vcmUsXG4gKiB1bmxlc3MgeW91IGNhbGwgYHVwZGF0ZWAgbWV0aG9kIG1hbnVhbGx5LlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG5mdW5jdGlvbiBkaXNhYmxlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gIGlmICh0aGlzLnN0YXRlLmV2ZW50c0VuYWJsZWQpIHtcbiAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnNjaGVkdWxlVXBkYXRlKTtcbiAgICB0aGlzLnN0YXRlID0gcmVtb3ZlRXZlbnRMaXN0ZW5lcnModGhpcy5yZWZlcmVuY2UsIHRoaXMuc3RhdGUpO1xuICB9XG59XG5cbi8qKlxuICogVGVsbHMgaWYgYSBnaXZlbiBpbnB1dCBpcyBhIG51bWJlclxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHsqfSBpbnB1dCB0byBjaGVja1xuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNOdW1lcmljKG4pIHtcbiAgcmV0dXJuIG4gIT09ICcnICYmICFpc05hTihwYXJzZUZsb2F0KG4pKSAmJiBpc0Zpbml0ZShuKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIHN0eWxlIHRvIHRoZSBnaXZlbiBwb3BwZXJcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudCAtIEVsZW1lbnQgdG8gYXBwbHkgdGhlIHN0eWxlIHRvXG4gKiBAYXJndW1lbnQge09iamVjdH0gc3R5bGVzXG4gKiBPYmplY3Qgd2l0aCBhIGxpc3Qgb2YgcHJvcGVydGllcyBhbmQgdmFsdWVzIHdoaWNoIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgZWxlbWVudFxuICovXG5mdW5jdGlvbiBzZXRTdHlsZXMoZWxlbWVudCwgc3R5bGVzKSB7XG4gIE9iamVjdC5rZXlzKHN0eWxlcykuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgIHZhciB1bml0ID0gJyc7XG4gICAgLy8gYWRkIHVuaXQgaWYgdGhlIHZhbHVlIGlzIG51bWVyaWMgYW5kIGlzIG9uZSBvZiB0aGUgZm9sbG93aW5nXG4gICAgaWYgKFsnd2lkdGgnLCAnaGVpZ2h0JywgJ3RvcCcsICdyaWdodCcsICdib3R0b20nLCAnbGVmdCddLmluZGV4T2YocHJvcCkgIT09IC0xICYmIGlzTnVtZXJpYyhzdHlsZXNbcHJvcF0pKSB7XG4gICAgICB1bml0ID0gJ3B4JztcbiAgICB9XG4gICAgZWxlbWVudC5zdHlsZVtwcm9wXSA9IHN0eWxlc1twcm9wXSArIHVuaXQ7XG4gIH0pO1xufVxuXG4vKipcbiAqIFNldCB0aGUgYXR0cmlidXRlcyB0byB0aGUgZ2l2ZW4gcG9wcGVyXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnQgLSBFbGVtZW50IHRvIGFwcGx5IHRoZSBhdHRyaWJ1dGVzIHRvXG4gKiBAYXJndW1lbnQge09iamVjdH0gc3R5bGVzXG4gKiBPYmplY3Qgd2l0aCBhIGxpc3Qgb2YgcHJvcGVydGllcyBhbmQgdmFsdWVzIHdoaWNoIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgZWxlbWVudFxuICovXG5mdW5jdGlvbiBzZXRBdHRyaWJ1dGVzKGVsZW1lbnQsIGF0dHJpYnV0ZXMpIHtcbiAgT2JqZWN0LmtleXMoYXR0cmlidXRlcykuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgIHZhciB2YWx1ZSA9IGF0dHJpYnV0ZXNbcHJvcF07XG4gICAgaWYgKHZhbHVlICE9PSBmYWxzZSkge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUocHJvcCwgYXR0cmlidXRlc1twcm9wXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKHByb3ApO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YS5zdHlsZXMgLSBMaXN0IG9mIHN0eWxlIHByb3BlcnRpZXMgLSB2YWx1ZXMgdG8gYXBwbHkgdG8gcG9wcGVyIGVsZW1lbnRcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhLmF0dHJpYnV0ZXMgLSBMaXN0IG9mIGF0dHJpYnV0ZSBwcm9wZXJ0aWVzIC0gdmFsdWVzIHRvIGFwcGx5IHRvIHBvcHBlciBlbGVtZW50XG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgc2FtZSBkYXRhIG9iamVjdFxuICovXG5mdW5jdGlvbiBhcHBseVN0eWxlKGRhdGEpIHtcbiAgLy8gYW55IHByb3BlcnR5IHByZXNlbnQgaW4gYGRhdGEuc3R5bGVzYCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlcixcbiAgLy8gaW4gdGhpcyB3YXkgd2UgY2FuIG1ha2UgdGhlIDNyZCBwYXJ0eSBtb2RpZmllcnMgYWRkIGN1c3RvbSBzdHlsZXMgdG8gaXRcbiAgLy8gQmUgYXdhcmUsIG1vZGlmaWVycyBjb3VsZCBvdmVycmlkZSB0aGUgcHJvcGVydGllcyBkZWZpbmVkIGluIHRoZSBwcmV2aW91c1xuICAvLyBsaW5lcyBvZiB0aGlzIG1vZGlmaWVyIVxuICBzZXRTdHlsZXMoZGF0YS5pbnN0YW5jZS5wb3BwZXIsIGRhdGEuc3R5bGVzKTtcblxuICAvLyBhbnkgcHJvcGVydHkgcHJlc2VudCBpbiBgZGF0YS5hdHRyaWJ1dGVzYCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlcixcbiAgLy8gdGhleSB3aWxsIGJlIHNldCBhcyBIVE1MIGF0dHJpYnV0ZXMgb2YgdGhlIGVsZW1lbnRcbiAgc2V0QXR0cmlidXRlcyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5hdHRyaWJ1dGVzKTtcblxuICAvLyBpZiBhcnJvd0VsZW1lbnQgaXMgZGVmaW5lZCBhbmQgYXJyb3dTdHlsZXMgaGFzIHNvbWUgcHJvcGVydGllc1xuICBpZiAoZGF0YS5hcnJvd0VsZW1lbnQgJiYgT2JqZWN0LmtleXMoZGF0YS5hcnJvd1N0eWxlcykubGVuZ3RoKSB7XG4gICAgc2V0U3R5bGVzKGRhdGEuYXJyb3dFbGVtZW50LCBkYXRhLmFycm93U3R5bGVzKTtcbiAgfVxuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIFNldCB0aGUgeC1wbGFjZW1lbnQgYXR0cmlidXRlIGJlZm9yZSBldmVyeXRoaW5nIGVsc2UgYmVjYXVzZSBpdCBjb3VsZCBiZSB1c2VkXG4gKiB0byBhZGQgbWFyZ2lucyB0byB0aGUgcG9wcGVyIG1hcmdpbnMgbmVlZHMgdG8gYmUgY2FsY3VsYXRlZCB0byBnZXQgdGhlXG4gKiBjb3JyZWN0IHBvcHBlciBvZmZzZXRzLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5tb2RpZmllcnNcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHJlZmVyZW5jZSAtIFRoZSByZWZlcmVuY2UgZWxlbWVudCB1c2VkIHRvIHBvc2l0aW9uIHRoZSBwb3BwZXJcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHBvcHBlciAtIFRoZSBIVE1MIGVsZW1lbnQgdXNlZCBhcyBwb3BwZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gUG9wcGVyLmpzIG9wdGlvbnNcbiAqL1xuZnVuY3Rpb24gYXBwbHlTdHlsZU9uTG9hZChyZWZlcmVuY2UsIHBvcHBlciwgb3B0aW9ucywgbW9kaWZpZXJPcHRpb25zLCBzdGF0ZSkge1xuICAvLyBjb21wdXRlIHJlZmVyZW5jZSBlbGVtZW50IG9mZnNldHNcbiAgdmFyIHJlZmVyZW5jZU9mZnNldHMgPSBnZXRSZWZlcmVuY2VPZmZzZXRzKHN0YXRlLCBwb3BwZXIsIHJlZmVyZW5jZSwgb3B0aW9ucy5wb3NpdGlvbkZpeGVkKTtcblxuICAvLyBjb21wdXRlIGF1dG8gcGxhY2VtZW50LCBzdG9yZSBwbGFjZW1lbnQgaW5zaWRlIHRoZSBkYXRhIG9iamVjdCxcbiAgLy8gbW9kaWZpZXJzIHdpbGwgYmUgYWJsZSB0byBlZGl0IGBwbGFjZW1lbnRgIGlmIG5lZWRlZFxuICAvLyBhbmQgcmVmZXIgdG8gb3JpZ2luYWxQbGFjZW1lbnQgdG8ga25vdyB0aGUgb3JpZ2luYWwgdmFsdWVcbiAgdmFyIHBsYWNlbWVudCA9IGNvbXB1dGVBdXRvUGxhY2VtZW50KG9wdGlvbnMucGxhY2VtZW50LCByZWZlcmVuY2VPZmZzZXRzLCBwb3BwZXIsIHJlZmVyZW5jZSwgb3B0aW9ucy5tb2RpZmllcnMuZmxpcC5ib3VuZGFyaWVzRWxlbWVudCwgb3B0aW9ucy5tb2RpZmllcnMuZmxpcC5wYWRkaW5nKTtcblxuICBwb3BwZXIuc2V0QXR0cmlidXRlKCd4LXBsYWNlbWVudCcsIHBsYWNlbWVudCk7XG5cbiAgLy8gQXBwbHkgYHBvc2l0aW9uYCB0byBwb3BwZXIgYmVmb3JlIGFueXRoaW5nIGVsc2UgYmVjYXVzZVxuICAvLyB3aXRob3V0IHRoZSBwb3NpdGlvbiBhcHBsaWVkIHdlIGNhbid0IGd1YXJhbnRlZSBjb3JyZWN0IGNvbXB1dGF0aW9uc1xuICBzZXRTdHlsZXMocG9wcGVyLCB7IHBvc2l0aW9uOiBvcHRpb25zLnBvc2l0aW9uRml4ZWQgPyAnZml4ZWQnIDogJ2Fic29sdXRlJyB9KTtcblxuICByZXR1cm4gb3B0aW9ucztcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gY29tcHV0ZVN0eWxlKGRhdGEsIG9wdGlvbnMpIHtcbiAgdmFyIHggPSBvcHRpb25zLngsXG4gICAgICB5ID0gb3B0aW9ucy55O1xuICB2YXIgcG9wcGVyID0gZGF0YS5vZmZzZXRzLnBvcHBlcjtcblxuICAvLyBSZW1vdmUgdGhpcyBsZWdhY3kgc3VwcG9ydCBpbiBQb3BwZXIuanMgdjJcblxuICB2YXIgbGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uID0gZmluZChkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgcmV0dXJuIG1vZGlmaWVyLm5hbWUgPT09ICdhcHBseVN0eWxlJztcbiAgfSkuZ3B1QWNjZWxlcmF0aW9uO1xuICBpZiAobGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zb2xlLndhcm4oJ1dBUk5JTkc6IGBncHVBY2NlbGVyYXRpb25gIG9wdGlvbiBtb3ZlZCB0byBgY29tcHV0ZVN0eWxlYCBtb2RpZmllciBhbmQgd2lsbCBub3QgYmUgc3VwcG9ydGVkIGluIGZ1dHVyZSB2ZXJzaW9ucyBvZiBQb3BwZXIuanMhJyk7XG4gIH1cbiAgdmFyIGdwdUFjY2VsZXJhdGlvbiA9IGxlZ2FjeUdwdUFjY2VsZXJhdGlvbk9wdGlvbiAhPT0gdW5kZWZpbmVkID8gbGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uIDogb3B0aW9ucy5ncHVBY2NlbGVyYXRpb247XG5cbiAgdmFyIG9mZnNldFBhcmVudCA9IGdldE9mZnNldFBhcmVudChkYXRhLmluc3RhbmNlLnBvcHBlcik7XG4gIHZhciBvZmZzZXRQYXJlbnRSZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KG9mZnNldFBhcmVudCk7XG5cbiAgLy8gU3R5bGVzXG4gIHZhciBzdHlsZXMgPSB7XG4gICAgcG9zaXRpb246IHBvcHBlci5wb3NpdGlvblxuICB9O1xuXG4gIC8vIEF2b2lkIGJsdXJyeSB0ZXh0IGJ5IHVzaW5nIGZ1bGwgcGl4ZWwgaW50ZWdlcnMuXG4gIC8vIEZvciBwaXhlbC1wZXJmZWN0IHBvc2l0aW9uaW5nLCB0b3AvYm90dG9tIHByZWZlcnMgcm91bmRlZFxuICAvLyB2YWx1ZXMsIHdoaWxlIGxlZnQvcmlnaHQgcHJlZmVycyBmbG9vcmVkIHZhbHVlcy5cbiAgdmFyIG9mZnNldHMgPSB7XG4gICAgbGVmdDogTWF0aC5mbG9vcihwb3BwZXIubGVmdCksXG4gICAgdG9wOiBNYXRoLnJvdW5kKHBvcHBlci50b3ApLFxuICAgIGJvdHRvbTogTWF0aC5yb3VuZChwb3BwZXIuYm90dG9tKSxcbiAgICByaWdodDogTWF0aC5mbG9vcihwb3BwZXIucmlnaHQpXG4gIH07XG5cbiAgdmFyIHNpZGVBID0geCA9PT0gJ2JvdHRvbScgPyAndG9wJyA6ICdib3R0b20nO1xuICB2YXIgc2lkZUIgPSB5ID09PSAncmlnaHQnID8gJ2xlZnQnIDogJ3JpZ2h0JztcblxuICAvLyBpZiBncHVBY2NlbGVyYXRpb24gaXMgc2V0IHRvIGB0cnVlYCBhbmQgdHJhbnNmb3JtIGlzIHN1cHBvcnRlZCxcbiAgLy8gIHdlIHVzZSBgdHJhbnNsYXRlM2RgIHRvIGFwcGx5IHRoZSBwb3NpdGlvbiB0byB0aGUgcG9wcGVyIHdlXG4gIC8vIGF1dG9tYXRpY2FsbHkgdXNlIHRoZSBzdXBwb3J0ZWQgcHJlZml4ZWQgdmVyc2lvbiBpZiBuZWVkZWRcbiAgdmFyIHByZWZpeGVkUHJvcGVydHkgPSBnZXRTdXBwb3J0ZWRQcm9wZXJ0eU5hbWUoJ3RyYW5zZm9ybScpO1xuXG4gIC8vIG5vdywgbGV0J3MgbWFrZSBhIHN0ZXAgYmFjayBhbmQgbG9vayBhdCB0aGlzIGNvZGUgY2xvc2VseSAod3RmPylcbiAgLy8gSWYgdGhlIGNvbnRlbnQgb2YgdGhlIHBvcHBlciBncm93cyBvbmNlIGl0J3MgYmVlbiBwb3NpdGlvbmVkLCBpdFxuICAvLyBtYXkgaGFwcGVuIHRoYXQgdGhlIHBvcHBlciBnZXRzIG1pc3BsYWNlZCBiZWNhdXNlIG9mIHRoZSBuZXcgY29udGVudFxuICAvLyBvdmVyZmxvd2luZyBpdHMgcmVmZXJlbmNlIGVsZW1lbnRcbiAgLy8gVG8gYXZvaWQgdGhpcyBwcm9ibGVtLCB3ZSBwcm92aWRlIHR3byBvcHRpb25zICh4IGFuZCB5KSwgd2hpY2ggYWxsb3dcbiAgLy8gdGhlIGNvbnN1bWVyIHRvIGRlZmluZSB0aGUgb2Zmc2V0IG9yaWdpbi5cbiAgLy8gSWYgd2UgcG9zaXRpb24gYSBwb3BwZXIgb24gdG9wIG9mIGEgcmVmZXJlbmNlIGVsZW1lbnQsIHdlIGNhbiBzZXRcbiAgLy8gYHhgIHRvIGB0b3BgIHRvIG1ha2UgdGhlIHBvcHBlciBncm93IHRvd2FyZHMgaXRzIHRvcCBpbnN0ZWFkIG9mXG4gIC8vIGl0cyBib3R0b20uXG4gIHZhciBsZWZ0ID0gdm9pZCAwLFxuICAgICAgdG9wID0gdm9pZCAwO1xuICBpZiAoc2lkZUEgPT09ICdib3R0b20nKSB7XG4gICAgLy8gd2hlbiBvZmZzZXRQYXJlbnQgaXMgPGh0bWw+IHRoZSBwb3NpdGlvbmluZyBpcyByZWxhdGl2ZSB0byB0aGUgYm90dG9tIG9mIHRoZSBzY3JlZW4gKGV4Y2x1ZGluZyB0aGUgc2Nyb2xsYmFyKVxuICAgIC8vIGFuZCBub3QgdGhlIGJvdHRvbSBvZiB0aGUgaHRtbCBlbGVtZW50XG4gICAgaWYgKG9mZnNldFBhcmVudC5ub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgICB0b3AgPSAtb2Zmc2V0UGFyZW50LmNsaWVudEhlaWdodCArIG9mZnNldHMuYm90dG9tO1xuICAgIH0gZWxzZSB7XG4gICAgICB0b3AgPSAtb2Zmc2V0UGFyZW50UmVjdC5oZWlnaHQgKyBvZmZzZXRzLmJvdHRvbTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdG9wID0gb2Zmc2V0cy50b3A7XG4gIH1cbiAgaWYgKHNpZGVCID09PSAncmlnaHQnKSB7XG4gICAgaWYgKG9mZnNldFBhcmVudC5ub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgICBsZWZ0ID0gLW9mZnNldFBhcmVudC5jbGllbnRXaWR0aCArIG9mZnNldHMucmlnaHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxlZnQgPSAtb2Zmc2V0UGFyZW50UmVjdC53aWR0aCArIG9mZnNldHMucmlnaHQ7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGxlZnQgPSBvZmZzZXRzLmxlZnQ7XG4gIH1cbiAgaWYgKGdwdUFjY2VsZXJhdGlvbiAmJiBwcmVmaXhlZFByb3BlcnR5KSB7XG4gICAgc3R5bGVzW3ByZWZpeGVkUHJvcGVydHldID0gJ3RyYW5zbGF0ZTNkKCcgKyBsZWZ0ICsgJ3B4LCAnICsgdG9wICsgJ3B4LCAwKSc7XG4gICAgc3R5bGVzW3NpZGVBXSA9IDA7XG4gICAgc3R5bGVzW3NpZGVCXSA9IDA7XG4gICAgc3R5bGVzLndpbGxDaGFuZ2UgPSAndHJhbnNmb3JtJztcbiAgfSBlbHNlIHtcbiAgICAvLyBvdGh3ZXJpc2UsIHdlIHVzZSB0aGUgc3RhbmRhcmQgYHRvcGAsIGBsZWZ0YCwgYGJvdHRvbWAgYW5kIGByaWdodGAgcHJvcGVydGllc1xuICAgIHZhciBpbnZlcnRUb3AgPSBzaWRlQSA9PT0gJ2JvdHRvbScgPyAtMSA6IDE7XG4gICAgdmFyIGludmVydExlZnQgPSBzaWRlQiA9PT0gJ3JpZ2h0JyA/IC0xIDogMTtcbiAgICBzdHlsZXNbc2lkZUFdID0gdG9wICogaW52ZXJ0VG9wO1xuICAgIHN0eWxlc1tzaWRlQl0gPSBsZWZ0ICogaW52ZXJ0TGVmdDtcbiAgICBzdHlsZXMud2lsbENoYW5nZSA9IHNpZGVBICsgJywgJyArIHNpZGVCO1xuICB9XG5cbiAgLy8gQXR0cmlidXRlc1xuICB2YXIgYXR0cmlidXRlcyA9IHtcbiAgICAneC1wbGFjZW1lbnQnOiBkYXRhLnBsYWNlbWVudFxuICB9O1xuXG4gIC8vIFVwZGF0ZSBgZGF0YWAgYXR0cmlidXRlcywgc3R5bGVzIGFuZCBhcnJvd1N0eWxlc1xuICBkYXRhLmF0dHJpYnV0ZXMgPSBfZXh0ZW5kcyh7fSwgYXR0cmlidXRlcywgZGF0YS5hdHRyaWJ1dGVzKTtcbiAgZGF0YS5zdHlsZXMgPSBfZXh0ZW5kcyh7fSwgc3R5bGVzLCBkYXRhLnN0eWxlcyk7XG4gIGRhdGEuYXJyb3dTdHlsZXMgPSBfZXh0ZW5kcyh7fSwgZGF0YS5vZmZzZXRzLmFycm93LCBkYXRhLmFycm93U3R5bGVzKTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBIZWxwZXIgdXNlZCB0byBrbm93IGlmIHRoZSBnaXZlbiBtb2RpZmllciBkZXBlbmRzIGZyb20gYW5vdGhlciBvbmUuPGJyIC8+XG4gKiBJdCBjaGVja3MgaWYgdGhlIG5lZWRlZCBtb2RpZmllciBpcyBsaXN0ZWQgYW5kIGVuYWJsZWQuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge0FycmF5fSBtb2RpZmllcnMgLSBsaXN0IG9mIG1vZGlmaWVyc1xuICogQHBhcmFtIHtTdHJpbmd9IHJlcXVlc3RpbmdOYW1lIC0gbmFtZSBvZiByZXF1ZXN0aW5nIG1vZGlmaWVyXG4gKiBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdGVkTmFtZSAtIG5hbWUgb2YgcmVxdWVzdGVkIG1vZGlmaWVyXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNNb2RpZmllclJlcXVpcmVkKG1vZGlmaWVycywgcmVxdWVzdGluZ05hbWUsIHJlcXVlc3RlZE5hbWUpIHtcbiAgdmFyIHJlcXVlc3RpbmcgPSBmaW5kKG1vZGlmaWVycywgZnVuY3Rpb24gKF9yZWYpIHtcbiAgICB2YXIgbmFtZSA9IF9yZWYubmFtZTtcbiAgICByZXR1cm4gbmFtZSA9PT0gcmVxdWVzdGluZ05hbWU7XG4gIH0pO1xuXG4gIHZhciBpc1JlcXVpcmVkID0gISFyZXF1ZXN0aW5nICYmIG1vZGlmaWVycy5zb21lKGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgIHJldHVybiBtb2RpZmllci5uYW1lID09PSByZXF1ZXN0ZWROYW1lICYmIG1vZGlmaWVyLmVuYWJsZWQgJiYgbW9kaWZpZXIub3JkZXIgPCByZXF1ZXN0aW5nLm9yZGVyO1xuICB9KTtcblxuICBpZiAoIWlzUmVxdWlyZWQpIHtcbiAgICB2YXIgX3JlcXVlc3RpbmcgPSAnYCcgKyByZXF1ZXN0aW5nTmFtZSArICdgJztcbiAgICB2YXIgcmVxdWVzdGVkID0gJ2AnICsgcmVxdWVzdGVkTmFtZSArICdgJztcbiAgICBjb25zb2xlLndhcm4ocmVxdWVzdGVkICsgJyBtb2RpZmllciBpcyByZXF1aXJlZCBieSAnICsgX3JlcXVlc3RpbmcgKyAnIG1vZGlmaWVyIGluIG9yZGVyIHRvIHdvcmssIGJlIHN1cmUgdG8gaW5jbHVkZSBpdCBiZWZvcmUgJyArIF9yZXF1ZXN0aW5nICsgJyEnKTtcbiAgfVxuICByZXR1cm4gaXNSZXF1aXJlZDtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGFycm93KGRhdGEsIG9wdGlvbnMpIHtcbiAgdmFyIF9kYXRhJG9mZnNldHMkYXJyb3c7XG5cbiAgLy8gYXJyb3cgZGVwZW5kcyBvbiBrZWVwVG9nZXRoZXIgaW4gb3JkZXIgdG8gd29ya1xuICBpZiAoIWlzTW9kaWZpZXJSZXF1aXJlZChkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgJ2Fycm93JywgJ2tlZXBUb2dldGhlcicpKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICB2YXIgYXJyb3dFbGVtZW50ID0gb3B0aW9ucy5lbGVtZW50O1xuXG4gIC8vIGlmIGFycm93RWxlbWVudCBpcyBhIHN0cmluZywgc3VwcG9zZSBpdCdzIGEgQ1NTIHNlbGVjdG9yXG4gIGlmICh0eXBlb2YgYXJyb3dFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgIGFycm93RWxlbWVudCA9IGRhdGEuaW5zdGFuY2UucG9wcGVyLnF1ZXJ5U2VsZWN0b3IoYXJyb3dFbGVtZW50KTtcblxuICAgIC8vIGlmIGFycm93RWxlbWVudCBpcyBub3QgZm91bmQsIGRvbid0IHJ1biB0aGUgbW9kaWZpZXJcbiAgICBpZiAoIWFycm93RWxlbWVudCkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIGlmIHRoZSBhcnJvd0VsZW1lbnQgaXNuJ3QgYSBxdWVyeSBzZWxlY3RvciB3ZSBtdXN0IGNoZWNrIHRoYXQgdGhlXG4gICAgLy8gcHJvdmlkZWQgRE9NIG5vZGUgaXMgY2hpbGQgb2YgaXRzIHBvcHBlciBub2RlXG4gICAgaWYgKCFkYXRhLmluc3RhbmNlLnBvcHBlci5jb250YWlucyhhcnJvd0VsZW1lbnQpKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1dBUk5JTkc6IGBhcnJvdy5lbGVtZW50YCBtdXN0IGJlIGNoaWxkIG9mIGl0cyBwb3BwZXIgZWxlbWVudCEnKTtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgfVxuXG4gIHZhciBwbGFjZW1lbnQgPSBkYXRhLnBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB2YXIgX2RhdGEkb2Zmc2V0cyA9IGRhdGEub2Zmc2V0cyxcbiAgICAgIHBvcHBlciA9IF9kYXRhJG9mZnNldHMucG9wcGVyLFxuICAgICAgcmVmZXJlbmNlID0gX2RhdGEkb2Zmc2V0cy5yZWZlcmVuY2U7XG5cbiAgdmFyIGlzVmVydGljYWwgPSBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xO1xuXG4gIHZhciBsZW4gPSBpc1ZlcnRpY2FsID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICB2YXIgc2lkZUNhcGl0YWxpemVkID0gaXNWZXJ0aWNhbCA/ICdUb3AnIDogJ0xlZnQnO1xuICB2YXIgc2lkZSA9IHNpZGVDYXBpdGFsaXplZC50b0xvd2VyQ2FzZSgpO1xuICB2YXIgYWx0U2lkZSA9IGlzVmVydGljYWwgPyAnbGVmdCcgOiAndG9wJztcbiAgdmFyIG9wU2lkZSA9IGlzVmVydGljYWwgPyAnYm90dG9tJyA6ICdyaWdodCc7XG4gIHZhciBhcnJvd0VsZW1lbnRTaXplID0gZ2V0T3V0ZXJTaXplcyhhcnJvd0VsZW1lbnQpW2xlbl07XG5cbiAgLy9cbiAgLy8gZXh0ZW5kcyBrZWVwVG9nZXRoZXIgYmVoYXZpb3IgbWFraW5nIHN1cmUgdGhlIHBvcHBlciBhbmQgaXRzXG4gIC8vIHJlZmVyZW5jZSBoYXZlIGVub3VnaCBwaXhlbHMgaW4gY29uanVuY3Rpb25cbiAgLy9cblxuICAvLyB0b3AvbGVmdCBzaWRlXG4gIGlmIChyZWZlcmVuY2Vbb3BTaWRlXSAtIGFycm93RWxlbWVudFNpemUgPCBwb3BwZXJbc2lkZV0pIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW3NpZGVdIC09IHBvcHBlcltzaWRlXSAtIChyZWZlcmVuY2Vbb3BTaWRlXSAtIGFycm93RWxlbWVudFNpemUpO1xuICB9XG4gIC8vIGJvdHRvbS9yaWdodCBzaWRlXG4gIGlmIChyZWZlcmVuY2Vbc2lkZV0gKyBhcnJvd0VsZW1lbnRTaXplID4gcG9wcGVyW29wU2lkZV0pIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW3NpZGVdICs9IHJlZmVyZW5jZVtzaWRlXSArIGFycm93RWxlbWVudFNpemUgLSBwb3BwZXJbb3BTaWRlXTtcbiAgfVxuICBkYXRhLm9mZnNldHMucG9wcGVyID0gZ2V0Q2xpZW50UmVjdChkYXRhLm9mZnNldHMucG9wcGVyKTtcblxuICAvLyBjb21wdXRlIGNlbnRlciBvZiB0aGUgcG9wcGVyXG4gIHZhciBjZW50ZXIgPSByZWZlcmVuY2Vbc2lkZV0gKyByZWZlcmVuY2VbbGVuXSAvIDIgLSBhcnJvd0VsZW1lbnRTaXplIC8gMjtcblxuICAvLyBDb21wdXRlIHRoZSBzaWRlVmFsdWUgdXNpbmcgdGhlIHVwZGF0ZWQgcG9wcGVyIG9mZnNldHNcbiAgLy8gdGFrZSBwb3BwZXIgbWFyZ2luIGluIGFjY291bnQgYmVjYXVzZSB3ZSBkb24ndCBoYXZlIHRoaXMgaW5mbyBhdmFpbGFibGVcbiAgdmFyIGNzcyA9IGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShkYXRhLmluc3RhbmNlLnBvcHBlcik7XG4gIHZhciBwb3BwZXJNYXJnaW5TaWRlID0gcGFyc2VGbG9hdChjc3NbJ21hcmdpbicgKyBzaWRlQ2FwaXRhbGl6ZWRdLCAxMCk7XG4gIHZhciBwb3BwZXJCb3JkZXJTaWRlID0gcGFyc2VGbG9hdChjc3NbJ2JvcmRlcicgKyBzaWRlQ2FwaXRhbGl6ZWQgKyAnV2lkdGgnXSwgMTApO1xuICB2YXIgc2lkZVZhbHVlID0gY2VudGVyIC0gZGF0YS5vZmZzZXRzLnBvcHBlcltzaWRlXSAtIHBvcHBlck1hcmdpblNpZGUgLSBwb3BwZXJCb3JkZXJTaWRlO1xuXG4gIC8vIHByZXZlbnQgYXJyb3dFbGVtZW50IGZyb20gYmVpbmcgcGxhY2VkIG5vdCBjb250aWd1b3VzbHkgdG8gaXRzIHBvcHBlclxuICBzaWRlVmFsdWUgPSBNYXRoLm1heChNYXRoLm1pbihwb3BwZXJbbGVuXSAtIGFycm93RWxlbWVudFNpemUsIHNpZGVWYWx1ZSksIDApO1xuXG4gIGRhdGEuYXJyb3dFbGVtZW50ID0gYXJyb3dFbGVtZW50O1xuICBkYXRhLm9mZnNldHMuYXJyb3cgPSAoX2RhdGEkb2Zmc2V0cyRhcnJvdyA9IHt9LCBkZWZpbmVQcm9wZXJ0eShfZGF0YSRvZmZzZXRzJGFycm93LCBzaWRlLCBNYXRoLnJvdW5kKHNpZGVWYWx1ZSkpLCBkZWZpbmVQcm9wZXJ0eShfZGF0YSRvZmZzZXRzJGFycm93LCBhbHRTaWRlLCAnJyksIF9kYXRhJG9mZnNldHMkYXJyb3cpO1xuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEdldCB0aGUgb3Bwb3NpdGUgcGxhY2VtZW50IHZhcmlhdGlvbiBvZiB0aGUgZ2l2ZW4gb25lXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge1N0cmluZ30gcGxhY2VtZW50IHZhcmlhdGlvblxuICogQHJldHVybnMge1N0cmluZ30gZmxpcHBlZCBwbGFjZW1lbnQgdmFyaWF0aW9uXG4gKi9cbmZ1bmN0aW9uIGdldE9wcG9zaXRlVmFyaWF0aW9uKHZhcmlhdGlvbikge1xuICBpZiAodmFyaWF0aW9uID09PSAnZW5kJykge1xuICAgIHJldHVybiAnc3RhcnQnO1xuICB9IGVsc2UgaWYgKHZhcmlhdGlvbiA9PT0gJ3N0YXJ0Jykge1xuICAgIHJldHVybiAnZW5kJztcbiAgfVxuICByZXR1cm4gdmFyaWF0aW9uO1xufVxuXG4vKipcbiAqIExpc3Qgb2YgYWNjZXB0ZWQgcGxhY2VtZW50cyB0byB1c2UgYXMgdmFsdWVzIG9mIHRoZSBgcGxhY2VtZW50YCBvcHRpb24uPGJyIC8+XG4gKiBWYWxpZCBwbGFjZW1lbnRzIGFyZTpcbiAqIC0gYGF1dG9gXG4gKiAtIGB0b3BgXG4gKiAtIGByaWdodGBcbiAqIC0gYGJvdHRvbWBcbiAqIC0gYGxlZnRgXG4gKlxuICogRWFjaCBwbGFjZW1lbnQgY2FuIGhhdmUgYSB2YXJpYXRpb24gZnJvbSB0aGlzIGxpc3Q6XG4gKiAtIGAtc3RhcnRgXG4gKiAtIGAtZW5kYFxuICpcbiAqIFZhcmlhdGlvbnMgYXJlIGludGVycHJldGVkIGVhc2lseSBpZiB5b3UgdGhpbmsgb2YgdGhlbSBhcyB0aGUgbGVmdCB0byByaWdodFxuICogd3JpdHRlbiBsYW5ndWFnZXMuIEhvcml6b250YWxseSAoYHRvcGAgYW5kIGBib3R0b21gKSwgYHN0YXJ0YCBpcyBsZWZ0IGFuZCBgZW5kYFxuICogaXMgcmlnaHQuPGJyIC8+XG4gKiBWZXJ0aWNhbGx5IChgbGVmdGAgYW5kIGByaWdodGApLCBgc3RhcnRgIGlzIHRvcCBhbmQgYGVuZGAgaXMgYm90dG9tLlxuICpcbiAqIFNvbWUgdmFsaWQgZXhhbXBsZXMgYXJlOlxuICogLSBgdG9wLWVuZGAgKG9uIHRvcCBvZiByZWZlcmVuY2UsIHJpZ2h0IGFsaWduZWQpXG4gKiAtIGByaWdodC1zdGFydGAgKG9uIHJpZ2h0IG9mIHJlZmVyZW5jZSwgdG9wIGFsaWduZWQpXG4gKiAtIGBib3R0b21gIChvbiBib3R0b20sIGNlbnRlcmVkKVxuICogLSBgYXV0by1lbmRgIChvbiB0aGUgc2lkZSB3aXRoIG1vcmUgc3BhY2UgYXZhaWxhYmxlLCBhbGlnbm1lbnQgZGVwZW5kcyBieSBwbGFjZW1lbnQpXG4gKlxuICogQHN0YXRpY1xuICogQHR5cGUge0FycmF5fVxuICogQGVudW0ge1N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1ldGhvZCBwbGFjZW1lbnRzXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbnZhciBwbGFjZW1lbnRzID0gWydhdXRvLXN0YXJ0JywgJ2F1dG8nLCAnYXV0by1lbmQnLCAndG9wLXN0YXJ0JywgJ3RvcCcsICd0b3AtZW5kJywgJ3JpZ2h0LXN0YXJ0JywgJ3JpZ2h0JywgJ3JpZ2h0LWVuZCcsICdib3R0b20tZW5kJywgJ2JvdHRvbScsICdib3R0b20tc3RhcnQnLCAnbGVmdC1lbmQnLCAnbGVmdCcsICdsZWZ0LXN0YXJ0J107XG5cbi8vIEdldCByaWQgb2YgYGF1dG9gIGBhdXRvLXN0YXJ0YCBhbmQgYGF1dG8tZW5kYFxudmFyIHZhbGlkUGxhY2VtZW50cyA9IHBsYWNlbWVudHMuc2xpY2UoMyk7XG5cbi8qKlxuICogR2l2ZW4gYW4gaW5pdGlhbCBwbGFjZW1lbnQsIHJldHVybnMgYWxsIHRoZSBzdWJzZXF1ZW50IHBsYWNlbWVudHNcbiAqIGNsb2Nrd2lzZSAob3IgY291bnRlci1jbG9ja3dpc2UpLlxuICpcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBwbGFjZW1lbnQgLSBBIHZhbGlkIHBsYWNlbWVudCAoaXQgYWNjZXB0cyB2YXJpYXRpb25zKVxuICogQGFyZ3VtZW50IHtCb29sZWFufSBjb3VudGVyIC0gU2V0IHRvIHRydWUgdG8gd2FsayB0aGUgcGxhY2VtZW50cyBjb3VudGVyY2xvY2t3aXNlXG4gKiBAcmV0dXJucyB7QXJyYXl9IHBsYWNlbWVudHMgaW5jbHVkaW5nIHRoZWlyIHZhcmlhdGlvbnNcbiAqL1xuZnVuY3Rpb24gY2xvY2t3aXNlKHBsYWNlbWVudCkge1xuICB2YXIgY291bnRlciA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7XG5cbiAgdmFyIGluZGV4ID0gdmFsaWRQbGFjZW1lbnRzLmluZGV4T2YocGxhY2VtZW50KTtcbiAgdmFyIGFyciA9IHZhbGlkUGxhY2VtZW50cy5zbGljZShpbmRleCArIDEpLmNvbmNhdCh2YWxpZFBsYWNlbWVudHMuc2xpY2UoMCwgaW5kZXgpKTtcbiAgcmV0dXJuIGNvdW50ZXIgPyBhcnIucmV2ZXJzZSgpIDogYXJyO1xufVxuXG52YXIgQkVIQVZJT1JTID0ge1xuICBGTElQOiAnZmxpcCcsXG4gIENMT0NLV0lTRTogJ2Nsb2Nrd2lzZScsXG4gIENPVU5URVJDTE9DS1dJU0U6ICdjb3VudGVyY2xvY2t3aXNlJ1xufTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGZsaXAoZGF0YSwgb3B0aW9ucykge1xuICAvLyBpZiBgaW5uZXJgIG1vZGlmaWVyIGlzIGVuYWJsZWQsIHdlIGNhbid0IHVzZSB0aGUgYGZsaXBgIG1vZGlmaWVyXG4gIGlmIChpc01vZGlmaWVyRW5hYmxlZChkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgJ2lubmVyJykpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIGlmIChkYXRhLmZsaXBwZWQgJiYgZGF0YS5wbGFjZW1lbnQgPT09IGRhdGEub3JpZ2luYWxQbGFjZW1lbnQpIHtcbiAgICAvLyBzZWVtcyBsaWtlIGZsaXAgaXMgdHJ5aW5nIHRvIGxvb3AsIHByb2JhYmx5IHRoZXJlJ3Mgbm90IGVub3VnaCBzcGFjZSBvbiBhbnkgb2YgdGhlIGZsaXBwYWJsZSBzaWRlc1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgdmFyIGJvdW5kYXJpZXMgPSBnZXRCb3VuZGFyaWVzKGRhdGEuaW5zdGFuY2UucG9wcGVyLCBkYXRhLmluc3RhbmNlLnJlZmVyZW5jZSwgb3B0aW9ucy5wYWRkaW5nLCBvcHRpb25zLmJvdW5kYXJpZXNFbGVtZW50LCBkYXRhLnBvc2l0aW9uRml4ZWQpO1xuXG4gIHZhciBwbGFjZW1lbnQgPSBkYXRhLnBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB2YXIgcGxhY2VtZW50T3Bwb3NpdGUgPSBnZXRPcHBvc2l0ZVBsYWNlbWVudChwbGFjZW1lbnQpO1xuICB2YXIgdmFyaWF0aW9uID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVsxXSB8fCAnJztcblxuICB2YXIgZmxpcE9yZGVyID0gW107XG5cbiAgc3dpdGNoIChvcHRpb25zLmJlaGF2aW9yKSB7XG4gICAgY2FzZSBCRUhBVklPUlMuRkxJUDpcbiAgICAgIGZsaXBPcmRlciA9IFtwbGFjZW1lbnQsIHBsYWNlbWVudE9wcG9zaXRlXTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQkVIQVZJT1JTLkNMT0NLV0lTRTpcbiAgICAgIGZsaXBPcmRlciA9IGNsb2Nrd2lzZShwbGFjZW1lbnQpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBCRUhBVklPUlMuQ09VTlRFUkNMT0NLV0lTRTpcbiAgICAgIGZsaXBPcmRlciA9IGNsb2Nrd2lzZShwbGFjZW1lbnQsIHRydWUpO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIGZsaXBPcmRlciA9IG9wdGlvbnMuYmVoYXZpb3I7XG4gIH1cblxuICBmbGlwT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAoc3RlcCwgaW5kZXgpIHtcbiAgICBpZiAocGxhY2VtZW50ICE9PSBzdGVwIHx8IGZsaXBPcmRlci5sZW5ndGggPT09IGluZGV4ICsgMSkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgICBwbGFjZW1lbnRPcHBvc2l0ZSA9IGdldE9wcG9zaXRlUGxhY2VtZW50KHBsYWNlbWVudCk7XG5cbiAgICB2YXIgcG9wcGVyT2Zmc2V0cyA9IGRhdGEub2Zmc2V0cy5wb3BwZXI7XG4gICAgdmFyIHJlZk9mZnNldHMgPSBkYXRhLm9mZnNldHMucmVmZXJlbmNlO1xuXG4gICAgLy8gdXNpbmcgZmxvb3IgYmVjYXVzZSB0aGUgcmVmZXJlbmNlIG9mZnNldHMgbWF5IGNvbnRhaW4gZGVjaW1hbHMgd2UgYXJlIG5vdCBnb2luZyB0byBjb25zaWRlciBoZXJlXG4gICAgdmFyIGZsb29yID0gTWF0aC5mbG9vcjtcbiAgICB2YXIgb3ZlcmxhcHNSZWYgPSBwbGFjZW1lbnQgPT09ICdsZWZ0JyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLnJpZ2h0KSA+IGZsb29yKHJlZk9mZnNldHMubGVmdCkgfHwgcGxhY2VtZW50ID09PSAncmlnaHQnICYmIGZsb29yKHBvcHBlck9mZnNldHMubGVmdCkgPCBmbG9vcihyZWZPZmZzZXRzLnJpZ2h0KSB8fCBwbGFjZW1lbnQgPT09ICd0b3AnICYmIGZsb29yKHBvcHBlck9mZnNldHMuYm90dG9tKSA+IGZsb29yKHJlZk9mZnNldHMudG9wKSB8fCBwbGFjZW1lbnQgPT09ICdib3R0b20nICYmIGZsb29yKHBvcHBlck9mZnNldHMudG9wKSA8IGZsb29yKHJlZk9mZnNldHMuYm90dG9tKTtcblxuICAgIHZhciBvdmVyZmxvd3NMZWZ0ID0gZmxvb3IocG9wcGVyT2Zmc2V0cy5sZWZ0KSA8IGZsb29yKGJvdW5kYXJpZXMubGVmdCk7XG4gICAgdmFyIG92ZXJmbG93c1JpZ2h0ID0gZmxvb3IocG9wcGVyT2Zmc2V0cy5yaWdodCkgPiBmbG9vcihib3VuZGFyaWVzLnJpZ2h0KTtcbiAgICB2YXIgb3ZlcmZsb3dzVG9wID0gZmxvb3IocG9wcGVyT2Zmc2V0cy50b3ApIDwgZmxvb3IoYm91bmRhcmllcy50b3ApO1xuICAgIHZhciBvdmVyZmxvd3NCb3R0b20gPSBmbG9vcihwb3BwZXJPZmZzZXRzLmJvdHRvbSkgPiBmbG9vcihib3VuZGFyaWVzLmJvdHRvbSk7XG5cbiAgICB2YXIgb3ZlcmZsb3dzQm91bmRhcmllcyA9IHBsYWNlbWVudCA9PT0gJ2xlZnQnICYmIG92ZXJmbG93c0xlZnQgfHwgcGxhY2VtZW50ID09PSAncmlnaHQnICYmIG92ZXJmbG93c1JpZ2h0IHx8IHBsYWNlbWVudCA9PT0gJ3RvcCcgJiYgb3ZlcmZsb3dzVG9wIHx8IHBsYWNlbWVudCA9PT0gJ2JvdHRvbScgJiYgb3ZlcmZsb3dzQm90dG9tO1xuXG4gICAgLy8gZmxpcCB0aGUgdmFyaWF0aW9uIGlmIHJlcXVpcmVkXG4gICAgdmFyIGlzVmVydGljYWwgPSBbJ3RvcCcsICdib3R0b20nXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xO1xuICAgIHZhciBmbGlwcGVkVmFyaWF0aW9uID0gISFvcHRpb25zLmZsaXBWYXJpYXRpb25zICYmIChpc1ZlcnRpY2FsICYmIHZhcmlhdGlvbiA9PT0gJ3N0YXJ0JyAmJiBvdmVyZmxvd3NMZWZ0IHx8IGlzVmVydGljYWwgJiYgdmFyaWF0aW9uID09PSAnZW5kJyAmJiBvdmVyZmxvd3NSaWdodCB8fCAhaXNWZXJ0aWNhbCAmJiB2YXJpYXRpb24gPT09ICdzdGFydCcgJiYgb3ZlcmZsb3dzVG9wIHx8ICFpc1ZlcnRpY2FsICYmIHZhcmlhdGlvbiA9PT0gJ2VuZCcgJiYgb3ZlcmZsb3dzQm90dG9tKTtcblxuICAgIGlmIChvdmVybGFwc1JlZiB8fCBvdmVyZmxvd3NCb3VuZGFyaWVzIHx8IGZsaXBwZWRWYXJpYXRpb24pIHtcbiAgICAgIC8vIHRoaXMgYm9vbGVhbiB0byBkZXRlY3QgYW55IGZsaXAgbG9vcFxuICAgICAgZGF0YS5mbGlwcGVkID0gdHJ1ZTtcblxuICAgICAgaWYgKG92ZXJsYXBzUmVmIHx8IG92ZXJmbG93c0JvdW5kYXJpZXMpIHtcbiAgICAgICAgcGxhY2VtZW50ID0gZmxpcE9yZGVyW2luZGV4ICsgMV07XG4gICAgICB9XG5cbiAgICAgIGlmIChmbGlwcGVkVmFyaWF0aW9uKSB7XG4gICAgICAgIHZhcmlhdGlvbiA9IGdldE9wcG9zaXRlVmFyaWF0aW9uKHZhcmlhdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGRhdGEucGxhY2VtZW50ID0gcGxhY2VtZW50ICsgKHZhcmlhdGlvbiA/ICctJyArIHZhcmlhdGlvbiA6ICcnKTtcblxuICAgICAgLy8gdGhpcyBvYmplY3QgY29udGFpbnMgYHBvc2l0aW9uYCwgd2Ugd2FudCB0byBwcmVzZXJ2ZSBpdCBhbG9uZyB3aXRoXG4gICAgICAvLyBhbnkgYWRkaXRpb25hbCBwcm9wZXJ0eSB3ZSBtYXkgYWRkIGluIHRoZSBmdXR1cmVcbiAgICAgIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBfZXh0ZW5kcyh7fSwgZGF0YS5vZmZzZXRzLnBvcHBlciwgZ2V0UG9wcGVyT2Zmc2V0cyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5vZmZzZXRzLnJlZmVyZW5jZSwgZGF0YS5wbGFjZW1lbnQpKTtcblxuICAgICAgZGF0YSA9IHJ1bk1vZGlmaWVycyhkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgZGF0YSwgJ2ZsaXAnKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGtlZXBUb2dldGhlcihkYXRhKSB7XG4gIHZhciBfZGF0YSRvZmZzZXRzID0gZGF0YS5vZmZzZXRzLFxuICAgICAgcG9wcGVyID0gX2RhdGEkb2Zmc2V0cy5wb3BwZXIsXG4gICAgICByZWZlcmVuY2UgPSBfZGF0YSRvZmZzZXRzLnJlZmVyZW5jZTtcblxuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgdmFyIGZsb29yID0gTWF0aC5mbG9vcjtcbiAgdmFyIGlzVmVydGljYWwgPSBbJ3RvcCcsICdib3R0b20nXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xO1xuICB2YXIgc2lkZSA9IGlzVmVydGljYWwgPyAncmlnaHQnIDogJ2JvdHRvbSc7XG4gIHZhciBvcFNpZGUgPSBpc1ZlcnRpY2FsID8gJ2xlZnQnIDogJ3RvcCc7XG4gIHZhciBtZWFzdXJlbWVudCA9IGlzVmVydGljYWwgPyAnd2lkdGgnIDogJ2hlaWdodCc7XG5cbiAgaWYgKHBvcHBlcltzaWRlXSA8IGZsb29yKHJlZmVyZW5jZVtvcFNpZGVdKSkge1xuICAgIGRhdGEub2Zmc2V0cy5wb3BwZXJbb3BTaWRlXSA9IGZsb29yKHJlZmVyZW5jZVtvcFNpZGVdKSAtIHBvcHBlclttZWFzdXJlbWVudF07XG4gIH1cbiAgaWYgKHBvcHBlcltvcFNpZGVdID4gZmxvb3IocmVmZXJlbmNlW3NpZGVdKSkge1xuICAgIGRhdGEub2Zmc2V0cy5wb3BwZXJbb3BTaWRlXSA9IGZsb29yKHJlZmVyZW5jZVtzaWRlXSk7XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHN0cmluZyBjb250YWluaW5nIHZhbHVlICsgdW5pdCBpbnRvIGEgcHggdmFsdWUgbnVtYmVyXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiB7bW9kaWZpZXJzfm9mZnNldH1cbiAqIEBwcml2YXRlXG4gKiBAYXJndW1lbnQge1N0cmluZ30gc3RyIC0gVmFsdWUgKyB1bml0IHN0cmluZ1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IG1lYXN1cmVtZW50IC0gYGhlaWdodGAgb3IgYHdpZHRoYFxuICogQGFyZ3VtZW50IHtPYmplY3R9IHBvcHBlck9mZnNldHNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSByZWZlcmVuY2VPZmZzZXRzXG4gKiBAcmV0dXJucyB7TnVtYmVyfFN0cmluZ31cbiAqIFZhbHVlIGluIHBpeGVscywgb3Igb3JpZ2luYWwgc3RyaW5nIGlmIG5vIHZhbHVlcyB3ZXJlIGV4dHJhY3RlZFxuICovXG5mdW5jdGlvbiB0b1ZhbHVlKHN0ciwgbWVhc3VyZW1lbnQsIHBvcHBlck9mZnNldHMsIHJlZmVyZW5jZU9mZnNldHMpIHtcbiAgLy8gc2VwYXJhdGUgdmFsdWUgZnJvbSB1bml0XG4gIHZhciBzcGxpdCA9IHN0ci5tYXRjaCgvKCg/OlxcLXxcXCspP1xcZCpcXC4/XFxkKikoLiopLyk7XG4gIHZhciB2YWx1ZSA9ICtzcGxpdFsxXTtcbiAgdmFyIHVuaXQgPSBzcGxpdFsyXTtcblxuICAvLyBJZiBpdCdzIG5vdCBhIG51bWJlciBpdCdzIGFuIG9wZXJhdG9yLCBJIGd1ZXNzXG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gc3RyO1xuICB9XG5cbiAgaWYgKHVuaXQuaW5kZXhPZignJScpID09PSAwKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB2b2lkIDA7XG4gICAgc3dpdGNoICh1bml0KSB7XG4gICAgICBjYXNlICclcCc6XG4gICAgICAgIGVsZW1lbnQgPSBwb3BwZXJPZmZzZXRzO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyUnOlxuICAgICAgY2FzZSAnJXInOlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgZWxlbWVudCA9IHJlZmVyZW5jZU9mZnNldHM7XG4gICAgfVxuXG4gICAgdmFyIHJlY3QgPSBnZXRDbGllbnRSZWN0KGVsZW1lbnQpO1xuICAgIHJldHVybiByZWN0W21lYXN1cmVtZW50XSAvIDEwMCAqIHZhbHVlO1xuICB9IGVsc2UgaWYgKHVuaXQgPT09ICd2aCcgfHwgdW5pdCA9PT0gJ3Z3Jykge1xuICAgIC8vIGlmIGlzIGEgdmggb3IgdncsIHdlIGNhbGN1bGF0ZSB0aGUgc2l6ZSBiYXNlZCBvbiB0aGUgdmlld3BvcnRcbiAgICB2YXIgc2l6ZSA9IHZvaWQgMDtcbiAgICBpZiAodW5pdCA9PT0gJ3ZoJykge1xuICAgICAgc2l6ZSA9IE1hdGgubWF4KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQsIHdpbmRvdy5pbm5lckhlaWdodCB8fCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2l6ZSA9IE1hdGgubWF4KGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCwgd2luZG93LmlubmVyV2lkdGggfHwgMCk7XG4gICAgfVxuICAgIHJldHVybiBzaXplIC8gMTAwICogdmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgLy8gaWYgaXMgYW4gZXhwbGljaXQgcGl4ZWwgdW5pdCwgd2UgZ2V0IHJpZCBvZiB0aGUgdW5pdCBhbmQga2VlcCB0aGUgdmFsdWVcbiAgICAvLyBpZiBpcyBhbiBpbXBsaWNpdCB1bml0LCBpdCdzIHB4LCBhbmQgd2UgcmV0dXJuIGp1c3QgdGhlIHZhbHVlXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG59XG5cbi8qKlxuICogUGFyc2UgYW4gYG9mZnNldGAgc3RyaW5nIHRvIGV4dHJhcG9sYXRlIGB4YCBhbmQgYHlgIG51bWVyaWMgb2Zmc2V0cy5cbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIHttb2RpZmllcnN+b2Zmc2V0fVxuICogQHByaXZhdGVcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBvZmZzZXRcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBwb3BwZXJPZmZzZXRzXG4gKiBAYXJndW1lbnQge09iamVjdH0gcmVmZXJlbmNlT2Zmc2V0c1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IGJhc2VQbGFjZW1lbnRcbiAqIEByZXR1cm5zIHtBcnJheX0gYSB0d28gY2VsbHMgYXJyYXkgd2l0aCB4IGFuZCB5IG9mZnNldHMgaW4gbnVtYmVyc1xuICovXG5mdW5jdGlvbiBwYXJzZU9mZnNldChvZmZzZXQsIHBvcHBlck9mZnNldHMsIHJlZmVyZW5jZU9mZnNldHMsIGJhc2VQbGFjZW1lbnQpIHtcbiAgdmFyIG9mZnNldHMgPSBbMCwgMF07XG5cbiAgLy8gVXNlIGhlaWdodCBpZiBwbGFjZW1lbnQgaXMgbGVmdCBvciByaWdodCBhbmQgaW5kZXggaXMgMCBvdGhlcndpc2UgdXNlIHdpZHRoXG4gIC8vIGluIHRoaXMgd2F5IHRoZSBmaXJzdCBvZmZzZXQgd2lsbCB1c2UgYW4gYXhpcyBhbmQgdGhlIHNlY29uZCBvbmVcbiAgLy8gd2lsbCB1c2UgdGhlIG90aGVyIG9uZVxuICB2YXIgdXNlSGVpZ2h0ID0gWydyaWdodCcsICdsZWZ0J10uaW5kZXhPZihiYXNlUGxhY2VtZW50KSAhPT0gLTE7XG5cbiAgLy8gU3BsaXQgdGhlIG9mZnNldCBzdHJpbmcgdG8gb2J0YWluIGEgbGlzdCBvZiB2YWx1ZXMgYW5kIG9wZXJhbmRzXG4gIC8vIFRoZSByZWdleCBhZGRyZXNzZXMgdmFsdWVzIHdpdGggdGhlIHBsdXMgb3IgbWludXMgc2lnbiBpbiBmcm9udCAoKzEwLCAtMjAsIGV0YylcbiAgdmFyIGZyYWdtZW50cyA9IG9mZnNldC5zcGxpdCgvKFxcK3xcXC0pLykubWFwKGZ1bmN0aW9uIChmcmFnKSB7XG4gICAgcmV0dXJuIGZyYWcudHJpbSgpO1xuICB9KTtcblxuICAvLyBEZXRlY3QgaWYgdGhlIG9mZnNldCBzdHJpbmcgY29udGFpbnMgYSBwYWlyIG9mIHZhbHVlcyBvciBhIHNpbmdsZSBvbmVcbiAgLy8gdGhleSBjb3VsZCBiZSBzZXBhcmF0ZWQgYnkgY29tbWEgb3Igc3BhY2VcbiAgdmFyIGRpdmlkZXIgPSBmcmFnbWVudHMuaW5kZXhPZihmaW5kKGZyYWdtZW50cywgZnVuY3Rpb24gKGZyYWcpIHtcbiAgICByZXR1cm4gZnJhZy5zZWFyY2goLyx8XFxzLykgIT09IC0xO1xuICB9KSk7XG5cbiAgaWYgKGZyYWdtZW50c1tkaXZpZGVyXSAmJiBmcmFnbWVudHNbZGl2aWRlcl0uaW5kZXhPZignLCcpID09PSAtMSkge1xuICAgIGNvbnNvbGUud2FybignT2Zmc2V0cyBzZXBhcmF0ZWQgYnkgd2hpdGUgc3BhY2UocykgYXJlIGRlcHJlY2F0ZWQsIHVzZSBhIGNvbW1hICgsKSBpbnN0ZWFkLicpO1xuICB9XG5cbiAgLy8gSWYgZGl2aWRlciBpcyBmb3VuZCwgd2UgZGl2aWRlIHRoZSBsaXN0IG9mIHZhbHVlcyBhbmQgb3BlcmFuZHMgdG8gZGl2aWRlXG4gIC8vIHRoZW0gYnkgb2ZzZXQgWCBhbmQgWS5cbiAgdmFyIHNwbGl0UmVnZXggPSAvXFxzKixcXHMqfFxccysvO1xuICB2YXIgb3BzID0gZGl2aWRlciAhPT0gLTEgPyBbZnJhZ21lbnRzLnNsaWNlKDAsIGRpdmlkZXIpLmNvbmNhdChbZnJhZ21lbnRzW2RpdmlkZXJdLnNwbGl0KHNwbGl0UmVnZXgpWzBdXSksIFtmcmFnbWVudHNbZGl2aWRlcl0uc3BsaXQoc3BsaXRSZWdleClbMV1dLmNvbmNhdChmcmFnbWVudHMuc2xpY2UoZGl2aWRlciArIDEpKV0gOiBbZnJhZ21lbnRzXTtcblxuICAvLyBDb252ZXJ0IHRoZSB2YWx1ZXMgd2l0aCB1bml0cyB0byBhYnNvbHV0ZSBwaXhlbHMgdG8gYWxsb3cgb3VyIGNvbXB1dGF0aW9uc1xuICBvcHMgPSBvcHMubWFwKGZ1bmN0aW9uIChvcCwgaW5kZXgpIHtcbiAgICAvLyBNb3N0IG9mIHRoZSB1bml0cyByZWx5IG9uIHRoZSBvcmllbnRhdGlvbiBvZiB0aGUgcG9wcGVyXG4gICAgdmFyIG1lYXN1cmVtZW50ID0gKGluZGV4ID09PSAxID8gIXVzZUhlaWdodCA6IHVzZUhlaWdodCkgPyAnaGVpZ2h0JyA6ICd3aWR0aCc7XG4gICAgdmFyIG1lcmdlV2l0aFByZXZpb3VzID0gZmFsc2U7XG4gICAgcmV0dXJuIG9wXG4gICAgLy8gVGhpcyBhZ2dyZWdhdGVzIGFueSBgK2Agb3IgYC1gIHNpZ24gdGhhdCBhcmVuJ3QgY29uc2lkZXJlZCBvcGVyYXRvcnNcbiAgICAvLyBlLmcuOiAxMCArICs1ID0+IFsxMCwgKywgKzVdXG4gICAgLnJlZHVjZShmdW5jdGlvbiAoYSwgYikge1xuICAgICAgaWYgKGFbYS5sZW5ndGggLSAxXSA9PT0gJycgJiYgWycrJywgJy0nXS5pbmRleE9mKGIpICE9PSAtMSkge1xuICAgICAgICBhW2EubGVuZ3RoIC0gMV0gPSBiO1xuICAgICAgICBtZXJnZVdpdGhQcmV2aW91cyA9IHRydWU7XG4gICAgICAgIHJldHVybiBhO1xuICAgICAgfSBlbHNlIGlmIChtZXJnZVdpdGhQcmV2aW91cykge1xuICAgICAgICBhW2EubGVuZ3RoIC0gMV0gKz0gYjtcbiAgICAgICAgbWVyZ2VXaXRoUHJldmlvdXMgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYS5jb25jYXQoYik7XG4gICAgICB9XG4gICAgfSwgW10pXG4gICAgLy8gSGVyZSB3ZSBjb252ZXJ0IHRoZSBzdHJpbmcgdmFsdWVzIGludG8gbnVtYmVyIHZhbHVlcyAoaW4gcHgpXG4gICAgLm1hcChmdW5jdGlvbiAoc3RyKSB7XG4gICAgICByZXR1cm4gdG9WYWx1ZShzdHIsIG1lYXN1cmVtZW50LCBwb3BwZXJPZmZzZXRzLCByZWZlcmVuY2VPZmZzZXRzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gTG9vcCB0cm91Z2ggdGhlIG9mZnNldHMgYXJyYXlzIGFuZCBleGVjdXRlIHRoZSBvcGVyYXRpb25zXG4gIG9wcy5mb3JFYWNoKGZ1bmN0aW9uIChvcCwgaW5kZXgpIHtcbiAgICBvcC5mb3JFYWNoKGZ1bmN0aW9uIChmcmFnLCBpbmRleDIpIHtcbiAgICAgIGlmIChpc051bWVyaWMoZnJhZykpIHtcbiAgICAgICAgb2Zmc2V0c1tpbmRleF0gKz0gZnJhZyAqIChvcFtpbmRleDIgLSAxXSA9PT0gJy0nID8gLTEgOiAxKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBvZmZzZXRzO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IHVwZGF0ZSBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEBhcmd1bWVudCB7TnVtYmVyfFN0cmluZ30gb3B0aW9ucy5vZmZzZXQ9MFxuICogVGhlIG9mZnNldCB2YWx1ZSBhcyBkZXNjcmliZWQgaW4gdGhlIG1vZGlmaWVyIGRlc2NyaXB0aW9uXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIG9mZnNldChkYXRhLCBfcmVmKSB7XG4gIHZhciBvZmZzZXQgPSBfcmVmLm9mZnNldDtcbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LFxuICAgICAgX2RhdGEkb2Zmc2V0cyA9IGRhdGEub2Zmc2V0cyxcbiAgICAgIHBvcHBlciA9IF9kYXRhJG9mZnNldHMucG9wcGVyLFxuICAgICAgcmVmZXJlbmNlID0gX2RhdGEkb2Zmc2V0cy5yZWZlcmVuY2U7XG5cbiAgdmFyIGJhc2VQbGFjZW1lbnQgPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcblxuICB2YXIgb2Zmc2V0cyA9IHZvaWQgMDtcbiAgaWYgKGlzTnVtZXJpYygrb2Zmc2V0KSkge1xuICAgIG9mZnNldHMgPSBbK29mZnNldCwgMF07XG4gIH0gZWxzZSB7XG4gICAgb2Zmc2V0cyA9IHBhcnNlT2Zmc2V0KG9mZnNldCwgcG9wcGVyLCByZWZlcmVuY2UsIGJhc2VQbGFjZW1lbnQpO1xuICB9XG5cbiAgaWYgKGJhc2VQbGFjZW1lbnQgPT09ICdsZWZ0Jykge1xuICAgIHBvcHBlci50b3AgKz0gb2Zmc2V0c1swXTtcbiAgICBwb3BwZXIubGVmdCAtPSBvZmZzZXRzWzFdO1xuICB9IGVsc2UgaWYgKGJhc2VQbGFjZW1lbnQgPT09ICdyaWdodCcpIHtcbiAgICBwb3BwZXIudG9wICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLmxlZnQgKz0gb2Zmc2V0c1sxXTtcbiAgfSBlbHNlIGlmIChiYXNlUGxhY2VtZW50ID09PSAndG9wJykge1xuICAgIHBvcHBlci5sZWZ0ICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLnRvcCAtPSBvZmZzZXRzWzFdO1xuICB9IGVsc2UgaWYgKGJhc2VQbGFjZW1lbnQgPT09ICdib3R0b20nKSB7XG4gICAgcG9wcGVyLmxlZnQgKz0gb2Zmc2V0c1swXTtcbiAgICBwb3BwZXIudG9wICs9IG9mZnNldHNbMV07XG4gIH1cblxuICBkYXRhLnBvcHBlciA9IHBvcHBlcjtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIHByZXZlbnRPdmVyZmxvdyhkYXRhLCBvcHRpb25zKSB7XG4gIHZhciBib3VuZGFyaWVzRWxlbWVudCA9IG9wdGlvbnMuYm91bmRhcmllc0VsZW1lbnQgfHwgZ2V0T2Zmc2V0UGFyZW50KGRhdGEuaW5zdGFuY2UucG9wcGVyKTtcblxuICAvLyBJZiBvZmZzZXRQYXJlbnQgaXMgdGhlIHJlZmVyZW5jZSBlbGVtZW50LCB3ZSByZWFsbHkgd2FudCB0b1xuICAvLyBnbyBvbmUgc3RlcCB1cCBhbmQgdXNlIHRoZSBuZXh0IG9mZnNldFBhcmVudCBhcyByZWZlcmVuY2UgdG9cbiAgLy8gYXZvaWQgdG8gbWFrZSB0aGlzIG1vZGlmaWVyIGNvbXBsZXRlbHkgdXNlbGVzcyBhbmQgbG9vayBsaWtlIGJyb2tlblxuICBpZiAoZGF0YS5pbnN0YW5jZS5yZWZlcmVuY2UgPT09IGJvdW5kYXJpZXNFbGVtZW50KSB7XG4gICAgYm91bmRhcmllc0VsZW1lbnQgPSBnZXRPZmZzZXRQYXJlbnQoYm91bmRhcmllc0VsZW1lbnQpO1xuICB9XG5cbiAgLy8gTk9URTogRE9NIGFjY2VzcyBoZXJlXG4gIC8vIHJlc2V0cyB0aGUgcG9wcGVyJ3MgcG9zaXRpb24gc28gdGhhdCB0aGUgZG9jdW1lbnQgc2l6ZSBjYW4gYmUgY2FsY3VsYXRlZCBleGNsdWRpbmdcbiAgLy8gdGhlIHNpemUgb2YgdGhlIHBvcHBlciBlbGVtZW50IGl0c2VsZlxuICB2YXIgdHJhbnNmb3JtUHJvcCA9IGdldFN1cHBvcnRlZFByb3BlcnR5TmFtZSgndHJhbnNmb3JtJyk7XG4gIHZhciBwb3BwZXJTdHlsZXMgPSBkYXRhLmluc3RhbmNlLnBvcHBlci5zdHlsZTsgLy8gYXNzaWdubWVudCB0byBoZWxwIG1pbmlmaWNhdGlvblxuICB2YXIgdG9wID0gcG9wcGVyU3R5bGVzLnRvcCxcbiAgICAgIGxlZnQgPSBwb3BwZXJTdHlsZXMubGVmdCxcbiAgICAgIHRyYW5zZm9ybSA9IHBvcHBlclN0eWxlc1t0cmFuc2Zvcm1Qcm9wXTtcblxuICBwb3BwZXJTdHlsZXMudG9wID0gJyc7XG4gIHBvcHBlclN0eWxlcy5sZWZ0ID0gJyc7XG4gIHBvcHBlclN0eWxlc1t0cmFuc2Zvcm1Qcm9wXSA9ICcnO1xuXG4gIHZhciBib3VuZGFyaWVzID0gZ2V0Qm91bmRhcmllcyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5pbnN0YW5jZS5yZWZlcmVuY2UsIG9wdGlvbnMucGFkZGluZywgYm91bmRhcmllc0VsZW1lbnQsIGRhdGEucG9zaXRpb25GaXhlZCk7XG5cbiAgLy8gTk9URTogRE9NIGFjY2VzcyBoZXJlXG4gIC8vIHJlc3RvcmVzIHRoZSBvcmlnaW5hbCBzdHlsZSBwcm9wZXJ0aWVzIGFmdGVyIHRoZSBvZmZzZXRzIGhhdmUgYmVlbiBjb21wdXRlZFxuICBwb3BwZXJTdHlsZXMudG9wID0gdG9wO1xuICBwb3BwZXJTdHlsZXMubGVmdCA9IGxlZnQ7XG4gIHBvcHBlclN0eWxlc1t0cmFuc2Zvcm1Qcm9wXSA9IHRyYW5zZm9ybTtcblxuICBvcHRpb25zLmJvdW5kYXJpZXMgPSBib3VuZGFyaWVzO1xuXG4gIHZhciBvcmRlciA9IG9wdGlvbnMucHJpb3JpdHk7XG4gIHZhciBwb3BwZXIgPSBkYXRhLm9mZnNldHMucG9wcGVyO1xuXG4gIHZhciBjaGVjayA9IHtcbiAgICBwcmltYXJ5OiBmdW5jdGlvbiBwcmltYXJ5KHBsYWNlbWVudCkge1xuICAgICAgdmFyIHZhbHVlID0gcG9wcGVyW3BsYWNlbWVudF07XG4gICAgICBpZiAocG9wcGVyW3BsYWNlbWVudF0gPCBib3VuZGFyaWVzW3BsYWNlbWVudF0gJiYgIW9wdGlvbnMuZXNjYXBlV2l0aFJlZmVyZW5jZSkge1xuICAgICAgICB2YWx1ZSA9IE1hdGgubWF4KHBvcHBlcltwbGFjZW1lbnRdLCBib3VuZGFyaWVzW3BsYWNlbWVudF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KHt9LCBwbGFjZW1lbnQsIHZhbHVlKTtcbiAgICB9LFxuICAgIHNlY29uZGFyeTogZnVuY3Rpb24gc2Vjb25kYXJ5KHBsYWNlbWVudCkge1xuICAgICAgdmFyIG1haW5TaWRlID0gcGxhY2VtZW50ID09PSAncmlnaHQnID8gJ2xlZnQnIDogJ3RvcCc7XG4gICAgICB2YXIgdmFsdWUgPSBwb3BwZXJbbWFpblNpZGVdO1xuICAgICAgaWYgKHBvcHBlcltwbGFjZW1lbnRdID4gYm91bmRhcmllc1twbGFjZW1lbnRdICYmICFvcHRpb25zLmVzY2FwZVdpdGhSZWZlcmVuY2UpIHtcbiAgICAgICAgdmFsdWUgPSBNYXRoLm1pbihwb3BwZXJbbWFpblNpZGVdLCBib3VuZGFyaWVzW3BsYWNlbWVudF0gLSAocGxhY2VtZW50ID09PSAncmlnaHQnID8gcG9wcGVyLndpZHRoIDogcG9wcGVyLmhlaWdodCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KHt9LCBtYWluU2lkZSwgdmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICBvcmRlci5mb3JFYWNoKGZ1bmN0aW9uIChwbGFjZW1lbnQpIHtcbiAgICB2YXIgc2lkZSA9IFsnbGVmdCcsICd0b3AnXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xID8gJ3ByaW1hcnknIDogJ3NlY29uZGFyeSc7XG4gICAgcG9wcGVyID0gX2V4dGVuZHMoe30sIHBvcHBlciwgY2hlY2tbc2lkZV0ocGxhY2VtZW50KSk7XG4gIH0pO1xuXG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBwb3BwZXI7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIHNoaWZ0KGRhdGEpIHtcbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50O1xuICB2YXIgYmFzZVBsYWNlbWVudCA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB2YXIgc2hpZnR2YXJpYXRpb24gPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVsxXTtcblxuICAvLyBpZiBzaGlmdCBzaGlmdHZhcmlhdGlvbiBpcyBzcGVjaWZpZWQsIHJ1biB0aGUgbW9kaWZpZXJcbiAgaWYgKHNoaWZ0dmFyaWF0aW9uKSB7XG4gICAgdmFyIF9kYXRhJG9mZnNldHMgPSBkYXRhLm9mZnNldHMsXG4gICAgICAgIHJlZmVyZW5jZSA9IF9kYXRhJG9mZnNldHMucmVmZXJlbmNlLFxuICAgICAgICBwb3BwZXIgPSBfZGF0YSRvZmZzZXRzLnBvcHBlcjtcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWydib3R0b20nLCAndG9wJ10uaW5kZXhPZihiYXNlUGxhY2VtZW50KSAhPT0gLTE7XG4gICAgdmFyIHNpZGUgPSBpc1ZlcnRpY2FsID8gJ2xlZnQnIDogJ3RvcCc7XG4gICAgdmFyIG1lYXN1cmVtZW50ID0gaXNWZXJ0aWNhbCA/ICd3aWR0aCcgOiAnaGVpZ2h0JztcblxuICAgIHZhciBzaGlmdE9mZnNldHMgPSB7XG4gICAgICBzdGFydDogZGVmaW5lUHJvcGVydHkoe30sIHNpZGUsIHJlZmVyZW5jZVtzaWRlXSksXG4gICAgICBlbmQ6IGRlZmluZVByb3BlcnR5KHt9LCBzaWRlLCByZWZlcmVuY2Vbc2lkZV0gKyByZWZlcmVuY2VbbWVhc3VyZW1lbnRdIC0gcG9wcGVyW21lYXN1cmVtZW50XSlcbiAgICB9O1xuXG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IF9leHRlbmRzKHt9LCBwb3BwZXIsIHNoaWZ0T2Zmc2V0c1tzaGlmdHZhcmlhdGlvbl0pO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBoaWRlKGRhdGEpIHtcbiAgaWYgKCFpc01vZGlmaWVyUmVxdWlyZWQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsICdoaWRlJywgJ3ByZXZlbnRPdmVyZmxvdycpKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICB2YXIgcmVmUmVjdCA9IGRhdGEub2Zmc2V0cy5yZWZlcmVuY2U7XG4gIHZhciBib3VuZCA9IGZpbmQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsIGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgIHJldHVybiBtb2RpZmllci5uYW1lID09PSAncHJldmVudE92ZXJmbG93JztcbiAgfSkuYm91bmRhcmllcztcblxuICBpZiAocmVmUmVjdC5ib3R0b20gPCBib3VuZC50b3AgfHwgcmVmUmVjdC5sZWZ0ID4gYm91bmQucmlnaHQgfHwgcmVmUmVjdC50b3AgPiBib3VuZC5ib3R0b20gfHwgcmVmUmVjdC5yaWdodCA8IGJvdW5kLmxlZnQpIHtcbiAgICAvLyBBdm9pZCB1bm5lY2Vzc2FyeSBET00gYWNjZXNzIGlmIHZpc2liaWxpdHkgaGFzbid0IGNoYW5nZWRcbiAgICBpZiAoZGF0YS5oaWRlID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICBkYXRhLmhpZGUgPSB0cnVlO1xuICAgIGRhdGEuYXR0cmlidXRlc1sneC1vdXQtb2YtYm91bmRhcmllcyddID0gJyc7XG4gIH0gZWxzZSB7XG4gICAgLy8gQXZvaWQgdW5uZWNlc3NhcnkgRE9NIGFjY2VzcyBpZiB2aXNpYmlsaXR5IGhhc24ndCBjaGFuZ2VkXG4gICAgaWYgKGRhdGEuaGlkZSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIGRhdGEuaGlkZSA9IGZhbHNlO1xuICAgIGRhdGEuYXR0cmlidXRlc1sneC1vdXQtb2YtYm91bmRhcmllcyddID0gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gaW5uZXIoZGF0YSkge1xuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQ7XG4gIHZhciBiYXNlUGxhY2VtZW50ID0gcGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gIHZhciBfZGF0YSRvZmZzZXRzID0gZGF0YS5vZmZzZXRzLFxuICAgICAgcG9wcGVyID0gX2RhdGEkb2Zmc2V0cy5wb3BwZXIsXG4gICAgICByZWZlcmVuY2UgPSBfZGF0YSRvZmZzZXRzLnJlZmVyZW5jZTtcblxuICB2YXIgaXNIb3JpeiA9IFsnbGVmdCcsICdyaWdodCddLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgIT09IC0xO1xuXG4gIHZhciBzdWJ0cmFjdExlbmd0aCA9IFsndG9wJywgJ2xlZnQnXS5pbmRleE9mKGJhc2VQbGFjZW1lbnQpID09PSAtMTtcblxuICBwb3BwZXJbaXNIb3JpeiA/ICdsZWZ0JyA6ICd0b3AnXSA9IHJlZmVyZW5jZVtiYXNlUGxhY2VtZW50XSAtIChzdWJ0cmFjdExlbmd0aCA/IHBvcHBlcltpc0hvcml6ID8gJ3dpZHRoJyA6ICdoZWlnaHQnXSA6IDApO1xuXG4gIGRhdGEucGxhY2VtZW50ID0gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocGxhY2VtZW50KTtcbiAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldENsaWVudFJlY3QocG9wcGVyKTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBNb2RpZmllciBmdW5jdGlvbiwgZWFjaCBtb2RpZmllciBjYW4gaGF2ZSBhIGZ1bmN0aW9uIG9mIHRoaXMgdHlwZSBhc3NpZ25lZFxuICogdG8gaXRzIGBmbmAgcHJvcGVydHkuPGJyIC8+XG4gKiBUaGVzZSBmdW5jdGlvbnMgd2lsbCBiZSBjYWxsZWQgb24gZWFjaCB1cGRhdGUsIHRoaXMgbWVhbnMgdGhhdCB5b3UgbXVzdFxuICogbWFrZSBzdXJlIHRoZXkgYXJlIHBlcmZvcm1hbnQgZW5vdWdoIHRvIGF2b2lkIHBlcmZvcm1hbmNlIGJvdHRsZW5lY2tzLlxuICpcbiAqIEBmdW5jdGlvbiBNb2RpZmllckZuXG4gKiBAYXJndW1lbnQge2RhdGFPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge2RhdGFPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuXG4vKipcbiAqIE1vZGlmaWVycyBhcmUgcGx1Z2lucyB1c2VkIHRvIGFsdGVyIHRoZSBiZWhhdmlvciBvZiB5b3VyIHBvcHBlcnMuPGJyIC8+XG4gKiBQb3BwZXIuanMgdXNlcyBhIHNldCBvZiA5IG1vZGlmaWVycyB0byBwcm92aWRlIGFsbCB0aGUgYmFzaWMgZnVuY3Rpb25hbGl0aWVzXG4gKiBuZWVkZWQgYnkgdGhlIGxpYnJhcnkuXG4gKlxuICogVXN1YWxseSB5b3UgZG9uJ3Qgd2FudCB0byBvdmVycmlkZSB0aGUgYG9yZGVyYCwgYGZuYCBhbmQgYG9uTG9hZGAgcHJvcHMuXG4gKiBBbGwgdGhlIG90aGVyIHByb3BlcnRpZXMgYXJlIGNvbmZpZ3VyYXRpb25zIHRoYXQgY291bGQgYmUgdHdlYWtlZC5cbiAqIEBuYW1lc3BhY2UgbW9kaWZpZXJzXG4gKi9cbnZhciBtb2RpZmllcnMgPSB7XG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIHNoaWZ0IHRoZSBwb3BwZXIgb24gdGhlIHN0YXJ0IG9yIGVuZCBvZiBpdHMgcmVmZXJlbmNlXG4gICAqIGVsZW1lbnQuPGJyIC8+XG4gICAqIEl0IHdpbGwgcmVhZCB0aGUgdmFyaWF0aW9uIG9mIHRoZSBgcGxhY2VtZW50YCBwcm9wZXJ0eS48YnIgLz5cbiAgICogSXQgY2FuIGJlIG9uZSBlaXRoZXIgYC1lbmRgIG9yIGAtc3RhcnRgLlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgc2hpZnQ6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9MTAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiAxMDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBzaGlmdFxuICB9LFxuXG4gIC8qKlxuICAgKiBUaGUgYG9mZnNldGAgbW9kaWZpZXIgY2FuIHNoaWZ0IHlvdXIgcG9wcGVyIG9uIGJvdGggaXRzIGF4aXMuXG4gICAqXG4gICAqIEl0IGFjY2VwdHMgdGhlIGZvbGxvd2luZyB1bml0czpcbiAgICogLSBgcHhgIG9yIHVuaXQtbGVzcywgaW50ZXJwcmV0ZWQgYXMgcGl4ZWxzXG4gICAqIC0gYCVgIG9yIGAlcmAsIHBlcmNlbnRhZ2UgcmVsYXRpdmUgdG8gdGhlIGxlbmd0aCBvZiB0aGUgcmVmZXJlbmNlIGVsZW1lbnRcbiAgICogLSBgJXBgLCBwZXJjZW50YWdlIHJlbGF0aXZlIHRvIHRoZSBsZW5ndGggb2YgdGhlIHBvcHBlciBlbGVtZW50XG4gICAqIC0gYHZ3YCwgQ1NTIHZpZXdwb3J0IHdpZHRoIHVuaXRcbiAgICogLSBgdmhgLCBDU1Mgdmlld3BvcnQgaGVpZ2h0IHVuaXRcbiAgICpcbiAgICogRm9yIGxlbmd0aCBpcyBpbnRlbmRlZCB0aGUgbWFpbiBheGlzIHJlbGF0aXZlIHRvIHRoZSBwbGFjZW1lbnQgb2YgdGhlIHBvcHBlci48YnIgLz5cbiAgICogVGhpcyBtZWFucyB0aGF0IGlmIHRoZSBwbGFjZW1lbnQgaXMgYHRvcGAgb3IgYGJvdHRvbWAsIHRoZSBsZW5ndGggd2lsbCBiZSB0aGVcbiAgICogYHdpZHRoYC4gSW4gY2FzZSBvZiBgbGVmdGAgb3IgYHJpZ2h0YCwgaXQgd2lsbCBiZSB0aGUgYGhlaWdodGAuXG4gICAqXG4gICAqIFlvdSBjYW4gcHJvdmlkZSBhIHNpbmdsZSB2YWx1ZSAoYXMgYE51bWJlcmAgb3IgYFN0cmluZ2ApLCBvciBhIHBhaXIgb2YgdmFsdWVzXG4gICAqIGFzIGBTdHJpbmdgIGRpdmlkZWQgYnkgYSBjb21tYSBvciBvbmUgKG9yIG1vcmUpIHdoaXRlIHNwYWNlcy48YnIgLz5cbiAgICogVGhlIGxhdHRlciBpcyBhIGRlcHJlY2F0ZWQgbWV0aG9kIGJlY2F1c2UgaXQgbGVhZHMgdG8gY29uZnVzaW9uIGFuZCB3aWxsIGJlXG4gICAqIHJlbW92ZWQgaW4gdjIuPGJyIC8+XG4gICAqIEFkZGl0aW9uYWxseSwgaXQgYWNjZXB0cyBhZGRpdGlvbnMgYW5kIHN1YnRyYWN0aW9ucyBiZXR3ZWVuIGRpZmZlcmVudCB1bml0cy5cbiAgICogTm90ZSB0aGF0IG11bHRpcGxpY2F0aW9ucyBhbmQgZGl2aXNpb25zIGFyZW4ndCBzdXBwb3J0ZWQuXG4gICAqXG4gICAqIFZhbGlkIGV4YW1wbGVzIGFyZTpcbiAgICogYGBgXG4gICAqIDEwXG4gICAqICcxMCUnXG4gICAqICcxMCwgMTAnXG4gICAqICcxMCUsIDEwJ1xuICAgKiAnMTAgKyAxMCUnXG4gICAqICcxMCAtIDV2aCArIDMlJ1xuICAgKiAnLTEwcHggKyA1dmgsIDVweCAtIDYlJ1xuICAgKiBgYGBcbiAgICogPiAqKk5CKio6IElmIHlvdSBkZXNpcmUgdG8gYXBwbHkgb2Zmc2V0cyB0byB5b3VyIHBvcHBlcnMgaW4gYSB3YXkgdGhhdCBtYXkgbWFrZSB0aGVtIG92ZXJsYXBcbiAgICogPiB3aXRoIHRoZWlyIHJlZmVyZW5jZSBlbGVtZW50LCB1bmZvcnR1bmF0ZWx5LCB5b3Ugd2lsbCBoYXZlIHRvIGRpc2FibGUgdGhlIGBmbGlwYCBtb2RpZmllci5cbiAgICogPiBZb3UgY2FuIHJlYWQgbW9yZSBvbiB0aGlzIGF0IHRoaXMgW2lzc3VlXShodHRwczovL2dpdGh1Yi5jb20vRmV6VnJhc3RhL3BvcHBlci5qcy9pc3N1ZXMvMzczKS5cbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIG9mZnNldDoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj0yMDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDIwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IG9mZnNldCxcbiAgICAvKiogQHByb3Age051bWJlcnxTdHJpbmd9IG9mZnNldD0wXG4gICAgICogVGhlIG9mZnNldCB2YWx1ZSBhcyBkZXNjcmliZWQgaW4gdGhlIG1vZGlmaWVyIGRlc2NyaXB0aW9uXG4gICAgICovXG4gICAgb2Zmc2V0OiAwXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gcHJldmVudCB0aGUgcG9wcGVyIGZyb20gYmVpbmcgcG9zaXRpb25lZCBvdXRzaWRlIHRoZSBib3VuZGFyeS5cbiAgICpcbiAgICogQSBzY2VuYXJpbyBleGlzdHMgd2hlcmUgdGhlIHJlZmVyZW5jZSBpdHNlbGYgaXMgbm90IHdpdGhpbiB0aGUgYm91bmRhcmllcy48YnIgLz5cbiAgICogV2UgY2FuIHNheSBpdCBoYXMgXCJlc2NhcGVkIHRoZSBib3VuZGFyaWVzXCIg4oCUIG9yIGp1c3QgXCJlc2NhcGVkXCIuPGJyIC8+XG4gICAqIEluIHRoaXMgY2FzZSB3ZSBuZWVkIHRvIGRlY2lkZSB3aGV0aGVyIHRoZSBwb3BwZXIgc2hvdWxkIGVpdGhlcjpcbiAgICpcbiAgICogLSBkZXRhY2ggZnJvbSB0aGUgcmVmZXJlbmNlIGFuZCByZW1haW4gXCJ0cmFwcGVkXCIgaW4gdGhlIGJvdW5kYXJpZXMsIG9yXG4gICAqIC0gaWYgaXQgc2hvdWxkIGlnbm9yZSB0aGUgYm91bmRhcnkgYW5kIFwiZXNjYXBlIHdpdGggaXRzIHJlZmVyZW5jZVwiXG4gICAqXG4gICAqIFdoZW4gYGVzY2FwZVdpdGhSZWZlcmVuY2VgIGlzIHNldCB0b2B0cnVlYCBhbmQgcmVmZXJlbmNlIGlzIGNvbXBsZXRlbHlcbiAgICogb3V0c2lkZSBpdHMgYm91bmRhcmllcywgdGhlIHBvcHBlciB3aWxsIG92ZXJmbG93IChvciBjb21wbGV0ZWx5IGxlYXZlKVxuICAgKiB0aGUgYm91bmRhcmllcyBpbiBvcmRlciB0byByZW1haW4gYXR0YWNoZWQgdG8gdGhlIGVkZ2Ugb2YgdGhlIHJlZmVyZW5jZS5cbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIHByZXZlbnRPdmVyZmxvdzoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj0zMDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDMwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IHByZXZlbnRPdmVyZmxvdyxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7QXJyYXl9IFtwcmlvcml0eT1bJ2xlZnQnLCdyaWdodCcsJ3RvcCcsJ2JvdHRvbSddXVxuICAgICAqIFBvcHBlciB3aWxsIHRyeSB0byBwcmV2ZW50IG92ZXJmbG93IGZvbGxvd2luZyB0aGVzZSBwcmlvcml0aWVzIGJ5IGRlZmF1bHQsXG4gICAgICogdGhlbiwgaXQgY291bGQgb3ZlcmZsb3cgb24gdGhlIGxlZnQgYW5kIG9uIHRvcCBvZiB0aGUgYGJvdW5kYXJpZXNFbGVtZW50YFxuICAgICAqL1xuICAgIHByaW9yaXR5OiBbJ2xlZnQnLCAncmlnaHQnLCAndG9wJywgJ2JvdHRvbSddLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtudW1iZXJ9IHBhZGRpbmc9NVxuICAgICAqIEFtb3VudCBvZiBwaXhlbCB1c2VkIHRvIGRlZmluZSBhIG1pbmltdW0gZGlzdGFuY2UgYmV0d2VlbiB0aGUgYm91bmRhcmllc1xuICAgICAqIGFuZCB0aGUgcG9wcGVyLiBUaGlzIG1ha2VzIHN1cmUgdGhlIHBvcHBlciBhbHdheXMgaGFzIGEgbGl0dGxlIHBhZGRpbmdcbiAgICAgKiBiZXR3ZWVuIHRoZSBlZGdlcyBvZiBpdHMgY29udGFpbmVyXG4gICAgICovXG4gICAgcGFkZGluZzogNSxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7U3RyaW5nfEhUTUxFbGVtZW50fSBib3VuZGFyaWVzRWxlbWVudD0nc2Nyb2xsUGFyZW50J1xuICAgICAqIEJvdW5kYXJpZXMgdXNlZCBieSB0aGUgbW9kaWZpZXIuIENhbiBiZSBgc2Nyb2xsUGFyZW50YCwgYHdpbmRvd2AsXG4gICAgICogYHZpZXdwb3J0YCBvciBhbnkgRE9NIGVsZW1lbnQuXG4gICAgICovXG4gICAgYm91bmRhcmllc0VsZW1lbnQ6ICdzY3JvbGxQYXJlbnQnXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gbWFrZSBzdXJlIHRoZSByZWZlcmVuY2UgYW5kIGl0cyBwb3BwZXIgc3RheSBuZWFyIGVhY2ggb3RoZXJcbiAgICogd2l0aG91dCBsZWF2aW5nIGFueSBnYXAgYmV0d2VlbiB0aGUgdHdvLiBFc3BlY2lhbGx5IHVzZWZ1bCB3aGVuIHRoZSBhcnJvdyBpc1xuICAgKiBlbmFibGVkIGFuZCB5b3Ugd2FudCB0byBlbnN1cmUgdGhhdCBpdCBwb2ludHMgdG8gaXRzIHJlZmVyZW5jZSBlbGVtZW50LlxuICAgKiBJdCBjYXJlcyBvbmx5IGFib3V0IHRoZSBmaXJzdCBheGlzLiBZb3UgY2FuIHN0aWxsIGhhdmUgcG9wcGVycyB3aXRoIG1hcmdpblxuICAgKiBiZXR3ZWVuIHRoZSBwb3BwZXIgYW5kIGl0cyByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGtlZXBUb2dldGhlcjoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj00MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDQwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGtlZXBUb2dldGhlclxuICB9LFxuXG4gIC8qKlxuICAgKiBUaGlzIG1vZGlmaWVyIGlzIHVzZWQgdG8gbW92ZSB0aGUgYGFycm93RWxlbWVudGAgb2YgdGhlIHBvcHBlciB0byBtYWtlXG4gICAqIHN1cmUgaXQgaXMgcG9zaXRpb25lZCBiZXR3ZWVuIHRoZSByZWZlcmVuY2UgZWxlbWVudCBhbmQgaXRzIHBvcHBlciBlbGVtZW50LlxuICAgKiBJdCB3aWxsIHJlYWQgdGhlIG91dGVyIHNpemUgb2YgdGhlIGBhcnJvd0VsZW1lbnRgIG5vZGUgdG8gZGV0ZWN0IGhvdyBtYW55XG4gICAqIHBpeGVscyBvZiBjb25qdW5jdGlvbiBhcmUgbmVlZGVkLlxuICAgKlxuICAgKiBJdCBoYXMgbm8gZWZmZWN0IGlmIG5vIGBhcnJvd0VsZW1lbnRgIGlzIHByb3ZpZGVkLlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgYXJyb3c6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9NTAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA1MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBhcnJvdyxcbiAgICAvKiogQHByb3Age1N0cmluZ3xIVE1MRWxlbWVudH0gZWxlbWVudD0nW3gtYXJyb3ddJyAtIFNlbGVjdG9yIG9yIG5vZGUgdXNlZCBhcyBhcnJvdyAqL1xuICAgIGVsZW1lbnQ6ICdbeC1hcnJvd10nXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gZmxpcCB0aGUgcG9wcGVyJ3MgcGxhY2VtZW50IHdoZW4gaXQgc3RhcnRzIHRvIG92ZXJsYXAgaXRzXG4gICAqIHJlZmVyZW5jZSBlbGVtZW50LlxuICAgKlxuICAgKiBSZXF1aXJlcyB0aGUgYHByZXZlbnRPdmVyZmxvd2AgbW9kaWZpZXIgYmVmb3JlIGl0IGluIG9yZGVyIHRvIHdvcmsuXG4gICAqXG4gICAqICoqTk9URToqKiB0aGlzIG1vZGlmaWVyIHdpbGwgaW50ZXJydXB0IHRoZSBjdXJyZW50IHVwZGF0ZSBjeWNsZSBhbmQgd2lsbFxuICAgKiByZXN0YXJ0IGl0IGlmIGl0IGRldGVjdHMgdGhlIG5lZWQgdG8gZmxpcCB0aGUgcGxhY2VtZW50LlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgZmxpcDoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj02MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDYwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGZsaXAsXG4gICAgLyoqXG4gICAgICogQHByb3Age1N0cmluZ3xBcnJheX0gYmVoYXZpb3I9J2ZsaXAnXG4gICAgICogVGhlIGJlaGF2aW9yIHVzZWQgdG8gY2hhbmdlIHRoZSBwb3BwZXIncyBwbGFjZW1lbnQuIEl0IGNhbiBiZSBvbmUgb2ZcbiAgICAgKiBgZmxpcGAsIGBjbG9ja3dpc2VgLCBgY291bnRlcmNsb2Nrd2lzZWAgb3IgYW4gYXJyYXkgd2l0aCBhIGxpc3Qgb2YgdmFsaWRcbiAgICAgKiBwbGFjZW1lbnRzICh3aXRoIG9wdGlvbmFsIHZhcmlhdGlvbnMpXG4gICAgICovXG4gICAgYmVoYXZpb3I6ICdmbGlwJyxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7bnVtYmVyfSBwYWRkaW5nPTVcbiAgICAgKiBUaGUgcG9wcGVyIHdpbGwgZmxpcCBpZiBpdCBoaXRzIHRoZSBlZGdlcyBvZiB0aGUgYGJvdW5kYXJpZXNFbGVtZW50YFxuICAgICAqL1xuICAgIHBhZGRpbmc6IDUsXG4gICAgLyoqXG4gICAgICogQHByb3Age1N0cmluZ3xIVE1MRWxlbWVudH0gYm91bmRhcmllc0VsZW1lbnQ9J3ZpZXdwb3J0J1xuICAgICAqIFRoZSBlbGVtZW50IHdoaWNoIHdpbGwgZGVmaW5lIHRoZSBib3VuZGFyaWVzIG9mIHRoZSBwb3BwZXIgcG9zaXRpb24uXG4gICAgICogVGhlIHBvcHBlciB3aWxsIG5ldmVyIGJlIHBsYWNlZCBvdXRzaWRlIG9mIHRoZSBkZWZpbmVkIGJvdW5kYXJpZXNcbiAgICAgKiAoZXhjZXB0IGlmIGBrZWVwVG9nZXRoZXJgIGlzIGVuYWJsZWQpXG4gICAgICovXG4gICAgYm91bmRhcmllc0VsZW1lbnQ6ICd2aWV3cG9ydCdcbiAgfSxcblxuICAvKipcbiAgICogTW9kaWZpZXIgdXNlZCB0byBtYWtlIHRoZSBwb3BwZXIgZmxvdyB0b3dhcmQgdGhlIGlubmVyIG9mIHRoZSByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogQnkgZGVmYXVsdCwgd2hlbiB0aGlzIG1vZGlmaWVyIGlzIGRpc2FibGVkLCB0aGUgcG9wcGVyIHdpbGwgYmUgcGxhY2VkIG91dHNpZGVcbiAgICogdGhlIHJlZmVyZW5jZSBlbGVtZW50LlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgaW5uZXI6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9NzAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA3MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPWZhbHNlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGlubmVyXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gaGlkZSB0aGUgcG9wcGVyIHdoZW4gaXRzIHJlZmVyZW5jZSBlbGVtZW50IGlzIG91dHNpZGUgb2YgdGhlXG4gICAqIHBvcHBlciBib3VuZGFyaWVzLiBJdCB3aWxsIHNldCBhIGB4LW91dC1vZi1ib3VuZGFyaWVzYCBhdHRyaWJ1dGUgd2hpY2ggY2FuXG4gICAqIGJlIHVzZWQgdG8gaGlkZSB3aXRoIGEgQ1NTIHNlbGVjdG9yIHRoZSBwb3BwZXIgd2hlbiBpdHMgcmVmZXJlbmNlIGlzXG4gICAqIG91dCBvZiBib3VuZGFyaWVzLlxuICAgKlxuICAgKiBSZXF1aXJlcyB0aGUgYHByZXZlbnRPdmVyZmxvd2AgbW9kaWZpZXIgYmVmb3JlIGl0IGluIG9yZGVyIHRvIHdvcmsuXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBoaWRlOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTgwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogODAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogaGlkZVxuICB9LFxuXG4gIC8qKlxuICAgKiBDb21wdXRlcyB0aGUgc3R5bGUgdGhhdCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlciBlbGVtZW50IHRvIGdldHNcbiAgICogcHJvcGVybHkgcG9zaXRpb25lZC5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgbW9kaWZpZXIgd2lsbCBub3QgdG91Y2ggdGhlIERPTSwgaXQganVzdCBwcmVwYXJlcyB0aGUgc3R5bGVzXG4gICAqIHNvIHRoYXQgYGFwcGx5U3R5bGVgIG1vZGlmaWVyIGNhbiBhcHBseSBpdC4gVGhpcyBzZXBhcmF0aW9uIGlzIHVzZWZ1bFxuICAgKiBpbiBjYXNlIHlvdSBuZWVkIHRvIHJlcGxhY2UgYGFwcGx5U3R5bGVgIHdpdGggYSBjdXN0b20gaW1wbGVtZW50YXRpb24uXG4gICAqXG4gICAqIFRoaXMgbW9kaWZpZXIgaGFzIGA4NTBgIGFzIGBvcmRlcmAgdmFsdWUgdG8gbWFpbnRhaW4gYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgKiB3aXRoIHByZXZpb3VzIHZlcnNpb25zIG9mIFBvcHBlci5qcy4gRXhwZWN0IHRoZSBtb2RpZmllcnMgb3JkZXJpbmcgbWV0aG9kXG4gICAqIHRvIGNoYW5nZSBpbiBmdXR1cmUgbWFqb3IgdmVyc2lvbnMgb2YgdGhlIGxpYnJhcnkuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBjb21wdXRlU3R5bGU6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9ODUwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA4NTAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBjb21wdXRlU3R5bGUsXG4gICAgLyoqXG4gICAgICogQHByb3Age0Jvb2xlYW59IGdwdUFjY2VsZXJhdGlvbj10cnVlXG4gICAgICogSWYgdHJ1ZSwgaXQgdXNlcyB0aGUgQ1NTIDNEIHRyYW5zZm9ybWF0aW9uIHRvIHBvc2l0aW9uIHRoZSBwb3BwZXIuXG4gICAgICogT3RoZXJ3aXNlLCBpdCB3aWxsIHVzZSB0aGUgYHRvcGAgYW5kIGBsZWZ0YCBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgZ3B1QWNjZWxlcmF0aW9uOiB0cnVlLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtzdHJpbmd9IFt4PSdib3R0b20nXVxuICAgICAqIFdoZXJlIHRvIGFuY2hvciB0aGUgWCBheGlzIChgYm90dG9tYCBvciBgdG9wYCkuIEFLQSBYIG9mZnNldCBvcmlnaW4uXG4gICAgICogQ2hhbmdlIHRoaXMgaWYgeW91ciBwb3BwZXIgc2hvdWxkIGdyb3cgaW4gYSBkaXJlY3Rpb24gZGlmZmVyZW50IGZyb20gYGJvdHRvbWBcbiAgICAgKi9cbiAgICB4OiAnYm90dG9tJyxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7c3RyaW5nfSBbeD0nbGVmdCddXG4gICAgICogV2hlcmUgdG8gYW5jaG9yIHRoZSBZIGF4aXMgKGBsZWZ0YCBvciBgcmlnaHRgKS4gQUtBIFkgb2Zmc2V0IG9yaWdpbi5cbiAgICAgKiBDaGFuZ2UgdGhpcyBpZiB5b3VyIHBvcHBlciBzaG91bGQgZ3JvdyBpbiBhIGRpcmVjdGlvbiBkaWZmZXJlbnQgZnJvbSBgcmlnaHRgXG4gICAgICovXG4gICAgeTogJ3JpZ2h0J1xuICB9LFxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIHRoZSBjb21wdXRlZCBzdHlsZXMgdG8gdGhlIHBvcHBlciBlbGVtZW50LlxuICAgKlxuICAgKiBBbGwgdGhlIERPTSBtYW5pcHVsYXRpb25zIGFyZSBsaW1pdGVkIHRvIHRoaXMgbW9kaWZpZXIuIFRoaXMgaXMgdXNlZnVsIGluIGNhc2VcbiAgICogeW91IHdhbnQgdG8gaW50ZWdyYXRlIFBvcHBlci5qcyBpbnNpZGUgYSBmcmFtZXdvcmsgb3IgdmlldyBsaWJyYXJ5IGFuZCB5b3VcbiAgICogd2FudCB0byBkZWxlZ2F0ZSBhbGwgdGhlIERPTSBtYW5pcHVsYXRpb25zIHRvIGl0LlxuICAgKlxuICAgKiBOb3RlIHRoYXQgaWYgeW91IGRpc2FibGUgdGhpcyBtb2RpZmllciwgeW91IG11c3QgbWFrZSBzdXJlIHRoZSBwb3BwZXIgZWxlbWVudFxuICAgKiBoYXMgaXRzIHBvc2l0aW9uIHNldCB0byBgYWJzb2x1dGVgIGJlZm9yZSBQb3BwZXIuanMgY2FuIGRvIGl0cyB3b3JrIVxuICAgKlxuICAgKiBKdXN0IGRpc2FibGUgdGhpcyBtb2RpZmllciBhbmQgZGVmaW5lIHlvdXIgb3duIHRvIGFjaGlldmUgdGhlIGRlc2lyZWQgZWZmZWN0LlxuICAgKlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgYXBwbHlTdHlsZToge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj05MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDkwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGFwcGx5U3R5bGUsXG4gICAgLyoqIEBwcm9wIHtGdW5jdGlvbn0gKi9cbiAgICBvbkxvYWQ6IGFwcGx5U3R5bGVPbkxvYWQsXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgdmVyc2lvbiAxLjEwLjAsIHRoZSBwcm9wZXJ0eSBtb3ZlZCB0byBgY29tcHV0ZVN0eWxlYCBtb2RpZmllclxuICAgICAqIEBwcm9wIHtCb29sZWFufSBncHVBY2NlbGVyYXRpb249dHJ1ZVxuICAgICAqIElmIHRydWUsIGl0IHVzZXMgdGhlIENTUyAzRCB0cmFuc2Zvcm1hdGlvbiB0byBwb3NpdGlvbiB0aGUgcG9wcGVyLlxuICAgICAqIE90aGVyd2lzZSwgaXQgd2lsbCB1c2UgdGhlIGB0b3BgIGFuZCBgbGVmdGAgcHJvcGVydGllc1xuICAgICAqL1xuICAgIGdwdUFjY2VsZXJhdGlvbjogdW5kZWZpbmVkXG4gIH1cbn07XG5cbi8qKlxuICogVGhlIGBkYXRhT2JqZWN0YCBpcyBhbiBvYmplY3QgY29udGFpbmluZyBhbGwgdGhlIGluZm9ybWF0aW9uIHVzZWQgYnkgUG9wcGVyLmpzLlxuICogVGhpcyBvYmplY3QgaXMgcGFzc2VkIHRvIG1vZGlmaWVycyBhbmQgdG8gdGhlIGBvbkNyZWF0ZWAgYW5kIGBvblVwZGF0ZWAgY2FsbGJhY2tzLlxuICogQG5hbWUgZGF0YU9iamVjdFxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuaW5zdGFuY2UgVGhlIFBvcHBlci5qcyBpbnN0YW5jZVxuICogQHByb3BlcnR5IHtTdHJpbmd9IGRhdGEucGxhY2VtZW50IFBsYWNlbWVudCBhcHBsaWVkIHRvIHBvcHBlclxuICogQHByb3BlcnR5IHtTdHJpbmd9IGRhdGEub3JpZ2luYWxQbGFjZW1lbnQgUGxhY2VtZW50IG9yaWdpbmFsbHkgZGVmaW5lZCBvbiBpbml0XG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IGRhdGEuZmxpcHBlZCBUcnVlIGlmIHBvcHBlciBoYXMgYmVlbiBmbGlwcGVkIGJ5IGZsaXAgbW9kaWZpZXJcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZGF0YS5oaWRlIFRydWUgaWYgdGhlIHJlZmVyZW5jZSBlbGVtZW50IGlzIG91dCBvZiBib3VuZGFyaWVzLCB1c2VmdWwgdG8ga25vdyB3aGVuIHRvIGhpZGUgdGhlIHBvcHBlclxuICogQHByb3BlcnR5IHtIVE1MRWxlbWVudH0gZGF0YS5hcnJvd0VsZW1lbnQgTm9kZSB1c2VkIGFzIGFycm93IGJ5IGFycm93IG1vZGlmaWVyXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5zdHlsZXMgQW55IENTUyBwcm9wZXJ0eSBkZWZpbmVkIGhlcmUgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIuIEl0IGV4cGVjdHMgdGhlIEphdmFTY3JpcHQgbm9tZW5jbGF0dXJlIChlZy4gYG1hcmdpbkJvdHRvbWApXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5hcnJvd1N0eWxlcyBBbnkgQ1NTIHByb3BlcnR5IGRlZmluZWQgaGVyZSB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlciBhcnJvdy4gSXQgZXhwZWN0cyB0aGUgSmF2YVNjcmlwdCBub21lbmNsYXR1cmUgKGVnLiBgbWFyZ2luQm90dG9tYClcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLmJvdW5kYXJpZXMgT2Zmc2V0cyBvZiB0aGUgcG9wcGVyIGJvdW5kYXJpZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLm9mZnNldHMgVGhlIG1lYXN1cmVtZW50cyBvZiBwb3BwZXIsIHJlZmVyZW5jZSBhbmQgYXJyb3cgZWxlbWVudHNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLm9mZnNldHMucG9wcGVyIGB0b3BgLCBgbGVmdGAsIGB3aWR0aGAsIGBoZWlnaHRgIHZhbHVlc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UgYHRvcGAsIGBsZWZ0YCwgYHdpZHRoYCwgYGhlaWdodGAgdmFsdWVzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5vZmZzZXRzLmFycm93XSBgdG9wYCBhbmQgYGxlZnRgIG9mZnNldHMsIG9ubHkgb25lIG9mIHRoZW0gd2lsbCBiZSBkaWZmZXJlbnQgZnJvbSAwXG4gKi9cblxuLyoqXG4gKiBEZWZhdWx0IG9wdGlvbnMgcHJvdmlkZWQgdG8gUG9wcGVyLmpzIGNvbnN0cnVjdG9yLjxiciAvPlxuICogVGhlc2UgY2FuIGJlIG92ZXJyaWRkZW4gdXNpbmcgdGhlIGBvcHRpb25zYCBhcmd1bWVudCBvZiBQb3BwZXIuanMuPGJyIC8+XG4gKiBUbyBvdmVycmlkZSBhbiBvcHRpb24sIHNpbXBseSBwYXNzIGFuIG9iamVjdCB3aXRoIHRoZSBzYW1lXG4gKiBzdHJ1Y3R1cmUgb2YgdGhlIGBvcHRpb25zYCBvYmplY3QsIGFzIHRoZSAzcmQgYXJndW1lbnQuIEZvciBleGFtcGxlOlxuICogYGBgXG4gKiBuZXcgUG9wcGVyKHJlZiwgcG9wLCB7XG4gKiAgIG1vZGlmaWVyczoge1xuICogICAgIHByZXZlbnRPdmVyZmxvdzogeyBlbmFibGVkOiBmYWxzZSB9XG4gKiAgIH1cbiAqIH0pXG4gKiBgYGBcbiAqIEB0eXBlIHtPYmplY3R9XG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbnZhciBEZWZhdWx0cyA9IHtcbiAgLyoqXG4gICAqIFBvcHBlcidzIHBsYWNlbWVudC5cbiAgICogQHByb3Age1BvcHBlci5wbGFjZW1lbnRzfSBwbGFjZW1lbnQ9J2JvdHRvbSdcbiAgICovXG4gIHBsYWNlbWVudDogJ2JvdHRvbScsXG5cbiAgLyoqXG4gICAqIFNldCB0aGlzIHRvIHRydWUgaWYgeW91IHdhbnQgcG9wcGVyIHRvIHBvc2l0aW9uIGl0IHNlbGYgaW4gJ2ZpeGVkJyBtb2RlXG4gICAqIEBwcm9wIHtCb29sZWFufSBwb3NpdGlvbkZpeGVkPWZhbHNlXG4gICAqL1xuICBwb3NpdGlvbkZpeGVkOiBmYWxzZSxcblxuICAvKipcbiAgICogV2hldGhlciBldmVudHMgKHJlc2l6ZSwgc2Nyb2xsKSBhcmUgaW5pdGlhbGx5IGVuYWJsZWQuXG4gICAqIEBwcm9wIHtCb29sZWFufSBldmVudHNFbmFibGVkPXRydWVcbiAgICovXG4gIGV2ZW50c0VuYWJsZWQ6IHRydWUsXG5cbiAgLyoqXG4gICAqIFNldCB0byB0cnVlIGlmIHlvdSB3YW50IHRvIGF1dG9tYXRpY2FsbHkgcmVtb3ZlIHRoZSBwb3BwZXIgd2hlblxuICAgKiB5b3UgY2FsbCB0aGUgYGRlc3Ryb3lgIG1ldGhvZC5cbiAgICogQHByb3Age0Jvb2xlYW59IHJlbW92ZU9uRGVzdHJveT1mYWxzZVxuICAgKi9cbiAgcmVtb3ZlT25EZXN0cm95OiBmYWxzZSxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHBvcHBlciBpcyBjcmVhdGVkLjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCBpdCBpcyBzZXQgdG8gbm8tb3AuPGJyIC8+XG4gICAqIEFjY2VzcyBQb3BwZXIuanMgaW5zdGFuY2Ugd2l0aCBgZGF0YS5pbnN0YW5jZWAuXG4gICAqIEBwcm9wIHtvbkNyZWF0ZX1cbiAgICovXG4gIG9uQ3JlYXRlOiBmdW5jdGlvbiBvbkNyZWF0ZSgpIHt9LFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBjYWxsZWQgd2hlbiB0aGUgcG9wcGVyIGlzIHVwZGF0ZWQuIFRoaXMgY2FsbGJhY2sgaXMgbm90IGNhbGxlZFxuICAgKiBvbiB0aGUgaW5pdGlhbGl6YXRpb24vY3JlYXRpb24gb2YgdGhlIHBvcHBlciwgYnV0IG9ubHkgb24gc3Vic2VxdWVudFxuICAgKiB1cGRhdGVzLjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCBpdCBpcyBzZXQgdG8gbm8tb3AuPGJyIC8+XG4gICAqIEFjY2VzcyBQb3BwZXIuanMgaW5zdGFuY2Ugd2l0aCBgZGF0YS5pbnN0YW5jZWAuXG4gICAqIEBwcm9wIHtvblVwZGF0ZX1cbiAgICovXG4gIG9uVXBkYXRlOiBmdW5jdGlvbiBvblVwZGF0ZSgpIHt9LFxuXG4gIC8qKlxuICAgKiBMaXN0IG9mIG1vZGlmaWVycyB1c2VkIHRvIG1vZGlmeSB0aGUgb2Zmc2V0cyBiZWZvcmUgdGhleSBhcmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLlxuICAgKiBUaGV5IHByb3ZpZGUgbW9zdCBvZiB0aGUgZnVuY3Rpb25hbGl0aWVzIG9mIFBvcHBlci5qcy5cbiAgICogQHByb3Age21vZGlmaWVyc31cbiAgICovXG4gIG1vZGlmaWVyczogbW9kaWZpZXJzXG59O1xuXG4vKipcbiAqIEBjYWxsYmFjayBvbkNyZWF0ZVxuICogQHBhcmFtIHtkYXRhT2JqZWN0fSBkYXRhXG4gKi9cblxuLyoqXG4gKiBAY2FsbGJhY2sgb25VcGRhdGVcbiAqIEBwYXJhbSB7ZGF0YU9iamVjdH0gZGF0YVxuICovXG5cbi8vIFV0aWxzXG4vLyBNZXRob2RzXG52YXIgUG9wcGVyID0gZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBQb3BwZXIuanMgaW5zdGFuY2UuXG4gICAqIEBjbGFzcyBQb3BwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxyZWZlcmVuY2VPYmplY3R9IHJlZmVyZW5jZSAtIFRoZSByZWZlcmVuY2UgZWxlbWVudCB1c2VkIHRvIHBvc2l0aW9uIHRoZSBwb3BwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyIC0gVGhlIEhUTUwgZWxlbWVudCB1c2VkIGFzIHRoZSBwb3BwZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBZb3VyIGN1c3RvbSBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBvbmVzIGRlZmluZWQgaW4gW0RlZmF1bHRzXSgjZGVmYXVsdHMpXG4gICAqIEByZXR1cm4ge09iamVjdH0gaW5zdGFuY2UgLSBUaGUgZ2VuZXJhdGVkIFBvcHBlci5qcyBpbnN0YW5jZVxuICAgKi9cbiAgZnVuY3Rpb24gUG9wcGVyKHJlZmVyZW5jZSwgcG9wcGVyKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTtcbiAgICBjbGFzc0NhbGxDaGVjayh0aGlzLCBQb3BwZXIpO1xuXG4gICAgdGhpcy5zY2hlZHVsZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoX3RoaXMudXBkYXRlKTtcbiAgICB9O1xuXG4gICAgLy8gbWFrZSB1cGRhdGUoKSBkZWJvdW5jZWQsIHNvIHRoYXQgaXQgb25seSBydW5zIGF0IG1vc3Qgb25jZS1wZXItdGlja1xuICAgIHRoaXMudXBkYXRlID0gZGVib3VuY2UodGhpcy51cGRhdGUuYmluZCh0aGlzKSk7XG5cbiAgICAvLyB3aXRoIHt9IHdlIGNyZWF0ZSBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgb3B0aW9ucyBpbnNpZGUgaXRcbiAgICB0aGlzLm9wdGlvbnMgPSBfZXh0ZW5kcyh7fSwgUG9wcGVyLkRlZmF1bHRzLCBvcHRpb25zKTtcblxuICAgIC8vIGluaXQgc3RhdGVcbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgaXNEZXN0cm95ZWQ6IGZhbHNlLFxuICAgICAgaXNDcmVhdGVkOiBmYWxzZSxcbiAgICAgIHNjcm9sbFBhcmVudHM6IFtdXG4gICAgfTtcblxuICAgIC8vIGdldCByZWZlcmVuY2UgYW5kIHBvcHBlciBlbGVtZW50cyAoYWxsb3cgalF1ZXJ5IHdyYXBwZXJzKVxuICAgIHRoaXMucmVmZXJlbmNlID0gcmVmZXJlbmNlICYmIHJlZmVyZW5jZS5qcXVlcnkgPyByZWZlcmVuY2VbMF0gOiByZWZlcmVuY2U7XG4gICAgdGhpcy5wb3BwZXIgPSBwb3BwZXIgJiYgcG9wcGVyLmpxdWVyeSA/IHBvcHBlclswXSA6IHBvcHBlcjtcblxuICAgIC8vIERlZXAgbWVyZ2UgbW9kaWZpZXJzIG9wdGlvbnNcbiAgICB0aGlzLm9wdGlvbnMubW9kaWZpZXJzID0ge307XG4gICAgT2JqZWN0LmtleXMoX2V4dGVuZHMoe30sIFBvcHBlci5EZWZhdWx0cy5tb2RpZmllcnMsIG9wdGlvbnMubW9kaWZpZXJzKSkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgX3RoaXMub3B0aW9ucy5tb2RpZmllcnNbbmFtZV0gPSBfZXh0ZW5kcyh7fSwgUG9wcGVyLkRlZmF1bHRzLm1vZGlmaWVyc1tuYW1lXSB8fCB7fSwgb3B0aW9ucy5tb2RpZmllcnMgPyBvcHRpb25zLm1vZGlmaWVyc1tuYW1lXSA6IHt9KTtcbiAgICB9KTtcblxuICAgIC8vIFJlZmFjdG9yaW5nIG1vZGlmaWVycycgbGlzdCAoT2JqZWN0ID0+IEFycmF5KVxuICAgIHRoaXMubW9kaWZpZXJzID0gT2JqZWN0LmtleXModGhpcy5vcHRpb25zLm1vZGlmaWVycykubWFwKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICByZXR1cm4gX2V4dGVuZHMoe1xuICAgICAgICBuYW1lOiBuYW1lXG4gICAgICB9LCBfdGhpcy5vcHRpb25zLm1vZGlmaWVyc1tuYW1lXSk7XG4gICAgfSlcbiAgICAvLyBzb3J0IHRoZSBtb2RpZmllcnMgYnkgb3JkZXJcbiAgICAuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEub3JkZXIgLSBiLm9yZGVyO1xuICAgIH0pO1xuXG4gICAgLy8gbW9kaWZpZXJzIGhhdmUgdGhlIGFiaWxpdHkgdG8gZXhlY3V0ZSBhcmJpdHJhcnkgY29kZSB3aGVuIFBvcHBlci5qcyBnZXQgaW5pdGVkXG4gICAgLy8gc3VjaCBjb2RlIGlzIGV4ZWN1dGVkIGluIHRoZSBzYW1lIG9yZGVyIG9mIGl0cyBtb2RpZmllclxuICAgIC8vIHRoZXkgY291bGQgYWRkIG5ldyBwcm9wZXJ0aWVzIHRvIHRoZWlyIG9wdGlvbnMgY29uZmlndXJhdGlvblxuICAgIC8vIEJFIEFXQVJFOiBkb24ndCBhZGQgb3B0aW9ucyB0byBgb3B0aW9ucy5tb2RpZmllcnMubmFtZWAgYnV0IHRvIGBtb2RpZmllck9wdGlvbnNgIVxuICAgIHRoaXMubW9kaWZpZXJzLmZvckVhY2goZnVuY3Rpb24gKG1vZGlmaWVyT3B0aW9ucykge1xuICAgICAgaWYgKG1vZGlmaWVyT3B0aW9ucy5lbmFibGVkICYmIGlzRnVuY3Rpb24obW9kaWZpZXJPcHRpb25zLm9uTG9hZCkpIHtcbiAgICAgICAgbW9kaWZpZXJPcHRpb25zLm9uTG9hZChfdGhpcy5yZWZlcmVuY2UsIF90aGlzLnBvcHBlciwgX3RoaXMub3B0aW9ucywgbW9kaWZpZXJPcHRpb25zLCBfdGhpcy5zdGF0ZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBmaXJlIHRoZSBmaXJzdCB1cGRhdGUgdG8gcG9zaXRpb24gdGhlIHBvcHBlciBpbiB0aGUgcmlnaHQgcGxhY2VcbiAgICB0aGlzLnVwZGF0ZSgpO1xuXG4gICAgdmFyIGV2ZW50c0VuYWJsZWQgPSB0aGlzLm9wdGlvbnMuZXZlbnRzRW5hYmxlZDtcbiAgICBpZiAoZXZlbnRzRW5hYmxlZCkge1xuICAgICAgLy8gc2V0dXAgZXZlbnQgbGlzdGVuZXJzLCB0aGV5IHdpbGwgdGFrZSBjYXJlIG9mIHVwZGF0ZSB0aGUgcG9zaXRpb24gaW4gc3BlY2lmaWMgc2l0dWF0aW9uc1xuICAgICAgdGhpcy5lbmFibGVFdmVudExpc3RlbmVycygpO1xuICAgIH1cblxuICAgIHRoaXMuc3RhdGUuZXZlbnRzRW5hYmxlZCA9IGV2ZW50c0VuYWJsZWQ7XG4gIH1cblxuICAvLyBXZSBjYW4ndCB1c2UgY2xhc3MgcHJvcGVydGllcyBiZWNhdXNlIHRoZXkgZG9uJ3QgZ2V0IGxpc3RlZCBpbiB0aGVcbiAgLy8gY2xhc3MgcHJvdG90eXBlIGFuZCBicmVhayBzdHVmZiBsaWtlIFNpbm9uIHN0dWJzXG5cblxuICBjcmVhdGVDbGFzcyhQb3BwZXIsIFt7XG4gICAga2V5OiAndXBkYXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlJCQxKCkge1xuICAgICAgcmV0dXJuIHVwZGF0ZS5jYWxsKHRoaXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2Rlc3Ryb3knLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBkZXN0cm95JCQxKCkge1xuICAgICAgcmV0dXJuIGRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdlbmFibGVFdmVudExpc3RlbmVycycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGVuYWJsZUV2ZW50TGlzdGVuZXJzJCQxKCkge1xuICAgICAgcmV0dXJuIGVuYWJsZUV2ZW50TGlzdGVuZXJzLmNhbGwodGhpcyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZGlzYWJsZUV2ZW50TGlzdGVuZXJzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZGlzYWJsZUV2ZW50TGlzdGVuZXJzJCQxKCkge1xuICAgICAgcmV0dXJuIGRpc2FibGVFdmVudExpc3RlbmVycy5jYWxsKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjaGVkdWxlcyBhbiB1cGRhdGUuIEl0IHdpbGwgcnVuIG9uIHRoZSBuZXh0IFVJIHVwZGF0ZSBhdmFpbGFibGUuXG4gICAgICogQG1ldGhvZCBzY2hlZHVsZVVwZGF0ZVxuICAgICAqIEBtZW1iZXJvZiBQb3BwZXJcbiAgICAgKi9cblxuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiB1dGlsaXRpZXMgdXNlZnVsIHdoZW4gd3JpdGluZyBjdXN0b20gbW9kaWZpZXJzLlxuICAgICAqIFN0YXJ0aW5nIGZyb20gdmVyc2lvbiAxLjcsIHRoaXMgbWV0aG9kIGlzIGF2YWlsYWJsZSBvbmx5IGlmIHlvdVxuICAgICAqIGluY2x1ZGUgYHBvcHBlci11dGlscy5qc2AgYmVmb3JlIGBwb3BwZXIuanNgLlxuICAgICAqXG4gICAgICogKipERVBSRUNBVElPTioqOiBUaGlzIHdheSB0byBhY2Nlc3MgUG9wcGVyVXRpbHMgaXMgZGVwcmVjYXRlZFxuICAgICAqIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gdjIhIFVzZSB0aGUgUG9wcGVyVXRpbHMgbW9kdWxlIGRpcmVjdGx5IGluc3RlYWQuXG4gICAgICogRHVlIHRvIHRoZSBoaWdoIGluc3RhYmlsaXR5IG9mIHRoZSBtZXRob2RzIGNvbnRhaW5lZCBpbiBVdGlscywgd2UgY2FuJ3RcbiAgICAgKiBndWFyYW50ZWUgdGhlbSB0byBmb2xsb3cgc2VtdmVyLiBVc2UgdGhlbSBhdCB5b3VyIG93biByaXNrIVxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgdmVyc2lvbiAxLjhcbiAgICAgKiBAbWVtYmVyIFV0aWxzXG4gICAgICogQG1lbWJlcm9mIFBvcHBlclxuICAgICAqL1xuXG4gIH1dKTtcbiAgcmV0dXJuIFBvcHBlcjtcbn0oKTtcblxuLyoqXG4gKiBUaGUgYHJlZmVyZW5jZU9iamVjdGAgaXMgYW4gb2JqZWN0IHRoYXQgcHJvdmlkZXMgYW4gaW50ZXJmYWNlIGNvbXBhdGlibGUgd2l0aCBQb3BwZXIuanNcbiAqIGFuZCBsZXRzIHlvdSB1c2UgaXQgYXMgcmVwbGFjZW1lbnQgb2YgYSByZWFsIERPTSBub2RlLjxiciAvPlxuICogWW91IGNhbiB1c2UgdGhpcyBtZXRob2QgdG8gcG9zaXRpb24gYSBwb3BwZXIgcmVsYXRpdmVseSB0byBhIHNldCBvZiBjb29yZGluYXRlc1xuICogaW4gY2FzZSB5b3UgZG9uJ3QgaGF2ZSBhIERPTSBub2RlIHRvIHVzZSBhcyByZWZlcmVuY2UuXG4gKlxuICogYGBgXG4gKiBuZXcgUG9wcGVyKHJlZmVyZW5jZU9iamVjdCwgcG9wcGVyTm9kZSk7XG4gKiBgYGBcbiAqXG4gKiBOQjogVGhpcyBmZWF0dXJlIGlzbid0IHN1cHBvcnRlZCBpbiBJbnRlcm5ldCBFeHBsb3JlciAxMC5cbiAqIEBuYW1lIHJlZmVyZW5jZU9iamVjdFxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gZGF0YS5nZXRCb3VuZGluZ0NsaWVudFJlY3RcbiAqIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgc2V0IG9mIGNvb3JkaW5hdGVzIGNvbXBhdGlibGUgd2l0aCB0aGUgbmF0aXZlIGBnZXRCb3VuZGluZ0NsaWVudFJlY3RgIG1ldGhvZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkYXRhLmNsaWVudFdpZHRoXG4gKiBBbiBFUzYgZ2V0dGVyIHRoYXQgd2lsbCByZXR1cm4gdGhlIHdpZHRoIG9mIHRoZSB2aXJ0dWFsIHJlZmVyZW5jZSBlbGVtZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IGRhdGEuY2xpZW50SGVpZ2h0XG4gKiBBbiBFUzYgZ2V0dGVyIHRoYXQgd2lsbCByZXR1cm4gdGhlIGhlaWdodCBvZiB0aGUgdmlydHVhbCByZWZlcmVuY2UgZWxlbWVudC5cbiAqL1xuXG5cblBvcHBlci5VdGlscyA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IGdsb2JhbCkuUG9wcGVyVXRpbHM7XG5Qb3BwZXIucGxhY2VtZW50cyA9IHBsYWNlbWVudHM7XG5Qb3BwZXIuRGVmYXVsdHMgPSBEZWZhdWx0cztcblxuZXhwb3J0IGRlZmF1bHQgUG9wcGVyO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cG9wcGVyLmpzLm1hcFxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvcG9wcGVyLmpzL2Rpc3QvZXNtL3BvcHBlci5qc1xuLy8gbW9kdWxlIGlkID0gM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSxldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2goZSkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgdGhlIHdpbmRvdyByZWZlcmVuY2UgaXMgYXZhaWxhYmxlXHJcblx0aWYodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIilcclxuXHRcdGcgPSB3aW5kb3c7XHJcbn1cclxuXHJcbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cclxuLy8gV2UgcmV0dXJuIHVuZGVmaW5lZCwgaW5zdGVhZCBvZiBub3RoaW5nIGhlcmUsIHNvIGl0J3NcclxuLy8gZWFzaWVyIHRvIGhhbmRsZSB0aGlzIGNhc2UuIGlmKCFnbG9iYWwpIHsgLi4ufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBnO1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9nbG9iYWwuanNcbi8vIG1vZHVsZSBpZCA9IDRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohXHJcbiAqIEJvb3RzdHJhcC1zZWxlY3QgdjEuMTIuNCAoaHR0cDovL3NpbHZpb21vcmV0by5naXRodWIuaW8vYm9vdHN0cmFwLXNlbGVjdClcclxuICpcclxuICogQ29weXJpZ2h0IDIwMTMtMjAxNyBib290c3RyYXAtc2VsZWN0XHJcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3NpbHZpb21vcmV0by9ib290c3RyYXAtc2VsZWN0L2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXHJcbiAqL1xyXG5cclxuKGZ1bmN0aW9uIChyb290LCBmYWN0b3J5KSB7XG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBBTUQuIFJlZ2lzdGVyIGFzIGFuIGFub255bW91cyBtb2R1bGUgdW5sZXNzIGFtZE1vZHVsZUlkIGlzIHNldFxuICAgIGRlZmluZShbXCJqcXVlcnlcIl0sIGZ1bmN0aW9uIChhMCkge1xuICAgICAgcmV0dXJuIChmYWN0b3J5KGEwKSk7XG4gICAgfSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAvLyBOb2RlLiBEb2VzIG5vdCB3b3JrIHdpdGggc3RyaWN0IENvbW1vbkpTLCBidXRcbiAgICAvLyBvbmx5IENvbW1vbkpTLWxpa2UgZW52aXJvbm1lbnRzIHRoYXQgc3VwcG9ydCBtb2R1bGUuZXhwb3J0cyxcbiAgICAvLyBsaWtlIE5vZGUuXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCJqcXVlcnlcIikpO1xuICB9IGVsc2Uge1xuICAgIGZhY3Rvcnkocm9vdFtcImpRdWVyeVwiXSk7XG4gIH1cbn0odGhpcywgZnVuY3Rpb24gKGpRdWVyeSkge1xuXG4oZnVuY3Rpb24gKCQpIHtcclxuICAndXNlIHN0cmljdCc7XHJcblxyXG4gIC8vPGVkaXRvci1mb2xkIGRlc2M9XCJTaGltc1wiPlxyXG4gIGlmICghU3RyaW5nLnByb3RvdHlwZS5pbmNsdWRlcykge1xyXG4gICAgKGZ1bmN0aW9uICgpIHtcclxuICAgICAgJ3VzZSBzdHJpY3QnOyAvLyBuZWVkZWQgdG8gc3VwcG9ydCBgYXBwbHlgL2BjYWxsYCB3aXRoIGB1bmRlZmluZWRgL2BudWxsYFxyXG4gICAgICB2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcclxuICAgICAgdmFyIGRlZmluZVByb3BlcnR5ID0gKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBJRSA4IG9ubHkgc3VwcG9ydHMgYE9iamVjdC5kZWZpbmVQcm9wZXJ0eWAgb24gRE9NIGVsZW1lbnRzXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcclxuICAgICAgICAgIHZhciAkZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gJGRlZmluZVByb3BlcnR5KG9iamVjdCwgb2JqZWN0LCBvYmplY3QpICYmICRkZWZpbmVQcm9wZXJ0eTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICB9KCkpO1xyXG4gICAgICB2YXIgaW5kZXhPZiA9ICcnLmluZGV4T2Y7XHJcbiAgICAgIHZhciBpbmNsdWRlcyA9IGZ1bmN0aW9uIChzZWFyY2gpIHtcclxuICAgICAgICBpZiAodGhpcyA9PSBudWxsKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdHJpbmcgPSBTdHJpbmcodGhpcyk7XHJcbiAgICAgICAgaWYgKHNlYXJjaCAmJiB0b1N0cmluZy5jYWxsKHNlYXJjaCkgPT0gJ1tvYmplY3QgUmVnRXhwXScpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0cmluZ0xlbmd0aCA9IHN0cmluZy5sZW5ndGg7XHJcbiAgICAgICAgdmFyIHNlYXJjaFN0cmluZyA9IFN0cmluZyhzZWFyY2gpO1xyXG4gICAgICAgIHZhciBzZWFyY2hMZW5ndGggPSBzZWFyY2hTdHJpbmcubGVuZ3RoO1xyXG4gICAgICAgIHZhciBwb3NpdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkO1xyXG4gICAgICAgIC8vIGBUb0ludGVnZXJgXHJcbiAgICAgICAgdmFyIHBvcyA9IHBvc2l0aW9uID8gTnVtYmVyKHBvc2l0aW9uKSA6IDA7XHJcbiAgICAgICAgaWYgKHBvcyAhPSBwb3MpIHsgLy8gYmV0dGVyIGBpc05hTmBcclxuICAgICAgICAgIHBvcyA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdGFydCA9IE1hdGgubWluKE1hdGgubWF4KHBvcywgMCksIHN0cmluZ0xlbmd0aCk7XHJcbiAgICAgICAgLy8gQXZvaWQgdGhlIGBpbmRleE9mYCBjYWxsIGlmIG5vIG1hdGNoIGlzIHBvc3NpYmxlXHJcbiAgICAgICAgaWYgKHNlYXJjaExlbmd0aCArIHN0YXJ0ID4gc3RyaW5nTGVuZ3RoKSB7XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBpbmRleE9mLmNhbGwoc3RyaW5nLCBzZWFyY2hTdHJpbmcsIHBvcykgIT0gLTE7XHJcbiAgICAgIH07XHJcbiAgICAgIGlmIChkZWZpbmVQcm9wZXJ0eSkge1xyXG4gICAgICAgIGRlZmluZVByb3BlcnR5KFN0cmluZy5wcm90b3R5cGUsICdpbmNsdWRlcycsIHtcclxuICAgICAgICAgICd2YWx1ZSc6IGluY2x1ZGVzLFxyXG4gICAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXHJcbiAgICAgICAgICAnd3JpdGFibGUnOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgU3RyaW5nLnByb3RvdHlwZS5pbmNsdWRlcyA9IGluY2x1ZGVzO1xyXG4gICAgICB9XHJcbiAgICB9KCkpO1xyXG4gIH1cclxuXHJcbiAgaWYgKCFTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGgpIHtcclxuICAgIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICd1c2Ugc3RyaWN0JzsgLy8gbmVlZGVkIHRvIHN1cHBvcnQgYGFwcGx5YC9gY2FsbGAgd2l0aCBgdW5kZWZpbmVkYC9gbnVsbGBcclxuICAgICAgdmFyIGRlZmluZVByb3BlcnR5ID0gKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBJRSA4IG9ubHkgc3VwcG9ydHMgYE9iamVjdC5kZWZpbmVQcm9wZXJ0eWAgb24gRE9NIGVsZW1lbnRzXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcclxuICAgICAgICAgIHZhciAkZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gJGRlZmluZVByb3BlcnR5KG9iamVjdCwgb2JqZWN0LCBvYmplY3QpICYmICRkZWZpbmVQcm9wZXJ0eTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICB9KCkpO1xyXG4gICAgICB2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcclxuICAgICAgdmFyIHN0YXJ0c1dpdGggPSBmdW5jdGlvbiAoc2VhcmNoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHRoaXMpO1xyXG4gICAgICAgIGlmIChzZWFyY2ggJiYgdG9TdHJpbmcuY2FsbChzZWFyY2gpID09ICdbb2JqZWN0IFJlZ0V4cF0nKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xyXG4gICAgICAgIHZhciBzZWFyY2hTdHJpbmcgPSBTdHJpbmcoc2VhcmNoKTtcclxuICAgICAgICB2YXIgc2VhcmNoTGVuZ3RoID0gc2VhcmNoU3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgcG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBgVG9JbnRlZ2VyYFxyXG4gICAgICAgIHZhciBwb3MgPSBwb3NpdGlvbiA/IE51bWJlcihwb3NpdGlvbikgOiAwO1xyXG4gICAgICAgIGlmIChwb3MgIT0gcG9zKSB7IC8vIGJldHRlciBgaXNOYU5gXHJcbiAgICAgICAgICBwb3MgPSAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBNYXRoLm1pbihNYXRoLm1heChwb3MsIDApLCBzdHJpbmdMZW5ndGgpO1xyXG4gICAgICAgIC8vIEF2b2lkIHRoZSBgaW5kZXhPZmAgY2FsbCBpZiBubyBtYXRjaCBpcyBwb3NzaWJsZVxyXG4gICAgICAgIGlmIChzZWFyY2hMZW5ndGggKyBzdGFydCA+IHN0cmluZ0xlbmd0aCkge1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgaW5kZXggPSAtMTtcclxuICAgICAgICB3aGlsZSAoKytpbmRleCA8IHNlYXJjaExlbmd0aCkge1xyXG4gICAgICAgICAgaWYgKHN0cmluZy5jaGFyQ29kZUF0KHN0YXJ0ICsgaW5kZXgpICE9IHNlYXJjaFN0cmluZy5jaGFyQ29kZUF0KGluZGV4KSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9O1xyXG4gICAgICBpZiAoZGVmaW5lUHJvcGVydHkpIHtcclxuICAgICAgICBkZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAnc3RhcnRzV2l0aCcsIHtcclxuICAgICAgICAgICd2YWx1ZSc6IHN0YXJ0c1dpdGgsXHJcbiAgICAgICAgICAnY29uZmlndXJhYmxlJzogdHJ1ZSxcclxuICAgICAgICAgICd3cml0YWJsZSc6IHRydWVcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGggPSBzdGFydHNXaXRoO1xyXG4gICAgICB9XHJcbiAgICB9KCkpO1xyXG4gIH1cclxuXHJcbiAgaWYgKCFPYmplY3Qua2V5cykge1xyXG4gICAgT2JqZWN0LmtleXMgPSBmdW5jdGlvbiAoXHJcbiAgICAgIG8sIC8vIG9iamVjdFxyXG4gICAgICBrLCAvLyBrZXlcclxuICAgICAgciAgLy8gcmVzdWx0IGFycmF5XHJcbiAgICAgICl7XHJcbiAgICAgIC8vIGluaXRpYWxpemUgb2JqZWN0IGFuZCByZXN1bHRcclxuICAgICAgcj1bXTtcclxuICAgICAgLy8gaXRlcmF0ZSBvdmVyIG9iamVjdCBrZXlzXHJcbiAgICAgIGZvciAoayBpbiBvKVxyXG4gICAgICAgICAgLy8gZmlsbCByZXN1bHQgYXJyYXkgd2l0aCBub24tcHJvdG90eXBpY2FsIGtleXNcclxuICAgICAgICByLmhhc093blByb3BlcnR5LmNhbGwobywgaykgJiYgci5wdXNoKGspO1xyXG4gICAgICAvLyByZXR1cm4gcmVzdWx0XHJcbiAgICAgIHJldHVybiByO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vIHNldCBkYXRhLXNlbGVjdGVkIG9uIHNlbGVjdCBlbGVtZW50IGlmIHRoZSB2YWx1ZSBoYXMgYmVlbiBwcm9ncmFtbWF0aWNhbGx5IHNlbGVjdGVkXHJcbiAgLy8gcHJpb3IgdG8gaW5pdGlhbGl6YXRpb24gb2YgYm9vdHN0cmFwLXNlbGVjdFxyXG4gIC8vICogY29uc2lkZXIgcmVtb3Zpbmcgb3IgcmVwbGFjaW5nIGFuIGFsdGVybmF0aXZlIG1ldGhvZCAqXHJcbiAgdmFyIHZhbEhvb2tzID0ge1xyXG4gICAgdXNlRGVmYXVsdDogZmFsc2UsXHJcbiAgICBfc2V0OiAkLnZhbEhvb2tzLnNlbGVjdC5zZXRcclxuICB9O1xyXG5cclxuICAkLnZhbEhvb2tzLnNlbGVjdC5zZXQgPSBmdW5jdGlvbihlbGVtLCB2YWx1ZSkge1xyXG4gICAgaWYgKHZhbHVlICYmICF2YWxIb29rcy51c2VEZWZhdWx0KSAkKGVsZW0pLmRhdGEoJ3NlbGVjdGVkJywgdHJ1ZSk7XHJcblxyXG4gICAgcmV0dXJuIHZhbEhvb2tzLl9zZXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICB9O1xyXG5cclxuICB2YXIgY2hhbmdlZF9hcmd1bWVudHMgPSBudWxsO1xyXG5cclxuICB2YXIgRXZlbnRJc1N1cHBvcnRlZCA9IChmdW5jdGlvbigpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIG5ldyBFdmVudCgnY2hhbmdlJyk7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgfSkoKTtcclxuXHJcbiAgJC5mbi50cmlnZ2VyTmF0aXZlID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xyXG4gICAgdmFyIGVsID0gdGhpc1swXSxcclxuICAgICAgICBldmVudDtcclxuXHJcbiAgICBpZiAoZWwuZGlzcGF0Y2hFdmVudCkgeyAvLyBmb3IgbW9kZXJuIGJyb3dzZXJzICYgSUU5K1xyXG4gICAgICBpZiAoRXZlbnRJc1N1cHBvcnRlZCkge1xyXG4gICAgICAgIC8vIEZvciBtb2Rlcm4gYnJvd3NlcnNcclxuICAgICAgICBldmVudCA9IG5ldyBFdmVudChldmVudE5hbWUsIHtcclxuICAgICAgICAgIGJ1YmJsZXM6IHRydWVcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBGb3IgSUUgc2luY2UgaXQgZG9lc24ndCBzdXBwb3J0IEV2ZW50IGNvbnN0cnVjdG9yXHJcbiAgICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcclxuICAgICAgICBldmVudC5pbml0RXZlbnQoZXZlbnROYW1lLCB0cnVlLCBmYWxzZSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGVsLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xyXG4gICAgfSBlbHNlIGlmIChlbC5maXJlRXZlbnQpIHsgLy8gZm9yIElFOFxyXG4gICAgICBldmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50T2JqZWN0KCk7XHJcbiAgICAgIGV2ZW50LmV2ZW50VHlwZSA9IGV2ZW50TmFtZTtcclxuICAgICAgZWwuZmlyZUV2ZW50KCdvbicgKyBldmVudE5hbWUsIGV2ZW50KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGZhbGwgYmFjayB0byBqUXVlcnkudHJpZ2dlclxyXG4gICAgICB0aGlzLnRyaWdnZXIoZXZlbnROYW1lKTtcclxuICAgIH1cclxuICB9O1xyXG4gIC8vPC9lZGl0b3ItZm9sZD5cclxuXHJcbiAgLy8gQ2FzZSBpbnNlbnNpdGl2ZSBjb250YWlucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5pY29udGFpbnMgPSBmdW5jdGlvbiAob2JqLCBpbmRleCwgbWV0YSkge1xyXG4gICAgdmFyICRvYmogPSAkKG9iaikuZmluZCgnYScpO1xyXG4gICAgdmFyIGhheXN0YWNrID0gKCRvYmouZGF0YSgndG9rZW5zJykgfHwgJG9iai50ZXh0KCkpLnRvU3RyaW5nKCkudG9VcHBlckNhc2UoKTtcclxuICAgIHJldHVybiBoYXlzdGFjay5pbmNsdWRlcyhtZXRhWzNdLnRvVXBwZXJDYXNlKCkpO1xyXG4gIH07XHJcblxyXG4gIC8vIENhc2UgaW5zZW5zaXRpdmUgYmVnaW5zIHNlYXJjaFxyXG4gICQuZXhwci5wc2V1ZG9zLmliZWdpbnMgPSBmdW5jdGlvbiAob2JqLCBpbmRleCwgbWV0YSkge1xyXG4gICAgdmFyICRvYmogPSAkKG9iaikuZmluZCgnYScpO1xyXG4gICAgdmFyIGhheXN0YWNrID0gKCRvYmouZGF0YSgndG9rZW5zJykgfHwgJG9iai50ZXh0KCkpLnRvU3RyaW5nKCkudG9VcHBlckNhc2UoKTtcclxuICAgIHJldHVybiBoYXlzdGFjay5zdGFydHNXaXRoKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ2FzZSBhbmQgYWNjZW50IGluc2Vuc2l0aXZlIGNvbnRhaW5zIHNlYXJjaFxyXG4gICQuZXhwci5wc2V1ZG9zLmFpY29udGFpbnMgPSBmdW5jdGlvbiAob2JqLCBpbmRleCwgbWV0YSkge1xyXG4gICAgdmFyICRvYmogPSAkKG9iaikuZmluZCgnYScpO1xyXG4gICAgdmFyIGhheXN0YWNrID0gKCRvYmouZGF0YSgndG9rZW5zJykgfHwgJG9iai5kYXRhKCdub3JtYWxpemVkVGV4dCcpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suaW5jbHVkZXMobWV0YVszXS50b1VwcGVyQ2FzZSgpKTtcclxuICB9O1xyXG5cclxuICAvLyBDYXNlIGFuZCBhY2NlbnQgaW5zZW5zaXRpdmUgYmVnaW5zIHNlYXJjaFxyXG4gICQuZXhwci5wc2V1ZG9zLmFpYmVnaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmouZGF0YSgnbm9ybWFsaXplZFRleHQnKSB8fCAkb2JqLnRleHQoKSkudG9TdHJpbmcoKS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgcmV0dXJuIGhheXN0YWNrLnN0YXJ0c1dpdGgobWV0YVszXS50b1VwcGVyQ2FzZSgpKTtcclxuICB9O1xyXG5cclxuICAvKipcclxuICAgKiBSZW1vdmUgYWxsIGRpYXRyaWNzIGZyb20gdGhlIGdpdmVuIHRleHQuXHJcbiAgICogQGFjY2VzcyBwcml2YXRlXHJcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRleHRcclxuICAgKiBAcmV0dXJucyB7U3RyaW5nfVxyXG4gICAqL1xyXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZVRvQmFzZSh0ZXh0KSB7XHJcbiAgICB2YXIgckV4cHMgPSBbXHJcbiAgICAgIHtyZTogL1tcXHhDMC1cXHhDNl0vZywgY2g6IFwiQVwifSxcclxuICAgICAge3JlOiAvW1xceEUwLVxceEU2XS9nLCBjaDogXCJhXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4QzgtXFx4Q0JdL2csIGNoOiBcIkVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhFOC1cXHhFQl0vZywgY2g6IFwiZVwifSxcclxuICAgICAge3JlOiAvW1xceENDLVxceENGXS9nLCBjaDogXCJJXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RUMtXFx4RUZdL2csIGNoOiBcImlcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhEMi1cXHhENl0vZywgY2g6IFwiT1wifSxcclxuICAgICAge3JlOiAvW1xceEYyLVxceEY2XS9nLCBjaDogXCJvXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RDktXFx4RENdL2csIGNoOiBcIlVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhGOS1cXHhGQ10vZywgY2g6IFwidVwifSxcclxuICAgICAge3JlOiAvW1xceEM3LVxceEU3XS9nLCBjaDogXCJjXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RDFdL2csIGNoOiBcIk5cIn0sXHJcbiAgICAgIHtyZTogL1tcXHhGMV0vZywgY2g6IFwiblwifVxyXG4gICAgXTtcclxuICAgICQuZWFjaChyRXhwcywgZnVuY3Rpb24gKCkge1xyXG4gICAgICB0ZXh0ID0gdGV4dCA/IHRleHQucmVwbGFjZSh0aGlzLnJlLCB0aGlzLmNoKSA6ICcnO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gdGV4dDtcclxuICB9XHJcblxyXG5cclxuICAvLyBMaXN0IG9mIEhUTUwgZW50aXRpZXMgZm9yIGVzY2FwaW5nLlxyXG4gIHZhciBlc2NhcGVNYXAgPSB7XHJcbiAgICAnJic6ICcmYW1wOycsXHJcbiAgICAnPCc6ICcmbHQ7JyxcclxuICAgICc+JzogJyZndDsnLFxyXG4gICAgJ1wiJzogJyZxdW90OycsXHJcbiAgICBcIidcIjogJyYjeDI3OycsXHJcbiAgICAnYCc6ICcmI3g2MDsnXHJcbiAgfTtcclxuICBcclxuICB2YXIgdW5lc2NhcGVNYXAgPSB7XHJcbiAgICAnJmFtcDsnOiAnJicsXHJcbiAgICAnJmx0Oyc6ICc8JyxcclxuICAgICcmZ3Q7JzogJz4nLFxyXG4gICAgJyZxdW90Oyc6ICdcIicsXHJcbiAgICAnJiN4Mjc7JzogXCInXCIsXHJcbiAgICAnJiN4NjA7JzogJ2AnXHJcbiAgfTtcclxuXHJcbiAgLy8gRnVuY3Rpb25zIGZvciBlc2NhcGluZyBhbmQgdW5lc2NhcGluZyBzdHJpbmdzIHRvL2Zyb20gSFRNTCBpbnRlcnBvbGF0aW9uLlxyXG4gIHZhciBjcmVhdGVFc2NhcGVyID0gZnVuY3Rpb24obWFwKSB7XHJcbiAgICB2YXIgZXNjYXBlciA9IGZ1bmN0aW9uKG1hdGNoKSB7XHJcbiAgICAgIHJldHVybiBtYXBbbWF0Y2hdO1xyXG4gICAgfTtcclxuICAgIC8vIFJlZ2V4ZXMgZm9yIGlkZW50aWZ5aW5nIGEga2V5IHRoYXQgbmVlZHMgdG8gYmUgZXNjYXBlZC5cclxuICAgIHZhciBzb3VyY2UgPSAnKD86JyArIE9iamVjdC5rZXlzKG1hcCkuam9pbignfCcpICsgJyknO1xyXG4gICAgdmFyIHRlc3RSZWdleHAgPSBSZWdFeHAoc291cmNlKTtcclxuICAgIHZhciByZXBsYWNlUmVnZXhwID0gUmVnRXhwKHNvdXJjZSwgJ2cnKTtcclxuICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcclxuICAgICAgc3RyaW5nID0gc3RyaW5nID09IG51bGwgPyAnJyA6ICcnICsgc3RyaW5nO1xyXG4gICAgICByZXR1cm4gdGVzdFJlZ2V4cC50ZXN0KHN0cmluZykgPyBzdHJpbmcucmVwbGFjZShyZXBsYWNlUmVnZXhwLCBlc2NhcGVyKSA6IHN0cmluZztcclxuICAgIH07XHJcbiAgfTtcclxuXHJcbiAgdmFyIGh0bWxFc2NhcGUgPSBjcmVhdGVFc2NhcGVyKGVzY2FwZU1hcCk7XHJcbiAgdmFyIGh0bWxVbmVzY2FwZSA9IGNyZWF0ZUVzY2FwZXIodW5lc2NhcGVNYXApO1xyXG5cclxuICB2YXIgU2VsZWN0cGlja2VyID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcclxuICAgIC8vIGJvb3RzdHJhcC1zZWxlY3QgaGFzIGJlZW4gaW5pdGlhbGl6ZWQgLSByZXZlcnQgdmFsSG9va3Muc2VsZWN0LnNldCBiYWNrIHRvIGl0cyBvcmlnaW5hbCBmdW5jdGlvblxyXG4gICAgaWYgKCF2YWxIb29rcy51c2VEZWZhdWx0KSB7XHJcbiAgICAgICQudmFsSG9va3Muc2VsZWN0LnNldCA9IHZhbEhvb2tzLl9zZXQ7XHJcbiAgICAgIHZhbEhvb2tzLnVzZURlZmF1bHQgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuJGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xyXG4gICAgdGhpcy4kbmV3RWxlbWVudCA9IG51bGw7XHJcbiAgICB0aGlzLiRidXR0b24gPSBudWxsO1xyXG4gICAgdGhpcy4kbWVudSA9IG51bGw7XHJcbiAgICB0aGlzLiRsaXMgPSBudWxsO1xyXG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcclxuXHJcbiAgICAvLyBJZiB3ZSBoYXZlIG5vIHRpdGxlIHlldCwgdHJ5IHRvIHB1bGwgaXQgZnJvbSB0aGUgaHRtbCB0aXRsZSBhdHRyaWJ1dGUgKGpRdWVyeSBkb2VzbnQnIHBpY2sgaXQgdXAgYXMgaXQncyBub3QgYVxyXG4gICAgLy8gZGF0YS1hdHRyaWJ1dGUpXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnRpdGxlID09PSBudWxsKSB7XHJcbiAgICAgIHRoaXMub3B0aW9ucy50aXRsZSA9IHRoaXMuJGVsZW1lbnQuYXR0cigndGl0bGUnKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBGb3JtYXQgd2luZG93IHBhZGRpbmdcclxuICAgIHZhciB3aW5QYWQgPSB0aGlzLm9wdGlvbnMud2luZG93UGFkZGluZztcclxuICAgIGlmICh0eXBlb2Ygd2luUGFkID09PSAnbnVtYmVyJykge1xyXG4gICAgICB0aGlzLm9wdGlvbnMud2luZG93UGFkZGluZyA9IFt3aW5QYWQsIHdpblBhZCwgd2luUGFkLCB3aW5QYWRdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vRXhwb3NlIHB1YmxpYyBtZXRob2RzXHJcbiAgICB0aGlzLnZhbCA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUudmFsO1xyXG4gICAgdGhpcy5yZW5kZXIgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnJlbmRlcjtcclxuICAgIHRoaXMucmVmcmVzaCA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUucmVmcmVzaDtcclxuICAgIHRoaXMuc2V0U3R5bGUgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnNldFN0eWxlO1xyXG4gICAgdGhpcy5zZWxlY3RBbGwgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnNlbGVjdEFsbDtcclxuICAgIHRoaXMuZGVzZWxlY3RBbGwgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLmRlc2VsZWN0QWxsO1xyXG4gICAgdGhpcy5kZXN0cm95ID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5kZXN0cm95O1xyXG4gICAgdGhpcy5yZW1vdmUgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnJlbW92ZTtcclxuICAgIHRoaXMuc2hvdyA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUuc2hvdztcclxuICAgIHRoaXMuaGlkZSA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUuaGlkZTtcclxuXHJcbiAgICB0aGlzLmluaXQoKTtcclxuICB9O1xyXG5cclxuICBTZWxlY3RwaWNrZXIuVkVSU0lPTiA9ICcxLjEyLjQnO1xyXG5cclxuICAvLyBwYXJ0IG9mIHRoaXMgaXMgZHVwbGljYXRlZCBpbiBpMThuL2RlZmF1bHRzLWVuX1VTLmpzLiBNYWtlIHN1cmUgdG8gdXBkYXRlIGJvdGguXHJcbiAgU2VsZWN0cGlja2VyLkRFRkFVTFRTID0ge1xyXG4gICAgbm9uZVNlbGVjdGVkVGV4dDogJ05vdGhpbmcgc2VsZWN0ZWQnLFxyXG4gICAgbm9uZVJlc3VsdHNUZXh0OiAnTm8gcmVzdWx0cyBtYXRjaGVkIHswfScsXHJcbiAgICBjb3VudFNlbGVjdGVkVGV4dDogZnVuY3Rpb24gKG51bVNlbGVjdGVkLCBudW1Ub3RhbCkge1xyXG4gICAgICByZXR1cm4gKG51bVNlbGVjdGVkID09IDEpID8gXCJ7MH0gaXRlbSBzZWxlY3RlZFwiIDogXCJ7MH0gaXRlbXMgc2VsZWN0ZWRcIjtcclxuICAgIH0sXHJcbiAgICBtYXhPcHRpb25zVGV4dDogZnVuY3Rpb24gKG51bUFsbCwgbnVtR3JvdXApIHtcclxuICAgICAgcmV0dXJuIFtcclxuICAgICAgICAobnVtQWxsID09IDEpID8gJ0xpbWl0IHJlYWNoZWQgKHtufSBpdGVtIG1heCknIDogJ0xpbWl0IHJlYWNoZWQgKHtufSBpdGVtcyBtYXgpJyxcclxuICAgICAgICAobnVtR3JvdXAgPT0gMSkgPyAnR3JvdXAgbGltaXQgcmVhY2hlZCAoe259IGl0ZW0gbWF4KScgOiAnR3JvdXAgbGltaXQgcmVhY2hlZCAoe259IGl0ZW1zIG1heCknXHJcbiAgICAgIF07XHJcbiAgICB9LFxyXG4gICAgc2VsZWN0QWxsVGV4dDogJ1NlbGVjdCBBbGwnLFxyXG4gICAgZGVzZWxlY3RBbGxUZXh0OiAnRGVzZWxlY3QgQWxsJyxcclxuICAgIGRvbmVCdXR0b246IGZhbHNlLFxyXG4gICAgZG9uZUJ1dHRvblRleHQ6ICdDbG9zZScsXHJcbiAgICBtdWx0aXBsZVNlcGFyYXRvcjogJywgJyxcclxuICAgIHN0eWxlQmFzZTogJ2J0bicsXHJcbiAgICBzdHlsZTogJ2J0bi1kZWZhdWx0JyxcclxuICAgIHNpemU6ICdhdXRvJyxcclxuICAgIHRpdGxlOiBudWxsLFxyXG4gICAgc2VsZWN0ZWRUZXh0Rm9ybWF0OiAndmFsdWVzJyxcclxuICAgIHdpZHRoOiBmYWxzZSxcclxuICAgIGNvbnRhaW5lcjogZmFsc2UsXHJcbiAgICBoaWRlRGlzYWJsZWQ6IGZhbHNlLFxyXG4gICAgc2hvd1N1YnRleHQ6IGZhbHNlLFxyXG4gICAgc2hvd0ljb246IHRydWUsXHJcbiAgICBzaG93Q29udGVudDogdHJ1ZSxcclxuICAgIGRyb3B1cEF1dG86IHRydWUsXHJcbiAgICBoZWFkZXI6IGZhbHNlLFxyXG4gICAgbGl2ZVNlYXJjaDogZmFsc2UsXHJcbiAgICBsaXZlU2VhcmNoUGxhY2Vob2xkZXI6IG51bGwsXHJcbiAgICBsaXZlU2VhcmNoTm9ybWFsaXplOiBmYWxzZSxcclxuICAgIGxpdmVTZWFyY2hTdHlsZTogJ2NvbnRhaW5zJyxcclxuICAgIGFjdGlvbnNCb3g6IGZhbHNlLFxyXG4gICAgaWNvbkJhc2U6ICdnbHlwaGljb24nLFxyXG4gICAgdGlja0ljb246ICdnbHlwaGljb24tb2snLFxyXG4gICAgc2hvd1RpY2s6IGZhbHNlLFxyXG4gICAgdGVtcGxhdGU6IHtcclxuICAgICAgY2FyZXQ6ICc8c3BhbiBjbGFzcz1cImNhcmV0XCI+PC9zcGFuPidcclxuICAgIH0sXHJcbiAgICBtYXhPcHRpb25zOiBmYWxzZSxcclxuICAgIG1vYmlsZTogZmFsc2UsXHJcbiAgICBzZWxlY3RPblRhYjogZmFsc2UsXHJcbiAgICBkcm9wZG93bkFsaWduUmlnaHQ6IGZhbHNlLFxyXG4gICAgd2luZG93UGFkZGluZzogMFxyXG4gIH07XHJcblxyXG4gIFNlbGVjdHBpY2tlci5wcm90b3R5cGUgPSB7XHJcblxyXG4gICAgY29uc3RydWN0b3I6IFNlbGVjdHBpY2tlcixcclxuXHJcbiAgICBpbml0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgIGlkID0gdGhpcy4kZWxlbWVudC5hdHRyKCdpZCcpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5hZGRDbGFzcygnYnMtc2VsZWN0LWhpZGRlbicpO1xyXG5cclxuICAgICAgLy8gc3RvcmUgb3JpZ2luYWxJbmRleCAoa2V5KSBhbmQgbmV3SW5kZXggKHZhbHVlKSBpbiB0aGlzLmxpT2JqIGZvciBmYXN0IGFjY2Vzc2liaWxpdHlcclxuICAgICAgLy8gYWxsb3dzIHVzIHRvIGRvIHRoaXMuJGxpcy5lcSh0aGF0LmxpT2JqW2luZGV4XSkgaW5zdGVhZCBvZiB0aGlzLiRsaXMuZmlsdGVyKCdbZGF0YS1vcmlnaW5hbC1pbmRleD1cIicgKyBpbmRleCArICdcIl0nKVxyXG4gICAgICB0aGlzLmxpT2JqID0ge307XHJcbiAgICAgIHRoaXMubXVsdGlwbGUgPSB0aGlzLiRlbGVtZW50LnByb3AoJ211bHRpcGxlJyk7XHJcbiAgICAgIHRoaXMuYXV0b2ZvY3VzID0gdGhpcy4kZWxlbWVudC5wcm9wKCdhdXRvZm9jdXMnKTtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudCA9IHRoaXMuY3JlYXRlVmlldygpO1xyXG4gICAgICB0aGlzLiRlbGVtZW50XHJcbiAgICAgICAgLmFmdGVyKHRoaXMuJG5ld0VsZW1lbnQpXHJcbiAgICAgICAgLmFwcGVuZFRvKHRoaXMuJG5ld0VsZW1lbnQpO1xyXG4gICAgICB0aGlzLiRidXR0b24gPSB0aGlzLiRuZXdFbGVtZW50LmNoaWxkcmVuKCdidXR0b24nKTtcclxuICAgICAgdGhpcy4kbWVudSA9IHRoaXMuJG5ld0VsZW1lbnQuY2hpbGRyZW4oJy5kcm9wZG93bi1tZW51Jyk7XHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lciA9IHRoaXMuJG1lbnUuY2hpbGRyZW4oJy5pbm5lcicpO1xyXG4gICAgICB0aGlzLiRzZWFyY2hib3ggPSB0aGlzLiRtZW51LmZpbmQoJ2lucHV0Jyk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50LnJlbW92ZUNsYXNzKCdicy1zZWxlY3QtaGlkZGVuJyk7XHJcblxyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmRyb3Bkb3duQWxpZ25SaWdodCA9PT0gdHJ1ZSkgdGhpcy4kbWVudS5hZGRDbGFzcygnZHJvcGRvd24tbWVudS1yaWdodCcpO1xyXG5cclxuICAgICAgaWYgKHR5cGVvZiBpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICB0aGlzLiRidXR0b24uYXR0cignZGF0YS1pZCcsIGlkKTtcclxuICAgICAgICAkKCdsYWJlbFtmb3I9XCInICsgaWQgKyAnXCJdJykuY2xpY2soZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLmNoZWNrRGlzYWJsZWQoKTtcclxuICAgICAgdGhpcy5jbGlja0xpc3RlbmVyKCk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaCkgdGhpcy5saXZlU2VhcmNoTGlzdGVuZXIoKTtcclxuICAgICAgdGhpcy5yZW5kZXIoKTtcclxuICAgICAgdGhpcy5zZXRTdHlsZSgpO1xyXG4gICAgICB0aGlzLnNldFdpZHRoKCk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuY29udGFpbmVyKSB0aGlzLnNlbGVjdFBvc2l0aW9uKCk7XHJcbiAgICAgIHRoaXMuJG1lbnUuZGF0YSgndGhpcycsIHRoaXMpO1xyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50LmRhdGEoJ3RoaXMnLCB0aGlzKTtcclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5tb2JpbGUpIHRoaXMubW9iaWxlKCk7XHJcblxyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50Lm9uKHtcclxuICAgICAgICAnaGlkZS5icy5kcm9wZG93bic6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuYXR0cignYXJpYS1leHBhbmRlZCcsIGZhbHNlKTtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignaGlkZS5icy5zZWxlY3QnLCBlKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgICdoaWRkZW4uYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdoaWRkZW4uYnMuc2VsZWN0JywgZSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAnc2hvdy5icy5kcm9wZG93bic6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuYXR0cignYXJpYS1leHBhbmRlZCcsIHRydWUpO1xyXG4gICAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdzaG93LmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgJ3Nob3duLmJzLmRyb3Bkb3duJzogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignc2hvd24uYnMuc2VsZWN0JywgZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGlmICh0aGF0LiRlbGVtZW50WzBdLmhhc0F0dHJpYnV0ZSgncmVxdWlyZWQnKSkge1xyXG4gICAgICAgIHRoaXMuJGVsZW1lbnQub24oJ2ludmFsaWQnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uYWRkQ2xhc3MoJ2JzLWludmFsaWQnKTtcclxuXHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50Lm9uKHtcclxuICAgICAgICAgICAgJ2ZvY3VzLmJzLnNlbGVjdCc6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICAgICAgICB0aGF0LiRlbGVtZW50Lm9mZignZm9jdXMuYnMuc2VsZWN0Jyk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICdzaG93bi5icy5zZWxlY3QnOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudFxyXG4gICAgICAgICAgICAgICAgLnZhbCh0aGF0LiRlbGVtZW50LnZhbCgpKSAvLyBzZXQgdGhlIHZhbHVlIHRvIGhpZGUgdGhlIHZhbGlkYXRpb24gbWVzc2FnZSBpbiBDaHJvbWUgd2hlbiBtZW51IGlzIG9wZW5lZFxyXG4gICAgICAgICAgICAgICAgLm9mZignc2hvd24uYnMuc2VsZWN0Jyk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICdyZW5kZXJlZC5icy5zZWxlY3QnOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgLy8gaWYgc2VsZWN0IGlzIG5vIGxvbmdlciBpbnZhbGlkLCByZW1vdmUgdGhlIGJzLWludmFsaWQgY2xhc3NcclxuICAgICAgICAgICAgICBpZiAodGhpcy52YWxpZGl0eS52YWxpZCkgdGhhdC4kYnV0dG9uLnJlbW92ZUNsYXNzKCdicy1pbnZhbGlkJyk7XHJcbiAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC5vZmYoJ3JlbmRlcmVkLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICB0aGF0LiRidXR0b24ub24oJ2JsdXIuYnMuc2VsZWN0JywgZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQuZm9jdXMoKS5ibHVyKCk7XHJcbiAgICAgICAgICAgIHRoYXQuJGJ1dHRvbi5vZmYoJ2JsdXIuYnMuc2VsZWN0Jyk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdsb2FkZWQuYnMuc2VsZWN0Jyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBjcmVhdGVEcm9wZG93bjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAvLyBPcHRpb25zXHJcbiAgICAgIC8vIElmIHdlIGFyZSBtdWx0aXBsZSBvciBzaG93VGljayBvcHRpb24gaXMgc2V0LCB0aGVuIGFkZCB0aGUgc2hvdy10aWNrIGNsYXNzXHJcbiAgICAgIHZhciBzaG93VGljayA9ICh0aGlzLm11bHRpcGxlIHx8IHRoaXMub3B0aW9ucy5zaG93VGljaykgPyAnIHNob3ctdGljaycgOiAnJyxcclxuICAgICAgICAgIGlucHV0R3JvdXAgPSB0aGlzLiRlbGVtZW50LnBhcmVudCgpLmhhc0NsYXNzKCdpbnB1dC1ncm91cCcpID8gJyBpbnB1dC1ncm91cC1idG4nIDogJycsXHJcbiAgICAgICAgICBhdXRvZm9jdXMgPSB0aGlzLmF1dG9mb2N1cyA/ICcgYXV0b2ZvY3VzJyA6ICcnO1xyXG4gICAgICAvLyBFbGVtZW50c1xyXG4gICAgICB2YXIgaGVhZGVyID0gdGhpcy5vcHRpb25zLmhlYWRlciA/ICc8ZGl2IGNsYXNzPVwicG9wb3Zlci10aXRsZVwiPjxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiY2xvc2VcIiBhcmlhLWhpZGRlbj1cInRydWVcIj4mdGltZXM7PC9idXR0b24+JyArIHRoaXMub3B0aW9ucy5oZWFkZXIgKyAnPC9kaXY+JyA6ICcnO1xyXG4gICAgICB2YXIgc2VhcmNoYm94ID0gdGhpcy5vcHRpb25zLmxpdmVTZWFyY2ggP1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJzLXNlYXJjaGJveFwiPicgK1xyXG4gICAgICAnPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBhdXRvY29tcGxldGU9XCJvZmZcIicgK1xyXG4gICAgICAobnVsbCA9PT0gdGhpcy5vcHRpb25zLmxpdmVTZWFyY2hQbGFjZWhvbGRlciA/ICcnIDogJyBwbGFjZWhvbGRlcj1cIicgKyBodG1sRXNjYXBlKHRoaXMub3B0aW9ucy5saXZlU2VhcmNoUGxhY2Vob2xkZXIpICsgJ1wiJykgKyAnIHJvbGU9XCJ0ZXh0Ym94XCIgYXJpYS1sYWJlbD1cIlNlYXJjaFwiPicgK1xyXG4gICAgICAnPC9kaXY+J1xyXG4gICAgICAgICAgOiAnJztcclxuICAgICAgdmFyIGFjdGlvbnNib3ggPSB0aGlzLm11bHRpcGxlICYmIHRoaXMub3B0aW9ucy5hY3Rpb25zQm94ID9cclxuICAgICAgJzxkaXYgY2xhc3M9XCJicy1hY3Rpb25zYm94XCI+JyArXHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIGJ0bi1ncm91cC1zbSBidG4tYmxvY2tcIj4nICtcclxuICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYWN0aW9ucy1idG4gYnMtc2VsZWN0LWFsbCBidG4gYnRuLWRlZmF1bHRcIj4nICtcclxuICAgICAgdGhpcy5vcHRpb25zLnNlbGVjdEFsbFRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImFjdGlvbnMtYnRuIGJzLWRlc2VsZWN0LWFsbCBidG4gYnRuLWRlZmF1bHRcIj4nICtcclxuICAgICAgdGhpcy5vcHRpb25zLmRlc2VsZWN0QWxsVGV4dCArXHJcbiAgICAgICc8L2J1dHRvbj4nICtcclxuICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAnPC9kaXY+J1xyXG4gICAgICAgICAgOiAnJztcclxuICAgICAgdmFyIGRvbmVidXR0b24gPSB0aGlzLm11bHRpcGxlICYmIHRoaXMub3B0aW9ucy5kb25lQnV0dG9uID9cclxuICAgICAgJzxkaXYgY2xhc3M9XCJicy1kb25lYnV0dG9uXCI+JyArXHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIGJ0bi1ibG9ja1wiPicgK1xyXG4gICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5kb25lQnV0dG9uVGV4dCArXHJcbiAgICAgICc8L2J1dHRvbj4nICtcclxuICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAnPC9kaXY+J1xyXG4gICAgICAgICAgOiAnJztcclxuICAgICAgdmFyIGRyb3AgPVxyXG4gICAgICAgICAgJzxkaXYgY2xhc3M9XCJidG4tZ3JvdXAgYm9vdHN0cmFwLXNlbGVjdCcgKyBzaG93VGljayArIGlucHV0R3JvdXAgKyAnXCI+JyArXHJcbiAgICAgICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCInICsgdGhpcy5vcHRpb25zLnN0eWxlQmFzZSArICcgZHJvcGRvd24tdG9nZ2xlXCIgZGF0YS10b2dnbGU9XCJkcm9wZG93blwiJyArIGF1dG9mb2N1cyArICcgcm9sZT1cImJ1dHRvblwiPicgK1xyXG4gICAgICAgICAgJzxzcGFuIGNsYXNzPVwiZmlsdGVyLW9wdGlvbiBwdWxsLWxlZnRcIj48L3NwYW4+Jm5ic3A7JyArXHJcbiAgICAgICAgICAnPHNwYW4gY2xhc3M9XCJicy1jYXJldFwiPicgK1xyXG4gICAgICAgICAgdGhpcy5vcHRpb25zLnRlbXBsYXRlLmNhcmV0ICtcclxuICAgICAgICAgICc8L3NwYW4+JyArXHJcbiAgICAgICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICAgICAnPGRpdiBjbGFzcz1cImRyb3Bkb3duLW1lbnUgb3BlblwiIHJvbGU9XCJjb21ib2JveFwiPicgK1xyXG4gICAgICAgICAgaGVhZGVyICtcclxuICAgICAgICAgIHNlYXJjaGJveCArXHJcbiAgICAgICAgICBhY3Rpb25zYm94ICtcclxuICAgICAgICAgICc8dWwgY2xhc3M9XCJkcm9wZG93bi1tZW51IGlubmVyXCIgcm9sZT1cImxpc3Rib3hcIiBhcmlhLWV4cGFuZGVkPVwiZmFsc2VcIj4nICtcclxuICAgICAgICAgICc8L3VsPicgK1xyXG4gICAgICAgICAgZG9uZWJ1dHRvbiArXHJcbiAgICAgICAgICAnPC9kaXY+JyArXHJcbiAgICAgICAgICAnPC9kaXY+JztcclxuXHJcbiAgICAgIHJldHVybiAkKGRyb3ApO1xyXG4gICAgfSxcclxuXHJcbiAgICBjcmVhdGVWaWV3OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHZhciAkZHJvcCA9IHRoaXMuY3JlYXRlRHJvcGRvd24oKSxcclxuICAgICAgICAgIGxpID0gdGhpcy5jcmVhdGVMaSgpO1xyXG5cclxuICAgICAgJGRyb3AuZmluZCgndWwnKVswXS5pbm5lckhUTUwgPSBsaTtcclxuICAgICAgcmV0dXJuICRkcm9wO1xyXG4gICAgfSxcclxuXHJcbiAgICByZWxvYWRMaTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAvLyByZWJ1aWxkXHJcbiAgICAgIHZhciBsaSA9IHRoaXMuY3JlYXRlTGkoKTtcclxuICAgICAgdGhpcy4kbWVudUlubmVyWzBdLmlubmVySFRNTCA9IGxpO1xyXG4gICAgfSxcclxuXHJcbiAgICBjcmVhdGVMaTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICBfbGkgPSBbXSxcclxuICAgICAgICAgIG9wdElEID0gMCxcclxuICAgICAgICAgIHRpdGxlT3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb3B0aW9uJyksXHJcbiAgICAgICAgICBsaUluZGV4ID0gLTE7IC8vIGluY3JlbWVudCBsaUluZGV4IHdoZW5ldmVyIGEgbmV3IDxsaT4gZWxlbWVudCBpcyBjcmVhdGVkIHRvIGVuc3VyZSBsaU9iaiBpcyBjb3JyZWN0XHJcblxyXG4gICAgICAvLyBIZWxwZXIgZnVuY3Rpb25zXHJcbiAgICAgIC8qKlxyXG4gICAgICAgKiBAcGFyYW0gY29udGVudFxyXG4gICAgICAgKiBAcGFyYW0gW2luZGV4XVxyXG4gICAgICAgKiBAcGFyYW0gW2NsYXNzZXNdXHJcbiAgICAgICAqIEBwYXJhbSBbb3B0Z3JvdXBdXHJcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAgICAgICAqL1xyXG4gICAgICB2YXIgZ2VuZXJhdGVMSSA9IGZ1bmN0aW9uIChjb250ZW50LCBpbmRleCwgY2xhc3Nlcywgb3B0Z3JvdXApIHtcclxuICAgICAgICByZXR1cm4gJzxsaScgK1xyXG4gICAgICAgICAgICAoKHR5cGVvZiBjbGFzc2VzICE9PSAndW5kZWZpbmVkJyAmJiAnJyAhPT0gY2xhc3NlcykgPyAnIGNsYXNzPVwiJyArIGNsYXNzZXMgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKCh0eXBlb2YgaW5kZXggIT09ICd1bmRlZmluZWQnICYmIG51bGwgIT09IGluZGV4KSA/ICcgZGF0YS1vcmlnaW5hbC1pbmRleD1cIicgKyBpbmRleCArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAoKHR5cGVvZiBvcHRncm91cCAhPT0gJ3VuZGVmaW5lZCcgJiYgbnVsbCAhPT0gb3B0Z3JvdXApID8gJ2RhdGEtb3B0Z3JvdXA9XCInICsgb3B0Z3JvdXAgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgJz4nICsgY29udGVudCArICc8L2xpPic7XHJcbiAgICAgIH07XHJcblxyXG4gICAgICAvKipcclxuICAgICAgICogQHBhcmFtIHRleHRcclxuICAgICAgICogQHBhcmFtIFtjbGFzc2VzXVxyXG4gICAgICAgKiBAcGFyYW0gW2lubGluZV1cclxuICAgICAgICogQHBhcmFtIFt0b2tlbnNdXHJcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAgICAgICAqL1xyXG4gICAgICB2YXIgZ2VuZXJhdGVBID0gZnVuY3Rpb24gKHRleHQsIGNsYXNzZXMsIGlubGluZSwgdG9rZW5zKSB7XHJcbiAgICAgICAgcmV0dXJuICc8YSB0YWJpbmRleD1cIjBcIicgK1xyXG4gICAgICAgICAgICAodHlwZW9mIGNsYXNzZXMgIT09ICd1bmRlZmluZWQnID8gJyBjbGFzcz1cIicgKyBjbGFzc2VzICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgIChpbmxpbmUgPyAnIHN0eWxlPVwiJyArIGlubGluZSArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2hOb3JtYWxpemUgPyAnIGRhdGEtbm9ybWFsaXplZC10ZXh0PVwiJyArIG5vcm1hbGl6ZVRvQmFzZShodG1sRXNjYXBlKCQodGV4dCkuaHRtbCgpKSkgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKHR5cGVvZiB0b2tlbnMgIT09ICd1bmRlZmluZWQnIHx8IHRva2VucyAhPT0gbnVsbCA/ICcgZGF0YS10b2tlbnM9XCInICsgdG9rZW5zICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICcgcm9sZT1cIm9wdGlvblwiPicgKyB0ZXh0ICtcclxuICAgICAgICAgICAgJzxzcGFuIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArIHRoYXQub3B0aW9ucy50aWNrSWNvbiArICcgY2hlY2stbWFya1wiPjwvc3Bhbj4nICtcclxuICAgICAgICAgICAgJzwvYT4nO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSAmJiAhdGhpcy5tdWx0aXBsZSkge1xyXG4gICAgICAgIC8vIHRoaXMgb3B0aW9uIGRvZXNuJ3QgY3JlYXRlIGEgbmV3IDxsaT4gZWxlbWVudCwgYnV0IGRvZXMgYWRkIGEgbmV3IG9wdGlvbiwgc28gbGlJbmRleCBpcyBkZWNyZWFzZWRcclxuICAgICAgICAvLyBzaW5jZSBsaU9iaiBpcyByZWNhbGN1bGF0ZWQgb24gZXZlcnkgcmVmcmVzaCwgbGlJbmRleCBuZWVkcyB0byBiZSBkZWNyZWFzZWQgZXZlbiBpZiB0aGUgdGl0bGVPcHRpb24gaXMgYWxyZWFkeSBhcHBlbmRlZFxyXG4gICAgICAgIGxpSW5kZXgtLTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLiRlbGVtZW50LmZpbmQoJy5icy10aXRsZS1vcHRpb24nKS5sZW5ndGgpIHtcclxuICAgICAgICAgIC8vIFVzZSBuYXRpdmUgSlMgdG8gcHJlcGVuZCBvcHRpb24gKGZhc3RlcilcclxuICAgICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy4kZWxlbWVudFswXTtcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLmNsYXNzTmFtZSA9ICdicy10aXRsZS1vcHRpb24nO1xyXG4gICAgICAgICAgdGl0bGVPcHRpb24uaW5uZXJIVE1MID0gdGhpcy5vcHRpb25zLnRpdGxlO1xyXG4gICAgICAgICAgdGl0bGVPcHRpb24udmFsdWUgPSAnJztcclxuICAgICAgICAgIGVsZW1lbnQuaW5zZXJ0QmVmb3JlKHRpdGxlT3B0aW9uLCBlbGVtZW50LmZpcnN0Q2hpbGQpO1xyXG4gICAgICAgICAgLy8gQ2hlY2sgaWYgc2VsZWN0ZWQgb3IgZGF0YS1zZWxlY3RlZCBhdHRyaWJ1dGUgaXMgYWxyZWFkeSBzZXQgb24gYW4gb3B0aW9uLiBJZiBub3QsIHNlbGVjdCB0aGUgdGl0bGVPcHRpb24gb3B0aW9uLlxyXG4gICAgICAgICAgLy8gdGhlIHNlbGVjdGVkIGl0ZW0gbWF5IGhhdmUgYmVlbiBjaGFuZ2VkIGJ5IHVzZXIgb3IgcHJvZ3JhbW1hdGljYWxseSBiZWZvcmUgdGhlIGJvb3RzdHJhcCBzZWxlY3QgcGx1Z2luIHJ1bnMsXHJcbiAgICAgICAgICAvLyBpZiBzbywgdGhlIHNlbGVjdCB3aWxsIGhhdmUgdGhlIGRhdGEtc2VsZWN0ZWQgYXR0cmlidXRlXHJcbiAgICAgICAgICB2YXIgJG9wdCA9ICQoZWxlbWVudC5vcHRpb25zW2VsZW1lbnQuc2VsZWN0ZWRJbmRleF0pO1xyXG4gICAgICAgICAgaWYgKCRvcHQuYXR0cignc2VsZWN0ZWQnKSA9PT0gdW5kZWZpbmVkICYmIHRoaXMuJGVsZW1lbnQuZGF0YSgnc2VsZWN0ZWQnKSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHRpdGxlT3B0aW9uLnNlbGVjdGVkID0gdHJ1ZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHZhciAkc2VsZWN0T3B0aW9ucyA9IHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJyk7XHJcblxyXG4gICAgICAkc2VsZWN0T3B0aW9ucy5lYWNoKGZ1bmN0aW9uIChpbmRleCkge1xyXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XHJcblxyXG4gICAgICAgIGxpSW5kZXgrKztcclxuXHJcbiAgICAgICAgaWYgKCR0aGlzLmhhc0NsYXNzKCdicy10aXRsZS1vcHRpb24nKSkgcmV0dXJuO1xyXG5cclxuICAgICAgICAvLyBHZXQgdGhlIGNsYXNzIGFuZCB0ZXh0IGZvciB0aGUgb3B0aW9uXHJcbiAgICAgICAgdmFyIG9wdGlvbkNsYXNzID0gdGhpcy5jbGFzc05hbWUgfHwgJycsXHJcbiAgICAgICAgICAgIGlubGluZSA9IGh0bWxFc2NhcGUodGhpcy5zdHlsZS5jc3NUZXh0KSxcclxuICAgICAgICAgICAgdGV4dCA9ICR0aGlzLmRhdGEoJ2NvbnRlbnQnKSA/ICR0aGlzLmRhdGEoJ2NvbnRlbnQnKSA6ICR0aGlzLmh0bWwoKSxcclxuICAgICAgICAgICAgdG9rZW5zID0gJHRoaXMuZGF0YSgndG9rZW5zJykgPyAkdGhpcy5kYXRhKCd0b2tlbnMnKSA6IG51bGwsXHJcbiAgICAgICAgICAgIHN1YnRleHQgPSB0eXBlb2YgJHRoaXMuZGF0YSgnc3VidGV4dCcpICE9PSAndW5kZWZpbmVkJyA/ICc8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JyArICR0aGlzLmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPicgOiAnJyxcclxuICAgICAgICAgICAgaWNvbiA9IHR5cGVvZiAkdGhpcy5kYXRhKCdpY29uJykgIT09ICd1bmRlZmluZWQnID8gJzxzcGFuIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArICR0aGlzLmRhdGEoJ2ljb24nKSArICdcIj48L3NwYW4+ICcgOiAnJyxcclxuICAgICAgICAgICAgJHBhcmVudCA9ICR0aGlzLnBhcmVudCgpLFxyXG4gICAgICAgICAgICBpc09wdGdyb3VwID0gJHBhcmVudFswXS50YWdOYW1lID09PSAnT1BUR1JPVVAnLFxyXG4gICAgICAgICAgICBpc09wdGdyb3VwRGlzYWJsZWQgPSBpc09wdGdyb3VwICYmICRwYXJlbnRbMF0uZGlzYWJsZWQsXHJcbiAgICAgICAgICAgIGlzRGlzYWJsZWQgPSB0aGlzLmRpc2FibGVkIHx8IGlzT3B0Z3JvdXBEaXNhYmxlZCxcclxuICAgICAgICAgICAgcHJldkhpZGRlbkluZGV4O1xyXG5cclxuICAgICAgICBpZiAoaWNvbiAhPT0gJycgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgaWNvbiA9ICc8c3Bhbj4nICsgaWNvbiArICc8L3NwYW4+JztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuaGlkZURpc2FibGVkICYmIChpc0Rpc2FibGVkICYmICFpc09wdGdyb3VwIHx8IGlzT3B0Z3JvdXBEaXNhYmxlZCkpIHtcclxuICAgICAgICAgIC8vIHNldCBwcmV2SGlkZGVuSW5kZXggLSB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGhpZGRlbiBvcHRpb24gaW4gYSBncm91cCBvZiBoaWRkZW4gb3B0aW9uc1xyXG4gICAgICAgICAgLy8gdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgYSBkaXZpZGVyIHNob3VsZCBiZSBwbGFjZWQgYWZ0ZXIgYW4gb3B0Z3JvdXAgaWYgdGhlcmUgYXJlXHJcbiAgICAgICAgICAvLyBoaWRkZW4gb3B0aW9ucyBiZXR3ZWVuIHRoZSBvcHRncm91cCBhbmQgdGhlIGZpcnN0IHZpc2libGUgb3B0aW9uXHJcbiAgICAgICAgICBwcmV2SGlkZGVuSW5kZXggPSAkdGhpcy5kYXRhKCdwcmV2SGlkZGVuSW5kZXgnKTtcclxuICAgICAgICAgICR0aGlzLm5leHQoKS5kYXRhKCdwcmV2SGlkZGVuSW5kZXgnLCAocHJldkhpZGRlbkluZGV4ICE9PSB1bmRlZmluZWQgPyBwcmV2SGlkZGVuSW5kZXggOiBpbmRleCkpO1xyXG5cclxuICAgICAgICAgIGxpSW5kZXgtLTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghJHRoaXMuZGF0YSgnY29udGVudCcpKSB7XHJcbiAgICAgICAgICAvLyBQcmVwZW5kIGFueSBpY29uIGFuZCBhcHBlbmQgYW55IHN1YnRleHQgdG8gdGhlIG1haW4gdGV4dC5cclxuICAgICAgICAgIHRleHQgPSBpY29uICsgJzxzcGFuIGNsYXNzPVwidGV4dFwiPicgKyB0ZXh0ICsgc3VidGV4dCArICc8L3NwYW4+JztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChpc09wdGdyb3VwICYmICR0aGlzLmRhdGEoJ2RpdmlkZXInKSAhPT0gdHJ1ZSkge1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5kYXRhKCdhbGxPcHRpb25zRGlzYWJsZWQnKSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgdmFyICRvcHRpb25zID0gJHBhcmVudC5jaGlsZHJlbigpO1xyXG4gICAgICAgICAgICAgICRwYXJlbnQuZGF0YSgnYWxsT3B0aW9uc0Rpc2FibGVkJywgJG9wdGlvbnMuZmlsdGVyKCc6ZGlzYWJsZWQnKS5sZW5ndGggPT09ICRvcHRpb25zLmxlbmd0aCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICgkcGFyZW50LmRhdGEoJ2FsbE9wdGlvbnNEaXNhYmxlZCcpKSB7XHJcbiAgICAgICAgICAgICAgbGlJbmRleC0tO1xyXG4gICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHZhciBvcHRHcm91cENsYXNzID0gJyAnICsgJHBhcmVudFswXS5jbGFzc05hbWUgfHwgJyc7XHJcblxyXG4gICAgICAgICAgaWYgKCR0aGlzLmluZGV4KCkgPT09IDApIHsgLy8gSXMgaXQgdGhlIGZpcnN0IG9wdGlvbiBvZiB0aGUgb3B0Z3JvdXA/XHJcbiAgICAgICAgICAgIG9wdElEICs9IDE7XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgdGhlIG9wdCBncm91cCBsYWJlbFxyXG4gICAgICAgICAgICB2YXIgbGFiZWwgPSAkcGFyZW50WzBdLmxhYmVsLFxyXG4gICAgICAgICAgICAgICAgbGFiZWxTdWJ0ZXh0ID0gdHlwZW9mICRwYXJlbnQuZGF0YSgnc3VidGV4dCcpICE9PSAndW5kZWZpbmVkJyA/ICc8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JyArICRwYXJlbnQuZGF0YSgnc3VidGV4dCcpICsgJzwvc21hbGw+JyA6ICcnLFxyXG4gICAgICAgICAgICAgICAgbGFiZWxJY29uID0gJHBhcmVudC5kYXRhKCdpY29uJykgPyAnPHNwYW4gY2xhc3M9XCInICsgdGhhdC5vcHRpb25zLmljb25CYXNlICsgJyAnICsgJHBhcmVudC5kYXRhKCdpY29uJykgKyAnXCI+PC9zcGFuPiAnIDogJyc7XHJcblxyXG4gICAgICAgICAgICBsYWJlbCA9IGxhYmVsSWNvbiArICc8c3BhbiBjbGFzcz1cInRleHRcIj4nICsgaHRtbEVzY2FwZShsYWJlbCkgKyBsYWJlbFN1YnRleHQgKyAnPC9zcGFuPic7XHJcblxyXG4gICAgICAgICAgICBpZiAoaW5kZXggIT09IDAgJiYgX2xpLmxlbmd0aCA+IDApIHsgLy8gSXMgaXQgTk9UIHRoZSBmaXJzdCBvcHRpb24gb2YgdGhlIHNlbGVjdCAmJiBhcmUgdGhlcmUgZWxlbWVudHMgaW4gdGhlIGRyb3Bkb3duP1xyXG4gICAgICAgICAgICAgIGxpSW5kZXgrKztcclxuICAgICAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKCcnLCBudWxsLCAnZGl2aWRlcicsIG9wdElEICsgJ2RpdicpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBsaUluZGV4Kys7XHJcbiAgICAgICAgICAgIF9saS5wdXNoKGdlbmVyYXRlTEkobGFiZWwsIG51bGwsICdkcm9wZG93bi1oZWFkZXInICsgb3B0R3JvdXBDbGFzcywgb3B0SUQpKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiBpc0Rpc2FibGVkKSB7XHJcbiAgICAgICAgICAgIGxpSW5kZXgtLTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIF9saS5wdXNoKGdlbmVyYXRlTEkoZ2VuZXJhdGVBKHRleHQsICdvcHQgJyArIG9wdGlvbkNsYXNzICsgb3B0R3JvdXBDbGFzcywgaW5saW5lLCB0b2tlbnMpLCBpbmRleCwgJycsIG9wdElEKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdkaXZpZGVyJykgPT09IHRydWUpIHtcclxuICAgICAgICAgIF9saS5wdXNoKGdlbmVyYXRlTEkoJycsIGluZGV4LCAnZGl2aWRlcicpKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCR0aGlzLmRhdGEoJ2hpZGRlbicpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAvLyBzZXQgcHJldkhpZGRlbkluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBoaWRkZW4gb3B0aW9uIGluIGEgZ3JvdXAgb2YgaGlkZGVuIG9wdGlvbnNcclxuICAgICAgICAgIC8vIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IGEgZGl2aWRlciBzaG91bGQgYmUgcGxhY2VkIGFmdGVyIGFuIG9wdGdyb3VwIGlmIHRoZXJlIGFyZVxyXG4gICAgICAgICAgLy8gaGlkZGVuIG9wdGlvbnMgYmV0d2VlbiB0aGUgb3B0Z3JvdXAgYW5kIHRoZSBmaXJzdCB2aXNpYmxlIG9wdGlvblxyXG4gICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcbiAgICAgICAgICAkdGhpcy5uZXh0KCkuZGF0YSgncHJldkhpZGRlbkluZGV4JywgKHByZXZIaWRkZW5JbmRleCAhPT0gdW5kZWZpbmVkID8gcHJldkhpZGRlbkluZGV4IDogaW5kZXgpKTtcclxuXHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCBvcHRpb25DbGFzcywgaW5saW5lLCB0b2tlbnMpLCBpbmRleCwgJ2hpZGRlbiBpcy1oaWRkZW4nKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHZhciBzaG93RGl2aWRlciA9IHRoaXMucHJldmlvdXNFbGVtZW50U2libGluZyAmJiB0aGlzLnByZXZpb3VzRWxlbWVudFNpYmxpbmcudGFnTmFtZSA9PT0gJ09QVEdST1VQJztcclxuXHJcbiAgICAgICAgICAvLyBpZiBwcmV2aW91cyBlbGVtZW50IGlzIG5vdCBhbiBvcHRncm91cCBhbmQgaGlkZURpc2FibGVkIGlzIHRydWVcclxuICAgICAgICAgIGlmICghc2hvd0RpdmlkZXIgJiYgdGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBwcmV2SGlkZGVuSW5kZXggPSAkdGhpcy5kYXRhKCdwcmV2SGlkZGVuSW5kZXgnKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChwcmV2SGlkZGVuSW5kZXggIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIC8vIHNlbGVjdCB0aGUgZWxlbWVudCAqKmJlZm9yZSoqIHRoZSBmaXJzdCBoaWRkZW4gZWxlbWVudCBpbiB0aGUgZ3JvdXBcclxuICAgICAgICAgICAgICB2YXIgcHJldkhpZGRlbiA9ICRzZWxlY3RPcHRpb25zLmVxKHByZXZIaWRkZW5JbmRleClbMF0ucHJldmlvdXNFbGVtZW50U2libGluZztcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICBpZiAocHJldkhpZGRlbiAmJiBwcmV2SGlkZGVuLnRhZ05hbWUgPT09ICdPUFRHUk9VUCcgJiYgIXByZXZIaWRkZW4uZGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgICAgIHNob3dEaXZpZGVyID0gdHJ1ZTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAoc2hvd0RpdmlkZXIpIHtcclxuICAgICAgICAgICAgbGlJbmRleCsrO1xyXG4gICAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKCcnLCBudWxsLCAnZGl2aWRlcicsIG9wdElEICsgJ2RpdicpKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIF9saS5wdXNoKGdlbmVyYXRlTEkoZ2VuZXJhdGVBKHRleHQsIG9wdGlvbkNsYXNzLCBpbmxpbmUsIHRva2VucyksIGluZGV4KSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGF0LmxpT2JqW2luZGV4XSA9IGxpSW5kZXg7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy9JZiB3ZSBhcmUgbm90IG11bHRpcGxlLCB3ZSBkb24ndCBoYXZlIGEgc2VsZWN0ZWQgaXRlbSwgYW5kIHdlIGRvbid0IGhhdmUgYSB0aXRsZSwgc2VsZWN0IHRoZSBmaXJzdCBlbGVtZW50IHNvIHNvbWV0aGluZyBpcyBzZXQgaW4gdGhlIGJ1dHRvblxyXG4gICAgICBpZiAoIXRoaXMubXVsdGlwbGUgJiYgdGhpcy4kZWxlbWVudC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5sZW5ndGggPT09IDAgJiYgIXRoaXMub3B0aW9ucy50aXRsZSkge1xyXG4gICAgICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJykuZXEoMCkucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKS5hdHRyKCdzZWxlY3RlZCcsICdzZWxlY3RlZCcpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gX2xpLmpvaW4oJycpO1xyXG4gICAgfSxcclxuXHJcbiAgICBmaW5kTGlzOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGlmICh0aGlzLiRsaXMgPT0gbnVsbCkgdGhpcy4kbGlzID0gdGhpcy4kbWVudS5maW5kKCdsaScpO1xyXG4gICAgICByZXR1cm4gdGhpcy4kbGlzO1xyXG4gICAgfSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSBbdXBkYXRlTGldIGRlZmF1bHRzIHRvIHRydWVcclxuICAgICAqL1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAodXBkYXRlTGkpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgbm90RGlzYWJsZWQsXHJcbiAgICAgICAgICAkc2VsZWN0T3B0aW9ucyA9IHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJyk7XHJcblxyXG4gICAgICAvL1VwZGF0ZSB0aGUgTEkgdG8gbWF0Y2ggdGhlIFNFTEVDVFxyXG4gICAgICBpZiAodXBkYXRlTGkgIT09IGZhbHNlKSB7XHJcbiAgICAgICAgJHNlbGVjdE9wdGlvbnMuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICAgIHZhciAkbGlzID0gdGhhdC5maW5kTGlzKCkuZXEodGhhdC5saU9ialtpbmRleF0pO1xyXG5cclxuICAgICAgICAgIHRoYXQuc2V0RGlzYWJsZWQoaW5kZXgsIHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5wYXJlbnROb2RlLnRhZ05hbWUgPT09ICdPUFRHUk9VUCcgJiYgdGhpcy5wYXJlbnROb2RlLmRpc2FibGVkLCAkbGlzKTtcclxuICAgICAgICAgIHRoYXQuc2V0U2VsZWN0ZWQoaW5kZXgsIHRoaXMuc2VsZWN0ZWQsICRsaXMpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7XHJcblxyXG4gICAgICB0aGlzLnRhYkluZGV4KCk7XHJcblxyXG4gICAgICB2YXIgc2VsZWN0ZWRJdGVtcyA9ICRzZWxlY3RPcHRpb25zLm1hcChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWQpIHtcclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuaGlkZURpc2FibGVkICYmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMucGFyZW50Tm9kZS50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmIHRoaXMucGFyZW50Tm9kZS5kaXNhYmxlZCkpIHJldHVybjtcclxuXHJcbiAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpLFxyXG4gICAgICAgICAgICAgIGljb24gPSAkdGhpcy5kYXRhKCdpY29uJykgJiYgdGhhdC5vcHRpb25zLnNob3dJY29uID8gJzxpIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArICR0aGlzLmRhdGEoJ2ljb24nKSArICdcIj48L2k+ICcgOiAnJyxcclxuICAgICAgICAgICAgICBzdWJ0ZXh0O1xyXG5cclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuc2hvd1N1YnRleHQgJiYgJHRoaXMuZGF0YSgnc3VidGV4dCcpICYmICF0aGF0Lm11bHRpcGxlKSB7XHJcbiAgICAgICAgICAgIHN1YnRleHQgPSAnIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWRcIj4nICsgJHRoaXMuZGF0YSgnc3VidGV4dCcpICsgJzwvc21hbGw+JztcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHN1YnRleHQgPSAnJztcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmICh0eXBlb2YgJHRoaXMuYXR0cigndGl0bGUnKSAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgcmV0dXJuICR0aGlzLmF0dHIoJ3RpdGxlJyk7XHJcbiAgICAgICAgICB9IGVsc2UgaWYgKCR0aGlzLmRhdGEoJ2NvbnRlbnQnKSAmJiB0aGF0Lm9wdGlvbnMuc2hvd0NvbnRlbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuICR0aGlzLmRhdGEoJ2NvbnRlbnQnKS50b1N0cmluZygpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIGljb24gKyAkdGhpcy5odG1sKCkgKyBzdWJ0ZXh0O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSkudG9BcnJheSgpO1xyXG5cclxuICAgICAgLy9GaXhlcyBpc3N1ZSBpbiBJRTEwIG9jY3VycmluZyB3aGVuIG5vIGRlZmF1bHQgb3B0aW9uIGlzIHNlbGVjdGVkIGFuZCBhdCBsZWFzdCBvbmUgb3B0aW9uIGlzIGRpc2FibGVkXHJcbiAgICAgIC8vQ29udmVydCBhbGwgdGhlIHZhbHVlcyBpbnRvIGEgY29tbWEgZGVsaW1pdGVkIHN0cmluZ1xyXG4gICAgICB2YXIgdGl0bGUgPSAhdGhpcy5tdWx0aXBsZSA/IHNlbGVjdGVkSXRlbXNbMF0gOiBzZWxlY3RlZEl0ZW1zLmpvaW4odGhpcy5vcHRpb25zLm11bHRpcGxlU2VwYXJhdG9yKTtcclxuXHJcbiAgICAgIC8vSWYgdGhpcyBpcyBtdWx0aSBzZWxlY3QsIGFuZCB0aGUgc2VsZWN0VGV4dCB0eXBlIGlzIGNvdW50LCB0aGUgc2hvdyAxIG9mIDIgc2VsZWN0ZWQgZXRjLi5cclxuICAgICAgaWYgKHRoaXMubXVsdGlwbGUgJiYgdGhpcy5vcHRpb25zLnNlbGVjdGVkVGV4dEZvcm1hdC5pbmRleE9mKCdjb3VudCcpID4gLTEpIHtcclxuICAgICAgICB2YXIgbWF4ID0gdGhpcy5vcHRpb25zLnNlbGVjdGVkVGV4dEZvcm1hdC5zcGxpdCgnPicpO1xyXG4gICAgICAgIGlmICgobWF4Lmxlbmd0aCA+IDEgJiYgc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiBtYXhbMV0pIHx8IChtYXgubGVuZ3RoID09IDEgJiYgc2VsZWN0ZWRJdGVtcy5sZW5ndGggPj0gMikpIHtcclxuICAgICAgICAgIG5vdERpc2FibGVkID0gdGhpcy5vcHRpb25zLmhpZGVEaXNhYmxlZCA/ICcsIFtkaXNhYmxlZF0nIDogJyc7XHJcbiAgICAgICAgICB2YXIgdG90YWxDb3VudCA9ICRzZWxlY3RPcHRpb25zLm5vdCgnW2RhdGEtZGl2aWRlcj1cInRydWVcIl0sIFtkYXRhLWhpZGRlbj1cInRydWVcIl0nICsgbm90RGlzYWJsZWQpLmxlbmd0aCxcclxuICAgICAgICAgICAgICB0cjhuVGV4dCA9ICh0eXBlb2YgdGhpcy5vcHRpb25zLmNvdW50U2VsZWN0ZWRUZXh0ID09PSAnZnVuY3Rpb24nKSA/IHRoaXMub3B0aW9ucy5jb3VudFNlbGVjdGVkVGV4dChzZWxlY3RlZEl0ZW1zLmxlbmd0aCwgdG90YWxDb3VudCkgOiB0aGlzLm9wdGlvbnMuY291bnRTZWxlY3RlZFRleHQ7XHJcbiAgICAgICAgICB0aXRsZSA9IHRyOG5UZXh0LnJlcGxhY2UoJ3swfScsIHNlbGVjdGVkSXRlbXMubGVuZ3RoLnRvU3RyaW5nKCkpLnJlcGxhY2UoJ3sxfScsIHRvdGFsQ291bnQudG9TdHJpbmcoKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnRpdGxlID09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHRoaXMub3B0aW9ucy50aXRsZSA9IHRoaXMuJGVsZW1lbnQuYXR0cigndGl0bGUnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQgPT0gJ3N0YXRpYycpIHtcclxuICAgICAgICB0aXRsZSA9IHRoaXMub3B0aW9ucy50aXRsZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy9JZiB3ZSBkb250IGhhdmUgYSB0aXRsZSwgdGhlbiB1c2UgdGhlIGRlZmF1bHQsIG9yIGlmIG5vdGhpbmcgaXMgc2V0IGF0IGFsbCwgdXNlIHRoZSBub3Qgc2VsZWN0ZWQgdGV4dFxyXG4gICAgICBpZiAoIXRpdGxlKSB7XHJcbiAgICAgICAgdGl0bGUgPSB0eXBlb2YgdGhpcy5vcHRpb25zLnRpdGxlICE9PSAndW5kZWZpbmVkJyA/IHRoaXMub3B0aW9ucy50aXRsZSA6IHRoaXMub3B0aW9ucy5ub25lU2VsZWN0ZWRUZXh0O1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL3N0cmlwIGFsbCBIVE1MIHRhZ3MgYW5kIHRyaW0gdGhlIHJlc3VsdCwgdGhlbiB1bmVzY2FwZSBhbnkgZXNjYXBlZCB0YWdzXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5hdHRyKCd0aXRsZScsIGh0bWxVbmVzY2FwZSgkLnRyaW0odGl0bGUucmVwbGFjZSgvPFtePl0qPj8vZywgJycpKSkpO1xyXG4gICAgICB0aGlzLiRidXR0b24uY2hpbGRyZW4oJy5maWx0ZXItb3B0aW9uJykuaHRtbCh0aXRsZSk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ3JlbmRlcmVkLmJzLnNlbGVjdCcpO1xyXG4gICAgfSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSBbc3R5bGVdXHJcbiAgICAgKiBAcGFyYW0gW3N0YXR1c11cclxuICAgICAqL1xyXG4gICAgc2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSwgc3RhdHVzKSB7XHJcbiAgICAgIGlmICh0aGlzLiRlbGVtZW50LmF0dHIoJ2NsYXNzJykpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmFkZENsYXNzKHRoaXMuJGVsZW1lbnQuYXR0cignY2xhc3MnKS5yZXBsYWNlKC9zZWxlY3RwaWNrZXJ8bW9iaWxlLWRldmljZXxicy1zZWxlY3QtaGlkZGVufHZhbGlkYXRlXFxbLipcXF0vZ2ksICcnKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHZhciBidXR0b25DbGFzcyA9IHN0eWxlID8gc3R5bGUgOiB0aGlzLm9wdGlvbnMuc3R5bGU7XHJcblxyXG4gICAgICBpZiAoc3RhdHVzID09ICdhZGQnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmFkZENsYXNzKGJ1dHRvbkNsYXNzKTtcclxuICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT0gJ3JlbW92ZScpIHtcclxuICAgICAgICB0aGlzLiRidXR0b24ucmVtb3ZlQ2xhc3MoYnV0dG9uQ2xhc3MpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuc3R5bGUpO1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcyhidXR0b25DbGFzcyk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgbGlIZWlnaHQ6IGZ1bmN0aW9uIChyZWZyZXNoKSB7XHJcbiAgICAgIGlmICghcmVmcmVzaCAmJiAodGhpcy5vcHRpb25zLnNpemUgPT09IGZhbHNlIHx8IHRoaXMuc2l6ZUluZm8pKSByZXR1cm47XHJcblxyXG4gICAgICB2YXIgbmV3RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxyXG4gICAgICAgICAgbWVudSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxyXG4gICAgICAgICAgbWVudUlubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndWwnKSxcclxuICAgICAgICAgIGRpdmlkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpLFxyXG4gICAgICAgICAgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpLFxyXG4gICAgICAgICAgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKSxcclxuICAgICAgICAgIHRleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksXHJcbiAgICAgICAgICBoZWFkZXIgPSB0aGlzLm9wdGlvbnMuaGVhZGVyICYmIHRoaXMuJG1lbnUuZmluZCgnLnBvcG92ZXItdGl0bGUnKS5sZW5ndGggPiAwID8gdGhpcy4kbWVudS5maW5kKCcucG9wb3Zlci10aXRsZScpWzBdLmNsb25lTm9kZSh0cnVlKSA6IG51bGwsXHJcbiAgICAgICAgICBzZWFyY2ggPSB0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaCA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpIDogbnVsbCxcclxuICAgICAgICAgIGFjdGlvbnMgPSB0aGlzLm9wdGlvbnMuYWN0aW9uc0JveCAmJiB0aGlzLm11bHRpcGxlICYmIHRoaXMuJG1lbnUuZmluZCgnLmJzLWFjdGlvbnNib3gnKS5sZW5ndGggPiAwID8gdGhpcy4kbWVudS5maW5kKCcuYnMtYWN0aW9uc2JveCcpWzBdLmNsb25lTm9kZSh0cnVlKSA6IG51bGwsXHJcbiAgICAgICAgICBkb25lQnV0dG9uID0gdGhpcy5vcHRpb25zLmRvbmVCdXR0b24gJiYgdGhpcy5tdWx0aXBsZSAmJiB0aGlzLiRtZW51LmZpbmQoJy5icy1kb25lYnV0dG9uJykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLmJzLWRvbmVidXR0b24nKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsO1xyXG5cclxuICAgICAgdGV4dC5jbGFzc05hbWUgPSAndGV4dCc7XHJcbiAgICAgIG5ld0VsZW1lbnQuY2xhc3NOYW1lID0gdGhpcy4kbWVudVswXS5wYXJlbnROb2RlLmNsYXNzTmFtZSArICcgb3Blbic7XHJcbiAgICAgIG1lbnUuY2xhc3NOYW1lID0gJ2Ryb3Bkb3duLW1lbnUgb3Blbic7XHJcbiAgICAgIG1lbnVJbm5lci5jbGFzc05hbWUgPSAnZHJvcGRvd24tbWVudSBpbm5lcic7XHJcbiAgICAgIGRpdmlkZXIuY2xhc3NOYW1lID0gJ2RpdmlkZXInO1xyXG5cclxuICAgICAgdGV4dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnSW5uZXIgdGV4dCcpKTtcclxuICAgICAgYS5hcHBlbmRDaGlsZCh0ZXh0KTtcclxuICAgICAgbGkuYXBwZW5kQ2hpbGQoYSk7XHJcbiAgICAgIG1lbnVJbm5lci5hcHBlbmRDaGlsZChsaSk7XHJcbiAgICAgIG1lbnVJbm5lci5hcHBlbmRDaGlsZChkaXZpZGVyKTtcclxuICAgICAgaWYgKGhlYWRlcikgbWVudS5hcHBlbmRDaGlsZChoZWFkZXIpO1xyXG4gICAgICBpZiAoc2VhcmNoKSB7XHJcbiAgICAgICAgdmFyIGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcclxuICAgICAgICBzZWFyY2guY2xhc3NOYW1lID0gJ2JzLXNlYXJjaGJveCc7XHJcbiAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gJ2Zvcm0tY29udHJvbCc7XHJcbiAgICAgICAgc2VhcmNoLmFwcGVuZENoaWxkKGlucHV0KTtcclxuICAgICAgICBtZW51LmFwcGVuZENoaWxkKHNlYXJjaCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGFjdGlvbnMpIG1lbnUuYXBwZW5kQ2hpbGQoYWN0aW9ucyk7XHJcbiAgICAgIG1lbnUuYXBwZW5kQ2hpbGQobWVudUlubmVyKTtcclxuICAgICAgaWYgKGRvbmVCdXR0b24pIG1lbnUuYXBwZW5kQ2hpbGQoZG9uZUJ1dHRvbik7XHJcbiAgICAgIG5ld0VsZW1lbnQuYXBwZW5kQ2hpbGQobWVudSk7XHJcblxyXG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgdmFyIGxpSGVpZ2h0ID0gYS5vZmZzZXRIZWlnaHQsXHJcbiAgICAgICAgICBoZWFkZXJIZWlnaHQgPSBoZWFkZXIgPyBoZWFkZXIub2Zmc2V0SGVpZ2h0IDogMCxcclxuICAgICAgICAgIHNlYXJjaEhlaWdodCA9IHNlYXJjaCA/IHNlYXJjaC5vZmZzZXRIZWlnaHQgOiAwLFxyXG4gICAgICAgICAgYWN0aW9uc0hlaWdodCA9IGFjdGlvbnMgPyBhY3Rpb25zLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBkb25lQnV0dG9uSGVpZ2h0ID0gZG9uZUJ1dHRvbiA/IGRvbmVCdXR0b24ub2Zmc2V0SGVpZ2h0IDogMCxcclxuICAgICAgICAgIGRpdmlkZXJIZWlnaHQgPSAkKGRpdmlkZXIpLm91dGVySGVpZ2h0KHRydWUpLFxyXG4gICAgICAgICAgLy8gZmFsbCBiYWNrIHRvIGpRdWVyeSBpZiBnZXRDb21wdXRlZFN0eWxlIGlzIG5vdCBzdXBwb3J0ZWRcclxuICAgICAgICAgIG1lbnVTdHlsZSA9IHR5cGVvZiBnZXRDb21wdXRlZFN0eWxlID09PSAnZnVuY3Rpb24nID8gZ2V0Q29tcHV0ZWRTdHlsZShtZW51KSA6IGZhbHNlLFxyXG4gICAgICAgICAgJG1lbnUgPSBtZW51U3R5bGUgPyBudWxsIDogJChtZW51KSxcclxuICAgICAgICAgIG1lbnVQYWRkaW5nID0ge1xyXG4gICAgICAgICAgICB2ZXJ0OiBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUucGFkZGluZ1RvcCA6ICRtZW51LmNzcygncGFkZGluZ1RvcCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5wYWRkaW5nQm90dG9tIDogJG1lbnUuY3NzKCdwYWRkaW5nQm90dG9tJykpICtcclxuICAgICAgICAgICAgICAgICAgcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLmJvcmRlclRvcFdpZHRoIDogJG1lbnUuY3NzKCdib3JkZXJUb3BXaWR0aCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJCb3R0b21XaWR0aCA6ICRtZW51LmNzcygnYm9yZGVyQm90dG9tV2lkdGgnKSksXHJcbiAgICAgICAgICAgIGhvcml6OiBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUucGFkZGluZ0xlZnQgOiAkbWVudS5jc3MoJ3BhZGRpbmdMZWZ0JykpICtcclxuICAgICAgICAgICAgICAgICAgcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdSaWdodCA6ICRtZW51LmNzcygncGFkZGluZ1JpZ2h0JykpICtcclxuICAgICAgICAgICAgICAgICAgcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLmJvcmRlckxlZnRXaWR0aCA6ICRtZW51LmNzcygnYm9yZGVyTGVmdFdpZHRoJykpICtcclxuICAgICAgICAgICAgICAgICAgcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLmJvcmRlclJpZ2h0V2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlclJpZ2h0V2lkdGgnKSlcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBtZW51RXh0cmFzID0gIHtcclxuICAgICAgICAgICAgdmVydDogbWVudVBhZGRpbmcudmVydCArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5Ub3AgOiAkbWVudS5jc3MoJ21hcmdpblRvcCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5Cb3R0b20gOiAkbWVudS5jc3MoJ21hcmdpbkJvdHRvbScpKSArIDIsXHJcbiAgICAgICAgICAgIGhvcml6OiBtZW51UGFkZGluZy5ob3JpeiArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5MZWZ0IDogJG1lbnUuY3NzKCdtYXJnaW5MZWZ0JykpICtcclxuICAgICAgICAgICAgICAgICAgcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLm1hcmdpblJpZ2h0IDogJG1lbnUuY3NzKCdtYXJnaW5SaWdodCcpKSArIDJcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQobmV3RWxlbWVudCk7XHJcblxyXG4gICAgICB0aGlzLnNpemVJbmZvID0ge1xyXG4gICAgICAgIGxpSGVpZ2h0OiBsaUhlaWdodCxcclxuICAgICAgICBoZWFkZXJIZWlnaHQ6IGhlYWRlckhlaWdodCxcclxuICAgICAgICBzZWFyY2hIZWlnaHQ6IHNlYXJjaEhlaWdodCxcclxuICAgICAgICBhY3Rpb25zSGVpZ2h0OiBhY3Rpb25zSGVpZ2h0LFxyXG4gICAgICAgIGRvbmVCdXR0b25IZWlnaHQ6IGRvbmVCdXR0b25IZWlnaHQsXHJcbiAgICAgICAgZGl2aWRlckhlaWdodDogZGl2aWRlckhlaWdodCxcclxuICAgICAgICBtZW51UGFkZGluZzogbWVudVBhZGRpbmcsXHJcbiAgICAgICAgbWVudUV4dHJhczogbWVudUV4dHJhc1xyXG4gICAgICB9O1xyXG4gICAgfSxcclxuXHJcbiAgICBzZXRTaXplOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuZmluZExpcygpO1xyXG4gICAgICB0aGlzLmxpSGVpZ2h0KCk7XHJcblxyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmhlYWRlcikgdGhpcy4kbWVudS5jc3MoJ3BhZGRpbmctdG9wJywgMCk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSA9PT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgICRtZW51ID0gdGhpcy4kbWVudSxcclxuICAgICAgICAgICRtZW51SW5uZXIgPSB0aGlzLiRtZW51SW5uZXIsXHJcbiAgICAgICAgICAkd2luZG93ID0gJCh3aW5kb3cpLFxyXG4gICAgICAgICAgc2VsZWN0SGVpZ2h0ID0gdGhpcy4kbmV3RWxlbWVudFswXS5vZmZzZXRIZWlnaHQsXHJcbiAgICAgICAgICBzZWxlY3RXaWR0aCA9IHRoaXMuJG5ld0VsZW1lbnRbMF0ub2Zmc2V0V2lkdGgsXHJcbiAgICAgICAgICBsaUhlaWdodCA9IHRoaXMuc2l6ZUluZm9bJ2xpSGVpZ2h0J10sXHJcbiAgICAgICAgICBoZWFkZXJIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydoZWFkZXJIZWlnaHQnXSxcclxuICAgICAgICAgIHNlYXJjaEhlaWdodCA9IHRoaXMuc2l6ZUluZm9bJ3NlYXJjaEhlaWdodCddLFxyXG4gICAgICAgICAgYWN0aW9uc0hlaWdodCA9IHRoaXMuc2l6ZUluZm9bJ2FjdGlvbnNIZWlnaHQnXSxcclxuICAgICAgICAgIGRvbmVCdXR0b25IZWlnaHQgPSB0aGlzLnNpemVJbmZvWydkb25lQnV0dG9uSGVpZ2h0J10sXHJcbiAgICAgICAgICBkaXZIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydkaXZpZGVySGVpZ2h0J10sXHJcbiAgICAgICAgICBtZW51UGFkZGluZyA9IHRoaXMuc2l6ZUluZm9bJ21lbnVQYWRkaW5nJ10sXHJcbiAgICAgICAgICBtZW51RXh0cmFzID0gdGhpcy5zaXplSW5mb1snbWVudUV4dHJhcyddLFxyXG4gICAgICAgICAgbm90RGlzYWJsZWQgPSB0aGlzLm9wdGlvbnMuaGlkZURpc2FibGVkID8gJy5kaXNhYmxlZCcgOiAnJyxcclxuICAgICAgICAgIG1lbnVIZWlnaHQsXHJcbiAgICAgICAgICBtZW51V2lkdGgsXHJcbiAgICAgICAgICBnZXRIZWlnaHQsXHJcbiAgICAgICAgICBnZXRXaWR0aCxcclxuICAgICAgICAgIHNlbGVjdE9mZnNldFRvcCxcclxuICAgICAgICAgIHNlbGVjdE9mZnNldEJvdCxcclxuICAgICAgICAgIHNlbGVjdE9mZnNldExlZnQsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRSaWdodCxcclxuICAgICAgICAgIGdldFBvcyA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB2YXIgcG9zID0gdGhhdC4kbmV3RWxlbWVudC5vZmZzZXQoKSxcclxuICAgICAgICAgICAgICAgICRjb250YWluZXIgPSAkKHRoYXQub3B0aW9ucy5jb250YWluZXIpLFxyXG4gICAgICAgICAgICAgICAgY29udGFpbmVyUG9zO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5jb250YWluZXIgJiYgISRjb250YWluZXIuaXMoJ2JvZHknKSkge1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcyA9ICRjb250YWluZXIub2Zmc2V0KCk7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zLnRvcCArPSBwYXJzZUludCgkY29udGFpbmVyLmNzcygnYm9yZGVyVG9wV2lkdGgnKSk7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zLmxlZnQgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2YXIgd2luUGFkID0gdGhhdC5vcHRpb25zLndpbmRvd1BhZGRpbmc7XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldFRvcCA9IHBvcy50b3AgLSBjb250YWluZXJQb3MudG9wIC0gJHdpbmRvdy5zY3JvbGxUb3AoKTtcclxuICAgICAgICAgICAgc2VsZWN0T2Zmc2V0Qm90ID0gJHdpbmRvdy5oZWlnaHQoKSAtIHNlbGVjdE9mZnNldFRvcCAtIHNlbGVjdEhlaWdodCAtIGNvbnRhaW5lclBvcy50b3AgLSB3aW5QYWRbMl07XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldExlZnQgPSBwb3MubGVmdCAtIGNvbnRhaW5lclBvcy5sZWZ0IC0gJHdpbmRvdy5zY3JvbGxMZWZ0KCk7XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldFJpZ2h0ID0gJHdpbmRvdy53aWR0aCgpIC0gc2VsZWN0T2Zmc2V0TGVmdCAtIHNlbGVjdFdpZHRoIC0gY29udGFpbmVyUG9zLmxlZnQgLSB3aW5QYWRbMV07XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldFRvcCAtPSB3aW5QYWRbMF07XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldExlZnQgLT0gd2luUGFkWzNdO1xyXG4gICAgICAgICAgfTtcclxuXHJcbiAgICAgIGdldFBvcygpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5zaXplID09PSAnYXV0bycpIHtcclxuICAgICAgICB2YXIgZ2V0U2l6ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgIHZhciBtaW5IZWlnaHQsXHJcbiAgICAgICAgICAgICAgaGFzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lLCBpbmNsdWRlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5jbHVkZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGVsZW1lbnQuY2xhc3NMaXN0ID8gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSA6ICQoZWxlbWVudCkuaGFzQ2xhc3MoY2xhc3NOYW1lKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEoZWxlbWVudC5jbGFzc0xpc3QgPyBlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpIDogJChlbGVtZW50KS5oYXNDbGFzcyhjbGFzc05hbWUpKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgbGlzID0gdGhhdC4kbWVudUlubmVyWzBdLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdsaScpLFxyXG4gICAgICAgICAgICAgIGxpc1Zpc2libGUgPSBBcnJheS5wcm90b3R5cGUuZmlsdGVyID8gQXJyYXkucHJvdG90eXBlLmZpbHRlci5jYWxsKGxpcywgaGFzQ2xhc3MoJ2hpZGRlbicsIGZhbHNlKSkgOiB0aGF0LiRsaXMubm90KCcuaGlkZGVuJyksXHJcbiAgICAgICAgICAgICAgb3B0R3JvdXAgPSBBcnJheS5wcm90b3R5cGUuZmlsdGVyID8gQXJyYXkucHJvdG90eXBlLmZpbHRlci5jYWxsKGxpc1Zpc2libGUsIGhhc0NsYXNzKCdkcm9wZG93bi1oZWFkZXInLCB0cnVlKSkgOiBsaXNWaXNpYmxlLmZpbHRlcignLmRyb3Bkb3duLWhlYWRlcicpO1xyXG5cclxuICAgICAgICAgIGdldFBvcygpO1xyXG4gICAgICAgICAgbWVudUhlaWdodCA9IHNlbGVjdE9mZnNldEJvdCAtIG1lbnVFeHRyYXMudmVydDtcclxuICAgICAgICAgIG1lbnVXaWR0aCA9IHNlbGVjdE9mZnNldFJpZ2h0IC0gbWVudUV4dHJhcy5ob3JpejtcclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICBpZiAoISRtZW51LmRhdGEoJ2hlaWdodCcpKSAkbWVudS5kYXRhKCdoZWlnaHQnLCAkbWVudS5oZWlnaHQoKSk7XHJcbiAgICAgICAgICAgIGdldEhlaWdodCA9ICRtZW51LmRhdGEoJ2hlaWdodCcpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCd3aWR0aCcpKSAkbWVudS5kYXRhKCd3aWR0aCcsICRtZW51LndpZHRoKCkpO1xyXG4gICAgICAgICAgICBnZXRXaWR0aCA9ICRtZW51LmRhdGEoJ3dpZHRoJyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBnZXRIZWlnaHQgPSAkbWVudS5oZWlnaHQoKTtcclxuICAgICAgICAgICAgZ2V0V2lkdGggPSAkbWVudS53aWR0aCgpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuZHJvcHVwQXV0bykge1xyXG4gICAgICAgICAgICB0aGF0LiRuZXdFbGVtZW50LnRvZ2dsZUNsYXNzKCdkcm9wdXAnLCBzZWxlY3RPZmZzZXRUb3AgPiBzZWxlY3RPZmZzZXRCb3QgJiYgKG1lbnVIZWlnaHQgLSBtZW51RXh0cmFzLnZlcnQpIDwgZ2V0SGVpZ2h0KTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC4kbmV3RWxlbWVudC5oYXNDbGFzcygnZHJvcHVwJykpIHtcclxuICAgICAgICAgICAgbWVudUhlaWdodCA9IHNlbGVjdE9mZnNldFRvcCAtIG1lbnVFeHRyYXMudmVydDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmRyb3Bkb3duQWxpZ25SaWdodCA9PT0gJ2F1dG8nKSB7XHJcbiAgICAgICAgICAgICRtZW51LnRvZ2dsZUNsYXNzKCdkcm9wZG93bi1tZW51LXJpZ2h0Jywgc2VsZWN0T2Zmc2V0TGVmdCA+IHNlbGVjdE9mZnNldFJpZ2h0ICYmIChtZW51V2lkdGggLSBtZW51RXh0cmFzLmhvcml6KSA8IChnZXRXaWR0aCAtIHNlbGVjdFdpZHRoKSk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKChsaXNWaXNpYmxlLmxlbmd0aCArIG9wdEdyb3VwLmxlbmd0aCkgPiAzKSB7XHJcbiAgICAgICAgICAgIG1pbkhlaWdodCA9IGxpSGVpZ2h0ICogMyArIG1lbnVFeHRyYXMudmVydCAtIDI7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBtaW5IZWlnaHQgPSAwO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICRtZW51LmNzcyh7XHJcbiAgICAgICAgICAgICdtYXgtaGVpZ2h0JzogbWVudUhlaWdodCArICdweCcsXHJcbiAgICAgICAgICAgICdvdmVyZmxvdyc6ICdoaWRkZW4nLFxyXG4gICAgICAgICAgICAnbWluLWhlaWdodCc6IG1pbkhlaWdodCArIGhlYWRlckhlaWdodCArIHNlYXJjaEhlaWdodCArIGFjdGlvbnNIZWlnaHQgKyBkb25lQnV0dG9uSGVpZ2h0ICsgJ3B4J1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICAkbWVudUlubmVyLmNzcyh7XHJcbiAgICAgICAgICAgICdtYXgtaGVpZ2h0JzogbWVudUhlaWdodCAtIGhlYWRlckhlaWdodCAtIHNlYXJjaEhlaWdodCAtIGFjdGlvbnNIZWlnaHQgLSBkb25lQnV0dG9uSGVpZ2h0IC0gbWVudVBhZGRpbmcudmVydCArICdweCcsXHJcbiAgICAgICAgICAgICdvdmVyZmxvdy15JzogJ2F1dG8nLFxyXG4gICAgICAgICAgICAnbWluLWhlaWdodCc6IE1hdGgubWF4KG1pbkhlaWdodCAtIG1lbnVQYWRkaW5nLnZlcnQsIDApICsgJ3B4J1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICBnZXRTaXplKCk7XHJcbiAgICAgICAgdGhpcy4kc2VhcmNoYm94Lm9mZignaW5wdXQuZ2V0U2l6ZSBwcm9wZXJ0eWNoYW5nZS5nZXRTaXplJykub24oJ2lucHV0LmdldFNpemUgcHJvcGVydHljaGFuZ2UuZ2V0U2l6ZScsIGdldFNpemUpO1xyXG4gICAgICAgICR3aW5kb3cub2ZmKCdyZXNpemUuZ2V0U2l6ZSBzY3JvbGwuZ2V0U2l6ZScpLm9uKCdyZXNpemUuZ2V0U2l6ZSBzY3JvbGwuZ2V0U2l6ZScsIGdldFNpemUpO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy5zaXplICYmIHRoaXMub3B0aW9ucy5zaXplICE9ICdhdXRvJyAmJiB0aGlzLiRsaXMubm90KG5vdERpc2FibGVkKS5sZW5ndGggPiB0aGlzLm9wdGlvbnMuc2l6ZSkge1xyXG4gICAgICAgIHZhciBvcHRJbmRleCA9IHRoaXMuJGxpcy5ub3QoJy5kaXZpZGVyJykubm90KG5vdERpc2FibGVkKS5jaGlsZHJlbigpLnNsaWNlKDAsIHRoaXMub3B0aW9ucy5zaXplKS5sYXN0KCkucGFyZW50KCkuaW5kZXgoKSxcclxuICAgICAgICAgICAgZGl2TGVuZ3RoID0gdGhpcy4kbGlzLnNsaWNlKDAsIG9wdEluZGV4ICsgMSkuZmlsdGVyKCcuZGl2aWRlcicpLmxlbmd0aDtcclxuICAgICAgICBtZW51SGVpZ2h0ID0gbGlIZWlnaHQgKiB0aGlzLm9wdGlvbnMuc2l6ZSArIGRpdkxlbmd0aCAqIGRpdkhlaWdodCArIG1lbnVQYWRkaW5nLnZlcnQ7XHJcblxyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSB7XHJcbiAgICAgICAgICBpZiAoISRtZW51LmRhdGEoJ2hlaWdodCcpKSAkbWVudS5kYXRhKCdoZWlnaHQnLCAkbWVudS5oZWlnaHQoKSk7XHJcbiAgICAgICAgICBnZXRIZWlnaHQgPSAkbWVudS5kYXRhKCdoZWlnaHQnKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuaGVpZ2h0KCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmRyb3B1cEF1dG8pIHtcclxuICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkQXNzaWdubWVudFxyXG4gICAgICAgICAgdGhpcy4kbmV3RWxlbWVudC50b2dnbGVDbGFzcygnZHJvcHVwJywgc2VsZWN0T2Zmc2V0VG9wID4gc2VsZWN0T2Zmc2V0Qm90ICYmIChtZW51SGVpZ2h0IC0gbWVudUV4dHJhcy52ZXJ0KSA8IGdldEhlaWdodCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgICRtZW51LmNzcyh7XHJcbiAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgKyBoZWFkZXJIZWlnaHQgKyBzZWFyY2hIZWlnaHQgKyBhY3Rpb25zSGVpZ2h0ICsgZG9uZUJ1dHRvbkhlaWdodCArICdweCcsXHJcbiAgICAgICAgICAnb3ZlcmZsb3cnOiAnaGlkZGVuJyxcclxuICAgICAgICAgICdtaW4taGVpZ2h0JzogJydcclxuICAgICAgICB9KTtcclxuICAgICAgICAkbWVudUlubmVyLmNzcyh7XHJcbiAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgLSBtZW51UGFkZGluZy52ZXJ0ICsgJ3B4JyxcclxuICAgICAgICAgICdvdmVyZmxvdy15JzogJ2F1dG8nLFxyXG4gICAgICAgICAgJ21pbi1oZWlnaHQnOiAnJ1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIHNldFdpZHRoOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMud2lkdGggPT09ICdhdXRvJykge1xyXG4gICAgICAgIHRoaXMuJG1lbnUuY3NzKCdtaW4td2lkdGgnLCAnMCcpO1xyXG5cclxuICAgICAgICAvLyBHZXQgY29ycmVjdCB3aWR0aCBpZiBlbGVtZW50IGlzIGhpZGRlblxyXG4gICAgICAgIHZhciAkc2VsZWN0Q2xvbmUgPSB0aGlzLiRtZW51LnBhcmVudCgpLmNsb25lKCkuYXBwZW5kVG8oJ2JvZHknKSxcclxuICAgICAgICAgICAgJHNlbGVjdENsb25lMiA9IHRoaXMub3B0aW9ucy5jb250YWluZXIgPyB0aGlzLiRuZXdFbGVtZW50LmNsb25lKCkuYXBwZW5kVG8oJ2JvZHknKSA6ICRzZWxlY3RDbG9uZSxcclxuICAgICAgICAgICAgdWxXaWR0aCA9ICRzZWxlY3RDbG9uZS5jaGlsZHJlbignLmRyb3Bkb3duLW1lbnUnKS5vdXRlcldpZHRoKCksXHJcbiAgICAgICAgICAgIGJ0bldpZHRoID0gJHNlbGVjdENsb25lMi5jc3MoJ3dpZHRoJywgJ2F1dG8nKS5jaGlsZHJlbignYnV0dG9uJykub3V0ZXJXaWR0aCgpO1xyXG5cclxuICAgICAgICAkc2VsZWN0Q2xvbmUucmVtb3ZlKCk7XHJcbiAgICAgICAgJHNlbGVjdENsb25lMi5yZW1vdmUoKTtcclxuXHJcbiAgICAgICAgLy8gU2V0IHdpZHRoIHRvIHdoYXRldmVyJ3MgbGFyZ2VyLCBidXR0b24gdGl0bGUgb3IgbG9uZ2VzdCBvcHRpb25cclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCBNYXRoLm1heCh1bFdpZHRoLCBidG5XaWR0aCkgKyAncHgnKTtcclxuICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMud2lkdGggPT09ICdmaXQnKSB7XHJcbiAgICAgICAgLy8gUmVtb3ZlIGlubGluZSBtaW4td2lkdGggc28gd2lkdGggY2FuIGJlIGNoYW5nZWQgZnJvbSAnYXV0bydcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJycpO1xyXG4gICAgICAgIHRoaXMuJG5ld0VsZW1lbnQuY3NzKCd3aWR0aCcsICcnKS5hZGRDbGFzcygnZml0LXdpZHRoJyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLndpZHRoKSB7XHJcbiAgICAgICAgLy8gUmVtb3ZlIGlubGluZSBtaW4td2lkdGggc28gd2lkdGggY2FuIGJlIGNoYW5nZWQgZnJvbSAnYXV0bydcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJycpO1xyXG4gICAgICAgIHRoaXMuJG5ld0VsZW1lbnQuY3NzKCd3aWR0aCcsIHRoaXMub3B0aW9ucy53aWR0aCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gUmVtb3ZlIGlubGluZSBtaW4td2lkdGgvd2lkdGggc28gd2lkdGggY2FuIGJlIGNoYW5nZWRcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJycpO1xyXG4gICAgICAgIHRoaXMuJG5ld0VsZW1lbnQuY3NzKCd3aWR0aCcsICcnKTtcclxuICAgICAgfVxyXG4gICAgICAvLyBSZW1vdmUgZml0LXdpZHRoIGNsYXNzIGlmIHdpZHRoIGlzIGNoYW5nZWQgcHJvZ3JhbW1hdGljYWxseVxyXG4gICAgICBpZiAodGhpcy4kbmV3RWxlbWVudC5oYXNDbGFzcygnZml0LXdpZHRoJykgJiYgdGhpcy5vcHRpb25zLndpZHRoICE9PSAnZml0Jykge1xyXG4gICAgICAgIHRoaXMuJG5ld0VsZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZpdC13aWR0aCcpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIHNlbGVjdFBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJGJzQ29udGFpbmVyID0gJCgnPGRpdiBjbGFzcz1cImJzLWNvbnRhaW5lclwiIC8+Jyk7XHJcblxyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkY29udGFpbmVyID0gJCh0aGlzLm9wdGlvbnMuY29udGFpbmVyKSxcclxuICAgICAgICAgIHBvcyxcclxuICAgICAgICAgIGNvbnRhaW5lclBvcyxcclxuICAgICAgICAgIGFjdHVhbEhlaWdodCxcclxuICAgICAgICAgIGdldFBsYWNlbWVudCA9IGZ1bmN0aW9uICgkZWxlbWVudCkge1xyXG4gICAgICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5hZGRDbGFzcygkZWxlbWVudC5hdHRyKCdjbGFzcycpLnJlcGxhY2UoL2Zvcm0tY29udHJvbHxmaXQtd2lkdGgvZ2ksICcnKSkudG9nZ2xlQ2xhc3MoJ2Ryb3B1cCcsICRlbGVtZW50Lmhhc0NsYXNzKCdkcm9wdXAnKSk7XHJcbiAgICAgICAgICAgIHBvcyA9ICRlbGVtZW50Lm9mZnNldCgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCEkY29udGFpbmVyLmlzKCdib2R5JykpIHtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MgPSAkY29udGFpbmVyLm9mZnNldCgpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy50b3AgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlclRvcFdpZHRoJykpIC0gJGNvbnRhaW5lci5zY3JvbGxUb3AoKTtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MubGVmdCArPSBwYXJzZUludCgkY29udGFpbmVyLmNzcygnYm9yZGVyTGVmdFdpZHRoJykpIC0gJGNvbnRhaW5lci5zY3JvbGxMZWZ0KCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgYWN0dWFsSGVpZ2h0ID0gJGVsZW1lbnQuaGFzQ2xhc3MoJ2Ryb3B1cCcpID8gMCA6ICRlbGVtZW50WzBdLm9mZnNldEhlaWdodDtcclxuXHJcbiAgICAgICAgICAgIHRoYXQuJGJzQ29udGFpbmVyLmNzcyh7XHJcbiAgICAgICAgICAgICAgJ3RvcCc6IHBvcy50b3AgLSBjb250YWluZXJQb3MudG9wICsgYWN0dWFsSGVpZ2h0LFxyXG4gICAgICAgICAgICAgICdsZWZ0JzogcG9zLmxlZnQgLSBjb250YWluZXJQb3MubGVmdCxcclxuICAgICAgICAgICAgICAnd2lkdGgnOiAkZWxlbWVudFswXS5vZmZzZXRXaWR0aFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24ub24oJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XHJcblxyXG4gICAgICAgIGlmICh0aGF0LmlzRGlzYWJsZWQoKSkge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZ2V0UGxhY2VtZW50KHRoYXQuJG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgICB0aGF0LiRic0NvbnRhaW5lclxyXG4gICAgICAgICAgLmFwcGVuZFRvKHRoYXQub3B0aW9ucy5jb250YWluZXIpXHJcbiAgICAgICAgICAudG9nZ2xlQ2xhc3MoJ29wZW4nLCAhJHRoaXMuaGFzQ2xhc3MoJ29wZW4nKSlcclxuICAgICAgICAgIC5hcHBlbmQodGhhdC4kbWVudSk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgJCh3aW5kb3cpLm9uKCdyZXNpemUgc2Nyb2xsJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGdldFBsYWNlbWVudCh0aGF0LiRuZXdFbGVtZW50KTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdoaWRlLmJzLnNlbGVjdCcsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LiRtZW51LmRhdGEoJ2hlaWdodCcsIHRoYXQuJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgIHRoYXQuJGJzQ29udGFpbmVyLmRldGFjaCgpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggLSB0aGUgaW5kZXggb2YgdGhlIG9wdGlvbiB0aGF0IGlzIGJlaW5nIGNoYW5nZWRcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2VsZWN0ZWQgLSB0cnVlIGlmIHRoZSBvcHRpb24gaXMgYmVpbmcgc2VsZWN0ZWQsIGZhbHNlIGlmIGJlaW5nIGRlc2VsZWN0ZWRcclxuICAgICAqIEBwYXJhbSB7SlF1ZXJ5fSAkbGlzIC0gdGhlICdsaScgZWxlbWVudCB0aGF0IGlzIGJlaW5nIG1vZGlmaWVkXHJcbiAgICAgKi9cclxuICAgIHNldFNlbGVjdGVkOiBmdW5jdGlvbiAoaW5kZXgsIHNlbGVjdGVkLCAkbGlzKSB7XHJcbiAgICAgIGlmICghJGxpcykge1xyXG4gICAgICAgIHRoaXMudG9nZ2xlUGxhY2Vob2xkZXIoKTsgLy8gY2hlY2sgaWYgc2V0U2VsZWN0ZWQgaXMgYmVpbmcgY2FsbGVkIGJ5IGNoYW5naW5nIHRoZSB2YWx1ZSBvZiB0aGUgc2VsZWN0XHJcbiAgICAgICAgJGxpcyA9IHRoaXMuZmluZExpcygpLmVxKHRoaXMubGlPYmpbaW5kZXhdKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJGxpcy50b2dnbGVDbGFzcygnc2VsZWN0ZWQnLCBzZWxlY3RlZCkuZmluZCgnYScpLmF0dHIoJ2FyaWEtc2VsZWN0ZWQnLCBzZWxlY3RlZCk7XHJcbiAgICB9LFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBvcHRpb24gdGhhdCBpcyBiZWluZyBkaXNhYmxlZFxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBkaXNhYmxlZCAtIHRydWUgaWYgdGhlIG9wdGlvbiBpcyBiZWluZyBkaXNhYmxlZCwgZmFsc2UgaWYgYmVpbmcgZW5hYmxlZFxyXG4gICAgICogQHBhcmFtIHtKUXVlcnl9ICRsaXMgLSB0aGUgJ2xpJyBlbGVtZW50IHRoYXQgaXMgYmVpbmcgbW9kaWZpZWRcclxuICAgICAqL1xyXG4gICAgc2V0RGlzYWJsZWQ6IGZ1bmN0aW9uIChpbmRleCwgZGlzYWJsZWQsICRsaXMpIHtcclxuICAgICAgaWYgKCEkbGlzKSB7XHJcbiAgICAgICAgJGxpcyA9IHRoaXMuZmluZExpcygpLmVxKHRoaXMubGlPYmpbaW5kZXhdKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGRpc2FibGVkKSB7XHJcbiAgICAgICAgJGxpcy5hZGRDbGFzcygnZGlzYWJsZWQnKS5jaGlsZHJlbignYScpLmF0dHIoJ2hyZWYnLCAnIycpLmF0dHIoJ3RhYmluZGV4JywgLTEpLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCB0cnVlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAkbGlzLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpLmNoaWxkcmVuKCdhJykucmVtb3ZlQXR0cignaHJlZicpLmF0dHIoJ3RhYmluZGV4JywgMCkuYXR0cignYXJpYS1kaXNhYmxlZCcsIGZhbHNlKTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBpc0Rpc2FibGVkOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50WzBdLmRpc2FibGVkO1xyXG4gICAgfSxcclxuXHJcbiAgICBjaGVja0Rpc2FibGVkOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcclxuXHJcbiAgICAgIGlmICh0aGlzLmlzRGlzYWJsZWQoKSkge1xyXG4gICAgICAgIHRoaXMuJG5ld0VsZW1lbnQuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmFkZENsYXNzKCdkaXNhYmxlZCcpLmF0dHIoJ3RhYmluZGV4JywgLTEpLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCB0cnVlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAodGhpcy4kYnV0dG9uLmhhc0NsYXNzKCdkaXNhYmxlZCcpKSB7XHJcbiAgICAgICAgICB0aGlzLiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgdGhpcy4kYnV0dG9uLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy4kYnV0dG9uLmF0dHIoJ3RhYmluZGV4JykgPT0gLTEgJiYgIXRoaXMuJGVsZW1lbnQuZGF0YSgndGFiaW5kZXgnKSkge1xyXG4gICAgICAgICAgdGhpcy4kYnV0dG9uLnJlbW92ZUF0dHIoJ3RhYmluZGV4Jyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24uY2xpY2soZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiAhdGhhdC5pc0Rpc2FibGVkKCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICB0b2dnbGVQbGFjZWhvbGRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdmFsdWUgPSB0aGlzLiRlbGVtZW50LnZhbCgpO1xyXG4gICAgICB0aGlzLiRidXR0b24udG9nZ2xlQ2xhc3MoJ2JzLXBsYWNlaG9sZGVyJywgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnIHx8ICh2YWx1ZS5jb25zdHJ1Y3RvciA9PT0gQXJyYXkgJiYgdmFsdWUubGVuZ3RoID09PSAwKSk7XHJcbiAgICB9LFxyXG5cclxuICAgIHRhYkluZGV4OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIGlmICh0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JykgIT09IHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAmJiBcclxuICAgICAgICAodGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcpICE9PSAtOTggJiYgdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcpICE9PSAnLTk4JykpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JywgdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcpKTtcclxuICAgICAgICB0aGlzLiRidXR0b24uYXR0cigndGFiaW5kZXgnLCB0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JykpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50LmF0dHIoJ3RhYmluZGV4JywgLTk4KTtcclxuICAgIH0sXHJcblxyXG4gICAgY2xpY2tMaXN0ZW5lcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkZG9jdW1lbnQgPSAkKGRvY3VtZW50KTtcclxuXHJcbiAgICAgICRkb2N1bWVudC5kYXRhKCdzcGFjZVNlbGVjdCcsIGZhbHNlKTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbigna2V5dXAnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmICgvKDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnKSkge1xyXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICRkb2N1bWVudC5kYXRhKCdzcGFjZVNlbGVjdCcsIGZhbHNlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LnNldFNpemUoKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdzaG93bi5icy5zZWxlY3QnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKCF0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCAmJiAhdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCBhJykuZm9jdXMoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCF0aGF0Lm11bHRpcGxlKSB7XHJcbiAgICAgICAgICB2YXIgc2VsZWN0ZWRJbmRleCA9IHRoYXQubGlPYmpbdGhhdC4kZWxlbWVudFswXS5zZWxlY3RlZEluZGV4XTtcclxuXHJcbiAgICAgICAgICBpZiAodHlwZW9mIHNlbGVjdGVkSW5kZXggIT09ICdudW1iZXInIHx8IHRoYXQub3B0aW9ucy5zaXplID09PSBmYWxzZSkgcmV0dXJuO1xyXG5cclxuICAgICAgICAgIC8vIHNjcm9sbCB0byBzZWxlY3RlZCBvcHRpb25cclxuICAgICAgICAgIHZhciBvZmZzZXQgPSB0aGF0LiRsaXMuZXEoc2VsZWN0ZWRJbmRleClbMF0ub2Zmc2V0VG9wIC0gdGhhdC4kbWVudUlubmVyWzBdLm9mZnNldFRvcDtcclxuICAgICAgICAgIG9mZnNldCA9IG9mZnNldCAtIHRoYXQuJG1lbnVJbm5lclswXS5vZmZzZXRIZWlnaHQvMiArIHRoYXQuc2l6ZUluZm8ubGlIZWlnaHQvMjtcclxuICAgICAgICAgIHRoYXQuJG1lbnVJbm5lclswXS5zY3JvbGxUb3AgPSBvZmZzZXQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lci5vbignY2xpY2snLCAnbGkgYScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICAgY2xpY2tlZEluZGV4ID0gJHRoaXMucGFyZW50KCkuZGF0YSgnb3JpZ2luYWxJbmRleCcpLFxyXG4gICAgICAgICAgICBwcmV2VmFsdWUgPSB0aGF0LiRlbGVtZW50LnZhbCgpLFxyXG4gICAgICAgICAgICBwcmV2SW5kZXggPSB0aGF0LiRlbGVtZW50LnByb3AoJ3NlbGVjdGVkSW5kZXgnKSxcclxuICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IHRydWU7XHJcblxyXG4gICAgICAgIC8vIERvbid0IGNsb3NlIG9uIG11bHRpIGNob2ljZSBtZW51XHJcbiAgICAgICAgaWYgKHRoYXQubXVsdGlwbGUgJiYgdGhhdC5vcHRpb25zLm1heE9wdGlvbnMgIT09IDEpIHtcclxuICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcblxyXG4gICAgICAgIC8vRG9uJ3QgcnVuIGlmIHdlIGhhdmUgYmVlbiBkaXNhYmxlZFxyXG4gICAgICAgIGlmICghdGhhdC5pc0Rpc2FibGVkKCkgJiYgISR0aGlzLnBhcmVudCgpLmhhc0NsYXNzKCdkaXNhYmxlZCcpKSB7XHJcbiAgICAgICAgICB2YXIgJG9wdGlvbnMgPSB0aGF0LiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgICAgICRvcHRpb24gPSAkb3B0aW9ucy5lcShjbGlja2VkSW5kZXgpLFxyXG4gICAgICAgICAgICAgIHN0YXRlID0gJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcpLFxyXG4gICAgICAgICAgICAgICRvcHRncm91cCA9ICRvcHRpb24ucGFyZW50KCdvcHRncm91cCcpLFxyXG4gICAgICAgICAgICAgIG1heE9wdGlvbnMgPSB0aGF0Lm9wdGlvbnMubWF4T3B0aW9ucyxcclxuICAgICAgICAgICAgICBtYXhPcHRpb25zR3JwID0gJG9wdGdyb3VwLmRhdGEoJ21heE9wdGlvbnMnKSB8fCBmYWxzZTtcclxuXHJcbiAgICAgICAgICBpZiAoIXRoYXQubXVsdGlwbGUpIHsgLy8gRGVzZWxlY3QgYWxsIG90aGVycyBpZiBub3QgbXVsdGkgc2VsZWN0IGJveFxyXG4gICAgICAgICAgICAkb3B0aW9ucy5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcclxuICAgICAgICAgICAgJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xyXG4gICAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnLnNlbGVjdGVkJykucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJykuZmluZCgnYScpLmF0dHIoJ2FyaWEtc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIHRoYXQuc2V0U2VsZWN0ZWQoY2xpY2tlZEluZGV4LCB0cnVlKTtcclxuICAgICAgICAgIH0gZWxzZSB7IC8vIFRvZ2dsZSB0aGUgb25lIHdlIGhhdmUgY2hvc2VuIGlmIHdlIGFyZSBtdWx0aSBzZWxlY3QuXHJcbiAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCAhc3RhdGUpO1xyXG4gICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgIXN0YXRlKTtcclxuICAgICAgICAgICAgJHRoaXMuYmx1cigpO1xyXG5cclxuICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgIT09IGZhbHNlIHx8IG1heE9wdGlvbnNHcnAgIT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgdmFyIG1heFJlYWNoZWQgPSBtYXhPcHRpb25zIDwgJG9wdGlvbnMuZmlsdGVyKCc6c2VsZWN0ZWQnKS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgIG1heFJlYWNoZWRHcnAgPSBtYXhPcHRpb25zR3JwIDwgJG9wdGdyb3VwLmZpbmQoJ29wdGlvbjpzZWxlY3RlZCcpLmxlbmd0aDtcclxuXHJcbiAgICAgICAgICAgICAgaWYgKChtYXhPcHRpb25zICYmIG1heFJlYWNoZWQpIHx8IChtYXhPcHRpb25zR3JwICYmIG1heFJlYWNoZWRHcnApKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAobWF4T3B0aW9ucyAmJiBtYXhPcHRpb25zID09IDEpIHtcclxuICAgICAgICAgICAgICAgICAgJG9wdGlvbnMucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCcpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xyXG4gICAgICAgICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1heE9wdGlvbnNHcnAgJiYgbWF4T3B0aW9uc0dycCA9PSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRncm91cC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICB2YXIgb3B0Z3JvdXBJRCA9ICR0aGlzLnBhcmVudCgpLmRhdGEoJ29wdGdyb3VwJyk7XHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCdbZGF0YS1vcHRncm91cD1cIicgKyBvcHRncm91cElEICsgJ1wiXScpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpO1xyXG4gICAgICAgICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICB2YXIgbWF4T3B0aW9uc1RleHQgPSB0eXBlb2YgdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0ID09PSAnc3RyaW5nJyA/IFt0aGF0Lm9wdGlvbnMubWF4T3B0aW9uc1RleHQsIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zVGV4dF0gOiB0aGF0Lm9wdGlvbnMubWF4T3B0aW9uc1RleHQsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXhPcHRpb25zQXJyID0gdHlwZW9mIG1heE9wdGlvbnNUZXh0ID09PSAnZnVuY3Rpb24nID8gbWF4T3B0aW9uc1RleHQobWF4T3B0aW9ucywgbWF4T3B0aW9uc0dycCkgOiBtYXhPcHRpb25zVGV4dCxcclxuICAgICAgICAgICAgICAgICAgICAgIG1heFR4dCA9IG1heE9wdGlvbnNBcnJbMF0ucmVwbGFjZSgne259JywgbWF4T3B0aW9ucyksXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXhUeHRHcnAgPSBtYXhPcHRpb25zQXJyWzFdLnJlcGxhY2UoJ3tufScsIG1heE9wdGlvbnNHcnApLFxyXG4gICAgICAgICAgICAgICAgICAgICAgJG5vdGlmeSA9ICQoJzxkaXYgY2xhc3M9XCJub3RpZnlcIj48L2Rpdj4nKTtcclxuICAgICAgICAgICAgICAgICAgLy8gSWYge3Zhcn0gaXMgc2V0IGluIGFycmF5LCByZXBsYWNlIGl0XHJcbiAgICAgICAgICAgICAgICAgIC8qKiBAZGVwcmVjYXRlZCAqL1xyXG4gICAgICAgICAgICAgICAgICBpZiAobWF4T3B0aW9uc0FyclsyXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG1heFR4dCA9IG1heFR4dC5yZXBsYWNlKCd7dmFyfScsIG1heE9wdGlvbnNBcnJbMl1bbWF4T3B0aW9ucyA+IDEgPyAwIDogMV0pO1xyXG4gICAgICAgICAgICAgICAgICAgIG1heFR4dEdycCA9IG1heFR4dEdycC5yZXBsYWNlKCd7dmFyfScsIG1heE9wdGlvbnNBcnJbMl1bbWF4T3B0aW9uc0dycCA+IDEgPyAwIDogMV0pO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgdGhhdC4kbWVudS5hcHBlbmQoJG5vdGlmeSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICBpZiAobWF4T3B0aW9ucyAmJiBtYXhSZWFjaGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJG5vdGlmeS5hcHBlbmQoJCgnPGRpdj4nICsgbWF4VHh0ICsgJzwvZGl2PicpKTtcclxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyQ2hhbmdlID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdtYXhSZWFjaGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICBpZiAobWF4T3B0aW9uc0dycCAmJiBtYXhSZWFjaGVkR3JwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJG5vdGlmeS5hcHBlbmQoJCgnPGRpdj4nICsgbWF4VHh0R3JwICsgJzwvZGl2PicpKTtcclxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyQ2hhbmdlID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdtYXhSZWFjaGVkR3JwLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICB9LCAxMCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAkbm90aWZ5LmRlbGF5KDc1MCkuZmFkZU91dCgzMDAsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZSgpO1xyXG4gICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAoIXRoYXQubXVsdGlwbGUgfHwgKHRoYXQubXVsdGlwbGUgJiYgdGhhdC5vcHRpb25zLm1heE9wdGlvbnMgPT09IDEpKSB7XHJcbiAgICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgICAgfSBlbHNlIGlmICh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBUcmlnZ2VyIHNlbGVjdCAnY2hhbmdlJ1xyXG4gICAgICAgICAgaWYgKHRyaWdnZXJDaGFuZ2UpIHtcclxuICAgICAgICAgICAgaWYgKChwcmV2VmFsdWUgIT0gdGhhdC4kZWxlbWVudC52YWwoKSAmJiB0aGF0Lm11bHRpcGxlKSB8fCAocHJldkluZGV4ICE9IHRoYXQuJGVsZW1lbnQucHJvcCgnc2VsZWN0ZWRJbmRleCcpICYmICF0aGF0Lm11bHRpcGxlKSkge1xyXG4gICAgICAgICAgICAgIC8vICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSBpcyBjdXJyZW50IG9wdGlvbiBzdGF0ZSAoc2VsZWN0ZWQvdW5zZWxlY3RlZCkuIHN0YXRlIGlzIHByZXZpb3VzIG9wdGlvbiBzdGF0ZS5cclxuICAgICAgICAgICAgICBjaGFuZ2VkX2FyZ3VtZW50cyA9IFtjbGlja2VkSW5kZXgsICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSwgc3RhdGVdO1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnRcclxuICAgICAgICAgICAgICAgIC50cmlnZ2VyTmF0aXZlKCdjaGFuZ2UnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51Lm9uKCdjbGljaycsICdsaS5kaXNhYmxlZCBhLCAucG9wb3Zlci10aXRsZSwgLnBvcG92ZXItdGl0bGUgOm5vdCguY2xvc2UpJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAoZS5jdXJyZW50VGFyZ2V0ID09IHRoaXMpIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2ggJiYgISQoZS50YXJnZXQpLmhhc0NsYXNzKCdjbG9zZScpKSB7XHJcbiAgICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lci5vbignY2xpY2snLCAnLmRpdmlkZXIsIC5kcm9wZG93bi1oZWFkZXInLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51Lm9uKCdjbGljaycsICcucG9wb3Zlci10aXRsZSAuY2xvc2UnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kYnV0dG9uLmNsaWNrKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kc2VhcmNoYm94Lm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51Lm9uKCdjbGljaycsICcuYWN0aW9ucy1idG4nLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgICAgIGlmICgkKHRoaXMpLmhhc0NsYXNzKCdicy1zZWxlY3QtYWxsJykpIHtcclxuICAgICAgICAgIHRoYXQuc2VsZWN0QWxsKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoYXQuZGVzZWxlY3RBbGwoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5jaGFuZ2UoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQucmVuZGVyKGZhbHNlKTtcclxuICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2NoYW5nZWQuYnMuc2VsZWN0JywgY2hhbmdlZF9hcmd1bWVudHMpO1xyXG4gICAgICAgIGNoYW5nZWRfYXJndW1lbnRzID0gbnVsbDtcclxuICAgICAgfSk7XHJcbiAgICB9LFxyXG5cclxuICAgIGxpdmVTZWFyY2hMaXN0ZW5lcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkbm9fcmVzdWx0cyA9ICQoJzxsaSBjbGFzcz1cIm5vLXJlc3VsdHNcIj48L2xpPicpO1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLm9uKCdjbGljay5kcm9wZG93bi5kYXRhLWFwaScsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICBpZiAoISF0aGF0LiRzZWFyY2hib3gudmFsKCkpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC52YWwoJycpO1xyXG4gICAgICAgICAgdGhhdC4kbGlzLm5vdCgnLmlzLWhpZGRlbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICAgIGlmICghISRub19yZXN1bHRzLnBhcmVudCgpLmxlbmd0aCkgJG5vX3Jlc3VsdHMucmVtb3ZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghdGhhdC5tdWx0aXBsZSkgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCcpLmFkZENsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0sIDEwKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRzZWFyY2hib3gub24oJ2NsaWNrLmRyb3Bkb3duLmRhdGEtYXBpIGZvY3VzLmRyb3Bkb3duLmRhdGEtYXBpIHRvdWNoZW5kLmRyb3Bkb3duLmRhdGEtYXBpJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJHNlYXJjaGJveC5vbignaW5wdXQgcHJvcGVydHljaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbGlzLm5vdCgnLmlzLWhpZGRlbicpLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICB0aGF0LiRsaXMuZmlsdGVyKCcuYWN0aXZlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpO1xyXG4gICAgICAgICRub19yZXN1bHRzLnJlbW92ZSgpO1xyXG5cclxuICAgICAgICBpZiAodGhhdC4kc2VhcmNoYm94LnZhbCgpKSB7XHJcbiAgICAgICAgICB2YXIgJHNlYXJjaEJhc2UgPSB0aGF0LiRsaXMubm90KCcuaXMtaGlkZGVuLCAuZGl2aWRlciwgLmRyb3Bkb3duLWhlYWRlcicpLFxyXG4gICAgICAgICAgICAgICRoaWRlSXRlbXM7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2hOb3JtYWxpemUpIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcyA9ICRzZWFyY2hCYXNlLm5vdCgnOmEnICsgdGhhdC5fc2VhcmNoU3R5bGUoKSArICcoXCInICsgbm9ybWFsaXplVG9CYXNlKHRoYXQuJHNlYXJjaGJveC52YWwoKSkgKyAnXCIpJyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAkaGlkZUl0ZW1zID0gJHNlYXJjaEJhc2Uubm90KCc6JyArIHRoYXQuX3NlYXJjaFN0eWxlKCkgKyAnKFwiJyArIHRoYXQuJHNlYXJjaGJveC52YWwoKSArICdcIiknKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAoJGhpZGVJdGVtcy5sZW5ndGggPT09ICRzZWFyY2hCYXNlLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAkbm9fcmVzdWx0cy5odG1sKHRoYXQub3B0aW9ucy5ub25lUmVzdWx0c1RleHQucmVwbGFjZSgnezB9JywgJ1wiJyArIGh0bWxFc2NhcGUodGhhdC4kc2VhcmNoYm94LnZhbCgpKSArICdcIicpKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLmFwcGVuZCgkbm9fcmVzdWx0cyk7XHJcbiAgICAgICAgICAgIHRoYXQuJGxpcy5hZGRDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAkaGlkZUl0ZW1zLmFkZENsYXNzKCdoaWRkZW4nKTtcclxuXHJcbiAgICAgICAgICAgIHZhciAkbGlzVmlzaWJsZSA9IHRoYXQuJGxpcy5ub3QoJy5oaWRkZW4nKSxcclxuICAgICAgICAgICAgICAgICRmb3VuZERpdjtcclxuXHJcbiAgICAgICAgICAgIC8vIGhpZGUgZGl2aWRlciBpZiBmaXJzdCBvciBsYXN0IHZpc2libGUsIG9yIGlmIGZvbGxvd2VkIGJ5IGFub3RoZXIgZGl2aWRlclxyXG4gICAgICAgICAgICAkbGlzVmlzaWJsZS5lYWNoKGZ1bmN0aW9uIChpbmRleCkge1xyXG4gICAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XHJcblxyXG4gICAgICAgICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygnZGl2aWRlcicpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoJGZvdW5kRGl2ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgJHRoaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgaWYgKCRmb3VuZERpdikgJGZvdW5kRGl2LmFkZENsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICAgICAgICAgICAgJGZvdW5kRGl2ID0gJHRoaXM7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5oYXNDbGFzcygnZHJvcGRvd24taGVhZGVyJykgJiYgJGxpc1Zpc2libGUuZXEoaW5kZXggKyAxKS5kYXRhKCdvcHRncm91cCcpICE9PSAkdGhpcy5kYXRhKCdvcHRncm91cCcpKSB7XHJcbiAgICAgICAgICAgICAgICAkdGhpcy5hZGRDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICRmb3VuZERpdiA9IG51bGw7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgaWYgKCRmb3VuZERpdikgJGZvdW5kRGl2LmFkZENsYXNzKCdoaWRkZW4nKTtcclxuXHJcbiAgICAgICAgICAgICRzZWFyY2hCYXNlLm5vdCgnLmhpZGRlbicpLmZpcnN0KCkuYWRkQ2xhc3MoJ2FjdGl2ZScpO1xyXG4gICAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuc2Nyb2xsVG9wKDApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9LFxyXG5cclxuICAgIF9zZWFyY2hTdHlsZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgc3R5bGVzID0ge1xyXG4gICAgICAgIGJlZ2luczogJ2liZWdpbnMnLFxyXG4gICAgICAgIHN0YXJ0c1dpdGg6ICdpYmVnaW5zJ1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgcmV0dXJuIHN0eWxlc1t0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaFN0eWxlXSB8fCAnaWNvbnRhaW5zJztcclxuICAgIH0sXHJcblxyXG4gICAgdmFsOiBmdW5jdGlvbiAodmFsdWUpIHtcclxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50LnZhbCh2YWx1ZSk7XHJcbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuJGVsZW1lbnQ7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuJGVsZW1lbnQudmFsKCk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgY2hhbmdlQWxsOiBmdW5jdGlvbiAoc3RhdHVzKSB7XHJcbiAgICAgIGlmICghdGhpcy5tdWx0aXBsZSkgcmV0dXJuO1xyXG4gICAgICBpZiAodHlwZW9mIHN0YXR1cyA9PT0gJ3VuZGVmaW5lZCcpIHN0YXR1cyA9IHRydWU7XHJcblxyXG4gICAgICB0aGlzLmZpbmRMaXMoKTtcclxuXHJcbiAgICAgIHZhciAkb3B0aW9ucyA9IHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJyksXHJcbiAgICAgICAgICAkbGlzVmlzaWJsZSA9IHRoaXMuJGxpcy5ub3QoJy5kaXZpZGVyLCAuZHJvcGRvd24taGVhZGVyLCAuZGlzYWJsZWQsIC5oaWRkZW4nKSxcclxuICAgICAgICAgIGxpc1Zpc0xlbiA9ICRsaXNWaXNpYmxlLmxlbmd0aCxcclxuICAgICAgICAgIHNlbGVjdGVkT3B0aW9ucyA9IFtdO1xyXG4gICAgICAgICAgXHJcbiAgICAgIGlmIChzdGF0dXMpIHtcclxuICAgICAgICBpZiAoJGxpc1Zpc2libGUuZmlsdGVyKCcuc2VsZWN0ZWQnKS5sZW5ndGggPT09ICRsaXNWaXNpYmxlLmxlbmd0aCkgcmV0dXJuO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmICgkbGlzVmlzaWJsZS5maWx0ZXIoJy5zZWxlY3RlZCcpLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgICAgICBcclxuICAgICAgJGxpc1Zpc2libGUudG9nZ2xlQ2xhc3MoJ3NlbGVjdGVkJywgc3RhdHVzKTtcclxuXHJcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzVmlzTGVuOyBpKyspIHtcclxuICAgICAgICB2YXIgb3JpZ0luZGV4ID0gJGxpc1Zpc2libGVbaV0uZ2V0QXR0cmlidXRlKCdkYXRhLW9yaWdpbmFsLWluZGV4Jyk7XHJcbiAgICAgICAgc2VsZWN0ZWRPcHRpb25zW3NlbGVjdGVkT3B0aW9ucy5sZW5ndGhdID0gJG9wdGlvbnMuZXEob3JpZ0luZGV4KVswXTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJChzZWxlY3RlZE9wdGlvbnMpLnByb3AoJ3NlbGVjdGVkJywgc3RhdHVzKTtcclxuXHJcbiAgICAgIHRoaXMucmVuZGVyKGZhbHNlKTtcclxuXHJcbiAgICAgIHRoaXMudG9nZ2xlUGxhY2Vob2xkZXIoKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnRcclxuICAgICAgICAudHJpZ2dlck5hdGl2ZSgnY2hhbmdlJyk7XHJcbiAgICB9LFxyXG5cclxuICAgIHNlbGVjdEFsbDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5jaGFuZ2VBbGwodHJ1ZSk7XHJcbiAgICB9LFxyXG5cclxuICAgIGRlc2VsZWN0QWxsOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmNoYW5nZUFsbChmYWxzZSk7XHJcbiAgICB9LFxyXG5cclxuICAgIHRvZ2dsZTogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgZSA9IGUgfHwgd2luZG93LmV2ZW50O1xyXG5cclxuICAgICAgaWYgKGUpIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24udHJpZ2dlcignY2xpY2snKTtcclxuICAgIH0sXHJcblxyXG4gICAga2V5ZG93bjogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICRwYXJlbnQgPSAkdGhpcy5pcygnaW5wdXQnKSA/ICR0aGlzLnBhcmVudCgpLnBhcmVudCgpIDogJHRoaXMucGFyZW50KCksXHJcbiAgICAgICAgICAkaXRlbXMsXHJcbiAgICAgICAgICB0aGF0ID0gJHBhcmVudC5kYXRhKCd0aGlzJyksXHJcbiAgICAgICAgICBpbmRleCxcclxuICAgICAgICAgIHByZXZJbmRleCxcclxuICAgICAgICAgIGlzQWN0aXZlLFxyXG4gICAgICAgICAgc2VsZWN0b3IgPSAnOm5vdCguZGlzYWJsZWQsIC5oaWRkZW4sIC5kcm9wZG93bi1oZWFkZXIsIC5kaXZpZGVyKScsXHJcbiAgICAgICAgICBrZXlDb2RlTWFwID0ge1xyXG4gICAgICAgICAgICAzMjogJyAnLFxyXG4gICAgICAgICAgICA0ODogJzAnLFxyXG4gICAgICAgICAgICA0OTogJzEnLFxyXG4gICAgICAgICAgICA1MDogJzInLFxyXG4gICAgICAgICAgICA1MTogJzMnLFxyXG4gICAgICAgICAgICA1MjogJzQnLFxyXG4gICAgICAgICAgICA1MzogJzUnLFxyXG4gICAgICAgICAgICA1NDogJzYnLFxyXG4gICAgICAgICAgICA1NTogJzcnLFxyXG4gICAgICAgICAgICA1NjogJzgnLFxyXG4gICAgICAgICAgICA1NzogJzknLFxyXG4gICAgICAgICAgICA1OTogJzsnLFxyXG4gICAgICAgICAgICA2NTogJ2EnLFxyXG4gICAgICAgICAgICA2NjogJ2InLFxyXG4gICAgICAgICAgICA2NzogJ2MnLFxyXG4gICAgICAgICAgICA2ODogJ2QnLFxyXG4gICAgICAgICAgICA2OTogJ2UnLFxyXG4gICAgICAgICAgICA3MDogJ2YnLFxyXG4gICAgICAgICAgICA3MTogJ2cnLFxyXG4gICAgICAgICAgICA3MjogJ2gnLFxyXG4gICAgICAgICAgICA3MzogJ2knLFxyXG4gICAgICAgICAgICA3NDogJ2onLFxyXG4gICAgICAgICAgICA3NTogJ2snLFxyXG4gICAgICAgICAgICA3NjogJ2wnLFxyXG4gICAgICAgICAgICA3NzogJ20nLFxyXG4gICAgICAgICAgICA3ODogJ24nLFxyXG4gICAgICAgICAgICA3OTogJ28nLFxyXG4gICAgICAgICAgICA4MDogJ3AnLFxyXG4gICAgICAgICAgICA4MTogJ3EnLFxyXG4gICAgICAgICAgICA4MjogJ3InLFxyXG4gICAgICAgICAgICA4MzogJ3MnLFxyXG4gICAgICAgICAgICA4NDogJ3QnLFxyXG4gICAgICAgICAgICA4NTogJ3UnLFxyXG4gICAgICAgICAgICA4NjogJ3YnLFxyXG4gICAgICAgICAgICA4NzogJ3cnLFxyXG4gICAgICAgICAgICA4ODogJ3gnLFxyXG4gICAgICAgICAgICA4OTogJ3knLFxyXG4gICAgICAgICAgICA5MDogJ3onLFxyXG4gICAgICAgICAgICA5NjogJzAnLFxyXG4gICAgICAgICAgICA5NzogJzEnLFxyXG4gICAgICAgICAgICA5ODogJzInLFxyXG4gICAgICAgICAgICA5OTogJzMnLFxyXG4gICAgICAgICAgICAxMDA6ICc0JyxcclxuICAgICAgICAgICAgMTAxOiAnNScsXHJcbiAgICAgICAgICAgIDEwMjogJzYnLFxyXG4gICAgICAgICAgICAxMDM6ICc3JyxcclxuICAgICAgICAgICAgMTA0OiAnOCcsXHJcbiAgICAgICAgICAgIDEwNTogJzknXHJcbiAgICAgICAgICB9O1xyXG5cclxuXHJcbiAgICAgIGlzQWN0aXZlID0gdGhhdC4kbmV3RWxlbWVudC5oYXNDbGFzcygnb3BlbicpO1xyXG5cclxuICAgICAgaWYgKCFpc0FjdGl2ZSAmJiAoZS5rZXlDb2RlID49IDQ4ICYmIGUua2V5Q29kZSA8PSA1NyB8fCBlLmtleUNvZGUgPj0gOTYgJiYgZS5rZXlDb2RlIDw9IDEwNSB8fCBlLmtleUNvZGUgPj0gNjUgJiYgZS5rZXlDb2RlIDw9IDkwKSkge1xyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmNvbnRhaW5lcikge1xyXG4gICAgICAgICAgdGhhdC5zZXRTaXplKCk7XHJcbiAgICAgICAgICB0aGF0LiRtZW51LnBhcmVudCgpLmFkZENsYXNzKCdvcGVuJyk7XHJcbiAgICAgICAgICBpc0FjdGl2ZSA9IHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoYXQuJGJ1dHRvbi50cmlnZ2VyKCdjbGljaycpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgIGlmICgvKF45JHwyNykvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgJiYgaXNBY3RpdmUpIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuY2xpY2soKTtcclxuICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKC8oMzh8NDApLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpKSB7XHJcbiAgICAgICAgJGl0ZW1zID0gdGhhdC4kbGlzLmZpbHRlcihzZWxlY3Rvcik7XHJcbiAgICAgICAgaWYgKCEkaXRlbXMubGVuZ3RoKSByZXR1cm47XHJcblxyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIGluZGV4ID0gJGl0ZW1zLmluZGV4KCRpdGVtcy5maW5kKCdhJykuZmlsdGVyKCc6Zm9jdXMnKS5wYXJlbnQoKSk7XHJcblx0ICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBpbmRleCA9ICRpdGVtcy5pbmRleCgkaXRlbXMuZmlsdGVyKCcuYWN0aXZlJykpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcHJldkluZGV4ID0gdGhhdC4kbWVudUlubmVyLmRhdGEoJ3ByZXZJbmRleCcpO1xyXG5cclxuICAgICAgICBpZiAoZS5rZXlDb2RlID09IDM4KSB7XHJcbiAgICAgICAgICBpZiAoKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoIHx8IGluZGV4ID09IHByZXZJbmRleCkgJiYgaW5kZXggIT0gLTEpIGluZGV4LS07XHJcbiAgICAgICAgICBpZiAoaW5kZXggPCAwKSBpbmRleCArPSAkaXRlbXMubGVuZ3RoO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoZS5rZXlDb2RlID09IDQwKSB7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2ggfHwgaW5kZXggPT0gcHJldkluZGV4KSBpbmRleCsrO1xyXG4gICAgICAgICAgaW5kZXggPSBpbmRleCAlICRpdGVtcy5sZW5ndGg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGF0LiRtZW51SW5uZXIuZGF0YSgncHJldkluZGV4JywgaW5kZXgpO1xyXG5cclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICAkaXRlbXMuZXEoaW5kZXgpLmNoaWxkcmVuKCdhJykuZm9jdXMoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgaWYgKCEkdGhpcy5oYXNDbGFzcygnZHJvcGRvd24tdG9nZ2xlJykpIHtcclxuICAgICAgICAgICAgJGl0ZW1zLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5lcShpbmRleCkuYWRkQ2xhc3MoJ2FjdGl2ZScpLmNoaWxkcmVuKCdhJykuZm9jdXMoKTtcclxuICAgICAgICAgICAgJHRoaXMuZm9jdXMoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICB9IGVsc2UgaWYgKCEkdGhpcy5pcygnaW5wdXQnKSkge1xyXG4gICAgICAgIHZhciBrZXlJbmRleCA9IFtdLFxyXG4gICAgICAgICAgICBjb3VudCxcclxuICAgICAgICAgICAgcHJldktleTtcclxuXHJcbiAgICAgICAgJGl0ZW1zID0gdGhhdC4kbGlzLmZpbHRlcihzZWxlY3Rvcik7XHJcbiAgICAgICAgJGl0ZW1zLmVhY2goZnVuY3Rpb24gKGkpIHtcclxuICAgICAgICAgIGlmICgkLnRyaW0oJCh0aGlzKS5jaGlsZHJlbignYScpLnRleHQoKS50b0xvd2VyQ2FzZSgpKS5zdWJzdHJpbmcoMCwgMSkgPT0ga2V5Q29kZU1hcFtlLmtleUNvZGVdKSB7XHJcbiAgICAgICAgICAgIGtleUluZGV4LnB1c2goaSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGNvdW50ID0gJChkb2N1bWVudCkuZGF0YSgna2V5Y291bnQnKTtcclxuICAgICAgICBjb3VudCsrO1xyXG4gICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgY291bnQpO1xyXG5cclxuICAgICAgICBwcmV2S2V5ID0gJC50cmltKCQoJzpmb2N1cycpLnRleHQoKS50b0xvd2VyQ2FzZSgpKS5zdWJzdHJpbmcoMCwgMSk7XHJcblxyXG4gICAgICAgIGlmIChwcmV2S2V5ICE9IGtleUNvZGVNYXBbZS5rZXlDb2RlXSkge1xyXG4gICAgICAgICAgY291bnQgPSAxO1xyXG4gICAgICAgICAgJChkb2N1bWVudCkuZGF0YSgna2V5Y291bnQnLCBjb3VudCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChjb3VudCA+PSBrZXlJbmRleC5sZW5ndGgpIHtcclxuICAgICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgMCk7XHJcbiAgICAgICAgICBpZiAoY291bnQgPiBrZXlJbmRleC5sZW5ndGgpIGNvdW50ID0gMTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICRpdGVtcy5lcShrZXlJbmRleFtjb3VudCAtIDFdKS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFNlbGVjdCBmb2N1c2VkIG9wdGlvbiBpZiBcIkVudGVyXCIsIFwiU3BhY2ViYXJcIiBvciBcIlRhYlwiICh3aGVuIHNlbGVjdE9uVGFiIGlzIHRydWUpIGFyZSBwcmVzc2VkIGluc2lkZSB0aGUgbWVudS5cclxuICAgICAgaWYgKCgvKDEzfDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSB8fCAoLyheOSQpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmIHRoYXQub3B0aW9ucy5zZWxlY3RPblRhYikpICYmIGlzQWN0aXZlKSB7XHJcbiAgICAgICAgaWYgKCEvKDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHZhciBlbGVtID0gJCgnOmZvY3VzJyk7XHJcbiAgICAgICAgICBlbGVtLmNsaWNrKCk7XHJcbiAgICAgICAgICAvLyBCcmluZyBiYWNrIGZvY3VzIGZvciBtdWx0aXNlbGVjdHNcclxuICAgICAgICAgIGVsZW0uZm9jdXMoKTtcclxuICAgICAgICAgIC8vIFByZXZlbnQgc2NyZWVuIGZyb20gc2Nyb2xsaW5nIGlmIHRoZSB1c2VyIGhpdCB0aGUgc3BhY2ViYXJcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIC8vIEZpeGVzIHNwYWNlYmFyIHNlbGVjdGlvbiBvZiBkcm9wZG93biBpdGVtcyBpbiBGRiAmIElFXHJcbiAgICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdzcGFjZVNlbGVjdCcsIHRydWUpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoIS8oMzIpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpKSB7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnLmFjdGl2ZSBhJykuY2xpY2soKTtcclxuICAgICAgICAgICR0aGlzLmZvY3VzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgMCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICgoLyheOSR8MjcpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmIGlzQWN0aXZlICYmICh0aGF0Lm11bHRpcGxlIHx8IHRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSkgfHwgKC8oMjcpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmICFpc0FjdGl2ZSkpIHtcclxuICAgICAgICB0aGF0LiRtZW51LnBhcmVudCgpLnJlbW92ZUNsYXNzKCdvcGVuJyk7XHJcbiAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5jb250YWluZXIpIHRoYXQuJG5ld0VsZW1lbnQucmVtb3ZlQ2xhc3MoJ29wZW4nKTtcclxuICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBtb2JpbGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kZWxlbWVudC5hZGRDbGFzcygnbW9iaWxlLWRldmljZScpO1xyXG4gICAgfSxcclxuXHJcbiAgICByZWZyZXNoOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJGxpcyA9IG51bGw7XHJcbiAgICAgIHRoaXMubGlPYmogPSB7fTtcclxuICAgICAgdGhpcy5yZWxvYWRMaSgpO1xyXG4gICAgICB0aGlzLnJlbmRlcigpO1xyXG4gICAgICB0aGlzLmNoZWNrRGlzYWJsZWQoKTtcclxuICAgICAgdGhpcy5saUhlaWdodCh0cnVlKTtcclxuICAgICAgdGhpcy5zZXRTdHlsZSgpO1xyXG4gICAgICB0aGlzLnNldFdpZHRoKCk7XHJcbiAgICAgIGlmICh0aGlzLiRsaXMpIHRoaXMuJHNlYXJjaGJveC50cmlnZ2VyKCdwcm9wZXJ0eWNoYW5nZScpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdyZWZyZXNoZWQuYnMuc2VsZWN0Jyk7XHJcbiAgICB9LFxyXG5cclxuICAgIGhpZGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5oaWRlKCk7XHJcbiAgICB9LFxyXG5cclxuICAgIHNob3c6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5zaG93KCk7XHJcbiAgICB9LFxyXG5cclxuICAgIHJlbW92ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50LnJlbW92ZSgpO1xyXG4gICAgICB0aGlzLiRlbGVtZW50LnJlbW92ZSgpO1xyXG4gICAgfSxcclxuXHJcbiAgICBkZXN0cm95OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuYmVmb3JlKHRoaXMuJGVsZW1lbnQpLnJlbW92ZSgpO1xyXG5cclxuICAgICAgaWYgKHRoaXMuJGJzQ29udGFpbmVyKSB7XHJcbiAgICAgICAgdGhpcy4kYnNDb250YWluZXIucmVtb3ZlKCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy4kbWVudS5yZW1vdmUoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudFxyXG4gICAgICAgIC5vZmYoJy5icy5zZWxlY3QnKVxyXG4gICAgICAgIC5yZW1vdmVEYXRhKCdzZWxlY3RwaWNrZXInKVxyXG4gICAgICAgIC5yZW1vdmVDbGFzcygnYnMtc2VsZWN0LWhpZGRlbiBzZWxlY3RwaWNrZXInKTtcclxuICAgIH1cclxuICB9O1xyXG5cclxuICAvLyBTRUxFQ1RQSUNLRVIgUExVR0lOIERFRklOSVRJT05cclxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XHJcbiAgICAvLyBnZXQgdGhlIGFyZ3Mgb2YgdGhlIG91dGVyIGZ1bmN0aW9uLi5cclxuICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xyXG4gICAgLy8gVGhlIGFyZ3VtZW50cyBvZiB0aGUgZnVuY3Rpb24gYXJlIGV4cGxpY2l0bHkgcmUtZGVmaW5lZCBmcm9tIHRoZSBhcmd1bWVudCBsaXN0LCBiZWNhdXNlIHRoZSBzaGlmdCBjYXVzZXMgdGhlbVxyXG4gICAgLy8gdG8gZ2V0IGxvc3QvY29ycnVwdGVkIGluIGFuZHJvaWQgMi4zIGFuZCBJRTkgIzcxNSAjNzc1XHJcbiAgICB2YXIgX29wdGlvbiA9IG9wdGlvbjtcclxuXHJcbiAgICBbXS5zaGlmdC5hcHBseShhcmdzKTtcclxuXHJcbiAgICB2YXIgdmFsdWU7XHJcbiAgICB2YXIgY2hhaW4gPSB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG4gICAgICBpZiAoJHRoaXMuaXMoJ3NlbGVjdCcpKSB7XHJcbiAgICAgICAgdmFyIGRhdGEgPSAkdGhpcy5kYXRhKCdzZWxlY3RwaWNrZXInKSxcclxuICAgICAgICAgICAgb3B0aW9ucyA9IHR5cGVvZiBfb3B0aW9uID09ICdvYmplY3QnICYmIF9vcHRpb247XHJcblxyXG4gICAgICAgIGlmICghZGF0YSkge1xyXG4gICAgICAgICAgdmFyIGNvbmZpZyA9ICQuZXh0ZW5kKHt9LCBTZWxlY3RwaWNrZXIuREVGQVVMVFMsICQuZm4uc2VsZWN0cGlja2VyLmRlZmF1bHRzIHx8IHt9LCAkdGhpcy5kYXRhKCksIG9wdGlvbnMpO1xyXG4gICAgICAgICAgY29uZmlnLnRlbXBsYXRlID0gJC5leHRlbmQoe30sIFNlbGVjdHBpY2tlci5ERUZBVUxUUy50ZW1wbGF0ZSwgKCQuZm4uc2VsZWN0cGlja2VyLmRlZmF1bHRzID8gJC5mbi5zZWxlY3RwaWNrZXIuZGVmYXVsdHMudGVtcGxhdGUgOiB7fSksICR0aGlzLmRhdGEoKS50ZW1wbGF0ZSwgb3B0aW9ucy50ZW1wbGF0ZSk7XHJcbiAgICAgICAgICAkdGhpcy5kYXRhKCdzZWxlY3RwaWNrZXInLCAoZGF0YSA9IG5ldyBTZWxlY3RwaWNrZXIodGhpcywgY29uZmlnKSkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucykge1xyXG4gICAgICAgICAgZm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KGkpKSB7XHJcbiAgICAgICAgICAgICAgZGF0YS5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBfb3B0aW9uID09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICBpZiAoZGF0YVtfb3B0aW9uXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XHJcbiAgICAgICAgICAgIHZhbHVlID0gZGF0YVtfb3B0aW9uXS5hcHBseShkYXRhLCBhcmdzKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHZhbHVlID0gZGF0YS5vcHRpb25zW19vcHRpb25dO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgLy9ub2luc3BlY3Rpb24gSlNVbnVzZWRBc3NpZ25tZW50XHJcbiAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiBjaGFpbjtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHZhciBvbGQgPSAkLmZuLnNlbGVjdHBpY2tlcjtcclxuICAkLmZuLnNlbGVjdHBpY2tlciA9IFBsdWdpbjtcclxuICAkLmZuLnNlbGVjdHBpY2tlci5Db25zdHJ1Y3RvciA9IFNlbGVjdHBpY2tlcjtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIE5PIENPTkZMSUNUXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICQuZm4uc2VsZWN0cGlja2VyID0gb2xkO1xyXG4gICAgcmV0dXJuIHRoaXM7XHJcbiAgfTtcclxuXHJcbiAgJChkb2N1bWVudClcclxuICAgICAgLmRhdGEoJ2tleWNvdW50JywgMClcclxuICAgICAgLm9uKCdrZXlkb3duLmJzLnNlbGVjdCcsICcuYm9vdHN0cmFwLXNlbGVjdCBbZGF0YS10b2dnbGU9ZHJvcGRvd25dLCAuYm9vdHN0cmFwLXNlbGVjdCBbcm9sZT1cImxpc3Rib3hcIl0sIC5icy1zZWFyY2hib3ggaW5wdXQnLCBTZWxlY3RwaWNrZXIucHJvdG90eXBlLmtleWRvd24pXHJcbiAgICAgIC5vbignZm9jdXNpbi5tb2RhbCcsICcuYm9vdHN0cmFwLXNlbGVjdCBbZGF0YS10b2dnbGU9ZHJvcGRvd25dLCAuYm9vdHN0cmFwLXNlbGVjdCBbcm9sZT1cImxpc3Rib3hcIl0sIC5icy1zZWFyY2hib3ggaW5wdXQnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAvLyBTRUxFQ1RQSUNLRVIgREFUQS1BUElcclxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cclxuICAkKHdpbmRvdykub24oJ2xvYWQuYnMuc2VsZWN0LmRhdGEtYXBpJywgZnVuY3Rpb24gKCkge1xyXG4gICAgJCgnLnNlbGVjdHBpY2tlcicpLmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgJHNlbGVjdHBpY2tlciA9ICQodGhpcyk7XHJcbiAgICAgIFBsdWdpbi5jYWxsKCRzZWxlY3RwaWNrZXIsICRzZWxlY3RwaWNrZXIuZGF0YSgpKTtcclxuICAgIH0pXHJcbiAgfSk7XHJcbn0pKGpRdWVyeSk7XHJcblxuXG59KSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtc2VsZWN0L2Rpc3QvanMvYm9vdHN0cmFwLXNlbGVjdC5qc1xuLy8gbW9kdWxlIGlkID0gNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcCAocGx1Z2luKTogdmFsaWRhdG9yLmpzIHYwLjExLjlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogVGhlIE1JVCBMaWNlbnNlIChNSVQpXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDE2IENpbmEgU2FmZmFyeS5cbiAqIE1hZGUgYnkgQDEwMDBoeiBpbiB0aGUgc3R5bGUgb2YgQm9vdHN0cmFwIDMgZXJhIEBmYXRcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gKiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gKiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICogVEhFIFNPRlRXQVJFLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cblxuK2Z1bmN0aW9uICgkKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBWQUxJREFUT1IgQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIGdldFZhbHVlKCRlbCkge1xuICAgIHJldHVybiAkZWwuaXMoJ1t0eXBlPVwiY2hlY2tib3hcIl0nKSA/ICRlbC5wcm9wKCdjaGVja2VkJykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOlxuICAgICAgICAgICAkZWwuaXMoJ1t0eXBlPVwicmFkaW9cIl0nKSAgICA/ICEhJCgnW25hbWU9XCInICsgJGVsLmF0dHIoJ25hbWUnKSArICdcIl06Y2hlY2tlZCcpLmxlbmd0aCA6XG4gICAgICAgICAgICRlbC5pcygnc2VsZWN0W211bHRpcGxlXScpICA/ICgkZWwudmFsKCkgfHwgW10pLmxlbmd0aCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZWwudmFsKClcbiAgfVxuXG4gIHZhciBWYWxpZGF0b3IgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMub3B0aW9ucyAgICA9IG9wdGlvbnNcbiAgICB0aGlzLnZhbGlkYXRvcnMgPSAkLmV4dGVuZCh7fSwgVmFsaWRhdG9yLlZBTElEQVRPUlMsIG9wdGlvbnMuY3VzdG9tKVxuICAgIHRoaXMuJGVsZW1lbnQgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLiRidG4gICAgICAgPSAkKCdidXR0b25bdHlwZT1cInN1Ym1pdFwiXSwgaW5wdXRbdHlwZT1cInN1Ym1pdFwiXScpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKCdbZm9ybT1cIicgKyB0aGlzLiRlbGVtZW50LmF0dHIoJ2lkJykgKyAnXCJdJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hZGQodGhpcy4kZWxlbWVudC5maW5kKCdpbnB1dFt0eXBlPVwic3VibWl0XCJdLCBidXR0b25bdHlwZT1cInN1Ym1pdFwiXScpKVxuXG4gICAgdGhpcy51cGRhdGUoKVxuXG4gICAgdGhpcy4kZWxlbWVudC5vbignaW5wdXQuYnMudmFsaWRhdG9yIGNoYW5nZS5icy52YWxpZGF0b3IgZm9jdXNvdXQuYnMudmFsaWRhdG9yJywgJC5wcm94eSh0aGlzLm9uSW5wdXQsIHRoaXMpKVxuICAgIHRoaXMuJGVsZW1lbnQub24oJ3N1Ym1pdC5icy52YWxpZGF0b3InLCAkLnByb3h5KHRoaXMub25TdWJtaXQsIHRoaXMpKVxuICAgIHRoaXMuJGVsZW1lbnQub24oJ3Jlc2V0LmJzLnZhbGlkYXRvcicsICQucHJveHkodGhpcy5yZXNldCwgdGhpcykpXG5cbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJ1tkYXRhLW1hdGNoXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICA9ICQodGhpcylcbiAgICAgIHZhciB0YXJnZXQgPSAkdGhpcy5hdHRyKCdkYXRhLW1hdGNoJylcblxuICAgICAgJCh0YXJnZXQpLm9uKCdpbnB1dC5icy52YWxpZGF0b3InLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBnZXRWYWx1ZSgkdGhpcykgJiYgJHRoaXMudHJpZ2dlcignaW5wdXQuYnMudmFsaWRhdG9yJylcbiAgICAgIH0pXG4gICAgfSlcblxuICAgIC8vIHJ1biB2YWxpZGF0b3JzIGZvciBmaWVsZHMgd2l0aCB2YWx1ZXMsIGJ1dCBkb24ndCBjbG9iYmVyIHNlcnZlci1zaWRlIGVycm9yc1xuICAgIHRoaXMuJGlucHV0cy5maWx0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGdldFZhbHVlKCQodGhpcykpICYmICEkKHRoaXMpLmNsb3Nlc3QoJy5oYXMtZXJyb3InKS5sZW5ndGhcbiAgICB9KS50cmlnZ2VyKCdmb2N1c291dCcpXG5cbiAgICB0aGlzLiRlbGVtZW50LmF0dHIoJ25vdmFsaWRhdGUnLCB0cnVlKSAvLyBkaXNhYmxlIGF1dG9tYXRpYyBuYXRpdmUgdmFsaWRhdGlvblxuICB9XG5cbiAgVmFsaWRhdG9yLlZFUlNJT04gPSAnMC4xMS45J1xuXG4gIFZhbGlkYXRvci5JTlBVVF9TRUxFQ1RPUiA9ICc6aW5wdXQ6bm90KFt0eXBlPVwiaGlkZGVuXCJdLCBbdHlwZT1cInN1Ym1pdFwiXSwgW3R5cGU9XCJyZXNldFwiXSwgYnV0dG9uKSdcblxuICBWYWxpZGF0b3IuRk9DVVNfT0ZGU0VUID0gMjBcblxuICBWYWxpZGF0b3IuREVGQVVMVFMgPSB7XG4gICAgZGVsYXk6IDUwMCxcbiAgICBodG1sOiBmYWxzZSxcbiAgICBkaXNhYmxlOiB0cnVlLFxuICAgIGZvY3VzOiB0cnVlLFxuICAgIGN1c3RvbToge30sXG4gICAgZXJyb3JzOiB7XG4gICAgICBtYXRjaDogJ0RvZXMgbm90IG1hdGNoJyxcbiAgICAgIG1pbmxlbmd0aDogJ05vdCBsb25nIGVub3VnaCdcbiAgICB9LFxuICAgIGZlZWRiYWNrOiB7XG4gICAgICBzdWNjZXNzOiAnZ2x5cGhpY29uLW9rJyxcbiAgICAgIGVycm9yOiAnZ2x5cGhpY29uLXJlbW92ZSdcbiAgICB9XG4gIH1cblxuICBWYWxpZGF0b3IuVkFMSURBVE9SUyA9IHtcbiAgICAnbmF0aXZlJzogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgdmFyIGVsID0gJGVsWzBdXG4gICAgICBpZiAoZWwuY2hlY2tWYWxpZGl0eSkge1xuICAgICAgICByZXR1cm4gIWVsLmNoZWNrVmFsaWRpdHkoKSAmJiAhZWwudmFsaWRpdHkudmFsaWQgJiYgKGVsLnZhbGlkYXRpb25NZXNzYWdlIHx8IFwiZXJyb3IhXCIpXG4gICAgICB9XG4gICAgfSxcbiAgICAnbWF0Y2gnOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICB2YXIgdGFyZ2V0ID0gJGVsLmF0dHIoJ2RhdGEtbWF0Y2gnKVxuICAgICAgcmV0dXJuICRlbC52YWwoKSAhPT0gJCh0YXJnZXQpLnZhbCgpICYmIFZhbGlkYXRvci5ERUZBVUxUUy5lcnJvcnMubWF0Y2hcbiAgICB9LFxuICAgICdtaW5sZW5ndGgnOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICB2YXIgbWlubGVuZ3RoID0gJGVsLmF0dHIoJ2RhdGEtbWlubGVuZ3RoJylcbiAgICAgIHJldHVybiAkZWwudmFsKCkubGVuZ3RoIDwgbWlubGVuZ3RoICYmIFZhbGlkYXRvci5ERUZBVUxUUy5lcnJvcnMubWlubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgICB0aGlzLiRpbnB1dHMgPSB0aGlzLiRlbGVtZW50LmZpbmQoVmFsaWRhdG9yLklOUFVUX1NFTEVDVE9SKVxuICAgICAgLmFkZCh0aGlzLiRlbGVtZW50LmZpbmQoJ1tkYXRhLXZhbGlkYXRlPVwidHJ1ZVwiXScpKVxuICAgICAgLm5vdCh0aGlzLiRlbGVtZW50LmZpbmQoJ1tkYXRhLXZhbGlkYXRlPVwiZmFsc2VcIl0nKVxuICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7IHNlbGYuY2xlYXJFcnJvcnMoJCh0aGlzKSkgfSlcbiAgICAgIClcblxuICAgIHRoaXMudG9nZ2xlU3VibWl0KClcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLm9uSW5wdXQgPSBmdW5jdGlvbiAoZSkge1xuICAgIHZhciBzZWxmICAgICAgICA9IHRoaXNcbiAgICB2YXIgJGVsICAgICAgICAgPSAkKGUudGFyZ2V0KVxuICAgIHZhciBkZWZlckVycm9ycyA9IGUudHlwZSAhPT0gJ2ZvY3Vzb3V0J1xuXG4gICAgaWYgKCF0aGlzLiRpbnB1dHMuaXMoJGVsKSkgcmV0dXJuXG5cbiAgICB0aGlzLnZhbGlkYXRlSW5wdXQoJGVsLCBkZWZlckVycm9ycykuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLnRvZ2dsZVN1Ym1pdCgpXG4gICAgfSlcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUudmFsaWRhdGVJbnB1dCA9IGZ1bmN0aW9uICgkZWwsIGRlZmVyRXJyb3JzKSB7XG4gICAgdmFyIHZhbHVlICAgICAgPSBnZXRWYWx1ZSgkZWwpXG4gICAgdmFyIHByZXZFcnJvcnMgPSAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycpXG5cbiAgICBpZiAoJGVsLmlzKCdbdHlwZT1cInJhZGlvXCJdJykpICRlbCA9IHRoaXMuJGVsZW1lbnQuZmluZCgnaW5wdXRbbmFtZT1cIicgKyAkZWwuYXR0cignbmFtZScpICsgJ1wiXScpXG5cbiAgICB2YXIgZSA9ICQuRXZlbnQoJ3ZhbGlkYXRlLmJzLnZhbGlkYXRvcicsIHtyZWxhdGVkVGFyZ2V0OiAkZWxbMF19KVxuICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcihlKVxuICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSByZXR1cm5cblxuICAgIHZhciBzZWxmID0gdGhpc1xuXG4gICAgcmV0dXJuIHRoaXMucnVuVmFsaWRhdG9ycygkZWwpLmRvbmUoZnVuY3Rpb24gKGVycm9ycykge1xuICAgICAgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5lcnJvcnMnLCBlcnJvcnMpXG5cbiAgICAgIGVycm9ycy5sZW5ndGhcbiAgICAgICAgPyBkZWZlckVycm9ycyA/IHNlbGYuZGVmZXIoJGVsLCBzZWxmLnNob3dFcnJvcnMpIDogc2VsZi5zaG93RXJyb3JzKCRlbClcbiAgICAgICAgOiBzZWxmLmNsZWFyRXJyb3JzKCRlbClcblxuICAgICAgaWYgKCFwcmV2RXJyb3JzIHx8IGVycm9ycy50b1N0cmluZygpICE9PSBwcmV2RXJyb3JzLnRvU3RyaW5nKCkpIHtcbiAgICAgICAgZSA9IGVycm9ycy5sZW5ndGhcbiAgICAgICAgICA/ICQuRXZlbnQoJ2ludmFsaWQuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXSwgZGV0YWlsOiBlcnJvcnN9KVxuICAgICAgICAgIDogJC5FdmVudCgndmFsaWQuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXSwgZGV0YWlsOiBwcmV2RXJyb3JzfSlcblxuICAgICAgICBzZWxmLiRlbGVtZW50LnRyaWdnZXIoZSlcbiAgICAgIH1cblxuICAgICAgc2VsZi50b2dnbGVTdWJtaXQoKVxuXG4gICAgICBzZWxmLiRlbGVtZW50LnRyaWdnZXIoJC5FdmVudCgndmFsaWRhdGVkLmJzLnZhbGlkYXRvcicsIHtyZWxhdGVkVGFyZ2V0OiAkZWxbMF19KSlcbiAgICB9KVxuICB9XG5cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnJ1blZhbGlkYXRvcnMgPSBmdW5jdGlvbiAoJGVsKSB7XG4gICAgdmFyIGVycm9ycyAgID0gW11cbiAgICB2YXIgZGVmZXJyZWQgPSAkLkRlZmVycmVkKClcblxuICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZGVmZXJyZWQnKSAmJiAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmRlZmVycmVkJykucmVqZWN0KClcbiAgICAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmRlZmVycmVkJywgZGVmZXJyZWQpXG5cbiAgICBmdW5jdGlvbiBnZXRWYWxpZGF0b3JTcGVjaWZpY0Vycm9yKGtleSkge1xuICAgICAgcmV0dXJuICRlbC5hdHRyKCdkYXRhLScgKyBrZXkgKyAnLWVycm9yJylcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRWYWxpZGl0eVN0YXRlRXJyb3IoKSB7XG4gICAgICB2YXIgdmFsaWRpdHkgPSAkZWxbMF0udmFsaWRpdHlcbiAgICAgIHJldHVybiB2YWxpZGl0eS50eXBlTWlzbWF0Y2ggICAgPyAkZWwuYXR0cignZGF0YS10eXBlLWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS5wYXR0ZXJuTWlzbWF0Y2ggPyAkZWwuYXR0cignZGF0YS1wYXR0ZXJuLWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS5zdGVwTWlzbWF0Y2ggICAgPyAkZWwuYXR0cignZGF0YS1zdGVwLWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS5yYW5nZU92ZXJmbG93ICAgPyAkZWwuYXR0cignZGF0YS1tYXgtZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnJhbmdlVW5kZXJmbG93ICA/ICRlbC5hdHRyKCdkYXRhLW1pbi1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkudmFsdWVNaXNzaW5nICAgID8gJGVsLmF0dHIoJ2RhdGEtcmVxdWlyZWQtZXJyb3InKVxuICAgICAgICAgICA6ICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bGxcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRHZW5lcmljRXJyb3IoKSB7XG4gICAgICByZXR1cm4gJGVsLmF0dHIoJ2RhdGEtZXJyb3InKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVycm9yTWVzc2FnZShrZXkpIHtcbiAgICAgIHJldHVybiBnZXRWYWxpZGF0b3JTcGVjaWZpY0Vycm9yKGtleSlcbiAgICAgICAgICB8fCBnZXRWYWxpZGl0eVN0YXRlRXJyb3IoKVxuICAgICAgICAgIHx8IGdldEdlbmVyaWNFcnJvcigpXG4gICAgfVxuXG4gICAgJC5lYWNoKHRoaXMudmFsaWRhdG9ycywgJC5wcm94eShmdW5jdGlvbiAoa2V5LCB2YWxpZGF0b3IpIHtcbiAgICAgIHZhciBlcnJvciA9IG51bGxcbiAgICAgIGlmICgoZ2V0VmFsdWUoJGVsKSB8fCAkZWwuYXR0cigncmVxdWlyZWQnKSkgJiZcbiAgICAgICAgICAoJGVsLmF0dHIoJ2RhdGEtJyArIGtleSkgIT09IHVuZGVmaW5lZCB8fCBrZXkgPT0gJ25hdGl2ZScpICYmXG4gICAgICAgICAgKGVycm9yID0gdmFsaWRhdG9yLmNhbGwodGhpcywgJGVsKSkpIHtcbiAgICAgICAgIGVycm9yID0gZ2V0RXJyb3JNZXNzYWdlKGtleSkgfHwgZXJyb3JcbiAgICAgICAgIX5lcnJvcnMuaW5kZXhPZihlcnJvcikgJiYgZXJyb3JzLnB1c2goZXJyb3IpXG4gICAgICB9XG4gICAgfSwgdGhpcykpXG5cbiAgICBpZiAoIWVycm9ycy5sZW5ndGggJiYgZ2V0VmFsdWUoJGVsKSAmJiAkZWwuYXR0cignZGF0YS1yZW1vdGUnKSkge1xuICAgICAgdGhpcy5kZWZlcigkZWwsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSB7fVxuICAgICAgICBkYXRhWyRlbC5hdHRyKCduYW1lJyldID0gZ2V0VmFsdWUoJGVsKVxuICAgICAgICAkLmdldCgkZWwuYXR0cignZGF0YS1yZW1vdGUnKSwgZGF0YSlcbiAgICAgICAgICAuZmFpbChmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yKSB7IGVycm9ycy5wdXNoKGdldEVycm9yTWVzc2FnZSgncmVtb3RlJykgfHwgZXJyb3IpIH0pXG4gICAgICAgICAgLmFsd2F5cyhmdW5jdGlvbiAoKSB7IGRlZmVycmVkLnJlc29sdmUoZXJyb3JzKX0pXG4gICAgICB9KVxuICAgIH0gZWxzZSBkZWZlcnJlZC5yZXNvbHZlKGVycm9ycylcblxuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlKClcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUudmFsaWRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgICAkLndoZW4odGhpcy4kaW5wdXRzLm1hcChmdW5jdGlvbiAoZWwpIHtcbiAgICAgIHJldHVybiBzZWxmLnZhbGlkYXRlSW5wdXQoJCh0aGlzKSwgZmFsc2UpXG4gICAgfSkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi50b2dnbGVTdWJtaXQoKVxuICAgICAgc2VsZi5mb2N1c0Vycm9yKClcbiAgICB9KVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuZm9jdXNFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5mb2N1cykgcmV0dXJuXG5cbiAgICB2YXIgJGlucHV0ID0gdGhpcy4kZWxlbWVudC5maW5kKFwiLmhhcy1lcnJvcjpmaXJzdCA6aW5wdXRcIilcbiAgICBpZiAoJGlucHV0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7c2Nyb2xsVG9wOiAkaW5wdXQub2Zmc2V0KCkudG9wIC0gVmFsaWRhdG9yLkZPQ1VTX09GRlNFVH0sIDI1MClcbiAgICAkaW5wdXQuZm9jdXMoKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5zaG93RXJyb3JzID0gZnVuY3Rpb24gKCRlbCkge1xuICAgIHZhciBtZXRob2QgPSB0aGlzLm9wdGlvbnMuaHRtbCA/ICdodG1sJyA6ICd0ZXh0J1xuICAgIHZhciBlcnJvcnMgPSAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycpXG4gICAgdmFyICRncm91cCA9ICRlbC5jbG9zZXN0KCcuZm9ybS1ncm91cCcpXG4gICAgdmFyICRibG9jayA9ICRncm91cC5maW5kKCcuaGVscC1ibG9jay53aXRoLWVycm9ycycpXG4gICAgdmFyICRmZWVkYmFjayA9ICRncm91cC5maW5kKCcuZm9ybS1jb250cm9sLWZlZWRiYWNrJylcblxuICAgIGlmICghZXJyb3JzLmxlbmd0aCkgcmV0dXJuXG5cbiAgICBlcnJvcnMgPSAkKCc8dWwvPicpXG4gICAgICAuYWRkQ2xhc3MoJ2xpc3QtdW5zdHlsZWQnKVxuICAgICAgLmFwcGVuZCgkLm1hcChlcnJvcnMsIGZ1bmN0aW9uIChlcnJvcikgeyByZXR1cm4gJCgnPGxpLz4nKVttZXRob2RdKGVycm9yKSB9KSlcblxuICAgICRibG9jay5kYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JykgPT09IHVuZGVmaW5lZCAmJiAkYmxvY2suZGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcsICRibG9jay5odG1sKCkpXG4gICAgJGJsb2NrLmVtcHR5KCkuYXBwZW5kKGVycm9ycylcbiAgICAkZ3JvdXAuYWRkQ2xhc3MoJ2hhcy1lcnJvciBoYXMtZGFuZ2VyJylcblxuICAgICRncm91cC5oYXNDbGFzcygnaGFzLWZlZWRiYWNrJylcbiAgICAgICYmICRmZWVkYmFjay5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suc3VjY2VzcylcbiAgICAgICYmICRmZWVkYmFjay5hZGRDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suZXJyb3IpXG4gICAgICAmJiAkZ3JvdXAucmVtb3ZlQ2xhc3MoJ2hhcy1zdWNjZXNzJylcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuY2xlYXJFcnJvcnMgPSBmdW5jdGlvbiAoJGVsKSB7XG4gICAgdmFyICRncm91cCA9ICRlbC5jbG9zZXN0KCcuZm9ybS1ncm91cCcpXG4gICAgdmFyICRibG9jayA9ICRncm91cC5maW5kKCcuaGVscC1ibG9jay53aXRoLWVycm9ycycpXG4gICAgdmFyICRmZWVkYmFjayA9ICRncm91cC5maW5kKCcuZm9ybS1jb250cm9sLWZlZWRiYWNrJylcblxuICAgICRibG9jay5odG1sKCRibG9jay5kYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JykpXG4gICAgJGdyb3VwLnJlbW92ZUNsYXNzKCdoYXMtZXJyb3IgaGFzLWRhbmdlciBoYXMtc3VjY2VzcycpXG5cbiAgICAkZ3JvdXAuaGFzQ2xhc3MoJ2hhcy1mZWVkYmFjaycpXG4gICAgICAmJiAkZmVlZGJhY2sucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLmVycm9yKVxuICAgICAgJiYgJGZlZWRiYWNrLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5zdWNjZXNzKVxuICAgICAgJiYgZ2V0VmFsdWUoJGVsKVxuICAgICAgJiYgJGZlZWRiYWNrLmFkZENsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5zdWNjZXNzKVxuICAgICAgJiYgJGdyb3VwLmFkZENsYXNzKCdoYXMtc3VjY2VzcycpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmhhc0Vycm9ycyA9IGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBmaWVsZEVycm9ycygpIHtcbiAgICAgIHJldHVybiAhISgkKHRoaXMpLmRhdGEoJ2JzLnZhbGlkYXRvci5lcnJvcnMnKSB8fCBbXSkubGVuZ3RoXG4gICAgfVxuXG4gICAgcmV0dXJuICEhdGhpcy4kaW5wdXRzLmZpbHRlcihmaWVsZEVycm9ycykubGVuZ3RoXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmlzSW5jb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBmaWVsZEluY29tcGxldGUoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBnZXRWYWx1ZSgkKHRoaXMpKVxuICAgICAgcmV0dXJuICEodHlwZW9mIHZhbHVlID09IFwic3RyaW5nXCIgPyAkLnRyaW0odmFsdWUpIDogdmFsdWUpXG4gICAgfVxuXG4gICAgcmV0dXJuICEhdGhpcy4kaW5wdXRzLmZpbHRlcignW3JlcXVpcmVkXScpLmZpbHRlcihmaWVsZEluY29tcGxldGUpLmxlbmd0aFxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5vblN1Ym1pdCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdGhpcy52YWxpZGF0ZSgpXG4gICAgaWYgKHRoaXMuaXNJbmNvbXBsZXRlKCkgfHwgdGhpcy5oYXNFcnJvcnMoKSkgZS5wcmV2ZW50RGVmYXVsdCgpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnRvZ2dsZVN1Ym1pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5kaXNhYmxlKSByZXR1cm5cbiAgICB0aGlzLiRidG4udG9nZ2xlQ2xhc3MoJ2Rpc2FibGVkJywgdGhpcy5pc0luY29tcGxldGUoKSB8fCB0aGlzLmhhc0Vycm9ycygpKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5kZWZlciA9IGZ1bmN0aW9uICgkZWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSAkLnByb3h5KGNhbGxiYWNrLCB0aGlzLCAkZWwpXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZGVsYXkpIHJldHVybiBjYWxsYmFjaygpXG4gICAgd2luZG93LmNsZWFyVGltZW91dCgkZWwuZGF0YSgnYnMudmFsaWRhdG9yLnRpbWVvdXQnKSlcbiAgICAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLnRpbWVvdXQnLCB3aW5kb3cuc2V0VGltZW91dChjYWxsYmFjaywgdGhpcy5vcHRpb25zLmRlbGF5KSlcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCcuZm9ybS1jb250cm9sLWZlZWRiYWNrJylcbiAgICAgIC5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suZXJyb3IpXG4gICAgICAucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG5cbiAgICB0aGlzLiRpbnB1dHNcbiAgICAgIC5yZW1vdmVEYXRhKFsnYnMudmFsaWRhdG9yLmVycm9ycycsICdicy52YWxpZGF0b3IuZGVmZXJyZWQnXSlcbiAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgICB2YXIgdGltZW91dCA9ICR0aGlzLmRhdGEoJ2JzLnZhbGlkYXRvci50aW1lb3V0JylcbiAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aW1lb3V0KSAmJiAkdGhpcy5yZW1vdmVEYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcpXG4gICAgICB9KVxuXG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCcuaGVscC1ibG9jay53aXRoLWVycm9ycycpXG4gICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcylcbiAgICAgICAgdmFyIG9yaWdpbmFsQ29udGVudCA9ICR0aGlzLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKVxuXG4gICAgICAgICR0aGlzXG4gICAgICAgICAgLnJlbW92ZURhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKVxuICAgICAgICAgIC5odG1sKG9yaWdpbmFsQ29udGVudClcbiAgICAgIH0pXG5cbiAgICB0aGlzLiRidG4ucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJylcblxuICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnLmhhcy1lcnJvciwgLmhhcy1kYW5nZXIsIC5oYXMtc3VjY2VzcycpLnJlbW92ZUNsYXNzKCdoYXMtZXJyb3IgaGFzLWRhbmdlciBoYXMtc3VjY2VzcycpXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMucmVzZXQoKVxuXG4gICAgdGhpcy4kZWxlbWVudFxuICAgICAgLnJlbW92ZUF0dHIoJ25vdmFsaWRhdGUnKVxuICAgICAgLnJlbW92ZURhdGEoJ2JzLnZhbGlkYXRvcicpXG4gICAgICAub2ZmKCcuYnMudmFsaWRhdG9yJylcblxuICAgIHRoaXMuJGlucHV0c1xuICAgICAgLm9mZignLmJzLnZhbGlkYXRvcicpXG5cbiAgICB0aGlzLm9wdGlvbnMgICAgPSBudWxsXG4gICAgdGhpcy52YWxpZGF0b3JzID0gbnVsbFxuICAgIHRoaXMuJGVsZW1lbnQgICA9IG51bGxcbiAgICB0aGlzLiRidG4gICAgICAgPSBudWxsXG4gICAgdGhpcy4kaW5wdXRzICAgID0gbnVsbFxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8vIFZBTElEQVRPUiBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuXG4gIGZ1bmN0aW9uIFBsdWdpbihvcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyAgID0gJCh0aGlzKVxuICAgICAgdmFyIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgVmFsaWRhdG9yLkRFRkFVTFRTLCAkdGhpcy5kYXRhKCksIHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uKVxuICAgICAgdmFyIGRhdGEgICAgPSAkdGhpcy5kYXRhKCdicy52YWxpZGF0b3InKVxuXG4gICAgICBpZiAoIWRhdGEgJiYgb3B0aW9uID09ICdkZXN0cm95JykgcmV0dXJuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLnZhbGlkYXRvcicsIChkYXRhID0gbmV3IFZhbGlkYXRvcih0aGlzLCBvcHRpb25zKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4udmFsaWRhdG9yXG5cbiAgJC5mbi52YWxpZGF0b3IgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi52YWxpZGF0b3IuQ29uc3RydWN0b3IgPSBWYWxpZGF0b3JcblxuXG4gIC8vIFZBTElEQVRPUiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLnZhbGlkYXRvci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4udmFsaWRhdG9yID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gVkFMSURBVE9SIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PT09PVxuXG4gICQod2luZG93KS5vbignbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAkKCdmb3JtW2RhdGEtdG9nZ2xlPVwidmFsaWRhdG9yXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJGZvcm0gPSAkKHRoaXMpXG4gICAgICBQbHVnaW4uY2FsbCgkZm9ybSwgJGZvcm0uZGF0YSgpKVxuICAgIH0pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC12YWxpZGF0b3IvanMvdmFsaWRhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSA2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxuICogYm9vdHN0cmFwLWZpbGVpbnB1dCB2NC40LjJcbiAqIGh0dHA6Ly9wbHVnaW5zLmtyYWplZS5jb20vZmlsZS1pbnB1dFxuICpcbiAqIEF1dGhvcjogS2FydGlrIFZpc3dlc3dhcmFuXG4gKiBDb3B5cmlnaHQ6IDIwMTQgLSAyMDE3LCBLYXJ0aWsgVmlzd2Vzd2FyYW4sIEtyYWplZS5jb21cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQlNEIDMtQ2xhdXNlXG4gKiBodHRwczovL2dpdGh1Yi5jb20va2FydGlrLXYvYm9vdHN0cmFwLWZpbGVpbnB1dC9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4gKi9cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuICAgICAgICBkZWZpbmUoWydqcXVlcnknXSwgZmFjdG9yeSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgIH0gZWxzZSB7IC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgICAgICAvLyBOb2RlL0NvbW1vbkpTXG4gICAgICAgICAgICAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCdqcXVlcnknKSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgICAgICAgICBmYWN0b3J5KHdpbmRvdy5qUXVlcnkpO1xuICAgICAgICB9XG4gICAgfVxufShmdW5jdGlvbiAoJCkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgJC5mbi5maWxlaW5wdXRMb2NhbGVzID0ge307XG4gICAgJC5mbi5maWxlaW5wdXRUaGVtZXMgPSB7fTtcblxuICAgIFN0cmluZy5wcm90b3R5cGUuc2V0VG9rZW5zID0gZnVuY3Rpb24gKHJlcGxhY2VQYWlycykge1xuICAgICAgICB2YXIgc3RyID0gdGhpcy50b1N0cmluZygpLCBrZXksIHJlO1xuICAgICAgICBmb3IgKGtleSBpbiByZXBsYWNlUGFpcnMpIHtcbiAgICAgICAgICAgIGlmIChyZXBsYWNlUGFpcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIHJlID0gbmV3IFJlZ0V4cChcIlxce1wiICsga2V5ICsgXCJcXH1cIiwgXCJnXCIpO1xuICAgICAgICAgICAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKHJlLCByZXBsYWNlUGFpcnNba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgdmFyICRoLCBGaWxlSW5wdXQ7XG5cbiAgICAvLyBmaWxlaW5wdXQgaGVscGVyIG9iamVjdCBmb3IgYWxsIGdsb2JhbCB2YXJpYWJsZXMgYW5kIGludGVybmFsIGhlbHBlciBtZXRob2RzXG4gICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAkaCA9IHtcbiAgICAgICAgRlJBTUVTOiAnLmt2LXByZXZpZXctdGh1bWInLFxuICAgICAgICBTT1JUX0NTUzogJ2ZpbGUtc29ydGFibGUnLFxuICAgICAgICBTVFlMRV9TRVRUSU5HOiAnc3R5bGU9XCJ3aWR0aDp7d2lkdGh9O2hlaWdodDp7aGVpZ2h0fTtcIicsXG4gICAgICAgIE9CSkVDVF9QQVJBTVM6ICc8cGFyYW0gbmFtZT1cImNvbnRyb2xsZXJcIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd0Z1bGxTY3JlZW5cIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd1NjcmlwdEFjY2Vzc1wiIHZhbHVlPVwiYWx3YXlzXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1BsYXlcIiB2YWx1ZT1cImZhbHNlXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1N0YXJ0XCIgdmFsdWU9XCJmYWxzZVwiIC8+XFxuJyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cInF1YWxpdHlcIiB2YWx1ZT1cImhpZ2hcIiAvPlxcbicsXG4gICAgICAgIERFRkFVTFRfUFJFVklFVzogJzxkaXYgY2xhc3M9XCJmaWxlLXByZXZpZXctb3RoZXJcIj5cXG4nICtcbiAgICAgICAgJzxzcGFuIGNsYXNzPVwie3ByZXZpZXdGaWxlSWNvbkNsYXNzfVwiPntwcmV2aWV3RmlsZUljb259PC9zcGFuPlxcbicgK1xuICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgTU9EQUxfSUQ6ICdrdkZpbGVpbnB1dE1vZGFsJyxcbiAgICAgICAgTU9EQUxfRVZFTlRTOiBbJ3Nob3cnLCAnc2hvd24nLCAnaGlkZScsICdoaWRkZW4nLCAnbG9hZGVkJ10sXG4gICAgICAgIG9ialVybDogd2luZG93LlVSTCB8fCB3aW5kb3cud2Via2l0VVJMLFxuICAgICAgICBjb21wYXJlOiBmdW5jdGlvbiAoaW5wdXQsIHN0ciwgZXhhY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPT0gdW5kZWZpbmVkICYmIChleGFjdCA/IGlucHV0ID09PSBzdHIgOiBpbnB1dC5tYXRjaChzdHIpKTtcbiAgICAgICAgfSxcbiAgICAgICAgaXNJRTogZnVuY3Rpb24gKHZlcikge1xuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIElFIHZlcnNpb25zIDwgMTFcbiAgICAgICAgICAgIGlmIChuYXZpZ2F0b3IuYXBwTmFtZSAhPT0gJ01pY3Jvc29mdCBJbnRlcm5ldCBFeHBsb3JlcicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmVyID09PSAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKCdtc2llXFxcXHMnICsgdmVyLCAnaScpLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKSwgc3RhdHVzO1xuICAgICAgICAgICAgZGl2LmlubmVySFRNTCA9IFwiPCEtLVtpZiBJRSBcIiArIHZlciArIFwiXT4gPGk+PC9pPiA8IVtlbmRpZl0tLT5cIjtcbiAgICAgICAgICAgIHN0YXR1cyA9IGRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZShcImlcIikubGVuZ3RoO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgICAgIHJldHVybiBzdGF0dXM7XG4gICAgICAgIH0sXG4gICAgICAgIGluaXRNb2RhbDogZnVuY3Rpb24gKCRtb2RhbCkge1xuICAgICAgICAgICAgdmFyICRib2R5ID0gJCgnYm9keScpO1xuICAgICAgICAgICAgaWYgKCRib2R5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICRtb2RhbC5hcHBlbmRUbygkYm9keSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGlzRW1wdHk6IGZ1bmN0aW9uICh2YWx1ZSwgdHJpbSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUubGVuZ3RoID09PSAwIHx8ICh0cmltICYmICQudHJpbSh2YWx1ZSkgPT09ICcnKTtcbiAgICAgICAgfSxcbiAgICAgICAgaXNBcnJheTogZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGEpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICAgICAgfSxcbiAgICAgICAgaWZTZXQ6IGZ1bmN0aW9uIChuZWVkbGUsIGhheXN0YWNrLCBkZWYpIHtcbiAgICAgICAgICAgIGRlZiA9IGRlZiB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiAoaGF5c3RhY2sgJiYgdHlwZW9mIGhheXN0YWNrID09PSAnb2JqZWN0JyAmJiBuZWVkbGUgaW4gaGF5c3RhY2spID8gaGF5c3RhY2tbbmVlZGxlXSA6IGRlZjtcbiAgICAgICAgfSxcbiAgICAgICAgY2xlYW5BcnJheTogZnVuY3Rpb24gKGFycikge1xuICAgICAgICAgICAgaWYgKCEoYXJyIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgYXJyID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYXJyLmZpbHRlcihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoZSAhPT0gdW5kZWZpbmVkICYmIGUgIT09IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHNwbGljZUFycmF5OiBmdW5jdGlvbiAoYXJyLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIGksIGogPSAwLCBvdXQgPSBbXTtcbiAgICAgICAgICAgIGlmICghKGFyciBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0W2pdID0gYXJyW2ldO1xuICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0TnVtOiBmdW5jdGlvbiAobnVtLCBkZWYpIHtcbiAgICAgICAgICAgIGRlZiA9IGRlZiB8fCAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBudW0gPSBwYXJzZUZsb2F0KG51bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaXNOYU4obnVtKSA/IGRlZiA6IG51bTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzRmlsZUFQSVN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhISh3aW5kb3cuRmlsZSAmJiB3aW5kb3cuRmlsZVJlYWRlcik7XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0RyYWdEcm9wU3VwcG9ydDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZGl2LmRyYWdnYWJsZSAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZGl2Lm9uZHJhZ3N0YXJ0ICovXG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkaXYub25kcm9wICovXG4gICAgICAgICAgICByZXR1cm4gISRoLmlzSUUoOSkgJiZcbiAgICAgICAgICAgICAgICAoZGl2LmRyYWdnYWJsZSAhPT0gdW5kZWZpbmVkIHx8IChkaXYub25kcmFnc3RhcnQgIT09IHVuZGVmaW5lZCAmJiBkaXYub25kcm9wICE9PSB1bmRlZmluZWQpKTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzRmlsZVVwbG9hZFN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAkaC5oYXNGaWxlQVBJU3VwcG9ydCgpICYmIHdpbmRvdy5Gb3JtRGF0YTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzQmxvYlN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICEhd2luZG93LkJsb2IgJiYgQm9vbGVhbihuZXcgQmxvYigpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0FycmF5QnVmZmVyVmlld1N1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9iKFtuZXcgVWludDhBcnJheSgxMDApXSkuc2l6ZSA9PT0gMTAwO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF0YVVSSTJCbG9iOiBmdW5jdGlvbiAoZGF0YVVSSSkge1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIHZhciBCbG9iQnVpbGRlciA9IHdpbmRvdy5CbG9iQnVpbGRlciB8fCB3aW5kb3cuV2ViS2l0QmxvYkJ1aWxkZXIgfHwgd2luZG93Lk1vekJsb2JCdWlsZGVyIHx8XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5NU0Jsb2JCdWlsZGVyLCBjYW5CbG9iID0gJGguaGFzQmxvYlN1cHBvcnQoKSwgYnl0ZVN0ciwgYXJyYXlCdWZmZXIsIGludEFycmF5LCBpLCBtaW1lU3RyLCBiYixcbiAgICAgICAgICAgICAgICBjYW5Qcm9jZWVkID0gKGNhbkJsb2IgfHwgQmxvYkJ1aWxkZXIpICYmIHdpbmRvdy5hdG9iICYmIHdpbmRvdy5BcnJheUJ1ZmZlciAmJiB3aW5kb3cuVWludDhBcnJheTtcbiAgICAgICAgICAgIGlmICghY2FuUHJvY2VlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRhdGFVUkkuc3BsaXQoJywnKVswXS5pbmRleE9mKCdiYXNlNjQnKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgYnl0ZVN0ciA9IGF0b2IoZGF0YVVSSS5zcGxpdCgnLCcpWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnl0ZVN0ciA9IGRlY29kZVVSSUNvbXBvbmVudChkYXRhVVJJLnNwbGl0KCcsJylbMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXJyYXlCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoYnl0ZVN0ci5sZW5ndGgpO1xuICAgICAgICAgICAgaW50QXJyYXkgPSBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYnl0ZVN0ci5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIGludEFycmF5W2ldID0gYnl0ZVN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWltZVN0ciA9IGRhdGFVUkkuc3BsaXQoJywnKVswXS5zcGxpdCgnOicpWzFdLnNwbGl0KCc7JylbMF07XG4gICAgICAgICAgICBpZiAoY2FuQmxvYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvYihbJGguaGFzQXJyYXlCdWZmZXJWaWV3U3VwcG9ydCgpID8gaW50QXJyYXkgOiBhcnJheUJ1ZmZlcl0sIHt0eXBlOiBtaW1lU3RyfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBiYiA9IG5ldyBCbG9iQnVpbGRlcigpO1xuICAgICAgICAgICAgYmIuYXBwZW5kKGFycmF5QnVmZmVyKTtcbiAgICAgICAgICAgIHJldHVybiBiYi5nZXRCbG9iKG1pbWVTdHIpO1xuICAgICAgICB9LFxuICAgICAgICBhZGRDc3M6IGZ1bmN0aW9uICgkZWwsIGNzcykge1xuICAgICAgICAgICAgJGVsLnJlbW92ZUNsYXNzKGNzcykuYWRkQ2xhc3MoY3NzKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RWxlbWVudDogZnVuY3Rpb24gKG9wdGlvbnMsIHBhcmFtLCB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuICgkaC5pc0VtcHR5KG9wdGlvbnMpIHx8ICRoLmlzRW1wdHkob3B0aW9uc1twYXJhbV0pKSA/IHZhbHVlIDogJChvcHRpb25zW3BhcmFtXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHVuaXFJZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgKyAoTWF0aC5yYW5kb20oKSAqIDEwMCkpO1xuICAgICAgICB9LFxuICAgICAgICBodG1sRW5jb2RlOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCAnJmFwb3M7Jyk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlcGxhY2VUYWdzOiBmdW5jdGlvbiAoc3RyLCB0YWdzKSB7XG4gICAgICAgICAgICB2YXIgb3V0ID0gc3RyO1xuICAgICAgICAgICAgaWYgKCF0YWdzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZWFjaCh0YWdzLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG91dCA9IG91dC5zcGxpdChrZXkpLmpvaW4odmFsdWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBjbGVhbk1lbW9yeTogZnVuY3Rpb24gKCR0aHVtYikge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSAkdGh1bWIuaXMoJ2ltZycpID8gJHRodW1iLmF0dHIoJ3NyYycpIDogJHRodW1iLmZpbmQoJ3NvdXJjZScpLmF0dHIoJ3NyYycpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgJGgub2JqVXJsLnJldm9rZU9iamVjdFVSTCAqL1xuICAgICAgICAgICAgJGgub2JqVXJsLnJldm9rZU9iamVjdFVSTChkYXRhKTtcbiAgICAgICAgfSxcbiAgICAgICAgZmluZEZpbGVOYW1lOiBmdW5jdGlvbiAoZmlsZVBhdGgpIHtcbiAgICAgICAgICAgIHZhciBzZXBJbmRleCA9IGZpbGVQYXRoLmxhc3RJbmRleE9mKCcvJyk7XG4gICAgICAgICAgICBpZiAoc2VwSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VwSW5kZXggPSBmaWxlUGF0aC5sYXN0SW5kZXhPZignXFxcXCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZpbGVQYXRoLnNwbGl0KGZpbGVQYXRoLnN1YnN0cmluZyhzZXBJbmRleCwgc2VwSW5kZXggKyAxKSkucG9wKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGNoZWNrRnVsbFNjcmVlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIHJldHVybiBkb2N1bWVudC5mdWxsc2NyZWVuRWxlbWVudCB8fCBkb2N1bWVudC5tb3pGdWxsU2NyZWVuRWxlbWVudCB8fCBkb2N1bWVudC53ZWJraXRGdWxsc2NyZWVuRWxlbWVudCB8fFxuICAgICAgICAgICAgICAgIGRvY3VtZW50Lm1zRnVsbHNjcmVlbkVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRvZ2dsZUZ1bGxTY3JlZW46IGZ1bmN0aW9uIChtYXhpbWl6ZSkge1xuICAgICAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LCBkZSA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZGUgJiYgbWF4aW1pemUgJiYgISRoLmNoZWNrRnVsbFNjcmVlbigpKSB7XG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQucmVxdWVzdEZ1bGxzY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC5tc1JlcXVlc3RGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubW96UmVxdWVzdEZ1bGxTY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIEVsZW1lbnQuQUxMT1dfS0VZQk9BUkRfSU5QVVQgKi9cbiAgICAgICAgICAgICAgICBpZiAoZGUucmVxdWVzdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUucmVxdWVzdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlLm1zUmVxdWVzdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUubXNSZXF1ZXN0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGUubW96UmVxdWVzdEZ1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUubW96UmVxdWVzdEZ1bGxTY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKEVsZW1lbnQuQUxMT1dfS0VZQk9BUkRfSU5QVVQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC5tc0V4aXRGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubW96Q2FuY2VsRnVsbFNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50LndlYmtpdEV4aXRGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgaWYgKGRvYy5leGl0RnVsbHNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2MuZXhpdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRvYy5tc0V4aXRGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvYy5tc0V4aXRGdWxsc2NyZWVuKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkb2MubW96Q2FuY2VsRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2MubW96Q2FuY2VsRnVsbFNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jLndlYmtpdEV4aXRGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvYy53ZWJraXRFeGl0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbW92ZUFycmF5OiBmdW5jdGlvbiAoYXJyLCBvbGRJbmRleCwgbmV3SW5kZXgpIHtcbiAgICAgICAgICAgIGlmIChuZXdJbmRleCA+PSBhcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGsgPSBuZXdJbmRleCAtIGFyci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgd2hpbGUgKChrLS0pICsgMSkge1xuICAgICAgICAgICAgICAgICAgICBhcnIucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFyci5zcGxpY2UobmV3SW5kZXgsIDAsIGFyci5zcGxpY2Uob2xkSW5kZXgsIDEpWzBdKTtcbiAgICAgICAgICAgIHJldHVybiBhcnI7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFuWm9vbUNhY2hlOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICAgICAgICB2YXIgJGNhY2hlID0gJGVsLmNsb3Nlc3QoJy5rdi16b29tLWNhY2hlLXRoZW1lJyk7XG4gICAgICAgICAgICBpZiAoISRjYWNoZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkY2FjaGUgPSAkZWwuY2xvc2VzdCgnLmt2LXpvb20tY2FjaGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRjYWNoZS5yZW1vdmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0T3JpZW50YXRpb246IGZ1bmN0aW9uIChidWZmZXIsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgc2Nhbm5lciA9IG5ldyBEYXRhVmlldyhidWZmZXIpLCBpZHggPSAwLCB2YWx1ZSA9IDEsIC8vIE5vbi1yb3RhdGVkIGlzIHRoZSBkZWZhdWx0XG4gICAgICAgICAgICAgICAgbWF4Qnl0ZXMsIHVJbnQxNiwgZXhpZkxlbmd0aDtcbiAgICAgICAgICAgIGlmIChzY2FubmVyLmdldFVpbnQxNihpZHgpICE9PSAweEZGRDggfHwgYnVmZmVyLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIG5vdCBhIHByb3BlciBKUEVHXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggKz0gMjtcbiAgICAgICAgICAgIG1heEJ5dGVzID0gc2Nhbm5lci5ieXRlTGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA8IG1heEJ5dGVzIC0gMikge1xuICAgICAgICAgICAgICAgIHVJbnQxNiA9IHNjYW5uZXIuZ2V0VWludDE2KGlkeCk7XG4gICAgICAgICAgICAgICAgaWR4ICs9IDI7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh1SW50MTYpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAweEZGRTE6IC8vIFN0YXJ0IG9mIEVYSUZcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aWZMZW5ndGggPSBzY2FubmVyLmdldFVpbnQxNihpZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qnl0ZXMgPSBleGlmTGVuZ3RoIC0gaWR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWR4ICs9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAweDAxMTI6IC8vIE9yaWVudGF0aW9uIHRhZ1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBzY2FubmVyLmdldFVpbnQxNihpZHggKyA2LCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhCeXRlcyA9IDA7IC8vIFN0b3Agc2Nhbm5pbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdmFsaWRhdGVPcmllbnRhdGlvbjogZnVuY3Rpb24gKGZpbGUsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBpZiAoIXdpbmRvdy5GaWxlUmVhZGVyIHx8ICF3aW5kb3cuRGF0YVZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIHNraXAgb3JpZW50YXRpb24gaWYgcHJlLXJlcXVpc2l0ZSBsaWJyYXJpZXMgbm90IHN1cHBvcnRlZCBieSBicm93c2VyXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKSwgYnVmZmVyO1xuICAgICAgICAgICAgcmVhZGVyLm9ubG9hZGVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBidWZmZXIgPSByZWFkZXIucmVzdWx0O1xuICAgICAgICAgICAgICAgICRoLnNldE9yaWVudGF0aW9uKGJ1ZmZlciwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihmaWxlKTtcbiAgICAgICAgfSxcbiAgICAgICAgYWRqdXN0T3JpZW50ZWRJbWFnZTogZnVuY3Rpb24gKCRpbWcsIGlzWm9vbSkge1xuICAgICAgICAgICAgdmFyIG9mZnNldENvbnRUb3AsIG9mZnNldFRvcCwgbmV3VG9wO1xuICAgICAgICAgICAgaWYgKCEkaW1nLmhhc0NsYXNzKCdpcy1wb3J0cmFpdC1ndDQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc1pvb20pIHtcbiAgICAgICAgICAgICAgICAkaW1nLmNzcyh7d2lkdGg6ICRpbWcucGFyZW50KCkuaGVpZ2h0KCl9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICRpbWcuY3NzKHtoZWlnaHQ6ICdhdXRvJywgd2lkdGg6ICRpbWcuaGVpZ2h0KCl9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9mZnNldENvbnRUb3AgPSAkaW1nLnBhcmVudCgpLm9mZnNldCgpLnRvcDtcbiAgICAgICAgICAgIG9mZnNldFRvcCA9ICRpbWcub2Zmc2V0KCkudG9wO1xuICAgICAgICAgICAgbmV3VG9wID0gb2Zmc2V0Q29udFRvcCAtIG9mZnNldFRvcDtcbiAgICAgICAgICAgICRpbWcuY3NzKCdtYXJnaW4tdG9wJywgbmV3VG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsZUlucHV0ID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBzZWxmLiRlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICAgICAgaWYgKCFzZWxmLl92YWxpZGF0ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5pc1ByZXZpZXdhYmxlID0gJGguaGFzRmlsZUFQSVN1cHBvcnQoKTtcbiAgICAgICAgc2VsZi5pc0lFOSA9ICRoLmlzSUUoOSk7XG4gICAgICAgIHNlbGYuaXNJRTEwID0gJGguaXNJRSgxMCk7XG4gICAgICAgIGlmIChzZWxmLmlzUHJldmlld2FibGUgfHwgc2VsZi5pc0lFOSkge1xuICAgICAgICAgICAgc2VsZi5faW5pdChvcHRpb25zKTtcbiAgICAgICAgICAgIHNlbGYuX2xpc3RlbigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5yZW1vdmVDbGFzcygnZmlsZS1sb2FkaW5nJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkR2xvYmFsU3ltYm9sc1xuICAgIEZpbGVJbnB1dC5wcm90b3R5cGUgPSB7XG4gICAgICAgIGNvbnN0cnVjdG9yOiBGaWxlSW5wdXQsXG4gICAgICAgIF9jbGVhbnVwOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLnJlYWRlciA9IG51bGw7XG4gICAgICAgICAgICBzZWxmLmZvcm1kYXRhID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuICAgICAgICAgICAgc2VsZi5hamF4UmVxdWVzdHMgPSBbXTtcbiAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICBzZWxmLmZpbGVCYXRjaENvbXBsZXRlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNQcmV2aWV3YWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuc2hvd1ByZXZpZXcgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5hamF4QWJvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5jYW5jZWxsaW5nID0gZmFsc2U7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0OiBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50LCAkY29udCwgdCwgdG1wO1xuICAgICAgICAgICAgc2VsZi5vcHRpb25zID0gb3B0aW9ucztcbiAgICAgICAgICAgICQuZWFjaChvcHRpb25zLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkZpbGVDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21heEZpbGVDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkZpbGVTaXplJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4RmlsZVNpemUnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtYXhGaWxlUHJldmlld1NpemUnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNpemVJbWFnZVF1YWxpdHknOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNpemVJZlNpemVNb3JlVGhhbic6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3Byb2dyZXNzVXBsb2FkVGhyZXNob2xkJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnaW5pdGlhbFByZXZpZXdDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3pvb21Nb2RhbEhlaWdodCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkltYWdlSGVpZ2h0JzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4SW1hZ2VIZWlnaHQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtaW5JbWFnZVdpZHRoJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4SW1hZ2VXaWR0aCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0gPSAkaC5nZXROdW0odmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHNlbGYucnRsKSB7IC8vIHN3YXAgYnV0dG9ucyBmb3IgcnRsXG4gICAgICAgICAgICAgICAgdG1wID0gc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLnByZXY7XG4gICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLnByZXYgPSBzZWxmLnByZXZpZXdab29tQnV0dG9uSWNvbnMubmV4dDtcbiAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdab29tQnV0dG9uSWNvbnMubmV4dCA9IHRtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2NsZWFudXAoKTtcbiAgICAgICAgICAgIHNlbGYuJGZvcm0gPSAkZWwuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFRlbXBsYXRlRGVmYXVsdHMoKTtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkRmlsZUF0dHIgPSAhJGguaXNFbXB0eSgkZWwuYXR0cignbmFtZScpKSA/ICRlbC5hdHRyKCduYW1lJykgOiAnZmlsZV9kYXRhJztcbiAgICAgICAgICAgIHQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgncHJvZ3Jlc3MnKTtcbiAgICAgICAgICAgIHNlbGYucHJvZ3Jlc3NUZW1wbGF0ZSA9IHQucmVwbGFjZSgne2NsYXNzfScsIHNlbGYucHJvZ3Jlc3NDbGFzcyk7XG4gICAgICAgICAgICBzZWxmLnByb2dyZXNzQ29tcGxldGVUZW1wbGF0ZSA9IHQucmVwbGFjZSgne2NsYXNzfScsIHNlbGYucHJvZ3Jlc3NDb21wbGV0ZUNsYXNzKTtcbiAgICAgICAgICAgIHNlbGYucHJvZ3Jlc3NFcnJvclRlbXBsYXRlID0gdC5yZXBsYWNlKCd7Y2xhc3N9Jywgc2VsZi5wcm9ncmVzc0Vycm9yQ2xhc3MpO1xuICAgICAgICAgICAgc2VsZi5kcm9wWm9uZUVuYWJsZWQgPSAkaC5oYXNEcmFnRHJvcFN1cHBvcnQoKSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZDtcbiAgICAgICAgICAgIHNlbGYuaXNEaXNhYmxlZCA9ICRlbC5hdHRyKCdkaXNhYmxlZCcpIHx8ICRlbC5hdHRyKCdyZWFkb25seScpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICRlbC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5pc1VwbG9hZGFibGUgPSAkaC5oYXNGaWxlVXBsb2FkU3VwcG9ydCgpICYmICEkaC5pc0VtcHR5KHNlbGYudXBsb2FkVXJsKTtcbiAgICAgICAgICAgIHNlbGYuaXNDbGlja2FibGUgPSBzZWxmLmJyb3dzZU9uWm9uZUNsaWNrICYmIHNlbGYuc2hvd1ByZXZpZXcgJiZcbiAgICAgICAgICAgICAgICAoc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQgfHwgISRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKTtcbiAgICAgICAgICAgIHNlbGYuc2x1ZyA9IHR5cGVvZiBvcHRpb25zLnNsdWdDYWxsYmFjayA9PT0gXCJmdW5jdGlvblwiID8gb3B0aW9ucy5zbHVnQ2FsbGJhY2sgOiBzZWxmLl9zbHVnRGVmYXVsdDtcbiAgICAgICAgICAgIHNlbGYubWFpblRlbXBsYXRlID0gc2VsZi5zaG93Q2FwdGlvbiA/IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdtYWluMScpIDogc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21haW4yJyk7XG4gICAgICAgICAgICBzZWxmLmNhcHRpb25UZW1wbGF0ZSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdjYXB0aW9uJyk7XG4gICAgICAgICAgICBzZWxmLnByZXZpZXdHZW5lcmljVGVtcGxhdGUgPSBzZWxmLl9nZXRQcmV2aWV3VGVtcGxhdGUoJ2dlbmVyaWMnKTtcbiAgICAgICAgICAgIGlmIChzZWxmLnJlc2l6ZUltYWdlICYmIChzZWxmLm1heEltYWdlV2lkdGggfHwgc2VsZi5tYXhJbWFnZUhlaWdodCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmltYWdlQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbWFnZUNhbnZhc0NvbnRleHQgPSBzZWxmLmltYWdlQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eSgkZWwuYXR0cignaWQnKSkpIHtcbiAgICAgICAgICAgICAgICAkZWwuYXR0cignaWQnLCAkaC51bmlxSWQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLm5hbWVzcGFjZSA9ICcuZmlsZWlucHV0XycgKyAkZWwuYXR0cignaWQnKS5yZXBsYWNlKC8tL2csICdfJyk7XG4gICAgICAgICAgICBpZiAoc2VsZi4kY29udGFpbmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIgPSBzZWxmLl9jcmVhdGVDb250YWluZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVmcmVzaENvbnRhaW5lcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGNvbnQgPSBzZWxmLiRjb250YWluZXI7XG4gICAgICAgICAgICBzZWxmLiRkcm9wWm9uZSA9ICRjb250LmZpbmQoJy5maWxlLWRyb3Atem9uZScpO1xuICAgICAgICAgICAgc2VsZi4kcHJvZ3Jlc3MgPSAkY29udC5maW5kKCcua3YtdXBsb2FkLXByb2dyZXNzJyk7XG4gICAgICAgICAgICBzZWxmLiRidG5VcGxvYWQgPSAkY29udC5maW5kKCcuZmlsZWlucHV0LXVwbG9hZCcpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lciA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsQ2FwdGlvbkNvbnRhaW5lcicsICRjb250LmZpbmQoJy5maWxlLWNhcHRpb24nKSk7XG4gICAgICAgICAgICBzZWxmLiRjYXB0aW9uID0gJGguZ2V0RWxlbWVudChvcHRpb25zLCAnZWxDYXB0aW9uVGV4dCcsICRjb250LmZpbmQoJy5maWxlLWNhcHRpb24tbmFtZScpKTtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXdDb250YWluZXIgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbFByZXZpZXdDb250YWluZXInLCAkY29udC5maW5kKCcuZmlsZS1wcmV2aWV3JykpO1xuICAgICAgICAgICAgc2VsZi4kcHJldmlldyA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsUHJldmlld0ltYWdlJywgJGNvbnQuZmluZCgnLmZpbGUtcHJldmlldy10aHVtYm5haWxzJykpO1xuICAgICAgICAgICAgc2VsZi4kcHJldmlld1N0YXR1cyA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsUHJldmlld1N0YXR1cycsICRjb250LmZpbmQoJy5maWxlLXByZXZpZXctc3RhdHVzJykpO1xuICAgICAgICAgICAgc2VsZi4kZXJyb3JDb250YWluZXIgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbEVycm9yQ29udGFpbmVyJyxcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3Q29udGFpbmVyLmZpbmQoJy5rdi1maWxlaW5wdXQtZXJyb3InKSk7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoc2VsZi5tc2dFcnJvckNsYXNzKSkge1xuICAgICAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRlcnJvckNvbnRhaW5lciwgc2VsZi5tc2dFcnJvckNsYXNzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGVycm9yQ29udGFpbmVyLmhpZGUoKTtcbiAgICAgICAgICAgIHNlbGYucHJldmlld0luaXRJZCA9IFwicHJldmlldy1cIiArICRoLnVuaXFJZCgpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdDYWNoZSgpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXcodHJ1ZSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgIHNlbGYuX3NldEZpbGVEcm9wWm9uZVRpdGxlKCk7XG4gICAgICAgICAgICAkZWwucmVtb3ZlQ2xhc3MoJ2ZpbGUtbG9hZGluZycpO1xuICAgICAgICAgICAgaWYgKCRlbC5hdHRyKCdkaXNhYmxlZCcpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5kaXNhYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9pbml0Wm9vbSgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaGlkZVRodW1ibmFpbENvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kcHJldmlldywgJ2hpZGUtY29udGVudCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaW5pdFRlbXBsYXRlRGVmYXVsdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdE1haW4xLCB0TWFpbjIsIHRQcmV2aWV3LCB0RmlsZUljb24sIHRDbG9zZSwgdENhcHRpb24sIHRCdG5EZWZhdWx0LCB0QnRuTGluaywgdEJ0bkJyb3dzZSxcbiAgICAgICAgICAgICAgICB0TW9kYWxNYWluLCB0TW9kYWwsIHRQcm9ncmVzcywgdFNpemUsIHRGb290ZXIsIHRBY3Rpb25zLCB0QWN0aW9uRGVsZXRlLCB0QWN0aW9uVXBsb2FkLCB0QWN0aW9uWm9vbSxcbiAgICAgICAgICAgICAgICB0QWN0aW9uRHJhZywgdEluZGljYXRvciwgdFRhZ0JlZiwgdFRhZ0JlZjEsIHRUYWdCZWYyLCB0VGFnQWZ0LCB0R2VuZXJpYywgdEh0bWwsIHRJbWFnZSwgdFRleHQsIHRWaWRlbyxcbiAgICAgICAgICAgICAgICB0QXVkaW8sIHRGbGFzaCwgdE9iamVjdCwgdFBkZiwgdE90aGVyLCB0Wm9vbUNhY2hlLCB2RGVmYXVsdERpbTtcbiAgICAgICAgICAgIHRNYWluMSA9ICd7cHJldmlld31cXG4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImt2LXVwbG9hZC1wcm9ncmVzcyBoaWRlXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cCB7Y2xhc3N9XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgIHtjYXB0aW9ufVxcbicgK1xuICAgICAgICAgICAgICAgICcgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICB7cmVtb3ZlfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAge2NhbmNlbH1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgIHt1cGxvYWR9XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICB7YnJvd3NlfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgICAgIHRNYWluMiA9ICd7cHJldmlld31cXG48ZGl2IGNsYXNzPVwia3YtdXBsb2FkLXByb2dyZXNzIGhpZGVcIj48L2Rpdj5cXG57cmVtb3ZlfVxcbntjYW5jZWx9XFxue3VwbG9hZH1cXG57YnJvd3NlfVxcbic7XG4gICAgICAgICAgICB0UHJldmlldyA9ICc8ZGl2IGNsYXNzPVwiZmlsZS1wcmV2aWV3IHtjbGFzc31cIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIHtjbG9zZX0nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJ7ZHJvcENsYXNzfVwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy10aHVtYm5haWxzXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPjwvZGl2PicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy1zdGF0dXMgdGV4dC1jZW50ZXIgdGV4dC1zdWNjZXNzXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwia3YtZmlsZWlucHV0LWVycm9yXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgICAgIHRDbG9zZSA9ICc8ZGl2IGNsYXNzPVwiY2xvc2UgZmlsZWlucHV0LXJlbW92ZVwiPiZ0aW1lczs8L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEZpbGVJY29uID0gJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1maWxlIGt2LWNhcHRpb24taWNvblwiPjwvaT4nO1xuICAgICAgICAgICAgdENhcHRpb24gPSAnPGRpdiB0YWJpbmRleD1cIjUwMFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGZpbGUtY2FwdGlvbiB7Y2xhc3N9XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgIDxkaXYgY2xhc3M9XCJmaWxlLWNhcHRpb24tbmFtZVwiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj5cXG4nO1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSHRtbFVua25vd25BdHRyaWJ1dGVcbiAgICAgICAgICAgIHRCdG5EZWZhdWx0ID0gJzxidXR0b24gdHlwZT1cInt0eXBlfVwiIHRhYmluZGV4PVwiNTAwXCIgdGl0bGU9XCJ7dGl0bGV9XCIgY2xhc3M9XCJ7Y3NzfVwiICcgK1xuICAgICAgICAgICAgICAgICd7c3RhdHVzfT57aWNvbn0ge2xhYmVsfTwvYnV0dG9uPic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEJ0bkxpbmsgPSAnPGEgaHJlZj1cIntocmVmfVwiIHRhYmluZGV4PVwiNTAwXCIgdGl0bGU9XCJ7dGl0bGV9XCIgY2xhc3M9XCJ7Y3NzfVwiIHtzdGF0dXN9PntpY29ufSB7bGFiZWx9PC9hPic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEJ0bkJyb3dzZSA9ICc8ZGl2IHRhYmluZGV4PVwiNTAwXCIgY2xhc3M9XCJ7Y3NzfVwiIHtzdGF0dXN9PntpY29ufSB7bGFiZWx9PC9kaXY+JztcbiAgICAgICAgICAgIHRNb2RhbE1haW4gPSAnPGRpdiBpZD1cIicgKyAkaC5NT0RBTF9JRCArICdcIiBjbGFzcz1cImZpbGUtem9vbS1kaWFsb2cgbW9kYWwgZmFkZVwiICcgK1xuICAgICAgICAgICAgICAgICd0YWJpbmRleD1cIi0xXCIgYXJpYS1sYWJlbGxlZGJ5PVwiJyArICRoLk1PREFMX0lEICsgJ0xhYmVsXCI+PC9kaXY+JztcbiAgICAgICAgICAgIHRNb2RhbCA9ICc8ZGl2IGNsYXNzPVwibW9kYWwtZGlhbG9nIG1vZGFsLWxne3J0bH1cIiByb2xlPVwiZG9jdW1lbnRcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwibW9kYWwtY29udGVudFwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIm1vZGFsLWhlYWRlclwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICA8ZGl2IGNsYXNzPVwia3Ytem9vbS1hY3Rpb25zIHB1bGwtcmlnaHRcIj57dG9nZ2xlaGVhZGVyfXtmdWxsc2NyZWVufXtib3JkZXJsZXNzfXtjbG9zZX08L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgPGgzIGNsYXNzPVwibW9kYWwtdGl0bGVcIj57aGVhZGluZ30gPHNtYWxsPjxzcGFuIGNsYXNzPVwia3Ytem9vbS10aXRsZVwiPjwvc3Bhbj48L3NtYWxsPjwvaDM+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgIDxkaXYgY2xhc3M9XCJmbG9hdGluZy1idXR0b25zXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgIDxkaXYgY2xhc3M9XCJrdi16b29tLWJvZHkgZmlsZS16b29tLWNvbnRlbnQge3pvb21GcmFtZUNsYXNzfVwiPjwvZGl2PlxcbicgKyAne3ByZXZ9IHtuZXh0fVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Plxcbic7XG4gICAgICAgICAgICB0UHJvZ3Jlc3MgPSAnPGRpdiBjbGFzcz1cInByb2dyZXNzXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwie2NsYXNzfVwiIHJvbGU9XCJwcm9ncmVzc2JhclwiJyArXG4gICAgICAgICAgICAgICAgJyBhcmlhLXZhbHVlbm93PVwie3BlcmNlbnR9XCIgYXJpYS12YWx1ZW1pbj1cIjBcIiBhcmlhLXZhbHVlbWF4PVwiMTAwXCIgc3R5bGU9XCJ3aWR0aDp7cGVyY2VudH0lO1wiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAgIHtzdGF0dXN9XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICB0U2l6ZSA9ICcgPHNhbXA+KHtzaXplVGV4dH0pPC9zYW1wPic7XG4gICAgICAgICAgICB0Rm9vdGVyID0gJzxkaXYgY2xhc3M9XCJmaWxlLXRodW1ibmFpbC1mb290ZXJcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLWZvb3Rlci1jYXB0aW9uXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIj57Y2FwdGlvbn08YnI+e3NpemV9PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICB7cHJvZ3Jlc3N9IHtpbmRpY2F0b3J9IHthY3Rpb25zfVxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICAgICAgdEFjdGlvbnMgPSAne2RyYWd9XFxuJyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmaWxlLWFjdGlvbnNcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLWZvb3Rlci1idXR0b25zXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICAge3VwbG9hZH0ge2RlbGV0ZX0ge3pvb219IHtvdGhlcn0nICtcbiAgICAgICAgICAgICAgICAnICAgIDwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImNsZWFyZml4XCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEFjdGlvbkRlbGV0ZSA9ICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImt2LWZpbGUtcmVtb3ZlIHtyZW1vdmVDbGFzc31cIiAnICtcbiAgICAgICAgICAgICAgICAndGl0bGU9XCJ7cmVtb3ZlVGl0bGV9XCIge2RhdGFVcmx9e2RhdGFLZXl9PntyZW1vdmVJY29ufTwvYnV0dG9uPlxcbic7XG4gICAgICAgICAgICB0QWN0aW9uVXBsb2FkID0gJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwia3YtZmlsZS11cGxvYWQge3VwbG9hZENsYXNzfVwiIHRpdGxlPVwie3VwbG9hZFRpdGxlfVwiPicgK1xuICAgICAgICAgICAgICAgICd7dXBsb2FkSWNvbn08L2J1dHRvbj4nO1xuICAgICAgICAgICAgdEFjdGlvblpvb20gPSAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrdi1maWxlLXpvb20ge3pvb21DbGFzc31cIiAnICtcbiAgICAgICAgICAgICAgICAndGl0bGU9XCJ7em9vbVRpdGxlfVwiPnt6b29tSWNvbn08L2J1dHRvbj4nO1xuICAgICAgICAgICAgdEFjdGlvbkRyYWcgPSAnPHNwYW4gY2xhc3M9XCJmaWxlLWRyYWctaGFuZGxlIHtkcmFnQ2xhc3N9XCIgdGl0bGU9XCJ7ZHJhZ1RpdGxlfVwiPntkcmFnSWNvbn08L3NwYW4+JztcbiAgICAgICAgICAgIHRJbmRpY2F0b3IgPSAnPGRpdiBjbGFzcz1cImZpbGUtdXBsb2FkLWluZGljYXRvclwiIHRpdGxlPVwie2luZGljYXRvclRpdGxlfVwiPntpbmRpY2F0b3J9PC9kaXY+JztcbiAgICAgICAgICAgIHRUYWdCZWYgPSAnPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy1mcmFtZSB7ZnJhbWVDbGFzc31cIiBpZD1cIntwcmV2aWV3SWR9XCIgZGF0YS1maWxlaW5kZXg9XCJ7ZmlsZWluZGV4fVwiJyArXG4gICAgICAgICAgICAgICAgJyBkYXRhLXRlbXBsYXRlPVwie3RlbXBsYXRlfVwiJztcbiAgICAgICAgICAgIHRUYWdCZWYxID0gdFRhZ0JlZiArICc+PGRpdiBjbGFzcz1cImt2LWZpbGUtY29udGVudFwiPlxcbic7XG4gICAgICAgICAgICB0VGFnQmVmMiA9IHRUYWdCZWYgKyAnIHRpdGxlPVwie2NhcHRpb259XCI+PGRpdiBjbGFzcz1cImt2LWZpbGUtY29udGVudFwiPlxcbic7XG4gICAgICAgICAgICB0VGFnQWZ0ID0gJzwvZGl2Pntmb290ZXJ9XFxuPC9kaXY+XFxuJztcbiAgICAgICAgICAgIHRHZW5lcmljID0gJ3tjb250ZW50fVxcbic7XG4gICAgICAgICAgICB0SHRtbCA9ICc8ZGl2IGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy1odG1sXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiAnICsgJGguU1RZTEVfU0VUVElORyArXG4gICAgICAgICAgICAgICAgJz57ZGF0YX08L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEltYWdlID0gJzxpbWcgc3JjPVwie2RhdGF9XCIgY2xhc3M9XCJmaWxlLXByZXZpZXctaW1hZ2Uga3YtcHJldmlldy1kYXRhXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiBhbHQ9XCJ7Y2FwdGlvbn1cIiAnICtcbiAgICAgICAgICAgICAgICAkaC5TVFlMRV9TRVRUSU5HICsgJz5cXG4nO1xuICAgICAgICAgICAgdFRleHQgPSAnPHRleHRhcmVhIGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy10ZXh0XCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiByZWFkb25seSAnICtcbiAgICAgICAgICAgICAgICAkaC5TVFlMRV9TRVRUSU5HICsgJz57ZGF0YX08L3RleHRhcmVhPlxcbic7XG4gICAgICAgICAgICB0VmlkZW8gPSAnPHZpZGVvIGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy12aWRlb1wiIHdpZHRoPVwie3dpZHRofVwiICcgK1xuICAgICAgICAgICAgICAgICdoZWlnaHQ9XCJ7aGVpZ2h0fVwiIGNvbnRyb2xzPlxcbicgKyAnPHNvdXJjZSBzcmM9XCJ7ZGF0YX1cIiB0eXBlPVwie3R5cGV9XCI+XFxuJyArICRoLkRFRkFVTFRfUFJFVklFVyArXG4gICAgICAgICAgICAgICAgJ1xcbjwvdmlkZW8+XFxuJztcbiAgICAgICAgICAgIHRBdWRpbyA9ICc8ZGl2IGNsYXNzPVwiZmlsZS1wcmV2aWV3LWF1ZGlvXCI+PGF1ZGlvIGNsYXNzPVwia3YtcHJldmlldy1kYXRhXCIgY29udHJvbHM+XFxuPHNvdXJjZSBzcmM9XCJ7ZGF0YX1cIiAnICtcbiAgICAgICAgICAgICAgICAndHlwZT1cInt0eXBlfVwiPlxcbicgKyAkaC5ERUZBVUxUX1BSRVZJRVcgKyAnXFxuPC9hdWRpbz48L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEZsYXNoID0gJzxvYmplY3QgY2xhc3M9XCJrdi1wcmV2aWV3LWRhdGEgZmlsZS1vYmplY3RcIiB0eXBlPVwiYXBwbGljYXRpb24veC1zaG9ja3dhdmUtZmxhc2hcIiAnICtcbiAgICAgICAgICAgICAgICAnd2lkdGg9XCJ7d2lkdGh9XCIgaGVpZ2h0PVwie2hlaWdodH1cIiBkYXRhPVwie2RhdGF9XCI+XFxuJyArICRoLk9CSkVDVF9QQVJBTVMgKyAnICcgKyAkaC5ERUZBVUxUX1BSRVZJRVcgK1xuICAgICAgICAgICAgICAgICdcXG48L29iamVjdD5cXG4nO1xuICAgICAgICAgICAgdE9iamVjdCA9ICc8b2JqZWN0IGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtb2JqZWN0IHt0eXBlQ3NzfVwiIGRhdGE9XCJ7ZGF0YX1cIiB0eXBlPVwie3R5cGV9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3dpZHRoPVwie3dpZHRofVwiIGhlaWdodD1cIntoZWlnaHR9XCI+XFxuJyArICc8cGFyYW0gbmFtZT1cIm1vdmllXCIgdmFsdWU9XCJ7Y2FwdGlvbn1cIiAvPlxcbicgK1xuICAgICAgICAgICAgICAgICRoLk9CSkVDVF9QQVJBTVMgKyAnICcgKyAkaC5ERUZBVUxUX1BSRVZJRVcgKyAnXFxuPC9vYmplY3Q+XFxuJztcbiAgICAgICAgICAgIHRQZGYgPSAnPGVtYmVkIGNsYXNzPVwia3YtcHJldmlldy1kYXRhXCIgc3JjPVwie2RhdGF9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3dpZHRoPVwie3dpZHRofVwiIGhlaWdodD1cIntoZWlnaHR9XCIgdHlwZT1cImFwcGxpY2F0aW9uL3BkZlwiPlxcbic7XG4gICAgICAgICAgICB0T3RoZXIgPSAnPGRpdiBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLXByZXZpZXctb3RoZXItZnJhbWVcIj5cXG4nICsgJGguREVGQVVMVF9QUkVWSUVXICsgJ1xcbjwvZGl2Plxcbic7XG4gICAgICAgICAgICB0Wm9vbUNhY2hlID0gJzxkaXYgY2xhc3M9XCJrdi16b29tLWNhY2hlXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmVcIj57em9vbUNvbnRlbnR9PC9kaXY+JztcbiAgICAgICAgICAgIHZEZWZhdWx0RGltID0ge3dpZHRoOiBcIjEwMCVcIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9O1xuICAgICAgICAgICAgc2VsZi5kZWZhdWx0cyA9IHtcbiAgICAgICAgICAgICAgICBsYXlvdXRUZW1wbGF0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgbWFpbjE6IHRNYWluMSxcbiAgICAgICAgICAgICAgICAgICAgbWFpbjI6IHRNYWluMixcbiAgICAgICAgICAgICAgICAgICAgcHJldmlldzogdFByZXZpZXcsXG4gICAgICAgICAgICAgICAgICAgIGNsb3NlOiB0Q2xvc2UsXG4gICAgICAgICAgICAgICAgICAgIGZpbGVJY29uOiB0RmlsZUljb24sXG4gICAgICAgICAgICAgICAgICAgIGNhcHRpb246IHRDYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICBtb2RhbE1haW46IHRNb2RhbE1haW4sXG4gICAgICAgICAgICAgICAgICAgIG1vZGFsOiB0TW9kYWwsXG4gICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiB0UHJvZ3Jlc3MsXG4gICAgICAgICAgICAgICAgICAgIHNpemU6IHRTaXplLFxuICAgICAgICAgICAgICAgICAgICBmb290ZXI6IHRGb290ZXIsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvcjogdEluZGljYXRvcixcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uczogdEFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbkRlbGV0ZTogdEFjdGlvbkRlbGV0ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uVXBsb2FkOiB0QWN0aW9uVXBsb2FkLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25ab29tOiB0QWN0aW9uWm9vbSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uRHJhZzogdEFjdGlvbkRyYWcsXG4gICAgICAgICAgICAgICAgICAgIGJ0bkRlZmF1bHQ6IHRCdG5EZWZhdWx0LFxuICAgICAgICAgICAgICAgICAgICBidG5MaW5rOiB0QnRuTGluayxcbiAgICAgICAgICAgICAgICAgICAgYnRuQnJvd3NlOiB0QnRuQnJvd3NlLFxuICAgICAgICAgICAgICAgICAgICB6b29tQ2FjaGU6IHRab29tQ2FjaGVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdNYXJrdXBUYWdzOiB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ0JlZm9yZTE6IHRUYWdCZWYxLFxuICAgICAgICAgICAgICAgICAgICB0YWdCZWZvcmUyOiB0VGFnQmVmMixcbiAgICAgICAgICAgICAgICAgICAgdGFnQWZ0ZXI6IHRUYWdBZnRcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdDb250ZW50VGVtcGxhdGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGdlbmVyaWM6IHRHZW5lcmljLFxuICAgICAgICAgICAgICAgICAgICBodG1sOiB0SHRtbCxcbiAgICAgICAgICAgICAgICAgICAgaW1hZ2U6IHRJbWFnZSxcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogdFRleHQsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0VmlkZW8sXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0QXVkaW8sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiB0Rmxhc2gsXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdDogdE9iamVjdCxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiB0UGRmLFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjogdE90aGVyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbGxvd2VkUHJldmlld1R5cGVzOiBbJ2ltYWdlJywgJ2h0bWwnLCAndGV4dCcsICd2aWRlbycsICdhdWRpbycsICdmbGFzaCcsICdwZGYnLCAnb2JqZWN0J10sXG4gICAgICAgICAgICAgICAgcHJldmlld1RlbXBsYXRlczoge30sXG4gICAgICAgICAgICAgICAgcHJldmlld1NldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIGh0bWw6IHt3aWR0aDogXCIyMTNweFwiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHt3aWR0aDogXCIyMTNweFwiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTAwJVwiLCAnbWF4LXdpZHRoJzogXCIxMDAlXCJ9LFxuICAgICAgICAgICAgICAgICAgICBhdWRpbzoge3dpZHRoOiBcIjEwMCVcIiwgaGVpZ2h0OiBcIjMwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTAwJVwiLCAnbWF4LXdpZHRoJzogXCIxMDAlXCJ9LFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IHtoZWlnaHQ6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiB7d2lkdGg6IFwiMTYwcHhcIiwgaGVpZ2h0OiBcIjE2MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjoge3dpZHRoOiBcIjE2MHB4XCIsIGhlaWdodDogXCIxNjBweFwifVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcHJldmlld1pvb21TZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZToge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcImF1dG9cIiwgJ21heC13aWR0aCc6IFwiMTAwJVwiLCAnbWF4LWhlaWdodCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgaHRtbDogdkRlZmF1bHREaW0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHZEZWZhdWx0RGltLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21heC13aWR0aCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW86IHt3aWR0aDogXCIxMDAlXCIsIGhlaWdodDogXCIzMHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBmbGFzaDoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjQ4MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCIxMDAlXCIsICdtYXgtd2lkdGgnOiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBwZGY6IHZEZWZhdWx0RGltLFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmaWxlVHlwZVNldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2ltYWdlLionKSB8fCAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKGdpZnxwbmd8anBlP2cpJC9pKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgaHRtbDogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICd0ZXh0L2h0bWwnKSB8fCAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKGh0bXxodG1sKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IGZ1bmN0aW9uICh2VHlwZSwgdk5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkaC5jb21wYXJlKHZUeXBlLCAndGV4dC4qJykgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLih4bWx8amF2YXNjcmlwdCkkL2kpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguY29tcGFyZSh2TmFtZSwgL1xcLih0eHR8bWR8Y3N2fG5mb3xpbml8anNvbnxwaHB8anN8Y3NzKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ3ZpZGVvLionKSAmJiAoJGguY29tcGFyZSh2VHlwZSwgLyhvZ2d8bXA0fG1wP2d8bW92fHdlYm18M2dwKSQvaSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKG9nP3xtcDR8d2VibXxtcD9nfG1vdnwzZ3ApJC9pKSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2F1ZGlvLionKSAmJiAoJGguY29tcGFyZSh2TmFtZSwgLyhvZ2d8bXAzfG1wP2d8d2F2KSQvaSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKG9nP3xtcDN8bXA/Z3x3YXYpJC9pKSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2FwcGxpY2F0aW9uL3gtc2hvY2t3YXZlLWZsYXNoJywgdHJ1ZSkgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLihzd2YpJC9pKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2FwcGxpY2F0aW9uL3BkZicsIHRydWUpIHx8ICRoLmNvbXBhcmUodk5hbWUsIC9cXC4ocGRmKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG90aGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmlsZUFjdGlvblNldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIHNob3dSZW1vdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNob3dVcGxvYWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNob3dab29tOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBzaG93RHJhZzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmFzaCB0ZXh0LWRhbmdlclwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICByZW1vdmVDbGFzczogJ2J0biBidG4teHMgYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICByZW1vdmVUaXRsZTogJ1JlbW92ZSBmaWxlJyxcbiAgICAgICAgICAgICAgICAgICAgdXBsb2FkSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi11cGxvYWQgdGV4dC1pbmZvXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZENsYXNzOiAnYnRuIGJ0bi14cyBidG4tZGVmYXVsdCcsXG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZFRpdGxlOiAnVXBsb2FkIGZpbGUnLFxuICAgICAgICAgICAgICAgICAgICB6b29tSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi16b29tLWluXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIHpvb21DbGFzczogJ2J0biBidG4teHMgYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICB6b29tVGl0bGU6ICdWaWV3IERldGFpbHMnLFxuICAgICAgICAgICAgICAgICAgICBkcmFnSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1tZW51LWhhbWJ1cmdlclwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBkcmFnQ2xhc3M6ICd0ZXh0LWluZm8nLFxuICAgICAgICAgICAgICAgICAgICBkcmFnVGl0bGU6ICdNb3ZlIC8gUmVhcnJhbmdlJyxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1NldHRpbmdzOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yTmV3OiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWhhbmQtZG93biB0ZXh0LXdhcm5pbmdcIj48L2k+JyxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yU3VjY2VzczogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1vay1zaWduIHRleHQtc3VjY2Vzc1wiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JFcnJvcjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1leGNsYW1hdGlvbi1zaWduIHRleHQtZGFuZ2VyXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvckxvYWRpbmc6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24taGFuZC11cCB0ZXh0LW11dGVkXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvck5ld1RpdGxlOiAnTm90IHVwbG9hZGVkIHlldCcsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvclN1Y2Nlc3NUaXRsZTogJ1VwbG9hZGVkJyxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yRXJyb3JUaXRsZTogJ1VwbG9hZCBFcnJvcicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvckxvYWRpbmdUaXRsZTogJ1VwbG9hZGluZyAuLi4nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICQuZWFjaChzZWxmLmRlZmF1bHRzLCBmdW5jdGlvbiAoa2V5LCBzZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2FsbG93ZWRQcmV2aWV3VHlwZXMnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmFsbG93ZWRQcmV2aWV3VHlwZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzID0gc2V0dGluZztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGZba2V5XSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBzZXR0aW5nLCBzZWxmW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld1RlbXBsYXRlcygpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXdUZW1wbGF0ZXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2ZnID0gc2VsZi5kZWZhdWx0cywgdGFncyA9IHNlbGYucHJldmlld01hcmt1cFRhZ3MsIHRhZ0JlZiwgdGFnQWZ0ID0gdGFncy50YWdBZnRlcjtcbiAgICAgICAgICAgICQuZWFjaChjZmcucHJldmlld0NvbnRlbnRUZW1wbGF0ZXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoc2VsZi5wcmV2aWV3VGVtcGxhdGVzW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ0JlZiA9IHRhZ3MudGFnQmVmb3JlMjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2dlbmVyaWMnIHx8IGtleSA9PT0gJ2ltYWdlJyB8fCBrZXkgPT09ICdodG1sJyB8fCBrZXkgPT09ICd0ZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnQmVmID0gdGFncy50YWdCZWZvcmUxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld1RlbXBsYXRlc1trZXldID0gdGFnQmVmICsgdmFsdWUgKyB0YWdBZnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0UHJldmlld0NhY2hlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZSA9IHtcbiAgICAgICAgICAgICAgICBkYXRhOiB7fSxcbiAgICAgICAgICAgICAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZW50ID0gc2VsZi5pbml0aWFsUHJldmlldztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMCAmJiAhJGguaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3BsaXQoc2VsZi5pbml0aWFsUHJldmlld0RlbGltaXRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmZXRjaDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50LmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4gIT09IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY291bnQ6IGZ1bmN0aW9uIChhbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSAmJiAhIXNlbGYucHJldmlld0NhY2hlLmRhdGEuY29udGVudCA/XG4gICAgICAgICAgICAgICAgICAgICAgICAoYWxsID8gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50Lmxlbmd0aCA6IHNlbGYucHJldmlld0NhY2hlLmZldGNoKCkubGVuZ3RoKSA6IDA7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIChpLCBpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmQgPSAnaW5pdF8nICsgaSwgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGRhdGEuY29udGVudFtpXSwgcHJldmlld0lkID0gc2VsZi5wcmV2aWV3SW5pdElkICsgJy0nICsgaW5kLCBvdXQsICR0bXAsIGNhdCwgZnRyLFxuICAgICAgICAgICAgICAgICAgICAgICAgZm5hbWUsIGZ0eXBlLCBmcmFtZUNsYXNzLCBhc0RhdGEgPSAkaC5pZlNldCgncHJldmlld0FzRGF0YScsIGNvbmZpZywgc2VsZi5pbml0aWFsUHJldmlld0FzRGF0YSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJzZVRlbXBsYXRlID0gZnVuY3Rpb24gKGNhdCwgZGF0LCBmbiwgZnQsIGlkLCBmdHIsIGluZCwgZmMsIHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYyA9ICcgZmlsZS1wcmV2aWV3LWluaXRpYWwgJyArICRoLlNPUlRfQ1NTICsgKGZjID8gJyAnICsgZmMgOiAnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dlbmVyYXRlUHJldmlld1RlbXBsYXRlKGNhdCwgZGF0LCBmbiwgZnQsIGlkLCBmYWxzZSwgbnVsbCwgZmMsIGZ0ciwgaW5kLCB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29udGVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQgPSBpc0Rpc2FibGVkID09PSB1bmRlZmluZWQgPyB0cnVlIDogaXNEaXNhYmxlZDtcbiAgICAgICAgICAgICAgICAgICAgY2F0ID0gJGguaWZTZXQoJ3R5cGUnLCBjb25maWcsIHNlbGYuaW5pdGlhbFByZXZpZXdGaWxlVHlwZSB8fCAnZ2VuZXJpYycpO1xuICAgICAgICAgICAgICAgICAgICBmbmFtZSA9ICRoLmlmU2V0KCdmaWxlbmFtZScsIGNvbmZpZywgJGguaWZTZXQoJ2NhcHRpb24nLCBjb25maWcpKTtcbiAgICAgICAgICAgICAgICAgICAgZnR5cGUgPSAkaC5pZlNldCgnZmlsZXR5cGUnLCBjb25maWcsIGNhdCk7XG4gICAgICAgICAgICAgICAgICAgIGZ0ciA9IHNlbGYucHJldmlld0NhY2hlLmZvb3RlcihpLCBpc0Rpc2FibGVkLCAoY29uZmlnICYmIGNvbmZpZy5zaXplIHx8IG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVDbGFzcyA9ICRoLmlmU2V0KCdmcmFtZUNsYXNzJywgY29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFzRGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gcGFyc2VUZW1wbGF0ZShjYXQsIGNvbnRlbnQsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBmdHIsIGluZCwgZnJhbWVDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSBwYXJzZVRlbXBsYXRlKCdnZW5lcmljJywgY29udGVudCwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGZ0ciwgaW5kLCBmcmFtZUNsYXNzLCBjYXQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFRva2Vucyh7J2NvbnRlbnQnOiBkYXRhLmNvbnRlbnRbaV19KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS50YWdzLmxlbmd0aCAmJiBkYXRhLnRhZ3NbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9ICRoLnJlcGxhY2VUYWdzKG91dCwgZGF0YS50YWdzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBjb25maWcuZnJhbWVBdHRyICovXG4gICAgICAgICAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShjb25maWcpICYmICEkaC5pc0VtcHR5KGNvbmZpZy5mcmFtZUF0dHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdG1wID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaHRtbChvdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRtcC5maW5kKCcuZmlsZS1wcmV2aWV3LWluaXRpYWwnKS5hdHRyKGNvbmZpZy5mcmFtZUF0dHIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gJHRtcC5odG1sKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdG1wLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhZGQ6IGZ1bmN0aW9uIChjb250ZW50LCBjb25maWcsIHRhZ3MsIGFwcGVuZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGluZGV4O1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRoLmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNwbGl0KHNlbGYuaW5pdGlhbFByZXZpZXdEZWxpbWl0ZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gZGF0YS5jb250ZW50LnB1c2goY29udGVudCkgLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWdbaW5kZXhdID0gY29uZmlnO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzW2luZGV4XSA9IHRhZ3M7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGNvbnRlbnQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29udGVudCA9IGNvbnRlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFncyA9IHRhZ3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKGNvbnRlbnQsIGNvbmZpZywgdGFncywgYXBwZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSwgaSwgY2hrO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbnRlbnQgfHwgIWNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkaC5pc0FycmF5KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gY29udGVudC5zcGxpdChzZWxmLmluaXRpYWxQcmV2aWV3RGVsaW1pdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjaGsgPSBjb250ZW50LmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4gIT09IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNoay5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5jb250ZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29udGVudCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNvbmZpZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnRhZ3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzID0gW107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFwcGVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbnRlbnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udGVudFtpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQucHVzaChjb250ZW50W2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29uZmlnLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpZ1tpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZy5wdXNoKGNvbmZpZ1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3MucHVzaCh0YWdzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQgPSBjb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWcgPSBjb25maWc7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3MgPSB0YWdzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdW5zZXQ6IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hrID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hrID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbnRlbnQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEuY29uZmlnID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLnRhZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbnRlbnRbaW5kZXhdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb25maWdbaW5kZXhdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS50YWdzW2luZGV4XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvdXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGh0bWwgPSAnJywgY2FwdGlvbiwgbGVuID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQodHJ1ZSksIGk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZW4gPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7Y29udGVudDogJycsIGNhcHRpb246ICcnfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gc2VsZi5wcmV2aWV3Q2FjaGUuZ2V0KGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzZWxmLl9nZXRNc2dTZWxlY3RlZChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtjb250ZW50OiBodG1sLCBjYXB0aW9uOiBjYXB0aW9ufTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZvb3RlcjogZnVuY3Rpb24gKGksIGlzRGlzYWJsZWQsIHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuY29uZmlnIHx8IGRhdGEuY29uZmlnLmxlbmd0aCA9PT0gMCB8fCAkaC5pc0VtcHR5KGRhdGEuY29uZmlnW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQgPSBpc0Rpc2FibGVkID09PSB1bmRlZmluZWQgPyB0cnVlIDogaXNEaXNhYmxlZDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldLCBjYXB0aW9uID0gJGguaWZTZXQoJ2NhcHRpb24nLCBjb25maWcpLCBhY3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAkaC5pZlNldCgnd2lkdGgnLCBjb25maWcsICdhdXRvJyksIHVybCA9ICRoLmlmU2V0KCd1cmwnLCBjb25maWcsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICRoLmlmU2V0KCdrZXknLCBjb25maWcsIG51bGwpLCBmcyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdFByZXZpZXdTaG93RGVsID0gc2VsZi5pbml0aWFsUHJldmlld1Nob3dEZWxldGUgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93RGVsID0gJGguaWZTZXQoJ3Nob3dEZWxldGUnLCBjb25maWcsICRoLmlmU2V0KCdzaG93RGVsZXRlJywgZnMsIGluaXRQcmV2aWV3U2hvd0RlbCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd1pvb20gPSAkaC5pZlNldCgnc2hvd1pvb20nLCBjb25maWcsICRoLmlmU2V0KCdzaG93Wm9vbScsIGZzLCB0cnVlKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93RHJhZyA9ICRoLmlmU2V0KCdzaG93RHJhZycsIGNvbmZpZywgJGguaWZTZXQoJ3Nob3dEcmFnJywgZnMsIHRydWUpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkID0gKHVybCA9PT0gZmFsc2UpICYmIGlzRGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnMgPSBzZWxmLl9yZW5kZXJGaWxlQWN0aW9ucyhmYWxzZSwgc2hvd0RlbCwgc2hvd1pvb20sIHNob3dEcmFnLCBkaXNhYmxlZCwgdXJsLCBrZXksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Zvb3RlcicpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAncHJvZ3Jlc3MnOiBzZWxmLl9yZW5kZXJUaHVtYlByb2dyZXNzKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAnYWN0aW9ucyc6IGFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZSc6IHNlbGYuX2dldFNpemUoc2l6ZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdpbmRpY2F0b3InOiAnJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuaW5pdCgpO1xuICAgICAgICB9LFxuICAgICAgICBfaGFuZGxlcjogZnVuY3Rpb24gKCRlbCwgZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIG5zID0gc2VsZi5uYW1lc3BhY2UsIGV2ID0gZXZlbnQuc3BsaXQoJyAnKS5qb2luKG5zICsgJyAnKSArIG5zO1xuICAgICAgICAgICAgaWYgKCEkZWwgfHwgISRlbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkZWwub2ZmKGV2KS5vbihldiwgY2FsbGJhY2spO1xuICAgICAgICB9LFxuICAgICAgICBfbG9nOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGlkID0gc2VsZi4kZWxlbWVudC5hdHRyKCdpZCcpO1xuICAgICAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gJ1wiJyArIGlkICsgJ1wiOiAnICsgbXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuY29uc29sZS5sb2cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KG1zZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF92YWxpZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBzdGF0dXMgPSBzZWxmLiRlbGVtZW50LmF0dHIoJ3R5cGUnKSA9PT0gJ2ZpbGUnO1xuICAgICAgICAgICAgaWYgKCFzdGF0dXMpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9sb2coJ1RoZSBpbnB1dCBcInR5cGVcIiBtdXN0IGJlIHNldCB0byBcImZpbGVcIiBmb3IgaW5pdGlhbGl6aW5nIHRoZSBcImJvb3RzdHJhcC1maWxlaW5wdXRcIiBwbHVnaW4uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3RhdHVzO1xuICAgICAgICB9LFxuICAgICAgICBfZXJyb3JzRXhpc3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVycjtcbiAgICAgICAgICAgIGlmIChzZWxmLiRlcnJvckNvbnRhaW5lci5maW5kKCdsaScpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVyciA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwoc2VsZi4kZXJyb3JDb250YWluZXIuaHRtbCgpKTtcbiAgICAgICAgICAgICRlcnIuZmluZCgnc3Bhbi5rdi1lcnJvci1jbG9zZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgJGVyci5maW5kKCd1bCcpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuICQudHJpbSgkZXJyLnRleHQoKSkubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBfZXJyb3JIYW5kbGVyOiBmdW5jdGlvbiAoZXZ0LCBjYXB0aW9uKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGVyciA9IGV2dC50YXJnZXQuZXJyb3IsIHNob3dFcnJvciA9IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93RXJyb3IobXNnLnJlcGxhY2UoJ3tuYW1lfScsIGNhcHRpb24pKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBlcnIuTk9UX0ZPVU5EX0VSUiAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZXJyLlNFQ1VSSVRZX0VSUiAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZXJyLk5PVF9SRUFEQUJMRV9FUlIgKi9cbiAgICAgICAgICAgIGlmIChlcnIuY29kZSA9PT0gZXJyLk5PVF9GT1VORF9FUlIpIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlTm90Rm91bmQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChlcnIuY29kZSA9PT0gZXJyLlNFQ1VSSVRZX0VSUikge1xuICAgICAgICAgICAgICAgIHNob3dFcnJvcihzZWxmLm1zZ0ZpbGVTZWN1cmVkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyLmNvZGUgPT09IGVyci5OT1RfUkVBREFCTEVfRVJSKSB7XG4gICAgICAgICAgICAgICAgc2hvd0Vycm9yKHNlbGYubXNnRmlsZU5vdFJlYWRhYmxlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyLmNvZGUgPT09IGVyci5BQk9SVF9FUlIpIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlUHJldmlld0Fib3J0ZWQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlUHJldmlld0Vycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2FkZEVycm9yOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKG1zZyAmJiAkZXJyb3IubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmh0bWwoc2VsZi5lcnJvckNsb3NlQnV0dG9uICsgbXNnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlcnJvci5maW5kKCcua3YtZXJyb3ItY2xvc2UnKSwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkZXJyb3IuZmFkZU91dCgnc2xvdycpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfcmVzZXRFcnJvcnM6IGZ1bmN0aW9uIChmYWRlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gZmFsc2U7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgJGVycm9yLmh0bWwoJycpO1xuICAgICAgICAgICAgaWYgKGZhZGUpIHtcbiAgICAgICAgICAgICAgICAkZXJyb3IuZmFkZU91dCgnc2xvdycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkZXJyb3IuaGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2hvd0ZvbGRlckVycm9yOiBmdW5jdGlvbiAoZm9sZGVycykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lciwgbXNnO1xuICAgICAgICAgICAgaWYgKCFmb2xkZXJzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dGb2xkZXJzTm90QWxsb3dlZC5yZXBsYWNlKCd7bn0nLCBmb2xkZXJzKTtcbiAgICAgICAgICAgIHNlbGYuX2FkZEVycm9yKG1zZyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgICAgICAkZXJyb3IuZmFkZUluKDgwMCk7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWZvbGRlcmVycm9yJywgW2ZvbGRlcnMsIG1zZ10pO1xuICAgICAgICB9LFxuICAgICAgICBfc2hvd1VwbG9hZEVycm9yOiBmdW5jdGlvbiAobXNnLCBwYXJhbXMsIGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyLCBldiA9IGV2ZW50IHx8ICdmaWxldXBsb2FkZXJyb3InLCBlID0gcGFyYW1zICYmIHBhcmFtcy5pZCA/XG4gICAgICAgICAgICAnPGxpIGRhdGEtZmlsZS1pZD1cIicgKyBwYXJhbXMuaWQgKyAnXCI+JyArIG1zZyArICc8L2xpPicgOiAnPGxpPicgKyBtc2cgKyAnPC9saT4nO1xuICAgICAgICAgICAgaWYgKCRlcnJvci5maW5kKCd1bCcpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2FkZEVycm9yKCc8dWw+JyArIGUgKyAnPC91bD4nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmZpbmQoJ3VsJykuYXBwZW5kKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVycm9yLmZhZGVJbig4MDApO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoZXYsIFtwYXJhbXMsIG1zZ10pO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9zaG93RXJyb3I6IGZ1bmN0aW9uIChtc2csIHBhcmFtcywgZXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVycm9yID0gc2VsZi4kZXJyb3JDb250YWluZXIsIGV2ID0gZXZlbnQgfHwgJ2ZpbGVlcnJvcic7XG4gICAgICAgICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgICAgICAgICBwYXJhbXMucmVhZGVyID0gc2VsZi5yZWFkZXI7XG4gICAgICAgICAgICBzZWxmLl9hZGRFcnJvcihtc2cpO1xuICAgICAgICAgICAgJGVycm9yLmZhZGVJbig4MDApO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoZXYsIFtwYXJhbXMsIG1zZ10pO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgICAgICBzZWxmLiRidG5VcGxvYWQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfbm9GaWxlc0Vycm9yOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGxhYmVsID0gc2VsZi5taW5GaWxlQ291bnQgPiAxID8gc2VsZi5maWxlUGx1cmFsIDogc2VsZi5maWxlU2luZ2xlLFxuICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnRmlsZXNUb29MZXNzLnJlcGxhY2UoJ3tufScsIHNlbGYubWluRmlsZUNvdW50KS5yZXBsYWNlKCd7ZmlsZXN9JywgbGFiZWwpLFxuICAgICAgICAgICAgICAgICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgc2VsZi5fYWRkRXJyb3IobXNnKTtcbiAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IHRydWU7XG4gICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscygwKTtcbiAgICAgICAgICAgICRlcnJvci5mYWRlSW4oODAwKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlZXJyb3InLCBbcGFyYW1zLCBtc2ddKTtcbiAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9wYXJzZUVycm9yOiBmdW5jdGlvbiAob3BlcmF0aW9uLCBqcVhIUiwgZXJyb3JUaHJvd24sIGZpbGVOYW1lKSB7XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBqcVhIUi5yZXNwb25zZUpTT04gKi9cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZXJyTXNnID0gJC50cmltKGVycm9yVGhyb3duICsgJycpLCBkb3QgPSBlcnJNc2cuc2xpY2UoLTEpID09PSAnLicgPyAnJyA6ICcuJyxcbiAgICAgICAgICAgICAgICB0ZXh0ID0ganFYSFIucmVzcG9uc2VKU09OICE9PSB1bmRlZmluZWQgJiYganFYSFIucmVzcG9uc2VKU09OLmVycm9yICE9PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgICAgICAgICBqcVhIUi5yZXNwb25zZUpTT04uZXJyb3IgOiBqcVhIUi5yZXNwb25zZVRleHQ7XG4gICAgICAgICAgICBpZiAoc2VsZi5jYW5jZWxsaW5nICYmIHNlbGYubXNnVXBsb2FkQWJvcnRlZCkge1xuICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYubXNnVXBsb2FkQWJvcnRlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dBamF4RXJyb3JEZXRhaWxzICYmIHRleHQpIHtcbiAgICAgICAgICAgICAgICB0ZXh0ID0gJC50cmltKHRleHQucmVwbGFjZSgvXFxuXFxzKlxcbi9nLCAnXFxuJykpO1xuICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0Lmxlbmd0aCA+IDAgPyAnPHByZT4nICsgdGV4dCArICc8L3ByZT4nIDogJyc7XG4gICAgICAgICAgICAgICAgZXJyTXNnICs9IGRvdCArIHRleHQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVyck1zZyArPSBkb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXJyTXNnID09PSBkb3QpIHtcbiAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLm1zZ0FqYXhFcnJvci5yZXBsYWNlKCd7b3BlcmF0aW9ufScsIG9wZXJhdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLmNhbmNlbGxpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBmaWxlTmFtZSA/ICc8Yj4nICsgZmlsZU5hbWUgKyAnOiA8L2I+JyArIGVyck1zZyA6IGVyck1zZztcbiAgICAgICAgfSxcbiAgICAgICAgX3BhcnNlRmlsZVR5cGU6IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGlzVmFsaWQsIHZUeXBlLCBjYXQsIGksIHR5cGVzID0gc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzIHx8IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2F0ID0gdHlwZXNbaV07XG4gICAgICAgICAgICAgICAgaXNWYWxpZCA9IHNlbGYuZmlsZVR5cGVTZXR0aW5nc1tjYXRdO1xuICAgICAgICAgICAgICAgIHZUeXBlID0gaXNWYWxpZChmaWxlLnR5cGUsIGZpbGUubmFtZSkgPyBjYXQgOiAnJztcbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkodlR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2VHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ290aGVyJztcbiAgICAgICAgfSxcbiAgICAgICAgX2dldFByZXZpZXdJY29uOiBmdW5jdGlvbiAoZm5hbWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZXh0LCBvdXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKGZuYW1lICYmIGZuYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgZXh0ID0gZm5hbWUuc3BsaXQoJy4nKS5wb3AoKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLnByZXZpZXdGaWxlSWNvblNldHRpbmdzW2V4dF0gfHwgc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5nc1tleHQudG9Mb3dlckNhc2UoKV0gfHwgbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYucHJldmlld0ZpbGVFeHRTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICAkLmVhY2goc2VsZi5wcmV2aWV3RmlsZUV4dFNldHRpbmdzLCBmdW5jdGlvbiAoa2V5LCBmdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5nc1trZXldICYmIGZ1bmMoZXh0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IHNlbGYucHJldmlld0ZpbGVJY29uU2V0dGluZ3Nba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBVbm5lY2Vzc2FyeVJldHVyblN0YXRlbWVudEpTXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBfcGFyc2VGaWxlUHJldmlld0ljb246IGZ1bmN0aW9uIChjb250ZW50LCBmbmFtZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpY24gPSBzZWxmLl9nZXRQcmV2aWV3SWNvbihmbmFtZSkgfHwgc2VsZi5wcmV2aWV3RmlsZUljb24sIG91dCA9IGNvbnRlbnQ7XG4gICAgICAgICAgICBpZiAob3V0LmluZGV4T2YoJ3twcmV2aWV3RmlsZUljb259JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIG91dCA9IG91dC5zZXRUb2tlbnMoeydwcmV2aWV3RmlsZUljb25DbGFzcyc6IHNlbGYucHJldmlld0ZpbGVJY29uQ2xhc3MsICdwcmV2aWV3RmlsZUljb24nOiBpY259KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9yYWlzZTogZnVuY3Rpb24gKGV2ZW50LCBwYXJhbXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZSA9ICQuRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmFtcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKGUsIHBhcmFtcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpIHx8IGUucmVzdWx0ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBpZ25vcmUgdGhlc2UgZXZlbnRzXG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGViYXRjaHVwbG9hZHN1Y2Nlc3MnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGV1cGxvYWRlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWNsZWFyJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlY2xlYXJlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZXJlc2V0JzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVmb2xkZXJlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZXVwbG9hZGVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlYmF0Y2h1cGxvYWRlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWRlbGV0ZWVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlY3VzdG9tZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVzdWNjZXNzcmVtb3ZlJzpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgLy8gcmVjZWl2ZSBkYXRhIHJlc3BvbnNlIHZpYSBgZmlsZWN1c3RvbWVycm9yYCBldmVudGBcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuYWpheEFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBlLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuRnVsbFNjcmVlbjogZnVuY3Rpb24gKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJGJ0bkZ1bGwsICRidG5Cb3JkO1xuICAgICAgICAgICAgaWYgKCEkbW9kYWwgfHwgISRtb2RhbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkYnRuRnVsbCA9ICRtb2RhbCAmJiAkbW9kYWwuZmluZCgnLmJ0bi1mdWxsc2NyZWVuJyk7XG4gICAgICAgICAgICAkYnRuQm9yZCA9ICRtb2RhbCAmJiAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyk7XG4gICAgICAgICAgICBpZiAoISRidG5GdWxsLmxlbmd0aCB8fCAhJGJ0bkJvcmQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGJ0bkZ1bGwucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgJGJ0bkJvcmQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgaWYgKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICRidG5GdWxsLmFkZENsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAndHJ1ZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkYnRuQm9yZC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkbW9kYWwuaGFzQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJykpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRmb3JtID0gc2VsZi4kZm9ybSwgJGNvbnQgPSBzZWxmLiRjb250YWluZXIsIGZ1bGxTY3JlZW5FdmVudHM7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlbCwgJ2NoYW5nZScsICQucHJveHkoc2VsZi5fY2hhbmdlLCBzZWxmKSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93QnJvd3NlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcihzZWxmLiRidG5GaWxlLCAnY2xpY2snLCAkLnByb3h5KHNlbGYuX2Jyb3dzZSwgc2VsZikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkY29udC5maW5kKCcuZmlsZWlucHV0LXJlbW92ZTpub3QoW2Rpc2FibGVkXSknKSwgJ2NsaWNrJywgJC5wcm94eShzZWxmLmNsZWFyLCBzZWxmKSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRjb250LmZpbmQoJy5maWxlaW5wdXQtY2FuY2VsJyksICdjbGljaycsICQucHJveHkoc2VsZi5jYW5jZWwsIHNlbGYpKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXREcmFnRHJvcCgpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZm9ybSwgJ3Jlc2V0JywgJC5wcm94eShzZWxmLnJlc2V0LCBzZWxmKSk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZm9ybSwgJ3N1Ym1pdCcsICQucHJveHkoc2VsZi5fc3VibWl0Rm9ybSwgc2VsZikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faGFuZGxlcihzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGVpbnB1dC11cGxvYWQnKSwgJ2NsaWNrJywgJC5wcm94eShzZWxmLl91cGxvYWRDbGljaywgc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkKHdpbmRvdyksICdyZXNpemUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbGlzdGVuRnVsbFNjcmVlbihzY3JlZW4ud2lkdGggPT09IHdpbmRvdy5pbm5lcldpZHRoICYmIHNjcmVlbi5oZWlnaHQgPT09IHdpbmRvdy5pbm5lckhlaWdodCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZ1bGxTY3JlZW5FdmVudHMgPSAnd2Via2l0ZnVsbHNjcmVlbmNoYW5nZSBtb3pmdWxsc2NyZWVuY2hhbmdlIGZ1bGxzY3JlZW5jaGFuZ2UgTVNGdWxsc2NyZWVuQ2hhbmdlJztcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJChkb2N1bWVudCksIGZ1bGxTY3JlZW5FdmVudHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9saXN0ZW5GdWxsU2NyZWVuKCRoLmNoZWNrRnVsbFNjcmVlbigpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faW5pdENsaWNrYWJsZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdENsaWNrYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkem9uZTtcbiAgICAgICAgICAgIGlmICghc2VsZi5pc0NsaWNrYWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR6b25lID0gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLiRkcm9wWm9uZSA6IHNlbGYuJHByZXZpZXcuZmluZCgnLmZpbGUtZGVmYXVsdC1wcmV2aWV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3MoJHpvbmUsICdjbGlja2FibGUnKTtcbiAgICAgICAgICAgICR6b25lLmF0dHIoJ3RhYmluZGV4JywgLTEpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkem9uZSwgJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRhciA9ICQoZS50YXJnZXQpO1xuICAgICAgICAgICAgICAgIGlmICghJHRhci5wYXJlbnRzKCcuZmlsZS1wcmV2aWV3LXRodW1ibmFpbHMnKS5sZW5ndGggfHwgJHRhci5wYXJlbnRzKCcuZmlsZS1kZWZhdWx0LXByZXZpZXcnKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgICAgICAkem9uZS5ibHVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0RHJhZ0Ryb3A6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHpvbmUgPSBzZWxmLiRkcm9wWm9uZTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZCAmJiBzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkem9uZSwgJ2RyYWdlbnRlciBkcmFnb3ZlcicsICQucHJveHkoc2VsZi5fem9uZURyYWdFbnRlciwgc2VsZikpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHpvbmUsICdkcmFnbGVhdmUnLCAkLnByb3h5KHNlbGYuX3pvbmVEcmFnTGVhdmUsIHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCR6b25lLCAnZHJvcCcsICQucHJveHkoc2VsZi5fem9uZURyb3AsIHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCQoZG9jdW1lbnQpLCAnZHJhZ2VudGVyIGRyYWdvdmVyIGRyb3AnLCBzZWxmLl96b25lRHJhZ0Ryb3BJbml0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcmFnRHJvcEluaXQ6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9LFxuICAgICAgICBfem9uZURyYWdFbnRlcjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaGFzRmlsZXMgPSAkLmluQXJyYXkoJ0ZpbGVzJywgZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci50eXBlcykgPiAtMTtcbiAgICAgICAgICAgIHNlbGYuX3pvbmVEcmFnRHJvcEluaXQoZSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Rpc2FibGVkIHx8ICFoYXNGaWxlcykge1xuICAgICAgICAgICAgICAgIGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICdub25lJztcbiAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGRyb3Bab25lLCAnZmlsZS1oaWdobGlnaHRlZCcpO1xuICAgICAgICB9LFxuICAgICAgICBfem9uZURyYWdMZWF2ZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuX3pvbmVEcmFnRHJvcEluaXQoZSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kZHJvcFpvbmUucmVtb3ZlQ2xhc3MoJ2ZpbGUtaGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcm9wOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2ZlciAqL1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCB8fCAkaC5pc0VtcHR5KGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuZmlsZXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fY2hhbmdlKGUsICdkcmFnZHJvcCcpO1xuICAgICAgICAgICAgc2VsZi4kZHJvcFpvbmUucmVtb3ZlQ2xhc3MoJ2ZpbGUtaGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwbG9hZENsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkYnRuID0gc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtdXBsb2FkJyksICRmb3JtLFxuICAgICAgICAgICAgICAgIGlzRW5hYmxlZCA9ICEkYnRuLmhhc0NsYXNzKCdkaXNhYmxlZCcpICYmICRoLmlzRW1wdHkoJGJ0bi5hdHRyKCdkaXNhYmxlZCcpKTtcbiAgICAgICAgICAgIGlmIChlICYmIGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCAmJiAkYnRuLmF0dHIoJ3R5cGUnKSAhPT0gJ3N1Ym1pdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgJGZvcm0gPSAkYnRuLmNsb3Nlc3QoJ2Zvcm0nKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gZG93bmdyYWRlIHRvIG5vcm1hbCBmb3JtIHN1Ym1pdCBpZiBwb3NzaWJsZVxuICAgICAgICAgICAgICAgICAgICBpZiAoJGZvcm0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZm9ybS50cmlnZ2VyKCdzdWJtaXQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc3VibWl0Rm9ybTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2lzRmlsZVNlbGVjdGlvblZhbGlkKCkgJiYgIXNlbGYuX2Fib3J0KHt9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyUHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkcCA9IHNlbGYuJHByZXZpZXcsXG4gICAgICAgICAgICAgICAgJHRodW1icyA9IHNlbGYuc2hvd1VwbG9hZGVkVGh1bWJzID8gc2VsZi5nZXRGcmFtZXMoJzpub3QoLmZpbGUtcHJldmlldy1zdWNjZXNzKScpIDogc2VsZi5nZXRGcmFtZXMoKTtcbiAgICAgICAgICAgICR0aHVtYnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwLmZpbmQoJyN6b29tLScgKyAkdGh1bWIuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuZ2V0RnJhbWVzKCkubGVuZ3RoIHx8ICFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlRGVmYXVsdFByZXZpZXcoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRTb3J0YWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRwcmV2aWV3LCBzZXR0aW5ncywgc2VsZWN0b3IgPSAnLicgKyAkaC5TT1JUX0NTUztcbiAgICAgICAgICAgIGlmICghd2luZG93Lkt2U29ydGFibGUgfHwgJGVsLmZpbmQoc2VsZWN0b3IpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkR2xvYmFsU3ltYm9sc1xuICAgICAgICAgICAgc2V0dGluZ3MgPSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlOiAnLmRyYWctaGFuZGxlLWluaXQnLFxuICAgICAgICAgICAgICAgIGRhdGFJZEF0dHI6ICdkYXRhLXByZXZpZXctaWQnLFxuICAgICAgICAgICAgICAgIHNjcm9sbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBzZWxlY3RvcixcbiAgICAgICAgICAgICAgICBvblNvcnQ6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvbGRJbmRleCA9IGUub2xkSW5kZXgsIG5ld0luZGV4ID0gZS5uZXdJbmRleCwga2V5LCAkZnJhbWU7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSAkaC5tb3ZlQXJyYXkoc2VsZi5pbml0aWFsUHJldmlldywgb2xkSW5kZXgsIG5ld0luZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyA9ICRoLm1vdmVBcnJheShzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnLCBvbGRJbmRleCwgbmV3SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWdbaV0gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXkgPSBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnW2ldLmtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUgPSAkKFwiLmt2LWZpbGUtcmVtb3ZlW2RhdGEta2V5PSdcIiArIGtleSArIFwiJ11cIikuY2xvc2VzdCgkaC5GUkFNRVMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcsICdpbml0XycgKyBpKS5hdHRyKCdkYXRhLWZpbGVpbmRleCcsICdpbml0XycgKyBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXNvcnRlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpZXdJZDogJChlLml0ZW0pLmF0dHIoJ2lkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAnb2xkSW5kZXgnOiBvbGRJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgICduZXdJbmRleCc6IG5ld0luZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhY2s6IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICgkZWwuZGF0YSgna3Zzb3J0YWJsZScpKSB7XG4gICAgICAgICAgICAgICAgJGVsLmt2c29ydGFibGUoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHNldHRpbmdzLCBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncy5kcmFnU2V0dGluZ3MpO1xuICAgICAgICAgICAgJGVsLmt2c29ydGFibGUoc2V0dGluZ3MpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXc6IGZ1bmN0aW9uIChpc0luaXQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2FwID0gc2VsZi5pbml0aWFsQ2FwdGlvbiB8fCAnJywgb3V0O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzSW5pdCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdENhcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICBjYXAgPSBpc0luaXQgJiYgc2VsZi5pbml0aWFsQ2FwdGlvbiA/IHNlbGYuaW5pdGlhbENhcHRpb24gOiBvdXQuY2FwdGlvbjtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbChvdXQuY29udGVudCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShvdXQuY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRab29tQnV0dG9uOiBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsYWJlbCA9IHNlbGYucHJldmlld1pvb21CdXR0b25JY29uc1t0eXBlXSwgY3NzID0gc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkNsYXNzZXNbdHlwZV0sXG4gICAgICAgICAgICAgICAgdGl0bGUgPSAnIHRpdGxlPVwiJyArIChzZWxmLnByZXZpZXdab29tQnV0dG9uVGl0bGVzW3R5cGVdIHx8ICcnKSArICdcIiAnLFxuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHRpdGxlICsgKHR5cGUgPT09ICdjbG9zZScgPyAnIGRhdGEtZGlzbWlzcz1cIm1vZGFsXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCInIDogJycpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdmdWxsc2NyZWVuJyB8fCB0eXBlID09PSAnYm9yZGVybGVzcycgfHwgdHlwZSA9PT0gJ3RvZ2dsZWhlYWRlcicpIHtcbiAgICAgICAgICAgICAgICBwYXJhbXMgKz0gJyBkYXRhLXRvZ2dsZT1cImJ1dHRvblwiIGFyaWEtcHJlc3NlZD1cImZhbHNlXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIicgKyBjc3MgKyAnIGJ0bi0nICsgdHlwZSArICdcIicgKyBwYXJhbXMgKyAnPicgKyBsYWJlbCArICc8L2J1dHRvbj4nO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0TW9kYWxDb250ZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21vZGFsJykuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAncnRsJzogc2VsZi5ydGwgPyAnIGt2LXJ0bCcgOiAnJyxcbiAgICAgICAgICAgICAgICAnem9vbUZyYW1lQ2xhc3MnOiBzZWxmLmZyYW1lQ2xhc3MsXG4gICAgICAgICAgICAgICAgJ2hlYWRpbmcnOiBzZWxmLm1zZ1pvb21Nb2RhbEhlYWRpbmcsXG4gICAgICAgICAgICAgICAgJ3ByZXYnOiBzZWxmLl9nZXRab29tQnV0dG9uKCdwcmV2JyksXG4gICAgICAgICAgICAgICAgJ25leHQnOiBzZWxmLl9nZXRab29tQnV0dG9uKCduZXh0JyksXG4gICAgICAgICAgICAgICAgJ3RvZ2dsZWhlYWRlcic6IHNlbGYuX2dldFpvb21CdXR0b24oJ3RvZ2dsZWhlYWRlcicpLFxuICAgICAgICAgICAgICAgICdmdWxsc2NyZWVuJzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbignZnVsbHNjcmVlbicpLFxuICAgICAgICAgICAgICAgICdib3JkZXJsZXNzJzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbignYm9yZGVybGVzcycpLFxuICAgICAgICAgICAgICAgICdjbG9zZSc6IHNlbGYuX2dldFpvb21CdXR0b24oJ2Nsb3NlJylcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuTW9kYWxFdmVudDogZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRtb2RhbCA9IHNlbGYuJG1vZGFsLCBnZXRQYXJhbXMgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZUV2ZW50OiBlLFxuICAgICAgICAgICAgICAgICAgICBwcmV2aWV3SWQ6ICRtb2RhbC5kYXRhKCdwcmV2aWV3SWQnKSxcbiAgICAgICAgICAgICAgICAgICAgbW9kYWw6ICRtb2RhbFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgJG1vZGFsLm9uKGV2ZW50ICsgJy5icy5tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyICRidG5GdWxsID0gJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpLCAkYnRuQm9yZCA9ICRtb2RhbC5maW5kKCcuYnRuLWJvcmRlcmxlc3MnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXpvb20nICsgZXZlbnQsIGdldFBhcmFtcyhlKSk7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50ID09PSAnc2hvd24nKSB7XG4gICAgICAgICAgICAgICAgICAgICRidG5Cb3JkLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgJGJ0bkZ1bGwucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoJG1vZGFsLmhhc0NsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkaC5jaGVja0Z1bGxTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5GdWxsLmFkZENsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAndHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb206IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGRpYWxvZywgbW9kYWxNYWluID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21vZGFsTWFpbicpLCBtb2RhbElkID0gJyMnICsgJGguTU9EQUxfSUQ7XG4gICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRtb2RhbCA9ICQobW9kYWxJZCk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuJG1vZGFsIHx8ICFzZWxmLiRtb2RhbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkZGlhbG9nID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaHRtbChtb2RhbE1haW4pLmluc2VydEFmdGVyKHNlbGYuJGNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgc2VsZi4kbW9kYWwgPSAkKG1vZGFsSWQpLmluc2VydEJlZm9yZSgkZGlhbG9nKTtcbiAgICAgICAgICAgICAgICAkZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguaW5pdE1vZGFsKHNlbGYuJG1vZGFsKTtcbiAgICAgICAgICAgIHNlbGYuJG1vZGFsLmh0bWwoc2VsZi5fZ2V0TW9kYWxDb250ZW50KCkpO1xuICAgICAgICAgICAgJC5lYWNoKCRoLk1PREFMX0VWRU5UUywgZnVuY3Rpb24gKGtleSwgZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9saXN0ZW5Nb2RhbEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb21CdXR0b25zOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHByZXZpZXdJZCA9IHNlbGYuJG1vZGFsLmRhdGEoJ3ByZXZpZXdJZCcpIHx8ICcnLCAkZmlyc3QsICRsYXN0LFxuICAgICAgICAgICAgICAgIHRodW1icyA9IHNlbGYuZ2V0RnJhbWVzKCkudG9BcnJheSgpLCBsZW4gPSB0aHVtYnMubGVuZ3RoLCAkcHJldiA9IHNlbGYuJG1vZGFsLmZpbmQoJy5idG4tcHJldicpLFxuICAgICAgICAgICAgICAgICRuZXh0ID0gc2VsZi4kbW9kYWwuZmluZCgnLmJ0bi1uZXh0Jyk7XG4gICAgICAgICAgICBpZiAodGh1bWJzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICAkcHJldi5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJG5leHQuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJHByZXYuc2hvdygpO1xuICAgICAgICAgICAgICAgICRuZXh0LnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbGVuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGZpcnN0ID0gJCh0aHVtYnNbMF0pO1xuICAgICAgICAgICAgJGxhc3QgPSAkKHRodW1ic1tsZW4gLSAxXSk7XG4gICAgICAgICAgICAkcHJldi5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgJG5leHQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIGlmICgkZmlyc3QubGVuZ3RoICYmICRmaXJzdC5hdHRyKCdpZCcpID09PSBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICAkcHJldi5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRsYXN0Lmxlbmd0aCAmJiAkbGFzdC5hdHRyKCdpZCcpID09PSBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICAkbmV4dC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfbWF4aW1pemVab29tRGlhbG9nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRtb2RhbCA9IHNlbGYuJG1vZGFsLCAkaGVhZCA9ICRtb2RhbC5maW5kKCcubW9kYWwtaGVhZGVyOnZpc2libGUnKSxcbiAgICAgICAgICAgICAgICAkZm9vdCA9ICRtb2RhbC5maW5kKCcubW9kYWwtZm9vdGVyOnZpc2libGUnKSwgJGJvZHkgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWJvZHknKSxcbiAgICAgICAgICAgICAgICBoID0gJCh3aW5kb3cpLmhlaWdodCgpLCBkaWZmID0gMDtcbiAgICAgICAgICAgICRtb2RhbC5hZGRDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKTtcbiAgICAgICAgICAgIGlmICgkaGVhZCAmJiAkaGVhZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBoIC09ICRoZWFkLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRmb290ICYmICRmb290Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGggLT0gJGZvb3Qub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGJvZHkgJiYgJGJvZHkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGlmZiA9ICRib2R5Lm91dGVySGVpZ2h0KHRydWUpIC0gJGJvZHkuaGVpZ2h0KCk7XG4gICAgICAgICAgICAgICAgaCAtPSBkaWZmO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmZpbmQoJy5rdi16b29tLWJvZHknKS5oZWlnaHQoaCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNpemVab29tRGlhbG9nOiBmdW5jdGlvbiAoZnVsbFNjcmVlbikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJGJ0bkZ1bGwgPSAkbW9kYWwuZmluZCgnLmJ0bi1mdWxsc2NyZWVuJyksXG4gICAgICAgICAgICAgICAgJGJ0bkJvcmQgPSAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyk7XG4gICAgICAgICAgICBpZiAoJG1vZGFsLmhhc0NsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgJGgudG9nZ2xlRnVsbFNjcmVlbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgaWYgKCFmdWxsU2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghJGJ0bkZ1bGwuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkbW9kYWwucmVtb3ZlQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLiRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5JykuY3NzKCdoZWlnaHQnLCBzZWxmLnpvb21Nb2RhbEhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYnRuRnVsbC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRidG5GdWxsLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJG1vZGFsLnJlbW92ZUNsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVzaXplWm9vbURpYWxvZyh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkYnRuQm9yZC5oYXNDbGFzcygnYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghZnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkaC50b2dnbGVGdWxsU2NyZWVuKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmZvY3VzKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRab29tQ29udGVudDogZnVuY3Rpb24gKCRmcmFtZSwgYW5pbWF0ZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkY29udGVudCwgdG1wbHQsIGJvZHksIHRpdGxlLCAkYm9keSwgJGRhdGFFbCwgY29uZmlnLCBwaWQgPSAkZnJhbWUuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJHByZXYgPSAkbW9kYWwuZmluZCgnLmJ0bi1wcmV2JyksICRuZXh0ID0gJG1vZGFsLmZpbmQoJy5idG4tbmV4dCcpLCAkdG1wLFxuICAgICAgICAgICAgICAgICRidG5GdWxsID0gJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpLCAkYnRuQm9yZCA9ICRtb2RhbC5maW5kKCcuYnRuLWJvcmRlcmxlc3MnKSwgY2FwLCBzaXplLFxuICAgICAgICAgICAgICAgICRidG5Ub2doID0gJG1vZGFsLmZpbmQoJy5idG4tdG9nZ2xlaGVhZGVyJyksICR6b29tUHJldmlldyA9IHNlbGYuJHByZXZpZXcuZmluZCgnI3pvb20tJyArIHBpZCk7XG4gICAgICAgICAgICB0bXBsdCA9ICR6b29tUHJldmlldy5hdHRyKCdkYXRhLXRlbXBsYXRlJykgfHwgJ2dlbmVyaWMnO1xuICAgICAgICAgICAgJGNvbnRlbnQgPSAkem9vbVByZXZpZXcuZmluZCgnLmt2LWZpbGUtY29udGVudCcpO1xuICAgICAgICAgICAgYm9keSA9ICRjb250ZW50Lmxlbmd0aCA/ICRjb250ZW50Lmh0bWwoKSA6ICcnO1xuICAgICAgICAgICAgY2FwID0gJGZyYW1lLmRhdGEoJ2NhcHRpb24nKSB8fCAnJztcbiAgICAgICAgICAgIHNpemUgPSAkZnJhbWUuZGF0YSgnc2l6ZScpIHx8ICcnO1xuICAgICAgICAgICAgdGl0bGUgPSBjYXAgKyAnICcgKyBzaXplO1xuICAgICAgICAgICAgJG1vZGFsLmZpbmQoJy5rdi16b29tLXRpdGxlJykuaHRtbCh0aXRsZSk7XG4gICAgICAgICAgICAkYm9keSA9ICRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5Jyk7XG4gICAgICAgICAgICAkbW9kYWwucmVtb3ZlQ2xhc3MoJ2t2LXNpbmdsZS1jb250ZW50Jyk7XG4gICAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgICAgICR0bXAgPSAkYm9keS5hZGRDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJykuY2xvbmUoKS5pbnNlcnRBZnRlcigkYm9keSk7XG4gICAgICAgICAgICAgICAgJGJvZHkuaHRtbChib2R5KS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJHRtcC5mYWRlT3V0KCdmYXN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkYm9keS5mYWRlSW4oJ2Zhc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYm9keS5yZW1vdmVDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAkdG1wLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkYm9keS5odG1sKGJvZHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlnID0gc2VsZi5wcmV2aWV3Wm9vbVNldHRpbmdzW3RtcGx0XTtcbiAgICAgICAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgICAgICAgICAkZGF0YUVsID0gJGJvZHkuZmluZCgnLmt2LXByZXZpZXctZGF0YScpO1xuICAgICAgICAgICAgICAgICRoLmFkZENzcygkZGF0YUVsLCAnZmlsZS16b29tLWRldGFpbCcpO1xuICAgICAgICAgICAgICAgICQuZWFjaChjb25maWcsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICRkYXRhRWwuY3NzKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKCRkYXRhRWwuYXR0cignd2lkdGgnKSAmJiBrZXkgPT09ICd3aWR0aCcpIHx8ICgkZGF0YUVsLmF0dHIoJ2hlaWdodCcpICYmIGtleSA9PT0gJ2hlaWdodCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZGF0YUVsLnJlbW92ZUF0dHIoa2V5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmRhdGEoJ3ByZXZpZXdJZCcsIHBpZCk7XG4gICAgICAgICAgICB2YXIgJGltZyA9ICRib2R5LmZpbmQoJ2ltZycpO1xuICAgICAgICAgICAgaWYgKCRpbWcubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGguYWRqdXN0T3JpZW50ZWRJbWFnZSgkaW1nLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHByZXYsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCdwcmV2JywgcGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkbmV4dCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3pvb21TbGlkZVNob3coJ25leHQnLCBwaWQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRidG5GdWxsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVzaXplWm9vbURpYWxvZyh0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkYnRuQm9yZCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2l6ZVpvb21EaWFsb2coZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRidG5Ub2doLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRoZWFkZXIgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWhlYWRlcicpLCAkZmxvYXRCYXIgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWJvZHkgLmZsb2F0aW5nLWJ1dHRvbnMnKSxcbiAgICAgICAgICAgICAgICAgICAgaHQsICRhY3Rpb25zID0gJGhlYWRlci5maW5kKCcua3Ytem9vbS1hY3Rpb25zJyksIHJlc2l6ZSA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkYm9keSA9IHNlbGYuJG1vZGFsLmZpbmQoJy5rdi16b29tLWJvZHknKSwgaCA9IHNlbGYuem9vbU1vZGFsSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRtb2RhbC5oYXNDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGggPSAkYm9keS5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoID0gaCAtICRoZWFkZXIub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGJvZHkuY3NzKCdoZWlnaHQnLCBoZWlnaHQgPyBoICsgaGVpZ2h0IDogaCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKCRoZWFkZXIuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgaHQgPSAkaGVhZGVyLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAkaGVhZGVyLnNsaWRlVXAoJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYWN0aW9ucy5maW5kKCcuYnRuJykuYXBwZW5kVG8oJGZsb2F0QmFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZShodCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICRmbG9hdEJhci5maW5kKCcuYnRuJykuYXBwZW5kVG8oJGFjdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAkaGVhZGVyLnNsaWRlRG93bignc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJG1vZGFsLmZvY3VzKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJG1vZGFsLCAna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGUud2hpY2ggfHwgZS5rZXlDb2RlO1xuICAgICAgICAgICAgICAgIGlmIChrZXkgPT09IDM3ICYmICEkcHJldi5hdHRyKCdkaXNhYmxlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3pvb21TbGlkZVNob3coJ3ByZXYnLCBwaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoa2V5ID09PSAzOSAmJiAhJG5leHQuYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCduZXh0JywgcGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvb21QcmV2aWV3OiBmdW5jdGlvbiAoJGJ0bikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUsICRtb2RhbCA9IHNlbGYuJG1vZGFsO1xuICAgICAgICAgICAgaWYgKCEkYnRuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93ICdDYW5ub3Qgem9vbSB0byBkZXRhaWxlZCBwcmV2aWV3ISc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaC5pbml0TW9kYWwoJG1vZGFsKTtcbiAgICAgICAgICAgICRtb2RhbC5odG1sKHNlbGYuX2dldE1vZGFsQ29udGVudCgpKTtcbiAgICAgICAgICAgICRmcmFtZSA9ICRidG4uY2xvc2VzdCgkaC5GUkFNRVMpO1xuICAgICAgICAgICAgc2VsZi5fc2V0Wm9vbUNvbnRlbnQoJGZyYW1lKTtcbiAgICAgICAgICAgICRtb2RhbC5tb2RhbCgnc2hvdycpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b25zKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF96b29tU2xpZGVTaG93OiBmdW5jdGlvbiAoZGlyLCBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGJ0biA9IHNlbGYuJG1vZGFsLmZpbmQoJy5rdi16b29tLWFjdGlvbnMgLmJ0bi0nICsgZGlyKSwgJHRhcmdGcmFtZSwgaSxcbiAgICAgICAgICAgICAgICB0aHVtYnMgPSBzZWxmLmdldEZyYW1lcygpLnRvQXJyYXkoKSwgbGVuID0gdGh1bWJzLmxlbmd0aCwgb3V0O1xuICAgICAgICAgICAgaWYgKCRidG4uYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICgkKHRodW1ic1tpXSkuYXR0cignaWQnKSA9PT0gcHJldmlld0lkKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9IGRpciA9PT0gJ3ByZXYnID8gaSAtIDEgOiBpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG91dCA8IDAgfHwgb3V0ID49IGxlbiB8fCAhdGh1bWJzW291dF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGFyZ0ZyYW1lID0gJCh0aHVtYnNbb3V0XSk7XG4gICAgICAgICAgICBpZiAoJHRhcmdGcmFtZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRab29tQ29udGVudCgkdGFyZ0ZyYW1lLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9ucygpO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGV6b29tJyArIGRpciwgeydwcmV2aWV3SWQnOiBwcmV2aWV3SWQsIG1vZGFsOiBzZWxmLiRtb2RhbH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb21CdXR0b246IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuZmluZCgnLmt2LWZpbGUtem9vbScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkZWwgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3pvb21QcmV2aWV3KCRlbCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyT2JqZWN0czogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgICAgICAgJGVsLmZpbmQoJ3ZpZGVvIGF1ZGlvJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICRlbC5maW5kKCdpbWcgb2JqZWN0IGRpdicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyRmlsZUlucHV0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRzcmNGcm0sICR0bXBGcm0sICR0bXBFbDtcbiAgICAgICAgICAgIHNlbGYuZmlsZUlucHV0Q2xlYXJlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eSgkZWwudmFsKCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRml4IGZvciBJRSB2ZXIgPCAxMSwgdGhhdCBkb2VzIG5vdCBjbGVhciBmaWxlIGlucHV0cy4gUmVxdWlyZXMgYSBzZXF1ZW5jZSBvZiBzdGVwcyB0byBwcmV2ZW50IElFXG4gICAgICAgICAgICAvLyBjcmFzaGluZyBidXQgc3RpbGwgYWxsb3cgY2xlYXJpbmcgb2YgdGhlIGZpbGUgaW5wdXQuXG4gICAgICAgICAgICBpZiAoc2VsZi5pc0lFOSB8fCBzZWxmLmlzSUUxMCkge1xuICAgICAgICAgICAgICAgICRzcmNGcm0gPSAkZWwuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgICAgICR0bXBGcm0gPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2Zvcm0nKSk7XG4gICAgICAgICAgICAgICAgJHRtcEVsID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgICAgICAgICAgICAgJGVsLmJlZm9yZSgkdG1wRWwpO1xuICAgICAgICAgICAgICAgIGlmICgkc3JjRnJtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAkc3JjRnJtLmFmdGVyKCR0bXBGcm0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICR0bXBFbC5hZnRlcigkdG1wRnJtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJHRtcEZybS5hcHBlbmQoJGVsKS50cmlnZ2VyKCdyZXNldCcpO1xuICAgICAgICAgICAgICAgICR0bXBFbC5iZWZvcmUoJGVsKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAkdG1wRnJtLnJlbW92ZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHsgLy8gbm9ybWFsIGlucHV0IGNsZWFyIGJlaGF2aW9yIGZvciBvdGhlciBzYW5lIGJyb3dzZXJzXG4gICAgICAgICAgICAgICAgJGVsLnZhbCgnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldFVwbG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZSA9IHtjb250ZW50OiBbXSwgY29uZmlnOiBbXSwgdGFnczogW10sIGFwcGVuZDogdHJ1ZX07XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygwKTtcbiAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRwcm9ncmVzcywgJ2hpZGUnKTtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKGZhbHNlKTtcbiAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuYWpheFJlcXVlc3RzID0gW107XG4gICAgICAgICAgICBzZWxmLl9yZXNldENhbnZhcygpO1xuICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0ge307XG4gICAgICAgICAgICBpZiAoc2VsZi5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9IFtdO1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSBbXTtcbiAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gW107XG4gICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgY29udGVudDogW10sXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZzogW10sXG4gICAgICAgICAgICAgICAgICAgIHRhZ3M6IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3Jlc2V0Q2FudmFzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoc2VsZi5jYW52YXMgJiYgc2VsZi5pbWFnZUNhbnZhc0NvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmltYWdlQ2FudmFzQ29udGV4dC5jbGVhclJlY3QoMCwgMCwgc2VsZi5jYW52YXMud2lkdGgsIHNlbGYuY2FudmFzLmhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9oYXNJbml0aWFsUHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuICFzZWxmLm92ZXJ3cml0ZUluaXRpYWwgJiYgc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3Jlc2V0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBvdXQsIGNhcDtcbiAgICAgICAgICAgIGlmIChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKG91dC5jb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICAgICAgY2FwID0gc2VsZi5pbml0aWFsQ2FwdGlvbiA/IHNlbGYuaW5pdGlhbENhcHRpb24gOiBvdXQuY2FwdGlvbjtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRDYXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRab29tKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9jbGVhckRlZmF1bHRQcmV2aWV3OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLiRwcmV2aWV3LmZpbmQoJy5maWxlLWRlZmF1bHQtcHJldmlldycpLnJlbW92ZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGVEZWZhdWx0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3IHx8ICRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKCc8ZGl2IGNsYXNzPVwiZmlsZS1kZWZhdWx0LXByZXZpZXdcIj4nICsgc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQgKyAnPC9kaXY+Jyk7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICBzZWxmLl9pbml0Q2xpY2thYmxlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldFByZXZpZXdUaHVtYnM6IGZ1bmN0aW9uIChpc0FqYXgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgb3V0O1xuICAgICAgICAgICAgaWYgKGlzQWpheCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLl9oYXNJbml0aWFsUHJldmlldygpKSB7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKG91dC5jb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihvdXQuY2FwdGlvbik7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfZ2V0TGF5b3V0VGVtcGxhdGU6IGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHRlbXBsYXRlID0gc2VsZi5sYXlvdXRUZW1wbGF0ZXNbdF07XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eShzZWxmLmN1c3RvbUxheW91dFRhZ3MpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRoLnJlcGxhY2VUYWdzKHRlbXBsYXRlLCBzZWxmLmN1c3RvbUxheW91dFRhZ3MpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0UHJldmlld1RlbXBsYXRlOiBmdW5jdGlvbiAodCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0ZW1wbGF0ZSA9IHNlbGYucHJldmlld1RlbXBsYXRlc1t0XTtcbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KHNlbGYuY3VzdG9tUHJldmlld1RhZ3MpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRoLnJlcGxhY2VUYWdzKHRlbXBsYXRlLCBzZWxmLmN1c3RvbVByZXZpZXdUYWdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldE91dERhdGE6IGZ1bmN0aW9uIChqcVhIUiwgcmVzcG9uc2VEYXRhLCBmaWxlc0RhdGEpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGpxWEhSID0ganFYSFIgfHwge307XG4gICAgICAgICAgICByZXNwb25zZURhdGEgPSByZXNwb25zZURhdGEgfHwge307XG4gICAgICAgICAgICBmaWxlc0RhdGEgPSBmaWxlc0RhdGEgfHwgc2VsZi5maWxlc3RhY2suc2xpY2UoMCkgfHwge307XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGZvcm06IHNlbGYuZm9ybWRhdGEsXG4gICAgICAgICAgICAgICAgZmlsZXM6IGZpbGVzRGF0YSxcbiAgICAgICAgICAgICAgICBmaWxlbmFtZXM6IHNlbGYuZmlsZW5hbWVzLFxuICAgICAgICAgICAgICAgIGZpbGVzY291bnQ6IHNlbGYuZ2V0RmlsZXNDb3VudCgpLFxuICAgICAgICAgICAgICAgIGV4dHJhOiBzZWxmLl9nZXRFeHRyYURhdGEoKSxcbiAgICAgICAgICAgICAgICByZXNwb25zZTogcmVzcG9uc2VEYXRhLFxuICAgICAgICAgICAgICAgIHJlYWRlcjogc2VsZi5yZWFkZXIsXG4gICAgICAgICAgICAgICAganFYSFI6IGpxWEhSXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0TXNnU2VsZWN0ZWQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHN0ckZpbGVzID0gbiA9PT0gMSA/IHNlbGYuZmlsZVNpbmdsZSA6IHNlbGYuZmlsZVBsdXJhbDtcbiAgICAgICAgICAgIHJldHVybiBuID4gMCA/IHNlbGYubXNnU2VsZWN0ZWQucmVwbGFjZSgne259JywgbikucmVwbGFjZSgne2ZpbGVzfScsIHN0ckZpbGVzKSA6IHNlbGYubXNnTm9GaWxlc1NlbGVjdGVkO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RnJhbWU6IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUgPSAkKCcjJyArIGlkKTtcbiAgICAgICAgICAgIGlmICghJGZyYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2xvZygnSW52YWxpZCB0aHVtYiBmcmFtZSB3aXRoIGlkOiBcIicgKyBpZCArICdcIi4nKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkZnJhbWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRUaHVtYnM6IGZ1bmN0aW9uIChjc3MpIHtcbiAgICAgICAgICAgIGNzcyA9IGNzcyB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEZyYW1lcygnOm5vdCguZmlsZS1wcmV2aWV3LWluaXRpYWwpJyArIGNzcyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRFeHRyYURhdGE6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGRhdGEgPSBzZWxmLnVwbG9hZEV4dHJhRGF0YTtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi51cGxvYWRFeHRyYURhdGEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBzZWxmLnVwbG9hZEV4dHJhRGF0YShwcmV2aWV3SWQsIGluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFhocjogZnVuY3Rpb24gKHhocm9iaiwgcHJldmlld0lkLCBmaWxlQ291bnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICh4aHJvYmoudXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgeGhyb2JqLnVwbG9hZC5hZGRFdmVudExpc3RlbmVyKCdwcm9ncmVzcycsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGN0ID0gMCwgdG90YWwgPSBldmVudC50b3RhbCwgcG9zaXRpb24gPSBldmVudC5sb2FkZWQgfHwgZXZlbnQucG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGV2ZW50Lmxlbmd0aENvbXB1dGFibGUgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50Lmxlbmd0aENvbXB1dGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBjdCA9IE1hdGguZmxvb3IocG9zaXRpb24gLyB0b3RhbCAqIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpZXdJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0QXN5bmNVcGxvYWRTdGF0dXMocHJldmlld0lkLCBwY3QsIGZpbGVDb3VudCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcyhwY3QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHhocm9iajtcbiAgICAgICAgfSxcbiAgICAgICAgX2FqYXhTdWJtaXQ6IGZ1bmN0aW9uIChmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yLCBwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHNldHRpbmdzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLl9yYWlzZSgnZmlsZXByZWFqYXgnLCBbcHJldmlld0lkLCBpbmRleF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fdXBsb2FkRXh0cmEocHJldmlld0lkLCBpbmRleCk7XG4gICAgICAgICAgICBzZXR0aW5ncyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB7XG4gICAgICAgICAgICAgICAgeGhyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4aHJvYmogPSAkLmFqYXhTZXR0aW5ncy54aHIoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2luaXRYaHIoeGhyb2JqLCBwcmV2aWV3SWQsIHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHVybDogc2VsZi51cGxvYWRVcmwsXG4gICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgZGF0YTogc2VsZi5mb3JtZGF0YSxcbiAgICAgICAgICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgcHJvY2Vzc0RhdGE6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBiZWZvcmVTZW5kOiBmbkJlZm9yZSxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmblN1Y2Nlc3MsXG4gICAgICAgICAgICAgICAgY29tcGxldGU6IGZuQ29tcGxldGUsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZuRXJyb3JcbiAgICAgICAgICAgIH0sIHNlbGYuYWpheFNldHRpbmdzKTtcbiAgICAgICAgICAgIHNlbGYuYWpheFJlcXVlc3RzLnB1c2goJC5hamF4KHNldHRpbmdzKSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9tZXJnZUFycmF5OiBmdW5jdGlvbiAocHJvcCwgY29udGVudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhcnIxID0gJGguY2xlYW5BcnJheShzZWxmW3Byb3BdKSwgYXJyMiA9ICRoLmNsZWFuQXJyYXkoY29udGVudCk7XG4gICAgICAgICAgICBzZWxmW3Byb3BdID0gYXJyMS5jb25jYXQoYXJyMik7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0VXBsb2FkU3VjY2VzczogZnVuY3Rpb24gKG91dCwgJHRodW1iLCBhbGxGaWxlcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhcHBlbmQsIGRhdGEsIGluZGV4LCAkZGl2LCAkbmV3Q2FjaGUsIGNvbnRlbnQsIGNvbmZpZywgdGFncywgaTtcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldyB8fCB0eXBlb2Ygb3V0ICE9PSAnb2JqZWN0JyB8fCAkLmlzRW1wdHlPYmplY3Qob3V0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdXQuaW5pdGlhbFByZXZpZXcgIT09IHVuZGVmaW5lZCAmJiBvdXQuaW5pdGlhbFByZXZpZXcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNlbGYuaGFzSW5pdERhdGEgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBvdXQuaW5pdGlhbFByZXZpZXcgfHwgW107XG4gICAgICAgICAgICAgICAgY29uZmlnID0gb3V0LmluaXRpYWxQcmV2aWV3Q29uZmlnIHx8IFtdO1xuICAgICAgICAgICAgICAgIHRhZ3MgPSBvdXQuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MgfHwgW107XG4gICAgICAgICAgICAgICAgYXBwZW5kID0gb3V0LmFwcGVuZCA9PT0gdW5kZWZpbmVkIHx8IG91dC5hcHBlbmQgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMCAmJiAhJGguaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gY29udGVudC5zcGxpdChzZWxmLmluaXRpYWxQcmV2aWV3RGVsaW1pdGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fbWVyZ2VBcnJheSgnaW5pdGlhbFByZXZpZXcnLCBjb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9tZXJnZUFycmF5KCdpbml0aWFsUHJldmlld0NvbmZpZycsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fbWVyZ2VBcnJheSgnaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MnLCB0YWdzKTtcbiAgICAgICAgICAgICAgICBpZiAoJHRodW1iICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBzZWxmLnByZXZpZXdDYWNoZS5hZGQoY29udGVudCwgY29uZmlnWzBdLCB0YWdzWzBdLCBhcHBlbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmdldChpbmRleCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGRpdiA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwoZGF0YSkuaGlkZSgpLmluc2VydEFmdGVyKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgICAgICAkbmV3Q2FjaGUgPSAkZGl2LmZpbmQoJy5rdi16b29tLWNhY2hlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJG5ld0NhY2hlICYmICRuZXdDYWNoZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbmV3Q2FjaGUuaW5zZXJ0QWZ0ZXIoJHRodW1iKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5mYWRlT3V0KCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkbmV3VGh1bWIgPSAkZGl2LmZpbmQoJy5maWxlLXByZXZpZXctZnJhbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJG5ld1RodW1iICYmICRuZXdUaHVtYi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJG5ld1RodW1iLmluc2VydEJlZm9yZSgkdGh1bWIpLmZhZGVJbignc2xvdycpLmNzcygnZGlzcGxheTppbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZShzZWxmLiRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyAkdGh1bWIuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGl2LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLmNvbnRlbnRbaV0gPSBjb250ZW50WzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS5jb25maWdbaV0gPSBjb25maWdbMF0gfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLnRhZ3NbaV0gPSB0YWdzWzBdIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS5hcHBlbmQgPSBhcHBlbmQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5zZXQoY29udGVudCwgY29uZmlnLCB0YWdzLCBhcHBlbmQpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlldygpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0U3VjY2Vzc1RodW1iczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCRoLkZSQU1FUyArICcuZmlsZS1wcmV2aWV3LXN1Y2Nlc3MnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3LCAkcmVtb3ZlID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXJlbW92ZScpO1xuICAgICAgICAgICAgICAgICRyZW1vdmUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRyZW1vdmUsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkID0gJHRodW1iLmF0dHIoJ2lkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLl9yYWlzZSgnZmlsZXN1Y2Nlc3NyZW1vdmUnLCBbaWQsICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICRoLmNsZWFuTWVtb3J5KCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvdXQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmZhZGVPdXQoJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZSgkcHJldmlldy5maW5kKCcjem9vbS0nICsgaWQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5nZXRGcmFtZXMoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jaGVja0FzeW5jQ29tcGxldGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgcHJldmlld0lkLCBpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGYuZmlsZXN0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArIFwiLVwiICsgaTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaW5BcnJheShwcmV2aWV3SWQsIHNlbGYudXBsb2FkTG9nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoc2VsZi51cGxvYWRBc3luY0NvdW50ID09PSBzZWxmLnVwbG9hZExvZy5sZW5ndGgpO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkRXh0cmE6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGRhdGEgPSBzZWxmLl9nZXRFeHRyYURhdGEocHJldmlld0lkLCBpbmRleCk7XG4gICAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmVhY2goZGF0YSwgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmZvcm1kYXRhLmFwcGVuZChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkU2luZ2xlOiBmdW5jdGlvbiAoaSwgZmlsZXMsIGFsbEZpbGVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHRvdGFsID0gc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGgsIGZvcm1kYXRhID0gbmV3IEZvcm1EYXRhKCksIG91dERhdGEsXG4gICAgICAgICAgICAgICAgcHJldmlld0lkID0gc2VsZi5wcmV2aWV3SW5pdElkICsgXCItXCIgKyBpLCAkdGh1bWIsIGNoa0NvbXBsZXRlLCAkYnRuVXBsb2FkLCAkYnRuRGVsZXRlLFxuICAgICAgICAgICAgICAgIGhhc1Bvc3REYXRhID0gc2VsZi5maWxlc3RhY2subGVuZ3RoID4gMCB8fCAhJC5pc0VtcHR5T2JqZWN0KHNlbGYudXBsb2FkRXh0cmFEYXRhKSxcbiAgICAgICAgICAgICAgICAkcHJvZyA9ICQoJyMnICsgcHJldmlld0lkKS5maW5kKCcuZmlsZS10aHVtYi1wcm9ncmVzcycpLFxuICAgICAgICAgICAgICAgIGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IsIHVwZGF0ZVVwbG9hZExvZywgcGFyYW1zID0ge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpfSxcbiAgICAgICAgICAgICAgICB1cGxvYWRGYWlsZWQsIG11bHRpVXBsb2FkTW9kZSA9ICEkaC5pc0VtcHR5KHNlbGYuJGVsZW1lbnQuYXR0cignbXVsdGlwbGUnKSk7XG4gICAgICAgICAgICBzZWxmLmZvcm1kYXRhID0gZm9ybWRhdGE7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICR0aHVtYiA9ICQoJyMnICsgcHJldmlld0lkICsgJzpub3QoLmZpbGUtcHJldmlldy1pbml0aWFsKScpO1xuICAgICAgICAgICAgICAgICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyk7XG4gICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZSA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS1yZW1vdmUnKTtcbiAgICAgICAgICAgICAgICAkcHJvZy5yZW1vdmVDbGFzcygnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvdGFsID09PSAwIHx8ICFoYXNQb3N0RGF0YSB8fCAoJGJ0blVwbG9hZCAmJiAkYnRuVXBsb2FkLmhhc0NsYXNzKCdkaXNhYmxlZCcpKSB8fCBzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nID0gZnVuY3Rpb24gKGksIHByZXZpZXdJZCkge1xuICAgICAgICAgICAgICAgIGlmIChtdWx0aVVwbG9hZE1vZGUgfHwgIXVwbG9hZEZhaWxlZCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGksIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkTG9nLnB1c2gocHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5fY2hlY2tBc3luY0NvbXBsZXRlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjaGtDb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdSA9IHNlbGYudXBsb2FkQ2FjaGUsICRpbml0VGh1bWJzLCBpLCBqLCBsZW4gPSAwLCBkYXRhID0gc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3O1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLmNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVuID0gZGF0YS5jb250ZW50Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmlnZ2VyUmVzZXQgPSBtdWx0aVVwbG9hZE1vZGUgfHwgIXVwbG9hZEZhaWxlZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLnNldCh1LmNvbnRlbnQsIHUuY29uZmlnLCB1LnRhZ3MsIHUuYXBwZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdS5jb250ZW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGogPSBpICsgbGVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnRbal0gPSB1LmNvbnRlbnRbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNvbmZpZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29uZmlnW2pdID0gdS5jb25maWdbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEudGFncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFnc1tqXSA9IHUudGFnc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gJGguY2xlYW5BcnJheShkYXRhLmNvbnRlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSAkaC5jbGVhbkFycmF5KGRhdGEuY29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gJGguY2xlYW5BcnJheShkYXRhLnRhZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gdS5jb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSB1LmNvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gdS50YWdzO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5oYXNJbml0RGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi51bmxvY2sodHJpZ2dlclJlc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWdnZXJSZXNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkaW5pdFRodW1icyA9IHNlbGYuJHByZXZpZXcuZmluZCgnLmZpbGUtcHJldmlldy1pbml0aWFsJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnVwbG9hZEFzeW5jICYmICRpbml0VGh1bWJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRpbml0VGh1bWJzLCAkaC5TT1JUX0NTUyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEpO1xuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5CZWZvcmUgPSBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUik7XG4gICAgICAgICAgICAgICAgc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISR0aHVtYi5oYXNDbGFzcygnZmlsZS1wcmV2aWV3LXN1Y2Nlc3MnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnTG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCR0aHVtYiwgJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAkYnRuRGVsZXRlLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2NrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlcHJldXBsb2FkJywgW291dERhdGEsIHByZXZpZXdJZCwgaV0pO1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHBhcmFtcywgb3V0RGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAganFYSFIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3NDYW5jZWxsZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5TdWNjZXNzID0gZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBpZCA9IHNlbGYuc2hvd1ByZXZpZXcgJiYgJHRodW1iLmF0dHIoJ2lkJykgPyAkdGh1bWIuYXR0cignaWQnKSA6IHByZXZpZXdJZDtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUiwgZGF0YSk7XG4gICAgICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgcGFyYW1zLCBvdXREYXRhKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYlN0YXR1cygkdGh1bWIsICdTdWNjZXNzJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFVwbG9hZFN1Y2Nlc3MoZGF0YSwgJHRodW1iLCBhbGxGaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxLCAkcHJvZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXVwbG9hZGVkJywgW291dERhdGEsIHBpZCwgaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soaSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nKGksIHBpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGxvYWRGYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGRhdGEuZXJyb3IsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iLCBpLCAobXVsdGlVcGxvYWRNb2RlID8gbnVsbCA6IHNlbGYuZmlsZXN0YWNrW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVVcGxvYWRMb2coaSwgcGlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5EZWxldGUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVubG9jayhmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hrQ29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0U3VjY2Vzc1RodW1icygpO1xuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLnVwbG9hZFRodW1iLFxuICAgICAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24sIChhbGxGaWxlcyA/IGZpbGVzW2ldLm5hbWUgOiBudWxsKSk7XG4gICAgICAgICAgICAgICAgdXBsb2FkRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVVcGxvYWRMb2coaSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1c1twcmV2aWV3SWRdID0gMTAwO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iLCBpLCAobXVsdGlVcGxvYWRNb2RlID8gbnVsbCA6IHNlbGYuZmlsZXN0YWNrW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHBhcmFtcywgc2VsZi5fZ2V0T3V0RGF0YShqcVhIUikpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsICRwcm9nLCBzZWxmLm1zZ0FqYXhQcm9ncmVzc0Vycm9yLnJlcGxhY2UoJ3tvcGVyYXRpb259Jywgb3ApKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGVyck1zZywgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvcm1kYXRhLmFwcGVuZChzZWxmLnVwbG9hZEZpbGVBdHRyLCBmaWxlc1tpXSwgc2VsZi5maWxlbmFtZXNbaV0pO1xuICAgICAgICAgICAgZm9ybWRhdGEuYXBwZW5kKCdmaWxlX2lkJywgaSk7XG4gICAgICAgICAgICBzZWxmLl9hamF4U3VibWl0KGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgIH0sXG4gICAgICAgIF91cGxvYWRCYXRjaDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBmaWxlcyA9IHNlbGYuZmlsZXN0YWNrLCB0b3RhbCA9IGZpbGVzLmxlbmd0aCwgcGFyYW1zID0ge30sIGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuRXJyb3IsXG4gICAgICAgICAgICAgICAgZm5Db21wbGV0ZSwgaGFzUG9zdERhdGEgPSBzZWxmLmZpbGVzdGFjay5sZW5ndGggPiAwIHx8ICEkLmlzRW1wdHlPYmplY3Qoc2VsZi51cGxvYWRFeHRyYURhdGEpLFxuICAgICAgICAgICAgICAgIHNldEFsbFVwbG9hZGVkO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgaWYgKHRvdGFsID09PSAwIHx8ICFoYXNQb3N0RGF0YSB8fCBzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0QWxsVXBsb2FkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soa2V5LCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5CZWZvcmUgPSBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmxvY2soKTtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZSA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS1yZW1vdmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghJHRodW1iLmhhc0NsYXNzKCdmaWxlLXByZXZpZXctc3VjY2VzcycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnTG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkdGh1bWIsICdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHByZXVwbG9hZCcsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KG91dERhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGpxWEhSLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzQ2FuY2VsbGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuU3VjY2VzcyA9IGZ1bmN0aW9uIChkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRhdGEuZXJyb3JrZXlzICovXG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSLCBkYXRhKSwgJHRodW1icyA9IHNlbGYuX2dldFRodW1icygnOm5vdCguZmlsZS1wcmV2aWV3LWVycm9yKScpLFxuICAgICAgICAgICAgICAgICAgICBrZXkgPSAwLFxuICAgICAgICAgICAgICAgICAgICBrZXlzID0gJGguaXNFbXB0eShkYXRhKSB8fCAkaC5pc0VtcHR5KGRhdGEuZXJyb3JrZXlzKSA/IFtdIDogZGF0YS5lcnJvcmtleXM7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2Fkc3VjY2VzcycsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgICAgIHNldEFsbFVwbG9hZGVkKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWJzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCAkYnRuVXBsb2FkID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnU3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksICRidG5EZWxldGUgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuRGVsZXRlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkLmluQXJyYXkoa2V5LCBrZXlzKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnU3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGtleSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihkYXRhLmVycm9yLCBvdXREYXRhLCAnZmlsZWJhdGNodXBsb2FkZXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVubG9jaygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTdWNjZXNzVGh1bWJzKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpLCBvcCA9IHNlbGYuYWpheE9wZXJhdGlvbnMudXBsb2FkQmF0Y2gsXG4gICAgICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYuX3BhcnNlRXJyb3Iob3AsIGpxWEhSLCBlcnJvclRocm93bik7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGVyck1zZywgb3V0RGF0YSwgJ2ZpbGViYXRjaHVwbG9hZGVycm9yJyk7XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRGaWxlQ291bnQgPSB0b3RhbCAtIDE7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCBrZXkgPSAkdGh1bWIuYXR0cignZGF0YS1maWxlaW5kZXgnKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5maWxlc3RhY2tba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygnIC5rdi1maWxlLXVwbG9hZCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCcgLmt2LWZpbGUtZGVsZXRlJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0FqYXhQcm9ncmVzc0Vycm9yLnJlcGxhY2UoJ3tvcGVyYXRpb259Jywgb3ApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAkLmVhY2goZmlsZXMsIGZ1bmN0aW9uIChrZXksIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZXNba2V5XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5mb3JtZGF0YS5hcHBlbmQoc2VsZi51cGxvYWRGaWxlQXR0ciwgZGF0YSwgc2VsZi5maWxlbmFtZXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9hamF4U3VibWl0KGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IpO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkRXh0cmFPbmx5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHBhcmFtcyA9IHt9LCBmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbkJlZm9yZSA9IGZ1bmN0aW9uIChqcVhIUikge1xuICAgICAgICAgICAgICAgIHNlbGYubG9jaygpO1xuICAgICAgICAgICAgICAgIHZhciBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUik7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHByZXVwbG9hZCcsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoNTApO1xuICAgICAgICAgICAgICAgIHBhcmFtcy5kYXRhID0gb3V0RGF0YTtcbiAgICAgICAgICAgICAgICBwYXJhbXMueGhyID0ganFYSFI7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAganFYSFIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3NDYW5jZWxsZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5TdWNjZXNzID0gZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSLCBkYXRhKTtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eShkYXRhKSB8fCAkaC5pc0VtcHR5KGRhdGEuZXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2h1cGxvYWRzdWNjZXNzJywgW291dERhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFVwbG9hZFN1Y2Nlc3MoZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGRhdGEuZXJyb3IsIG91dERhdGEsICdmaWxlYmF0Y2h1cGxvYWRlcnJvcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmbkNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYudW5sb2NrKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpLCBvcCA9IHNlbGYuYWpheE9wZXJhdGlvbnMudXBsb2FkRXh0cmEsXG4gICAgICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYuX3BhcnNlRXJyb3Iob3AsIGpxWEhSLCBlcnJvclRocm93bik7XG4gICAgICAgICAgICAgICAgcGFyYW1zLmRhdGEgPSBvdXREYXRhO1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihlcnJNc2csIG91dERhdGEsICdmaWxlYmF0Y2h1cGxvYWRlcnJvcicpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSwgc2VsZi4kcHJvZ3Jlc3MsIHNlbGYubXNnQWpheFByb2dyZXNzRXJyb3IucmVwbGFjZSgne29wZXJhdGlvbn0nLCBvcCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGYuX2FqYXhTdWJtaXQoZm5CZWZvcmUsIGZuU3VjY2VzcywgZm5Db21wbGV0ZSwgZm5FcnJvcik7XG4gICAgICAgIH0sXG4gICAgICAgIF9kZWxldGVGaWxlSW5kZXg6IGZ1bmN0aW9uICgkZnJhbWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaW5kID0gJGZyYW1lLmF0dHIoJ2RhdGEtZmlsZWluZGV4Jyk7XG4gICAgICAgICAgICBpZiAoaW5kLnN1YnN0cmluZygwLCA1KSA9PT0gJ2luaXRfJykge1xuICAgICAgICAgICAgICAgIGluZCA9IHBhcnNlSW50KGluZC5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXcsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFncyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5nZXRGcmFtZXMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRuRnJhbWUgPSAkKHRoaXMpLCBuSW5kID0gJG5GcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobkluZC5zdWJzdHJpbmcoMCwgNSkgPT09ICdpbml0XycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5JbmQgPSBwYXJzZUludChuSW5kLnJlcGxhY2UoJ2luaXRfJywgJycpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuSW5kID4gaW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbkluZC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuRnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnLCAnaW5pdF8nICsgbkluZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi51cGxvYWRBc3luYykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlSW5pdGlhbFByZXZpZXcgPSBzZWxmLmdldFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0RmlsZUFjdGlvbnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b24oKTtcbiAgICAgICAgICAgIHNlbGYuZ2V0RnJhbWVzKCcgLmt2LWZpbGUtcmVtb3ZlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlbCA9ICQodGhpcyksICRmcmFtZSA9ICRlbC5jbG9zZXN0KCRoLkZSQU1FUyksIGhhc0Vycm9yLCBpZCA9ICRmcmFtZS5hdHRyKCdpZCcpLFxuICAgICAgICAgICAgICAgICAgICBpbmQgPSAkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKSwgbiwgY2FwLCBzdGF0dXM7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZWwsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gc2VsZi5fcmFpc2UoJ2ZpbGVwcmVyZW1vdmUnLCBbaWQsIGluZF0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSBmYWxzZSB8fCAhc2VsZi5fdmFsaWRhdGVNaW5Db3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaGFzRXJyb3IgPSAkZnJhbWUuaGFzQ2xhc3MoJ2ZpbGUtcHJldmlldy1lcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICAkaC5jbGVhbk1lbW9yeSgkZnJhbWUpO1xuICAgICAgICAgICAgICAgICAgICAkZnJhbWUuZmFkZU91dCgnc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyBpZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGRhdGVTdGFjayhpbmQsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhck9iamVjdHMoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpZCAmJiBoYXNFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuJGVycm9yQ29udGFpbmVyLmZpbmQoJ2xpW2RhdGEtZmlsZS1pZD1cIicgKyBpZCArICdcIl0nKS5mYWRlT3V0KCdmYXN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuX2Vycm9yc0V4aXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmlsZXN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2sodHJ1ZSksIGNoayA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuID0gZmlsZXN0YWNrLmxlbmd0aCwgaGFzVGh1bWIgPSBzZWxmLnNob3dQcmV2aWV3ICYmIHNlbGYuZ2V0RnJhbWVzKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbiA9PT0gMCAmJiBjaGsgPT09IDAgJiYgIWhhc1RodW1iKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gY2hrICsgbGVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcCA9IG4gPiAxID8gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobikgOiAoZmlsZXN0YWNrWzBdID8gc2VsZi5fZ2V0RmlsZU5hbWVzKClbMF0gOiAnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVyZW1vdmVkJywgW2lkLCBpbmRdKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuZ2V0RnJhbWVzKCcgLmt2LWZpbGUtdXBsb2FkJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlbCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZWwsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRmcmFtZSA9ICRlbC5jbG9zZXN0KCRoLkZSQU1FUyksIGluZCA9ICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRmcmFtZS5oYXNDbGFzcygnZmlsZS1wcmV2aWV3LWVycm9yJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwbG9hZFNpbmdsZShpbmQsIHNlbGYuZmlsZXN0YWNrLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXdBY3Rpb25zOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldywgZGVsZXRlRXh0cmFEYXRhID0gc2VsZi5kZWxldGVFeHRyYURhdGEgfHwge30sXG4gICAgICAgICAgICAgICAgYnRuUmVtb3ZlID0gJGguRlJBTUVTICsgJyAua3YtZmlsZS1yZW1vdmUnLFxuICAgICAgICAgICAgICAgIHJlc2V0UHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoYXNGaWxlcyA9IHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSA6IHNlbGYuJGVsZW1lbnQuZ2V0KDApLmZpbGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRwcmV2aWV3LmZpbmQoYnRuUmVtb3ZlKS5sZW5ndGggPT09IDAgJiYgIWhhc0ZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxDYXB0aW9uID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b24oKTtcbiAgICAgICAgICAgICRwcmV2aWV3LmZpbmQoYnRuUmVtb3ZlKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVsID0gJCh0aGlzKSwgdlVybCA9ICRlbC5kYXRhKCd1cmwnKSB8fCBzZWxmLmRlbGV0ZVVybCwgdktleSA9ICRlbC5kYXRhKCdrZXknKTtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eSh2VXJsKSB8fCB2S2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgJGZyYW1lID0gJGVsLmNsb3Nlc3QoJGguRlJBTUVTKSwgY2FjaGUgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBzZXR0aW5ncywgcGFyYW1zLCBpbmRleCA9ICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpLCBjb25maWcsIGV4dHJhRGF0YTtcbiAgICAgICAgICAgICAgICBpbmRleCA9IHBhcnNlSW50KGluZGV4LnJlcGxhY2UoJ2luaXRfJywgJycpKTtcbiAgICAgICAgICAgICAgICBjb25maWcgPSAkaC5pc0VtcHR5KGNhY2hlLmNvbmZpZykgJiYgJGguaXNFbXB0eShjYWNoZS5jb25maWdbaW5kZXhdKSA/IG51bGwgOiBjYWNoZS5jb25maWdbaW5kZXhdO1xuICAgICAgICAgICAgICAgIGV4dHJhRGF0YSA9ICRoLmlzRW1wdHkoY29uZmlnKSB8fCAkaC5pc0VtcHR5KGNvbmZpZy5leHRyYSkgPyBkZWxldGVFeHRyYURhdGEgOiBjb25maWcuZXh0cmE7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBleHRyYURhdGEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBleHRyYURhdGEgPSBleHRyYURhdGEoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge2lkOiAkZWwuYXR0cignaWQnKSwga2V5OiB2S2V5LCBleHRyYTogZXh0cmFEYXRhfTtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB7XG4gICAgICAgICAgICAgICAgICAgIHVybDogdlVybCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiAkLmV4dGVuZCh0cnVlLCB7fSwge2tleTogdktleX0sIGV4dHJhRGF0YSksXG4gICAgICAgICAgICAgICAgICAgIGJlZm9yZVNlbmQ6IGZ1bmN0aW9uIChqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hamF4QWJvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVwcmVkZWxldGUnLCBbdktleSwganFYSFIsIGV4dHJhRGF0YV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuYWpheEFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqcVhIUi5hYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJGZyYW1lLCAnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJGVsLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbiwgY2FwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gcGFyc2VJbnQoKCRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpKS5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUudW5zZXQoaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcCA9IG4gPiAwID8gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobikgOiAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9kZWxldGVGaWxlSW5kZXgoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVkZWxldGVkJywgW3ZLZXksIGpxWEhSLCBleHRyYURhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmpxWEhSID0ganFYSFI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnJlc3BvbnNlID0gZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zaG93RXJyb3IoZGF0YS5lcnJvciwgcGFyYW1zLCAnZmlsZWRlbGV0ZWVycm9yJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldFByb2dyZXNzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpLmFkZENsYXNzKCdmaWxlLWRlbGV0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5mYWRlT3V0KCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyAkZnJhbWUuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyT2JqZWN0cygkZnJhbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldFByb2dyZXNzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFuICYmIHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLmRlbGV0ZVRodW1iLCBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmpxWEhSID0ganFYSFI7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dFcnJvcihlcnJNc2csIHBhcmFtcywgJ2ZpbGVkZWxldGVlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRQcm9ncmVzcygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgc2VsZi5hamF4RGVsZXRlU2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5fdmFsaWRhdGVNaW5Db3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJC5hamF4KHNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaGlkZUZpbGVJY29uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2FwdGlvbkNvbnRhaW5lci5maW5kKCcua3YtY2FwdGlvbi1pY29uJykuaGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2hvd0ZpbGVJY29uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5zaG93KCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRTaXplOiBmdW5jdGlvbiAoYnl0ZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgc2l6ZSA9IHBhcnNlRmxvYXQoYnl0ZXMpLCBpLCBmdW5jID0gc2VsZi5maWxlU2l6ZUdldHRlciwgc2l6ZXMsIG91dDtcbiAgICAgICAgICAgIGlmICghJC5pc051bWVyaWMoYnl0ZXMpIHx8ICEkLmlzTnVtZXJpYyhzaXplKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIG91dCA9IGZ1bmMoc2l6ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzaXplID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9ICcwLjAwIEInO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGkgPSBNYXRoLmZsb29yKE1hdGgubG9nKHNpemUpIC8gTWF0aC5sb2coMTAyNCkpO1xuICAgICAgICAgICAgICAgICAgICBzaXplcyA9IFsnQicsICdLQicsICdNQicsICdHQicsICdUQicsICdQQicsICdFQicsICdaQicsICdZQiddO1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSAoc2l6ZSAvIE1hdGgucG93KDEwMjQsIGkpKS50b0ZpeGVkKDIpICogMSArICcgJyArIHNpemVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnc2l6ZScpLnJlcGxhY2UoJ3tzaXplVGV4dH0nLCBvdXQpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGU6IGZ1bmN0aW9uIChjYXQsIGRhdGEsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBpc0Vycm9yLCBzaXplLCBmcmFtZUNsYXNzLCBmb290LCBpbmQsIHRlbXBsKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLCBwcmV2Q29udGVudCwgem9vbUNvbnRlbnQgPSAnJyxcbiAgICAgICAgICAgICAgICBjb25maWcgPSBzZWxmLnByZXZpZXdTZXR0aW5nc1tjYXRdIHx8IHNlbGYuZGVmYXVsdHMucHJldmlld1NldHRpbmdzW2NhdF0sXG4gICAgICAgICAgICAgICAgdyA9IGNvbmZpZyAmJiBjb25maWcud2lkdGggPyBjb25maWcud2lkdGggOiAnJywgaCA9IGNvbmZpZyAmJiBjb25maWcuaGVpZ2h0ID8gY29uZmlnLmhlaWdodCA6ICcnLFxuICAgICAgICAgICAgICAgIGZvb3RlciA9IGZvb3QgfHwgc2VsZi5fcmVuZGVyRmlsZUZvb3RlcihjYXB0aW9uLCBzaXplLCAoJGguaXNFbXB0eSh3KSA/ICdhdXRvJyA6IHcpLCBpc0Vycm9yKSxcbiAgICAgICAgICAgICAgICBoYXNJY29uU2V0dGluZyA9IHNlbGYuX2dldFByZXZpZXdJY29uKGZuYW1lKSwgdHlwZUNzcyA9ICd0eXBlLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgIGZvcmNlUHJldkljb24gPSBoYXNJY29uU2V0dGluZyAmJiBzZWxmLnByZWZlckljb25pY1ByZXZpZXcsXG4gICAgICAgICAgICAgICAgZm9yY2Vab29tSWNvbiA9IGhhc0ljb25TZXR0aW5nICYmIHNlbGYucHJlZmVySWNvbmljWm9vbVByZXZpZXcsXG4gICAgICAgICAgICAgICAgZ2V0Q29udGVudCA9IGZ1bmN0aW9uIChjLCBkLCB6b29tLCBmcmFtZUNzcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaWQgPSB6b29tID8gJ3pvb20tJyArIHByZXZpZXdJZCA6IHByZXZpZXdJZCwgdG1wbHQgPSBzZWxmLl9nZXRQcmV2aWV3VGVtcGxhdGUoYyksXG4gICAgICAgICAgICAgICAgICAgICAgICBjc3MgPSAoZnJhbWVDbGFzcyB8fCAnJykgKyAnICcgKyBmcmFtZUNzcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuZnJhbWVDbGFzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3NzID0gc2VsZi5mcmFtZUNsYXNzICsgJyAnICsgY3NzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh6b29tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjc3MgPSBjc3MucmVwbGFjZSgnICcgKyAkaC5TT1JUX0NTUywgJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRtcGx0ID0gc2VsZi5fcGFyc2VGaWxlUHJldmlld0ljb24odG1wbHQsIGZuYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMgPT09ICd0ZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZCA9ICRoLmh0bWxFbmNvZGUoZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhdCA9PT0gJ29iamVjdCcgJiYgIWZ0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2goc2VsZi5kZWZhdWx0cy5maWxlVHlwZVNldHRpbmdzLCBmdW5jdGlvbiAoa2V5LCBmdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ29iamVjdCcgfHwga2V5ID09PSAnb3RoZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmMoZm5hbWUsIGZ0eXBlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlQ3NzID0gJ3R5cGUtJyArIGtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdG1wbHQuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICdwcmV2aWV3SWQnOiBpZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdjYXB0aW9uJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICdmcmFtZUNsYXNzJzogY3NzLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBmdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICdmaWxlaW5kZXgnOiBpbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3LFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2hlaWdodCc6IGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAndHlwZUNzcyc6IHR5cGVDc3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZm9vdGVyJzogZm9vdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2RhdGEnOiBkLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RlbXBsYXRlJzogdGVtcGwgfHwgY2F0XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpbmQgPSBpbmQgfHwgcHJldmlld0lkLnNsaWNlKHByZXZpZXdJZC5sYXN0SW5kZXhPZignLScpICsgMSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5maWxlQWN0aW9uU2V0dGluZ3Muc2hvd1pvb20pIHtcbiAgICAgICAgICAgICAgICB6b29tQ29udGVudCA9IGdldENvbnRlbnQoKGZvcmNlWm9vbUljb24gPyAnb3RoZXInIDogY2F0KSwgZGF0YSwgdHJ1ZSwgJ2t2LXpvb20tdGh1bWInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHpvb21Db250ZW50ID0gJ1xcbicgKyBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnem9vbUNhY2hlJykucmVwbGFjZSgne3pvb21Db250ZW50fScsIHpvb21Db250ZW50KTtcbiAgICAgICAgICAgIHByZXZDb250ZW50ID0gZ2V0Q29udGVudCgoZm9yY2VQcmV2SWNvbiA/ICdvdGhlcicgOiBjYXQpLCBkYXRhLCBmYWxzZSwgJ2t2LXByZXZpZXctdGh1bWInKTtcbiAgICAgICAgICAgIHJldHVybiBwcmV2Q29udGVudCArIHpvb21Db250ZW50O1xuICAgICAgICB9LFxuICAgICAgICBfcHJldmlld0RlZmF1bHQ6IGZ1bmN0aW9uIChmaWxlLCBwcmV2aWV3SWQsIGlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGZuYW1lID0gZmlsZSA/IGZpbGUubmFtZSA6ICcnLCBmdHlwZSA9IGZpbGUgPyBmaWxlLnR5cGUgOiAnJywgY29udGVudCwgc2l6ZSA9IGZpbGUuc2l6ZSB8fCAwLFxuICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLCBpc0Vycm9yID0gaXNEaXNhYmxlZCA9PT0gdHJ1ZSAmJiAhc2VsZi5pc1VwbG9hZGFibGUsXG4gICAgICAgICAgICAgICAgZGF0YSA9ICRoLm9ialVybC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG4gICAgICAgICAgICBzZWxmLl9jbGVhckRlZmF1bHRQcmV2aWV3KCk7XG4gICAgICAgICAgICBjb250ZW50ID0gc2VsZi5fZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGUoJ290aGVyJywgZGF0YSwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGlzRXJyb3IsIHNpemUpO1xuICAgICAgICAgICAgJHByZXZpZXcuYXBwZW5kKFwiXFxuXCIgKyBjb250ZW50KTtcbiAgICAgICAgICAgIHNlbGYuX3NldFRodW1iQXR0cihwcmV2aWV3SWQsIGNhcHRpb24sIHNpemUpO1xuICAgICAgICAgICAgaWYgKGlzRGlzYWJsZWQgPT09IHRydWUgJiYgc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYlN0YXR1cygkKCcjJyArIHByZXZpZXdJZCksICdFcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfcHJldmlld0ZpbGU6IGZ1bmN0aW9uIChpLCBmaWxlLCB0aGVGaWxlLCBwcmV2aWV3SWQsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2F0ID0gc2VsZi5fcGFyc2VGaWxlVHlwZShmaWxlKSwgZm5hbWUgPSBmaWxlID8gZmlsZS5uYW1lIDogJycsIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLFxuICAgICAgICAgICAgICAgIHR5cGVzID0gc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzLCBtaW1lcyA9IHNlbGYuYWxsb3dlZFByZXZpZXdNaW1lVHlwZXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldyxcbiAgICAgICAgICAgICAgICBjaGtUeXBlcyA9IHR5cGVzICYmIHR5cGVzLmluZGV4T2YoY2F0KSA+PSAwLCBmc2l6ZSA9IGZpbGUuc2l6ZSB8fCAwLCBmdHlwZSA9IGZpbGUudHlwZSxcbiAgICAgICAgICAgICAgICBpRGF0YSA9IChjYXQgPT09ICd0ZXh0JyB8fCBjYXQgPT09ICdodG1sJyB8fCBjYXQgPT09ICdpbWFnZScpID8gdGhlRmlsZS50YXJnZXQucmVzdWx0IDogZGF0YSwgY29udGVudCxcbiAgICAgICAgICAgICAgICBjaGtNaW1lcyA9IG1pbWVzICYmIG1pbWVzLmluZGV4T2YoZnR5cGUpICE9PSAtMTtcbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIHdpbmRvdy5ET01QdXJpZnkgKi9cbiAgICAgICAgICAgIGlmIChjYXQgPT09ICdodG1sJyAmJiBzZWxmLnB1cmlmeUh0bWwgJiYgd2luZG93LkRPTVB1cmlmeSkge1xuICAgICAgICAgICAgICAgIGlEYXRhID0gd2luZG93LkRPTVB1cmlmeS5zYW5pdGl6ZShpRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2hrVHlwZXMgfHwgY2hrTWltZXMpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gc2VsZi5fZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGUoY2F0LCBpRGF0YSwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGZhbHNlLCBmc2l6ZSk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJEZWZhdWx0UHJldmlldygpO1xuICAgICAgICAgICAgICAgICRwcmV2aWV3LmFwcGVuZChcIlxcblwiICsgY29udGVudCk7XG4gICAgICAgICAgICAgICAgdmFyICRpbWcgPSAkcHJldmlldy5maW5kKCcjJyArIHByZXZpZXdJZCArICcgaW1nJyk7XG4gICAgICAgICAgICAgICAgaWYgKCRpbWcubGVuZ3RoICYmIHNlbGYuYXV0b09yaWVudEltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICRoLnZhbGlkYXRlT3JpZW50YXRpb24oZmlsZSwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHpvb21JbWcgPSAkcHJldmlldy5maW5kKCcjem9vbS0nICsgcHJldmlld0lkICsgJyBpbWcnKSwgY3NzID0gJ3JvdGF0ZS0nICsgdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID4gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjc3MgKz0gKCRpbWcud2lkdGgoKSA+ICRpbWcuaGVpZ2h0KCkgPyAnIGlzLXBvcnRyYWl0LWd0NCcgOiAnIGlzLWxhbmRzY2FwZS1ndDQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRpbWcsIGNzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCR6b29tSW1nLCBjc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VvcmllbnRlZCcsIHsnJGltZyc6ICRpbWcsICdmaWxlJzogZmlsZX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVJbWFnZShwcmV2aWV3SWQsIGNhcHRpb24sIGZ0eXBlLCBmc2l6ZSwgaURhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRqdXN0T3JpZW50ZWRJbWFnZSgkaW1nKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVJbWFnZShwcmV2aWV3SWQsIGNhcHRpb24sIGZ0eXBlLCBmc2l6ZSwgaURhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3NldFRodW1iQXR0cihwcmV2aWV3SWQsIGNhcHRpb24sIGZzaXplKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0VGh1bWJBdHRyOiBmdW5jdGlvbiAoaWQsIGNhcHRpb24sIHNpemUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gJCgnIycgKyBpZCk7XG4gICAgICAgICAgICBpZiAoJGZyYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNpemUgPSBzaXplICYmIHNpemUgPiAwID8gc2VsZi5fZ2V0U2l6ZShzaXplKSA6ICcnO1xuICAgICAgICAgICAgICAgICRmcmFtZS5kYXRhKHsnY2FwdGlvbic6IGNhcHRpb24sICdzaXplJzogc2l6ZX0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2V0SW5pdFRodW1iQXR0cjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSwgbGVuID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQodHJ1ZSksIGNvbmZpZyxcbiAgICAgICAgICAgICAgICBjYXB0aW9uLCBzaXplLCBwcmV2aWV3SWQ7XG4gICAgICAgICAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArICctJyArICdpbml0XycgKyBpO1xuICAgICAgICAgICAgICAgIGNhcHRpb24gPSAkaC5pZlNldCgnY2FwdGlvbicsIGNvbmZpZywgJGguaWZTZXQoJ2ZpbGVuYW1lJywgY29uZmlnKSk7XG4gICAgICAgICAgICAgICAgc2l6ZSA9ICRoLmlmU2V0KCdzaXplJywgY29uZmlnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYkF0dHIocHJldmlld0lkLCBjYXB0aW9uLCBzaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3NsdWdEZWZhdWx0OiBmdW5jdGlvbiAodGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuICRoLmlzRW1wdHkodGV4dCkgPyAnJyA6IFN0cmluZyh0ZXh0KS5yZXBsYWNlKC9bXFwtXFxbXFxdXFwvXFx7fTo7IyU9XFwoXFwpXFwqXFwrXFw/XFxcXFxcXlxcJFxcfDw+JlwiJ10vZywgJ18nKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlYWRGaWxlczogZnVuY3Rpb24gKGZpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldywgcmVhZGVyID0gc2VsZi5yZWFkZXIsXG4gICAgICAgICAgICAgICAgJGNvbnRhaW5lciA9IHNlbGYuJHByZXZpZXdDb250YWluZXIsICRzdGF0dXMgPSBzZWxmLiRwcmV2aWV3U3RhdHVzLCBtc2dMb2FkaW5nID0gc2VsZi5tc2dMb2FkaW5nLFxuICAgICAgICAgICAgICAgIG1zZ1Byb2dyZXNzID0gc2VsZi5tc2dQcm9ncmVzcywgcHJldmlld0luaXRJZCA9IHNlbGYucHJldmlld0luaXRJZCwgbnVtRmlsZXMgPSBmaWxlcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSBzZWxmLmZpbGVUeXBlU2V0dGluZ3MsIGN0ciA9IHNlbGYuZmlsZXN0YWNrLmxlbmd0aCwgcmVhZEZpbGUsXG4gICAgICAgICAgICAgICAgZmlsZVR5cGVzID0gc2VsZi5hbGxvd2VkRmlsZVR5cGVzLCB0eXBMZW4gPSBmaWxlVHlwZXMgPyBmaWxlVHlwZXMubGVuZ3RoIDogMCxcbiAgICAgICAgICAgICAgICBmaWxlRXh0ID0gc2VsZi5hbGxvd2VkRmlsZUV4dGVuc2lvbnMsIHN0ckV4dCA9ICRoLmlzRW1wdHkoZmlsZUV4dCkgPyAnJyA6IGZpbGVFeHQuam9pbignLCAnKSxcbiAgICAgICAgICAgICAgICBtYXhQcmV2aWV3U2l6ZSA9IHNlbGYubWF4RmlsZVByZXZpZXdTaXplICYmIHBhcnNlRmxvYXQoc2VsZi5tYXhGaWxlUHJldmlld1NpemUpLFxuICAgICAgICAgICAgICAgIGNhblByZXZpZXcgPSAkcHJldmlldy5sZW5ndGggJiYgKCFtYXhQcmV2aWV3U2l6ZSB8fCBpc05hTihtYXhQcmV2aWV3U2l6ZSkpLFxuICAgICAgICAgICAgICAgIHRocm93RXJyb3IgPSBmdW5jdGlvbiAobXNnLCBmaWxlLCBwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwMSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBzZWxmLl9nZXRPdXREYXRhKHt9LCB7fSwgZmlsZXMpLCB7aWQ6IHByZXZpZXdJZCwgaW5kZXg6IGluZGV4fSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwMiA9IHtpZDogcHJldmlld0lkLCBpbmRleDogaW5kZXgsIGZpbGU6IGZpbGUsIGZpbGVzOiBmaWxlc307XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdEZWZhdWx0KGZpbGUsIHByZXZpZXdJZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRUb1N0YWNrKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpbmRleCArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0RmlsZUFjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYucmVtb3ZlRnJvbVByZXZpZXdPbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcjJyArIHByZXZpZXdJZCkucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1zZywgcDEpIDogc2VsZi5fc2hvd0Vycm9yKG1zZywgcDIpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuXG4gICAgICAgICAgICAkLmVhY2goZmlsZXMsIGZ1bmN0aW9uIChrZXksIGZpbGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IHNlbGYuZmlsZVR5cGVTZXR0aW5ncy5pbWFnZTtcbiAgICAgICAgICAgICAgICBpZiAoZnVuYyAmJiBmdW5jKGZpbGUudHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi50b3RhbEltYWdlc0NvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZWFkRmlsZSA9IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoJGVsLmF0dHIoJ211bHRpcGxlJykpKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bUZpbGVzID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGkgPj0gbnVtRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlICYmIHNlbGYuZmlsZXN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hzZWxlY3RlZCcsIFtzZWxmLmdldEZpbGVTdGFjaygpXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNoc2VsZWN0ZWQnLCBbZmlsZXNdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgJHN0YXR1cy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IGN0ciArIGksIHByZXZpZXdJZCA9IHByZXZpZXdJbml0SWQgKyBcIi1cIiArIG5vZGUsIGlzVGV4dCwgaXNJbWFnZSwgZmlsZSA9IGZpbGVzW2ldLCBmU2l6ZUtCLFxuICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gZmlsZS5uYW1lID8gc2VsZi5zbHVnKGZpbGUubmFtZSkgOiAnJywgZmlsZVNpemUgPSAoZmlsZS5zaXplIHx8IDApIC8gMTAwMCwgaiwgbXNnLFxuICAgICAgICAgICAgICAgICAgICBmaWxlRXh0RXhwciA9ICcnLCBwcmV2aWV3RGF0YSA9ICRoLm9ialVybC5jcmVhdGVPYmplY3RVUkwoZmlsZSksIHR5cCwgY2hrLCB0eXAxLCB0eXAyLFxuICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgPSAwLCBzdHJUeXBlcyA9ICcnLCBmdW5jO1xuICAgICAgICAgICAgICAgIGlmICh0eXBMZW4gPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB0eXBMZW47IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwMSA9IGZpbGVUeXBlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cDIgPSBzZWxmLm1zZ0ZpbGVUeXBlc1t0eXAxXSB8fCB0eXAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyVHlwZXMgKz0gaiA9PT0gMCA/IHR5cDIgOiAnLCAnICsgdHlwMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2FwdGlvbiA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjYXB0aW9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ludmFsaWRGaWxlTmFtZS5yZXBsYWNlKCd7bmFtZX0nLCAkaC5odG1sRW5jb2RlKGZpbGUubmFtZSkpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZUV4dCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZUV4dEV4cHIgPSBuZXcgUmVnRXhwKCdcXFxcLignICsgZmlsZUV4dC5qb2luKCd8JykgKyAnKSQnLCAnaScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmU2l6ZUtCID0gZmlsZVNpemUudG9GaXhlZCgyKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5tYXhGaWxlU2l6ZSA+IDAgJiYgZmlsZVNpemUgPiBzZWxmLm1heEZpbGVTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnU2l6ZVRvb0xhcmdlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAnbmFtZSc6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZSc6IGZTaXplS0IsXG4gICAgICAgICAgICAgICAgICAgICAgICAnbWF4U2l6ZSc6IHNlbGYubWF4RmlsZVNpemVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IHRocm93RXJyb3IobXNnLCBmaWxlLCBwcmV2aWV3SWQsIGkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzZWxmLm1pbkZpbGVTaXplICE9PSBudWxsICYmIGZpbGVTaXplIDw9ICRoLmdldE51bShzZWxmLm1pbkZpbGVTaXplKSkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ1NpemVUb29TbWFsbC5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBmU2l6ZUtCLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ21pblNpemUnOiBzZWxmLm1pbkZpbGVTaXplXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZVR5cGVzKSAmJiAkaC5pc0FycmF5KGZpbGVUeXBlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGZpbGVUeXBlcy5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwID0gZmlsZVR5cGVzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuYyA9IHNldHRpbmdzW3R5cF07XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgKz0gIWZ1bmMgfHwgKHR5cGVvZiBmdW5jICE9PSAnZnVuY3Rpb24nKSA/IDAgOiAoZnVuYyhmaWxlLnR5cGUsIGZpbGUubmFtZSkgPyAxIDogMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGVDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dJbnZhbGlkRmlsZVR5cGUuc2V0VG9rZW5zKHsnbmFtZSc6IGNhcHRpb24sICd0eXBlcyc6IHN0clR5cGVzfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmlsZUNvdW50ID09PSAwICYmICEkaC5pc0VtcHR5KGZpbGVFeHQpICYmICRoLmlzQXJyYXkoZmlsZUV4dCkgJiYgISRoLmlzRW1wdHkoZmlsZUV4dEV4cHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoayA9ICRoLmNvbXBhcmUoY2FwdGlvbiwgZmlsZUV4dEV4cHIpO1xuICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgKz0gJGguaXNFbXB0eShjaGspID8gMCA6IGNoay5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnSW52YWxpZEZpbGVFeHRlbnNpb24uc2V0VG9rZW5zKHsnbmFtZSc6IGNhcHRpb24sICdleHRlbnNpb25zJzogc3RyRXh0fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmFkZFRvU3RhY2soZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlbG9hZGVkJywgW2ZpbGUsIHByZXZpZXdJZCwgaSwgcmVhZGVyXSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFjYW5QcmV2aWV3ICYmIGZpbGVTaXplID4gbWF4UHJldmlld1NpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRUb1N0YWNrKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLmFkZENsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdEZpbGVBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKG51bUZpbGVzKTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgkcHJldmlldy5sZW5ndGggJiYgRmlsZVJlYWRlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2dMb2FkaW5nLnJlcGxhY2UoJ3tpbmRleH0nLCBpICsgMSkucmVwbGFjZSgne2ZpbGVzfScsIG51bUZpbGVzKSk7XG4gICAgICAgICAgICAgICAgICAgICRjb250YWluZXIuYWRkQ2xhc3MoJ2ZpbGUtdGh1bWItbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2Vycm9ySGFuZGxlcihldnQsIGNhcHRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKHRoZUZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdGaWxlKGksIGZpbGUsIHRoZUZpbGUsIHByZXZpZXdJZCwgcHJldmlld0RhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdEZpbGVBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5vbmxvYWRlbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBtc2dQcm9ncmVzcy5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpbmRleCc6IGkgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdmaWxlcyc6IG51bUZpbGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdwZXJjZW50JzogNTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKG51bUZpbGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVsb2FkZWQnLCBbZmlsZSwgcHJldmlld0lkLCBpLCByZWFkZXJdKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEubGVuZ3RoQ29tcHV0YWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmYWN0ID0gKGRhdGEubG9hZGVkIC8gZGF0YS50b3RhbCkgKiAxMDAsIHByb2dyZXNzID0gTWF0aC5jZWlsKGZhY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZyA9IG1zZ1Byb2dyZXNzLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpbmRleCc6IGkgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmlsZXMnOiBudW1GaWxlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3BlcmNlbnQnOiBwcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlzVGV4dCA9IHNldHRpbmdzLnRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGlzSW1hZ2UgPSBzZXR0aW5ncy5pbWFnZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNUZXh0KGZpbGUudHlwZSwgY2FwdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUsIHNlbGYudGV4dEVuY29kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0ltYWdlKGZpbGUudHlwZSwgY2FwdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlbG9hZGVkJywgW2ZpbGUsIHByZXZpZXdJZCwgaSwgcmVhZGVyXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuYWRkVG9TdGFjayhmaWxlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJlYWRGaWxlKDApO1xuICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMobnVtRmlsZXMsIGZhbHNlKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwZGF0ZUZpbGVEZXRhaWxzOiBmdW5jdGlvbiAobnVtRmlsZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kZWxlbWVudCwgZmlsZVN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2soKSxcbiAgICAgICAgICAgICAgICBuYW1lID0gKCRoLmlzSUUoOSkgJiYgJGguZmluZEZpbGVOYW1lKCRlbC52YWwoKSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICgkZWxbMF0uZmlsZXNbMF0gJiYgJGVsWzBdLmZpbGVzWzBdLm5hbWUpIHx8IChmaWxlU3RhY2subGVuZ3RoICYmIGZpbGVTdGFja1swXS5uYW1lKSB8fCAnJyxcbiAgICAgICAgICAgICAgICBsYWJlbCA9IHNlbGYuc2x1ZyhuYW1lKSwgbiA9IHNlbGYuaXNVcGxvYWRhYmxlID8gZmlsZVN0YWNrLmxlbmd0aCA6IG51bUZpbGVzLFxuICAgICAgICAgICAgICAgIG5GaWxlcyA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCkgKyBuLCBsb2cgPSBuID4gMSA/IHNlbGYuX2dldE1zZ1NlbGVjdGVkKG5GaWxlcykgOiBsYWJlbDtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3Q29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3U3RhdHVzLmh0bWwoJycpO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmt2LWNhcHRpb24taWNvbicpLmhpZGUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0ZpbGVJY29uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGxvZywgc2VsZi5pc0Vycm9yKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS1pbnB1dC1uZXcgZmlsZS1pbnB1dC1hamF4LW5ldycpO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXNlbGVjdCcsIFtudW1GaWxlcywgbGFiZWxdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRUaHVtYlN0YXR1czogZnVuY3Rpb24gKCR0aHVtYiwgc3RhdHVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaWNvbiA9ICdpbmRpY2F0b3InICsgc3RhdHVzLCBtc2cgPSBpY29uICsgJ1RpdGxlJyxcbiAgICAgICAgICAgICAgICBjc3MgPSAnZmlsZS1wcmV2aWV3LScgKyBzdGF0dXMudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgICAgICAgICAkaW5kaWNhdG9yID0gJHRodW1iLmZpbmQoJy5maWxlLXVwbG9hZC1pbmRpY2F0b3InKSxcbiAgICAgICAgICAgICAgICBjb25maWcgPSBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncztcbiAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS1wcmV2aWV3LXN1Y2Nlc3MgZmlsZS1wcmV2aWV3LWVycm9yIGZpbGUtcHJldmlldy1sb2FkaW5nJyk7XG4gICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnU3VjY2VzcycpIHtcbiAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmZpbGUtZHJhZy1oYW5kbGUnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAkaW5kaWNhdG9yLmNzcygnbWFyZ2luLWxlZnQnLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRpbmRpY2F0b3IuaHRtbChjb25maWdbaWNvbl0pO1xuICAgICAgICAgICAgJGluZGljYXRvci5hdHRyKCd0aXRsZScsIGNvbmZpZ1ttc2ddKTtcbiAgICAgICAgICAgICR0aHVtYi5hZGRDbGFzcyhjc3MpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0UHJvZ3Jlc3NDYW5jZWxsZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSwgc2VsZi4kcHJvZ3Jlc3MsIHNlbGYubXNnQ2FuY2VsbGVkKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3NldFByb2dyZXNzOiBmdW5jdGlvbiAocCwgJGVsLCBlcnJvcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBwY3QgPSBNYXRoLm1pbihwLCAxMDApLCBvdXQsIHBjdExpbWl0ID0gc2VsZi5wcm9ncmVzc1VwbG9hZFRocmVzaG9sZCxcbiAgICAgICAgICAgICAgICB0ID0gcCA8PSAxMDAgPyBzZWxmLnByb2dyZXNzVGVtcGxhdGUgOiBzZWxmLnByb2dyZXNzQ29tcGxldGVUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZSA9IHBjdCA8IDEwMCA/IHNlbGYucHJvZ3Jlc3NUZW1wbGF0ZSA6IChlcnJvciA/IHNlbGYucHJvZ3Jlc3NFcnJvclRlbXBsYXRlIDogdCk7XG4gICAgICAgICAgICAkZWwgPSAkZWwgfHwgc2VsZi4kcHJvZ3Jlc3M7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkodGVtcGxhdGUpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBjdExpbWl0ICYmIHBjdCA+IHBjdExpbWl0ICYmIHAgPD0gMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7J3BlcmNlbnQnOiBwY3RMaW1pdCwgJ3N0YXR1cyc6IHNlbGYubXNnVXBsb2FkVGhyZXNob2xkfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0ID0gdGVtcGxhdGUuc2V0VG9rZW5zKHsncGVyY2VudCc6IHBjdCwgJ3N0YXR1cyc6IChwID4gMTAwID8gc2VsZi5tc2dVcGxvYWRFbmQgOiBwY3QgKyAnJScpfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRlbC5odG1sKG91dCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICRlbC5maW5kKCdbcm9sZT1cInByb2dyZXNzYmFyXCJdJykuaHRtbChlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2V0RmlsZURyb3Bab25lVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHpvbmUgPSBzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGUtZHJvcC16b25lJyksIHRpdGxlID0gc2VsZi5kcm9wWm9uZVRpdGxlLCBzdHJGaWxlcztcbiAgICAgICAgICAgIGlmIChzZWxmLmlzQ2xpY2thYmxlKSB7XG4gICAgICAgICAgICAgICAgc3RyRmlsZXMgPSAkaC5pc0VtcHR5KHNlbGYuJGVsZW1lbnQuYXR0cignbXVsdGlwbGUnKSkgPyBzZWxmLmZpbGVTaW5nbGUgOiBzZWxmLmZpbGVQbHVyYWw7XG4gICAgICAgICAgICAgICAgdGl0bGUgKz0gc2VsZi5kcm9wWm9uZUNsaWNrVGl0bGUucmVwbGFjZSgne2ZpbGVzfScsIHN0ckZpbGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR6b25lLmZpbmQoJy4nICsgc2VsZi5kcm9wWm9uZVRpdGxlQ2xhc3MpLnJlbW92ZSgpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSB8fCAhc2VsZi5zaG93UHJldmlldyB8fCAkem9uZS5sZW5ndGggPT09IDAgfHwgc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGggPiAwIHx8ICFzZWxmLmRyb3Bab25lRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkem9uZS5maW5kKCRoLkZSQU1FUykubGVuZ3RoID09PSAwICYmICRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgJHpvbmUucHJlcGVuZCgnPGRpdiBjbGFzcz1cIicgKyBzZWxmLmRyb3Bab25lVGl0bGVDbGFzcyArICdcIj4nICsgdGl0bGUgKyAnPC9kaXY+Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnZmlsZS1pbnB1dC1hamF4LW5ldycpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0QXN5bmNVcGxvYWRTdGF0dXM6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIHBjdCwgdG90YWwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgc3VtID0gMDtcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKHBjdCwgJCgnIycgKyBwcmV2aWV3SWQpLmZpbmQoJy5maWxlLXRodW1iLXByb2dyZXNzJykpO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRTdGF0dXNbcHJldmlld0lkXSA9IHBjdDtcbiAgICAgICAgICAgICQuZWFjaChzZWxmLnVwbG9hZFN0YXR1cywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzdW0gKz0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKE1hdGguZmxvb3Ioc3VtIC8gdG90YWwpKTtcblxuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGVNaW5Db3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsZW4gPSBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoIDogc2VsZi4kZWxlbWVudC5nZXQoMCkuZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHNlbGYudmFsaWRhdGVJbml0aWFsQ291bnQgJiYgc2VsZi5taW5GaWxlQ291bnQgPiAwICYmIHNlbGYuX2dldEZpbGVDb3VudChsZW4gLSAxKSA8IHNlbGYubWluRmlsZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbm9GaWxlc0Vycm9yKHt9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZpbGVDb3VudDogZnVuY3Rpb24gKGZpbGVDb3VudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhZGRDb3VudCA9IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi52YWxpZGF0ZUluaXRpYWxDb3VudCAmJiAhc2VsZi5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgYWRkQ291bnQgPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpO1xuICAgICAgICAgICAgICAgIGZpbGVDb3VudCArPSBhZGRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmaWxlQ291bnQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlSWQ6IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGN1c3RvbSA9IHNlbGYuZ2VuZXJhdGVGaWxlSWQsIHJlbGF0aXZlUGF0aDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VzdG9tID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN1c3RvbShmaWxlLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGZpbGUud2Via2l0UmVsYXRpdmVQYXRoICovXG4gICAgICAgICAgICByZWxhdGl2ZVBhdGggPSBmaWxlLndlYmtpdFJlbGF0aXZlUGF0aCB8fCBmaWxlLmZpbGVOYW1lIHx8IGZpbGUubmFtZSB8fCBudWxsO1xuICAgICAgICAgICAgaWYgKCFyZWxhdGl2ZVBhdGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoZmlsZS5zaXplICsgJy0nICsgcmVsYXRpdmVQYXRoLnJlcGxhY2UoL1teMC05YS16QS1aXy1dL2ltZywgJycpKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZpbGVOYW1lOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZpbGUgJiYgZmlsZS5uYW1lID8gdGhpcy5zbHVnKGZpbGUubmFtZSkgOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlSWRzOiBmdW5jdGlvbiAoc2tpcE51bGwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmZpbGVpZHMuZmlsdGVyKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChza2lwTnVsbCA/IG4gIT09IHVuZGVmaW5lZCA6IG4gIT09IHVuZGVmaW5lZCAmJiBuICE9PSBudWxsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RmlsZU5hbWVzOiBmdW5jdGlvbiAoc2tpcE51bGwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmZpbGVuYW1lcy5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHNraXBOdWxsID8gbiAhPT0gdW5kZWZpbmVkIDogbiAhPT0gdW5kZWZpbmVkICYmIG4gIT09IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRQcmV2aWV3RXJyb3I6IGZ1bmN0aW9uICgkdGh1bWIsIGksIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKGkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soaSwgdmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnJlbW92ZUZyb21QcmV2aWV3T25FcnJvcikge1xuICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnRXJyb3InKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2NoZWNrRGltZW5zaW9uczogZnVuY3Rpb24gKGksIGNoaywgJGltZywgJHRodW1iLCBmbmFtZSwgdHlwZSwgcGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIG1zZywgZGltLCB0YWcgPSBjaGsgPT09ICdTbWFsbCcgPyAnbWluJyA6ICdtYXgnLCBsaW1pdCA9IHNlbGZbdGFnICsgJ0ltYWdlJyArIHR5cGVdLFxuICAgICAgICAgICAgICAgICRpbWdFbCwgaXNWYWxpZDtcbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KGxpbWl0KSB8fCAhJGltZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaW1nRWwgPSAkaW1nWzBdO1xuICAgICAgICAgICAgZGltID0gKHR5cGUgPT09ICdXaWR0aCcpID8gJGltZ0VsLm5hdHVyYWxXaWR0aCB8fCAkaW1nRWwud2lkdGggOiAkaW1nRWwubmF0dXJhbEhlaWdodCB8fCAkaW1nRWwuaGVpZ2h0O1xuICAgICAgICAgICAgaXNWYWxpZCA9IGNoayA9PT0gJ1NtYWxsJyA/IGRpbSA+PSBsaW1pdCA6IGRpbSA8PSBsaW1pdDtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbXNnID0gc2VsZlsnbXNnSW1hZ2UnICsgdHlwZSArIGNoa10uc2V0VG9rZW5zKHsnbmFtZSc6IGZuYW1lLCAnc2l6ZSc6IGxpbWl0fSk7XG4gICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3IobXNnLCBwYXJhbXMpO1xuICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYiwgaSwgbnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIF92YWxpZGF0ZUltYWdlOiBmdW5jdGlvbiAocHJldmlld0lkLCBmbmFtZSwgZnR5cGUsIGZzaXplLCBpRGF0YSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkcHJldmlldyA9IHNlbGYuJHByZXZpZXcsIHBhcmFtcywgdzEsIHcyLCAkdGh1bWIgPSAkcHJldmlldy5maW5kKFwiI1wiICsgcHJldmlld0lkKSxcbiAgICAgICAgICAgICAgICBpID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4JyksICRpbWcgPSAkdGh1bWIuZmluZCgnaW1nJyksIGV4aWZPYmplY3Q7XG4gICAgICAgICAgICBmbmFtZSA9IGZuYW1lIHx8ICdVbnRpdGxlZCc7XG4gICAgICAgICAgICAkaW1nLm9uZSgnbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB3MSA9ICR0aHVtYi53aWR0aCgpO1xuICAgICAgICAgICAgICAgIHcyID0gJHByZXZpZXcud2lkdGgoKTtcbiAgICAgICAgICAgICAgICBpZiAodzEgPiB3Mikge1xuICAgICAgICAgICAgICAgICAgICAkaW1nLmNzcygnd2lkdGgnLCAnMTAwJScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJhbXMgPSB7aW5kOiBpLCBpZDogcHJldmlld0lkfTtcbiAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ1NtYWxsJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ1dpZHRoJywgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ1NtYWxsJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ0hlaWdodCcsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLnJlc2l6ZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2NoZWNrRGltZW5zaW9ucyhpLCAnTGFyZ2UnLCAkaW1nLCAkdGh1bWIsIGZuYW1lLCAnV2lkdGgnLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ0xhcmdlJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ0hlaWdodCcsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2Vsb2FkZWQnLCBbcHJldmlld0lkXSk7XG4gICAgICAgICAgICAgICAgZXhpZk9iamVjdCA9IHdpbmRvdy5waWV4aWYgPyB3aW5kb3cucGlleGlmLmxvYWQoaURhdGEpIDogbnVsbDtcbiAgICAgICAgICAgICAgICBzZWxmLmxvYWRlZEltYWdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgaW5kOiBpLFxuICAgICAgICAgICAgICAgICAgICBpbWc6ICRpbWcsXG4gICAgICAgICAgICAgICAgICAgIHRodW1iOiAkdGh1bWIsXG4gICAgICAgICAgICAgICAgICAgIHBpZDogcHJldmlld0lkLFxuICAgICAgICAgICAgICAgICAgICB0eXA6IGZ0eXBlLFxuICAgICAgICAgICAgICAgICAgICBzaXo6IGZzaXplLFxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBpbWdEYXRhOiBpRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgZXhpZk9iajogZXhpZk9iamVjdFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICR0aHVtYi5kYXRhKCdleGlmJywgZXhpZk9iamVjdCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVBbGxJbWFnZXMoKTtcbiAgICAgICAgICAgIH0pLm9uZSgnZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZWxvYWRlcnJvcicsIFtwcmV2aWV3SWRdKTtcbiAgICAgICAgICAgIH0pLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudHJpZ2dlcignbG9hZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRyaWdnZXIoJ2Vycm9yJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3ZhbGlkYXRlQWxsSW1hZ2VzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGksIGNvdW50ZXIgPSB7dmFsOiAwfSwgbnVtSW1ncyA9IHNlbGYubG9hZGVkSW1hZ2VzLmxlbmd0aCwgY29uZmlnLFxuICAgICAgICAgICAgICAgIGZzaXplLCBtaW5TaXplID0gc2VsZi5yZXNpemVJZlNpemVNb3JlVGhhbjtcbiAgICAgICAgICAgIGlmIChudW1JbWdzICE9PSBzZWxmLnRvdGFsSW1hZ2VzQ291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlc2xvYWRlZCcpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnJlc2l6ZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGYubG9hZGVkSW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnID0gc2VsZi5sb2FkZWRJbWFnZXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy52YWxpZGF0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZzaXplID0gY29uZmlnLnNpejtcbiAgICAgICAgICAgICAgICBpZiAoZnNpemUgJiYgZnNpemUgPiBtaW5TaXplICogMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9nZXRSZXNpemVkSW1hZ2UoY29uZmlnLCBjb3VudGVyLCBudW1JbWdzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5sb2FkZWRJbWFnZXNbaV0udmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2dldFJlc2l6ZWRJbWFnZTogZnVuY3Rpb24gKGNvbmZpZywgY291bnRlciwgbnVtSW1ncykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpbWcgPSAkKGNvbmZpZy5pbWcpWzBdLCB3aWR0aCA9IGltZy5uYXR1cmFsV2lkdGgsIGhlaWdodCA9IGltZy5uYXR1cmFsSGVpZ2h0LCBibG9iLFxuICAgICAgICAgICAgICAgIHJhdGlvID0gMSwgbWF4V2lkdGggPSBzZWxmLm1heEltYWdlV2lkdGggfHwgd2lkdGgsIG1heEhlaWdodCA9IHNlbGYubWF4SW1hZ2VIZWlnaHQgfHwgaGVpZ2h0LFxuICAgICAgICAgICAgICAgIGlzVmFsaWRJbWFnZSA9ICEhKHdpZHRoICYmIGhlaWdodCksIGNoa1dpZHRoLCBjaGtIZWlnaHQsIGNhbnZhcyA9IHNlbGYuaW1hZ2VDYW52YXMsIGRhdGFVUkksXG4gICAgICAgICAgICAgICAgY29udGV4dCA9IHNlbGYuaW1hZ2VDYW52YXNDb250ZXh0LCB0eXBlID0gY29uZmlnLnR5cCwgcGlkID0gY29uZmlnLnBpZCwgaW5kID0gY29uZmlnLmluZCxcbiAgICAgICAgICAgICAgICAkdGh1bWIgPSBjb25maWcudGh1bWIsIHRocm93RXJyb3IsIG1zZywgZXhpZk9iaiA9IGNvbmZpZy5leGlmT2JqLCBleGlmU3RyO1xuICAgICAgICAgICAgdGhyb3dFcnJvciA9IGZ1bmN0aW9uIChtc2csIHBhcmFtcywgZXYpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1zZywgcGFyYW1zLCBldik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd0Vycm9yKG1zZywgcGFyYW1zLCBldik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIsIGluZCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCFzZWxmLmZpbGVzdGFja1tpbmRdIHx8ICFpc1ZhbGlkSW1hZ2UgfHwgKHdpZHRoIDw9IG1heFdpZHRoICYmIGhlaWdodCA8PSBtYXhIZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRJbWFnZSAmJiBzZWxmLmZpbGVzdGFja1tpbmRdKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VyZXNpemVkJywgW3BpZCwgaW5kXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvdW50ZXIudmFsKys7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIudmFsID09PSBudW1JbWdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VzcmVzaXplZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvd0Vycm9yKHNlbGYubXNnSW1hZ2VSZXNpemVFcnJvciwge2lkOiBwaWQsICdpbmRleCc6IGluZH0sICdmaWxlaW1hZ2VyZXNpemVlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHlwZSA9IHR5cGUgfHwgc2VsZi5yZXNpemVEZWZhdWx0SW1hZ2VUeXBlO1xuICAgICAgICAgICAgY2hrV2lkdGggPSB3aWR0aCA+IG1heFdpZHRoO1xuICAgICAgICAgICAgY2hrSGVpZ2h0ID0gaGVpZ2h0ID4gbWF4SGVpZ2h0O1xuICAgICAgICAgICAgaWYgKHNlbGYucmVzaXplUHJlZmVyZW5jZSA9PT0gJ3dpZHRoJykge1xuICAgICAgICAgICAgICAgIHJhdGlvID0gY2hrV2lkdGggPyBtYXhXaWR0aCAvIHdpZHRoIDogKGNoa0hlaWdodCA/IG1heEhlaWdodCAvIGhlaWdodCA6IDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByYXRpbyA9IGNoa0hlaWdodCA/IG1heEhlaWdodCAvIGhlaWdodCA6IChjaGtXaWR0aCA/IG1heFdpZHRoIC8gd2lkdGggOiAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0Q2FudmFzKCk7XG4gICAgICAgICAgICB3aWR0aCAqPSByYXRpbztcbiAgICAgICAgICAgIGhlaWdodCAqPSByYXRpbztcbiAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5kcmF3SW1hZ2UoaW1nLCAwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBkYXRhVVJJID0gY2FudmFzLnRvRGF0YVVSTCh0eXBlLCBzZWxmLnJlc2l6ZVF1YWxpdHkpO1xuICAgICAgICAgICAgICAgIGlmIChleGlmT2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aWZTdHIgPSB3aW5kb3cucGlleGlmLmR1bXAoZXhpZk9iaik7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFVUkkgPSB3aW5kb3cucGlleGlmLmluc2VydChleGlmU3RyLCBkYXRhVVJJKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYmxvYiA9ICRoLmRhdGFVUkkyQmxvYihkYXRhVVJJKTtcbiAgICAgICAgICAgICAgICBzZWxmLmZpbGVzdGFja1tpbmRdID0gYmxvYjtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlcmVzaXplZCcsIFtwaWQsIGluZF0pO1xuICAgICAgICAgICAgICAgIGNvdW50ZXIudmFsKys7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIudmFsID09PSBudW1JbWdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VzcmVzaXplZCcsIFt1bmRlZmluZWQsIHVuZGVmaW5lZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIShibG9iIGluc3RhbmNlb2YgQmxvYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihzZWxmLm1zZ0ltYWdlUmVzaXplRXJyb3IsIHtpZDogcGlkLCAnaW5kZXgnOiBpbmR9LCAnZmlsZWltYWdlcmVzaXplZXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY291bnRlci52YWwrKztcbiAgICAgICAgICAgICAgICBpZiAoY291bnRlci52YWwgPT09IG51bUltZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZXNyZXNpemVkJywgW3VuZGVmaW5lZCwgdW5kZWZpbmVkXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnSW1hZ2VSZXNpemVFeGNlcHRpb24ucmVwbGFjZSgne2Vycm9yc30nLCBlcnIubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgdGhyb3dFcnJvcihtc2csIHtpZDogcGlkLCAnaW5kZXgnOiBpbmR9LCAnZmlsZWltYWdlcmVzaXplZXhjZXB0aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0QnJvd3NlOiBmdW5jdGlvbiAoJGNvbnRhaW5lcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd0Jyb3dzZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGJ0bkZpbGUgPSAkY29udGFpbmVyLmZpbmQoJy5idG4tZmlsZScpO1xuICAgICAgICAgICAgICAgIHNlbGYuJGJ0bkZpbGUuYXBwZW5kKHNlbGYuJGVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRlbGVtZW50LmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRDYXB0aW9uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcCA9IHNlbGYuaW5pdGlhbENhcHRpb24gfHwgJyc7XG4gICAgICAgICAgICBpZiAoc2VsZi5vdmVyd3JpdGVJbml0aWFsIHx8ICRoLmlzRW1wdHkoY2FwKSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRDYXB0aW9uOiBmdW5jdGlvbiAoY29udGVudCwgaXNFcnJvcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0aXRsZSwgb3V0LCBuLCBjYXAsIHN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2soKTtcbiAgICAgICAgICAgIGlmICghc2VsZi4kY2FwdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNFcnJvcikge1xuICAgICAgICAgICAgICAgIHRpdGxlID0gJCgnPGRpdj4nICsgc2VsZi5tc2dWYWxpZGF0aW9uRXJyb3IgKyAnPC9kaXY+JykudGV4dCgpO1xuICAgICAgICAgICAgICAgIG4gPSBzdGFjay5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FwID0gbiA9PT0gMSAmJiBzdGFja1swXSA/IHNlbGYuX2dldEZpbGVOYW1lcygpWzBdIDogc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2FwID0gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQoc2VsZi5tc2dObyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG91dCA9ICc8c3BhbiBjbGFzcz1cIicgKyBzZWxmLm1zZ1ZhbGlkYXRpb25FcnJvckNsYXNzICsgJ1wiPicgKyBzZWxmLm1zZ1ZhbGlkYXRpb25FcnJvckljb24gK1xuICAgICAgICAgICAgICAgICAgICAoJGguaXNFbXB0eShjb250ZW50KSA/IGNhcCA6IGNvbnRlbnQpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRpdGxlID0gJCgnPGRpdj4nICsgY29udGVudCArICc8L2Rpdj4nKS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2ZpbGVJY29uJykgKyB0aXRsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbChvdXQpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbi5hdHRyKCd0aXRsZScsIHRpdGxlKTtcbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmZpbGUtY2FwdGlvbi1lbGxpcHNpcycpLmF0dHIoJ3RpdGxlJywgdGl0bGUpO1xuICAgICAgICB9LFxuICAgICAgICBfY3JlYXRlQ29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGF0dHJpYnMgPSB7XCJjbGFzc1wiOiAnZmlsZS1pbnB1dCBmaWxlLWlucHV0LW5ldycgKyAoc2VsZi5ydGwgPyAnIGt2LXJ0bCcgOiAnJyl9LFxuICAgICAgICAgICAgICAgICRjb250YWluZXIgPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpLmF0dHIoYXR0cmlicykuaHRtbChzZWxmLl9yZW5kZXJNYWluKCkpO1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5iZWZvcmUoJGNvbnRhaW5lcik7XG4gICAgICAgICAgICBzZWxmLl9pbml0QnJvd3NlKCRjb250YWluZXIpO1xuICAgICAgICAgICAgaWYgKHNlbGYudGhlbWUpIHtcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyLmFkZENsYXNzKCd0aGVtZS0nICsgc2VsZi50aGVtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJGNvbnRhaW5lcjtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlZnJlc2hDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGNvbnRhaW5lciA9IHNlbGYuJGNvbnRhaW5lcjtcbiAgICAgICAgICAgICRjb250YWluZXIuYmVmb3JlKHNlbGYuJGVsZW1lbnQpO1xuICAgICAgICAgICAgJGNvbnRhaW5lci5odG1sKHNlbGYuX3JlbmRlck1haW4oKSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0QnJvd3NlKCRjb250YWluZXIpO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyTWFpbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgICAgICAgIGRyb3BDc3MgPSAoc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQpID8gJyBmaWxlLWRyb3Atem9uZScgOiAnZmlsZS1kcm9wLWRpc2FibGVkJyxcbiAgICAgICAgICAgICAgICBjbG9zZSA9ICFzZWxmLnNob3dDbG9zZSA/ICcnIDogc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Nsb3NlJyksXG4gICAgICAgICAgICAgICAgcHJldmlldyA9ICFzZWxmLnNob3dQcmV2aWV3ID8gJycgOiBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgncHJldmlldycpXG4gICAgICAgICAgICAgICAgICAgIC5zZXRUb2tlbnMoeydjbGFzcyc6IHNlbGYucHJldmlld0NsYXNzLCAnZHJvcENsYXNzJzogZHJvcENzc30pLFxuICAgICAgICAgICAgICAgIGNzcyA9IHNlbGYuaXNEaXNhYmxlZCA/IHNlbGYuY2FwdGlvbkNsYXNzICsgJyBmaWxlLWNhcHRpb24tZGlzYWJsZWQnIDogc2VsZi5jYXB0aW9uQ2xhc3MsXG4gICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNlbGYuY2FwdGlvblRlbXBsYXRlLnNldFRva2Vucyh7J2NsYXNzJzogY3NzICsgJyBrdi1maWxlaW5wdXQtY2FwdGlvbid9KTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLm1haW5UZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6IHNlbGYubWFpbkNsYXNzICsgKCFzZWxmLnNob3dCcm93c2UgJiYgc2VsZi5zaG93Q2FwdGlvbiA/ICcgbm8tYnJvd3NlJyA6ICcnKSxcbiAgICAgICAgICAgICAgICAncHJldmlldyc6IHByZXZpZXcsXG4gICAgICAgICAgICAgICAgJ2Nsb3NlJzogY2xvc2UsXG4gICAgICAgICAgICAgICAgJ2NhcHRpb24nOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICd1cGxvYWQnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ3VwbG9hZCcpLFxuICAgICAgICAgICAgICAgICdyZW1vdmUnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ3JlbW92ZScpLFxuICAgICAgICAgICAgICAgICdjYW5jZWwnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ2NhbmNlbCcpLFxuICAgICAgICAgICAgICAgICdicm93c2UnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ2Jyb3dzZScpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyQnV0dG9uOiBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0bXBsdCA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdidG5EZWZhdWx0JyksIGNzcyA9IHNlbGZbdHlwZSArICdDbGFzcyddLFxuICAgICAgICAgICAgICAgIHRpdGxlID0gc2VsZlt0eXBlICsgJ1RpdGxlJ10sIGljb24gPSBzZWxmW3R5cGUgKyAnSWNvbiddLCBsYWJlbCA9IHNlbGZbdHlwZSArICdMYWJlbCddLFxuICAgICAgICAgICAgICAgIHN0YXR1cyA9IHNlbGYuaXNEaXNhYmxlZCA/ICcgZGlzYWJsZWQnIDogJycsIGJ0blR5cGUgPSAnYnV0dG9uJztcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JlbW92ZSc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2FuY2VsJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjc3MgKz0gJyBoaWRlJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndXBsb2FkJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dVcGxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUgJiYgIXNlbGYuaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG1wbHQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYnRuTGluaycpLnJlcGxhY2UoJ3tocmVmfScsIHNlbGYudXBsb2FkVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ0blR5cGUgPSAnc3VibWl0JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdicm93c2UnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuc2hvd0Jyb3dzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRtcGx0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2J0bkJyb3dzZScpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNzcyArPSB0eXBlID09PSAnYnJvd3NlJyA/ICcgYnRuLWZpbGUnIDogJyBmaWxlaW5wdXQtJyArIHR5cGUgKyAnIGZpbGVpbnB1dC0nICsgdHlwZSArICctYnV0dG9uJztcbiAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShsYWJlbCkpIHtcbiAgICAgICAgICAgICAgICBsYWJlbCA9ICcgPHNwYW4gY2xhc3M9XCInICsgc2VsZi5idXR0b25MYWJlbENsYXNzICsgJ1wiPicgKyBsYWJlbCArICc8L3NwYW4+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0bXBsdC5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICd0eXBlJzogYnRuVHlwZSwgJ2Nzcyc6IGNzcywgJ3RpdGxlJzogdGl0bGUsICdzdGF0dXMnOiBzdGF0dXMsICdpY29uJzogaWNvbiwgJ2xhYmVsJzogbGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyVGh1bWJQcm9ncmVzczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuICc8ZGl2IGNsYXNzPVwiZmlsZS10aHVtYi1wcm9ncmVzcyBoaWRlXCI+JyArXG4gICAgICAgICAgICAgICAgc2VsZi5wcm9ncmVzc1RlbXBsYXRlLnNldFRva2Vucyh7J3BlcmNlbnQnOiAnMCcsICdzdGF0dXMnOiBzZWxmLm1zZ1VwbG9hZEJlZ2lufSkgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyRmlsZUZvb3RlcjogZnVuY3Rpb24gKGNhcHRpb24sIHNpemUsIHdpZHRoLCBpc0Vycm9yKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNvbmZpZyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLCByZW0gPSBjb25maWcuc2hvd1JlbW92ZSwgZHJnID0gY29uZmlnLnNob3dEcmFnLFxuICAgICAgICAgICAgICAgIHVwbCA9IGNvbmZpZy5zaG93VXBsb2FkLCB6b29tID0gY29uZmlnLnNob3dab29tLCBvdXQsIHRlbXBsYXRlID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Zvb3RlcicpLFxuICAgICAgICAgICAgICAgIGluZCA9IGlzRXJyb3IgPyBjb25maWcuaW5kaWNhdG9yRXJyb3IgOiBjb25maWcuaW5kaWNhdG9yTmV3LFxuICAgICAgICAgICAgICAgIHRJbmQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnaW5kaWNhdG9yJyksXG4gICAgICAgICAgICAgICAgdGl0bGUgPSBpc0Vycm9yID8gY29uZmlnLmluZGljYXRvckVycm9yVGl0bGUgOiBjb25maWcuaW5kaWNhdG9yTmV3VGl0bGUsXG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gdEluZC5zZXRUb2tlbnMoeydpbmRpY2F0b3InOiBpbmQsICdpbmRpY2F0b3JUaXRsZSc6IHRpdGxlfSk7XG4gICAgICAgICAgICBzaXplID0gc2VsZi5fZ2V0U2l6ZShzaXplKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdhY3Rpb25zJzogc2VsZi5fcmVuZGVyRmlsZUFjdGlvbnModXBsLCByZW0sIHpvb20sIGRyZywgZmFsc2UsIGZhbHNlLCBmYWxzZSksXG4gICAgICAgICAgICAgICAgICAgICdjYXB0aW9uJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBzaXplLFxuICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgJ3Byb2dyZXNzJzogc2VsZi5fcmVuZGVyVGh1bWJQcm9ncmVzcygpLFxuICAgICAgICAgICAgICAgICAgICAnaW5kaWNhdG9yJzogaW5kaWNhdG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdhY3Rpb25zJzogc2VsZi5fcmVuZGVyRmlsZUFjdGlvbnMoZmFsc2UsIGZhbHNlLCB6b29tLCBkcmcsIGZhbHNlLCBmYWxzZSwgZmFsc2UpLFxuICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICdzaXplJzogc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICdwcm9ncmVzcyc6ICcnLFxuICAgICAgICAgICAgICAgICAgICAnaW5kaWNhdG9yJzogaW5kaWNhdG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvdXQgPSAkaC5yZXBsYWNlVGFncyhvdXQsIHNlbGYucHJldmlld1RodW1iVGFncyk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyRmlsZUFjdGlvbnM6IGZ1bmN0aW9uIChzaG93VXBsb2FkLCBzaG93RGVsZXRlLCBzaG93Wm9vbSwgc2hvd0RyYWcsIGRpc2FibGVkLCB1cmwsIGtleSwgaXNJbml0KSB7XG4gICAgICAgICAgICBpZiAoIXNob3dVcGxvYWQgJiYgIXNob3dEZWxldGUgJiYgIXNob3dab29tICYmICFzaG93RHJhZykge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdlVybCA9IHVybCA9PT0gZmFsc2UgPyAnJyA6ICcgZGF0YS11cmw9XCInICsgdXJsICsgJ1wiJyxcbiAgICAgICAgICAgICAgICB2S2V5ID0ga2V5ID09PSBmYWxzZSA/ICcnIDogJyBkYXRhLWtleT1cIicgKyBrZXkgKyAnXCInLFxuICAgICAgICAgICAgICAgIGJ0bkRlbGV0ZSA9ICcnLCBidG5VcGxvYWQgPSAnJywgYnRuWm9vbSA9ICcnLCBidG5EcmFnID0gJycsIGNzcyxcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdhY3Rpb25zJyksIGNvbmZpZyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgIG90aGVyQnV0dG9ucyA9IHNlbGYub3RoZXJBY3Rpb25CdXR0b25zLnNldFRva2Vucyh7J2RhdGFLZXknOiB2S2V5fSksXG4gICAgICAgICAgICAgICAgcmVtb3ZlQ2xhc3MgPSBkaXNhYmxlZCA/IGNvbmZpZy5yZW1vdmVDbGFzcyArICcgZGlzYWJsZWQnIDogY29uZmlnLnJlbW92ZUNsYXNzO1xuICAgICAgICAgICAgaWYgKHNob3dEZWxldGUpIHtcbiAgICAgICAgICAgICAgICBidG5EZWxldGUgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYWN0aW9uRGVsZXRlJykuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgJ3JlbW92ZUNsYXNzJzogcmVtb3ZlQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgICdyZW1vdmVJY29uJzogY29uZmlnLnJlbW92ZUljb24sXG4gICAgICAgICAgICAgICAgICAgICdyZW1vdmVUaXRsZSc6IGNvbmZpZy5yZW1vdmVUaXRsZSxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGFVcmwnOiB2VXJsLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YUtleSc6IHZLZXlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzaG93VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgYnRuVXBsb2FkID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvblVwbG9hZCcpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICd1cGxvYWRDbGFzcyc6IGNvbmZpZy51cGxvYWRDbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgJ3VwbG9hZEljb24nOiBjb25maWcudXBsb2FkSWNvbixcbiAgICAgICAgICAgICAgICAgICAgJ3VwbG9hZFRpdGxlJzogY29uZmlnLnVwbG9hZFRpdGxlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hvd1pvb20pIHtcbiAgICAgICAgICAgICAgICBidG5ab29tID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvblpvb20nKS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAnem9vbUNsYXNzJzogY29uZmlnLnpvb21DbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgJ3pvb21JY29uJzogY29uZmlnLnpvb21JY29uLFxuICAgICAgICAgICAgICAgICAgICAnem9vbVRpdGxlJzogY29uZmlnLnpvb21UaXRsZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNob3dEcmFnICYmIGlzSW5pdCkge1xuICAgICAgICAgICAgICAgIGNzcyA9ICdkcmFnLWhhbmRsZS1pbml0ICcgKyBjb25maWcuZHJhZ0NsYXNzO1xuICAgICAgICAgICAgICAgIGJ0bkRyYWcgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYWN0aW9uRHJhZycpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdkcmFnQ2xhc3MnOiBjc3MsXG4gICAgICAgICAgICAgICAgICAgICdkcmFnVGl0bGUnOiBjb25maWcuZHJhZ1RpdGxlLFxuICAgICAgICAgICAgICAgICAgICAnZHJhZ0ljb24nOiBjb25maWcuZHJhZ0ljb25cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICdkZWxldGUnOiBidG5EZWxldGUsXG4gICAgICAgICAgICAgICAgJ3VwbG9hZCc6IGJ0blVwbG9hZCxcbiAgICAgICAgICAgICAgICAnem9vbSc6IGJ0blpvb20sXG4gICAgICAgICAgICAgICAgJ2RyYWcnOiBidG5EcmFnLFxuICAgICAgICAgICAgICAgICdvdGhlcic6IG90aGVyQnV0dG9uc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9icm93c2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJyb3dzZScpO1xuICAgICAgICAgICAgaWYgKGUgJiYgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzRXJyb3IgJiYgIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5jbGVhcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lci5mb2N1cygpO1xuICAgICAgICB9LFxuICAgICAgICBfZmlsdGVyRHVwbGljYXRlOiBmdW5jdGlvbiAoZmlsZSwgZmlsZXMsIGZpbGVJZHMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZmlsZUlkID0gc2VsZi5fZ2V0RmlsZUlkKGZpbGUpO1xuICAgICAgICAgICAgaWYgKGZpbGVJZCAmJiBmaWxlSWRzICYmIGZpbGVJZHMuaW5kZXhPZihmaWxlSWQpID4gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZpbGVJZHMpIHtcbiAgICAgICAgICAgICAgICBmaWxlSWRzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgICAgICAgZmlsZUlkcy5wdXNoKGZpbGVJZCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlICYmICRoLmlzRW1wdHkoJGVsLnZhbCgpKSAmJiBzZWxmLmZpbGVJbnB1dENsZWFyZWQpIHsgLy8gSUUgMTEgZml4XG4gICAgICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgdGZpbGVzID0gW10sIG1zZywgdG90YWwsIGlzRHJhZ0Ryb3AgPSBhcmd1bWVudHMubGVuZ3RoID4gMSwgaXNBamF4VXBsb2FkID0gc2VsZi5pc1VwbG9hZGFibGUsIG4sIGxlbixcbiAgICAgICAgICAgICAgICBmaWxlcyA9IGlzRHJhZ0Ryb3AgPyBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzIDogJGVsLmdldCgwKS5maWxlcywgY3RyID0gc2VsZi5maWxlc3RhY2subGVuZ3RoLFxuICAgICAgICAgICAgICAgIGlzU2luZ2xlVXBsb2FkID0gJGguaXNFbXB0eSgkZWwuYXR0cignbXVsdGlwbGUnKSksIGZsYWdTaW5nbGUgPSAoaXNTaW5nbGVVcGxvYWQgJiYgY3RyID4gMCksXG4gICAgICAgICAgICAgICAgZm9sZGVycyA9IDAsIGZpbGVJZHMgPSBzZWxmLl9nZXRGaWxlSWRzKCksIHRocm93RXJyb3IgPSBmdW5jdGlvbiAobWVzZywgZmlsZSwgcHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcDEgPSAkLmV4dGVuZCh0cnVlLCB7fSwgc2VsZi5fZ2V0T3V0RGF0YSh7fSwge30sIGZpbGVzKSwge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpbmRleH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgcDIgPSB7aWQ6IHByZXZpZXdJZCwgaW5kZXg6IGluZGV4LCBmaWxlOiBmaWxlLCBmaWxlczogZmlsZXN9O1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLl9zaG93VXBsb2FkRXJyb3IobWVzZywgcDEpIDogc2VsZi5fc2hvd0Vycm9yKG1lc2csIHAyKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5yZWFkZXIgPSBudWxsO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIHNlbGYuX2hpZGVGaWxlSWNvbigpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlLWRyb3Atem9uZSAuJyArIHNlbGYuZHJvcFpvbmVUaXRsZUNsYXNzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0RyYWdEcm9wKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoaSwgZikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZiAmJiAhZi50eXBlICYmIGYuc2l6ZSAhPT0gdW5kZWZpbmVkICYmIGYuc2l6ZSAlIDQwOTYgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbGRlcnMrKztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2ZpbHRlckR1cGxpY2F0ZShmLCB0ZmlsZXMsIGZpbGVJZHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChlLnRhcmdldCAmJiBlLnRhcmdldC5maWxlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzID0gZS50YXJnZXQudmFsdWUgPyBbe25hbWU6IGUudGFyZ2V0LnZhbHVlLnJlcGxhY2UoL14uK1xcXFwvLCAnJyl9XSA6IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzID0gZS50YXJnZXQuZmlsZXMgfHwge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpc0FqYXhVcGxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoaSwgZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fZmlsdGVyRHVwbGljYXRlKGYsIHRmaWxlcywgZmlsZUlkcyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRmaWxlcyA9IGZpbGVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KHRmaWxlcykgfHwgdGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNBamF4VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0ZvbGRlckVycm9yKGZvbGRlcnMpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlc2VsZWN0bm9uZScpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKCk7XG4gICAgICAgICAgICBsZW4gPSB0ZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgdG90YWwgPSBzZWxmLl9nZXRGaWxlQ291bnQoc2VsZi5pc1VwbG9hZGFibGUgPyAoc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGggKyBsZW4pIDogbGVuKTtcbiAgICAgICAgICAgIGlmIChzZWxmLm1heEZpbGVDb3VudCA+IDAgJiYgdG90YWwgPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5hdXRvUmVwbGFjZSB8fCBsZW4gPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICBuID0gKHNlbGYuYXV0b1JlcGxhY2UgJiYgbGVuID4gc2VsZi5tYXhGaWxlQ291bnQpID8gbGVuIDogdG90YWw7XG4gICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnRmlsZXNUb29NYW55LnJlcGxhY2UoJ3ttfScsIHNlbGYubWF4RmlsZUNvdW50KS5yZXBsYWNlKCd7bn0nLCBuKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIG51bGwsIG51bGwsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oJycsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3IGZpbGUtaW5wdXQtYWpheC1uZXcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodG90YWwgPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXdUaHVtYnMoaXNBamF4VXBsb2FkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghaXNBamF4VXBsb2FkIHx8IGZsYWdTaW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRQcmV2aWV3VGh1bWJzKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZsYWdTaW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQWpheFVwbG9hZCAmJiBjdHIgPT09IDAgJiYgKCFzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpIHx8IHNlbGYub3ZlcndyaXRlSW5pdGlhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0UHJldmlld1RodW1icyh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzUHJldmlld2FibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZWFkRmlsZXModGZpbGVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zaG93Rm9sZGVyRXJyb3IoZm9sZGVycyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9hYm9ydDogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhO1xuICAgICAgICAgICAgaWYgKHNlbGYuYWpheEFib3J0ZWQgJiYgdHlwZW9mIHNlbGYuYWpheEFib3J0ZWQgPT09IFwib2JqZWN0XCIgJiYgc2VsZi5hamF4QWJvcnRlZC5tZXNzYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gJC5leHRlbmQodHJ1ZSwge30sIHNlbGYuX2dldE91dERhdGEoKSwgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICBkYXRhLmFib3J0RGF0YSA9IHNlbGYuYWpheEFib3J0ZWQuZGF0YSB8fCB7fTtcbiAgICAgICAgICAgICAgICBkYXRhLmFib3J0TWVzc2FnZSA9IHNlbGYuYWpheEFib3J0ZWQubWVzc2FnZTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0NhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKHNlbGYuYWpheEFib3J0ZWQubWVzc2FnZSwgZGF0YSwgJ2ZpbGVjdXN0b21lcnJvcicpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldEZpbGVTdGFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpID0gMCwgbmV3c3RhY2sgPSBbXSwgbmV3bmFtZXMgPSBbXSwgbmV3aWRzID0gW107XG4gICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwgaW5kID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4JyksIGZpbGUgPSBzZWxmLmZpbGVzdGFja1tpbmRdLFxuICAgICAgICAgICAgICAgICAgICBwaWQgPSAkdGh1bWIuYXR0cignaWQnKSwgbmV3SWQ7XG4gICAgICAgICAgICAgICAgaWYgKGluZCA9PT0gJy0xJyB8fCBpbmQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdzdGFja1tpXSA9IGZpbGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld25hbWVzW2ldID0gc2VsZi5fZ2V0RmlsZU5hbWUoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld2lkc1tpXSA9IHNlbGYuX2dldEZpbGVJZChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmF0dHIoeydpZCc6IHNlbGYucHJldmlld0luaXRJZCArICctJyArIGksICdkYXRhLWZpbGVpbmRleCc6IGl9KTtcbiAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0lkID0gJ3VwbG9hZGVkLScgKyAkaC51bmlxSWQoKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmF0dHIoeydpZCc6IG5ld0lkLCAnZGF0YS1maWxlaW5kZXgnOiAnLTEnfSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuZmluZCgnI3pvb20tJyArIHBpZCkuYXR0cignaWQnLCAnem9vbS0nICsgbmV3SWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5maWxlc3RhY2sgPSBuZXdzdGFjaztcbiAgICAgICAgICAgIHNlbGYuZmlsZW5hbWVzID0gbmV3bmFtZXM7XG4gICAgICAgICAgICBzZWxmLmZpbGVpZHMgPSBuZXdpZHM7XG4gICAgICAgIH0sXG4gICAgICAgIF9pc0ZpbGVTZWxlY3Rpb25WYWxpZDogZnVuY3Rpb24gKGNudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgY250ID0gY250IHx8IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi5yZXF1aXJlZCAmJiAhc2VsZi5nZXRGaWxlc0NvdW50KCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRlcnJvckNvbnRhaW5lci5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3Ioc2VsZi5tc2dGaWxlUmVxdWlyZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLm1pbkZpbGVDb3VudCA+IDAgJiYgc2VsZi5fZ2V0RmlsZUNvdW50KGNudCkgPCBzZWxmLm1pbkZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX25vRmlsZXNFcnJvcih7fSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFyU3RhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuZmlsZXN0YWNrID0gW107XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzID0gW107XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgdXBkYXRlU3RhY2s6IGZ1bmN0aW9uIChpLCBmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmZpbGVzdGFja1tpXSA9IGZpbGU7XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lc1tpXSA9IHNlbGYuX2dldEZpbGVOYW1lKGZpbGUpO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzW2ldID0gZmlsZSAmJiBzZWxmLl9nZXRGaWxlSWQoZmlsZSkgfHwgbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBhZGRUb1N0YWNrOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5maWxlc3RhY2sucHVzaChmaWxlKTtcbiAgICAgICAgICAgIHNlbGYuZmlsZW5hbWVzLnB1c2goc2VsZi5fZ2V0RmlsZU5hbWUoZmlsZSkpO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzLnB1c2goc2VsZi5fZ2V0RmlsZUlkKGZpbGUpKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBnZXRGaWxlU3RhY2s6IGZ1bmN0aW9uIChza2lwTnVsbCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuZmlsZXN0YWNrLmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgIHJldHVybiAoc2tpcE51bGwgPyBuICE9PSB1bmRlZmluZWQgOiBuICE9PSB1bmRlZmluZWQgJiYgbiAhPT0gbnVsbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RmlsZXNDb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsZW4gPSBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoIDogc2VsZi4kZWxlbWVudC5nZXQoMCkuZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dldEZpbGVDb3VudChsZW4pO1xuICAgICAgICB9LFxuICAgICAgICBsb2NrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycygpO1xuICAgICAgICAgICAgc2VsZi5kaXNhYmxlKCk7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LXJlbW92ZScpLCAnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd0NhbmNlbCkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LWNhbmNlbCcpLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWxvY2snLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgdW5sb2NrOiBmdW5jdGlvbiAocmVzZXQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmIChyZXNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmVzZXQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5lbmFibGUoKTtcbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtY2FuY2VsJyksICdoaWRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtcmVtb3ZlJykucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXNldCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0RmlsZVN0YWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXVubG9jaycsIFtzZWxmLmZpbGVzdGFjaywgc2VsZi5fZ2V0RXh0cmFEYXRhKCldKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgeGhyID0gc2VsZi5hamF4UmVxdWVzdHMsIGxlbiA9IHhoci5sZW5ndGgsIGk7XG4gICAgICAgICAgICBpZiAobGVuID4gMCkge1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNhbmNlbGxpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB4aHJbaV0uYWJvcnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzc0NhbmNlbGxlZCgpO1xuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksIGluZCA9ICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5maWxlc3RhY2tbaW5kXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi51bmxvY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcDtcbiAgICAgICAgICAgIGlmICghc2VsZi5fcmFpc2UoJ2ZpbGVjbGVhcicpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5maW5kKCd2aWRlbyxhdWRpbyxpbWcnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAkaC5jbGVhbk1lbW9yeSgkKHRoaXMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKHRydWUpO1xuICAgICAgICAgICAgaWYgKHNlbGYuX2hhc0luaXRpYWxQcmV2aWV3KCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93RmlsZUljb24oKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhck9iamVjdHMoJCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICBjYXAgPSAoIXNlbGYub3ZlcndyaXRlSW5pdGlhbCAmJiBzZWxmLmluaXRpYWxDYXB0aW9uLmxlbmd0aCA+IDApID8gc2VsZi5pbml0aWFsQ2FwdGlvbiA6ICcnO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbChjYXApO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uYXR0cigndGl0bGUnLCAnJyk7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVEZWZhdWx0UHJldmlldygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuJGNvbnRhaW5lci5maW5kKCRoLkZSQU1FUykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLl9pbml0Q2FwdGlvbigpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmt2LWNhcHRpb24taWNvbicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9oaWRlRmlsZUljb24oKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlY2xlYXJlZCcpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lci5mb2N1cygpO1xuICAgICAgICAgICAgc2VsZi5fc2V0RmlsZURyb3Bab25lVGl0bGUoKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLl9yYWlzZSgnZmlsZXJlc2V0JykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXcoKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LWZpbGVuYW1lJykudGV4dCgnJyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnZmlsZS1pbnB1dC1uZXcnKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmdldEZyYW1lcygpLmxlbmd0aCB8fCBzZWxmLmlzVXBsb2FkYWJsZSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS1pbnB1dC1uZXcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3NldEZpbGVEcm9wWm9uZVRpdGxlKCk7XG4gICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgIHNlbGYuZm9ybWRhdGEgPSB7fTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmlzRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoXCIua3YtZmlsZWlucHV0LWNhcHRpb25cIikuYWRkQ2xhc3MoXCJmaWxlLWNhcHRpb24tZGlzYWJsZWRcIik7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZChcIi5idG4tZmlsZSwgLmZpbGVpbnB1dC1yZW1vdmUsIC5maWxlaW5wdXQtdXBsb2FkLCAuZmlsZS1wcmV2aWV3LWZyYW1lIGJ1dHRvblwiKVxuICAgICAgICAgICAgICAgIC5hdHRyKFwiZGlzYWJsZWRcIiwgdHJ1ZSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0RHJhZ0Ryb3AoKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBlbmFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuaXNEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVlbmFibGVkJyk7XG4gICAgICAgICAgICBzZWxmLiRlbGVtZW50LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZChcIi5rdi1maWxlaW5wdXQtY2FwdGlvblwiKS5yZW1vdmVDbGFzcyhcImZpbGUtY2FwdGlvbi1kaXNhYmxlZFwiKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKFwiLmJ0bi1maWxlLCAuZmlsZWlucHV0LXJlbW92ZSwgLmZpbGVpbnB1dC11cGxvYWQsIC5maWxlLXByZXZpZXctZnJhbWUgYnV0dG9uXCIpXG4gICAgICAgICAgICAgICAgLnJlbW92ZUF0dHIoXCJkaXNhYmxlZFwiKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXREcmFnRHJvcCgpO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHVwbG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0b3RMZW4gPSBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCwgaSwgb3V0RGF0YSwgbGVuLFxuICAgICAgICAgICAgICAgIGhhc0V4dHJhRGF0YSA9ICEkLmlzRW1wdHlPYmplY3Qoc2VsZi5fZ2V0RXh0cmFEYXRhKCkpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSB8fCBzZWxmLmlzRGlzYWJsZWQgfHwgIXNlbGYuX2lzRmlsZVNlbGVjdGlvblZhbGlkKHRvdExlbikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldFVwbG9hZCgpO1xuICAgICAgICAgICAgaWYgKHRvdExlbiA9PT0gMCAmJiAhaGFzRXh0cmFEYXRhKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKHNlbGYubXNnVXBsb2FkRW1wdHkpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJHByb2dyZXNzLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5sb2NrKCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygyKTtcbiAgICAgICAgICAgIGlmICh0b3RMZW4gPT09IDAgJiYgaGFzRXh0cmFEYXRhKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fdXBsb2FkRXh0cmFPbmx5KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGVuID0gc2VsZi5maWxlc3RhY2subGVuZ3RoO1xuICAgICAgICAgICAgc2VsZi5oYXNJbml0RGF0YSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHNlbGYudXBsb2FkQXN5bmMpIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hwcmV1cGxvYWQnLCBbb3V0RGF0YV0pO1xuICAgICAgICAgICAgICAgIHNlbGYuZmlsZUJhdGNoQ29tcGxldGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZSA9IHtjb250ZW50OiBbXSwgY29uZmlnOiBbXSwgdGFnczogW10sIGFwcGVuZDogdHJ1ZX07XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuY29udGVudFtpXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuY29uZmlnW2ldID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS50YWdzW2ldID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5maW5kKCcuZmlsZS1wcmV2aWV3LWluaXRpYWwnKS5yZW1vdmVDbGFzcygkaC5TT1JUX0NTUyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0gc2VsZi5nZXRQcmV2aWV3KCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2ldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwbG9hZFNpbmdsZShpLCBzZWxmLmZpbGVzdGFjaywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fdXBsb2FkQmF0Y2goKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBkZXN0cm95OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRmb3JtID0gc2VsZi4kZm9ybSwgJGNvbnQgPSBzZWxmLiRjb250YWluZXIsICRlbCA9IHNlbGYuJGVsZW1lbnQsIG5zID0gc2VsZi5uYW1lc3BhY2U7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS5vZmYobnMpO1xuICAgICAgICAgICAgJCh3aW5kb3cpLm9mZihucyk7XG4gICAgICAgICAgICBpZiAoJGZvcm0gJiYgJGZvcm0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGZvcm0ub2ZmKG5zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9jbGVhbnVwKCk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0NhY2hlKCk7XG4gICAgICAgICAgICAkZWwuaW5zZXJ0QmVmb3JlKCRjb250KS5vZmYobnMpLnJlbW92ZURhdGEoKTtcbiAgICAgICAgICAgICRjb250Lm9mZigpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuICRlbDtcbiAgICAgICAgfSxcbiAgICAgICAgcmVmcmVzaDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8gJC5leHRlbmQodHJ1ZSwge30sIHNlbGYub3B0aW9ucywgb3B0aW9ucykgOiBzZWxmLm9wdGlvbnM7XG4gICAgICAgICAgICBzZWxmLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICRlbC5maWxlaW5wdXQob3B0aW9ucyk7XG4gICAgICAgICAgICBzZWxmID0gJGVsLmRhdGEoJ2ZpbGVpbnB1dCcpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkZWwudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAkZWwudHJpZ2dlcignY2hhbmdlLmZpbGVpbnB1dCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRlbDtcbiAgICAgICAgfSxcbiAgICAgICAgem9vbTogZnVuY3Rpb24gKGZyYW1lSWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gc2VsZi5fZ2V0RnJhbWUoZnJhbWVJZCksICRtb2RhbCA9IHNlbGYuJG1vZGFsO1xuICAgICAgICAgICAgaWYgKCEkZnJhbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaC5pbml0TW9kYWwoJG1vZGFsKTtcbiAgICAgICAgICAgICRtb2RhbC5odG1sKHNlbGYuX2dldE1vZGFsQ29udGVudCgpKTtcbiAgICAgICAgICAgIHNlbGYuX3NldFpvb21Db250ZW50KCRmcmFtZSk7XG4gICAgICAgICAgICAkbW9kYWwubW9kYWwoJ3Nob3cnKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9ucygpO1xuICAgICAgICB9LFxuICAgICAgICBnZXRFeGlmOiBmdW5jdGlvbiAoZnJhbWVJZCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUgPSBzZWxmLl9nZXRGcmFtZShmcmFtZUlkKTtcbiAgICAgICAgICAgIHJldHVybiAkZnJhbWUgJiYgJGZyYW1lLmRhdGEoJ2V4aWYnKSB8fCBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBnZXRGcmFtZXM6IGZ1bmN0aW9uIChjc3NGaWx0ZXIpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGNzc0ZpbHRlciA9IGNzc0ZpbHRlciB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRwcmV2aWV3LmZpbmQoJGguRlJBTUVTICsgY3NzRmlsdGVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjb250ZW50OiBzZWxmLmluaXRpYWxQcmV2aWV3LFxuICAgICAgICAgICAgICAgIGNvbmZpZzogc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyxcbiAgICAgICAgICAgICAgICB0YWdzOiBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgICQuZm4uZmlsZWlucHV0ID0gZnVuY3Rpb24gKG9wdGlvbikge1xuICAgICAgICBpZiAoISRoLmhhc0ZpbGVBUElTdXBwb3J0KCkgJiYgISRoLmlzSUUoOSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYXJncyA9IEFycmF5LmFwcGx5KG51bGwsIGFyZ3VtZW50cyksIHJldHZhbHMgPSBbXTtcbiAgICAgICAgYXJncy5zaGlmdCgpO1xuICAgICAgICB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSAkKHRoaXMpLCBkYXRhID0gc2VsZi5kYXRhKCdmaWxlaW5wdXQnKSwgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb24gPT09ICdvYmplY3QnICYmIG9wdGlvbixcbiAgICAgICAgICAgICAgICB0aGVtZSA9IG9wdGlvbnMudGhlbWUgfHwgc2VsZi5kYXRhKCd0aGVtZScpLCBsID0ge30sIHQgPSB7fSxcbiAgICAgICAgICAgICAgICBsYW5nID0gb3B0aW9ucy5sYW5ndWFnZSB8fCBzZWxmLmRhdGEoJ2xhbmd1YWdlJykgfHwgJC5mbi5maWxlaW5wdXQuZGVmYXVsdHMubGFuZ3VhZ2UgfHwgJ2VuJywgb3B0O1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoZW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHQgPSAkLmZuLmZpbGVpbnB1dFRoZW1lc1t0aGVtZV0gfHwge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChsYW5nICE9PSAnZW4nICYmICEkaC5pc0VtcHR5KCQuZm4uZmlsZWlucHV0TG9jYWxlc1tsYW5nXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbCA9ICQuZm4uZmlsZWlucHV0TG9jYWxlc1tsYW5nXSB8fCB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3B0ID0gJC5leHRlbmQodHJ1ZSwge30sICQuZm4uZmlsZWlucHV0LmRlZmF1bHRzLCB0LCAkLmZuLmZpbGVpbnB1dExvY2FsZXMuZW4sIGwsIG9wdGlvbnMsIHNlbGYuZGF0YSgpKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IEZpbGVJbnB1dCh0aGlzLCBvcHQpO1xuICAgICAgICAgICAgICAgIHNlbGYuZGF0YSgnZmlsZWlucHV0JywgZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHJldHZhbHMucHVzaChkYXRhW29wdGlvbl0uYXBwbHkoZGF0YSwgYXJncykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgc3dpdGNoIChyZXR2YWxzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXR2YWxzWzBdO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dmFscztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dC5kZWZhdWx0cyA9IHtcbiAgICAgICAgbGFuZ3VhZ2U6ICdlbicsXG4gICAgICAgIHNob3dDYXB0aW9uOiB0cnVlLFxuICAgICAgICBzaG93QnJvd3NlOiB0cnVlLFxuICAgICAgICBzaG93UHJldmlldzogdHJ1ZSxcbiAgICAgICAgc2hvd1JlbW92ZTogdHJ1ZSxcbiAgICAgICAgc2hvd1VwbG9hZDogdHJ1ZSxcbiAgICAgICAgc2hvd0NhbmNlbDogdHJ1ZSxcbiAgICAgICAgc2hvd0Nsb3NlOiB0cnVlLFxuICAgICAgICBzaG93VXBsb2FkZWRUaHVtYnM6IHRydWUsXG4gICAgICAgIGJyb3dzZU9uWm9uZUNsaWNrOiBmYWxzZSxcbiAgICAgICAgYXV0b1JlcGxhY2U6IGZhbHNlLFxuICAgICAgICBhdXRvT3JpZW50SW1hZ2U6IHRydWUsIC8vIGZvciBKUEVHIGltYWdlcyBiYXNlZCBvbiBFWElGIG9yaWVudGF0aW9uIHRhZ1xuICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgIHJ0bDogZmFsc2UsXG4gICAgICAgIGhpZGVUaHVtYm5haWxDb250ZW50OiBmYWxzZSxcbiAgICAgICAgZ2VuZXJhdGVGaWxlSWQ6IG51bGwsXG4gICAgICAgIHByZXZpZXdDbGFzczogJycsXG4gICAgICAgIGNhcHRpb25DbGFzczogJycsXG4gICAgICAgIGZyYW1lQ2xhc3M6ICdrcmFqZWUtZGVmYXVsdCcsXG4gICAgICAgIG1haW5DbGFzczogJ2ZpbGUtY2FwdGlvbi1tYWluJyxcbiAgICAgICAgbWFpblRlbXBsYXRlOiBudWxsLFxuICAgICAgICBwdXJpZnlIdG1sOiB0cnVlLFxuICAgICAgICBmaWxlU2l6ZUdldHRlcjogbnVsbCxcbiAgICAgICAgaW5pdGlhbENhcHRpb246ICcnLFxuICAgICAgICBpbml0aWFsUHJldmlldzogW10sXG4gICAgICAgIGluaXRpYWxQcmV2aWV3RGVsaW1pdGVyOiAnKiQkKicsXG4gICAgICAgIGluaXRpYWxQcmV2aWV3QXNEYXRhOiBmYWxzZSxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdGaWxlVHlwZTogJ2ltYWdlJyxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdDb25maWc6IFtdLFxuICAgICAgICBpbml0aWFsUHJldmlld1RodW1iVGFnczogW10sXG4gICAgICAgIHByZXZpZXdUaHVtYlRhZ3M6IHt9LFxuICAgICAgICBpbml0aWFsUHJldmlld1Nob3dEZWxldGU6IHRydWUsXG4gICAgICAgIHJlbW92ZUZyb21QcmV2aWV3T25FcnJvcjogZmFsc2UsXG4gICAgICAgIGRlbGV0ZVVybDogJycsXG4gICAgICAgIGRlbGV0ZUV4dHJhRGF0YToge30sXG4gICAgICAgIG92ZXJ3cml0ZUluaXRpYWw6IHRydWUsXG4gICAgICAgIHByZXZpZXdab29tQnV0dG9uSWNvbnM6IHtcbiAgICAgICAgICAgIHByZXY6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJpYW5nbGUtbGVmdFwiPjwvaT4nLFxuICAgICAgICAgICAgbmV4dDogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmlhbmdsZS1yaWdodFwiPjwvaT4nLFxuICAgICAgICAgICAgdG9nZ2xlaGVhZGVyOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXJlc2l6ZS12ZXJ0aWNhbFwiPjwvaT4nLFxuICAgICAgICAgICAgZnVsbHNjcmVlbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1mdWxsc2NyZWVuXCI+PC9pPicsXG4gICAgICAgICAgICBib3JkZXJsZXNzOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXJlc2l6ZS1mdWxsXCI+PC9pPicsXG4gICAgICAgICAgICBjbG9zZTogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1yZW1vdmVcIj48L2k+J1xuICAgICAgICB9LFxuICAgICAgICBwcmV2aWV3Wm9vbUJ1dHRvbkNsYXNzZXM6IHtcbiAgICAgICAgICAgIHByZXY6ICdidG4gYnRuLW5hdmlnYXRlJyxcbiAgICAgICAgICAgIG5leHQ6ICdidG4gYnRuLW5hdmlnYXRlJyxcbiAgICAgICAgICAgIHRvZ2dsZWhlYWRlcjogJ2J0biBidG4tZGVmYXVsdCBidG4taGVhZGVyLXRvZ2dsZScsXG4gICAgICAgICAgICBmdWxsc2NyZWVuOiAnYnRuIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgICAgIGJvcmRlcmxlc3M6ICdidG4gYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgY2xvc2U6ICdidG4gYnRuLWRlZmF1bHQnXG4gICAgICAgIH0sXG4gICAgICAgIHByZWZlckljb25pY1ByZXZpZXc6IGZhbHNlLFxuICAgICAgICBwcmVmZXJJY29uaWNab29tUHJldmlldzogZmFsc2UsXG4gICAgICAgIGFsbG93ZWRQcmV2aWV3VHlwZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgYWxsb3dlZFByZXZpZXdNaW1lVHlwZXM6IG51bGwsXG4gICAgICAgIGFsbG93ZWRGaWxlVHlwZXM6IG51bGwsXG4gICAgICAgIGFsbG93ZWRGaWxlRXh0ZW5zaW9uczogbnVsbCxcbiAgICAgICAgZGVmYXVsdFByZXZpZXdDb250ZW50OiBudWxsLFxuICAgICAgICBjdXN0b21MYXlvdXRUYWdzOiB7fSxcbiAgICAgICAgY3VzdG9tUHJldmlld1RhZ3M6IHt9LFxuICAgICAgICBwcmV2aWV3RmlsZUljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tZmlsZVwiPjwvaT4nLFxuICAgICAgICBwcmV2aWV3RmlsZUljb25DbGFzczogJ2ZpbGUtb3RoZXItaWNvbicsXG4gICAgICAgIHByZXZpZXdGaWxlSWNvblNldHRpbmdzOiB7fSxcbiAgICAgICAgcHJldmlld0ZpbGVFeHRTZXR0aW5nczoge30sXG4gICAgICAgIGJ1dHRvbkxhYmVsQ2xhc3M6ICdoaWRkZW4teHMnLFxuICAgICAgICBicm93c2VJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWZvbGRlci1vcGVuXCI+PC9pPiZuYnNwOycsXG4gICAgICAgIGJyb3dzZUNsYXNzOiAnYnRuIGJ0bi1wcmltYXJ5JyxcbiAgICAgICAgcmVtb3ZlSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmFzaFwiPjwvaT4nLFxuICAgICAgICByZW1vdmVDbGFzczogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgIGNhbmNlbEljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tYmFuLWNpcmNsZVwiPjwvaT4nLFxuICAgICAgICBjYW5jZWxDbGFzczogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgIHVwbG9hZEljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdXBsb2FkXCI+PC9pPicsXG4gICAgICAgIHVwbG9hZENsYXNzOiAnYnRuIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgdXBsb2FkVXJsOiBudWxsLFxuICAgICAgICB1cGxvYWRBc3luYzogdHJ1ZSxcbiAgICAgICAgdXBsb2FkRXh0cmFEYXRhOiB7fSxcbiAgICAgICAgem9vbU1vZGFsSGVpZ2h0OiA0ODAsXG4gICAgICAgIG1pbkltYWdlV2lkdGg6IG51bGwsXG4gICAgICAgIG1pbkltYWdlSGVpZ2h0OiBudWxsLFxuICAgICAgICBtYXhJbWFnZVdpZHRoOiBudWxsLFxuICAgICAgICBtYXhJbWFnZUhlaWdodDogbnVsbCxcbiAgICAgICAgcmVzaXplSW1hZ2U6IGZhbHNlLFxuICAgICAgICByZXNpemVQcmVmZXJlbmNlOiAnd2lkdGgnLFxuICAgICAgICByZXNpemVRdWFsaXR5OiAwLjkyLFxuICAgICAgICByZXNpemVEZWZhdWx0SW1hZ2VUeXBlOiAnaW1hZ2UvanBlZycsXG4gICAgICAgIHJlc2l6ZUlmU2l6ZU1vcmVUaGFuOiAwLCAvLyBpbiBLQlxuICAgICAgICBtaW5GaWxlU2l6ZTogMCxcbiAgICAgICAgbWF4RmlsZVNpemU6IDAsXG4gICAgICAgIG1heEZpbGVQcmV2aWV3U2l6ZTogMjU2MDAsIC8vIDI1IE1CXG4gICAgICAgIG1pbkZpbGVDb3VudDogMCxcbiAgICAgICAgbWF4RmlsZUNvdW50OiAwLFxuICAgICAgICB2YWxpZGF0ZUluaXRpYWxDb3VudDogZmFsc2UsXG4gICAgICAgIG1zZ1ZhbGlkYXRpb25FcnJvckNsYXNzOiAndGV4dC1kYW5nZXInLFxuICAgICAgICBtc2dWYWxpZGF0aW9uRXJyb3JJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWV4Y2xhbWF0aW9uLXNpZ25cIj48L2k+ICcsXG4gICAgICAgIG1zZ0Vycm9yQ2xhc3M6ICdmaWxlLWVycm9yLW1lc3NhZ2UnLFxuICAgICAgICBwcm9ncmVzc1RodW1iQ2xhc3M6IFwicHJvZ3Jlc3MtYmFyIHByb2dyZXNzLWJhci1zdWNjZXNzIHByb2dyZXNzLWJhci1zdHJpcGVkIGFjdGl2ZVwiLFxuICAgICAgICBwcm9ncmVzc0NsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItc3VjY2VzcyBwcm9ncmVzcy1iYXItc3RyaXBlZCBhY3RpdmVcIixcbiAgICAgICAgcHJvZ3Jlc3NDb21wbGV0ZUNsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItc3VjY2Vzc1wiLFxuICAgICAgICBwcm9ncmVzc0Vycm9yQ2xhc3M6IFwicHJvZ3Jlc3MtYmFyIHByb2dyZXNzLWJhci1kYW5nZXJcIixcbiAgICAgICAgcHJvZ3Jlc3NVcGxvYWRUaHJlc2hvbGQ6IDk5LFxuICAgICAgICBwcmV2aWV3RmlsZVR5cGU6ICdpbWFnZScsXG4gICAgICAgIGVsQ2FwdGlvbkNvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgZWxDYXB0aW9uVGV4dDogbnVsbCxcbiAgICAgICAgZWxQcmV2aWV3Q29udGFpbmVyOiBudWxsLFxuICAgICAgICBlbFByZXZpZXdJbWFnZTogbnVsbCxcbiAgICAgICAgZWxQcmV2aWV3U3RhdHVzOiBudWxsLFxuICAgICAgICBlbEVycm9yQ29udGFpbmVyOiBudWxsLFxuICAgICAgICBlcnJvckNsb3NlQnV0dG9uOiAnPHNwYW4gY2xhc3M9XCJjbG9zZSBrdi1lcnJvci1jbG9zZVwiPiZ0aW1lczs8L3NwYW4+JyxcbiAgICAgICAgc2x1Z0NhbGxiYWNrOiBudWxsLFxuICAgICAgICBkcm9wWm9uZUVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGRyb3Bab25lVGl0bGVDbGFzczogJ2ZpbGUtZHJvcC16b25lLXRpdGxlJyxcbiAgICAgICAgZmlsZUFjdGlvblNldHRpbmdzOiB7fSxcbiAgICAgICAgb3RoZXJBY3Rpb25CdXR0b25zOiAnJyxcbiAgICAgICAgdGV4dEVuY29kaW5nOiAnVVRGLTgnLFxuICAgICAgICBhamF4U2V0dGluZ3M6IHt9LFxuICAgICAgICBhamF4RGVsZXRlU2V0dGluZ3M6IHt9LFxuICAgICAgICBzaG93QWpheEVycm9yRGV0YWlsczogdHJ1ZVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dExvY2FsZXMuZW4gPSB7XG4gICAgICAgIGZpbGVTaW5nbGU6ICdmaWxlJyxcbiAgICAgICAgZmlsZVBsdXJhbDogJ2ZpbGVzJyxcbiAgICAgICAgYnJvd3NlTGFiZWw6ICdCcm93c2UgJmhlbGxpcDsnLFxuICAgICAgICByZW1vdmVMYWJlbDogJ1JlbW92ZScsXG4gICAgICAgIHJlbW92ZVRpdGxlOiAnQ2xlYXIgc2VsZWN0ZWQgZmlsZXMnLFxuICAgICAgICBjYW5jZWxMYWJlbDogJ0NhbmNlbCcsXG4gICAgICAgIGNhbmNlbFRpdGxlOiAnQWJvcnQgb25nb2luZyB1cGxvYWQnLFxuICAgICAgICB1cGxvYWRMYWJlbDogJ1VwbG9hZCcsXG4gICAgICAgIHVwbG9hZFRpdGxlOiAnVXBsb2FkIHNlbGVjdGVkIGZpbGVzJyxcbiAgICAgICAgbXNnTm86ICdObycsXG4gICAgICAgIG1zZ05vRmlsZXNTZWxlY3RlZDogJ05vIGZpbGVzIHNlbGVjdGVkJyxcbiAgICAgICAgbXNnQ2FuY2VsbGVkOiAnQ2FuY2VsbGVkJyxcbiAgICAgICAgbXNnWm9vbU1vZGFsSGVhZGluZzogJ0RldGFpbGVkIFByZXZpZXcnLFxuICAgICAgICBtc2dGaWxlUmVxdWlyZWQ6ICdZb3UgbXVzdCBzZWxlY3QgYSBmaWxlIHRvIHVwbG9hZC4nLFxuICAgICAgICBtc2dTaXplVG9vU21hbGw6ICdGaWxlIFwie25hbWV9XCIgKDxiPntzaXplfSBLQjwvYj4pIGlzIHRvbyBzbWFsbCBhbmQgbXVzdCBiZSBsYXJnZXIgdGhhbiA8Yj57bWluU2l6ZX0gS0I8L2I+LicsXG4gICAgICAgIG1zZ1NpemVUb29MYXJnZTogJ0ZpbGUgXCJ7bmFtZX1cIiAoPGI+e3NpemV9IEtCPC9iPikgZXhjZWVkcyBtYXhpbXVtIGFsbG93ZWQgdXBsb2FkIHNpemUgb2YgPGI+e21heFNpemV9IEtCPC9iPi4nLFxuICAgICAgICBtc2dGaWxlc1Rvb0xlc3M6ICdZb3UgbXVzdCBzZWxlY3QgYXQgbGVhc3QgPGI+e259PC9iPiB7ZmlsZXN9IHRvIHVwbG9hZC4nLFxuICAgICAgICBtc2dGaWxlc1Rvb01hbnk6ICdOdW1iZXIgb2YgZmlsZXMgc2VsZWN0ZWQgZm9yIHVwbG9hZCA8Yj4oe259KTwvYj4gZXhjZWVkcyBtYXhpbXVtIGFsbG93ZWQgbGltaXQgb2YgPGI+e219PC9iPi4nLFxuICAgICAgICBtc2dGaWxlTm90Rm91bmQ6ICdGaWxlIFwie25hbWV9XCIgbm90IGZvdW5kIScsXG4gICAgICAgIG1zZ0ZpbGVTZWN1cmVkOiAnU2VjdXJpdHkgcmVzdHJpY3Rpb25zIHByZXZlbnQgcmVhZGluZyB0aGUgZmlsZSBcIntuYW1lfVwiLicsXG4gICAgICAgIG1zZ0ZpbGVOb3RSZWFkYWJsZTogJ0ZpbGUgXCJ7bmFtZX1cIiBpcyBub3QgcmVhZGFibGUuJyxcbiAgICAgICAgbXNnRmlsZVByZXZpZXdBYm9ydGVkOiAnRmlsZSBwcmV2aWV3IGFib3J0ZWQgZm9yIFwie25hbWV9XCIuJyxcbiAgICAgICAgbXNnRmlsZVByZXZpZXdFcnJvcjogJ0FuIGVycm9yIG9jY3VycmVkIHdoaWxlIHJlYWRpbmcgdGhlIGZpbGUgXCJ7bmFtZX1cIi4nLFxuICAgICAgICBtc2dJbnZhbGlkRmlsZU5hbWU6ICdJbnZhbGlkIG9yIHVuc3VwcG9ydGVkIGNoYXJhY3RlcnMgaW4gZmlsZSBuYW1lIFwie25hbWV9XCIuJyxcbiAgICAgICAgbXNnSW52YWxpZEZpbGVUeXBlOiAnSW52YWxpZCB0eXBlIGZvciBmaWxlIFwie25hbWV9XCIuIE9ubHkgXCJ7dHlwZXN9XCIgZmlsZXMgYXJlIHN1cHBvcnRlZC4nLFxuICAgICAgICBtc2dJbnZhbGlkRmlsZUV4dGVuc2lvbjogJ0ludmFsaWQgZXh0ZW5zaW9uIGZvciBmaWxlIFwie25hbWV9XCIuIE9ubHkgXCJ7ZXh0ZW5zaW9uc31cIiBmaWxlcyBhcmUgc3VwcG9ydGVkLicsXG4gICAgICAgIG1zZ0ZpbGVUeXBlczoge1xuICAgICAgICAgICAgJ2ltYWdlJzogJ2ltYWdlJyxcbiAgICAgICAgICAgICdodG1sJzogJ0hUTUwnLFxuICAgICAgICAgICAgJ3RleHQnOiAndGV4dCcsXG4gICAgICAgICAgICAndmlkZW8nOiAndmlkZW8nLFxuICAgICAgICAgICAgJ2F1ZGlvJzogJ2F1ZGlvJyxcbiAgICAgICAgICAgICdmbGFzaCc6ICdmbGFzaCcsXG4gICAgICAgICAgICAncGRmJzogJ1BERicsXG4gICAgICAgICAgICAnb2JqZWN0JzogJ29iamVjdCdcbiAgICAgICAgfSxcbiAgICAgICAgbXNnVXBsb2FkQWJvcnRlZDogJ1RoZSBmaWxlIHVwbG9hZCB3YXMgYWJvcnRlZCcsXG4gICAgICAgIG1zZ1VwbG9hZFRocmVzaG9sZDogJ1Byb2Nlc3NpbmcuLi4nLFxuICAgICAgICBtc2dVcGxvYWRCZWdpbjogJ0luaXRpYWxpemluZy4uLicsXG4gICAgICAgIG1zZ1VwbG9hZEVuZDogJ0RvbmUnLFxuICAgICAgICBtc2dVcGxvYWRFbXB0eTogJ05vIHZhbGlkIGRhdGEgYXZhaWxhYmxlIGZvciB1cGxvYWQuJyxcbiAgICAgICAgbXNnVmFsaWRhdGlvbkVycm9yOiAnVmFsaWRhdGlvbiBFcnJvcicsXG4gICAgICAgIG1zZ0xvYWRpbmc6ICdMb2FkaW5nIGZpbGUge2luZGV4fSBvZiB7ZmlsZXN9ICZoZWxsaXA7JyxcbiAgICAgICAgbXNnUHJvZ3Jlc3M6ICdMb2FkaW5nIGZpbGUge2luZGV4fSBvZiB7ZmlsZXN9IC0ge25hbWV9IC0ge3BlcmNlbnR9JSBjb21wbGV0ZWQuJyxcbiAgICAgICAgbXNnU2VsZWN0ZWQ6ICd7bn0ge2ZpbGVzfSBzZWxlY3RlZCcsXG4gICAgICAgIG1zZ0ZvbGRlcnNOb3RBbGxvd2VkOiAnRHJhZyAmIGRyb3AgZmlsZXMgb25seSEge259IGZvbGRlcihzKSBkcm9wcGVkIHdlcmUgc2tpcHBlZC4nLFxuICAgICAgICBtc2dJbWFnZVdpZHRoU21hbGw6ICdXaWR0aCBvZiBpbWFnZSBmaWxlIFwie25hbWV9XCIgbXVzdCBiZSBhdCBsZWFzdCB7c2l6ZX0gcHguJyxcbiAgICAgICAgbXNnSW1hZ2VIZWlnaHRTbWFsbDogJ0hlaWdodCBvZiBpbWFnZSBmaWxlIFwie25hbWV9XCIgbXVzdCBiZSBhdCBsZWFzdCB7c2l6ZX0gcHguJyxcbiAgICAgICAgbXNnSW1hZ2VXaWR0aExhcmdlOiAnV2lkdGggb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIGNhbm5vdCBleGNlZWQge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlSGVpZ2h0TGFyZ2U6ICdIZWlnaHQgb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIGNhbm5vdCBleGNlZWQge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlUmVzaXplRXJyb3I6ICdDb3VsZCBub3QgZ2V0IHRoZSBpbWFnZSBkaW1lbnNpb25zIHRvIHJlc2l6ZS4nLFxuICAgICAgICBtc2dJbWFnZVJlc2l6ZUV4Y2VwdGlvbjogJ0Vycm9yIHdoaWxlIHJlc2l6aW5nIHRoZSBpbWFnZS48cHJlPntlcnJvcnN9PC9wcmU+JyxcbiAgICAgICAgbXNnQWpheEVycm9yOiAnU29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCB0aGUge29wZXJhdGlvbn0gb3BlcmF0aW9uLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyIScsXG4gICAgICAgIG1zZ0FqYXhQcm9ncmVzc0Vycm9yOiAne29wZXJhdGlvbn0gZmFpbGVkJyxcbiAgICAgICAgYWpheE9wZXJhdGlvbnM6IHtcbiAgICAgICAgICAgIGRlbGV0ZVRodW1iOiAnZmlsZSBkZWxldGUnLFxuICAgICAgICAgICAgdXBsb2FkVGh1bWI6ICdmaWxlIHVwbG9hZCcsXG4gICAgICAgICAgICB1cGxvYWRCYXRjaDogJ2JhdGNoIGZpbGUgdXBsb2FkJyxcbiAgICAgICAgICAgIHVwbG9hZEV4dHJhOiAnZm9ybSBkYXRhIHVwbG9hZCdcbiAgICAgICAgfSxcbiAgICAgICAgZHJvcFpvbmVUaXRsZTogJ0RyYWcgJiBkcm9wIGZpbGVzIGhlcmUgJmhlbGxpcDsnLFxuICAgICAgICBkcm9wWm9uZUNsaWNrVGl0bGU6ICc8YnI+KG9yIGNsaWNrIHRvIHNlbGVjdCB7ZmlsZXN9KScsXG4gICAgICAgIHByZXZpZXdab29tQnV0dG9uVGl0bGVzOiB7XG4gICAgICAgICAgICBwcmV2OiAnVmlldyBwcmV2aW91cyBmaWxlJyxcbiAgICAgICAgICAgIG5leHQ6ICdWaWV3IG5leHQgZmlsZScsXG4gICAgICAgICAgICB0b2dnbGVoZWFkZXI6ICdUb2dnbGUgaGVhZGVyJyxcbiAgICAgICAgICAgIGZ1bGxzY3JlZW46ICdUb2dnbGUgZnVsbCBzY3JlZW4nLFxuICAgICAgICAgICAgYm9yZGVybGVzczogJ1RvZ2dsZSBib3JkZXJsZXNzIG1vZGUnLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSBkZXRhaWxlZCBwcmV2aWV3J1xuICAgICAgICB9XG4gICAgfTtcblxuICAgICQuZm4uZmlsZWlucHV0LkNvbnN0cnVjdG9yID0gRmlsZUlucHV0O1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydCBhdXRvbWF0aWNhbGx5IGZpbGUgaW5wdXRzIHdpdGggY2xhc3MgJ2ZpbGUnIGludG8gYSBib290c3RyYXAgZmlsZWlucHV0IGNvbnRyb2wuXG4gICAgICovXG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGlucHV0ID0gJCgnaW5wdXQuZmlsZVt0eXBlPWZpbGVdJyk7XG4gICAgICAgIGlmICgkaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAkaW5wdXQuZmlsZWlucHV0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn0pKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2pzL2ZpbGVpbnB1dC5qc1xuLy8gbW9kdWxlIGlkID0gN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2Nzcy9ib290c3RyYXAuY3NzXG4vLyBtb2R1bGUgaWQgPSA4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzc1xuLy8gbW9kdWxlIGlkID0gOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3Ncbi8vIG1vZHVsZSBpZCA9IDEwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvQGZvcnRhd2Vzb21lL2ZvbnRhd2Vzb21lLWZyZWUvY3NzL2FsbC5jc3Ncbi8vIG1vZHVsZSBpZCA9IDExXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvc3R5bGUuY3NzXG4vLyBtb2R1bGUgaWQgPSAxMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwic291cmNlUm9vdCI6IiJ9