main.bundle.js 1.6 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216
  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__(15);
  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__(16);
  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__(17);
  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__(18);
  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__(19);
  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__(20);
  8411. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css__);
  8412. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css__ = __webpack_require__(21);
  8413. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8__style_css__);
  8414. // Javascript
  8415. // CSS
  8416. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(function () {
  8417. __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#myInput").on("keyup", function(eventObject) {
  8418. var input, filter, ul, li, a, i;
  8419. input = eventObject.currentTarget;
  8420. filter = input.value.toUpperCase();
  8421. ul = document.getElementById("myUL");
  8422. li = ul.getElementsByTagName('a');
  8423. // Loop through all list items, and hide those who don't match the search query
  8424. for (i = 0; i < li.length; i++) {
  8425. a = li[i]; //li[i].getElementsByTagName("a")[0];
  8426. if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
  8427. li[i].style.display = "";
  8428. } else {
  8429. li[i].style.display = "none";
  8430. }
  8431. }
  8432. });
  8433. function checkUsernameInputHandler(eventObject) {
  8434. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8435. var data = JSON.stringify({"username": input_el.val()});
  8436. var url = `/teachers/check_username/${input_el.val()}`
  8437. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8438. url,
  8439. data,
  8440. function(result) {
  8441. if (result.exists) {
  8442. console.log("Username exists");
  8443. }
  8444. },
  8445. "json"
  8446. );
  8447. }
  8448. function usernameGenerator(eventObject, firstname, surname) {
  8449. var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
  8450. input_el.val(firstname+"."+surname);
  8451. }
  8452. function deleteRelationHandler(eventObject) {
  8453. var url = this.dataset.url;
  8454. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8455. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8456. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8457. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8458. url: url,
  8459. type: 'DELETE',
  8460. success: function(result) {
  8461. el.closest(".list-group-item").remove();
  8462. modalEl.modal('hide');
  8463. }
  8464. });
  8465. });
  8466. return false;
  8467. };
  8468. function deleteHandler(eventObject) {
  8469. var url = this.dataset.url;
  8470. var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
  8471. var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
  8472. modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
  8473. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
  8474. url: url,
  8475. type: 'DELETE',
  8476. success: function(result) {
  8477. modalEl.modal('hide');
  8478. window.location.replace(result.redirect_url);
  8479. }
  8480. });
  8481. });
  8482. return false;
  8483. };
  8484. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".ajax-post").on("click", function(eventObject) {
  8485. var select_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.select).first();
  8486. var listgroup_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.listgroup).first();
  8487. var url = this.dataset.url;
  8488. var data = JSON.stringify({"ids": select_el.val()});
  8489. __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
  8490. url,
  8491. data,
  8492. function(result) {
  8493. var i;
  8494. if (result.elements != null) {
  8495. for (i = 0; i < result.elements.length; i++) {
  8496. var newItem = `
  8497. <a href="#" class="list-group-item clearfix">
  8498. <span class="glyphicon glyphicon-book"></span>
  8499. ${result.elements[i].Name}
  8500. <span class="pull-right">
  8501. <button data-url="/${result.name1}/${result.id1}/${result.name2}/${result.id2[i]}/delete" class="btn btn-xs btn-warning karmen-ajax-delete">
  8502. <span class="glyphicon glyphicon-trash"></span>
  8503. </button>
  8504. </span>
  8505. `;
  8506. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(listgroup_el).append(newItem);
  8507. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8508. }
  8509. }
  8510. },
  8511. "json"
  8512. );
  8513. select_el.val('default');
  8514. select_el.selectpicker("refresh");
  8515. return false;
  8516. });
  8517. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete-relation").on("click", deleteRelationHandler);
  8518. __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
  8519. });
  8520. /***/ }),
  8521. /* 2 */
  8522. /***/ (function(module, exports, __webpack_require__) {
  8523. // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
  8524. __webpack_require__(3)
  8525. __webpack_require__(4)
  8526. __webpack_require__(5)
  8527. __webpack_require__(6)
  8528. __webpack_require__(7)
  8529. __webpack_require__(8)
  8530. __webpack_require__(9)
  8531. __webpack_require__(10)
  8532. __webpack_require__(11)
  8533. __webpack_require__(12)
  8534. __webpack_require__(13)
  8535. __webpack_require__(14)
  8536. /***/ }),
  8537. /* 3 */
  8538. /***/ (function(module, exports, __webpack_require__) {
  8539. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  8540. * Bootstrap: transition.js v3.3.7
  8541. * http://getbootstrap.com/javascript/#transitions
  8542. * ========================================================================
  8543. * Copyright 2011-2016 Twitter, Inc.
  8544. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8545. * ======================================================================== */
  8546. +function ($) {
  8547. 'use strict';
  8548. // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  8549. // ============================================================
  8550. function transitionEnd() {
  8551. var el = document.createElement('bootstrap')
  8552. var transEndEventNames = {
  8553. WebkitTransition : 'webkitTransitionEnd',
  8554. MozTransition : 'transitionend',
  8555. OTransition : 'oTransitionEnd otransitionend',
  8556. transition : 'transitionend'
  8557. }
  8558. for (var name in transEndEventNames) {
  8559. if (el.style[name] !== undefined) {
  8560. return { end: transEndEventNames[name] }
  8561. }
  8562. }
  8563. return false // explicit for ie8 ( ._.)
  8564. }
  8565. // http://blog.alexmaccaw.com/css-transitions
  8566. $.fn.emulateTransitionEnd = function (duration) {
  8567. var called = false
  8568. var $el = this
  8569. $(this).one('bsTransitionEnd', function () { called = true })
  8570. var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
  8571. setTimeout(callback, duration)
  8572. return this
  8573. }
  8574. $(function () {
  8575. $.support.transition = transitionEnd()
  8576. if (!$.support.transition) return
  8577. $.event.special.bsTransitionEnd = {
  8578. bindType: $.support.transition.end,
  8579. delegateType: $.support.transition.end,
  8580. handle: function (e) {
  8581. if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
  8582. }
  8583. }
  8584. })
  8585. }(jQuery);
  8586. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  8587. /***/ }),
  8588. /* 4 */
  8589. /***/ (function(module, exports, __webpack_require__) {
  8590. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  8591. * Bootstrap: alert.js v3.3.7
  8592. * http://getbootstrap.com/javascript/#alerts
  8593. * ========================================================================
  8594. * Copyright 2011-2016 Twitter, Inc.
  8595. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8596. * ======================================================================== */
  8597. +function ($) {
  8598. 'use strict';
  8599. // ALERT CLASS DEFINITION
  8600. // ======================
  8601. var dismiss = '[data-dismiss="alert"]'
  8602. var Alert = function (el) {
  8603. $(el).on('click', dismiss, this.close)
  8604. }
  8605. Alert.VERSION = '3.3.7'
  8606. Alert.TRANSITION_DURATION = 150
  8607. Alert.prototype.close = function (e) {
  8608. var $this = $(this)
  8609. var selector = $this.attr('data-target')
  8610. if (!selector) {
  8611. selector = $this.attr('href')
  8612. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  8613. }
  8614. var $parent = $(selector === '#' ? [] : selector)
  8615. if (e) e.preventDefault()
  8616. if (!$parent.length) {
  8617. $parent = $this.closest('.alert')
  8618. }
  8619. $parent.trigger(e = $.Event('close.bs.alert'))
  8620. if (e.isDefaultPrevented()) return
  8621. $parent.removeClass('in')
  8622. function removeElement() {
  8623. // detach from parent, fire event then clean up data
  8624. $parent.detach().trigger('closed.bs.alert').remove()
  8625. }
  8626. $.support.transition && $parent.hasClass('fade') ?
  8627. $parent
  8628. .one('bsTransitionEnd', removeElement)
  8629. .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
  8630. removeElement()
  8631. }
  8632. // ALERT PLUGIN DEFINITION
  8633. // =======================
  8634. function Plugin(option) {
  8635. return this.each(function () {
  8636. var $this = $(this)
  8637. var data = $this.data('bs.alert')
  8638. if (!data) $this.data('bs.alert', (data = new Alert(this)))
  8639. if (typeof option == 'string') data[option].call($this)
  8640. })
  8641. }
  8642. var old = $.fn.alert
  8643. $.fn.alert = Plugin
  8644. $.fn.alert.Constructor = Alert
  8645. // ALERT NO CONFLICT
  8646. // =================
  8647. $.fn.alert.noConflict = function () {
  8648. $.fn.alert = old
  8649. return this
  8650. }
  8651. // ALERT DATA-API
  8652. // ==============
  8653. $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
  8654. }(jQuery);
  8655. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  8656. /***/ }),
  8657. /* 5 */
  8658. /***/ (function(module, exports, __webpack_require__) {
  8659. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  8660. * Bootstrap: button.js v3.3.7
  8661. * http://getbootstrap.com/javascript/#buttons
  8662. * ========================================================================
  8663. * Copyright 2011-2016 Twitter, Inc.
  8664. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8665. * ======================================================================== */
  8666. +function ($) {
  8667. 'use strict';
  8668. // BUTTON PUBLIC CLASS DEFINITION
  8669. // ==============================
  8670. var Button = function (element, options) {
  8671. this.$element = $(element)
  8672. this.options = $.extend({}, Button.DEFAULTS, options)
  8673. this.isLoading = false
  8674. }
  8675. Button.VERSION = '3.3.7'
  8676. Button.DEFAULTS = {
  8677. loadingText: 'loading...'
  8678. }
  8679. Button.prototype.setState = function (state) {
  8680. var d = 'disabled'
  8681. var $el = this.$element
  8682. var val = $el.is('input') ? 'val' : 'html'
  8683. var data = $el.data()
  8684. state += 'Text'
  8685. if (data.resetText == null) $el.data('resetText', $el[val]())
  8686. // push to event loop to allow forms to submit
  8687. setTimeout($.proxy(function () {
  8688. $el[val](data[state] == null ? this.options[state] : data[state])
  8689. if (state == 'loadingText') {
  8690. this.isLoading = true
  8691. $el.addClass(d).attr(d, d).prop(d, true)
  8692. } else if (this.isLoading) {
  8693. this.isLoading = false
  8694. $el.removeClass(d).removeAttr(d).prop(d, false)
  8695. }
  8696. }, this), 0)
  8697. }
  8698. Button.prototype.toggle = function () {
  8699. var changed = true
  8700. var $parent = this.$element.closest('[data-toggle="buttons"]')
  8701. if ($parent.length) {
  8702. var $input = this.$element.find('input')
  8703. if ($input.prop('type') == 'radio') {
  8704. if ($input.prop('checked')) changed = false
  8705. $parent.find('.active').removeClass('active')
  8706. this.$element.addClass('active')
  8707. } else if ($input.prop('type') == 'checkbox') {
  8708. if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
  8709. this.$element.toggleClass('active')
  8710. }
  8711. $input.prop('checked', this.$element.hasClass('active'))
  8712. if (changed) $input.trigger('change')
  8713. } else {
  8714. this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
  8715. this.$element.toggleClass('active')
  8716. }
  8717. }
  8718. // BUTTON PLUGIN DEFINITION
  8719. // ========================
  8720. function Plugin(option) {
  8721. return this.each(function () {
  8722. var $this = $(this)
  8723. var data = $this.data('bs.button')
  8724. var options = typeof option == 'object' && option
  8725. if (!data) $this.data('bs.button', (data = new Button(this, options)))
  8726. if (option == 'toggle') data.toggle()
  8727. else if (option) data.setState(option)
  8728. })
  8729. }
  8730. var old = $.fn.button
  8731. $.fn.button = Plugin
  8732. $.fn.button.Constructor = Button
  8733. // BUTTON NO CONFLICT
  8734. // ==================
  8735. $.fn.button.noConflict = function () {
  8736. $.fn.button = old
  8737. return this
  8738. }
  8739. // BUTTON DATA-API
  8740. // ===============
  8741. $(document)
  8742. .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  8743. var $btn = $(e.target).closest('.btn')
  8744. Plugin.call($btn, 'toggle')
  8745. if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
  8746. // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
  8747. e.preventDefault()
  8748. // The target component still receive the focus
  8749. if ($btn.is('input,button')) $btn.trigger('focus')
  8750. else $btn.find('input:visible,button:visible').first().trigger('focus')
  8751. }
  8752. })
  8753. .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  8754. $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
  8755. })
  8756. }(jQuery);
  8757. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  8758. /***/ }),
  8759. /* 6 */
  8760. /***/ (function(module, exports, __webpack_require__) {
  8761. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  8762. * Bootstrap: carousel.js v3.3.7
  8763. * http://getbootstrap.com/javascript/#carousel
  8764. * ========================================================================
  8765. * Copyright 2011-2016 Twitter, Inc.
  8766. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8767. * ======================================================================== */
  8768. +function ($) {
  8769. 'use strict';
  8770. // CAROUSEL CLASS DEFINITION
  8771. // =========================
  8772. var Carousel = function (element, options) {
  8773. this.$element = $(element)
  8774. this.$indicators = this.$element.find('.carousel-indicators')
  8775. this.options = options
  8776. this.paused = null
  8777. this.sliding = null
  8778. this.interval = null
  8779. this.$active = null
  8780. this.$items = null
  8781. this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
  8782. this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
  8783. .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
  8784. .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
  8785. }
  8786. Carousel.VERSION = '3.3.7'
  8787. Carousel.TRANSITION_DURATION = 600
  8788. Carousel.DEFAULTS = {
  8789. interval: 5000,
  8790. pause: 'hover',
  8791. wrap: true,
  8792. keyboard: true
  8793. }
  8794. Carousel.prototype.keydown = function (e) {
  8795. if (/input|textarea/i.test(e.target.tagName)) return
  8796. switch (e.which) {
  8797. case 37: this.prev(); break
  8798. case 39: this.next(); break
  8799. default: return
  8800. }
  8801. e.preventDefault()
  8802. }
  8803. Carousel.prototype.cycle = function (e) {
  8804. e || (this.paused = false)
  8805. this.interval && clearInterval(this.interval)
  8806. this.options.interval
  8807. && !this.paused
  8808. && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
  8809. return this
  8810. }
  8811. Carousel.prototype.getItemIndex = function (item) {
  8812. this.$items = item.parent().children('.item')
  8813. return this.$items.index(item || this.$active)
  8814. }
  8815. Carousel.prototype.getItemForDirection = function (direction, active) {
  8816. var activeIndex = this.getItemIndex(active)
  8817. var willWrap = (direction == 'prev' && activeIndex === 0)
  8818. || (direction == 'next' && activeIndex == (this.$items.length - 1))
  8819. if (willWrap && !this.options.wrap) return active
  8820. var delta = direction == 'prev' ? -1 : 1
  8821. var itemIndex = (activeIndex + delta) % this.$items.length
  8822. return this.$items.eq(itemIndex)
  8823. }
  8824. Carousel.prototype.to = function (pos) {
  8825. var that = this
  8826. var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
  8827. if (pos > (this.$items.length - 1) || pos < 0) return
  8828. if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
  8829. if (activeIndex == pos) return this.pause().cycle()
  8830. return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
  8831. }
  8832. Carousel.prototype.pause = function (e) {
  8833. e || (this.paused = true)
  8834. if (this.$element.find('.next, .prev').length && $.support.transition) {
  8835. this.$element.trigger($.support.transition.end)
  8836. this.cycle(true)
  8837. }
  8838. this.interval = clearInterval(this.interval)
  8839. return this
  8840. }
  8841. Carousel.prototype.next = function () {
  8842. if (this.sliding) return
  8843. return this.slide('next')
  8844. }
  8845. Carousel.prototype.prev = function () {
  8846. if (this.sliding) return
  8847. return this.slide('prev')
  8848. }
  8849. Carousel.prototype.slide = function (type, next) {
  8850. var $active = this.$element.find('.item.active')
  8851. var $next = next || this.getItemForDirection(type, $active)
  8852. var isCycling = this.interval
  8853. var direction = type == 'next' ? 'left' : 'right'
  8854. var that = this
  8855. if ($next.hasClass('active')) return (this.sliding = false)
  8856. var relatedTarget = $next[0]
  8857. var slideEvent = $.Event('slide.bs.carousel', {
  8858. relatedTarget: relatedTarget,
  8859. direction: direction
  8860. })
  8861. this.$element.trigger(slideEvent)
  8862. if (slideEvent.isDefaultPrevented()) return
  8863. this.sliding = true
  8864. isCycling && this.pause()
  8865. if (this.$indicators.length) {
  8866. this.$indicators.find('.active').removeClass('active')
  8867. var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
  8868. $nextIndicator && $nextIndicator.addClass('active')
  8869. }
  8870. var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
  8871. if ($.support.transition && this.$element.hasClass('slide')) {
  8872. $next.addClass(type)
  8873. $next[0].offsetWidth // force reflow
  8874. $active.addClass(direction)
  8875. $next.addClass(direction)
  8876. $active
  8877. .one('bsTransitionEnd', function () {
  8878. $next.removeClass([type, direction].join(' ')).addClass('active')
  8879. $active.removeClass(['active', direction].join(' '))
  8880. that.sliding = false
  8881. setTimeout(function () {
  8882. that.$element.trigger(slidEvent)
  8883. }, 0)
  8884. })
  8885. .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
  8886. } else {
  8887. $active.removeClass('active')
  8888. $next.addClass('active')
  8889. this.sliding = false
  8890. this.$element.trigger(slidEvent)
  8891. }
  8892. isCycling && this.cycle()
  8893. return this
  8894. }
  8895. // CAROUSEL PLUGIN DEFINITION
  8896. // ==========================
  8897. function Plugin(option) {
  8898. return this.each(function () {
  8899. var $this = $(this)
  8900. var data = $this.data('bs.carousel')
  8901. var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
  8902. var action = typeof option == 'string' ? option : options.slide
  8903. if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
  8904. if (typeof option == 'number') data.to(option)
  8905. else if (action) data[action]()
  8906. else if (options.interval) data.pause().cycle()
  8907. })
  8908. }
  8909. var old = $.fn.carousel
  8910. $.fn.carousel = Plugin
  8911. $.fn.carousel.Constructor = Carousel
  8912. // CAROUSEL NO CONFLICT
  8913. // ====================
  8914. $.fn.carousel.noConflict = function () {
  8915. $.fn.carousel = old
  8916. return this
  8917. }
  8918. // CAROUSEL DATA-API
  8919. // =================
  8920. var clickHandler = function (e) {
  8921. var href
  8922. var $this = $(this)
  8923. var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
  8924. if (!$target.hasClass('carousel')) return
  8925. var options = $.extend({}, $target.data(), $this.data())
  8926. var slideIndex = $this.attr('data-slide-to')
  8927. if (slideIndex) options.interval = false
  8928. Plugin.call($target, options)
  8929. if (slideIndex) {
  8930. $target.data('bs.carousel').to(slideIndex)
  8931. }
  8932. e.preventDefault()
  8933. }
  8934. $(document)
  8935. .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
  8936. .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
  8937. $(window).on('load', function () {
  8938. $('[data-ride="carousel"]').each(function () {
  8939. var $carousel = $(this)
  8940. Plugin.call($carousel, $carousel.data())
  8941. })
  8942. })
  8943. }(jQuery);
  8944. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  8945. /***/ }),
  8946. /* 7 */
  8947. /***/ (function(module, exports, __webpack_require__) {
  8948. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  8949. * Bootstrap: collapse.js v3.3.7
  8950. * http://getbootstrap.com/javascript/#collapse
  8951. * ========================================================================
  8952. * Copyright 2011-2016 Twitter, Inc.
  8953. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8954. * ======================================================================== */
  8955. /* jshint latedef: false */
  8956. +function ($) {
  8957. 'use strict';
  8958. // COLLAPSE PUBLIC CLASS DEFINITION
  8959. // ================================
  8960. var Collapse = function (element, options) {
  8961. this.$element = $(element)
  8962. this.options = $.extend({}, Collapse.DEFAULTS, options)
  8963. this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
  8964. '[data-toggle="collapse"][data-target="#' + element.id + '"]')
  8965. this.transitioning = null
  8966. if (this.options.parent) {
  8967. this.$parent = this.getParent()
  8968. } else {
  8969. this.addAriaAndCollapsedClass(this.$element, this.$trigger)
  8970. }
  8971. if (this.options.toggle) this.toggle()
  8972. }
  8973. Collapse.VERSION = '3.3.7'
  8974. Collapse.TRANSITION_DURATION = 350
  8975. Collapse.DEFAULTS = {
  8976. toggle: true
  8977. }
  8978. Collapse.prototype.dimension = function () {
  8979. var hasWidth = this.$element.hasClass('width')
  8980. return hasWidth ? 'width' : 'height'
  8981. }
  8982. Collapse.prototype.show = function () {
  8983. if (this.transitioning || this.$element.hasClass('in')) return
  8984. var activesData
  8985. var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
  8986. if (actives && actives.length) {
  8987. activesData = actives.data('bs.collapse')
  8988. if (activesData && activesData.transitioning) return
  8989. }
  8990. var startEvent = $.Event('show.bs.collapse')
  8991. this.$element.trigger(startEvent)
  8992. if (startEvent.isDefaultPrevented()) return
  8993. if (actives && actives.length) {
  8994. Plugin.call(actives, 'hide')
  8995. activesData || actives.data('bs.collapse', null)
  8996. }
  8997. var dimension = this.dimension()
  8998. this.$element
  8999. .removeClass('collapse')
  9000. .addClass('collapsing')[dimension](0)
  9001. .attr('aria-expanded', true)
  9002. this.$trigger
  9003. .removeClass('collapsed')
  9004. .attr('aria-expanded', true)
  9005. this.transitioning = 1
  9006. var complete = function () {
  9007. this.$element
  9008. .removeClass('collapsing')
  9009. .addClass('collapse in')[dimension]('')
  9010. this.transitioning = 0
  9011. this.$element
  9012. .trigger('shown.bs.collapse')
  9013. }
  9014. if (!$.support.transition) return complete.call(this)
  9015. var scrollSize = $.camelCase(['scroll', dimension].join('-'))
  9016. this.$element
  9017. .one('bsTransitionEnd', $.proxy(complete, this))
  9018. .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
  9019. }
  9020. Collapse.prototype.hide = function () {
  9021. if (this.transitioning || !this.$element.hasClass('in')) return
  9022. var startEvent = $.Event('hide.bs.collapse')
  9023. this.$element.trigger(startEvent)
  9024. if (startEvent.isDefaultPrevented()) return
  9025. var dimension = this.dimension()
  9026. this.$element[dimension](this.$element[dimension]())[0].offsetHeight
  9027. this.$element
  9028. .addClass('collapsing')
  9029. .removeClass('collapse in')
  9030. .attr('aria-expanded', false)
  9031. this.$trigger
  9032. .addClass('collapsed')
  9033. .attr('aria-expanded', false)
  9034. this.transitioning = 1
  9035. var complete = function () {
  9036. this.transitioning = 0
  9037. this.$element
  9038. .removeClass('collapsing')
  9039. .addClass('collapse')
  9040. .trigger('hidden.bs.collapse')
  9041. }
  9042. if (!$.support.transition) return complete.call(this)
  9043. this.$element
  9044. [dimension](0)
  9045. .one('bsTransitionEnd', $.proxy(complete, this))
  9046. .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
  9047. }
  9048. Collapse.prototype.toggle = function () {
  9049. this[this.$element.hasClass('in') ? 'hide' : 'show']()
  9050. }
  9051. Collapse.prototype.getParent = function () {
  9052. return $(this.options.parent)
  9053. .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
  9054. .each($.proxy(function (i, element) {
  9055. var $element = $(element)
  9056. this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
  9057. }, this))
  9058. .end()
  9059. }
  9060. Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
  9061. var isOpen = $element.hasClass('in')
  9062. $element.attr('aria-expanded', isOpen)
  9063. $trigger
  9064. .toggleClass('collapsed', !isOpen)
  9065. .attr('aria-expanded', isOpen)
  9066. }
  9067. function getTargetFromTrigger($trigger) {
  9068. var href
  9069. var target = $trigger.attr('data-target')
  9070. || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
  9071. return $(target)
  9072. }
  9073. // COLLAPSE PLUGIN DEFINITION
  9074. // ==========================
  9075. function Plugin(option) {
  9076. return this.each(function () {
  9077. var $this = $(this)
  9078. var data = $this.data('bs.collapse')
  9079. var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
  9080. if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
  9081. if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
  9082. if (typeof option == 'string') data[option]()
  9083. })
  9084. }
  9085. var old = $.fn.collapse
  9086. $.fn.collapse = Plugin
  9087. $.fn.collapse.Constructor = Collapse
  9088. // COLLAPSE NO CONFLICT
  9089. // ====================
  9090. $.fn.collapse.noConflict = function () {
  9091. $.fn.collapse = old
  9092. return this
  9093. }
  9094. // COLLAPSE DATA-API
  9095. // =================
  9096. $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
  9097. var $this = $(this)
  9098. if (!$this.attr('data-target')) e.preventDefault()
  9099. var $target = getTargetFromTrigger($this)
  9100. var data = $target.data('bs.collapse')
  9101. var option = data ? 'toggle' : $this.data()
  9102. Plugin.call($target, option)
  9103. })
  9104. }(jQuery);
  9105. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  9106. /***/ }),
  9107. /* 8 */
  9108. /***/ (function(module, exports, __webpack_require__) {
  9109. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  9110. * Bootstrap: dropdown.js v3.3.7
  9111. * http://getbootstrap.com/javascript/#dropdowns
  9112. * ========================================================================
  9113. * Copyright 2011-2016 Twitter, Inc.
  9114. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9115. * ======================================================================== */
  9116. +function ($) {
  9117. 'use strict';
  9118. // DROPDOWN CLASS DEFINITION
  9119. // =========================
  9120. var backdrop = '.dropdown-backdrop'
  9121. var toggle = '[data-toggle="dropdown"]'
  9122. var Dropdown = function (element) {
  9123. $(element).on('click.bs.dropdown', this.toggle)
  9124. }
  9125. Dropdown.VERSION = '3.3.7'
  9126. function getParent($this) {
  9127. var selector = $this.attr('data-target')
  9128. if (!selector) {
  9129. selector = $this.attr('href')
  9130. selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  9131. }
  9132. var $parent = selector && $(selector)
  9133. return $parent && $parent.length ? $parent : $this.parent()
  9134. }
  9135. function clearMenus(e) {
  9136. if (e && e.which === 3) return
  9137. $(backdrop).remove()
  9138. $(toggle).each(function () {
  9139. var $this = $(this)
  9140. var $parent = getParent($this)
  9141. var relatedTarget = { relatedTarget: this }
  9142. if (!$parent.hasClass('open')) return
  9143. if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
  9144. $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
  9145. if (e.isDefaultPrevented()) return
  9146. $this.attr('aria-expanded', 'false')
  9147. $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
  9148. })
  9149. }
  9150. Dropdown.prototype.toggle = function (e) {
  9151. var $this = $(this)
  9152. if ($this.is('.disabled, :disabled')) return
  9153. var $parent = getParent($this)
  9154. var isActive = $parent.hasClass('open')
  9155. clearMenus()
  9156. if (!isActive) {
  9157. if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
  9158. // if mobile we use a backdrop because click events don't delegate
  9159. $(document.createElement('div'))
  9160. .addClass('dropdown-backdrop')
  9161. .insertAfter($(this))
  9162. .on('click', clearMenus)
  9163. }
  9164. var relatedTarget = { relatedTarget: this }
  9165. $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
  9166. if (e.isDefaultPrevented()) return
  9167. $this
  9168. .trigger('focus')
  9169. .attr('aria-expanded', 'true')
  9170. $parent
  9171. .toggleClass('open')
  9172. .trigger($.Event('shown.bs.dropdown', relatedTarget))
  9173. }
  9174. return false
  9175. }
  9176. Dropdown.prototype.keydown = function (e) {
  9177. if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
  9178. var $this = $(this)
  9179. e.preventDefault()
  9180. e.stopPropagation()
  9181. if ($this.is('.disabled, :disabled')) return
  9182. var $parent = getParent($this)
  9183. var isActive = $parent.hasClass('open')
  9184. if (!isActive && e.which != 27 || isActive && e.which == 27) {
  9185. if (e.which == 27) $parent.find(toggle).trigger('focus')
  9186. return $this.trigger('click')
  9187. }
  9188. var desc = ' li:not(.disabled):visible a'
  9189. var $items = $parent.find('.dropdown-menu' + desc)
  9190. if (!$items.length) return
  9191. var index = $items.index(e.target)
  9192. if (e.which == 38 && index > 0) index-- // up
  9193. if (e.which == 40 && index < $items.length - 1) index++ // down
  9194. if (!~index) index = 0
  9195. $items.eq(index).trigger('focus')
  9196. }
  9197. // DROPDOWN PLUGIN DEFINITION
  9198. // ==========================
  9199. function Plugin(option) {
  9200. return this.each(function () {
  9201. var $this = $(this)
  9202. var data = $this.data('bs.dropdown')
  9203. if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
  9204. if (typeof option == 'string') data[option].call($this)
  9205. })
  9206. }
  9207. var old = $.fn.dropdown
  9208. $.fn.dropdown = Plugin
  9209. $.fn.dropdown.Constructor = Dropdown
  9210. // DROPDOWN NO CONFLICT
  9211. // ====================
  9212. $.fn.dropdown.noConflict = function () {
  9213. $.fn.dropdown = old
  9214. return this
  9215. }
  9216. // APPLY TO STANDARD DROPDOWN ELEMENTS
  9217. // ===================================
  9218. $(document)
  9219. .on('click.bs.dropdown.data-api', clearMenus)
  9220. .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
  9221. .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
  9222. .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
  9223. .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
  9224. }(jQuery);
  9225. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  9226. /***/ }),
  9227. /* 9 */
  9228. /***/ (function(module, exports, __webpack_require__) {
  9229. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  9230. * Bootstrap: modal.js v3.3.7
  9231. * http://getbootstrap.com/javascript/#modals
  9232. * ========================================================================
  9233. * Copyright 2011-2016 Twitter, Inc.
  9234. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9235. * ======================================================================== */
  9236. +function ($) {
  9237. 'use strict';
  9238. // MODAL CLASS DEFINITION
  9239. // ======================
  9240. var Modal = function (element, options) {
  9241. this.options = options
  9242. this.$body = $(document.body)
  9243. this.$element = $(element)
  9244. this.$dialog = this.$element.find('.modal-dialog')
  9245. this.$backdrop = null
  9246. this.isShown = null
  9247. this.originalBodyPad = null
  9248. this.scrollbarWidth = 0
  9249. this.ignoreBackdropClick = false
  9250. if (this.options.remote) {
  9251. this.$element
  9252. .find('.modal-content')
  9253. .load(this.options.remote, $.proxy(function () {
  9254. this.$element.trigger('loaded.bs.modal')
  9255. }, this))
  9256. }
  9257. }
  9258. Modal.VERSION = '3.3.7'
  9259. Modal.TRANSITION_DURATION = 300
  9260. Modal.BACKDROP_TRANSITION_DURATION = 150
  9261. Modal.DEFAULTS = {
  9262. backdrop: true,
  9263. keyboard: true,
  9264. show: true
  9265. }
  9266. Modal.prototype.toggle = function (_relatedTarget) {
  9267. return this.isShown ? this.hide() : this.show(_relatedTarget)
  9268. }
  9269. Modal.prototype.show = function (_relatedTarget) {
  9270. var that = this
  9271. var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
  9272. this.$element.trigger(e)
  9273. if (this.isShown || e.isDefaultPrevented()) return
  9274. this.isShown = true
  9275. this.checkScrollbar()
  9276. this.setScrollbar()
  9277. this.$body.addClass('modal-open')
  9278. this.escape()
  9279. this.resize()
  9280. this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  9281. this.$dialog.on('mousedown.dismiss.bs.modal', function () {
  9282. that.$element.one('mouseup.dismiss.bs.modal', function (e) {
  9283. if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
  9284. })
  9285. })
  9286. this.backdrop(function () {
  9287. var transition = $.support.transition && that.$element.hasClass('fade')
  9288. if (!that.$element.parent().length) {
  9289. that.$element.appendTo(that.$body) // don't move modals dom position
  9290. }
  9291. that.$element
  9292. .show()
  9293. .scrollTop(0)
  9294. that.adjustDialog()
  9295. if (transition) {
  9296. that.$element[0].offsetWidth // force reflow
  9297. }
  9298. that.$element.addClass('in')
  9299. that.enforceFocus()
  9300. var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  9301. transition ?
  9302. that.$dialog // wait for modal to slide in
  9303. .one('bsTransitionEnd', function () {
  9304. that.$element.trigger('focus').trigger(e)
  9305. })
  9306. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  9307. that.$element.trigger('focus').trigger(e)
  9308. })
  9309. }
  9310. Modal.prototype.hide = function (e) {
  9311. if (e) e.preventDefault()
  9312. e = $.Event('hide.bs.modal')
  9313. this.$element.trigger(e)
  9314. if (!this.isShown || e.isDefaultPrevented()) return
  9315. this.isShown = false
  9316. this.escape()
  9317. this.resize()
  9318. $(document).off('focusin.bs.modal')
  9319. this.$element
  9320. .removeClass('in')
  9321. .off('click.dismiss.bs.modal')
  9322. .off('mouseup.dismiss.bs.modal')
  9323. this.$dialog.off('mousedown.dismiss.bs.modal')
  9324. $.support.transition && this.$element.hasClass('fade') ?
  9325. this.$element
  9326. .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  9327. .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  9328. this.hideModal()
  9329. }
  9330. Modal.prototype.enforceFocus = function () {
  9331. $(document)
  9332. .off('focusin.bs.modal') // guard against infinite focus loop
  9333. .on('focusin.bs.modal', $.proxy(function (e) {
  9334. if (document !== e.target &&
  9335. this.$element[0] !== e.target &&
  9336. !this.$element.has(e.target).length) {
  9337. this.$element.trigger('focus')
  9338. }
  9339. }, this))
  9340. }
  9341. Modal.prototype.escape = function () {
  9342. if (this.isShown && this.options.keyboard) {
  9343. this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
  9344. e.which == 27 && this.hide()
  9345. }, this))
  9346. } else if (!this.isShown) {
  9347. this.$element.off('keydown.dismiss.bs.modal')
  9348. }
  9349. }
  9350. Modal.prototype.resize = function () {
  9351. if (this.isShown) {
  9352. $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
  9353. } else {
  9354. $(window).off('resize.bs.modal')
  9355. }
  9356. }
  9357. Modal.prototype.hideModal = function () {
  9358. var that = this
  9359. this.$element.hide()
  9360. this.backdrop(function () {
  9361. that.$body.removeClass('modal-open')
  9362. that.resetAdjustments()
  9363. that.resetScrollbar()
  9364. that.$element.trigger('hidden.bs.modal')
  9365. })
  9366. }
  9367. Modal.prototype.removeBackdrop = function () {
  9368. this.$backdrop && this.$backdrop.remove()
  9369. this.$backdrop = null
  9370. }
  9371. Modal.prototype.backdrop = function (callback) {
  9372. var that = this
  9373. var animate = this.$element.hasClass('fade') ? 'fade' : ''
  9374. if (this.isShown && this.options.backdrop) {
  9375. var doAnimate = $.support.transition && animate
  9376. this.$backdrop = $(document.createElement('div'))
  9377. .addClass('modal-backdrop ' + animate)
  9378. .appendTo(this.$body)
  9379. this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
  9380. if (this.ignoreBackdropClick) {
  9381. this.ignoreBackdropClick = false
  9382. return
  9383. }
  9384. if (e.target !== e.currentTarget) return
  9385. this.options.backdrop == 'static'
  9386. ? this.$element[0].focus()
  9387. : this.hide()
  9388. }, this))
  9389. if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  9390. this.$backdrop.addClass('in')
  9391. if (!callback) return
  9392. doAnimate ?
  9393. this.$backdrop
  9394. .one('bsTransitionEnd', callback)
  9395. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  9396. callback()
  9397. } else if (!this.isShown && this.$backdrop) {
  9398. this.$backdrop.removeClass('in')
  9399. var callbackRemove = function () {
  9400. that.removeBackdrop()
  9401. callback && callback()
  9402. }
  9403. $.support.transition && this.$element.hasClass('fade') ?
  9404. this.$backdrop
  9405. .one('bsTransitionEnd', callbackRemove)
  9406. .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  9407. callbackRemove()
  9408. } else if (callback) {
  9409. callback()
  9410. }
  9411. }
  9412. // these following methods are used to handle overflowing modals
  9413. Modal.prototype.handleUpdate = function () {
  9414. this.adjustDialog()
  9415. }
  9416. Modal.prototype.adjustDialog = function () {
  9417. var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
  9418. this.$element.css({
  9419. paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
  9420. paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
  9421. })
  9422. }
  9423. Modal.prototype.resetAdjustments = function () {
  9424. this.$element.css({
  9425. paddingLeft: '',
  9426. paddingRight: ''
  9427. })
  9428. }
  9429. Modal.prototype.checkScrollbar = function () {
  9430. var fullWindowWidth = window.innerWidth
  9431. if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
  9432. var documentElementRect = document.documentElement.getBoundingClientRect()
  9433. fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
  9434. }
  9435. this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
  9436. this.scrollbarWidth = this.measureScrollbar()
  9437. }
  9438. Modal.prototype.setScrollbar = function () {
  9439. var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  9440. this.originalBodyPad = document.body.style.paddingRight || ''
  9441. if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  9442. }
  9443. Modal.prototype.resetScrollbar = function () {
  9444. this.$body.css('padding-right', this.originalBodyPad)
  9445. }
  9446. Modal.prototype.measureScrollbar = function () { // thx walsh
  9447. var scrollDiv = document.createElement('div')
  9448. scrollDiv.className = 'modal-scrollbar-measure'
  9449. this.$body.append(scrollDiv)
  9450. var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  9451. this.$body[0].removeChild(scrollDiv)
  9452. return scrollbarWidth
  9453. }
  9454. // MODAL PLUGIN DEFINITION
  9455. // =======================
  9456. function Plugin(option, _relatedTarget) {
  9457. return this.each(function () {
  9458. var $this = $(this)
  9459. var data = $this.data('bs.modal')
  9460. var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  9461. if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  9462. if (typeof option == 'string') data[option](_relatedTarget)
  9463. else if (options.show) data.show(_relatedTarget)
  9464. })
  9465. }
  9466. var old = $.fn.modal
  9467. $.fn.modal = Plugin
  9468. $.fn.modal.Constructor = Modal
  9469. // MODAL NO CONFLICT
  9470. // =================
  9471. $.fn.modal.noConflict = function () {
  9472. $.fn.modal = old
  9473. return this
  9474. }
  9475. // MODAL DATA-API
  9476. // ==============
  9477. $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  9478. var $this = $(this)
  9479. var href = $this.attr('href')
  9480. var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
  9481. var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  9482. if ($this.is('a')) e.preventDefault()
  9483. $target.one('show.bs.modal', function (showEvent) {
  9484. if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
  9485. $target.one('hidden.bs.modal', function () {
  9486. $this.is(':visible') && $this.trigger('focus')
  9487. })
  9488. })
  9489. Plugin.call($target, option, this)
  9490. })
  9491. }(jQuery);
  9492. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  9493. /***/ }),
  9494. /* 10 */
  9495. /***/ (function(module, exports, __webpack_require__) {
  9496. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  9497. * Bootstrap: tooltip.js v3.3.7
  9498. * http://getbootstrap.com/javascript/#tooltip
  9499. * Inspired by the original jQuery.tipsy by Jason Frame
  9500. * ========================================================================
  9501. * Copyright 2011-2016 Twitter, Inc.
  9502. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9503. * ======================================================================== */
  9504. +function ($) {
  9505. 'use strict';
  9506. // TOOLTIP PUBLIC CLASS DEFINITION
  9507. // ===============================
  9508. var Tooltip = function (element, options) {
  9509. this.type = null
  9510. this.options = null
  9511. this.enabled = null
  9512. this.timeout = null
  9513. this.hoverState = null
  9514. this.$element = null
  9515. this.inState = null
  9516. this.init('tooltip', element, options)
  9517. }
  9518. Tooltip.VERSION = '3.3.7'
  9519. Tooltip.TRANSITION_DURATION = 150
  9520. Tooltip.DEFAULTS = {
  9521. animation: true,
  9522. placement: 'top',
  9523. selector: false,
  9524. template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
  9525. trigger: 'hover focus',
  9526. title: '',
  9527. delay: 0,
  9528. html: false,
  9529. container: false,
  9530. viewport: {
  9531. selector: 'body',
  9532. padding: 0
  9533. }
  9534. }
  9535. Tooltip.prototype.init = function (type, element, options) {
  9536. this.enabled = true
  9537. this.type = type
  9538. this.$element = $(element)
  9539. this.options = this.getOptions(options)
  9540. this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
  9541. this.inState = { click: false, hover: false, focus: false }
  9542. if (this.$element[0] instanceof document.constructor && !this.options.selector) {
  9543. throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
  9544. }
  9545. var triggers = this.options.trigger.split(' ')
  9546. for (var i = triggers.length; i--;) {
  9547. var trigger = triggers[i]
  9548. if (trigger == 'click') {
  9549. this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  9550. } else if (trigger != 'manual') {
  9551. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
  9552. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
  9553. this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
  9554. this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  9555. }
  9556. }
  9557. this.options.selector ?
  9558. (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  9559. this.fixTitle()
  9560. }
  9561. Tooltip.prototype.getDefaults = function () {
  9562. return Tooltip.DEFAULTS
  9563. }
  9564. Tooltip.prototype.getOptions = function (options) {
  9565. options = $.extend({}, this.getDefaults(), this.$element.data(), options)
  9566. if (options.delay && typeof options.delay == 'number') {
  9567. options.delay = {
  9568. show: options.delay,
  9569. hide: options.delay
  9570. }
  9571. }
  9572. return options
  9573. }
  9574. Tooltip.prototype.getDelegateOptions = function () {
  9575. var options = {}
  9576. var defaults = this.getDefaults()
  9577. this._options && $.each(this._options, function (key, value) {
  9578. if (defaults[key] != value) options[key] = value
  9579. })
  9580. return options
  9581. }
  9582. Tooltip.prototype.enter = function (obj) {
  9583. var self = obj instanceof this.constructor ?
  9584. obj : $(obj.currentTarget).data('bs.' + this.type)
  9585. if (!self) {
  9586. self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  9587. $(obj.currentTarget).data('bs.' + this.type, self)
  9588. }
  9589. if (obj instanceof $.Event) {
  9590. self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
  9591. }
  9592. if (self.tip().hasClass('in') || self.hoverState == 'in') {
  9593. self.hoverState = 'in'
  9594. return
  9595. }
  9596. clearTimeout(self.timeout)
  9597. self.hoverState = 'in'
  9598. if (!self.options.delay || !self.options.delay.show) return self.show()
  9599. self.timeout = setTimeout(function () {
  9600. if (self.hoverState == 'in') self.show()
  9601. }, self.options.delay.show)
  9602. }
  9603. Tooltip.prototype.isInStateTrue = function () {
  9604. for (var key in this.inState) {
  9605. if (this.inState[key]) return true
  9606. }
  9607. return false
  9608. }
  9609. Tooltip.prototype.leave = function (obj) {
  9610. var self = obj instanceof this.constructor ?
  9611. obj : $(obj.currentTarget).data('bs.' + this.type)
  9612. if (!self) {
  9613. self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  9614. $(obj.currentTarget).data('bs.' + this.type, self)
  9615. }
  9616. if (obj instanceof $.Event) {
  9617. self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
  9618. }
  9619. if (self.isInStateTrue()) return
  9620. clearTimeout(self.timeout)
  9621. self.hoverState = 'out'
  9622. if (!self.options.delay || !self.options.delay.hide) return self.hide()
  9623. self.timeout = setTimeout(function () {
  9624. if (self.hoverState == 'out') self.hide()
  9625. }, self.options.delay.hide)
  9626. }
  9627. Tooltip.prototype.show = function () {
  9628. var e = $.Event('show.bs.' + this.type)
  9629. if (this.hasContent() && this.enabled) {
  9630. this.$element.trigger(e)
  9631. var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  9632. if (e.isDefaultPrevented() || !inDom) return
  9633. var that = this
  9634. var $tip = this.tip()
  9635. var tipId = this.getUID(this.type)
  9636. this.setContent()
  9637. $tip.attr('id', tipId)
  9638. this.$element.attr('aria-describedby', tipId)
  9639. if (this.options.animation) $tip.addClass('fade')
  9640. var placement = typeof this.options.placement == 'function' ?
  9641. this.options.placement.call(this, $tip[0], this.$element[0]) :
  9642. this.options.placement
  9643. var autoToken = /\s?auto?\s?/i
  9644. var autoPlace = autoToken.test(placement)
  9645. if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
  9646. $tip
  9647. .detach()
  9648. .css({ top: 0, left: 0, display: 'block' })
  9649. .addClass(placement)
  9650. .data('bs.' + this.type, this)
  9651. this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  9652. this.$element.trigger('inserted.bs.' + this.type)
  9653. var pos = this.getPosition()
  9654. var actualWidth = $tip[0].offsetWidth
  9655. var actualHeight = $tip[0].offsetHeight
  9656. if (autoPlace) {
  9657. var orgPlacement = placement
  9658. var viewportDim = this.getPosition(this.$viewport)
  9659. placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
  9660. placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
  9661. placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
  9662. placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
  9663. placement
  9664. $tip
  9665. .removeClass(orgPlacement)
  9666. .addClass(placement)
  9667. }
  9668. var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  9669. this.applyPlacement(calculatedOffset, placement)
  9670. var complete = function () {
  9671. var prevHoverState = that.hoverState
  9672. that.$element.trigger('shown.bs.' + that.type)
  9673. that.hoverState = null
  9674. if (prevHoverState == 'out') that.leave(that)
  9675. }
  9676. $.support.transition && this.$tip.hasClass('fade') ?
  9677. $tip
  9678. .one('bsTransitionEnd', complete)
  9679. .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  9680. complete()
  9681. }
  9682. }
  9683. Tooltip.prototype.applyPlacement = function (offset, placement) {
  9684. var $tip = this.tip()
  9685. var width = $tip[0].offsetWidth
  9686. var height = $tip[0].offsetHeight
  9687. // manually read margins because getBoundingClientRect includes difference
  9688. var marginTop = parseInt($tip.css('margin-top'), 10)
  9689. var marginLeft = parseInt($tip.css('margin-left'), 10)
  9690. // we must check for NaN for ie 8/9
  9691. if (isNaN(marginTop)) marginTop = 0
  9692. if (isNaN(marginLeft)) marginLeft = 0
  9693. offset.top += marginTop
  9694. offset.left += marginLeft
  9695. // $.fn.offset doesn't round pixel values
  9696. // so we use setOffset directly with our own function B-0
  9697. $.offset.setOffset($tip[0], $.extend({
  9698. using: function (props) {
  9699. $tip.css({
  9700. top: Math.round(props.top),
  9701. left: Math.round(props.left)
  9702. })
  9703. }
  9704. }, offset), 0)
  9705. $tip.addClass('in')
  9706. // check to see if placing tip in new offset caused the tip to resize itself
  9707. var actualWidth = $tip[0].offsetWidth
  9708. var actualHeight = $tip[0].offsetHeight
  9709. if (placement == 'top' && actualHeight != height) {
  9710. offset.top = offset.top + height - actualHeight
  9711. }
  9712. var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
  9713. if (delta.left) offset.left += delta.left
  9714. else offset.top += delta.top
  9715. var isVertical = /top|bottom/.test(placement)
  9716. var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
  9717. var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
  9718. $tip.offset(offset)
  9719. this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  9720. }
  9721. Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
  9722. this.arrow()
  9723. .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
  9724. .css(isVertical ? 'top' : 'left', '')
  9725. }
  9726. Tooltip.prototype.setContent = function () {
  9727. var $tip = this.tip()
  9728. var title = this.getTitle()
  9729. $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
  9730. $tip.removeClass('fade in top bottom left right')
  9731. }
  9732. Tooltip.prototype.hide = function (callback) {
  9733. var that = this
  9734. var $tip = $(this.$tip)
  9735. var e = $.Event('hide.bs.' + this.type)
  9736. function complete() {
  9737. if (that.hoverState != 'in') $tip.detach()
  9738. if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
  9739. that.$element
  9740. .removeAttr('aria-describedby')
  9741. .trigger('hidden.bs.' + that.type)
  9742. }
  9743. callback && callback()
  9744. }
  9745. this.$element.trigger(e)
  9746. if (e.isDefaultPrevented()) return
  9747. $tip.removeClass('in')
  9748. $.support.transition && $tip.hasClass('fade') ?
  9749. $tip
  9750. .one('bsTransitionEnd', complete)
  9751. .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  9752. complete()
  9753. this.hoverState = null
  9754. return this
  9755. }
  9756. Tooltip.prototype.fixTitle = function () {
  9757. var $e = this.$element
  9758. if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
  9759. $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
  9760. }
  9761. }
  9762. Tooltip.prototype.hasContent = function () {
  9763. return this.getTitle()
  9764. }
  9765. Tooltip.prototype.getPosition = function ($element) {
  9766. $element = $element || this.$element
  9767. var el = $element[0]
  9768. var isBody = el.tagName == 'BODY'
  9769. var elRect = el.getBoundingClientRect()
  9770. if (elRect.width == null) {
  9771. // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
  9772. elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
  9773. }
  9774. var isSvg = window.SVGElement && el instanceof window.SVGElement
  9775. // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
  9776. // See https://github.com/twbs/bootstrap/issues/20280
  9777. var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
  9778. var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
  9779. var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
  9780. return $.extend({}, elRect, scroll, outerDims, elOffset)
  9781. }
  9782. Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
  9783. return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  9784. placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  9785. placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
  9786. /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
  9787. }
  9788. Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
  9789. var delta = { top: 0, left: 0 }
  9790. if (!this.$viewport) return delta
  9791. var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
  9792. var viewportDimensions = this.getPosition(this.$viewport)
  9793. if (/right|left/.test(placement)) {
  9794. var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
  9795. var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
  9796. if (topEdgeOffset < viewportDimensions.top) { // top overflow
  9797. delta.top = viewportDimensions.top - topEdgeOffset
  9798. } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
  9799. delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
  9800. }
  9801. } else {
  9802. var leftEdgeOffset = pos.left - viewportPadding
  9803. var rightEdgeOffset = pos.left + viewportPadding + actualWidth
  9804. if (leftEdgeOffset < viewportDimensions.left) { // left overflow
  9805. delta.left = viewportDimensions.left - leftEdgeOffset
  9806. } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
  9807. delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
  9808. }
  9809. }
  9810. return delta
  9811. }
  9812. Tooltip.prototype.getTitle = function () {
  9813. var title
  9814. var $e = this.$element
  9815. var o = this.options
  9816. title = $e.attr('data-original-title')
  9817. || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
  9818. return title
  9819. }
  9820. Tooltip.prototype.getUID = function (prefix) {
  9821. do prefix += ~~(Math.random() * 1000000)
  9822. while (document.getElementById(prefix))
  9823. return prefix
  9824. }
  9825. Tooltip.prototype.tip = function () {
  9826. if (!this.$tip) {
  9827. this.$tip = $(this.options.template)
  9828. if (this.$tip.length != 1) {
  9829. throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
  9830. }
  9831. }
  9832. return this.$tip
  9833. }
  9834. Tooltip.prototype.arrow = function () {
  9835. return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  9836. }
  9837. Tooltip.prototype.enable = function () {
  9838. this.enabled = true
  9839. }
  9840. Tooltip.prototype.disable = function () {
  9841. this.enabled = false
  9842. }
  9843. Tooltip.prototype.toggleEnabled = function () {
  9844. this.enabled = !this.enabled
  9845. }
  9846. Tooltip.prototype.toggle = function (e) {
  9847. var self = this
  9848. if (e) {
  9849. self = $(e.currentTarget).data('bs.' + this.type)
  9850. if (!self) {
  9851. self = new this.constructor(e.currentTarget, this.getDelegateOptions())
  9852. $(e.currentTarget).data('bs.' + this.type, self)
  9853. }
  9854. }
  9855. if (e) {
  9856. self.inState.click = !self.inState.click
  9857. if (self.isInStateTrue()) self.enter(self)
  9858. else self.leave(self)
  9859. } else {
  9860. self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  9861. }
  9862. }
  9863. Tooltip.prototype.destroy = function () {
  9864. var that = this
  9865. clearTimeout(this.timeout)
  9866. this.hide(function () {
  9867. that.$element.off('.' + that.type).removeData('bs.' + that.type)
  9868. if (that.$tip) {
  9869. that.$tip.detach()
  9870. }
  9871. that.$tip = null
  9872. that.$arrow = null
  9873. that.$viewport = null
  9874. that.$element = null
  9875. })
  9876. }
  9877. // TOOLTIP PLUGIN DEFINITION
  9878. // =========================
  9879. function Plugin(option) {
  9880. return this.each(function () {
  9881. var $this = $(this)
  9882. var data = $this.data('bs.tooltip')
  9883. var options = typeof option == 'object' && option
  9884. if (!data && /destroy|hide/.test(option)) return
  9885. if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
  9886. if (typeof option == 'string') data[option]()
  9887. })
  9888. }
  9889. var old = $.fn.tooltip
  9890. $.fn.tooltip = Plugin
  9891. $.fn.tooltip.Constructor = Tooltip
  9892. // TOOLTIP NO CONFLICT
  9893. // ===================
  9894. $.fn.tooltip.noConflict = function () {
  9895. $.fn.tooltip = old
  9896. return this
  9897. }
  9898. }(jQuery);
  9899. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  9900. /***/ }),
  9901. /* 11 */
  9902. /***/ (function(module, exports, __webpack_require__) {
  9903. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  9904. * Bootstrap: popover.js v3.3.7
  9905. * http://getbootstrap.com/javascript/#popovers
  9906. * ========================================================================
  9907. * Copyright 2011-2016 Twitter, Inc.
  9908. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9909. * ======================================================================== */
  9910. +function ($) {
  9911. 'use strict';
  9912. // POPOVER PUBLIC CLASS DEFINITION
  9913. // ===============================
  9914. var Popover = function (element, options) {
  9915. this.init('popover', element, options)
  9916. }
  9917. if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
  9918. Popover.VERSION = '3.3.7'
  9919. Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
  9920. placement: 'right',
  9921. trigger: 'click',
  9922. content: '',
  9923. template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  9924. })
  9925. // NOTE: POPOVER EXTENDS tooltip.js
  9926. // ================================
  9927. Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
  9928. Popover.prototype.constructor = Popover
  9929. Popover.prototype.getDefaults = function () {
  9930. return Popover.DEFAULTS
  9931. }
  9932. Popover.prototype.setContent = function () {
  9933. var $tip = this.tip()
  9934. var title = this.getTitle()
  9935. var content = this.getContent()
  9936. $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
  9937. $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
  9938. this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
  9939. ](content)
  9940. $tip.removeClass('fade top bottom left right in')
  9941. // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
  9942. // this manually by checking the contents.
  9943. if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  9944. }
  9945. Popover.prototype.hasContent = function () {
  9946. return this.getTitle() || this.getContent()
  9947. }
  9948. Popover.prototype.getContent = function () {
  9949. var $e = this.$element
  9950. var o = this.options
  9951. return $e.attr('data-content')
  9952. || (typeof o.content == 'function' ?
  9953. o.content.call($e[0]) :
  9954. o.content)
  9955. }
  9956. Popover.prototype.arrow = function () {
  9957. return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  9958. }
  9959. // POPOVER PLUGIN DEFINITION
  9960. // =========================
  9961. function Plugin(option) {
  9962. return this.each(function () {
  9963. var $this = $(this)
  9964. var data = $this.data('bs.popover')
  9965. var options = typeof option == 'object' && option
  9966. if (!data && /destroy|hide/.test(option)) return
  9967. if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
  9968. if (typeof option == 'string') data[option]()
  9969. })
  9970. }
  9971. var old = $.fn.popover
  9972. $.fn.popover = Plugin
  9973. $.fn.popover.Constructor = Popover
  9974. // POPOVER NO CONFLICT
  9975. // ===================
  9976. $.fn.popover.noConflict = function () {
  9977. $.fn.popover = old
  9978. return this
  9979. }
  9980. }(jQuery);
  9981. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  9982. /***/ }),
  9983. /* 12 */
  9984. /***/ (function(module, exports, __webpack_require__) {
  9985. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  9986. * Bootstrap: scrollspy.js v3.3.7
  9987. * http://getbootstrap.com/javascript/#scrollspy
  9988. * ========================================================================
  9989. * Copyright 2011-2016 Twitter, Inc.
  9990. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  9991. * ======================================================================== */
  9992. +function ($) {
  9993. 'use strict';
  9994. // SCROLLSPY CLASS DEFINITION
  9995. // ==========================
  9996. function ScrollSpy(element, options) {
  9997. this.$body = $(document.body)
  9998. this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
  9999. this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
  10000. this.selector = (this.options.target || '') + ' .nav li > a'
  10001. this.offsets = []
  10002. this.targets = []
  10003. this.activeTarget = null
  10004. this.scrollHeight = 0
  10005. this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
  10006. this.refresh()
  10007. this.process()
  10008. }
  10009. ScrollSpy.VERSION = '3.3.7'
  10010. ScrollSpy.DEFAULTS = {
  10011. offset: 10
  10012. }
  10013. ScrollSpy.prototype.getScrollHeight = function () {
  10014. return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  10015. }
  10016. ScrollSpy.prototype.refresh = function () {
  10017. var that = this
  10018. var offsetMethod = 'offset'
  10019. var offsetBase = 0
  10020. this.offsets = []
  10021. this.targets = []
  10022. this.scrollHeight = this.getScrollHeight()
  10023. if (!$.isWindow(this.$scrollElement[0])) {
  10024. offsetMethod = 'position'
  10025. offsetBase = this.$scrollElement.scrollTop()
  10026. }
  10027. this.$body
  10028. .find(this.selector)
  10029. .map(function () {
  10030. var $el = $(this)
  10031. var href = $el.data('target') || $el.attr('href')
  10032. var $href = /^#./.test(href) && $(href)
  10033. return ($href
  10034. && $href.length
  10035. && $href.is(':visible')
  10036. && [[$href[offsetMethod]().top + offsetBase, href]]) || null
  10037. })
  10038. .sort(function (a, b) { return a[0] - b[0] })
  10039. .each(function () {
  10040. that.offsets.push(this[0])
  10041. that.targets.push(this[1])
  10042. })
  10043. }
  10044. ScrollSpy.prototype.process = function () {
  10045. var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
  10046. var scrollHeight = this.getScrollHeight()
  10047. var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
  10048. var offsets = this.offsets
  10049. var targets = this.targets
  10050. var activeTarget = this.activeTarget
  10051. var i
  10052. if (this.scrollHeight != scrollHeight) {
  10053. this.refresh()
  10054. }
  10055. if (scrollTop >= maxScroll) {
  10056. return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  10057. }
  10058. if (activeTarget && scrollTop < offsets[0]) {
  10059. this.activeTarget = null
  10060. return this.clear()
  10061. }
  10062. for (i = offsets.length; i--;) {
  10063. activeTarget != targets[i]
  10064. && scrollTop >= offsets[i]
  10065. && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
  10066. && this.activate(targets[i])
  10067. }
  10068. }
  10069. ScrollSpy.prototype.activate = function (target) {
  10070. this.activeTarget = target
  10071. this.clear()
  10072. var selector = this.selector +
  10073. '[data-target="' + target + '"],' +
  10074. this.selector + '[href="' + target + '"]'
  10075. var active = $(selector)
  10076. .parents('li')
  10077. .addClass('active')
  10078. if (active.parent('.dropdown-menu').length) {
  10079. active = active
  10080. .closest('li.dropdown')
  10081. .addClass('active')
  10082. }
  10083. active.trigger('activate.bs.scrollspy')
  10084. }
  10085. ScrollSpy.prototype.clear = function () {
  10086. $(this.selector)
  10087. .parentsUntil(this.options.target, '.active')
  10088. .removeClass('active')
  10089. }
  10090. // SCROLLSPY PLUGIN DEFINITION
  10091. // ===========================
  10092. function Plugin(option) {
  10093. return this.each(function () {
  10094. var $this = $(this)
  10095. var data = $this.data('bs.scrollspy')
  10096. var options = typeof option == 'object' && option
  10097. if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
  10098. if (typeof option == 'string') data[option]()
  10099. })
  10100. }
  10101. var old = $.fn.scrollspy
  10102. $.fn.scrollspy = Plugin
  10103. $.fn.scrollspy.Constructor = ScrollSpy
  10104. // SCROLLSPY NO CONFLICT
  10105. // =====================
  10106. $.fn.scrollspy.noConflict = function () {
  10107. $.fn.scrollspy = old
  10108. return this
  10109. }
  10110. // SCROLLSPY DATA-API
  10111. // ==================
  10112. $(window).on('load.bs.scrollspy.data-api', function () {
  10113. $('[data-spy="scroll"]').each(function () {
  10114. var $spy = $(this)
  10115. Plugin.call($spy, $spy.data())
  10116. })
  10117. })
  10118. }(jQuery);
  10119. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  10120. /***/ }),
  10121. /* 13 */
  10122. /***/ (function(module, exports, __webpack_require__) {
  10123. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  10124. * Bootstrap: tab.js v3.3.7
  10125. * http://getbootstrap.com/javascript/#tabs
  10126. * ========================================================================
  10127. * Copyright 2011-2016 Twitter, Inc.
  10128. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10129. * ======================================================================== */
  10130. +function ($) {
  10131. 'use strict';
  10132. // TAB CLASS DEFINITION
  10133. // ====================
  10134. var Tab = function (element) {
  10135. // jscs:disable requireDollarBeforejQueryAssignment
  10136. this.element = $(element)
  10137. // jscs:enable requireDollarBeforejQueryAssignment
  10138. }
  10139. Tab.VERSION = '3.3.7'
  10140. Tab.TRANSITION_DURATION = 150
  10141. Tab.prototype.show = function () {
  10142. var $this = this.element
  10143. var $ul = $this.closest('ul:not(.dropdown-menu)')
  10144. var selector = $this.data('target')
  10145. if (!selector) {
  10146. selector = $this.attr('href')
  10147. selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  10148. }
  10149. if ($this.parent('li').hasClass('active')) return
  10150. var $previous = $ul.find('.active:last a')
  10151. var hideEvent = $.Event('hide.bs.tab', {
  10152. relatedTarget: $this[0]
  10153. })
  10154. var showEvent = $.Event('show.bs.tab', {
  10155. relatedTarget: $previous[0]
  10156. })
  10157. $previous.trigger(hideEvent)
  10158. $this.trigger(showEvent)
  10159. if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
  10160. var $target = $(selector)
  10161. this.activate($this.closest('li'), $ul)
  10162. this.activate($target, $target.parent(), function () {
  10163. $previous.trigger({
  10164. type: 'hidden.bs.tab',
  10165. relatedTarget: $this[0]
  10166. })
  10167. $this.trigger({
  10168. type: 'shown.bs.tab',
  10169. relatedTarget: $previous[0]
  10170. })
  10171. })
  10172. }
  10173. Tab.prototype.activate = function (element, container, callback) {
  10174. var $active = container.find('> .active')
  10175. var transition = callback
  10176. && $.support.transition
  10177. && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
  10178. function next() {
  10179. $active
  10180. .removeClass('active')
  10181. .find('> .dropdown-menu > .active')
  10182. .removeClass('active')
  10183. .end()
  10184. .find('[data-toggle="tab"]')
  10185. .attr('aria-expanded', false)
  10186. element
  10187. .addClass('active')
  10188. .find('[data-toggle="tab"]')
  10189. .attr('aria-expanded', true)
  10190. if (transition) {
  10191. element[0].offsetWidth // reflow for transition
  10192. element.addClass('in')
  10193. } else {
  10194. element.removeClass('fade')
  10195. }
  10196. if (element.parent('.dropdown-menu').length) {
  10197. element
  10198. .closest('li.dropdown')
  10199. .addClass('active')
  10200. .end()
  10201. .find('[data-toggle="tab"]')
  10202. .attr('aria-expanded', true)
  10203. }
  10204. callback && callback()
  10205. }
  10206. $active.length && transition ?
  10207. $active
  10208. .one('bsTransitionEnd', next)
  10209. .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
  10210. next()
  10211. $active.removeClass('in')
  10212. }
  10213. // TAB PLUGIN DEFINITION
  10214. // =====================
  10215. function Plugin(option) {
  10216. return this.each(function () {
  10217. var $this = $(this)
  10218. var data = $this.data('bs.tab')
  10219. if (!data) $this.data('bs.tab', (data = new Tab(this)))
  10220. if (typeof option == 'string') data[option]()
  10221. })
  10222. }
  10223. var old = $.fn.tab
  10224. $.fn.tab = Plugin
  10225. $.fn.tab.Constructor = Tab
  10226. // TAB NO CONFLICT
  10227. // ===============
  10228. $.fn.tab.noConflict = function () {
  10229. $.fn.tab = old
  10230. return this
  10231. }
  10232. // TAB DATA-API
  10233. // ============
  10234. var clickHandler = function (e) {
  10235. e.preventDefault()
  10236. Plugin.call($(this), 'show')
  10237. }
  10238. $(document)
  10239. .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
  10240. .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
  10241. }(jQuery);
  10242. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  10243. /***/ }),
  10244. /* 14 */
  10245. /***/ (function(module, exports, __webpack_require__) {
  10246. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  10247. * Bootstrap: affix.js v3.3.7
  10248. * http://getbootstrap.com/javascript/#affix
  10249. * ========================================================================
  10250. * Copyright 2011-2016 Twitter, Inc.
  10251. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  10252. * ======================================================================== */
  10253. +function ($) {
  10254. 'use strict';
  10255. // AFFIX CLASS DEFINITION
  10256. // ======================
  10257. var Affix = function (element, options) {
  10258. this.options = $.extend({}, Affix.DEFAULTS, options)
  10259. this.$target = $(this.options.target)
  10260. .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
  10261. .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
  10262. this.$element = $(element)
  10263. this.affixed = null
  10264. this.unpin = null
  10265. this.pinnedOffset = null
  10266. this.checkPosition()
  10267. }
  10268. Affix.VERSION = '3.3.7'
  10269. Affix.RESET = 'affix affix-top affix-bottom'
  10270. Affix.DEFAULTS = {
  10271. offset: 0,
  10272. target: window
  10273. }
  10274. Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
  10275. var scrollTop = this.$target.scrollTop()
  10276. var position = this.$element.offset()
  10277. var targetHeight = this.$target.height()
  10278. if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
  10279. if (this.affixed == 'bottom') {
  10280. if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
  10281. return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
  10282. }
  10283. var initializing = this.affixed == null
  10284. var colliderTop = initializing ? scrollTop : position.top
  10285. var colliderHeight = initializing ? targetHeight : height
  10286. if (offsetTop != null && scrollTop <= offsetTop) return 'top'
  10287. if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
  10288. return false
  10289. }
  10290. Affix.prototype.getPinnedOffset = function () {
  10291. if (this.pinnedOffset) return this.pinnedOffset
  10292. this.$element.removeClass(Affix.RESET).addClass('affix')
  10293. var scrollTop = this.$target.scrollTop()
  10294. var position = this.$element.offset()
  10295. return (this.pinnedOffset = position.top - scrollTop)
  10296. }
  10297. Affix.prototype.checkPositionWithEventLoop = function () {
  10298. setTimeout($.proxy(this.checkPosition, this), 1)
  10299. }
  10300. Affix.prototype.checkPosition = function () {
  10301. if (!this.$element.is(':visible')) return
  10302. var height = this.$element.height()
  10303. var offset = this.options.offset
  10304. var offsetTop = offset.top
  10305. var offsetBottom = offset.bottom
  10306. var scrollHeight = Math.max($(document).height(), $(document.body).height())
  10307. if (typeof offset != 'object') offsetBottom = offsetTop = offset
  10308. if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
  10309. if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
  10310. var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
  10311. if (this.affixed != affix) {
  10312. if (this.unpin != null) this.$element.css('top', '')
  10313. var affixType = 'affix' + (affix ? '-' + affix : '')
  10314. var e = $.Event(affixType + '.bs.affix')
  10315. this.$element.trigger(e)
  10316. if (e.isDefaultPrevented()) return
  10317. this.affixed = affix
  10318. this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
  10319. this.$element
  10320. .removeClass(Affix.RESET)
  10321. .addClass(affixType)
  10322. .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
  10323. }
  10324. if (affix == 'bottom') {
  10325. this.$element.offset({
  10326. top: scrollHeight - height - offsetBottom
  10327. })
  10328. }
  10329. }
  10330. // AFFIX PLUGIN DEFINITION
  10331. // =======================
  10332. function Plugin(option) {
  10333. return this.each(function () {
  10334. var $this = $(this)
  10335. var data = $this.data('bs.affix')
  10336. var options = typeof option == 'object' && option
  10337. if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
  10338. if (typeof option == 'string') data[option]()
  10339. })
  10340. }
  10341. var old = $.fn.affix
  10342. $.fn.affix = Plugin
  10343. $.fn.affix.Constructor = Affix
  10344. // AFFIX NO CONFLICT
  10345. // =================
  10346. $.fn.affix.noConflict = function () {
  10347. $.fn.affix = old
  10348. return this
  10349. }
  10350. // AFFIX DATA-API
  10351. // ==============
  10352. $(window).on('load', function () {
  10353. $('[data-spy="affix"]').each(function () {
  10354. var $spy = $(this)
  10355. var data = $spy.data()
  10356. data.offset = data.offset || {}
  10357. if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
  10358. if (data.offsetTop != null) data.offset.top = data.offsetTop
  10359. Plugin.call($spy, data)
  10360. })
  10361. })
  10362. }(jQuery);
  10363. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  10364. /***/ }),
  10365. /* 15 */
  10366. /***/ (function(module, exports, __webpack_require__) {
  10367. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  10368. * Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
  10369. *
  10370. * Copyright 2013-2017 bootstrap-select
  10371. * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
  10372. */
  10373. (function (root, factory) {
  10374. if (true) {
  10375. // AMD. Register as an anonymous module unless amdModuleId is set
  10376. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = function (a0) {
  10377. return (factory(a0));
  10378. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  10379. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  10380. } else if (typeof module === 'object' && module.exports) {
  10381. // Node. Does not work with strict CommonJS, but
  10382. // only CommonJS-like environments that support module.exports,
  10383. // like Node.
  10384. module.exports = factory(require("jquery"));
  10385. } else {
  10386. factory(root["jQuery"]);
  10387. }
  10388. }(this, function (jQuery) {
  10389. (function ($) {
  10390. 'use strict';
  10391. //<editor-fold desc="Shims">
  10392. if (!String.prototype.includes) {
  10393. (function () {
  10394. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  10395. var toString = {}.toString;
  10396. var defineProperty = (function () {
  10397. // IE 8 only supports `Object.defineProperty` on DOM elements
  10398. try {
  10399. var object = {};
  10400. var $defineProperty = Object.defineProperty;
  10401. var result = $defineProperty(object, object, object) && $defineProperty;
  10402. } catch (error) {
  10403. }
  10404. return result;
  10405. }());
  10406. var indexOf = ''.indexOf;
  10407. var includes = function (search) {
  10408. if (this == null) {
  10409. throw new TypeError();
  10410. }
  10411. var string = String(this);
  10412. if (search && toString.call(search) == '[object RegExp]') {
  10413. throw new TypeError();
  10414. }
  10415. var stringLength = string.length;
  10416. var searchString = String(search);
  10417. var searchLength = searchString.length;
  10418. var position = arguments.length > 1 ? arguments[1] : undefined;
  10419. // `ToInteger`
  10420. var pos = position ? Number(position) : 0;
  10421. if (pos != pos) { // better `isNaN`
  10422. pos = 0;
  10423. }
  10424. var start = Math.min(Math.max(pos, 0), stringLength);
  10425. // Avoid the `indexOf` call if no match is possible
  10426. if (searchLength + start > stringLength) {
  10427. return false;
  10428. }
  10429. return indexOf.call(string, searchString, pos) != -1;
  10430. };
  10431. if (defineProperty) {
  10432. defineProperty(String.prototype, 'includes', {
  10433. 'value': includes,
  10434. 'configurable': true,
  10435. 'writable': true
  10436. });
  10437. } else {
  10438. String.prototype.includes = includes;
  10439. }
  10440. }());
  10441. }
  10442. if (!String.prototype.startsWith) {
  10443. (function () {
  10444. 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
  10445. var defineProperty = (function () {
  10446. // IE 8 only supports `Object.defineProperty` on DOM elements
  10447. try {
  10448. var object = {};
  10449. var $defineProperty = Object.defineProperty;
  10450. var result = $defineProperty(object, object, object) && $defineProperty;
  10451. } catch (error) {
  10452. }
  10453. return result;
  10454. }());
  10455. var toString = {}.toString;
  10456. var startsWith = function (search) {
  10457. if (this == null) {
  10458. throw new TypeError();
  10459. }
  10460. var string = String(this);
  10461. if (search && toString.call(search) == '[object RegExp]') {
  10462. throw new TypeError();
  10463. }
  10464. var stringLength = string.length;
  10465. var searchString = String(search);
  10466. var searchLength = searchString.length;
  10467. var position = arguments.length > 1 ? arguments[1] : undefined;
  10468. // `ToInteger`
  10469. var pos = position ? Number(position) : 0;
  10470. if (pos != pos) { // better `isNaN`
  10471. pos = 0;
  10472. }
  10473. var start = Math.min(Math.max(pos, 0), stringLength);
  10474. // Avoid the `indexOf` call if no match is possible
  10475. if (searchLength + start > stringLength) {
  10476. return false;
  10477. }
  10478. var index = -1;
  10479. while (++index < searchLength) {
  10480. if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
  10481. return false;
  10482. }
  10483. }
  10484. return true;
  10485. };
  10486. if (defineProperty) {
  10487. defineProperty(String.prototype, 'startsWith', {
  10488. 'value': startsWith,
  10489. 'configurable': true,
  10490. 'writable': true
  10491. });
  10492. } else {
  10493. String.prototype.startsWith = startsWith;
  10494. }
  10495. }());
  10496. }
  10497. if (!Object.keys) {
  10498. Object.keys = function (
  10499. o, // object
  10500. k, // key
  10501. r // result array
  10502. ){
  10503. // initialize object and result
  10504. r=[];
  10505. // iterate over object keys
  10506. for (k in o)
  10507. // fill result array with non-prototypical keys
  10508. r.hasOwnProperty.call(o, k) && r.push(k);
  10509. // return result
  10510. return r;
  10511. };
  10512. }
  10513. // set data-selected on select element if the value has been programmatically selected
  10514. // prior to initialization of bootstrap-select
  10515. // * consider removing or replacing an alternative method *
  10516. var valHooks = {
  10517. useDefault: false,
  10518. _set: $.valHooks.select.set
  10519. };
  10520. $.valHooks.select.set = function(elem, value) {
  10521. if (value && !valHooks.useDefault) $(elem).data('selected', true);
  10522. return valHooks._set.apply(this, arguments);
  10523. };
  10524. var changed_arguments = null;
  10525. var EventIsSupported = (function() {
  10526. try {
  10527. new Event('change');
  10528. return true;
  10529. } catch (e) {
  10530. return false;
  10531. }
  10532. })();
  10533. $.fn.triggerNative = function (eventName) {
  10534. var el = this[0],
  10535. event;
  10536. if (el.dispatchEvent) { // for modern browsers & IE9+
  10537. if (EventIsSupported) {
  10538. // For modern browsers
  10539. event = new Event(eventName, {
  10540. bubbles: true
  10541. });
  10542. } else {
  10543. // For IE since it doesn't support Event constructor
  10544. event = document.createEvent('Event');
  10545. event.initEvent(eventName, true, false);
  10546. }
  10547. el.dispatchEvent(event);
  10548. } else if (el.fireEvent) { // for IE8
  10549. event = document.createEventObject();
  10550. event.eventType = eventName;
  10551. el.fireEvent('on' + eventName, event);
  10552. } else {
  10553. // fall back to jQuery.trigger
  10554. this.trigger(eventName);
  10555. }
  10556. };
  10557. //</editor-fold>
  10558. // Case insensitive contains search
  10559. $.expr.pseudos.icontains = function (obj, index, meta) {
  10560. var $obj = $(obj).find('a');
  10561. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  10562. return haystack.includes(meta[3].toUpperCase());
  10563. };
  10564. // Case insensitive begins search
  10565. $.expr.pseudos.ibegins = function (obj, index, meta) {
  10566. var $obj = $(obj).find('a');
  10567. var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
  10568. return haystack.startsWith(meta[3].toUpperCase());
  10569. };
  10570. // Case and accent insensitive contains search
  10571. $.expr.pseudos.aicontains = function (obj, index, meta) {
  10572. var $obj = $(obj).find('a');
  10573. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  10574. return haystack.includes(meta[3].toUpperCase());
  10575. };
  10576. // Case and accent insensitive begins search
  10577. $.expr.pseudos.aibegins = function (obj, index, meta) {
  10578. var $obj = $(obj).find('a');
  10579. var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
  10580. return haystack.startsWith(meta[3].toUpperCase());
  10581. };
  10582. /**
  10583. * Remove all diatrics from the given text.
  10584. * @access private
  10585. * @param {String} text
  10586. * @returns {String}
  10587. */
  10588. function normalizeToBase(text) {
  10589. var rExps = [
  10590. {re: /[\xC0-\xC6]/g, ch: "A"},
  10591. {re: /[\xE0-\xE6]/g, ch: "a"},
  10592. {re: /[\xC8-\xCB]/g, ch: "E"},
  10593. {re: /[\xE8-\xEB]/g, ch: "e"},
  10594. {re: /[\xCC-\xCF]/g, ch: "I"},
  10595. {re: /[\xEC-\xEF]/g, ch: "i"},
  10596. {re: /[\xD2-\xD6]/g, ch: "O"},
  10597. {re: /[\xF2-\xF6]/g, ch: "o"},
  10598. {re: /[\xD9-\xDC]/g, ch: "U"},
  10599. {re: /[\xF9-\xFC]/g, ch: "u"},
  10600. {re: /[\xC7-\xE7]/g, ch: "c"},
  10601. {re: /[\xD1]/g, ch: "N"},
  10602. {re: /[\xF1]/g, ch: "n"}
  10603. ];
  10604. $.each(rExps, function () {
  10605. text = text ? text.replace(this.re, this.ch) : '';
  10606. });
  10607. return text;
  10608. }
  10609. // List of HTML entities for escaping.
  10610. var escapeMap = {
  10611. '&': '&amp;',
  10612. '<': '&lt;',
  10613. '>': '&gt;',
  10614. '"': '&quot;',
  10615. "'": '&#x27;',
  10616. '`': '&#x60;'
  10617. };
  10618. var unescapeMap = {
  10619. '&amp;': '&',
  10620. '&lt;': '<',
  10621. '&gt;': '>',
  10622. '&quot;': '"',
  10623. '&#x27;': "'",
  10624. '&#x60;': '`'
  10625. };
  10626. // Functions for escaping and unescaping strings to/from HTML interpolation.
  10627. var createEscaper = function(map) {
  10628. var escaper = function(match) {
  10629. return map[match];
  10630. };
  10631. // Regexes for identifying a key that needs to be escaped.
  10632. var source = '(?:' + Object.keys(map).join('|') + ')';
  10633. var testRegexp = RegExp(source);
  10634. var replaceRegexp = RegExp(source, 'g');
  10635. return function(string) {
  10636. string = string == null ? '' : '' + string;
  10637. return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
  10638. };
  10639. };
  10640. var htmlEscape = createEscaper(escapeMap);
  10641. var htmlUnescape = createEscaper(unescapeMap);
  10642. var Selectpicker = function (element, options) {
  10643. // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
  10644. if (!valHooks.useDefault) {
  10645. $.valHooks.select.set = valHooks._set;
  10646. valHooks.useDefault = true;
  10647. }
  10648. this.$element = $(element);
  10649. this.$newElement = null;
  10650. this.$button = null;
  10651. this.$menu = null;
  10652. this.$lis = null;
  10653. this.options = options;
  10654. // 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
  10655. // data-attribute)
  10656. if (this.options.title === null) {
  10657. this.options.title = this.$element.attr('title');
  10658. }
  10659. // Format window padding
  10660. var winPad = this.options.windowPadding;
  10661. if (typeof winPad === 'number') {
  10662. this.options.windowPadding = [winPad, winPad, winPad, winPad];
  10663. }
  10664. //Expose public methods
  10665. this.val = Selectpicker.prototype.val;
  10666. this.render = Selectpicker.prototype.render;
  10667. this.refresh = Selectpicker.prototype.refresh;
  10668. this.setStyle = Selectpicker.prototype.setStyle;
  10669. this.selectAll = Selectpicker.prototype.selectAll;
  10670. this.deselectAll = Selectpicker.prototype.deselectAll;
  10671. this.destroy = Selectpicker.prototype.destroy;
  10672. this.remove = Selectpicker.prototype.remove;
  10673. this.show = Selectpicker.prototype.show;
  10674. this.hide = Selectpicker.prototype.hide;
  10675. this.init();
  10676. };
  10677. Selectpicker.VERSION = '1.12.4';
  10678. // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
  10679. Selectpicker.DEFAULTS = {
  10680. noneSelectedText: 'Nothing selected',
  10681. noneResultsText: 'No results matched {0}',
  10682. countSelectedText: function (numSelected, numTotal) {
  10683. return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
  10684. },
  10685. maxOptionsText: function (numAll, numGroup) {
  10686. return [
  10687. (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
  10688. (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
  10689. ];
  10690. },
  10691. selectAllText: 'Select All',
  10692. deselectAllText: 'Deselect All',
  10693. doneButton: false,
  10694. doneButtonText: 'Close',
  10695. multipleSeparator: ', ',
  10696. styleBase: 'btn',
  10697. style: 'btn-default',
  10698. size: 'auto',
  10699. title: null,
  10700. selectedTextFormat: 'values',
  10701. width: false,
  10702. container: false,
  10703. hideDisabled: false,
  10704. showSubtext: false,
  10705. showIcon: true,
  10706. showContent: true,
  10707. dropupAuto: true,
  10708. header: false,
  10709. liveSearch: false,
  10710. liveSearchPlaceholder: null,
  10711. liveSearchNormalize: false,
  10712. liveSearchStyle: 'contains',
  10713. actionsBox: false,
  10714. iconBase: 'glyphicon',
  10715. tickIcon: 'glyphicon-ok',
  10716. showTick: false,
  10717. template: {
  10718. caret: '<span class="caret"></span>'
  10719. },
  10720. maxOptions: false,
  10721. mobile: false,
  10722. selectOnTab: false,
  10723. dropdownAlignRight: false,
  10724. windowPadding: 0
  10725. };
  10726. Selectpicker.prototype = {
  10727. constructor: Selectpicker,
  10728. init: function () {
  10729. var that = this,
  10730. id = this.$element.attr('id');
  10731. this.$element.addClass('bs-select-hidden');
  10732. // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
  10733. // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
  10734. this.liObj = {};
  10735. this.multiple = this.$element.prop('multiple');
  10736. this.autofocus = this.$element.prop('autofocus');
  10737. this.$newElement = this.createView();
  10738. this.$element
  10739. .after(this.$newElement)
  10740. .appendTo(this.$newElement);
  10741. this.$button = this.$newElement.children('button');
  10742. this.$menu = this.$newElement.children('.dropdown-menu');
  10743. this.$menuInner = this.$menu.children('.inner');
  10744. this.$searchbox = this.$menu.find('input');
  10745. this.$element.removeClass('bs-select-hidden');
  10746. if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
  10747. if (typeof id !== 'undefined') {
  10748. this.$button.attr('data-id', id);
  10749. $('label[for="' + id + '"]').click(function (e) {
  10750. e.preventDefault();
  10751. that.$button.focus();
  10752. });
  10753. }
  10754. this.checkDisabled();
  10755. this.clickListener();
  10756. if (this.options.liveSearch) this.liveSearchListener();
  10757. this.render();
  10758. this.setStyle();
  10759. this.setWidth();
  10760. if (this.options.container) this.selectPosition();
  10761. this.$menu.data('this', this);
  10762. this.$newElement.data('this', this);
  10763. if (this.options.mobile) this.mobile();
  10764. this.$newElement.on({
  10765. 'hide.bs.dropdown': function (e) {
  10766. that.$menuInner.attr('aria-expanded', false);
  10767. that.$element.trigger('hide.bs.select', e);
  10768. },
  10769. 'hidden.bs.dropdown': function (e) {
  10770. that.$element.trigger('hidden.bs.select', e);
  10771. },
  10772. 'show.bs.dropdown': function (e) {
  10773. that.$menuInner.attr('aria-expanded', true);
  10774. that.$element.trigger('show.bs.select', e);
  10775. },
  10776. 'shown.bs.dropdown': function (e) {
  10777. that.$element.trigger('shown.bs.select', e);
  10778. }
  10779. });
  10780. if (that.$element[0].hasAttribute('required')) {
  10781. this.$element.on('invalid', function () {
  10782. that.$button.addClass('bs-invalid');
  10783. that.$element.on({
  10784. 'focus.bs.select': function () {
  10785. that.$button.focus();
  10786. that.$element.off('focus.bs.select');
  10787. },
  10788. 'shown.bs.select': function () {
  10789. that.$element
  10790. .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
  10791. .off('shown.bs.select');
  10792. },
  10793. 'rendered.bs.select': function () {
  10794. // if select is no longer invalid, remove the bs-invalid class
  10795. if (this.validity.valid) that.$button.removeClass('bs-invalid');
  10796. that.$element.off('rendered.bs.select');
  10797. }
  10798. });
  10799. that.$button.on('blur.bs.select', function() {
  10800. that.$element.focus().blur();
  10801. that.$button.off('blur.bs.select');
  10802. });
  10803. });
  10804. }
  10805. setTimeout(function () {
  10806. that.$element.trigger('loaded.bs.select');
  10807. });
  10808. },
  10809. createDropdown: function () {
  10810. // Options
  10811. // If we are multiple or showTick option is set, then add the show-tick class
  10812. var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
  10813. inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
  10814. autofocus = this.autofocus ? ' autofocus' : '';
  10815. // Elements
  10816. var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
  10817. var searchbox = this.options.liveSearch ?
  10818. '<div class="bs-searchbox">' +
  10819. '<input type="text" class="form-control" autocomplete="off"' +
  10820. (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
  10821. '</div>'
  10822. : '';
  10823. var actionsbox = this.multiple && this.options.actionsBox ?
  10824. '<div class="bs-actionsbox">' +
  10825. '<div class="btn-group btn-group-sm btn-block">' +
  10826. '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
  10827. this.options.selectAllText +
  10828. '</button>' +
  10829. '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
  10830. this.options.deselectAllText +
  10831. '</button>' +
  10832. '</div>' +
  10833. '</div>'
  10834. : '';
  10835. var donebutton = this.multiple && this.options.doneButton ?
  10836. '<div class="bs-donebutton">' +
  10837. '<div class="btn-group btn-block">' +
  10838. '<button type="button" class="btn btn-sm btn-default">' +
  10839. this.options.doneButtonText +
  10840. '</button>' +
  10841. '</div>' +
  10842. '</div>'
  10843. : '';
  10844. var drop =
  10845. '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
  10846. '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
  10847. '<span class="filter-option pull-left"></span>&nbsp;' +
  10848. '<span class="bs-caret">' +
  10849. this.options.template.caret +
  10850. '</span>' +
  10851. '</button>' +
  10852. '<div class="dropdown-menu open" role="combobox">' +
  10853. header +
  10854. searchbox +
  10855. actionsbox +
  10856. '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
  10857. '</ul>' +
  10858. donebutton +
  10859. '</div>' +
  10860. '</div>';
  10861. return $(drop);
  10862. },
  10863. createView: function () {
  10864. var $drop = this.createDropdown(),
  10865. li = this.createLi();
  10866. $drop.find('ul')[0].innerHTML = li;
  10867. return $drop;
  10868. },
  10869. reloadLi: function () {
  10870. // rebuild
  10871. var li = this.createLi();
  10872. this.$menuInner[0].innerHTML = li;
  10873. },
  10874. createLi: function () {
  10875. var that = this,
  10876. _li = [],
  10877. optID = 0,
  10878. titleOption = document.createElement('option'),
  10879. liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
  10880. // Helper functions
  10881. /**
  10882. * @param content
  10883. * @param [index]
  10884. * @param [classes]
  10885. * @param [optgroup]
  10886. * @returns {string}
  10887. */
  10888. var generateLI = function (content, index, classes, optgroup) {
  10889. return '<li' +
  10890. ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
  10891. ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
  10892. ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
  10893. '>' + content + '</li>';
  10894. };
  10895. /**
  10896. * @param text
  10897. * @param [classes]
  10898. * @param [inline]
  10899. * @param [tokens]
  10900. * @returns {string}
  10901. */
  10902. var generateA = function (text, classes, inline, tokens) {
  10903. return '<a tabindex="0"' +
  10904. (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
  10905. (inline ? ' style="' + inline + '"' : '') +
  10906. (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
  10907. (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
  10908. ' role="option">' + text +
  10909. '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
  10910. '</a>';
  10911. };
  10912. if (this.options.title && !this.multiple) {
  10913. // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
  10914. // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
  10915. liIndex--;
  10916. if (!this.$element.find('.bs-title-option').length) {
  10917. // Use native JS to prepend option (faster)
  10918. var element = this.$element[0];
  10919. titleOption.className = 'bs-title-option';
  10920. titleOption.innerHTML = this.options.title;
  10921. titleOption.value = '';
  10922. element.insertBefore(titleOption, element.firstChild);
  10923. // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
  10924. // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
  10925. // if so, the select will have the data-selected attribute
  10926. var $opt = $(element.options[element.selectedIndex]);
  10927. if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
  10928. titleOption.selected = true;
  10929. }
  10930. }
  10931. }
  10932. var $selectOptions = this.$element.find('option');
  10933. $selectOptions.each(function (index) {
  10934. var $this = $(this);
  10935. liIndex++;
  10936. if ($this.hasClass('bs-title-option')) return;
  10937. // Get the class and text for the option
  10938. var optionClass = this.className || '',
  10939. inline = htmlEscape(this.style.cssText),
  10940. text = $this.data('content') ? $this.data('content') : $this.html(),
  10941. tokens = $this.data('tokens') ? $this.data('tokens') : null,
  10942. subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
  10943. icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
  10944. $parent = $this.parent(),
  10945. isOptgroup = $parent[0].tagName === 'OPTGROUP',
  10946. isOptgroupDisabled = isOptgroup && $parent[0].disabled,
  10947. isDisabled = this.disabled || isOptgroupDisabled,
  10948. prevHiddenIndex;
  10949. if (icon !== '' && isDisabled) {
  10950. icon = '<span>' + icon + '</span>';
  10951. }
  10952. if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
  10953. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  10954. // used to determine whether or not a divider should be placed after an optgroup if there are
  10955. // hidden options between the optgroup and the first visible option
  10956. prevHiddenIndex = $this.data('prevHiddenIndex');
  10957. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  10958. liIndex--;
  10959. return;
  10960. }
  10961. if (!$this.data('content')) {
  10962. // Prepend any icon and append any subtext to the main text.
  10963. text = icon + '<span class="text">' + text + subtext + '</span>';
  10964. }
  10965. if (isOptgroup && $this.data('divider') !== true) {
  10966. if (that.options.hideDisabled && isDisabled) {
  10967. if ($parent.data('allOptionsDisabled') === undefined) {
  10968. var $options = $parent.children();
  10969. $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
  10970. }
  10971. if ($parent.data('allOptionsDisabled')) {
  10972. liIndex--;
  10973. return;
  10974. }
  10975. }
  10976. var optGroupClass = ' ' + $parent[0].className || '';
  10977. if ($this.index() === 0) { // Is it the first option of the optgroup?
  10978. optID += 1;
  10979. // Get the opt group label
  10980. var label = $parent[0].label,
  10981. labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
  10982. labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
  10983. label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
  10984. if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
  10985. liIndex++;
  10986. _li.push(generateLI('', null, 'divider', optID + 'div'));
  10987. }
  10988. liIndex++;
  10989. _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
  10990. }
  10991. if (that.options.hideDisabled && isDisabled) {
  10992. liIndex--;
  10993. return;
  10994. }
  10995. _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
  10996. } else if ($this.data('divider') === true) {
  10997. _li.push(generateLI('', index, 'divider'));
  10998. } else if ($this.data('hidden') === true) {
  10999. // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
  11000. // used to determine whether or not a divider should be placed after an optgroup if there are
  11001. // hidden options between the optgroup and the first visible option
  11002. prevHiddenIndex = $this.data('prevHiddenIndex');
  11003. $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
  11004. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
  11005. } else {
  11006. var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
  11007. // if previous element is not an optgroup and hideDisabled is true
  11008. if (!showDivider && that.options.hideDisabled) {
  11009. prevHiddenIndex = $this.data('prevHiddenIndex');
  11010. if (prevHiddenIndex !== undefined) {
  11011. // select the element **before** the first hidden element in the group
  11012. var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
  11013. if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
  11014. showDivider = true;
  11015. }
  11016. }
  11017. }
  11018. if (showDivider) {
  11019. liIndex++;
  11020. _li.push(generateLI('', null, 'divider', optID + 'div'));
  11021. }
  11022. _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
  11023. }
  11024. that.liObj[index] = liIndex;
  11025. });
  11026. //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
  11027. if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
  11028. this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
  11029. }
  11030. return _li.join('');
  11031. },
  11032. findLis: function () {
  11033. if (this.$lis == null) this.$lis = this.$menu.find('li');
  11034. return this.$lis;
  11035. },
  11036. /**
  11037. * @param [updateLi] defaults to true
  11038. */
  11039. render: function (updateLi) {
  11040. var that = this,
  11041. notDisabled,
  11042. $selectOptions = this.$element.find('option');
  11043. //Update the LI to match the SELECT
  11044. if (updateLi !== false) {
  11045. $selectOptions.each(function (index) {
  11046. var $lis = that.findLis().eq(that.liObj[index]);
  11047. that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
  11048. that.setSelected(index, this.selected, $lis);
  11049. });
  11050. }
  11051. this.togglePlaceholder();
  11052. this.tabIndex();
  11053. var selectedItems = $selectOptions.map(function () {
  11054. if (this.selected) {
  11055. if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
  11056. var $this = $(this),
  11057. icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
  11058. subtext;
  11059. if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
  11060. subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
  11061. } else {
  11062. subtext = '';
  11063. }
  11064. if (typeof $this.attr('title') !== 'undefined') {
  11065. return $this.attr('title');
  11066. } else if ($this.data('content') && that.options.showContent) {
  11067. return $this.data('content').toString();
  11068. } else {
  11069. return icon + $this.html() + subtext;
  11070. }
  11071. }
  11072. }).toArray();
  11073. //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
  11074. //Convert all the values into a comma delimited string
  11075. var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
  11076. //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
  11077. if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
  11078. var max = this.options.selectedTextFormat.split('>');
  11079. if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
  11080. notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
  11081. var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
  11082. tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
  11083. title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
  11084. }
  11085. }
  11086. if (this.options.title == undefined) {
  11087. this.options.title = this.$element.attr('title');
  11088. }
  11089. if (this.options.selectedTextFormat == 'static') {
  11090. title = this.options.title;
  11091. }
  11092. //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
  11093. if (!title) {
  11094. title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
  11095. }
  11096. //strip all HTML tags and trim the result, then unescape any escaped tags
  11097. this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
  11098. this.$button.children('.filter-option').html(title);
  11099. this.$element.trigger('rendered.bs.select');
  11100. },
  11101. /**
  11102. * @param [style]
  11103. * @param [status]
  11104. */
  11105. setStyle: function (style, status) {
  11106. if (this.$element.attr('class')) {
  11107. this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
  11108. }
  11109. var buttonClass = style ? style : this.options.style;
  11110. if (status == 'add') {
  11111. this.$button.addClass(buttonClass);
  11112. } else if (status == 'remove') {
  11113. this.$button.removeClass(buttonClass);
  11114. } else {
  11115. this.$button.removeClass(this.options.style);
  11116. this.$button.addClass(buttonClass);
  11117. }
  11118. },
  11119. liHeight: function (refresh) {
  11120. if (!refresh && (this.options.size === false || this.sizeInfo)) return;
  11121. var newElement = document.createElement('div'),
  11122. menu = document.createElement('div'),
  11123. menuInner = document.createElement('ul'),
  11124. divider = document.createElement('li'),
  11125. li = document.createElement('li'),
  11126. a = document.createElement('a'),
  11127. text = document.createElement('span'),
  11128. header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
  11129. search = this.options.liveSearch ? document.createElement('div') : null,
  11130. actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
  11131. doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
  11132. text.className = 'text';
  11133. newElement.className = this.$menu[0].parentNode.className + ' open';
  11134. menu.className = 'dropdown-menu open';
  11135. menuInner.className = 'dropdown-menu inner';
  11136. divider.className = 'divider';
  11137. text.appendChild(document.createTextNode('Inner text'));
  11138. a.appendChild(text);
  11139. li.appendChild(a);
  11140. menuInner.appendChild(li);
  11141. menuInner.appendChild(divider);
  11142. if (header) menu.appendChild(header);
  11143. if (search) {
  11144. var input = document.createElement('input');
  11145. search.className = 'bs-searchbox';
  11146. input.className = 'form-control';
  11147. search.appendChild(input);
  11148. menu.appendChild(search);
  11149. }
  11150. if (actions) menu.appendChild(actions);
  11151. menu.appendChild(menuInner);
  11152. if (doneButton) menu.appendChild(doneButton);
  11153. newElement.appendChild(menu);
  11154. document.body.appendChild(newElement);
  11155. var liHeight = a.offsetHeight,
  11156. headerHeight = header ? header.offsetHeight : 0,
  11157. searchHeight = search ? search.offsetHeight : 0,
  11158. actionsHeight = actions ? actions.offsetHeight : 0,
  11159. doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
  11160. dividerHeight = $(divider).outerHeight(true),
  11161. // fall back to jQuery if getComputedStyle is not supported
  11162. menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
  11163. $menu = menuStyle ? null : $(menu),
  11164. menuPadding = {
  11165. vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
  11166. parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
  11167. parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
  11168. parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
  11169. horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
  11170. parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
  11171. parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
  11172. parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
  11173. },
  11174. menuExtras = {
  11175. vert: menuPadding.vert +
  11176. parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
  11177. parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
  11178. horiz: menuPadding.horiz +
  11179. parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
  11180. parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
  11181. }
  11182. document.body.removeChild(newElement);
  11183. this.sizeInfo = {
  11184. liHeight: liHeight,
  11185. headerHeight: headerHeight,
  11186. searchHeight: searchHeight,
  11187. actionsHeight: actionsHeight,
  11188. doneButtonHeight: doneButtonHeight,
  11189. dividerHeight: dividerHeight,
  11190. menuPadding: menuPadding,
  11191. menuExtras: menuExtras
  11192. };
  11193. },
  11194. setSize: function () {
  11195. this.findLis();
  11196. this.liHeight();
  11197. if (this.options.header) this.$menu.css('padding-top', 0);
  11198. if (this.options.size === false) return;
  11199. var that = this,
  11200. $menu = this.$menu,
  11201. $menuInner = this.$menuInner,
  11202. $window = $(window),
  11203. selectHeight = this.$newElement[0].offsetHeight,
  11204. selectWidth = this.$newElement[0].offsetWidth,
  11205. liHeight = this.sizeInfo['liHeight'],
  11206. headerHeight = this.sizeInfo['headerHeight'],
  11207. searchHeight = this.sizeInfo['searchHeight'],
  11208. actionsHeight = this.sizeInfo['actionsHeight'],
  11209. doneButtonHeight = this.sizeInfo['doneButtonHeight'],
  11210. divHeight = this.sizeInfo['dividerHeight'],
  11211. menuPadding = this.sizeInfo['menuPadding'],
  11212. menuExtras = this.sizeInfo['menuExtras'],
  11213. notDisabled = this.options.hideDisabled ? '.disabled' : '',
  11214. menuHeight,
  11215. menuWidth,
  11216. getHeight,
  11217. getWidth,
  11218. selectOffsetTop,
  11219. selectOffsetBot,
  11220. selectOffsetLeft,
  11221. selectOffsetRight,
  11222. getPos = function() {
  11223. var pos = that.$newElement.offset(),
  11224. $container = $(that.options.container),
  11225. containerPos;
  11226. if (that.options.container && !$container.is('body')) {
  11227. containerPos = $container.offset();
  11228. containerPos.top += parseInt($container.css('borderTopWidth'));
  11229. containerPos.left += parseInt($container.css('borderLeftWidth'));
  11230. } else {
  11231. containerPos = { top: 0, left: 0 };
  11232. }
  11233. var winPad = that.options.windowPadding;
  11234. selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
  11235. selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
  11236. selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
  11237. selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
  11238. selectOffsetTop -= winPad[0];
  11239. selectOffsetLeft -= winPad[3];
  11240. };
  11241. getPos();
  11242. if (this.options.size === 'auto') {
  11243. var getSize = function () {
  11244. var minHeight,
  11245. hasClass = function (className, include) {
  11246. return function (element) {
  11247. if (include) {
  11248. return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  11249. } else {
  11250. return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
  11251. }
  11252. };
  11253. },
  11254. lis = that.$menuInner[0].getElementsByTagName('li'),
  11255. lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
  11256. optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
  11257. getPos();
  11258. menuHeight = selectOffsetBot - menuExtras.vert;
  11259. menuWidth = selectOffsetRight - menuExtras.horiz;
  11260. if (that.options.container) {
  11261. if (!$menu.data('height')) $menu.data('height', $menu.height());
  11262. getHeight = $menu.data('height');
  11263. if (!$menu.data('width')) $menu.data('width', $menu.width());
  11264. getWidth = $menu.data('width');
  11265. } else {
  11266. getHeight = $menu.height();
  11267. getWidth = $menu.width();
  11268. }
  11269. if (that.options.dropupAuto) {
  11270. that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  11271. }
  11272. if (that.$newElement.hasClass('dropup')) {
  11273. menuHeight = selectOffsetTop - menuExtras.vert;
  11274. }
  11275. if (that.options.dropdownAlignRight === 'auto') {
  11276. $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
  11277. }
  11278. if ((lisVisible.length + optGroup.length) > 3) {
  11279. minHeight = liHeight * 3 + menuExtras.vert - 2;
  11280. } else {
  11281. minHeight = 0;
  11282. }
  11283. $menu.css({
  11284. 'max-height': menuHeight + 'px',
  11285. 'overflow': 'hidden',
  11286. 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
  11287. });
  11288. $menuInner.css({
  11289. 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
  11290. 'overflow-y': 'auto',
  11291. 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
  11292. });
  11293. };
  11294. getSize();
  11295. this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
  11296. $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
  11297. } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
  11298. var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
  11299. divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
  11300. menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
  11301. if (that.options.container) {
  11302. if (!$menu.data('height')) $menu.data('height', $menu.height());
  11303. getHeight = $menu.data('height');
  11304. } else {
  11305. getHeight = $menu.height();
  11306. }
  11307. if (that.options.dropupAuto) {
  11308. //noinspection JSUnusedAssignment
  11309. this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
  11310. }
  11311. $menu.css({
  11312. 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
  11313. 'overflow': 'hidden',
  11314. 'min-height': ''
  11315. });
  11316. $menuInner.css({
  11317. 'max-height': menuHeight - menuPadding.vert + 'px',
  11318. 'overflow-y': 'auto',
  11319. 'min-height': ''
  11320. });
  11321. }
  11322. },
  11323. setWidth: function () {
  11324. if (this.options.width === 'auto') {
  11325. this.$menu.css('min-width', '0');
  11326. // Get correct width if element is hidden
  11327. var $selectClone = this.$menu.parent().clone().appendTo('body'),
  11328. $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
  11329. ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
  11330. btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
  11331. $selectClone.remove();
  11332. $selectClone2.remove();
  11333. // Set width to whatever's larger, button title or longest option
  11334. this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
  11335. } else if (this.options.width === 'fit') {
  11336. // Remove inline min-width so width can be changed from 'auto'
  11337. this.$menu.css('min-width', '');
  11338. this.$newElement.css('width', '').addClass('fit-width');
  11339. } else if (this.options.width) {
  11340. // Remove inline min-width so width can be changed from 'auto'
  11341. this.$menu.css('min-width', '');
  11342. this.$newElement.css('width', this.options.width);
  11343. } else {
  11344. // Remove inline min-width/width so width can be changed
  11345. this.$menu.css('min-width', '');
  11346. this.$newElement.css('width', '');
  11347. }
  11348. // Remove fit-width class if width is changed programmatically
  11349. if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
  11350. this.$newElement.removeClass('fit-width');
  11351. }
  11352. },
  11353. selectPosition: function () {
  11354. this.$bsContainer = $('<div class="bs-container" />');
  11355. var that = this,
  11356. $container = $(this.options.container),
  11357. pos,
  11358. containerPos,
  11359. actualHeight,
  11360. getPlacement = function ($element) {
  11361. that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
  11362. pos = $element.offset();
  11363. if (!$container.is('body')) {
  11364. containerPos = $container.offset();
  11365. containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
  11366. containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
  11367. } else {
  11368. containerPos = { top: 0, left: 0 };
  11369. }
  11370. actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
  11371. that.$bsContainer.css({
  11372. 'top': pos.top - containerPos.top + actualHeight,
  11373. 'left': pos.left - containerPos.left,
  11374. 'width': $element[0].offsetWidth
  11375. });
  11376. };
  11377. this.$button.on('click', function () {
  11378. var $this = $(this);
  11379. if (that.isDisabled()) {
  11380. return;
  11381. }
  11382. getPlacement(that.$newElement);
  11383. that.$bsContainer
  11384. .appendTo(that.options.container)
  11385. .toggleClass('open', !$this.hasClass('open'))
  11386. .append(that.$menu);
  11387. });
  11388. $(window).on('resize scroll', function () {
  11389. getPlacement(that.$newElement);
  11390. });
  11391. this.$element.on('hide.bs.select', function () {
  11392. that.$menu.data('height', that.$menu.height());
  11393. that.$bsContainer.detach();
  11394. });
  11395. },
  11396. /**
  11397. * @param {number} index - the index of the option that is being changed
  11398. * @param {boolean} selected - true if the option is being selected, false if being deselected
  11399. * @param {JQuery} $lis - the 'li' element that is being modified
  11400. */
  11401. setSelected: function (index, selected, $lis) {
  11402. if (!$lis) {
  11403. this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
  11404. $lis = this.findLis().eq(this.liObj[index]);
  11405. }
  11406. $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
  11407. },
  11408. /**
  11409. * @param {number} index - the index of the option that is being disabled
  11410. * @param {boolean} disabled - true if the option is being disabled, false if being enabled
  11411. * @param {JQuery} $lis - the 'li' element that is being modified
  11412. */
  11413. setDisabled: function (index, disabled, $lis) {
  11414. if (!$lis) {
  11415. $lis = this.findLis().eq(this.liObj[index]);
  11416. }
  11417. if (disabled) {
  11418. $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
  11419. } else {
  11420. $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
  11421. }
  11422. },
  11423. isDisabled: function () {
  11424. return this.$element[0].disabled;
  11425. },
  11426. checkDisabled: function () {
  11427. var that = this;
  11428. if (this.isDisabled()) {
  11429. this.$newElement.addClass('disabled');
  11430. this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
  11431. } else {
  11432. if (this.$button.hasClass('disabled')) {
  11433. this.$newElement.removeClass('disabled');
  11434. this.$button.removeClass('disabled').attr('aria-disabled', false);
  11435. }
  11436. if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
  11437. this.$button.removeAttr('tabindex');
  11438. }
  11439. }
  11440. this.$button.click(function () {
  11441. return !that.isDisabled();
  11442. });
  11443. },
  11444. togglePlaceholder: function () {
  11445. var value = this.$element.val();
  11446. this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
  11447. },
  11448. tabIndex: function () {
  11449. if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
  11450. (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
  11451. this.$element.data('tabindex', this.$element.attr('tabindex'));
  11452. this.$button.attr('tabindex', this.$element.data('tabindex'));
  11453. }
  11454. this.$element.attr('tabindex', -98);
  11455. },
  11456. clickListener: function () {
  11457. var that = this,
  11458. $document = $(document);
  11459. $document.data('spaceSelect', false);
  11460. this.$button.on('keyup', function (e) {
  11461. if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
  11462. e.preventDefault();
  11463. $document.data('spaceSelect', false);
  11464. }
  11465. });
  11466. this.$button.on('click', function () {
  11467. that.setSize();
  11468. });
  11469. this.$element.on('shown.bs.select', function () {
  11470. if (!that.options.liveSearch && !that.multiple) {
  11471. that.$menuInner.find('.selected a').focus();
  11472. } else if (!that.multiple) {
  11473. var selectedIndex = that.liObj[that.$element[0].selectedIndex];
  11474. if (typeof selectedIndex !== 'number' || that.options.size === false) return;
  11475. // scroll to selected option
  11476. var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
  11477. offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
  11478. that.$menuInner[0].scrollTop = offset;
  11479. }
  11480. });
  11481. this.$menuInner.on('click', 'li a', function (e) {
  11482. var $this = $(this),
  11483. clickedIndex = $this.parent().data('originalIndex'),
  11484. prevValue = that.$element.val(),
  11485. prevIndex = that.$element.prop('selectedIndex'),
  11486. triggerChange = true;
  11487. // Don't close on multi choice menu
  11488. if (that.multiple && that.options.maxOptions !== 1) {
  11489. e.stopPropagation();
  11490. }
  11491. e.preventDefault();
  11492. //Don't run if we have been disabled
  11493. if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
  11494. var $options = that.$element.find('option'),
  11495. $option = $options.eq(clickedIndex),
  11496. state = $option.prop('selected'),
  11497. $optgroup = $option.parent('optgroup'),
  11498. maxOptions = that.options.maxOptions,
  11499. maxOptionsGrp = $optgroup.data('maxOptions') || false;
  11500. if (!that.multiple) { // Deselect all others if not multi select box
  11501. $options.prop('selected', false);
  11502. $option.prop('selected', true);
  11503. that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
  11504. that.setSelected(clickedIndex, true);
  11505. } else { // Toggle the one we have chosen if we are multi select.
  11506. $option.prop('selected', !state);
  11507. that.setSelected(clickedIndex, !state);
  11508. $this.blur();
  11509. if (maxOptions !== false || maxOptionsGrp !== false) {
  11510. var maxReached = maxOptions < $options.filter(':selected').length,
  11511. maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
  11512. if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
  11513. if (maxOptions && maxOptions == 1) {
  11514. $options.prop('selected', false);
  11515. $option.prop('selected', true);
  11516. that.$menuInner.find('.selected').removeClass('selected');
  11517. that.setSelected(clickedIndex, true);
  11518. } else if (maxOptionsGrp && maxOptionsGrp == 1) {
  11519. $optgroup.find('option:selected').prop('selected', false);
  11520. $option.prop('selected', true);
  11521. var optgroupID = $this.parent().data('optgroup');
  11522. that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
  11523. that.setSelected(clickedIndex, true);
  11524. } else {
  11525. var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
  11526. maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
  11527. maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
  11528. maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
  11529. $notify = $('<div class="notify"></div>');
  11530. // If {var} is set in array, replace it
  11531. /** @deprecated */
  11532. if (maxOptionsArr[2]) {
  11533. maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
  11534. maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
  11535. }
  11536. $option.prop('selected', false);
  11537. that.$menu.append($notify);
  11538. if (maxOptions && maxReached) {
  11539. $notify.append($('<div>' + maxTxt + '</div>'));
  11540. triggerChange = false;
  11541. that.$element.trigger('maxReached.bs.select');
  11542. }
  11543. if (maxOptionsGrp && maxReachedGrp) {
  11544. $notify.append($('<div>' + maxTxtGrp + '</div>'));
  11545. triggerChange = false;
  11546. that.$element.trigger('maxReachedGrp.bs.select');
  11547. }
  11548. setTimeout(function () {
  11549. that.setSelected(clickedIndex, false);
  11550. }, 10);
  11551. $notify.delay(750).fadeOut(300, function () {
  11552. $(this).remove();
  11553. });
  11554. }
  11555. }
  11556. }
  11557. }
  11558. if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
  11559. that.$button.focus();
  11560. } else if (that.options.liveSearch) {
  11561. that.$searchbox.focus();
  11562. }
  11563. // Trigger select 'change'
  11564. if (triggerChange) {
  11565. if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
  11566. // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
  11567. changed_arguments = [clickedIndex, $option.prop('selected'), state];
  11568. that.$element
  11569. .triggerNative('change');
  11570. }
  11571. }
  11572. }
  11573. });
  11574. this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
  11575. if (e.currentTarget == this) {
  11576. e.preventDefault();
  11577. e.stopPropagation();
  11578. if (that.options.liveSearch && !$(e.target).hasClass('close')) {
  11579. that.$searchbox.focus();
  11580. } else {
  11581. that.$button.focus();
  11582. }
  11583. }
  11584. });
  11585. this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
  11586. e.preventDefault();
  11587. e.stopPropagation();
  11588. if (that.options.liveSearch) {
  11589. that.$searchbox.focus();
  11590. } else {
  11591. that.$button.focus();
  11592. }
  11593. });
  11594. this.$menu.on('click', '.popover-title .close', function () {
  11595. that.$button.click();
  11596. });
  11597. this.$searchbox.on('click', function (e) {
  11598. e.stopPropagation();
  11599. });
  11600. this.$menu.on('click', '.actions-btn', function (e) {
  11601. if (that.options.liveSearch) {
  11602. that.$searchbox.focus();
  11603. } else {
  11604. that.$button.focus();
  11605. }
  11606. e.preventDefault();
  11607. e.stopPropagation();
  11608. if ($(this).hasClass('bs-select-all')) {
  11609. that.selectAll();
  11610. } else {
  11611. that.deselectAll();
  11612. }
  11613. });
  11614. this.$element.change(function () {
  11615. that.render(false);
  11616. that.$element.trigger('changed.bs.select', changed_arguments);
  11617. changed_arguments = null;
  11618. });
  11619. },
  11620. liveSearchListener: function () {
  11621. var that = this,
  11622. $no_results = $('<li class="no-results"></li>');
  11623. this.$button.on('click.dropdown.data-api', function () {
  11624. that.$menuInner.find('.active').removeClass('active');
  11625. if (!!that.$searchbox.val()) {
  11626. that.$searchbox.val('');
  11627. that.$lis.not('.is-hidden').removeClass('hidden');
  11628. if (!!$no_results.parent().length) $no_results.remove();
  11629. }
  11630. if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
  11631. setTimeout(function () {
  11632. that.$searchbox.focus();
  11633. }, 10);
  11634. });
  11635. this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
  11636. e.stopPropagation();
  11637. });
  11638. this.$searchbox.on('input propertychange', function () {
  11639. that.$lis.not('.is-hidden').removeClass('hidden');
  11640. that.$lis.filter('.active').removeClass('active');
  11641. $no_results.remove();
  11642. if (that.$searchbox.val()) {
  11643. var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
  11644. $hideItems;
  11645. if (that.options.liveSearchNormalize) {
  11646. $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
  11647. } else {
  11648. $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
  11649. }
  11650. if ($hideItems.length === $searchBase.length) {
  11651. $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
  11652. that.$menuInner.append($no_results);
  11653. that.$lis.addClass('hidden');
  11654. } else {
  11655. $hideItems.addClass('hidden');
  11656. var $lisVisible = that.$lis.not('.hidden'),
  11657. $foundDiv;
  11658. // hide divider if first or last visible, or if followed by another divider
  11659. $lisVisible.each(function (index) {
  11660. var $this = $(this);
  11661. if ($this.hasClass('divider')) {
  11662. if ($foundDiv === undefined) {
  11663. $this.addClass('hidden');
  11664. } else {
  11665. if ($foundDiv) $foundDiv.addClass('hidden');
  11666. $foundDiv = $this;
  11667. }
  11668. } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
  11669. $this.addClass('hidden');
  11670. } else {
  11671. $foundDiv = null;
  11672. }
  11673. });
  11674. if ($foundDiv) $foundDiv.addClass('hidden');
  11675. $searchBase.not('.hidden').first().addClass('active');
  11676. that.$menuInner.scrollTop(0);
  11677. }
  11678. }
  11679. });
  11680. },
  11681. _searchStyle: function () {
  11682. var styles = {
  11683. begins: 'ibegins',
  11684. startsWith: 'ibegins'
  11685. };
  11686. return styles[this.options.liveSearchStyle] || 'icontains';
  11687. },
  11688. val: function (value) {
  11689. if (typeof value !== 'undefined') {
  11690. this.$element.val(value);
  11691. this.render();
  11692. return this.$element;
  11693. } else {
  11694. return this.$element.val();
  11695. }
  11696. },
  11697. changeAll: function (status) {
  11698. if (!this.multiple) return;
  11699. if (typeof status === 'undefined') status = true;
  11700. this.findLis();
  11701. var $options = this.$element.find('option'),
  11702. $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
  11703. lisVisLen = $lisVisible.length,
  11704. selectedOptions = [];
  11705. if (status) {
  11706. if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
  11707. } else {
  11708. if ($lisVisible.filter('.selected').length === 0) return;
  11709. }
  11710. $lisVisible.toggleClass('selected', status);
  11711. for (var i = 0; i < lisVisLen; i++) {
  11712. var origIndex = $lisVisible[i].getAttribute('data-original-index');
  11713. selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
  11714. }
  11715. $(selectedOptions).prop('selected', status);
  11716. this.render(false);
  11717. this.togglePlaceholder();
  11718. this.$element
  11719. .triggerNative('change');
  11720. },
  11721. selectAll: function () {
  11722. return this.changeAll(true);
  11723. },
  11724. deselectAll: function () {
  11725. return this.changeAll(false);
  11726. },
  11727. toggle: function (e) {
  11728. e = e || window.event;
  11729. if (e) e.stopPropagation();
  11730. this.$button.trigger('click');
  11731. },
  11732. keydown: function (e) {
  11733. var $this = $(this),
  11734. $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
  11735. $items,
  11736. that = $parent.data('this'),
  11737. index,
  11738. prevIndex,
  11739. isActive,
  11740. selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
  11741. keyCodeMap = {
  11742. 32: ' ',
  11743. 48: '0',
  11744. 49: '1',
  11745. 50: '2',
  11746. 51: '3',
  11747. 52: '4',
  11748. 53: '5',
  11749. 54: '6',
  11750. 55: '7',
  11751. 56: '8',
  11752. 57: '9',
  11753. 59: ';',
  11754. 65: 'a',
  11755. 66: 'b',
  11756. 67: 'c',
  11757. 68: 'd',
  11758. 69: 'e',
  11759. 70: 'f',
  11760. 71: 'g',
  11761. 72: 'h',
  11762. 73: 'i',
  11763. 74: 'j',
  11764. 75: 'k',
  11765. 76: 'l',
  11766. 77: 'm',
  11767. 78: 'n',
  11768. 79: 'o',
  11769. 80: 'p',
  11770. 81: 'q',
  11771. 82: 'r',
  11772. 83: 's',
  11773. 84: 't',
  11774. 85: 'u',
  11775. 86: 'v',
  11776. 87: 'w',
  11777. 88: 'x',
  11778. 89: 'y',
  11779. 90: 'z',
  11780. 96: '0',
  11781. 97: '1',
  11782. 98: '2',
  11783. 99: '3',
  11784. 100: '4',
  11785. 101: '5',
  11786. 102: '6',
  11787. 103: '7',
  11788. 104: '8',
  11789. 105: '9'
  11790. };
  11791. isActive = that.$newElement.hasClass('open');
  11792. if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
  11793. if (!that.options.container) {
  11794. that.setSize();
  11795. that.$menu.parent().addClass('open');
  11796. isActive = true;
  11797. } else {
  11798. that.$button.trigger('click');
  11799. }
  11800. that.$searchbox.focus();
  11801. return;
  11802. }
  11803. if (that.options.liveSearch) {
  11804. if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
  11805. e.preventDefault();
  11806. e.stopPropagation();
  11807. that.$menuInner.click();
  11808. that.$button.focus();
  11809. }
  11810. }
  11811. if (/(38|40)/.test(e.keyCode.toString(10))) {
  11812. $items = that.$lis.filter(selector);
  11813. if (!$items.length) return;
  11814. if (!that.options.liveSearch) {
  11815. index = $items.index($items.find('a').filter(':focus').parent());
  11816. } else {
  11817. index = $items.index($items.filter('.active'));
  11818. }
  11819. prevIndex = that.$menuInner.data('prevIndex');
  11820. if (e.keyCode == 38) {
  11821. if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
  11822. if (index < 0) index += $items.length;
  11823. } else if (e.keyCode == 40) {
  11824. if (that.options.liveSearch || index == prevIndex) index++;
  11825. index = index % $items.length;
  11826. }
  11827. that.$menuInner.data('prevIndex', index);
  11828. if (!that.options.liveSearch) {
  11829. $items.eq(index).children('a').focus();
  11830. } else {
  11831. e.preventDefault();
  11832. if (!$this.hasClass('dropdown-toggle')) {
  11833. $items.removeClass('active').eq(index).addClass('active').children('a').focus();
  11834. $this.focus();
  11835. }
  11836. }
  11837. } else if (!$this.is('input')) {
  11838. var keyIndex = [],
  11839. count,
  11840. prevKey;
  11841. $items = that.$lis.filter(selector);
  11842. $items.each(function (i) {
  11843. if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
  11844. keyIndex.push(i);
  11845. }
  11846. });
  11847. count = $(document).data('keycount');
  11848. count++;
  11849. $(document).data('keycount', count);
  11850. prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
  11851. if (prevKey != keyCodeMap[e.keyCode]) {
  11852. count = 1;
  11853. $(document).data('keycount', count);
  11854. } else if (count >= keyIndex.length) {
  11855. $(document).data('keycount', 0);
  11856. if (count > keyIndex.length) count = 1;
  11857. }
  11858. $items.eq(keyIndex[count - 1]).children('a').focus();
  11859. }
  11860. // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
  11861. if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
  11862. if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
  11863. if (!that.options.liveSearch) {
  11864. var elem = $(':focus');
  11865. elem.click();
  11866. // Bring back focus for multiselects
  11867. elem.focus();
  11868. // Prevent screen from scrolling if the user hit the spacebar
  11869. e.preventDefault();
  11870. // Fixes spacebar selection of dropdown items in FF & IE
  11871. $(document).data('spaceSelect', true);
  11872. } else if (!/(32)/.test(e.keyCode.toString(10))) {
  11873. that.$menuInner.find('.active a').click();
  11874. $this.focus();
  11875. }
  11876. $(document).data('keycount', 0);
  11877. }
  11878. if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
  11879. that.$menu.parent().removeClass('open');
  11880. if (that.options.container) that.$newElement.removeClass('open');
  11881. that.$button.focus();
  11882. }
  11883. },
  11884. mobile: function () {
  11885. this.$element.addClass('mobile-device');
  11886. },
  11887. refresh: function () {
  11888. this.$lis = null;
  11889. this.liObj = {};
  11890. this.reloadLi();
  11891. this.render();
  11892. this.checkDisabled();
  11893. this.liHeight(true);
  11894. this.setStyle();
  11895. this.setWidth();
  11896. if (this.$lis) this.$searchbox.trigger('propertychange');
  11897. this.$element.trigger('refreshed.bs.select');
  11898. },
  11899. hide: function () {
  11900. this.$newElement.hide();
  11901. },
  11902. show: function () {
  11903. this.$newElement.show();
  11904. },
  11905. remove: function () {
  11906. this.$newElement.remove();
  11907. this.$element.remove();
  11908. },
  11909. destroy: function () {
  11910. this.$newElement.before(this.$element).remove();
  11911. if (this.$bsContainer) {
  11912. this.$bsContainer.remove();
  11913. } else {
  11914. this.$menu.remove();
  11915. }
  11916. this.$element
  11917. .off('.bs.select')
  11918. .removeData('selectpicker')
  11919. .removeClass('bs-select-hidden selectpicker');
  11920. }
  11921. };
  11922. // SELECTPICKER PLUGIN DEFINITION
  11923. // ==============================
  11924. function Plugin(option) {
  11925. // get the args of the outer function..
  11926. var args = arguments;
  11927. // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
  11928. // to get lost/corrupted in android 2.3 and IE9 #715 #775
  11929. var _option = option;
  11930. [].shift.apply(args);
  11931. var value;
  11932. var chain = this.each(function () {
  11933. var $this = $(this);
  11934. if ($this.is('select')) {
  11935. var data = $this.data('selectpicker'),
  11936. options = typeof _option == 'object' && _option;
  11937. if (!data) {
  11938. var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
  11939. config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
  11940. $this.data('selectpicker', (data = new Selectpicker(this, config)));
  11941. } else if (options) {
  11942. for (var i in options) {
  11943. if (options.hasOwnProperty(i)) {
  11944. data.options[i] = options[i];
  11945. }
  11946. }
  11947. }
  11948. if (typeof _option == 'string') {
  11949. if (data[_option] instanceof Function) {
  11950. value = data[_option].apply(data, args);
  11951. } else {
  11952. value = data.options[_option];
  11953. }
  11954. }
  11955. }
  11956. });
  11957. if (typeof value !== 'undefined') {
  11958. //noinspection JSUnusedAssignment
  11959. return value;
  11960. } else {
  11961. return chain;
  11962. }
  11963. }
  11964. var old = $.fn.selectpicker;
  11965. $.fn.selectpicker = Plugin;
  11966. $.fn.selectpicker.Constructor = Selectpicker;
  11967. // SELECTPICKER NO CONFLICT
  11968. // ========================
  11969. $.fn.selectpicker.noConflict = function () {
  11970. $.fn.selectpicker = old;
  11971. return this;
  11972. };
  11973. $(document)
  11974. .data('keycount', 0)
  11975. .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
  11976. .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
  11977. e.stopPropagation();
  11978. });
  11979. // SELECTPICKER DATA-API
  11980. // =====================
  11981. $(window).on('load.bs.select.data-api', function () {
  11982. $('.selectpicker').each(function () {
  11983. var $selectpicker = $(this);
  11984. Plugin.call($selectpicker, $selectpicker.data());
  11985. })
  11986. });
  11987. })(jQuery);
  11988. }));
  11989. /***/ }),
  11990. /* 16 */
  11991. /***/ (function(module, exports, __webpack_require__) {
  11992. /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
  11993. * Bootstrap (plugin): validator.js v0.11.9
  11994. * ========================================================================
  11995. * The MIT License (MIT)
  11996. *
  11997. * Copyright (c) 2016 Cina Saffary.
  11998. * Made by @1000hz in the style of Bootstrap 3 era @fat
  11999. *
  12000. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12001. * of this software and associated documentation files (the "Software"), to deal
  12002. * in the Software without restriction, including without limitation the rights
  12003. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12004. * copies of the Software, and to permit persons to whom the Software is
  12005. * furnished to do so, subject to the following conditions:
  12006. *
  12007. * The above copyright notice and this permission notice shall be included in
  12008. * all copies or substantial portions of the Software.
  12009. *
  12010. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12011. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12012. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  12013. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  12014. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  12015. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  12016. * THE SOFTWARE.
  12017. * ======================================================================== */
  12018. +function ($) {
  12019. 'use strict';
  12020. // VALIDATOR CLASS DEFINITION
  12021. // ==========================
  12022. function getValue($el) {
  12023. return $el.is('[type="checkbox"]') ? $el.prop('checked') :
  12024. $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
  12025. $el.is('select[multiple]') ? ($el.val() || []).length :
  12026. $el.val()
  12027. }
  12028. var Validator = function (element, options) {
  12029. this.options = options
  12030. this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
  12031. this.$element = $(element)
  12032. this.$btn = $('button[type="submit"], input[type="submit"]')
  12033. .filter('[form="' + this.$element.attr('id') + '"]')
  12034. .add(this.$element.find('input[type="submit"], button[type="submit"]'))
  12035. this.update()
  12036. this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this))
  12037. this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
  12038. this.$element.on('reset.bs.validator', $.proxy(this.reset, this))
  12039. this.$element.find('[data-match]').each(function () {
  12040. var $this = $(this)
  12041. var target = $this.attr('data-match')
  12042. $(target).on('input.bs.validator', function (e) {
  12043. getValue($this) && $this.trigger('input.bs.validator')
  12044. })
  12045. })
  12046. // run validators for fields with values, but don't clobber server-side errors
  12047. this.$inputs.filter(function () {
  12048. return getValue($(this)) && !$(this).closest('.has-error').length
  12049. }).trigger('focusout')
  12050. this.$element.attr('novalidate', true) // disable automatic native validation
  12051. }
  12052. Validator.VERSION = '0.11.9'
  12053. Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'
  12054. Validator.FOCUS_OFFSET = 20
  12055. Validator.DEFAULTS = {
  12056. delay: 500,
  12057. html: false,
  12058. disable: true,
  12059. focus: true,
  12060. custom: {},
  12061. errors: {
  12062. match: 'Does not match',
  12063. minlength: 'Not long enough'
  12064. },
  12065. feedback: {
  12066. success: 'glyphicon-ok',
  12067. error: 'glyphicon-remove'
  12068. }
  12069. }
  12070. Validator.VALIDATORS = {
  12071. 'native': function ($el) {
  12072. var el = $el[0]
  12073. if (el.checkValidity) {
  12074. return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
  12075. }
  12076. },
  12077. 'match': function ($el) {
  12078. var target = $el.attr('data-match')
  12079. return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
  12080. },
  12081. 'minlength': function ($el) {
  12082. var minlength = $el.attr('data-minlength')
  12083. return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
  12084. }
  12085. }
  12086. Validator.prototype.update = function () {
  12087. var self = this
  12088. this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
  12089. .add(this.$element.find('[data-validate="true"]'))
  12090. .not(this.$element.find('[data-validate="false"]')
  12091. .each(function () { self.clearErrors($(this)) })
  12092. )
  12093. this.toggleSubmit()
  12094. return this
  12095. }
  12096. Validator.prototype.onInput = function (e) {
  12097. var self = this
  12098. var $el = $(e.target)
  12099. var deferErrors = e.type !== 'focusout'
  12100. if (!this.$inputs.is($el)) return
  12101. this.validateInput($el, deferErrors).done(function () {
  12102. self.toggleSubmit()
  12103. })
  12104. }
  12105. Validator.prototype.validateInput = function ($el, deferErrors) {
  12106. var value = getValue($el)
  12107. var prevErrors = $el.data('bs.validator.errors')
  12108. if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
  12109. var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
  12110. this.$element.trigger(e)
  12111. if (e.isDefaultPrevented()) return
  12112. var self = this
  12113. return this.runValidators($el).done(function (errors) {
  12114. $el.data('bs.validator.errors', errors)
  12115. errors.length
  12116. ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
  12117. : self.clearErrors($el)
  12118. if (!prevErrors || errors.toString() !== prevErrors.toString()) {
  12119. e = errors.length
  12120. ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
  12121. : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
  12122. self.$element.trigger(e)
  12123. }
  12124. self.toggleSubmit()
  12125. self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
  12126. })
  12127. }
  12128. Validator.prototype.runValidators = function ($el) {
  12129. var errors = []
  12130. var deferred = $.Deferred()
  12131. $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
  12132. $el.data('bs.validator.deferred', deferred)
  12133. function getValidatorSpecificError(key) {
  12134. return $el.attr('data-' + key + '-error')
  12135. }
  12136. function getValidityStateError() {
  12137. var validity = $el[0].validity
  12138. return validity.typeMismatch ? $el.attr('data-type-error')
  12139. : validity.patternMismatch ? $el.attr('data-pattern-error')
  12140. : validity.stepMismatch ? $el.attr('data-step-error')
  12141. : validity.rangeOverflow ? $el.attr('data-max-error')
  12142. : validity.rangeUnderflow ? $el.attr('data-min-error')
  12143. : validity.valueMissing ? $el.attr('data-required-error')
  12144. : null
  12145. }
  12146. function getGenericError() {
  12147. return $el.attr('data-error')
  12148. }
  12149. function getErrorMessage(key) {
  12150. return getValidatorSpecificError(key)
  12151. || getValidityStateError()
  12152. || getGenericError()
  12153. }
  12154. $.each(this.validators, $.proxy(function (key, validator) {
  12155. var error = null
  12156. if ((getValue($el) || $el.attr('required')) &&
  12157. ($el.attr('data-' + key) !== undefined || key == 'native') &&
  12158. (error = validator.call(this, $el))) {
  12159. error = getErrorMessage(key) || error
  12160. !~errors.indexOf(error) && errors.push(error)
  12161. }
  12162. }, this))
  12163. if (!errors.length && getValue($el) && $el.attr('data-remote')) {
  12164. this.defer($el, function () {
  12165. var data = {}
  12166. data[$el.attr('name')] = getValue($el)
  12167. $.get($el.attr('data-remote'), data)
  12168. .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
  12169. .always(function () { deferred.resolve(errors)})
  12170. })
  12171. } else deferred.resolve(errors)
  12172. return deferred.promise()
  12173. }
  12174. Validator.prototype.validate = function () {
  12175. var self = this
  12176. $.when(this.$inputs.map(function (el) {
  12177. return self.validateInput($(this), false)
  12178. })).then(function () {
  12179. self.toggleSubmit()
  12180. self.focusError()
  12181. })
  12182. return this
  12183. }
  12184. Validator.prototype.focusError = function () {
  12185. if (!this.options.focus) return
  12186. var $input = this.$element.find(".has-error:first :input")
  12187. if ($input.length === 0) return
  12188. $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
  12189. $input.focus()
  12190. }
  12191. Validator.prototype.showErrors = function ($el) {
  12192. var method = this.options.html ? 'html' : 'text'
  12193. var errors = $el.data('bs.validator.errors')
  12194. var $group = $el.closest('.form-group')
  12195. var $block = $group.find('.help-block.with-errors')
  12196. var $feedback = $group.find('.form-control-feedback')
  12197. if (!errors.length) return
  12198. errors = $('<ul/>')
  12199. .addClass('list-unstyled')
  12200. .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
  12201. $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
  12202. $block.empty().append(errors)
  12203. $group.addClass('has-error has-danger')
  12204. $group.hasClass('has-feedback')
  12205. && $feedback.removeClass(this.options.feedback.success)
  12206. && $feedback.addClass(this.options.feedback.error)
  12207. && $group.removeClass('has-success')
  12208. }
  12209. Validator.prototype.clearErrors = function ($el) {
  12210. var $group = $el.closest('.form-group')
  12211. var $block = $group.find('.help-block.with-errors')
  12212. var $feedback = $group.find('.form-control-feedback')
  12213. $block.html($block.data('bs.validator.originalContent'))
  12214. $group.removeClass('has-error has-danger has-success')
  12215. $group.hasClass('has-feedback')
  12216. && $feedback.removeClass(this.options.feedback.error)
  12217. && $feedback.removeClass(this.options.feedback.success)
  12218. && getValue($el)
  12219. && $feedback.addClass(this.options.feedback.success)
  12220. && $group.addClass('has-success')
  12221. }
  12222. Validator.prototype.hasErrors = function () {
  12223. function fieldErrors() {
  12224. return !!($(this).data('bs.validator.errors') || []).length
  12225. }
  12226. return !!this.$inputs.filter(fieldErrors).length
  12227. }
  12228. Validator.prototype.isIncomplete = function () {
  12229. function fieldIncomplete() {
  12230. var value = getValue($(this))
  12231. return !(typeof value == "string" ? $.trim(value) : value)
  12232. }
  12233. return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
  12234. }
  12235. Validator.prototype.onSubmit = function (e) {
  12236. this.validate()
  12237. if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
  12238. }
  12239. Validator.prototype.toggleSubmit = function () {
  12240. if (!this.options.disable) return
  12241. this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
  12242. }
  12243. Validator.prototype.defer = function ($el, callback) {
  12244. callback = $.proxy(callback, this, $el)
  12245. if (!this.options.delay) return callback()
  12246. window.clearTimeout($el.data('bs.validator.timeout'))
  12247. $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
  12248. }
  12249. Validator.prototype.reset = function () {
  12250. this.$element.find('.form-control-feedback')
  12251. .removeClass(this.options.feedback.error)
  12252. .removeClass(this.options.feedback.success)
  12253. this.$inputs
  12254. .removeData(['bs.validator.errors', 'bs.validator.deferred'])
  12255. .each(function () {
  12256. var $this = $(this)
  12257. var timeout = $this.data('bs.validator.timeout')
  12258. window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
  12259. })
  12260. this.$element.find('.help-block.with-errors')
  12261. .each(function () {
  12262. var $this = $(this)
  12263. var originalContent = $this.data('bs.validator.originalContent')
  12264. $this
  12265. .removeData('bs.validator.originalContent')
  12266. .html(originalContent)
  12267. })
  12268. this.$btn.removeClass('disabled')
  12269. this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
  12270. return this
  12271. }
  12272. Validator.prototype.destroy = function () {
  12273. this.reset()
  12274. this.$element
  12275. .removeAttr('novalidate')
  12276. .removeData('bs.validator')
  12277. .off('.bs.validator')
  12278. this.$inputs
  12279. .off('.bs.validator')
  12280. this.options = null
  12281. this.validators = null
  12282. this.$element = null
  12283. this.$btn = null
  12284. this.$inputs = null
  12285. return this
  12286. }
  12287. // VALIDATOR PLUGIN DEFINITION
  12288. // ===========================
  12289. function Plugin(option) {
  12290. return this.each(function () {
  12291. var $this = $(this)
  12292. var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
  12293. var data = $this.data('bs.validator')
  12294. if (!data && option == 'destroy') return
  12295. if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
  12296. if (typeof option == 'string') data[option]()
  12297. })
  12298. }
  12299. var old = $.fn.validator
  12300. $.fn.validator = Plugin
  12301. $.fn.validator.Constructor = Validator
  12302. // VALIDATOR NO CONFLICT
  12303. // =====================
  12304. $.fn.validator.noConflict = function () {
  12305. $.fn.validator = old
  12306. return this
  12307. }
  12308. // VALIDATOR DATA-API
  12309. // ==================
  12310. $(window).on('load', function () {
  12311. $('form[data-toggle="validator"]').each(function () {
  12312. var $form = $(this)
  12313. Plugin.call($form, $form.data())
  12314. })
  12315. })
  12316. }(jQuery);
  12317. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
  12318. /***/ }),
  12319. /* 17 */
  12320. /***/ (function(module, exports, __webpack_require__) {
  12321. var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
  12322. * bootstrap-fileinput v4.4.2
  12323. * http://plugins.krajee.com/file-input
  12324. *
  12325. * Author: Kartik Visweswaran
  12326. * Copyright: 2014 - 2017, Kartik Visweswaran, Krajee.com
  12327. *
  12328. * Licensed under the BSD 3-Clause
  12329. * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
  12330. */
  12331. (function (factory) {
  12332. "use strict";
  12333. //noinspection JSUnresolvedVariable
  12334. if (true) { // jshint ignore:line
  12335. // AMD. Register as an anonymous module.
  12336. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
  12337. __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
  12338. (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
  12339. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // jshint ignore:line
  12340. } else { // noinspection JSUnresolvedVariable
  12341. if (typeof module === 'object' && module.exports) { // jshint ignore:line
  12342. // Node/CommonJS
  12343. // noinspection JSUnresolvedVariable
  12344. module.exports = factory(require('jquery')); // jshint ignore:line
  12345. } else {
  12346. // Browser globals
  12347. factory(window.jQuery);
  12348. }
  12349. }
  12350. }(function ($) {
  12351. "use strict";
  12352. $.fn.fileinputLocales = {};
  12353. $.fn.fileinputThemes = {};
  12354. String.prototype.setTokens = function (replacePairs) {
  12355. var str = this.toString(), key, re;
  12356. for (key in replacePairs) {
  12357. if (replacePairs.hasOwnProperty(key)) {
  12358. re = new RegExp("\{" + key + "\}", "g");
  12359. str = str.replace(re, replacePairs[key]);
  12360. }
  12361. }
  12362. return str;
  12363. };
  12364. var $h, FileInput;
  12365. // fileinput helper object for all global variables and internal helper methods
  12366. //noinspection JSUnresolvedVariable
  12367. $h = {
  12368. FRAMES: '.kv-preview-thumb',
  12369. SORT_CSS: 'file-sortable',
  12370. STYLE_SETTING: 'style="width:{width};height:{height};"',
  12371. OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
  12372. '<param name="allowFullScreen" value="true" />\n' +
  12373. '<param name="allowScriptAccess" value="always" />\n' +
  12374. '<param name="autoPlay" value="false" />\n' +
  12375. '<param name="autoStart" value="false" />\n' +
  12376. '<param name="quality" value="high" />\n',
  12377. DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
  12378. '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
  12379. '</div>',
  12380. MODAL_ID: 'kvFileinputModal',
  12381. MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
  12382. objUrl: window.URL || window.webkitURL,
  12383. compare: function (input, str, exact) {
  12384. return input !== undefined && (exact ? input === str : input.match(str));
  12385. },
  12386. isIE: function (ver) {
  12387. // check for IE versions < 11
  12388. if (navigator.appName !== 'Microsoft Internet Explorer') {
  12389. return false;
  12390. }
  12391. if (ver === 10) {
  12392. return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
  12393. }
  12394. var div = document.createElement("div"), status;
  12395. div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
  12396. status = div.getElementsByTagName("i").length;
  12397. document.body.appendChild(div);
  12398. div.parentNode.removeChild(div);
  12399. return status;
  12400. },
  12401. initModal: function ($modal) {
  12402. var $body = $('body');
  12403. if ($body.length) {
  12404. $modal.appendTo($body);
  12405. }
  12406. },
  12407. isEmpty: function (value, trim) {
  12408. return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
  12409. },
  12410. isArray: function (a) {
  12411. return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
  12412. },
  12413. ifSet: function (needle, haystack, def) {
  12414. def = def || '';
  12415. return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
  12416. },
  12417. cleanArray: function (arr) {
  12418. if (!(arr instanceof Array)) {
  12419. arr = [];
  12420. }
  12421. return arr.filter(function (e) {
  12422. return (e !== undefined && e !== null);
  12423. });
  12424. },
  12425. spliceArray: function (arr, index) {
  12426. var i, j = 0, out = [];
  12427. if (!(arr instanceof Array)) {
  12428. return [];
  12429. }
  12430. for (i = 0; i < arr.length; i++) {
  12431. if (i !== index) {
  12432. out[j] = arr[i];
  12433. j++;
  12434. }
  12435. }
  12436. return out;
  12437. },
  12438. getNum: function (num, def) {
  12439. def = def || 0;
  12440. if (typeof num === "number") {
  12441. return num;
  12442. }
  12443. if (typeof num === "string") {
  12444. num = parseFloat(num);
  12445. }
  12446. return isNaN(num) ? def : num;
  12447. },
  12448. hasFileAPISupport: function () {
  12449. return !!(window.File && window.FileReader);
  12450. },
  12451. hasDragDropSupport: function () {
  12452. var div = document.createElement('div');
  12453. /** @namespace div.draggable */
  12454. /** @namespace div.ondragstart */
  12455. /** @namespace div.ondrop */
  12456. return !$h.isIE(9) &&
  12457. (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
  12458. },
  12459. hasFileUploadSupport: function () {
  12460. return $h.hasFileAPISupport() && window.FormData;
  12461. },
  12462. hasBlobSupport: function () {
  12463. try {
  12464. return !!window.Blob && Boolean(new Blob());
  12465. } catch (e) {
  12466. return false;
  12467. }
  12468. },
  12469. hasArrayBufferViewSupport: function () {
  12470. try {
  12471. return new Blob([new Uint8Array(100)]).size === 100;
  12472. } catch (e) {
  12473. return false;
  12474. }
  12475. },
  12476. dataURI2Blob: function (dataURI) {
  12477. //noinspection JSUnresolvedVariable
  12478. var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
  12479. window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
  12480. canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
  12481. if (!canProceed) {
  12482. return null;
  12483. }
  12484. if (dataURI.split(',')[0].indexOf('base64') >= 0) {
  12485. byteStr = atob(dataURI.split(',')[1]);
  12486. } else {
  12487. byteStr = decodeURIComponent(dataURI.split(',')[1]);
  12488. }
  12489. arrayBuffer = new ArrayBuffer(byteStr.length);
  12490. intArray = new Uint8Array(arrayBuffer);
  12491. for (i = 0; i < byteStr.length; i += 1) {
  12492. intArray[i] = byteStr.charCodeAt(i);
  12493. }
  12494. mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
  12495. if (canBlob) {
  12496. return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
  12497. }
  12498. bb = new BlobBuilder();
  12499. bb.append(arrayBuffer);
  12500. return bb.getBlob(mimeStr);
  12501. },
  12502. addCss: function ($el, css) {
  12503. $el.removeClass(css).addClass(css);
  12504. },
  12505. getElement: function (options, param, value) {
  12506. return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
  12507. },
  12508. uniqId: function () {
  12509. return Math.round(new Date().getTime() + (Math.random() * 100));
  12510. },
  12511. htmlEncode: function (str) {
  12512. return str.replace(/&/g, '&amp;')
  12513. .replace(/</g, '&lt;')
  12514. .replace(/>/g, '&gt;')
  12515. .replace(/"/g, '&quot;')
  12516. .replace(/'/g, '&apos;');
  12517. },
  12518. replaceTags: function (str, tags) {
  12519. var out = str;
  12520. if (!tags) {
  12521. return out;
  12522. }
  12523. $.each(tags, function (key, value) {
  12524. if (typeof value === "function") {
  12525. value = value();
  12526. }
  12527. out = out.split(key).join(value);
  12528. });
  12529. return out;
  12530. },
  12531. cleanMemory: function ($thumb) {
  12532. var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
  12533. /** @namespace $h.objUrl.revokeObjectURL */
  12534. $h.objUrl.revokeObjectURL(data);
  12535. },
  12536. findFileName: function (filePath) {
  12537. var sepIndex = filePath.lastIndexOf('/');
  12538. if (sepIndex === -1) {
  12539. sepIndex = filePath.lastIndexOf('\\');
  12540. }
  12541. return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
  12542. },
  12543. checkFullScreen: function () {
  12544. //noinspection JSUnresolvedVariable
  12545. return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
  12546. document.msFullscreenElement;
  12547. },
  12548. toggleFullScreen: function (maximize) {
  12549. var doc = document, de = doc.documentElement;
  12550. if (de && maximize && !$h.checkFullScreen()) {
  12551. /** @namespace document.requestFullscreen */
  12552. /** @namespace document.msRequestFullscreen */
  12553. /** @namespace document.mozRequestFullScreen */
  12554. /** @namespace document.webkitRequestFullscreen */
  12555. /** @namespace Element.ALLOW_KEYBOARD_INPUT */
  12556. if (de.requestFullscreen) {
  12557. de.requestFullscreen();
  12558. } else if (de.msRequestFullscreen) {
  12559. de.msRequestFullscreen();
  12560. } else if (de.mozRequestFullScreen) {
  12561. de.mozRequestFullScreen();
  12562. } else if (de.webkitRequestFullscreen) {
  12563. de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  12564. }
  12565. } else {
  12566. /** @namespace document.exitFullscreen */
  12567. /** @namespace document.msExitFullscreen */
  12568. /** @namespace document.mozCancelFullScreen */
  12569. /** @namespace document.webkitExitFullscreen */
  12570. if (doc.exitFullscreen) {
  12571. doc.exitFullscreen();
  12572. } else if (doc.msExitFullscreen) {
  12573. doc.msExitFullscreen();
  12574. } else if (doc.mozCancelFullScreen) {
  12575. doc.mozCancelFullScreen();
  12576. } else if (doc.webkitExitFullscreen) {
  12577. doc.webkitExitFullscreen();
  12578. }
  12579. }
  12580. },
  12581. moveArray: function (arr, oldIndex, newIndex) {
  12582. if (newIndex >= arr.length) {
  12583. var k = newIndex - arr.length;
  12584. while ((k--) + 1) {
  12585. arr.push(undefined);
  12586. }
  12587. }
  12588. arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);
  12589. return arr;
  12590. },
  12591. cleanZoomCache: function ($el) {
  12592. var $cache = $el.closest('.kv-zoom-cache-theme');
  12593. if (!$cache.length) {
  12594. $cache = $el.closest('.kv-zoom-cache');
  12595. }
  12596. $cache.remove();
  12597. },
  12598. setOrientation: function (buffer, callback) {
  12599. var scanner = new DataView(buffer), idx = 0, value = 1, // Non-rotated is the default
  12600. maxBytes, uInt16, exifLength;
  12601. if (scanner.getUint16(idx) !== 0xFFD8 || buffer.length < 2) {
  12602. return; // not a proper JPEG
  12603. }
  12604. idx += 2;
  12605. maxBytes = scanner.byteLength;
  12606. while (idx < maxBytes - 2) {
  12607. uInt16 = scanner.getUint16(idx);
  12608. idx += 2;
  12609. switch (uInt16) {
  12610. case 0xFFE1: // Start of EXIF
  12611. exifLength = scanner.getUint16(idx);
  12612. maxBytes = exifLength - idx;
  12613. idx += 2;
  12614. break;
  12615. case 0x0112: // Orientation tag
  12616. value = scanner.getUint16(idx + 6, false);
  12617. maxBytes = 0; // Stop scanning
  12618. break;
  12619. }
  12620. }
  12621. if (callback) {
  12622. callback(value);
  12623. }
  12624. },
  12625. validateOrientation: function (file, callback) {
  12626. if (!window.FileReader || !window.DataView) {
  12627. return; // skip orientation if pre-requisite libraries not supported by browser
  12628. }
  12629. var reader = new FileReader(), buffer;
  12630. reader.onloadend = function () {
  12631. buffer = reader.result;
  12632. $h.setOrientation(buffer, callback);
  12633. };
  12634. reader.readAsArrayBuffer(file);
  12635. },
  12636. adjustOrientedImage: function ($img, isZoom) {
  12637. var offsetContTop, offsetTop, newTop;
  12638. if (!$img.hasClass('is-portrait-gt4')) {
  12639. return;
  12640. }
  12641. if (isZoom) {
  12642. $img.css({width: $img.parent().height()});
  12643. return;
  12644. } else {
  12645. $img.css({height: 'auto', width: $img.height()});
  12646. }
  12647. offsetContTop = $img.parent().offset().top;
  12648. offsetTop = $img.offset().top;
  12649. newTop = offsetContTop - offsetTop;
  12650. $img.css('margin-top', newTop);
  12651. }
  12652. };
  12653. FileInput = function (element, options) {
  12654. var self = this;
  12655. self.$element = $(element);
  12656. if (!self._validate()) {
  12657. return;
  12658. }
  12659. self.isPreviewable = $h.hasFileAPISupport();
  12660. self.isIE9 = $h.isIE(9);
  12661. self.isIE10 = $h.isIE(10);
  12662. if (self.isPreviewable || self.isIE9) {
  12663. self._init(options);
  12664. self._listen();
  12665. } else {
  12666. self.$element.removeClass('file-loading');
  12667. }
  12668. };
  12669. //noinspection JSUnusedGlobalSymbols
  12670. FileInput.prototype = {
  12671. constructor: FileInput,
  12672. _cleanup: function () {
  12673. var self = this;
  12674. self.reader = null;
  12675. self.formdata = {};
  12676. self.uploadCount = 0;
  12677. self.uploadStatus = {};
  12678. self.uploadLog = [];
  12679. self.uploadAsyncCount = 0;
  12680. self.loadedImages = [];
  12681. self.totalImagesCount = 0;
  12682. self.ajaxRequests = [];
  12683. self.clearStack();
  12684. self.fileInputCleared = false;
  12685. self.fileBatchCompleted = true;
  12686. if (!self.isPreviewable) {
  12687. self.showPreview = false;
  12688. }
  12689. self.isError = false;
  12690. self.ajaxAborted = false;
  12691. self.cancelling = false;
  12692. },
  12693. _init: function (options) {
  12694. var self = this, $el = self.$element, $cont, t, tmp;
  12695. self.options = options;
  12696. $.each(options, function (key, value) {
  12697. switch (key) {
  12698. case 'minFileCount':
  12699. case 'maxFileCount':
  12700. case 'minFileSize':
  12701. case 'maxFileSize':
  12702. case 'maxFilePreviewSize':
  12703. case 'resizeImageQuality':
  12704. case 'resizeIfSizeMoreThan':
  12705. case 'progressUploadThreshold':
  12706. case 'initialPreviewCount':
  12707. case 'zoomModalHeight':
  12708. case 'minImageHeight':
  12709. case 'maxImageHeight':
  12710. case 'minImageWidth':
  12711. case 'maxImageWidth':
  12712. self[key] = $h.getNum(value);
  12713. break;
  12714. default:
  12715. self[key] = value;
  12716. break;
  12717. }
  12718. });
  12719. if (self.rtl) { // swap buttons for rtl
  12720. tmp = self.previewZoomButtonIcons.prev;
  12721. self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
  12722. self.previewZoomButtonIcons.next = tmp;
  12723. }
  12724. self._cleanup();
  12725. self.$form = $el.closest('form');
  12726. self._initTemplateDefaults();
  12727. self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
  12728. t = self._getLayoutTemplate('progress');
  12729. self.progressTemplate = t.replace('{class}', self.progressClass);
  12730. self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
  12731. self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
  12732. self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
  12733. self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
  12734. if (self.isDisabled) {
  12735. $el.attr('disabled', true);
  12736. }
  12737. self.isUploadable = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
  12738. self.isClickable = self.browseOnZoneClick && self.showPreview &&
  12739. (self.isUploadable && self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
  12740. self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self._slugDefault;
  12741. self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
  12742. self.captionTemplate = self._getLayoutTemplate('caption');
  12743. self.previewGenericTemplate = self._getPreviewTemplate('generic');
  12744. if (self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
  12745. self.imageCanvas = document.createElement('canvas');
  12746. self.imageCanvasContext = self.imageCanvas.getContext('2d');
  12747. }
  12748. if ($h.isEmpty($el.attr('id'))) {
  12749. $el.attr('id', $h.uniqId());
  12750. }
  12751. self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
  12752. if (self.$container === undefined) {
  12753. self.$container = self._createContainer();
  12754. } else {
  12755. self._refreshContainer();
  12756. }
  12757. $cont = self.$container;
  12758. self.$dropZone = $cont.find('.file-drop-zone');
  12759. self.$progress = $cont.find('.kv-upload-progress');
  12760. self.$btnUpload = $cont.find('.fileinput-upload');
  12761. self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
  12762. self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
  12763. self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
  12764. self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
  12765. self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
  12766. self.$errorContainer = $h.getElement(options, 'elErrorContainer',
  12767. self.$previewContainer.find('.kv-fileinput-error'));
  12768. if (!$h.isEmpty(self.msgErrorClass)) {
  12769. $h.addCss(self.$errorContainer, self.msgErrorClass);
  12770. }
  12771. self.$errorContainer.hide();
  12772. self.previewInitId = "preview-" + $h.uniqId();
  12773. self._initPreviewCache();
  12774. self._initPreview(true);
  12775. self._initPreviewActions();
  12776. self._setFileDropZoneTitle();
  12777. $el.removeClass('file-loading');
  12778. if ($el.attr('disabled')) {
  12779. self.disable();
  12780. }
  12781. self._initZoom();
  12782. if (self.hideThumbnailContent) {
  12783. $h.addCss(self.$preview, 'hide-content');
  12784. }
  12785. },
  12786. _initTemplateDefaults: function () {
  12787. var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
  12788. tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionZoom,
  12789. tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage, tText, tVideo,
  12790. tAudio, tFlash, tObject, tPdf, tOther, tZoomCache, vDefaultDim;
  12791. tMain1 = '{preview}\n' +
  12792. '<div class="kv-upload-progress hide"></div>\n' +
  12793. '<div class="input-group {class}">\n' +
  12794. ' {caption}\n' +
  12795. ' <div class="input-group-btn">\n' +
  12796. ' {remove}\n' +
  12797. ' {cancel}\n' +
  12798. ' {upload}\n' +
  12799. ' {browse}\n' +
  12800. ' </div>\n' +
  12801. '</div>';
  12802. tMain2 = '{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
  12803. tPreview = '<div class="file-preview {class}">\n' +
  12804. ' {close}' +
  12805. ' <div class="{dropClass}">\n' +
  12806. ' <div class="file-preview-thumbnails">\n' +
  12807. ' </div>\n' +
  12808. ' <div class="clearfix"></div>' +
  12809. ' <div class="file-preview-status text-center text-success"></div>\n' +
  12810. ' <div class="kv-fileinput-error"></div>\n' +
  12811. ' </div>\n' +
  12812. '</div>';
  12813. tClose = '<div class="close fileinput-remove">&times;</div>\n';
  12814. tFileIcon = '<i class="glyphicon glyphicon-file kv-caption-icon"></i>';
  12815. tCaption = '<div tabindex="500" class="form-control file-caption {class}">\n' +
  12816. ' <div class="file-caption-name"></div>\n' +
  12817. '</div>\n';
  12818. //noinspection HtmlUnknownAttribute
  12819. tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" ' +
  12820. '{status}>{icon} {label}</button>';
  12821. //noinspection HtmlUnknownAttribute
  12822. tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon} {label}</a>';
  12823. //noinspection HtmlUnknownAttribute
  12824. tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon} {label}</div>';
  12825. tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
  12826. 'tabindex="-1" aria-labelledby="' + $h.MODAL_ID + 'Label"></div>';
  12827. tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
  12828. ' <div class="modal-content">\n' +
  12829. ' <div class="modal-header">\n' +
  12830. ' <div class="kv-zoom-actions pull-right">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
  12831. ' <h3 class="modal-title">{heading} <small><span class="kv-zoom-title"></span></small></h3>\n' +
  12832. ' </div>\n' +
  12833. ' <div class="modal-body">\n' +
  12834. ' <div class="floating-buttons"></div>\n' +
  12835. ' <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
  12836. ' </div>\n' +
  12837. ' </div>\n' +
  12838. '</div>\n';
  12839. tProgress = '<div class="progress">\n' +
  12840. ' <div class="{class}" role="progressbar"' +
  12841. ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
  12842. ' {status}\n' +
  12843. ' </div>\n' +
  12844. '</div>';
  12845. tSize = ' <samp>({sizeText})</samp>';
  12846. tFooter = '<div class="file-thumbnail-footer">\n' +
  12847. ' <div class="file-footer-caption" title="{caption}">{caption}<br>{size}</div>\n' +
  12848. ' {progress} {indicator} {actions}\n' +
  12849. '</div>';
  12850. tActions = '{drag}\n' +
  12851. '<div class="file-actions">\n' +
  12852. ' <div class="file-footer-buttons">\n' +
  12853. ' {upload} {delete} {zoom} {other}' +
  12854. ' </div>\n' +
  12855. ' <div class="clearfix"></div>\n' +
  12856. '</div>';
  12857. //noinspection HtmlUnknownAttribute
  12858. tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
  12859. 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
  12860. tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
  12861. '{uploadIcon}</button>';
  12862. tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
  12863. 'title="{zoomTitle}">{zoomIcon}</button>';
  12864. tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
  12865. tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
  12866. tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
  12867. ' data-template="{template}"';
  12868. tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
  12869. tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
  12870. tTagAft = '</div>{footer}\n</div>\n';
  12871. tGeneric = '{content}\n';
  12872. tHtml = '<div class="kv-preview-data file-preview-html" title="{caption}" ' + $h.STYLE_SETTING +
  12873. '>{data}</div>\n';
  12874. tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{caption}" alt="{caption}" ' +
  12875. $h.STYLE_SETTING + '>\n';
  12876. tText = '<textarea class="kv-preview-data file-preview-text" title="{caption}" readonly ' +
  12877. $h.STYLE_SETTING + '>{data}</textarea>\n';
  12878. tVideo = '<video class="kv-preview-data file-preview-video" width="{width}" ' +
  12879. 'height="{height}" controls>\n' + '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW +
  12880. '\n</video>\n';
  12881. tAudio = '<div class="file-preview-audio"><audio class="kv-preview-data" controls>\n<source src="{data}" ' +
  12882. 'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio></div>\n';
  12883. tFlash = '<object class="kv-preview-data file-object" type="application/x-shockwave-flash" ' +
  12884. 'width="{width}" height="{height}" data="{data}">\n' + $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW +
  12885. '\n</object>\n';
  12886. tObject = '<object class="kv-preview-data file-object {typeCss}" data="{data}" type="{type}" ' +
  12887. 'width="{width}" height="{height}">\n' + '<param name="movie" value="{caption}" />\n' +
  12888. $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
  12889. tPdf = '<embed class="kv-preview-data" src="{data}" ' +
  12890. 'width="{width}" height="{height}" type="application/pdf">\n';
  12891. tOther = '<div class="kv-preview-data file-preview-other-frame">\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
  12892. tZoomCache = '<div class="kv-zoom-cache" style="display:none">{zoomContent}</div>';
  12893. vDefaultDim = {width: "100%", height: "100%", 'min-height': "480px"};
  12894. self.defaults = {
  12895. layoutTemplates: {
  12896. main1: tMain1,
  12897. main2: tMain2,
  12898. preview: tPreview,
  12899. close: tClose,
  12900. fileIcon: tFileIcon,
  12901. caption: tCaption,
  12902. modalMain: tModalMain,
  12903. modal: tModal,
  12904. progress: tProgress,
  12905. size: tSize,
  12906. footer: tFooter,
  12907. indicator: tIndicator,
  12908. actions: tActions,
  12909. actionDelete: tActionDelete,
  12910. actionUpload: tActionUpload,
  12911. actionZoom: tActionZoom,
  12912. actionDrag: tActionDrag,
  12913. btnDefault: tBtnDefault,
  12914. btnLink: tBtnLink,
  12915. btnBrowse: tBtnBrowse,
  12916. zoomCache: tZoomCache
  12917. },
  12918. previewMarkupTags: {
  12919. tagBefore1: tTagBef1,
  12920. tagBefore2: tTagBef2,
  12921. tagAfter: tTagAft
  12922. },
  12923. previewContentTemplates: {
  12924. generic: tGeneric,
  12925. html: tHtml,
  12926. image: tImage,
  12927. text: tText,
  12928. video: tVideo,
  12929. audio: tAudio,
  12930. flash: tFlash,
  12931. object: tObject,
  12932. pdf: tPdf,
  12933. other: tOther
  12934. },
  12935. allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
  12936. previewTemplates: {},
  12937. previewSettings: {
  12938. image: {width: "auto", height: "160px"},
  12939. html: {width: "213px", height: "160px"},
  12940. text: {width: "213px", height: "160px"},
  12941. video: {width: "auto", height: "100%", 'max-width': "100%"},
  12942. audio: {width: "100%", height: "30px"},
  12943. flash: {width: "auto", height: "100%", 'max-width': "100%"},
  12944. object: {height: "100%"},
  12945. pdf: {width: "160px", height: "160px"},
  12946. other: {width: "160px", height: "160px"}
  12947. },
  12948. previewZoomSettings: {
  12949. image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
  12950. html: vDefaultDim,
  12951. text: vDefaultDim,
  12952. video: {width: "auto", height: "100%", 'max-width': "100%"},
  12953. audio: {width: "100%", height: "30px"},
  12954. flash: {width: "auto", height: "480px"},
  12955. object: {width: "auto", height: "100%", 'max-width': "100%", 'min-height': "480px"},
  12956. pdf: vDefaultDim,
  12957. other: {width: "auto", height: "100%", 'min-height': "480px"}
  12958. },
  12959. fileTypeSettings: {
  12960. image: function (vType, vName) {
  12961. return $h.compare(vType, 'image.*') || $h.compare(vName, /\.(gif|png|jpe?g)$/i);
  12962. },
  12963. html: function (vType, vName) {
  12964. return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
  12965. },
  12966. text: function (vType, vName) {
  12967. return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
  12968. $h.compare(vName, /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
  12969. },
  12970. video: function (vType, vName) {
  12971. return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
  12972. $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
  12973. },
  12974. audio: function (vType, vName) {
  12975. return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
  12976. $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
  12977. },
  12978. flash: function (vType, vName) {
  12979. return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName, /\.(swf)$/i);
  12980. },
  12981. pdf: function (vType, vName) {
  12982. return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
  12983. },
  12984. object: function () {
  12985. return true;
  12986. },
  12987. other: function () {
  12988. return true;
  12989. }
  12990. },
  12991. fileActionSettings: {
  12992. showRemove: true,
  12993. showUpload: true,
  12994. showZoom: true,
  12995. showDrag: true,
  12996. removeIcon: '<i class="glyphicon glyphicon-trash text-danger"></i>',
  12997. removeClass: 'btn btn-xs btn-default',
  12998. removeTitle: 'Remove file',
  12999. uploadIcon: '<i class="glyphicon glyphicon-upload text-info"></i>',
  13000. uploadClass: 'btn btn-xs btn-default',
  13001. uploadTitle: 'Upload file',
  13002. zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
  13003. zoomClass: 'btn btn-xs btn-default',
  13004. zoomTitle: 'View Details',
  13005. dragIcon: '<i class="glyphicon glyphicon-menu-hamburger"></i>',
  13006. dragClass: 'text-info',
  13007. dragTitle: 'Move / Rearrange',
  13008. dragSettings: {},
  13009. indicatorNew: '<i class="glyphicon glyphicon-hand-down text-warning"></i>',
  13010. indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
  13011. indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
  13012. indicatorLoading: '<i class="glyphicon glyphicon-hand-up text-muted"></i>',
  13013. indicatorNewTitle: 'Not uploaded yet',
  13014. indicatorSuccessTitle: 'Uploaded',
  13015. indicatorErrorTitle: 'Upload Error',
  13016. indicatorLoadingTitle: 'Uploading ...'
  13017. }
  13018. };
  13019. $.each(self.defaults, function (key, setting) {
  13020. if (key === 'allowedPreviewTypes') {
  13021. if (self.allowedPreviewTypes === undefined) {
  13022. self.allowedPreviewTypes = setting;
  13023. }
  13024. return;
  13025. }
  13026. self[key] = $.extend(true, {}, setting, self[key]);
  13027. });
  13028. self._initPreviewTemplates();
  13029. },
  13030. _initPreviewTemplates: function () {
  13031. var self = this, cfg = self.defaults, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
  13032. $.each(cfg.previewContentTemplates, function (key, value) {
  13033. if ($h.isEmpty(self.previewTemplates[key])) {
  13034. tagBef = tags.tagBefore2;
  13035. if (key === 'generic' || key === 'image' || key === 'html' || key === 'text') {
  13036. tagBef = tags.tagBefore1;
  13037. }
  13038. self.previewTemplates[key] = tagBef + value + tagAft;
  13039. }
  13040. });
  13041. },
  13042. _initPreviewCache: function () {
  13043. var self = this;
  13044. self.previewCache = {
  13045. data: {},
  13046. init: function () {
  13047. var content = self.initialPreview;
  13048. if (content.length > 0 && !$h.isArray(content)) {
  13049. content = content.split(self.initialPreviewDelimiter);
  13050. }
  13051. self.previewCache.data = {
  13052. content: content,
  13053. config: self.initialPreviewConfig,
  13054. tags: self.initialPreviewThumbTags
  13055. };
  13056. },
  13057. fetch: function () {
  13058. return self.previewCache.data.content.filter(function (n) {
  13059. return n !== null;
  13060. });
  13061. },
  13062. count: function (all) {
  13063. return !!self.previewCache.data && !!self.previewCache.data.content ?
  13064. (all ? self.previewCache.data.content.length : self.previewCache.fetch().length) : 0;
  13065. },
  13066. get: function (i, isDisabled) {
  13067. var ind = 'init_' + i, data = self.previewCache.data, config = data.config[i],
  13068. content = data.content[i], previewId = self.previewInitId + '-' + ind, out, $tmp, cat, ftr,
  13069. fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
  13070. parseTemplate = function (cat, dat, fn, ft, id, ftr, ind, fc, t) {
  13071. fc = ' file-preview-initial ' + $h.SORT_CSS + (fc ? ' ' + fc : '');
  13072. return self._generatePreviewTemplate(cat, dat, fn, ft, id, false, null, fc, ftr, ind, t);
  13073. };
  13074. if (!content) {
  13075. return '';
  13076. }
  13077. isDisabled = isDisabled === undefined ? true : isDisabled;
  13078. cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
  13079. fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
  13080. ftype = $h.ifSet('filetype', config, cat);
  13081. ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
  13082. frameClass = $h.ifSet('frameClass', config);
  13083. if (asData) {
  13084. out = parseTemplate(cat, content, fname, ftype, previewId, ftr, ind, frameClass);
  13085. } else {
  13086. out = parseTemplate('generic', content, fname, ftype, previewId, ftr, ind, frameClass, cat)
  13087. .setTokens({'content': data.content[i]});
  13088. }
  13089. if (data.tags.length && data.tags[i]) {
  13090. out = $h.replaceTags(out, data.tags[i]);
  13091. }
  13092. /** @namespace config.frameAttr */
  13093. if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
  13094. $tmp = $(document.createElement('div')).html(out);
  13095. $tmp.find('.file-preview-initial').attr(config.frameAttr);
  13096. out = $tmp.html();
  13097. $tmp.remove();
  13098. }
  13099. return out;
  13100. },
  13101. add: function (content, config, tags, append) {
  13102. var data = self.previewCache.data, index;
  13103. if (!$h.isArray(content)) {
  13104. content = content.split(self.initialPreviewDelimiter);
  13105. }
  13106. if (append) {
  13107. index = data.content.push(content) - 1;
  13108. data.config[index] = config;
  13109. data.tags[index] = tags;
  13110. } else {
  13111. index = content.length - 1;
  13112. data.content = content;
  13113. data.config = config;
  13114. data.tags = tags;
  13115. }
  13116. self.previewCache.data = data;
  13117. return index;
  13118. },
  13119. set: function (content, config, tags, append) {
  13120. var data = self.previewCache.data, i, chk;
  13121. if (!content || !content.length) {
  13122. return;
  13123. }
  13124. if (!$h.isArray(content)) {
  13125. content = content.split(self.initialPreviewDelimiter);
  13126. }
  13127. chk = content.filter(function (n) {
  13128. return n !== null;
  13129. });
  13130. if (!chk.length) {
  13131. return;
  13132. }
  13133. if (data.content === undefined) {
  13134. data.content = [];
  13135. }
  13136. if (data.config === undefined) {
  13137. data.config = [];
  13138. }
  13139. if (data.tags === undefined) {
  13140. data.tags = [];
  13141. }
  13142. if (append) {
  13143. for (i = 0; i < content.length; i++) {
  13144. if (content[i]) {
  13145. data.content.push(content[i]);
  13146. }
  13147. }
  13148. for (i = 0; i < config.length; i++) {
  13149. if (config[i]) {
  13150. data.config.push(config[i]);
  13151. }
  13152. }
  13153. for (i = 0; i < tags.length; i++) {
  13154. if (tags[i]) {
  13155. data.tags.push(tags[i]);
  13156. }
  13157. }
  13158. } else {
  13159. data.content = content;
  13160. data.config = config;
  13161. data.tags = tags;
  13162. }
  13163. self.previewCache.data = data;
  13164. },
  13165. unset: function (index) {
  13166. var chk = self.previewCache.count();
  13167. if (!chk) {
  13168. return;
  13169. }
  13170. if (chk === 1) {
  13171. self.previewCache.data.content = [];
  13172. self.previewCache.data.config = [];
  13173. self.previewCache.data.tags = [];
  13174. self.initialPreview = [];
  13175. self.initialPreviewConfig = [];
  13176. self.initialPreviewThumbTags = [];
  13177. return;
  13178. }
  13179. self.previewCache.data.content[index] = null;
  13180. self.previewCache.data.config[index] = null;
  13181. self.previewCache.data.tags[index] = null;
  13182. },
  13183. out: function () {
  13184. var html = '', caption, len = self.previewCache.count(true), i;
  13185. if (len === 0) {
  13186. return {content: '', caption: ''};
  13187. }
  13188. for (i = 0; i < len; i++) {
  13189. html += self.previewCache.get(i);
  13190. }
  13191. caption = self._getMsgSelected(self.previewCache.count());
  13192. return {content: html, caption: caption};
  13193. },
  13194. footer: function (i, isDisabled, size) {
  13195. var data = self.previewCache.data;
  13196. if (!data || !data.config || data.config.length === 0 || $h.isEmpty(data.config[i])) {
  13197. return '';
  13198. }
  13199. isDisabled = isDisabled === undefined ? true : isDisabled;
  13200. var config = data.config[i], caption = $h.ifSet('caption', config), actions,
  13201. width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
  13202. key = $h.ifSet('key', config, null), fs = self.fileActionSettings,
  13203. initPreviewShowDel = self.initialPreviewShowDelete || false,
  13204. showDel = $h.ifSet('showDelete', config, $h.ifSet('showDelete', fs, initPreviewShowDel)),
  13205. showZoom = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
  13206. showDrag = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
  13207. disabled = (url === false) && isDisabled;
  13208. actions = self._renderFileActions(false, showDel, showZoom, showDrag, disabled, url, key, true);
  13209. return self._getLayoutTemplate('footer').setTokens({
  13210. 'progress': self._renderThumbProgress(),
  13211. 'actions': actions,
  13212. 'caption': caption,
  13213. 'size': self._getSize(size),
  13214. 'width': width,
  13215. 'indicator': ''
  13216. });
  13217. }
  13218. };
  13219. self.previewCache.init();
  13220. },
  13221. _handler: function ($el, event, callback) {
  13222. var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
  13223. if (!$el || !$el.length) {
  13224. return;
  13225. }
  13226. $el.off(ev).on(ev, callback);
  13227. },
  13228. _log: function (msg) {
  13229. var self = this, id = self.$element.attr('id');
  13230. if (id) {
  13231. msg = '"' + id + '": ' + msg;
  13232. }
  13233. if (typeof window.console.log !== "undefined") {
  13234. window.console.log(msg);
  13235. } else {
  13236. window.alert(msg);
  13237. }
  13238. },
  13239. _validate: function () {
  13240. var self = this, status = self.$element.attr('type') === 'file';
  13241. if (!status) {
  13242. self._log('The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.');
  13243. }
  13244. return status;
  13245. },
  13246. _errorsExist: function () {
  13247. var self = this, $err;
  13248. if (self.$errorContainer.find('li').length) {
  13249. return true;
  13250. }
  13251. $err = $(document.createElement('div')).html(self.$errorContainer.html());
  13252. $err.find('span.kv-error-close').remove();
  13253. $err.find('ul').remove();
  13254. return $.trim($err.text()).length ? true : false;
  13255. },
  13256. _errorHandler: function (evt, caption) {
  13257. var self = this, err = evt.target.error, showError = function (msg) {
  13258. self._showError(msg.replace('{name}', caption));
  13259. };
  13260. /** @namespace err.NOT_FOUND_ERR */
  13261. /** @namespace err.SECURITY_ERR */
  13262. /** @namespace err.NOT_READABLE_ERR */
  13263. if (err.code === err.NOT_FOUND_ERR) {
  13264. showError(self.msgFileNotFound);
  13265. } else if (err.code === err.SECURITY_ERR) {
  13266. showError(self.msgFileSecured);
  13267. } else if (err.code === err.NOT_READABLE_ERR) {
  13268. showError(self.msgFileNotReadable);
  13269. } else if (err.code === err.ABORT_ERR) {
  13270. showError(self.msgFilePreviewAborted);
  13271. } else {
  13272. showError(self.msgFilePreviewError);
  13273. }
  13274. },
  13275. _addError: function (msg) {
  13276. var self = this, $error = self.$errorContainer;
  13277. if (msg && $error.length) {
  13278. $error.html(self.errorCloseButton + msg);
  13279. self._handler($error.find('.kv-error-close'), 'click', function () {
  13280. $error.fadeOut('slow');
  13281. });
  13282. }
  13283. },
  13284. _resetErrors: function (fade) {
  13285. var self = this, $error = self.$errorContainer;
  13286. self.isError = false;
  13287. self.$container.removeClass('has-error');
  13288. $error.html('');
  13289. if (fade) {
  13290. $error.fadeOut('slow');
  13291. } else {
  13292. $error.hide();
  13293. }
  13294. },
  13295. _showFolderError: function (folders) {
  13296. var self = this, $error = self.$errorContainer, msg;
  13297. if (!folders) {
  13298. return;
  13299. }
  13300. msg = self.msgFoldersNotAllowed.replace('{n}', folders);
  13301. self._addError(msg);
  13302. $h.addCss(self.$container, 'has-error');
  13303. $error.fadeIn(800);
  13304. self._raise('filefoldererror', [folders, msg]);
  13305. },
  13306. _showUploadError: function (msg, params, event) {
  13307. var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror', e = params && params.id ?
  13308. '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
  13309. if ($error.find('ul').length === 0) {
  13310. self._addError('<ul>' + e + '</ul>');
  13311. } else {
  13312. $error.find('ul').append(e);
  13313. }
  13314. $error.fadeIn(800);
  13315. self._raise(ev, [params, msg]);
  13316. self.$container.removeClass('file-input-new');
  13317. $h.addCss(self.$container, 'has-error');
  13318. return true;
  13319. },
  13320. _showError: function (msg, params, event) {
  13321. var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
  13322. params = params || {};
  13323. params.reader = self.reader;
  13324. self._addError(msg);
  13325. $error.fadeIn(800);
  13326. self._raise(ev, [params, msg]);
  13327. if (!self.isUploadable) {
  13328. self._clearFileInput();
  13329. }
  13330. self.$container.removeClass('file-input-new');
  13331. $h.addCss(self.$container, 'has-error');
  13332. self.$btnUpload.attr('disabled', true);
  13333. return true;
  13334. },
  13335. _noFilesError: function (params) {
  13336. var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
  13337. msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
  13338. $error = self.$errorContainer;
  13339. self._addError(msg);
  13340. self.isError = true;
  13341. self._updateFileDetails(0);
  13342. $error.fadeIn(800);
  13343. self._raise('fileerror', [params, msg]);
  13344. self._clearFileInput();
  13345. $h.addCss(self.$container, 'has-error');
  13346. },
  13347. _parseError: function (operation, jqXHR, errorThrown, fileName) {
  13348. /** @namespace jqXHR.responseJSON */
  13349. var self = this, errMsg = $.trim(errorThrown + ''), dot = errMsg.slice(-1) === '.' ? '' : '.',
  13350. text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
  13351. jqXHR.responseJSON.error : jqXHR.responseText;
  13352. if (self.cancelling && self.msgUploadAborted) {
  13353. errMsg = self.msgUploadAborted;
  13354. }
  13355. if (self.showAjaxErrorDetails && text) {
  13356. text = $.trim(text.replace(/\n\s*\n/g, '\n'));
  13357. text = text.length > 0 ? '<pre>' + text + '</pre>' : '';
  13358. errMsg += dot + text;
  13359. } else {
  13360. errMsg += dot;
  13361. }
  13362. if (errMsg === dot) {
  13363. errMsg = self.msgAjaxError.replace('{operation}', operation);
  13364. }
  13365. self.cancelling = false;
  13366. return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
  13367. },
  13368. _parseFileType: function (file) {
  13369. var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
  13370. for (i = 0; i < types.length; i++) {
  13371. cat = types[i];
  13372. isValid = self.fileTypeSettings[cat];
  13373. vType = isValid(file.type, file.name) ? cat : '';
  13374. if (!$h.isEmpty(vType)) {
  13375. return vType;
  13376. }
  13377. }
  13378. return 'other';
  13379. },
  13380. _getPreviewIcon: function (fname) {
  13381. var self = this, ext, out = null;
  13382. if (fname && fname.indexOf('.') > -1) {
  13383. ext = fname.split('.').pop();
  13384. if (self.previewFileIconSettings) {
  13385. out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
  13386. }
  13387. if (self.previewFileExtSettings) {
  13388. $.each(self.previewFileExtSettings, function (key, func) {
  13389. if (self.previewFileIconSettings[key] && func(ext)) {
  13390. out = self.previewFileIconSettings[key];
  13391. //noinspection UnnecessaryReturnStatementJS
  13392. return;
  13393. }
  13394. });
  13395. }
  13396. }
  13397. return out;
  13398. },
  13399. _parseFilePreviewIcon: function (content, fname) {
  13400. var self = this, icn = self._getPreviewIcon(fname) || self.previewFileIcon, out = content;
  13401. if (out.indexOf('{previewFileIcon}') > -1) {
  13402. out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
  13403. }
  13404. return out;
  13405. },
  13406. _raise: function (event, params) {
  13407. var self = this, e = $.Event(event);
  13408. if (params !== undefined) {
  13409. self.$element.trigger(e, params);
  13410. } else {
  13411. self.$element.trigger(e);
  13412. }
  13413. if (e.isDefaultPrevented() || e.result === false) {
  13414. return false;
  13415. }
  13416. switch (event) {
  13417. // ignore these events
  13418. case 'filebatchuploadcomplete':
  13419. case 'filebatchuploadsuccess':
  13420. case 'fileuploaded':
  13421. case 'fileclear':
  13422. case 'filecleared':
  13423. case 'filereset':
  13424. case 'fileerror':
  13425. case 'filefoldererror':
  13426. case 'fileuploaderror':
  13427. case 'filebatchuploaderror':
  13428. case 'filedeleteerror':
  13429. case 'filecustomerror':
  13430. case 'filesuccessremove':
  13431. break;
  13432. // receive data response via `filecustomerror` event`
  13433. default:
  13434. if (!self.ajaxAborted) {
  13435. self.ajaxAborted = e.result;
  13436. }
  13437. break;
  13438. }
  13439. return true;
  13440. },
  13441. _listenFullScreen: function (isFullScreen) {
  13442. var self = this, $modal = self.$modal, $btnFull, $btnBord;
  13443. if (!$modal || !$modal.length) {
  13444. return;
  13445. }
  13446. $btnFull = $modal && $modal.find('.btn-fullscreen');
  13447. $btnBord = $modal && $modal.find('.btn-borderless');
  13448. if (!$btnFull.length || !$btnBord.length) {
  13449. return;
  13450. }
  13451. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  13452. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  13453. if (isFullScreen) {
  13454. $btnFull.addClass('active').attr('aria-pressed', 'true');
  13455. } else {
  13456. $btnBord.addClass('active').attr('aria-pressed', 'true');
  13457. }
  13458. if ($modal.hasClass('file-zoom-fullscreen')) {
  13459. self._maximizeZoomDialog();
  13460. } else {
  13461. if (isFullScreen) {
  13462. self._maximizeZoomDialog();
  13463. } else {
  13464. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  13465. }
  13466. }
  13467. },
  13468. _listen: function () {
  13469. var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEvents;
  13470. self._handler($el, 'change', $.proxy(self._change, self));
  13471. if (self.showBrowse) {
  13472. self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
  13473. }
  13474. self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
  13475. self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
  13476. self._initDragDrop();
  13477. self._handler($form, 'reset', $.proxy(self.reset, self));
  13478. if (!self.isUploadable) {
  13479. self._handler($form, 'submit', $.proxy(self._submitForm, self));
  13480. }
  13481. self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
  13482. self._handler($(window), 'resize', function () {
  13483. self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
  13484. });
  13485. fullScreenEvents = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
  13486. self._handler($(document), fullScreenEvents, function () {
  13487. self._listenFullScreen($h.checkFullScreen());
  13488. });
  13489. self._initClickable();
  13490. },
  13491. _initClickable: function () {
  13492. var self = this, $zone;
  13493. if (!self.isClickable) {
  13494. return;
  13495. }
  13496. $zone = self.isUploadable ? self.$dropZone : self.$preview.find('.file-default-preview');
  13497. $h.addCss($zone, 'clickable');
  13498. $zone.attr('tabindex', -1);
  13499. self._handler($zone, 'click', function (e) {
  13500. var $tar = $(e.target);
  13501. if (!$tar.parents('.file-preview-thumbnails').length || $tar.parents('.file-default-preview').length) {
  13502. self.$element.trigger('click');
  13503. $zone.blur();
  13504. }
  13505. });
  13506. },
  13507. _initDragDrop: function () {
  13508. var self = this, $zone = self.$dropZone;
  13509. if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
  13510. self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
  13511. self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
  13512. self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
  13513. self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
  13514. }
  13515. },
  13516. _zoneDragDropInit: function (e) {
  13517. e.stopPropagation();
  13518. e.preventDefault();
  13519. },
  13520. _zoneDragEnter: function (e) {
  13521. var self = this, hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
  13522. self._zoneDragDropInit(e);
  13523. if (self.isDisabled || !hasFiles) {
  13524. e.originalEvent.dataTransfer.effectAllowed = 'none';
  13525. e.originalEvent.dataTransfer.dropEffect = 'none';
  13526. return;
  13527. }
  13528. $h.addCss(self.$dropZone, 'file-highlighted');
  13529. },
  13530. _zoneDragLeave: function (e) {
  13531. var self = this;
  13532. self._zoneDragDropInit(e);
  13533. if (self.isDisabled) {
  13534. return;
  13535. }
  13536. self.$dropZone.removeClass('file-highlighted');
  13537. },
  13538. _zoneDrop: function (e) {
  13539. var self = this;
  13540. e.preventDefault();
  13541. /** @namespace e.originalEvent.dataTransfer */
  13542. if (self.isDisabled || $h.isEmpty(e.originalEvent.dataTransfer.files)) {
  13543. return;
  13544. }
  13545. self._change(e, 'dragdrop');
  13546. self.$dropZone.removeClass('file-highlighted');
  13547. },
  13548. _uploadClick: function (e) {
  13549. var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
  13550. isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
  13551. if (e && e.isDefaultPrevented()) {
  13552. return;
  13553. }
  13554. if (!self.isUploadable) {
  13555. if (isEnabled && $btn.attr('type') !== 'submit') {
  13556. $form = $btn.closest('form');
  13557. // downgrade to normal form submit if possible
  13558. if ($form.length) {
  13559. $form.trigger('submit');
  13560. }
  13561. e.preventDefault();
  13562. }
  13563. return;
  13564. }
  13565. e.preventDefault();
  13566. if (isEnabled) {
  13567. self.upload();
  13568. }
  13569. },
  13570. _submitForm: function () {
  13571. var self = this;
  13572. return self._isFileSelectionValid() && !self._abort({});
  13573. },
  13574. _clearPreview: function () {
  13575. var self = this, $p = self.$preview,
  13576. $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
  13577. $thumbs.each(function () {
  13578. var $thumb = $(this);
  13579. $thumb.remove();
  13580. $h.cleanZoomCache($p.find('#zoom-' + $thumb.attr('id')));
  13581. });
  13582. if (!self.getFrames().length || !self.showPreview) {
  13583. self._resetUpload();
  13584. }
  13585. self._validateDefaultPreview();
  13586. },
  13587. _initSortable: function () {
  13588. var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS;
  13589. if (!window.KvSortable || $el.find(selector).length === 0) {
  13590. return;
  13591. }
  13592. //noinspection JSUnusedGlobalSymbols
  13593. settings = {
  13594. handle: '.drag-handle-init',
  13595. dataIdAttr: 'data-preview-id',
  13596. scroll: false,
  13597. draggable: selector,
  13598. onSort: function (e) {
  13599. var oldIndex = e.oldIndex, newIndex = e.newIndex, key, $frame;
  13600. self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex);
  13601. self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex);
  13602. self.previewCache.init();
  13603. for (var i = 0; i < self.initialPreviewConfig.length; i++) {
  13604. if (self.initialPreviewConfig[i] !== null) {
  13605. key = self.initialPreviewConfig[i].key;
  13606. $frame = $(".kv-file-remove[data-key='" + key + "']").closest($h.FRAMES);
  13607. $frame.attr('data-fileindex', 'init_' + i).attr('data-fileindex', 'init_' + i);
  13608. }
  13609. }
  13610. self._raise('filesorted', {
  13611. previewId: $(e.item).attr('id'),
  13612. 'oldIndex': oldIndex,
  13613. 'newIndex': newIndex,
  13614. stack: self.initialPreviewConfig
  13615. });
  13616. }
  13617. };
  13618. if ($el.data('kvsortable')) {
  13619. $el.kvsortable('destroy');
  13620. }
  13621. $.extend(true, settings, self.fileActionSettings.dragSettings);
  13622. $el.kvsortable(settings);
  13623. },
  13624. _initPreview: function (isInit) {
  13625. var self = this, cap = self.initialCaption || '', out;
  13626. if (!self.previewCache.count()) {
  13627. self._clearPreview();
  13628. if (isInit) {
  13629. self._setCaption(cap);
  13630. } else {
  13631. self._initCaption();
  13632. }
  13633. return;
  13634. }
  13635. out = self.previewCache.out();
  13636. cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
  13637. self.$preview.html(out.content);
  13638. self._setInitThumbAttr();
  13639. self._setCaption(cap);
  13640. self._initSortable();
  13641. if (!$h.isEmpty(out.content)) {
  13642. self.$container.removeClass('file-input-new');
  13643. }
  13644. },
  13645. _getZoomButton: function (type) {
  13646. var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
  13647. title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ',
  13648. params = title + (type === 'close' ? ' data-dismiss="modal" aria-hidden="true"' : '');
  13649. if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
  13650. params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
  13651. }
  13652. return '<button type="button" class="' + css + ' btn-' + type + '"' + params + '>' + label + '</button>';
  13653. },
  13654. _getModalContent: function () {
  13655. var self = this;
  13656. return self._getLayoutTemplate('modal').setTokens({
  13657. 'rtl': self.rtl ? ' kv-rtl' : '',
  13658. 'zoomFrameClass': self.frameClass,
  13659. 'heading': self.msgZoomModalHeading,
  13660. 'prev': self._getZoomButton('prev'),
  13661. 'next': self._getZoomButton('next'),
  13662. 'toggleheader': self._getZoomButton('toggleheader'),
  13663. 'fullscreen': self._getZoomButton('fullscreen'),
  13664. 'borderless': self._getZoomButton('borderless'),
  13665. 'close': self._getZoomButton('close')
  13666. });
  13667. },
  13668. _listenModalEvent: function (event) {
  13669. var self = this, $modal = self.$modal, getParams = function (e) {
  13670. return {
  13671. sourceEvent: e,
  13672. previewId: $modal.data('previewId'),
  13673. modal: $modal
  13674. };
  13675. };
  13676. $modal.on(event + '.bs.modal', function (e) {
  13677. var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
  13678. self._raise('filezoom' + event, getParams(e));
  13679. if (event === 'shown') {
  13680. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  13681. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  13682. if ($modal.hasClass('file-zoom-fullscreen')) {
  13683. self._maximizeZoomDialog();
  13684. if ($h.checkFullScreen()) {
  13685. $btnFull.addClass('active').attr('aria-pressed', 'true');
  13686. } else {
  13687. $btnBord.addClass('active').attr('aria-pressed', 'true');
  13688. }
  13689. }
  13690. }
  13691. });
  13692. },
  13693. _initZoom: function () {
  13694. var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
  13695. if (!self.showPreview) {
  13696. return;
  13697. }
  13698. self.$modal = $(modalId);
  13699. if (!self.$modal || !self.$modal.length) {
  13700. $dialog = $(document.createElement('div')).html(modalMain).insertAfter(self.$container);
  13701. self.$modal = $(modalId).insertBefore($dialog);
  13702. $dialog.remove();
  13703. }
  13704. $h.initModal(self.$modal);
  13705. self.$modal.html(self._getModalContent());
  13706. $.each($h.MODAL_EVENTS, function (key, event) {
  13707. self._listenModalEvent(event);
  13708. });
  13709. },
  13710. _initZoomButtons: function () {
  13711. var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
  13712. thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-prev'),
  13713. $next = self.$modal.find('.btn-next');
  13714. if (thumbs.length < 2) {
  13715. $prev.hide();
  13716. $next.hide();
  13717. return;
  13718. } else {
  13719. $prev.show();
  13720. $next.show();
  13721. }
  13722. if (!len) {
  13723. return;
  13724. }
  13725. $first = $(thumbs[0]);
  13726. $last = $(thumbs[len - 1]);
  13727. $prev.removeAttr('disabled');
  13728. $next.removeAttr('disabled');
  13729. if ($first.length && $first.attr('id') === previewId) {
  13730. $prev.attr('disabled', true);
  13731. }
  13732. if ($last.length && $last.attr('id') === previewId) {
  13733. $next.attr('disabled', true);
  13734. }
  13735. },
  13736. _maximizeZoomDialog: function () {
  13737. var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
  13738. $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.modal-body'),
  13739. h = $(window).height(), diff = 0;
  13740. $modal.addClass('file-zoom-fullscreen');
  13741. if ($head && $head.length) {
  13742. h -= $head.outerHeight(true);
  13743. }
  13744. if ($foot && $foot.length) {
  13745. h -= $foot.outerHeight(true);
  13746. }
  13747. if ($body && $body.length) {
  13748. diff = $body.outerHeight(true) - $body.height();
  13749. h -= diff;
  13750. }
  13751. $modal.find('.kv-zoom-body').height(h);
  13752. },
  13753. _resizeZoomDialog: function (fullScreen) {
  13754. var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-fullscreen'),
  13755. $btnBord = $modal.find('.btn-borderless');
  13756. if ($modal.hasClass('file-zoom-fullscreen')) {
  13757. $h.toggleFullScreen(false);
  13758. if (!fullScreen) {
  13759. if (!$btnFull.hasClass('active')) {
  13760. $modal.removeClass('file-zoom-fullscreen');
  13761. self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
  13762. } else {
  13763. $btnFull.removeClass('active').attr('aria-pressed', 'false');
  13764. }
  13765. } else {
  13766. if (!$btnFull.hasClass('active')) {
  13767. $modal.removeClass('file-zoom-fullscreen');
  13768. self._resizeZoomDialog(true);
  13769. if ($btnBord.hasClass('active')) {
  13770. $btnBord.removeClass('active').attr('aria-pressed', 'false');
  13771. }
  13772. }
  13773. }
  13774. } else {
  13775. if (!fullScreen) {
  13776. self._maximizeZoomDialog();
  13777. return;
  13778. }
  13779. $h.toggleFullScreen(true);
  13780. }
  13781. $modal.focus();
  13782. },
  13783. _setZoomContent: function ($frame, animate) {
  13784. var self = this, $content, tmplt, body, title, $body, $dataEl, config, pid = $frame.attr('id'),
  13785. $modal = self.$modal, $prev = $modal.find('.btn-prev'), $next = $modal.find('.btn-next'), $tmp,
  13786. $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless'), cap, size,
  13787. $btnTogh = $modal.find('.btn-toggleheader'), $zoomPreview = self.$preview.find('#zoom-' + pid);
  13788. tmplt = $zoomPreview.attr('data-template') || 'generic';
  13789. $content = $zoomPreview.find('.kv-file-content');
  13790. body = $content.length ? $content.html() : '';
  13791. cap = $frame.data('caption') || '';
  13792. size = $frame.data('size') || '';
  13793. title = cap + ' ' + size;
  13794. $modal.find('.kv-zoom-title').html(title);
  13795. $body = $modal.find('.kv-zoom-body');
  13796. $modal.removeClass('kv-single-content');
  13797. if (animate) {
  13798. $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
  13799. $body.html(body).hide();
  13800. $tmp.fadeOut('fast', function () {
  13801. $body.fadeIn('fast', function () {
  13802. $body.removeClass('file-thumb-loading');
  13803. });
  13804. $tmp.remove();
  13805. });
  13806. } else {
  13807. $body.html(body);
  13808. }
  13809. config = self.previewZoomSettings[tmplt];
  13810. if (config) {
  13811. $dataEl = $body.find('.kv-preview-data');
  13812. $h.addCss($dataEl, 'file-zoom-detail');
  13813. $.each(config, function (key, value) {
  13814. $dataEl.css(key, value);
  13815. if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
  13816. $dataEl.removeAttr(key);
  13817. }
  13818. });
  13819. }
  13820. $modal.data('previewId', pid);
  13821. var $img = $body.find('img');
  13822. if ($img.length) {
  13823. $h.adjustOrientedImage($img, true);
  13824. }
  13825. self._handler($prev, 'click', function () {
  13826. self._zoomSlideShow('prev', pid);
  13827. });
  13828. self._handler($next, 'click', function () {
  13829. self._zoomSlideShow('next', pid);
  13830. });
  13831. self._handler($btnFull, 'click', function () {
  13832. self._resizeZoomDialog(true);
  13833. });
  13834. self._handler($btnBord, 'click', function () {
  13835. self._resizeZoomDialog(false);
  13836. });
  13837. self._handler($btnTogh, 'click', function () {
  13838. var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.modal-body .floating-buttons'),
  13839. ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
  13840. var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
  13841. if ($modal.hasClass('file-zoom-fullscreen')) {
  13842. h = $body.outerHeight(true);
  13843. if (!height) {
  13844. h = h - $header.outerHeight(true);
  13845. }
  13846. }
  13847. $body.css('height', height ? h + height : h);
  13848. };
  13849. if ($header.is(':visible')) {
  13850. ht = $header.outerHeight(true);
  13851. $header.slideUp('slow', function () {
  13852. $actions.find('.btn').appendTo($floatBar);
  13853. resize(ht);
  13854. });
  13855. } else {
  13856. $floatBar.find('.btn').appendTo($actions);
  13857. $header.slideDown('slow', function () {
  13858. resize();
  13859. });
  13860. }
  13861. $modal.focus();
  13862. });
  13863. self._handler($modal, 'keydown', function (e) {
  13864. var key = e.which || e.keyCode;
  13865. if (key === 37 && !$prev.attr('disabled')) {
  13866. self._zoomSlideShow('prev', pid);
  13867. }
  13868. if (key === 39 && !$next.attr('disabled')) {
  13869. self._zoomSlideShow('next', pid);
  13870. }
  13871. });
  13872. },
  13873. _zoomPreview: function ($btn) {
  13874. var self = this, $frame, $modal = self.$modal;
  13875. if (!$btn.length) {
  13876. throw 'Cannot zoom to detailed preview!';
  13877. }
  13878. $h.initModal($modal);
  13879. $modal.html(self._getModalContent());
  13880. $frame = $btn.closest($h.FRAMES);
  13881. self._setZoomContent($frame);
  13882. $modal.modal('show');
  13883. self._initZoomButtons();
  13884. },
  13885. _zoomSlideShow: function (dir, previewId) {
  13886. var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-' + dir), $targFrame, i,
  13887. thumbs = self.getFrames().toArray(), len = thumbs.length, out;
  13888. if ($btn.attr('disabled')) {
  13889. return;
  13890. }
  13891. for (i = 0; i < len; i++) {
  13892. if ($(thumbs[i]).attr('id') === previewId) {
  13893. out = dir === 'prev' ? i - 1 : i + 1;
  13894. break;
  13895. }
  13896. }
  13897. if (out < 0 || out >= len || !thumbs[out]) {
  13898. return;
  13899. }
  13900. $targFrame = $(thumbs[out]);
  13901. if ($targFrame.length) {
  13902. self._setZoomContent($targFrame, true);
  13903. }
  13904. self._initZoomButtons();
  13905. self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
  13906. },
  13907. _initZoomButton: function () {
  13908. var self = this;
  13909. self.$preview.find('.kv-file-zoom').each(function () {
  13910. var $el = $(this);
  13911. self._handler($el, 'click', function () {
  13912. self._zoomPreview($el);
  13913. });
  13914. });
  13915. },
  13916. _clearObjects: function ($el) {
  13917. $el.find('video audio').each(function () {
  13918. this.pause();
  13919. $(this).remove();
  13920. });
  13921. $el.find('img object div').each(function () {
  13922. $(this).remove();
  13923. });
  13924. },
  13925. _clearFileInput: function () {
  13926. var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
  13927. self.fileInputCleared = true;
  13928. if ($h.isEmpty($el.val())) {
  13929. return;
  13930. }
  13931. // Fix for IE ver < 11, that does not clear file inputs. Requires a sequence of steps to prevent IE
  13932. // crashing but still allow clearing of the file input.
  13933. if (self.isIE9 || self.isIE10) {
  13934. $srcFrm = $el.closest('form');
  13935. $tmpFrm = $(document.createElement('form'));
  13936. $tmpEl = $(document.createElement('div'));
  13937. $el.before($tmpEl);
  13938. if ($srcFrm.length) {
  13939. $srcFrm.after($tmpFrm);
  13940. } else {
  13941. $tmpEl.after($tmpFrm);
  13942. }
  13943. $tmpFrm.append($el).trigger('reset');
  13944. $tmpEl.before($el).remove();
  13945. $tmpFrm.remove();
  13946. } else { // normal input clear behavior for other sane browsers
  13947. $el.val('');
  13948. }
  13949. },
  13950. _resetUpload: function () {
  13951. var self = this;
  13952. self.uploadCache = {content: [], config: [], tags: [], append: true};
  13953. self.uploadCount = 0;
  13954. self.uploadStatus = {};
  13955. self.uploadLog = [];
  13956. self.uploadAsyncCount = 0;
  13957. self.loadedImages = [];
  13958. self.totalImagesCount = 0;
  13959. self.$btnUpload.removeAttr('disabled');
  13960. self._setProgress(0);
  13961. $h.addCss(self.$progress, 'hide');
  13962. self._resetErrors(false);
  13963. self.ajaxAborted = false;
  13964. self.ajaxRequests = [];
  13965. self._resetCanvas();
  13966. self.cacheInitialPreview = {};
  13967. if (self.overwriteInitial) {
  13968. self.initialPreview = [];
  13969. self.initialPreviewConfig = [];
  13970. self.initialPreviewThumbTags = [];
  13971. self.previewCache.data = {
  13972. content: [],
  13973. config: [],
  13974. tags: []
  13975. };
  13976. }
  13977. },
  13978. _resetCanvas: function () {
  13979. var self = this;
  13980. if (self.canvas && self.imageCanvasContext) {
  13981. self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
  13982. }
  13983. },
  13984. _hasInitialPreview: function () {
  13985. var self = this;
  13986. return !self.overwriteInitial && self.previewCache.count();
  13987. },
  13988. _resetPreview: function () {
  13989. var self = this, out, cap;
  13990. if (self.previewCache.count()) {
  13991. out = self.previewCache.out();
  13992. self.$preview.html(out.content);
  13993. self._setInitThumbAttr();
  13994. cap = self.initialCaption ? self.initialCaption : out.caption;
  13995. self._setCaption(cap);
  13996. } else {
  13997. self._clearPreview();
  13998. self._initCaption();
  13999. }
  14000. if (self.showPreview) {
  14001. self._initZoom();
  14002. self._initSortable();
  14003. }
  14004. },
  14005. _clearDefaultPreview: function () {
  14006. var self = this;
  14007. self.$preview.find('.file-default-preview').remove();
  14008. },
  14009. _validateDefaultPreview: function () {
  14010. var self = this;
  14011. if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
  14012. return;
  14013. }
  14014. self.$preview.html('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
  14015. self.$container.removeClass('file-input-new');
  14016. self._initClickable();
  14017. },
  14018. _resetPreviewThumbs: function (isAjax) {
  14019. var self = this, out;
  14020. if (isAjax) {
  14021. self._clearPreview();
  14022. self.clearStack();
  14023. return;
  14024. }
  14025. if (self._hasInitialPreview()) {
  14026. out = self.previewCache.out();
  14027. self.$preview.html(out.content);
  14028. self._setInitThumbAttr();
  14029. self._setCaption(out.caption);
  14030. self._initPreviewActions();
  14031. } else {
  14032. self._clearPreview();
  14033. }
  14034. },
  14035. _getLayoutTemplate: function (t) {
  14036. var self = this, template = self.layoutTemplates[t];
  14037. if ($h.isEmpty(self.customLayoutTags)) {
  14038. return template;
  14039. }
  14040. return $h.replaceTags(template, self.customLayoutTags);
  14041. },
  14042. _getPreviewTemplate: function (t) {
  14043. var self = this, template = self.previewTemplates[t];
  14044. if ($h.isEmpty(self.customPreviewTags)) {
  14045. return template;
  14046. }
  14047. return $h.replaceTags(template, self.customPreviewTags);
  14048. },
  14049. _getOutData: function (jqXHR, responseData, filesData) {
  14050. var self = this;
  14051. jqXHR = jqXHR || {};
  14052. responseData = responseData || {};
  14053. filesData = filesData || self.filestack.slice(0) || {};
  14054. return {
  14055. form: self.formdata,
  14056. files: filesData,
  14057. filenames: self.filenames,
  14058. filescount: self.getFilesCount(),
  14059. extra: self._getExtraData(),
  14060. response: responseData,
  14061. reader: self.reader,
  14062. jqXHR: jqXHR
  14063. };
  14064. },
  14065. _getMsgSelected: function (n) {
  14066. var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
  14067. return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) : self.msgNoFilesSelected;
  14068. },
  14069. _getFrame: function (id) {
  14070. var self = this, $frame = $('#' + id);
  14071. if (!$frame.length) {
  14072. self._log('Invalid thumb frame with id: "' + id + '".');
  14073. return null;
  14074. }
  14075. return $frame;
  14076. },
  14077. _getThumbs: function (css) {
  14078. css = css || '';
  14079. return this.getFrames(':not(.file-preview-initial)' + css);
  14080. },
  14081. _getExtraData: function (previewId, index) {
  14082. var self = this, data = self.uploadExtraData;
  14083. if (typeof self.uploadExtraData === "function") {
  14084. data = self.uploadExtraData(previewId, index);
  14085. }
  14086. return data;
  14087. },
  14088. _initXhr: function (xhrobj, previewId, fileCount) {
  14089. var self = this;
  14090. if (xhrobj.upload) {
  14091. xhrobj.upload.addEventListener('progress', function (event) {
  14092. var pct = 0, total = event.total, position = event.loaded || event.position;
  14093. /** @namespace event.lengthComputable */
  14094. if (event.lengthComputable) {
  14095. pct = Math.floor(position / total * 100);
  14096. }
  14097. if (previewId) {
  14098. self._setAsyncUploadStatus(previewId, pct, fileCount);
  14099. } else {
  14100. self._setProgress(pct);
  14101. }
  14102. }, false);
  14103. }
  14104. return xhrobj;
  14105. },
  14106. _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
  14107. var self = this, settings;
  14108. if (!self._raise('filepreajax', [previewId, index])) {
  14109. return;
  14110. }
  14111. self._uploadExtra(previewId, index);
  14112. settings = $.extend(true, {}, {
  14113. xhr: function () {
  14114. var xhrobj = $.ajaxSettings.xhr();
  14115. return self._initXhr(xhrobj, previewId, self.getFileStack().length);
  14116. },
  14117. url: self.uploadUrl,
  14118. type: 'POST',
  14119. dataType: 'json',
  14120. data: self.formdata,
  14121. cache: false,
  14122. processData: false,
  14123. contentType: false,
  14124. beforeSend: fnBefore,
  14125. success: fnSuccess,
  14126. complete: fnComplete,
  14127. error: fnError
  14128. }, self.ajaxSettings);
  14129. self.ajaxRequests.push($.ajax(settings));
  14130. },
  14131. _mergeArray: function (prop, content) {
  14132. var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
  14133. self[prop] = arr1.concat(arr2);
  14134. },
  14135. _initUploadSuccess: function (out, $thumb, allFiles) {
  14136. var self = this, append, data, index, $div, $newCache, content, config, tags, i;
  14137. if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
  14138. return;
  14139. }
  14140. if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
  14141. self.hasInitData = true;
  14142. content = out.initialPreview || [];
  14143. config = out.initialPreviewConfig || [];
  14144. tags = out.initialPreviewThumbTags || [];
  14145. append = out.append === undefined || out.append ? true : false;
  14146. if (content.length > 0 && !$h.isArray(content)) {
  14147. content = content.split(self.initialPreviewDelimiter);
  14148. }
  14149. self._mergeArray('initialPreview', content);
  14150. self._mergeArray('initialPreviewConfig', config);
  14151. self._mergeArray('initialPreviewThumbTags', tags);
  14152. if ($thumb !== undefined) {
  14153. if (!allFiles) {
  14154. index = self.previewCache.add(content, config[0], tags[0], append);
  14155. data = self.previewCache.get(index, false);
  14156. $div = $(document.createElement('div')).html(data).hide().insertAfter($thumb);
  14157. $newCache = $div.find('.kv-zoom-cache');
  14158. if ($newCache && $newCache.length) {
  14159. $newCache.insertAfter($thumb);
  14160. }
  14161. $thumb.fadeOut('slow', function () {
  14162. var $newThumb = $div.find('.file-preview-frame');
  14163. if ($newThumb && $newThumb.length) {
  14164. $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
  14165. }
  14166. self._initPreviewActions();
  14167. self._clearFileInput();
  14168. $h.cleanZoomCache(self.$preview.find('#zoom-' + $thumb.attr('id')));
  14169. $thumb.remove();
  14170. $div.remove();
  14171. self._initSortable();
  14172. });
  14173. } else {
  14174. i = $thumb.attr('data-fileindex');
  14175. self.uploadCache.content[i] = content[0];
  14176. self.uploadCache.config[i] = config[0] || [];
  14177. self.uploadCache.tags[i] = tags[0] || [];
  14178. self.uploadCache.append = append;
  14179. }
  14180. } else {
  14181. self.previewCache.set(content, config, tags, append);
  14182. self._initPreview();
  14183. self._initPreviewActions();
  14184. }
  14185. }
  14186. },
  14187. _initSuccessThumbs: function () {
  14188. var self = this;
  14189. if (!self.showPreview) {
  14190. return;
  14191. }
  14192. self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
  14193. var $thumb = $(this), $preview = self.$preview, $remove = $thumb.find('.kv-file-remove');
  14194. $remove.removeAttr('disabled');
  14195. self._handler($remove, 'click', function () {
  14196. var id = $thumb.attr('id'),
  14197. out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
  14198. $h.cleanMemory($thumb);
  14199. if (out === false) {
  14200. return;
  14201. }
  14202. $thumb.fadeOut('slow', function () {
  14203. $h.cleanZoomCache($preview.find('#zoom-' + id));
  14204. $thumb.remove();
  14205. if (!self.getFrames().length) {
  14206. self.reset();
  14207. }
  14208. });
  14209. });
  14210. });
  14211. },
  14212. _checkAsyncComplete: function () {
  14213. var self = this, previewId, i;
  14214. for (i = 0; i < self.filestack.length; i++) {
  14215. if (self.filestack[i]) {
  14216. previewId = self.previewInitId + "-" + i;
  14217. if ($.inArray(previewId, self.uploadLog) === -1) {
  14218. return false;
  14219. }
  14220. }
  14221. }
  14222. return (self.uploadAsyncCount === self.uploadLog.length);
  14223. },
  14224. _uploadExtra: function (previewId, index) {
  14225. var self = this, data = self._getExtraData(previewId, index);
  14226. if (data.length === 0) {
  14227. return;
  14228. }
  14229. $.each(data, function (key, value) {
  14230. self.formdata.append(key, value);
  14231. });
  14232. },
  14233. _uploadSingle: function (i, files, allFiles) {
  14234. var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
  14235. previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
  14236. hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  14237. $prog = $('#' + previewId).find('.file-thumb-progress'),
  14238. fnBefore, fnSuccess, fnComplete, fnError, updateUploadLog, params = {id: previewId, index: i},
  14239. uploadFailed, multiUploadMode = !$h.isEmpty(self.$element.attr('multiple'));
  14240. self.formdata = formdata;
  14241. if (self.showPreview) {
  14242. $thumb = $('#' + previewId + ':not(.file-preview-initial)');
  14243. $btnUpload = $thumb.find('.kv-file-upload');
  14244. $btnDelete = $thumb.find('.kv-file-remove');
  14245. $prog.removeClass('hide');
  14246. }
  14247. if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self._abort(params)) {
  14248. return;
  14249. }
  14250. updateUploadLog = function (i, previewId) {
  14251. if (multiUploadMode || !uploadFailed) {
  14252. self.updateStack(i, undefined);
  14253. }
  14254. self.uploadLog.push(previewId);
  14255. if (self._checkAsyncComplete()) {
  14256. self.fileBatchCompleted = true;
  14257. }
  14258. };
  14259. chkComplete = function () {
  14260. var u = self.uploadCache, $initThumbs, i, j, len = 0, data = self.cacheInitialPreview;
  14261. if (!self.fileBatchCompleted) {
  14262. return;
  14263. }
  14264. if (data && data.content) {
  14265. len = data.content.length;
  14266. }
  14267. setTimeout(function () {
  14268. var triggerReset = multiUploadMode || !uploadFailed;
  14269. if (self.showPreview) {
  14270. self.previewCache.set(u.content, u.config, u.tags, u.append);
  14271. if (len) {
  14272. for (i = 0; i < u.content.length; i++) {
  14273. j = i + len;
  14274. data.content[j] = u.content[i];
  14275. //noinspection JSUnresolvedVariable
  14276. if (data.config.length) {
  14277. data.config[j] = u.config[i];
  14278. }
  14279. if (data.tags.length) {
  14280. data.tags[j] = u.tags[i];
  14281. }
  14282. }
  14283. self.initialPreview = $h.cleanArray(data.content);
  14284. self.initialPreviewConfig = $h.cleanArray(data.config);
  14285. self.initialPreviewThumbTags = $h.cleanArray(data.tags);
  14286. } else {
  14287. self.initialPreview = u.content;
  14288. self.initialPreviewConfig = u.config;
  14289. self.initialPreviewThumbTags = u.tags;
  14290. }
  14291. self.cacheInitialPreview = {};
  14292. if (self.hasInitData) {
  14293. self._initPreview();
  14294. self._initPreviewActions();
  14295. }
  14296. }
  14297. self.unlock(triggerReset);
  14298. if (triggerReset) {
  14299. self._clearFileInput();
  14300. }
  14301. $initThumbs = self.$preview.find('.file-preview-initial');
  14302. if (self.uploadAsync && $initThumbs.length) {
  14303. $h.addCss($initThumbs, $h.SORT_CSS);
  14304. self._initSortable();
  14305. }
  14306. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  14307. self.uploadCount = 0;
  14308. self.uploadStatus = {};
  14309. self.uploadLog = [];
  14310. self._setProgress(101);
  14311. }, 100);
  14312. };
  14313. fnBefore = function (jqXHR) {
  14314. outData = self._getOutData(jqXHR);
  14315. self.fileBatchCompleted = false;
  14316. if (self.showPreview) {
  14317. if (!$thumb.hasClass('file-preview-success')) {
  14318. self._setThumbStatus($thumb, 'Loading');
  14319. $h.addCss($thumb, 'file-uploading');
  14320. }
  14321. $btnUpload.attr('disabled', true);
  14322. $btnDelete.attr('disabled', true);
  14323. }
  14324. if (!allFiles) {
  14325. self.lock();
  14326. }
  14327. self._raise('filepreupload', [outData, previewId, i]);
  14328. $.extend(true, params, outData);
  14329. if (self._abort(params)) {
  14330. jqXHR.abort();
  14331. self._setProgressCancelled();
  14332. }
  14333. };
  14334. fnSuccess = function (data, textStatus, jqXHR) {
  14335. var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
  14336. outData = self._getOutData(jqXHR, data);
  14337. $.extend(true, params, outData);
  14338. setTimeout(function () {
  14339. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  14340. if (self.showPreview) {
  14341. self._setThumbStatus($thumb, 'Success');
  14342. $btnUpload.hide();
  14343. self._initUploadSuccess(data, $thumb, allFiles);
  14344. self._setProgress(101, $prog);
  14345. }
  14346. self._raise('fileuploaded', [outData, pid, i]);
  14347. if (!allFiles) {
  14348. self.updateStack(i, undefined);
  14349. } else {
  14350. updateUploadLog(i, pid);
  14351. }
  14352. } else {
  14353. uploadFailed = true;
  14354. self._showUploadError(data.error, params);
  14355. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  14356. if (allFiles) {
  14357. updateUploadLog(i, pid);
  14358. }
  14359. }
  14360. }, 100);
  14361. };
  14362. fnComplete = function () {
  14363. setTimeout(function () {
  14364. if (self.showPreview) {
  14365. $btnUpload.removeAttr('disabled');
  14366. $btnDelete.removeAttr('disabled');
  14367. $thumb.removeClass('file-uploading');
  14368. }
  14369. if (!allFiles) {
  14370. self.unlock(false);
  14371. self._clearFileInput();
  14372. } else {
  14373. chkComplete();
  14374. }
  14375. self._initSuccessThumbs();
  14376. }, 100);
  14377. };
  14378. fnError = function (jqXHR, textStatus, errorThrown) {
  14379. var op = self.ajaxOperations.uploadThumb,
  14380. errMsg = self._parseError(op, jqXHR, errorThrown, (allFiles ? files[i].name : null));
  14381. uploadFailed = true;
  14382. setTimeout(function () {
  14383. if (allFiles) {
  14384. updateUploadLog(i, previewId);
  14385. }
  14386. self.uploadStatus[previewId] = 100;
  14387. self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
  14388. $.extend(true, params, self._getOutData(jqXHR));
  14389. self._setProgress(101, $prog, self.msgAjaxProgressError.replace('{operation}', op));
  14390. self._showUploadError(errMsg, params);
  14391. }, 100);
  14392. };
  14393. formdata.append(self.uploadFileAttr, files[i], self.filenames[i]);
  14394. formdata.append('file_id', i);
  14395. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
  14396. },
  14397. _uploadBatch: function () {
  14398. var self = this, files = self.filestack, total = files.length, params = {}, fnBefore, fnSuccess, fnError,
  14399. fnComplete, hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
  14400. setAllUploaded;
  14401. self.formdata = new FormData();
  14402. if (total === 0 || !hasPostData || self._abort(params)) {
  14403. return;
  14404. }
  14405. setAllUploaded = function () {
  14406. $.each(files, function (key) {
  14407. self.updateStack(key, undefined);
  14408. });
  14409. self._clearFileInput();
  14410. };
  14411. fnBefore = function (jqXHR) {
  14412. self.lock();
  14413. var outData = self._getOutData(jqXHR);
  14414. if (self.showPreview) {
  14415. self._getThumbs().each(function () {
  14416. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
  14417. $btnDelete = $thumb.find('.kv-file-remove');
  14418. if (!$thumb.hasClass('file-preview-success')) {
  14419. self._setThumbStatus($thumb, 'Loading');
  14420. $h.addCss($thumb, 'file-uploading');
  14421. }
  14422. $btnUpload.attr('disabled', true);
  14423. $btnDelete.attr('disabled', true);
  14424. });
  14425. }
  14426. self._raise('filebatchpreupload', [outData]);
  14427. if (self._abort(outData)) {
  14428. jqXHR.abort();
  14429. self._setProgressCancelled();
  14430. }
  14431. };
  14432. fnSuccess = function (data, textStatus, jqXHR) {
  14433. /** @namespace data.errorkeys */
  14434. var outData = self._getOutData(jqXHR, data), $thumbs = self._getThumbs(':not(.file-preview-error)'),
  14435. key = 0,
  14436. keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
  14437. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  14438. self._raise('filebatchuploadsuccess', [outData]);
  14439. setAllUploaded();
  14440. if (self.showPreview) {
  14441. $thumbs.each(function () {
  14442. var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload');
  14443. $thumb.find('.kv-file-upload').hide();
  14444. self._setThumbStatus($thumb, 'Success');
  14445. $thumb.removeClass('file-uploading');
  14446. $btnUpload.removeAttr('disabled');
  14447. });
  14448. self._initUploadSuccess(data);
  14449. } else {
  14450. self.reset();
  14451. }
  14452. self._setProgress(101);
  14453. } else {
  14454. if (self.showPreview) {
  14455. $thumbs.each(function () {
  14456. var $thumb = $(this), $btnDelete = $thumb.find('.kv-file-remove'),
  14457. $btnUpload = $thumb.find('.kv-file-upload');
  14458. $thumb.removeClass('file-uploading');
  14459. $btnUpload.removeAttr('disabled');
  14460. $btnDelete.removeAttr('disabled');
  14461. if (keys.length === 0) {
  14462. self._setPreviewError($thumb);
  14463. return;
  14464. }
  14465. if ($.inArray(key, keys) !== -1) {
  14466. self._setPreviewError($thumb);
  14467. } else {
  14468. $thumb.find('.kv-file-upload').hide();
  14469. self._setThumbStatus($thumb, 'Success');
  14470. self.updateStack(key, undefined);
  14471. }
  14472. key++;
  14473. });
  14474. self._initUploadSuccess(data);
  14475. }
  14476. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  14477. }
  14478. };
  14479. fnComplete = function () {
  14480. self.unlock();
  14481. self._initSuccessThumbs();
  14482. self._clearFileInput();
  14483. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  14484. };
  14485. fnError = function (jqXHR, textStatus, errorThrown) {
  14486. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadBatch,
  14487. errMsg = self._parseError(op, jqXHR, errorThrown);
  14488. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  14489. self.uploadFileCount = total - 1;
  14490. if (!self.showPreview) {
  14491. return;
  14492. }
  14493. self._getThumbs().each(function () {
  14494. var $thumb = $(this), key = $thumb.attr('data-fileindex');
  14495. $thumb.removeClass('file-uploading');
  14496. if (self.filestack[key] !== undefined) {
  14497. self._setPreviewError($thumb);
  14498. }
  14499. });
  14500. self._getThumbs().removeClass('file-uploading');
  14501. self._getThumbs(' .kv-file-upload').removeAttr('disabled');
  14502. self._getThumbs(' .kv-file-delete').removeAttr('disabled');
  14503. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  14504. };
  14505. $.each(files, function (key, data) {
  14506. if (!$h.isEmpty(files[key])) {
  14507. self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
  14508. }
  14509. });
  14510. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  14511. },
  14512. _uploadExtraOnly: function () {
  14513. var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
  14514. self.formdata = new FormData();
  14515. if (self._abort(params)) {
  14516. return;
  14517. }
  14518. fnBefore = function (jqXHR) {
  14519. self.lock();
  14520. var outData = self._getOutData(jqXHR);
  14521. self._raise('filebatchpreupload', [outData]);
  14522. self._setProgress(50);
  14523. params.data = outData;
  14524. params.xhr = jqXHR;
  14525. if (self._abort(params)) {
  14526. jqXHR.abort();
  14527. self._setProgressCancelled();
  14528. }
  14529. };
  14530. fnSuccess = function (data, textStatus, jqXHR) {
  14531. var outData = self._getOutData(jqXHR, data);
  14532. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  14533. self._raise('filebatchuploadsuccess', [outData]);
  14534. self._clearFileInput();
  14535. self._initUploadSuccess(data);
  14536. self._setProgress(101);
  14537. } else {
  14538. self._showUploadError(data.error, outData, 'filebatchuploaderror');
  14539. }
  14540. };
  14541. fnComplete = function () {
  14542. self.unlock();
  14543. self._clearFileInput();
  14544. self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
  14545. };
  14546. fnError = function (jqXHR, textStatus, errorThrown) {
  14547. var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadExtra,
  14548. errMsg = self._parseError(op, jqXHR, errorThrown);
  14549. params.data = outData;
  14550. self._showUploadError(errMsg, outData, 'filebatchuploaderror');
  14551. self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
  14552. };
  14553. self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
  14554. },
  14555. _deleteFileIndex: function ($frame) {
  14556. var self = this, ind = $frame.attr('data-fileindex');
  14557. if (ind.substring(0, 5) === 'init_') {
  14558. ind = parseInt(ind.replace('init_', ''));
  14559. self.initialPreview = $h.spliceArray(self.initialPreview, ind);
  14560. self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind);
  14561. self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind);
  14562. self.getFrames().each(function () {
  14563. var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
  14564. if (nInd.substring(0, 5) === 'init_') {
  14565. nInd = parseInt(nInd.replace('init_', ''));
  14566. if (nInd > ind) {
  14567. nInd--;
  14568. $nFrame.attr('data-fileindex', 'init_' + nInd);
  14569. }
  14570. }
  14571. });
  14572. if (self.uploadAsync) {
  14573. self.cacheInitialPreview = self.getPreview();
  14574. }
  14575. }
  14576. },
  14577. _initFileActions: function () {
  14578. var self = this, $preview = self.$preview;
  14579. if (!self.showPreview) {
  14580. return;
  14581. }
  14582. self._initZoomButton();
  14583. self.getFrames(' .kv-file-remove').each(function () {
  14584. var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
  14585. ind = $frame.attr('data-fileindex'), n, cap, status;
  14586. self._handler($el, 'click', function () {
  14587. status = self._raise('filepreremove', [id, ind]);
  14588. if (status === false || !self._validateMinCount()) {
  14589. return false;
  14590. }
  14591. hasError = $frame.hasClass('file-preview-error');
  14592. $h.cleanMemory($frame);
  14593. $frame.fadeOut('slow', function () {
  14594. $h.cleanZoomCache($preview.find('#zoom-' + id));
  14595. self.updateStack(ind, undefined);
  14596. self._clearObjects($frame);
  14597. $frame.remove();
  14598. if (id && hasError) {
  14599. self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
  14600. $(this).remove();
  14601. if (!self._errorsExist()) {
  14602. self._resetErrors();
  14603. }
  14604. });
  14605. }
  14606. self._clearFileInput();
  14607. var filestack = self.getFileStack(true), chk = self.previewCache.count(),
  14608. len = filestack.length, hasThumb = self.showPreview && self.getFrames().length;
  14609. if (len === 0 && chk === 0 && !hasThumb) {
  14610. self.reset();
  14611. } else {
  14612. n = chk + len;
  14613. cap = n > 1 ? self._getMsgSelected(n) : (filestack[0] ? self._getFileNames()[0] : '');
  14614. self._setCaption(cap);
  14615. }
  14616. self._raise('fileremoved', [id, ind]);
  14617. });
  14618. });
  14619. });
  14620. self.getFrames(' .kv-file-upload').each(function () {
  14621. var $el = $(this);
  14622. self._handler($el, 'click', function () {
  14623. var $frame = $el.closest($h.FRAMES), ind = $frame.attr('data-fileindex');
  14624. if (!$frame.hasClass('file-preview-error')) {
  14625. self._uploadSingle(ind, self.filestack, false);
  14626. }
  14627. });
  14628. });
  14629. },
  14630. _initPreviewActions: function () {
  14631. var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
  14632. btnRemove = $h.FRAMES + ' .kv-file-remove',
  14633. resetProgress = function () {
  14634. var hasFiles = self.isUploadable ? self.previewCache.count() : self.$element.get(0).files.length;
  14635. if ($preview.find(btnRemove).length === 0 && !hasFiles) {
  14636. self.reset();
  14637. self.initialCaption = '';
  14638. }
  14639. };
  14640. self._initZoomButton();
  14641. $preview.find(btnRemove).each(function () {
  14642. var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
  14643. if ($h.isEmpty(vUrl) || vKey === undefined) {
  14644. return;
  14645. }
  14646. var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data,
  14647. settings, params, index = $frame.attr('data-fileindex'), config, extraData;
  14648. index = parseInt(index.replace('init_', ''));
  14649. config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
  14650. extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
  14651. if (typeof extraData === "function") {
  14652. extraData = extraData();
  14653. }
  14654. params = {id: $el.attr('id'), key: vKey, extra: extraData};
  14655. settings = $.extend(true, {}, {
  14656. url: vUrl,
  14657. type: 'POST',
  14658. dataType: 'json',
  14659. data: $.extend(true, {}, {key: vKey}, extraData),
  14660. beforeSend: function (jqXHR) {
  14661. self.ajaxAborted = false;
  14662. self._raise('filepredelete', [vKey, jqXHR, extraData]);
  14663. if (self.ajaxAborted) {
  14664. jqXHR.abort();
  14665. } else {
  14666. $h.addCss($frame, 'file-uploading');
  14667. $h.addCss($el, 'disabled');
  14668. }
  14669. },
  14670. success: function (data, textStatus, jqXHR) {
  14671. var n, cap;
  14672. if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
  14673. index = parseInt(($frame.attr('data-fileindex')).replace('init_', ''));
  14674. self.previewCache.unset(index);
  14675. n = self.previewCache.count();
  14676. cap = n > 0 ? self._getMsgSelected(n) : '';
  14677. self._deleteFileIndex($frame);
  14678. self._setCaption(cap);
  14679. self._raise('filedeleted', [vKey, jqXHR, extraData]);
  14680. } else {
  14681. params.jqXHR = jqXHR;
  14682. params.response = data;
  14683. self._showError(data.error, params, 'filedeleteerror');
  14684. $frame.removeClass('file-uploading');
  14685. $el.removeClass('disabled');
  14686. resetProgress();
  14687. return;
  14688. }
  14689. $frame.removeClass('file-uploading').addClass('file-deleted');
  14690. $frame.fadeOut('slow', function () {
  14691. $h.cleanZoomCache($preview.find('#zoom-' + $frame.attr('id')));
  14692. self._clearObjects($frame);
  14693. $frame.remove();
  14694. resetProgress();
  14695. if (!n && self.getFileStack().length === 0) {
  14696. self._setCaption('');
  14697. self.reset();
  14698. }
  14699. });
  14700. },
  14701. error: function (jqXHR, textStatus, errorThrown) {
  14702. var op = self.ajaxOperations.deleteThumb, errMsg = self._parseError(op, jqXHR, errorThrown);
  14703. params.jqXHR = jqXHR;
  14704. params.response = {};
  14705. self._showError(errMsg, params, 'filedeleteerror');
  14706. $frame.removeClass('file-uploading');
  14707. resetProgress();
  14708. }
  14709. }, self.ajaxDeleteSettings);
  14710. self._handler($el, 'click', function () {
  14711. if (!self._validateMinCount()) {
  14712. return false;
  14713. }
  14714. $.ajax(settings);
  14715. });
  14716. });
  14717. },
  14718. _hideFileIcon: function () {
  14719. if (this.overwriteInitial) {
  14720. this.$captionContainer.find('.kv-caption-icon').hide();
  14721. }
  14722. },
  14723. _showFileIcon: function () {
  14724. this.$captionContainer.find('.kv-caption-icon').show();
  14725. },
  14726. _getSize: function (bytes) {
  14727. var self = this, size = parseFloat(bytes), i, func = self.fileSizeGetter, sizes, out;
  14728. if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
  14729. return '';
  14730. }
  14731. if (typeof func === 'function') {
  14732. out = func(size);
  14733. } else {
  14734. if (size === 0) {
  14735. out = '0.00 B';
  14736. } else {
  14737. i = Math.floor(Math.log(size) / Math.log(1024));
  14738. sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  14739. out = (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
  14740. }
  14741. }
  14742. return self._getLayoutTemplate('size').replace('{sizeText}', out);
  14743. },
  14744. _generatePreviewTemplate: function (cat, data, fname, ftype, previewId, isError, size, frameClass, foot, ind, templ) {
  14745. var self = this, caption = self.slug(fname), prevContent, zoomContent = '',
  14746. config = self.previewSettings[cat] || self.defaults.previewSettings[cat],
  14747. w = config && config.width ? config.width : '', h = config && config.height ? config.height : '',
  14748. footer = foot || self._renderFileFooter(caption, size, ($h.isEmpty(w) ? 'auto' : w), isError),
  14749. hasIconSetting = self._getPreviewIcon(fname), typeCss = 'type-default',
  14750. forcePrevIcon = hasIconSetting && self.preferIconicPreview,
  14751. forceZoomIcon = hasIconSetting && self.preferIconicZoomPreview,
  14752. getContent = function (c, d, zoom, frameCss) {
  14753. var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(c),
  14754. css = (frameClass || '') + ' ' + frameCss;
  14755. if (self.frameClass) {
  14756. css = self.frameClass + ' ' + css;
  14757. }
  14758. if (zoom) {
  14759. css = css.replace(' ' + $h.SORT_CSS, '');
  14760. }
  14761. tmplt = self._parseFilePreviewIcon(tmplt, fname);
  14762. if (c === 'text') {
  14763. d = $h.htmlEncode(d);
  14764. }
  14765. if (cat === 'object' && !ftype) {
  14766. $.each(self.defaults.fileTypeSettings, function (key, func) {
  14767. if (key === 'object' || key === 'other') {
  14768. return;
  14769. }
  14770. if (func(fname, ftype)) {
  14771. typeCss = 'type-' + key;
  14772. }
  14773. });
  14774. }
  14775. return tmplt.setTokens({
  14776. 'previewId': id,
  14777. 'caption': caption,
  14778. 'frameClass': css,
  14779. 'type': ftype,
  14780. 'fileindex': ind,
  14781. 'width': w,
  14782. 'height': h,
  14783. 'typeCss': typeCss,
  14784. 'footer': footer,
  14785. 'data': d,
  14786. 'template': templ || cat
  14787. });
  14788. };
  14789. ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
  14790. if (self.fileActionSettings.showZoom) {
  14791. zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb');
  14792. }
  14793. zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
  14794. prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb');
  14795. return prevContent + zoomContent;
  14796. },
  14797. _previewDefault: function (file, previewId, isDisabled) {
  14798. var self = this, $preview = self.$preview;
  14799. if (!self.showPreview) {
  14800. return;
  14801. }
  14802. var fname = file ? file.name : '', ftype = file ? file.type : '', content, size = file.size || 0,
  14803. caption = self.slug(fname), isError = isDisabled === true && !self.isUploadable,
  14804. data = $h.objUrl.createObjectURL(file);
  14805. self._clearDefaultPreview();
  14806. content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, isError, size);
  14807. $preview.append("\n" + content);
  14808. self._setThumbAttr(previewId, caption, size);
  14809. if (isDisabled === true && self.isUploadable) {
  14810. self._setThumbStatus($('#' + previewId), 'Error');
  14811. }
  14812. },
  14813. _previewFile: function (i, file, theFile, previewId, data) {
  14814. if (!this.showPreview) {
  14815. return;
  14816. }
  14817. var self = this, cat = self._parseFileType(file), fname = file ? file.name : '', caption = self.slug(fname),
  14818. types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes, $preview = self.$preview,
  14819. chkTypes = types && types.indexOf(cat) >= 0, fsize = file.size || 0, ftype = file.type,
  14820. iData = (cat === 'text' || cat === 'html' || cat === 'image') ? theFile.target.result : data, content,
  14821. chkMimes = mimes && mimes.indexOf(ftype) !== -1;
  14822. /** @namespace window.DOMPurify */
  14823. if (cat === 'html' && self.purifyHtml && window.DOMPurify) {
  14824. iData = window.DOMPurify.sanitize(iData);
  14825. }
  14826. if (chkTypes || chkMimes) {
  14827. content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, false, fsize);
  14828. self._clearDefaultPreview();
  14829. $preview.append("\n" + content);
  14830. var $img = $preview.find('#' + previewId + ' img');
  14831. if ($img.length && self.autoOrientImage) {
  14832. $h.validateOrientation(file, function (value) {
  14833. if (value) {
  14834. var $zoomImg = $preview.find('#zoom-' + previewId + ' img'), css = 'rotate-' + value;
  14835. if (value > 4) {
  14836. css += ($img.width() > $img.height() ? ' is-portrait-gt4' : ' is-landscape-gt4');
  14837. }
  14838. $h.addCss($img, css);
  14839. $h.addCss($zoomImg, css);
  14840. self._raise('fileimageoriented', {'$img': $img, 'file': file});
  14841. }
  14842. self._validateImage(previewId, caption, ftype, fsize, iData);
  14843. $h.adjustOrientedImage($img);
  14844. });
  14845. } else {
  14846. self._validateImage(previewId, caption, ftype, fsize, iData);
  14847. }
  14848. } else {
  14849. self._previewDefault(file, previewId);
  14850. }
  14851. self._setThumbAttr(previewId, caption, fsize);
  14852. self._initSortable();
  14853. },
  14854. _setThumbAttr: function (id, caption, size) {
  14855. var self = this, $frame = $('#' + id);
  14856. if ($frame.length) {
  14857. size = size && size > 0 ? self._getSize(size) : '';
  14858. $frame.data({'caption': caption, 'size': size});
  14859. }
  14860. },
  14861. _setInitThumbAttr: function () {
  14862. var self = this, data = self.previewCache.data, len = self.previewCache.count(true), config,
  14863. caption, size, previewId;
  14864. if (len === 0) {
  14865. return;
  14866. }
  14867. for (var i = 0; i < len; i++) {
  14868. config = data.config[i];
  14869. previewId = self.previewInitId + '-' + 'init_' + i;
  14870. caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
  14871. size = $h.ifSet('size', config);
  14872. self._setThumbAttr(previewId, caption, size);
  14873. }
  14874. },
  14875. _slugDefault: function (text) {
  14876. return $h.isEmpty(text) ? '' : String(text).replace(/[\-\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
  14877. },
  14878. _readFiles: function (files) {
  14879. this.reader = new FileReader();
  14880. var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
  14881. $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
  14882. msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
  14883. settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
  14884. fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
  14885. fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
  14886. maxPreviewSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize),
  14887. canPreview = $preview.length && (!maxPreviewSize || isNaN(maxPreviewSize)),
  14888. throwError = function (msg, file, previewId, index) {
  14889. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  14890. p2 = {id: previewId, index: index, file: file, files: files};
  14891. self._previewDefault(file, previewId, true);
  14892. if (self.isUploadable) {
  14893. self.addToStack(undefined);
  14894. setTimeout(function () {
  14895. readFile(index + 1);
  14896. }, 100);
  14897. }
  14898. self._initFileActions();
  14899. if (self.removeFromPreviewOnError) {
  14900. $('#' + previewId).remove();
  14901. }
  14902. return self.isUploadable ? self._showUploadError(msg, p1) : self._showError(msg, p2);
  14903. };
  14904. self.loadedImages = [];
  14905. self.totalImagesCount = 0;
  14906. $.each(files, function (key, file) {
  14907. var func = self.fileTypeSettings.image;
  14908. if (func && func(file.type)) {
  14909. self.totalImagesCount++;
  14910. }
  14911. });
  14912. readFile = function (i) {
  14913. if ($h.isEmpty($el.attr('multiple'))) {
  14914. numFiles = 1;
  14915. }
  14916. if (i >= numFiles) {
  14917. if (self.isUploadable && self.filestack.length > 0) {
  14918. self._raise('filebatchselected', [self.getFileStack()]);
  14919. } else {
  14920. self._raise('filebatchselected', [files]);
  14921. }
  14922. $container.removeClass('file-thumb-loading');
  14923. $status.html('');
  14924. return;
  14925. }
  14926. var node = ctr + i, previewId = previewInitId + "-" + node, isText, isImage, file = files[i], fSizeKB,
  14927. caption = file.name ? self.slug(file.name) : '', fileSize = (file.size || 0) / 1000, j, msg,
  14928. fileExtExpr = '', previewData = $h.objUrl.createObjectURL(file), typ, chk, typ1, typ2,
  14929. fileCount = 0, strTypes = '', func;
  14930. if (typLen > 0) {
  14931. for (j = 0; j < typLen; j++) {
  14932. typ1 = fileTypes[j];
  14933. typ2 = self.msgFileTypes[typ1] || typ1;
  14934. strTypes += j === 0 ? typ2 : ', ' + typ2;
  14935. }
  14936. }
  14937. if (caption === false) {
  14938. readFile(i + 1);
  14939. return;
  14940. }
  14941. if (caption.length === 0) {
  14942. msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode(file.name));
  14943. self.isError = throwError(msg, file, previewId, i);
  14944. return;
  14945. }
  14946. if (!$h.isEmpty(fileExt)) {
  14947. fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
  14948. }
  14949. fSizeKB = fileSize.toFixed(2);
  14950. if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
  14951. msg = self.msgSizeTooLarge.setTokens({
  14952. 'name': caption,
  14953. 'size': fSizeKB,
  14954. 'maxSize': self.maxFileSize
  14955. });
  14956. self.isError = throwError(msg, file, previewId, i);
  14957. return;
  14958. }
  14959. if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
  14960. msg = self.msgSizeTooSmall.setTokens({
  14961. 'name': caption,
  14962. 'size': fSizeKB,
  14963. 'minSize': self.minFileSize
  14964. });
  14965. self.isError = throwError(msg, file, previewId, i);
  14966. return;
  14967. }
  14968. if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
  14969. for (j = 0; j < fileTypes.length; j += 1) {
  14970. typ = fileTypes[j];
  14971. func = settings[typ];
  14972. fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type, file.name) ? 1 : 0);
  14973. }
  14974. if (fileCount === 0) {
  14975. msg = self.msgInvalidFileType.setTokens({'name': caption, 'types': strTypes});
  14976. self.isError = throwError(msg, file, previewId, i);
  14977. return;
  14978. }
  14979. }
  14980. if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
  14981. chk = $h.compare(caption, fileExtExpr);
  14982. fileCount += $h.isEmpty(chk) ? 0 : chk.length;
  14983. if (fileCount === 0) {
  14984. msg = self.msgInvalidFileExtension.setTokens({'name': caption, 'extensions': strExt});
  14985. self.isError = throwError(msg, file, previewId, i);
  14986. return;
  14987. }
  14988. }
  14989. if (!self.showPreview) {
  14990. if (self.isUploadable) {
  14991. self.addToStack(file);
  14992. }
  14993. setTimeout(function () {
  14994. readFile(i + 1);
  14995. self._updateFileDetails(numFiles);
  14996. }, 100);
  14997. self._raise('fileloaded', [file, previewId, i, reader]);
  14998. return;
  14999. }
  15000. if (!canPreview && fileSize > maxPreviewSize) {
  15001. self.addToStack(file);
  15002. $container.addClass('file-thumb-loading');
  15003. self._previewDefault(file, previewId);
  15004. self._initFileActions();
  15005. self._updateFileDetails(numFiles);
  15006. readFile(i + 1);
  15007. return;
  15008. }
  15009. if ($preview.length && FileReader !== undefined) {
  15010. $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
  15011. $container.addClass('file-thumb-loading');
  15012. reader.onerror = function (evt) {
  15013. self._errorHandler(evt, caption);
  15014. };
  15015. reader.onload = function (theFile) {
  15016. self._previewFile(i, file, theFile, previewId, previewData);
  15017. self._initFileActions();
  15018. };
  15019. reader.onloadend = function () {
  15020. msg = msgProgress.setTokens({
  15021. 'index': i + 1,
  15022. 'files': numFiles,
  15023. 'percent': 50,
  15024. 'name': caption
  15025. });
  15026. setTimeout(function () {
  15027. $status.html(msg);
  15028. self._updateFileDetails(numFiles);
  15029. readFile(i + 1);
  15030. }, 100);
  15031. self._raise('fileloaded', [file, previewId, i, reader]);
  15032. };
  15033. reader.onprogress = function (data) {
  15034. if (data.lengthComputable) {
  15035. var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
  15036. msg = msgProgress.setTokens({
  15037. 'index': i + 1,
  15038. 'files': numFiles,
  15039. 'percent': progress,
  15040. 'name': caption
  15041. });
  15042. setTimeout(function () {
  15043. $status.html(msg);
  15044. }, 100);
  15045. }
  15046. };
  15047. isText = settings.text;
  15048. isImage = settings.image;
  15049. if (isText(file.type, caption)) {
  15050. reader.readAsText(file, self.textEncoding);
  15051. } else {
  15052. if (isImage(file.type, caption)) {
  15053. reader.readAsDataURL(file);
  15054. } else {
  15055. reader.readAsArrayBuffer(file);
  15056. }
  15057. }
  15058. } else {
  15059. self._previewDefault(file, previewId);
  15060. setTimeout(function () {
  15061. readFile(i + 1);
  15062. self._updateFileDetails(numFiles);
  15063. }, 100);
  15064. self._raise('fileloaded', [file, previewId, i, reader]);
  15065. }
  15066. self.addToStack(file);
  15067. };
  15068. readFile(0);
  15069. self._updateFileDetails(numFiles, false);
  15070. },
  15071. _updateFileDetails: function (numFiles) {
  15072. var self = this, $el = self.$element, fileStack = self.getFileStack(),
  15073. name = ($h.isIE(9) && $h.findFileName($el.val())) ||
  15074. ($el[0].files[0] && $el[0].files[0].name) || (fileStack.length && fileStack[0].name) || '',
  15075. label = self.slug(name), n = self.isUploadable ? fileStack.length : numFiles,
  15076. nFiles = self.previewCache.count() + n, log = n > 1 ? self._getMsgSelected(nFiles) : label;
  15077. if (self.isError) {
  15078. self.$previewContainer.removeClass('file-thumb-loading');
  15079. self.$previewStatus.html('');
  15080. self.$captionContainer.find('.kv-caption-icon').hide();
  15081. } else {
  15082. self._showFileIcon();
  15083. }
  15084. self._setCaption(log, self.isError);
  15085. self.$container.removeClass('file-input-new file-input-ajax-new');
  15086. if (arguments.length === 1) {
  15087. self._raise('fileselect', [numFiles, label]);
  15088. }
  15089. if (self.previewCache.count()) {
  15090. self._initPreviewActions();
  15091. }
  15092. },
  15093. _setThumbStatus: function ($thumb, status) {
  15094. var self = this;
  15095. if (!self.showPreview) {
  15096. return;
  15097. }
  15098. var icon = 'indicator' + status, msg = icon + 'Title',
  15099. css = 'file-preview-' + status.toLowerCase(),
  15100. $indicator = $thumb.find('.file-upload-indicator'),
  15101. config = self.fileActionSettings;
  15102. $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
  15103. if (status === 'Error') {
  15104. $thumb.find('.kv-file-upload').attr('disabled', true);
  15105. }
  15106. if (status === 'Success') {
  15107. $thumb.find('.file-drag-handle').remove();
  15108. $indicator.css('margin-left', 0);
  15109. }
  15110. $indicator.html(config[icon]);
  15111. $indicator.attr('title', config[msg]);
  15112. $thumb.addClass(css);
  15113. },
  15114. _setProgressCancelled: function () {
  15115. var self = this;
  15116. self._setProgress(101, self.$progress, self.msgCancelled);
  15117. },
  15118. _setProgress: function (p, $el, error) {
  15119. var self = this, pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
  15120. t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
  15121. template = pct < 100 ? self.progressTemplate : (error ? self.progressErrorTemplate : t);
  15122. $el = $el || self.$progress;
  15123. if (!$h.isEmpty(template)) {
  15124. if (pctLimit && pct > pctLimit && p <= 100) {
  15125. out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
  15126. } else {
  15127. out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
  15128. }
  15129. $el.html(out);
  15130. if (error) {
  15131. $el.find('[role="progressbar"]').html(error);
  15132. }
  15133. }
  15134. },
  15135. _setFileDropZoneTitle: function () {
  15136. var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
  15137. if (self.isClickable) {
  15138. strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
  15139. title += self.dropZoneClickTitle.replace('{files}', strFiles);
  15140. }
  15141. $zone.find('.' + self.dropZoneTitleClass).remove();
  15142. if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
  15143. return;
  15144. }
  15145. if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
  15146. $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
  15147. }
  15148. self.$container.removeClass('file-input-new');
  15149. $h.addCss(self.$container, 'file-input-ajax-new');
  15150. },
  15151. _setAsyncUploadStatus: function (previewId, pct, total) {
  15152. var self = this, sum = 0;
  15153. self._setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
  15154. self.uploadStatus[previewId] = pct;
  15155. $.each(self.uploadStatus, function (key, value) {
  15156. sum += value;
  15157. });
  15158. self._setProgress(Math.floor(sum / total));
  15159. },
  15160. _validateMinCount: function () {
  15161. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  15162. if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
  15163. self._noFilesError({});
  15164. return false;
  15165. }
  15166. return true;
  15167. },
  15168. _getFileCount: function (fileCount) {
  15169. var self = this, addCount = 0;
  15170. if (self.validateInitialCount && !self.overwriteInitial) {
  15171. addCount = self.previewCache.count();
  15172. fileCount += addCount;
  15173. }
  15174. return fileCount;
  15175. },
  15176. _getFileId: function (file) {
  15177. var self = this, custom = self.generateFileId, relativePath;
  15178. if (typeof custom === 'function') {
  15179. return custom(file, event);
  15180. }
  15181. if (!file) {
  15182. return null;
  15183. }
  15184. /** @namespace file.webkitRelativePath */
  15185. relativePath = file.webkitRelativePath || file.fileName || file.name || null;
  15186. if (!relativePath) {
  15187. return null;
  15188. }
  15189. return (file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
  15190. },
  15191. _getFileName: function (file) {
  15192. return file && file.name ? this.slug(file.name) : undefined;
  15193. },
  15194. _getFileIds: function (skipNull) {
  15195. var self = this;
  15196. return self.fileids.filter(function (n) {
  15197. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  15198. });
  15199. },
  15200. _getFileNames: function (skipNull) {
  15201. var self = this;
  15202. return self.filenames.filter(function (n) {
  15203. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  15204. });
  15205. },
  15206. _setPreviewError: function ($thumb, i, val) {
  15207. var self = this;
  15208. if (i !== undefined) {
  15209. self.updateStack(i, val);
  15210. }
  15211. if (self.removeFromPreviewOnError) {
  15212. $thumb.remove();
  15213. } else {
  15214. self._setThumbStatus($thumb, 'Error');
  15215. }
  15216. },
  15217. _checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
  15218. var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type],
  15219. $imgEl, isValid;
  15220. if ($h.isEmpty(limit) || !$img.length) {
  15221. return;
  15222. }
  15223. $imgEl = $img[0];
  15224. dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
  15225. isValid = chk === 'Small' ? dim >= limit : dim <= limit;
  15226. if (isValid) {
  15227. return;
  15228. }
  15229. msg = self['msgImage' + type + chk].setTokens({'name': fname, 'size': limit});
  15230. self._showUploadError(msg, params);
  15231. self._setPreviewError($thumb, i, null);
  15232. },
  15233. _validateImage: function (previewId, fname, ftype, fsize, iData) {
  15234. var self = this, $preview = self.$preview, params, w1, w2, $thumb = $preview.find("#" + previewId),
  15235. i = $thumb.attr('data-fileindex'), $img = $thumb.find('img'), exifObject;
  15236. fname = fname || 'Untitled';
  15237. $img.one('load', function () {
  15238. w1 = $thumb.width();
  15239. w2 = $preview.width();
  15240. if (w1 > w2) {
  15241. $img.css('width', '100%');
  15242. }
  15243. params = {ind: i, id: previewId};
  15244. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
  15245. self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
  15246. if (!self.resizeImage) {
  15247. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
  15248. self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
  15249. }
  15250. self._raise('fileimageloaded', [previewId]);
  15251. exifObject = window.piexif ? window.piexif.load(iData) : null;
  15252. self.loadedImages.push({
  15253. ind: i,
  15254. img: $img,
  15255. thumb: $thumb,
  15256. pid: previewId,
  15257. typ: ftype,
  15258. siz: fsize,
  15259. validated: false,
  15260. imgData: iData,
  15261. exifObj: exifObject
  15262. });
  15263. $thumb.data('exif', exifObject);
  15264. self._validateAllImages();
  15265. }).one('error', function () {
  15266. self._raise('fileimageloaderror', [previewId]);
  15267. }).each(function () {
  15268. if (this.complete) {
  15269. $(this).trigger('load');
  15270. } else {
  15271. if (this.error) {
  15272. $(this).trigger('error');
  15273. }
  15274. }
  15275. });
  15276. },
  15277. _validateAllImages: function () {
  15278. var self = this, i, counter = {val: 0}, numImgs = self.loadedImages.length, config,
  15279. fsize, minSize = self.resizeIfSizeMoreThan;
  15280. if (numImgs !== self.totalImagesCount) {
  15281. return;
  15282. }
  15283. self._raise('fileimagesloaded');
  15284. if (!self.resizeImage) {
  15285. return;
  15286. }
  15287. for (i = 0; i < self.loadedImages.length; i++) {
  15288. config = self.loadedImages[i];
  15289. if (config.validated) {
  15290. continue;
  15291. }
  15292. fsize = config.siz;
  15293. if (fsize && fsize > minSize * 1000) {
  15294. self._getResizedImage(config, counter, numImgs);
  15295. }
  15296. self.loadedImages[i].validated = true;
  15297. }
  15298. },
  15299. _getResizedImage: function (config, counter, numImgs) {
  15300. var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
  15301. ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
  15302. isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
  15303. context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
  15304. $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr;
  15305. throwError = function (msg, params, ev) {
  15306. if (self.isUploadable) {
  15307. self._showUploadError(msg, params, ev);
  15308. } else {
  15309. self._showError(msg, params, ev);
  15310. }
  15311. self._setPreviewError($thumb, ind);
  15312. };
  15313. if (!self.filestack[ind] || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
  15314. if (isValidImage && self.filestack[ind]) {
  15315. self._raise('fileimageresized', [pid, ind]);
  15316. }
  15317. counter.val++;
  15318. if (counter.val === numImgs) {
  15319. self._raise('fileimagesresized');
  15320. }
  15321. if (!isValidImage) {
  15322. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  15323. return;
  15324. }
  15325. }
  15326. type = type || self.resizeDefaultImageType;
  15327. chkWidth = width > maxWidth;
  15328. chkHeight = height > maxHeight;
  15329. if (self.resizePreference === 'width') {
  15330. ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
  15331. } else {
  15332. ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
  15333. }
  15334. self._resetCanvas();
  15335. width *= ratio;
  15336. height *= ratio;
  15337. canvas.width = width;
  15338. canvas.height = height;
  15339. try {
  15340. context.drawImage(img, 0, 0, width, height);
  15341. dataURI = canvas.toDataURL(type, self.resizeQuality);
  15342. if (exifObj) {
  15343. exifStr = window.piexif.dump(exifObj);
  15344. dataURI = window.piexif.insert(exifStr, dataURI);
  15345. }
  15346. blob = $h.dataURI2Blob(dataURI);
  15347. self.filestack[ind] = blob;
  15348. self._raise('fileimageresized', [pid, ind]);
  15349. counter.val++;
  15350. if (counter.val === numImgs) {
  15351. self._raise('fileimagesresized', [undefined, undefined]);
  15352. }
  15353. if (!(blob instanceof Blob)) {
  15354. throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
  15355. }
  15356. }
  15357. catch (err) {
  15358. counter.val++;
  15359. if (counter.val === numImgs) {
  15360. self._raise('fileimagesresized', [undefined, undefined]);
  15361. }
  15362. msg = self.msgImageResizeException.replace('{errors}', err.message);
  15363. throwError(msg, {id: pid, 'index': ind}, 'fileimageresizeexception');
  15364. }
  15365. },
  15366. _initBrowse: function ($container) {
  15367. var self = this;
  15368. if (self.showBrowse) {
  15369. self.$btnFile = $container.find('.btn-file');
  15370. self.$btnFile.append(self.$element);
  15371. } else {
  15372. self.$element.hide();
  15373. }
  15374. },
  15375. _initCaption: function () {
  15376. var self = this, cap = self.initialCaption || '';
  15377. if (self.overwriteInitial || $h.isEmpty(cap)) {
  15378. self.$caption.html('');
  15379. return false;
  15380. }
  15381. self._setCaption(cap);
  15382. return true;
  15383. },
  15384. _setCaption: function (content, isError) {
  15385. var self = this, title, out, n, cap, stack = self.getFileStack();
  15386. if (!self.$caption.length) {
  15387. return;
  15388. }
  15389. if (isError) {
  15390. title = $('<div>' + self.msgValidationError + '</div>').text();
  15391. n = stack.length;
  15392. if (n) {
  15393. cap = n === 1 && stack[0] ? self._getFileNames()[0] : self._getMsgSelected(n);
  15394. } else {
  15395. cap = self._getMsgSelected(self.msgNo);
  15396. }
  15397. out = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon +
  15398. ($h.isEmpty(content) ? cap : content) + '</span>';
  15399. } else {
  15400. if ($h.isEmpty(content)) {
  15401. return;
  15402. }
  15403. title = $('<div>' + content + '</div>').text();
  15404. out = self._getLayoutTemplate('fileIcon') + title;
  15405. }
  15406. self.$caption.html(out);
  15407. self.$caption.attr('title', title);
  15408. self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
  15409. },
  15410. _createContainer: function () {
  15411. var self = this, attribs = {"class": 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
  15412. $container = $(document.createElement("div")).attr(attribs).html(self._renderMain());
  15413. self.$element.before($container);
  15414. self._initBrowse($container);
  15415. if (self.theme) {
  15416. $container.addClass('theme-' + self.theme);
  15417. }
  15418. return $container;
  15419. },
  15420. _refreshContainer: function () {
  15421. var self = this, $container = self.$container;
  15422. $container.before(self.$element);
  15423. $container.html(self._renderMain());
  15424. self._initBrowse($container);
  15425. },
  15426. _renderMain: function () {
  15427. var self = this,
  15428. dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : 'file-drop-disabled',
  15429. close = !self.showClose ? '' : self._getLayoutTemplate('close'),
  15430. preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
  15431. .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
  15432. css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
  15433. caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
  15434. return self.mainTemplate.setTokens({
  15435. 'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
  15436. 'preview': preview,
  15437. 'close': close,
  15438. 'caption': caption,
  15439. 'upload': self._renderButton('upload'),
  15440. 'remove': self._renderButton('remove'),
  15441. 'cancel': self._renderButton('cancel'),
  15442. 'browse': self._renderButton('browse')
  15443. });
  15444. },
  15445. _renderButton: function (type) {
  15446. var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
  15447. title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
  15448. status = self.isDisabled ? ' disabled' : '', btnType = 'button';
  15449. switch (type) {
  15450. case 'remove':
  15451. if (!self.showRemove) {
  15452. return '';
  15453. }
  15454. break;
  15455. case 'cancel':
  15456. if (!self.showCancel) {
  15457. return '';
  15458. }
  15459. css += ' hide';
  15460. break;
  15461. case 'upload':
  15462. if (!self.showUpload) {
  15463. return '';
  15464. }
  15465. if (self.isUploadable && !self.isDisabled) {
  15466. tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
  15467. } else {
  15468. btnType = 'submit';
  15469. }
  15470. break;
  15471. case 'browse':
  15472. if (!self.showBrowse) {
  15473. return '';
  15474. }
  15475. tmplt = self._getLayoutTemplate('btnBrowse');
  15476. break;
  15477. default:
  15478. return '';
  15479. }
  15480. css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
  15481. if (!$h.isEmpty(label)) {
  15482. label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
  15483. }
  15484. return tmplt.setTokens({
  15485. 'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
  15486. });
  15487. },
  15488. _renderThumbProgress: function () {
  15489. var self = this;
  15490. return '<div class="file-thumb-progress hide">' +
  15491. self.progressTemplate.setTokens({'percent': '0', 'status': self.msgUploadBegin}) +
  15492. '</div>';
  15493. },
  15494. _renderFileFooter: function (caption, size, width, isError) {
  15495. var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
  15496. upl = config.showUpload, zoom = config.showZoom, out, template = self._getLayoutTemplate('footer'),
  15497. ind = isError ? config.indicatorError : config.indicatorNew,
  15498. tInd = self._getLayoutTemplate('indicator'),
  15499. title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
  15500. indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
  15501. size = self._getSize(size);
  15502. if (self.isUploadable) {
  15503. out = template.setTokens({
  15504. 'actions': self._renderFileActions(upl, rem, zoom, drg, false, false, false),
  15505. 'caption': caption,
  15506. 'size': size,
  15507. 'width': width,
  15508. 'progress': self._renderThumbProgress(),
  15509. 'indicator': indicator
  15510. });
  15511. } else {
  15512. out = template.setTokens({
  15513. 'actions': self._renderFileActions(false, false, zoom, drg, false, false, false),
  15514. 'caption': caption,
  15515. 'size': size,
  15516. 'width': width,
  15517. 'progress': '',
  15518. 'indicator': indicator
  15519. });
  15520. }
  15521. out = $h.replaceTags(out, self.previewThumbTags);
  15522. return out;
  15523. },
  15524. _renderFileActions: function (showUpload, showDelete, showZoom, showDrag, disabled, url, key, isInit) {
  15525. if (!showUpload && !showDelete && !showZoom && !showDrag) {
  15526. return '';
  15527. }
  15528. var self = this, vUrl = url === false ? '' : ' data-url="' + url + '"',
  15529. vKey = key === false ? '' : ' data-key="' + key + '"',
  15530. btnDelete = '', btnUpload = '', btnZoom = '', btnDrag = '', css,
  15531. template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
  15532. otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey}),
  15533. removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
  15534. if (showDelete) {
  15535. btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
  15536. 'removeClass': removeClass,
  15537. 'removeIcon': config.removeIcon,
  15538. 'removeTitle': config.removeTitle,
  15539. 'dataUrl': vUrl,
  15540. 'dataKey': vKey
  15541. });
  15542. }
  15543. if (showUpload) {
  15544. btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
  15545. 'uploadClass': config.uploadClass,
  15546. 'uploadIcon': config.uploadIcon,
  15547. 'uploadTitle': config.uploadTitle
  15548. });
  15549. }
  15550. if (showZoom) {
  15551. btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
  15552. 'zoomClass': config.zoomClass,
  15553. 'zoomIcon': config.zoomIcon,
  15554. 'zoomTitle': config.zoomTitle
  15555. });
  15556. }
  15557. if (showDrag && isInit) {
  15558. css = 'drag-handle-init ' + config.dragClass;
  15559. btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
  15560. 'dragClass': css,
  15561. 'dragTitle': config.dragTitle,
  15562. 'dragIcon': config.dragIcon
  15563. });
  15564. }
  15565. return template.setTokens({
  15566. 'delete': btnDelete,
  15567. 'upload': btnUpload,
  15568. 'zoom': btnZoom,
  15569. 'drag': btnDrag,
  15570. 'other': otherButtons
  15571. });
  15572. },
  15573. _browse: function (e) {
  15574. var self = this;
  15575. self._raise('filebrowse');
  15576. if (e && e.isDefaultPrevented()) {
  15577. return;
  15578. }
  15579. if (self.isError && !self.isUploadable) {
  15580. self.clear();
  15581. }
  15582. self.$captionContainer.focus();
  15583. },
  15584. _filterDuplicate: function (file, files, fileIds) {
  15585. var self = this, fileId = self._getFileId(file);
  15586. if (fileId && fileIds && fileIds.indexOf(fileId) > -1) {
  15587. return;
  15588. }
  15589. if (!fileIds) {
  15590. fileIds = [];
  15591. }
  15592. files.push(file);
  15593. fileIds.push(fileId);
  15594. },
  15595. _change: function (e) {
  15596. var self = this, $el = self.$element;
  15597. if (!self.isUploadable && $h.isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
  15598. self.fileInputCleared = false;
  15599. return;
  15600. }
  15601. self.fileInputCleared = false;
  15602. var tfiles = [], msg, total, isDragDrop = arguments.length > 1, isAjaxUpload = self.isUploadable, n, len,
  15603. files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files, ctr = self.filestack.length,
  15604. isSingleUpload = $h.isEmpty($el.attr('multiple')), flagSingle = (isSingleUpload && ctr > 0),
  15605. folders = 0, fileIds = self._getFileIds(), throwError = function (mesg, file, previewId, index) {
  15606. var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
  15607. p2 = {id: previewId, index: index, file: file, files: files};
  15608. return self.isUploadable ? self._showUploadError(mesg, p1) : self._showError(mesg, p2);
  15609. };
  15610. self.reader = null;
  15611. self._resetUpload();
  15612. self._hideFileIcon();
  15613. if (self.isUploadable) {
  15614. self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
  15615. }
  15616. if (isDragDrop) {
  15617. $.each(files, function (i, f) {
  15618. if (f && !f.type && f.size !== undefined && f.size % 4096 === 0) {
  15619. folders++;
  15620. } else {
  15621. self._filterDuplicate(f, tfiles, fileIds);
  15622. }
  15623. });
  15624. } else {
  15625. if (e.target && e.target.files === undefined) {
  15626. files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
  15627. } else {
  15628. files = e.target.files || {};
  15629. }
  15630. if (isAjaxUpload) {
  15631. $.each(files, function (i, f) {
  15632. self._filterDuplicate(f, tfiles, fileIds);
  15633. });
  15634. } else {
  15635. tfiles = files;
  15636. }
  15637. }
  15638. if ($h.isEmpty(tfiles) || tfiles.length === 0) {
  15639. if (!isAjaxUpload) {
  15640. self.clear();
  15641. }
  15642. self._showFolderError(folders);
  15643. self._raise('fileselectnone');
  15644. return;
  15645. }
  15646. self._resetErrors();
  15647. len = tfiles.length;
  15648. total = self._getFileCount(self.isUploadable ? (self.getFileStack().length + len) : len);
  15649. if (self.maxFileCount > 0 && total > self.maxFileCount) {
  15650. if (!self.autoReplace || len > self.maxFileCount) {
  15651. n = (self.autoReplace && len > self.maxFileCount) ? len : total;
  15652. msg = self.msgFilesTooMany.replace('{m}', self.maxFileCount).replace('{n}', n);
  15653. self.isError = throwError(msg, null, null, null);
  15654. self.$captionContainer.find('.kv-caption-icon').hide();
  15655. self._setCaption('', true);
  15656. self.$container.removeClass('file-input-new file-input-ajax-new');
  15657. return;
  15658. }
  15659. if (total > self.maxFileCount) {
  15660. self._resetPreviewThumbs(isAjaxUpload);
  15661. }
  15662. } else {
  15663. if (!isAjaxUpload || flagSingle) {
  15664. self._resetPreviewThumbs(false);
  15665. if (flagSingle) {
  15666. self.clearStack();
  15667. }
  15668. } else {
  15669. if (isAjaxUpload && ctr === 0 && (!self.previewCache.count() || self.overwriteInitial)) {
  15670. self._resetPreviewThumbs(true);
  15671. }
  15672. }
  15673. }
  15674. if (self.isPreviewable) {
  15675. self._readFiles(tfiles);
  15676. } else {
  15677. self._updateFileDetails(1);
  15678. }
  15679. self._showFolderError(folders);
  15680. },
  15681. _abort: function (params) {
  15682. var self = this, data;
  15683. if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
  15684. data = $.extend(true, {}, self._getOutData(), params);
  15685. data.abortData = self.ajaxAborted.data || {};
  15686. data.abortMessage = self.ajaxAborted.message;
  15687. self._setProgress(101, self.$progress, self.msgCancelled);
  15688. self._showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
  15689. self.cancel();
  15690. return true;
  15691. }
  15692. return false;
  15693. },
  15694. _resetFileStack: function () {
  15695. var self = this, i = 0, newstack = [], newnames = [], newids = [];
  15696. self._getThumbs().each(function () {
  15697. var $thumb = $(this), ind = $thumb.attr('data-fileindex'), file = self.filestack[ind],
  15698. pid = $thumb.attr('id'), newId;
  15699. if (ind === '-1' || ind === -1) {
  15700. return;
  15701. }
  15702. if (file !== undefined) {
  15703. newstack[i] = file;
  15704. newnames[i] = self._getFileName(file);
  15705. newids[i] = self._getFileId(file);
  15706. $thumb.attr({'id': self.previewInitId + '-' + i, 'data-fileindex': i});
  15707. i++;
  15708. } else {
  15709. newId = 'uploaded-' + $h.uniqId();
  15710. $thumb.attr({'id': newId, 'data-fileindex': '-1'});
  15711. self.$preview.find('#zoom-' + pid).attr('id', 'zoom-' + newId);
  15712. }
  15713. });
  15714. self.filestack = newstack;
  15715. self.filenames = newnames;
  15716. self.fileids = newids;
  15717. },
  15718. _isFileSelectionValid: function (cnt) {
  15719. var self = this;
  15720. cnt = cnt || 0;
  15721. if (self.required && !self.getFilesCount()) {
  15722. self.$errorContainer.html('');
  15723. self._showUploadError(self.msgFileRequired);
  15724. return false;
  15725. }
  15726. if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
  15727. self._noFilesError({});
  15728. return false;
  15729. }
  15730. return true;
  15731. },
  15732. clearStack: function () {
  15733. var self = this;
  15734. self.filestack = [];
  15735. self.filenames = [];
  15736. self.fileids = [];
  15737. return self.$element;
  15738. },
  15739. updateStack: function (i, file) {
  15740. var self = this;
  15741. self.filestack[i] = file;
  15742. self.filenames[i] = self._getFileName(file);
  15743. self.fileids[i] = file && self._getFileId(file) || null;
  15744. return self.$element;
  15745. },
  15746. addToStack: function (file) {
  15747. var self = this;
  15748. self.filestack.push(file);
  15749. self.filenames.push(self._getFileName(file));
  15750. self.fileids.push(self._getFileId(file));
  15751. return self.$element;
  15752. },
  15753. getFileStack: function (skipNull) {
  15754. var self = this;
  15755. return self.filestack.filter(function (n) {
  15756. return (skipNull ? n !== undefined : n !== undefined && n !== null);
  15757. });
  15758. },
  15759. getFilesCount: function () {
  15760. var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
  15761. return self._getFileCount(len);
  15762. },
  15763. lock: function () {
  15764. var self = this;
  15765. self._resetErrors();
  15766. self.disable();
  15767. if (self.showRemove) {
  15768. $h.addCss(self.$container.find('.fileinput-remove'), 'hide');
  15769. }
  15770. if (self.showCancel) {
  15771. self.$container.find('.fileinput-cancel').removeClass('hide');
  15772. }
  15773. self._raise('filelock', [self.filestack, self._getExtraData()]);
  15774. return self.$element;
  15775. },
  15776. unlock: function (reset) {
  15777. var self = this;
  15778. if (reset === undefined) {
  15779. reset = true;
  15780. }
  15781. self.enable();
  15782. if (self.showCancel) {
  15783. $h.addCss(self.$container.find('.fileinput-cancel'), 'hide');
  15784. }
  15785. if (self.showRemove) {
  15786. self.$container.find('.fileinput-remove').removeClass('hide');
  15787. }
  15788. if (reset) {
  15789. self._resetFileStack();
  15790. }
  15791. self._raise('fileunlock', [self.filestack, self._getExtraData()]);
  15792. return self.$element;
  15793. },
  15794. cancel: function () {
  15795. var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
  15796. if (len > 0) {
  15797. for (i = 0; i < len; i += 1) {
  15798. self.cancelling = true;
  15799. xhr[i].abort();
  15800. }
  15801. }
  15802. self._setProgressCancelled();
  15803. self._getThumbs().each(function () {
  15804. var $thumb = $(this), ind = $thumb.attr('data-fileindex');
  15805. $thumb.removeClass('file-uploading');
  15806. if (self.filestack[ind] !== undefined) {
  15807. $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
  15808. $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
  15809. }
  15810. self.unlock();
  15811. });
  15812. return self.$element;
  15813. },
  15814. clear: function () {
  15815. var self = this, cap;
  15816. if (!self._raise('fileclear')) {
  15817. return;
  15818. }
  15819. self.$btnUpload.removeAttr('disabled');
  15820. self._getThumbs().find('video,audio,img').each(function () {
  15821. $h.cleanMemory($(this));
  15822. });
  15823. self._resetUpload();
  15824. self.clearStack();
  15825. self._clearFileInput();
  15826. self._resetErrors(true);
  15827. if (self._hasInitialPreview()) {
  15828. self._showFileIcon();
  15829. self._resetPreview();
  15830. self._initPreviewActions();
  15831. self.$container.removeClass('file-input-new');
  15832. } else {
  15833. self._getThumbs().each(function () {
  15834. self._clearObjects($(this));
  15835. });
  15836. if (self.isUploadable) {
  15837. self.previewCache.data = {};
  15838. }
  15839. self.$preview.html('');
  15840. cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
  15841. self.$caption.html(cap);
  15842. self.$caption.attr('title', '');
  15843. $h.addCss(self.$container, 'file-input-new');
  15844. self._validateDefaultPreview();
  15845. }
  15846. if (self.$container.find($h.FRAMES).length === 0) {
  15847. if (!self._initCaption()) {
  15848. self.$captionContainer.find('.kv-caption-icon').hide();
  15849. }
  15850. }
  15851. self._hideFileIcon();
  15852. self._raise('filecleared');
  15853. self.$captionContainer.focus();
  15854. self._setFileDropZoneTitle();
  15855. return self.$element;
  15856. },
  15857. reset: function () {
  15858. var self = this;
  15859. if (!self._raise('filereset')) {
  15860. return;
  15861. }
  15862. self._resetPreview();
  15863. self.$container.find('.fileinput-filename').text('');
  15864. $h.addCss(self.$container, 'file-input-new');
  15865. if (self.getFrames().length || self.isUploadable && self.dropZoneEnabled) {
  15866. self.$container.removeClass('file-input-new');
  15867. }
  15868. self._setFileDropZoneTitle();
  15869. self.clearStack();
  15870. self.formdata = {};
  15871. return self.$element;
  15872. },
  15873. disable: function () {
  15874. var self = this;
  15875. self.isDisabled = true;
  15876. self._raise('filedisabled');
  15877. self.$element.attr('disabled', 'disabled');
  15878. self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
  15879. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  15880. .attr("disabled", true);
  15881. self._initDragDrop();
  15882. return self.$element;
  15883. },
  15884. enable: function () {
  15885. var self = this;
  15886. self.isDisabled = false;
  15887. self._raise('fileenabled');
  15888. self.$element.removeAttr('disabled');
  15889. self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
  15890. self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
  15891. .removeAttr("disabled");
  15892. self._initDragDrop();
  15893. return self.$element;
  15894. },
  15895. upload: function () {
  15896. var self = this, totLen = self.getFileStack().length, i, outData, len,
  15897. hasExtraData = !$.isEmptyObject(self._getExtraData());
  15898. if (!self.isUploadable || self.isDisabled || !self._isFileSelectionValid(totLen)) {
  15899. return;
  15900. }
  15901. self._resetUpload();
  15902. if (totLen === 0 && !hasExtraData) {
  15903. self._showUploadError(self.msgUploadEmpty);
  15904. return;
  15905. }
  15906. self.$progress.removeClass('hide');
  15907. self.uploadCount = 0;
  15908. self.uploadStatus = {};
  15909. self.uploadLog = [];
  15910. self.lock();
  15911. self._setProgress(2);
  15912. if (totLen === 0 && hasExtraData) {
  15913. self._uploadExtraOnly();
  15914. return;
  15915. }
  15916. len = self.filestack.length;
  15917. self.hasInitData = false;
  15918. if (self.uploadAsync) {
  15919. outData = self._getOutData();
  15920. self._raise('filebatchpreupload', [outData]);
  15921. self.fileBatchCompleted = false;
  15922. self.uploadCache = {content: [], config: [], tags: [], append: true};
  15923. self.uploadAsyncCount = self.getFileStack().length;
  15924. for (i = 0; i < len; i++) {
  15925. self.uploadCache.content[i] = null;
  15926. self.uploadCache.config[i] = null;
  15927. self.uploadCache.tags[i] = null;
  15928. }
  15929. self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
  15930. self._initSortable();
  15931. self.cacheInitialPreview = self.getPreview();
  15932. for (i = 0; i < len; i++) {
  15933. if (self.filestack[i] !== undefined) {
  15934. self._uploadSingle(i, self.filestack, true);
  15935. }
  15936. }
  15937. return;
  15938. }
  15939. self._uploadBatch();
  15940. return self.$element;
  15941. },
  15942. destroy: function () {
  15943. var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
  15944. $(document).off(ns);
  15945. $(window).off(ns);
  15946. if ($form && $form.length) {
  15947. $form.off(ns);
  15948. }
  15949. if (self.isUploadable) {
  15950. self._clearFileInput();
  15951. }
  15952. self._cleanup();
  15953. self._initPreviewCache();
  15954. $el.insertBefore($cont).off(ns).removeData();
  15955. $cont.off().remove();
  15956. return $el;
  15957. },
  15958. refresh: function (options) {
  15959. var self = this, $el = self.$element;
  15960. options = options ? $.extend(true, {}, self.options, options) : self.options;
  15961. self.destroy();
  15962. $el.fileinput(options);
  15963. self = $el.data('fileinput');
  15964. if (self.isUploadable) {
  15965. self._clearFileInput();
  15966. }
  15967. if ($el.val()) {
  15968. $el.trigger('change.fileinput');
  15969. }
  15970. return $el;
  15971. },
  15972. zoom: function (frameId) {
  15973. var self = this, $frame = self._getFrame(frameId), $modal = self.$modal;
  15974. if (!$frame) {
  15975. return;
  15976. }
  15977. $h.initModal($modal);
  15978. $modal.html(self._getModalContent());
  15979. self._setZoomContent($frame);
  15980. $modal.modal('show');
  15981. self._initZoomButtons();
  15982. },
  15983. getExif: function (frameId) {
  15984. var self = this, $frame = self._getFrame(frameId);
  15985. return $frame && $frame.data('exif') || null;
  15986. },
  15987. getFrames: function (cssFilter) {
  15988. var self = this;
  15989. cssFilter = cssFilter || '';
  15990. return self.$preview.find($h.FRAMES + cssFilter);
  15991. },
  15992. getPreview: function () {
  15993. var self = this;
  15994. return {
  15995. content: self.initialPreview,
  15996. config: self.initialPreviewConfig,
  15997. tags: self.initialPreviewThumbTags
  15998. };
  15999. }
  16000. };
  16001. $.fn.fileinput = function (option) {
  16002. if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
  16003. return;
  16004. }
  16005. var args = Array.apply(null, arguments), retvals = [];
  16006. args.shift();
  16007. this.each(function () {
  16008. var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
  16009. theme = options.theme || self.data('theme'), l = {}, t = {},
  16010. lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
  16011. if (!data) {
  16012. if (theme) {
  16013. t = $.fn.fileinputThemes[theme] || {};
  16014. }
  16015. if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
  16016. l = $.fn.fileinputLocales[lang] || {};
  16017. }
  16018. opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
  16019. data = new FileInput(this, opt);
  16020. self.data('fileinput', data);
  16021. }
  16022. if (typeof option === 'string') {
  16023. retvals.push(data[option].apply(data, args));
  16024. }
  16025. });
  16026. switch (retvals.length) {
  16027. case 0:
  16028. return this;
  16029. case 1:
  16030. return retvals[0];
  16031. default:
  16032. return retvals;
  16033. }
  16034. };
  16035. $.fn.fileinput.defaults = {
  16036. language: 'en',
  16037. showCaption: true,
  16038. showBrowse: true,
  16039. showPreview: true,
  16040. showRemove: true,
  16041. showUpload: true,
  16042. showCancel: true,
  16043. showClose: true,
  16044. showUploadedThumbs: true,
  16045. browseOnZoneClick: false,
  16046. autoReplace: false,
  16047. autoOrientImage: true, // for JPEG images based on EXIF orientation tag
  16048. required: false,
  16049. rtl: false,
  16050. hideThumbnailContent: false,
  16051. generateFileId: null,
  16052. previewClass: '',
  16053. captionClass: '',
  16054. frameClass: 'krajee-default',
  16055. mainClass: 'file-caption-main',
  16056. mainTemplate: null,
  16057. purifyHtml: true,
  16058. fileSizeGetter: null,
  16059. initialCaption: '',
  16060. initialPreview: [],
  16061. initialPreviewDelimiter: '*$$*',
  16062. initialPreviewAsData: false,
  16063. initialPreviewFileType: 'image',
  16064. initialPreviewConfig: [],
  16065. initialPreviewThumbTags: [],
  16066. previewThumbTags: {},
  16067. initialPreviewShowDelete: true,
  16068. removeFromPreviewOnError: false,
  16069. deleteUrl: '',
  16070. deleteExtraData: {},
  16071. overwriteInitial: true,
  16072. previewZoomButtonIcons: {
  16073. prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
  16074. next: '<i class="glyphicon glyphicon-triangle-right"></i>',
  16075. toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
  16076. fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
  16077. borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
  16078. close: '<i class="glyphicon glyphicon-remove"></i>'
  16079. },
  16080. previewZoomButtonClasses: {
  16081. prev: 'btn btn-navigate',
  16082. next: 'btn btn-navigate',
  16083. toggleheader: 'btn btn-default btn-header-toggle',
  16084. fullscreen: 'btn btn-default',
  16085. borderless: 'btn btn-default',
  16086. close: 'btn btn-default'
  16087. },
  16088. preferIconicPreview: false,
  16089. preferIconicZoomPreview: false,
  16090. allowedPreviewTypes: undefined,
  16091. allowedPreviewMimeTypes: null,
  16092. allowedFileTypes: null,
  16093. allowedFileExtensions: null,
  16094. defaultPreviewContent: null,
  16095. customLayoutTags: {},
  16096. customPreviewTags: {},
  16097. previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
  16098. previewFileIconClass: 'file-other-icon',
  16099. previewFileIconSettings: {},
  16100. previewFileExtSettings: {},
  16101. buttonLabelClass: 'hidden-xs',
  16102. browseIcon: '<i class="glyphicon glyphicon-folder-open"></i>&nbsp;',
  16103. browseClass: 'btn btn-primary',
  16104. removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
  16105. removeClass: 'btn btn-default',
  16106. cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
  16107. cancelClass: 'btn btn-default',
  16108. uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
  16109. uploadClass: 'btn btn-default',
  16110. uploadUrl: null,
  16111. uploadAsync: true,
  16112. uploadExtraData: {},
  16113. zoomModalHeight: 480,
  16114. minImageWidth: null,
  16115. minImageHeight: null,
  16116. maxImageWidth: null,
  16117. maxImageHeight: null,
  16118. resizeImage: false,
  16119. resizePreference: 'width',
  16120. resizeQuality: 0.92,
  16121. resizeDefaultImageType: 'image/jpeg',
  16122. resizeIfSizeMoreThan: 0, // in KB
  16123. minFileSize: 0,
  16124. maxFileSize: 0,
  16125. maxFilePreviewSize: 25600, // 25 MB
  16126. minFileCount: 0,
  16127. maxFileCount: 0,
  16128. validateInitialCount: false,
  16129. msgValidationErrorClass: 'text-danger',
  16130. msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
  16131. msgErrorClass: 'file-error-message',
  16132. progressThumbClass: "progress-bar progress-bar-success progress-bar-striped active",
  16133. progressClass: "progress-bar progress-bar-success progress-bar-striped active",
  16134. progressCompleteClass: "progress-bar progress-bar-success",
  16135. progressErrorClass: "progress-bar progress-bar-danger",
  16136. progressUploadThreshold: 99,
  16137. previewFileType: 'image',
  16138. elCaptionContainer: null,
  16139. elCaptionText: null,
  16140. elPreviewContainer: null,
  16141. elPreviewImage: null,
  16142. elPreviewStatus: null,
  16143. elErrorContainer: null,
  16144. errorCloseButton: '<span class="close kv-error-close">&times;</span>',
  16145. slugCallback: null,
  16146. dropZoneEnabled: true,
  16147. dropZoneTitleClass: 'file-drop-zone-title',
  16148. fileActionSettings: {},
  16149. otherActionButtons: '',
  16150. textEncoding: 'UTF-8',
  16151. ajaxSettings: {},
  16152. ajaxDeleteSettings: {},
  16153. showAjaxErrorDetails: true
  16154. };
  16155. $.fn.fileinputLocales.en = {
  16156. fileSingle: 'file',
  16157. filePlural: 'files',
  16158. browseLabel: 'Browse &hellip;',
  16159. removeLabel: 'Remove',
  16160. removeTitle: 'Clear selected files',
  16161. cancelLabel: 'Cancel',
  16162. cancelTitle: 'Abort ongoing upload',
  16163. uploadLabel: 'Upload',
  16164. uploadTitle: 'Upload selected files',
  16165. msgNo: 'No',
  16166. msgNoFilesSelected: 'No files selected',
  16167. msgCancelled: 'Cancelled',
  16168. msgZoomModalHeading: 'Detailed Preview',
  16169. msgFileRequired: 'You must select a file to upload.',
  16170. msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
  16171. msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
  16172. msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
  16173. msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
  16174. msgFileNotFound: 'File "{name}" not found!',
  16175. msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
  16176. msgFileNotReadable: 'File "{name}" is not readable.',
  16177. msgFilePreviewAborted: 'File preview aborted for "{name}".',
  16178. msgFilePreviewError: 'An error occurred while reading the file "{name}".',
  16179. msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
  16180. msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
  16181. msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
  16182. msgFileTypes: {
  16183. 'image': 'image',
  16184. 'html': 'HTML',
  16185. 'text': 'text',
  16186. 'video': 'video',
  16187. 'audio': 'audio',
  16188. 'flash': 'flash',
  16189. 'pdf': 'PDF',
  16190. 'object': 'object'
  16191. },
  16192. msgUploadAborted: 'The file upload was aborted',
  16193. msgUploadThreshold: 'Processing...',
  16194. msgUploadBegin: 'Initializing...',
  16195. msgUploadEnd: 'Done',
  16196. msgUploadEmpty: 'No valid data available for upload.',
  16197. msgValidationError: 'Validation Error',
  16198. msgLoading: 'Loading file {index} of {files} &hellip;',
  16199. msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
  16200. msgSelected: '{n} {files} selected',
  16201. msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
  16202. msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
  16203. msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
  16204. msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
  16205. msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
  16206. msgImageResizeError: 'Could not get the image dimensions to resize.',
  16207. msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
  16208. msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
  16209. msgAjaxProgressError: '{operation} failed',
  16210. ajaxOperations: {
  16211. deleteThumb: 'file delete',
  16212. uploadThumb: 'file upload',
  16213. uploadBatch: 'batch file upload',
  16214. uploadExtra: 'form data upload'
  16215. },
  16216. dropZoneTitle: 'Drag & drop files here &hellip;',
  16217. dropZoneClickTitle: '<br>(or click to select {files})',
  16218. previewZoomButtonTitles: {
  16219. prev: 'View previous file',
  16220. next: 'View next file',
  16221. toggleheader: 'Toggle header',
  16222. fullscreen: 'Toggle full screen',
  16223. borderless: 'Toggle borderless mode',
  16224. close: 'Close detailed preview'
  16225. }
  16226. };
  16227. $.fn.fileinput.Constructor = FileInput;
  16228. /**
  16229. * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
  16230. */
  16231. $(document).ready(function () {
  16232. var $input = $('input.file[type=file]');
  16233. if ($input.length) {
  16234. $input.fileinput();
  16235. }
  16236. });
  16237. }));
  16238. /***/ }),
  16239. /* 18 */
  16240. /***/ (function(module, exports) {
  16241. // removed by extract-text-webpack-plugin
  16242. /***/ }),
  16243. /* 19 */
  16244. /***/ (function(module, exports) {
  16245. // removed by extract-text-webpack-plugin
  16246. /***/ }),
  16247. /* 20 */
  16248. /***/ (function(module, exports) {
  16249. // removed by extract-text-webpack-plugin
  16250. /***/ }),
  16251. /* 21 */
  16252. /***/ (function(module, exports) {
  16253. // removed by extract-text-webpack-plugin
  16254. /***/ })
  16255. /******/ ]);
  16256. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgZjJhMzFjMmJjMGY3ZDkxNzdjYjIiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS9kaXN0L2pxdWVyeS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2pzL25wbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL3RyYW5zaXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9hbGVydC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2J1dHRvbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Nhcm91c2VsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvY29sbGFwc2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9kcm9wZG93bi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL21vZGFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvdG9vbHRpcC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL3BvcG92ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9zY3JvbGxzcHkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90YWIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9hZmZpeC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2pzL2Jvb3RzdHJhcC1zZWxlY3QuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC12YWxpZGF0b3IvanMvdmFsaWRhdG9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2pzL2ZpbGVpbnB1dC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvY3NzL2Jvb3RzdHJhcC5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1zZWxlY3QvZGlzdC9jc3MvYm9vdHN0cmFwLXNlbGVjdC5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3MiLCJ3ZWJwYWNrOi8vLy4vc3JjL3N0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7OztBQUlBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsWUFBWTs7QUFFcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxTQUFTO0FBQ2xCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyxZQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLFNBQVM7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxnQkFBZ0IsSUFBSTs7QUFFcEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esd0NBQXdDLElBQUk7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSx5QkFBeUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUSw2QkFBNkI7QUFDaEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGdCQUFnQjtBQUMzQixhQUFhLHVCQUF1QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGNBQWM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGVBQWU7O0FBRWYsU0FBUzs7QUFFVDtBQUNBLFFBQVEsaUNBQWlDO0FBQ3pDLFFBQVEsb0JBQW9CO0FBQzVCLFFBQVEsc0NBQXNDO0FBQzlDLFFBQVE7QUFDUixFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYSxFQUFFO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw0REFBNEQ7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEOztBQUU3RDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0VBQWdFOztBQUVoRTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFLFVBQVU7QUFDM0Usc0NBQXNDLDJCQUEyQjtBQUNqRTtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxVQUFVO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsY0FBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFlBQVksdUVBQXVFO0FBQ25GO0FBQ0E7QUFDQSxZQUFZLDRCQUE0QjtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLFNBQVM7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSwyREFBMkQ7O0FBRTNEO0FBQ0E7QUFDQSxvRkFBb0Y7O0FBRXBGO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaURBQWlEO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pELFVBQVUsd0NBQXdDO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsTUFBTTtBQUNqQixXQUFXLE1BQU07QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUEsQ0FBQzs7OztBQUlEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLFFBQVEsR0FBRztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOzs7O0FBSUE7O0FBRUE7O0FBRUE7QUFDQTs7OztBQUlBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLFNBQVM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUEsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVLE9BQU87QUFDakIsMEJBQTBCLHdCQUF3Qjs7QUFFbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsMENBQTBDO0FBQzFDLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxjQUFjO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLHNDQUFzQztBQUM5RSxvQ0FBb0MsdUNBQXVDO0FBQzNFLG9DQUFvQyxzQ0FBc0M7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUixPQUFPO0FBQ1A7QUFDQSxNQUFNO0FBQ04sS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTs7QUFFVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQyxxQ0FBcUM7QUFDckMsb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7Ozs7O0FBS0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxTQUFTO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGFBQWE7QUFDcEMsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsU0FBUztBQUM3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSxnQkFBZ0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsT0FBTztBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLE9BQU87QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRSxnQkFBZ0I7QUFDbEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQVc7O0FBRVg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsY0FBYzs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix1Q0FBdUM7QUFDakU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVEQUF1RDtBQUM5RTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGNBQWM7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixnQkFBZ0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLCtCQUErQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLE9BQU87QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLE9BQU87QUFDL0M7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLHFDQUFxQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBLFNBQVMsOEJBQThCO0FBQ3ZDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxZQUFZLE9BQU87QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLFdBQVc7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7O0FBSUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCLHNCQUFzQixjQUFjO0FBQ3BDLGdCQUFnQixXQUFXLFlBQVk7QUFDdkMsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFVBQVUsU0FBUyxNQUFNLGFBQWE7QUFDM0UsYUFBYSxlQUFlO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0YsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwrREFBK0Q7QUFDM0U7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsUUFBUSxPQUFPOztBQUVmO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGdCQUFnQjtBQUNsQztBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQSxVQUFVLE9BQU87QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQSxRQUFRLE9BQU87QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsZ0JBQWdCO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osaURBQWlELDBCQUEwQjtBQUMzRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsZ0JBQWdCO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0E7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQSxRQUFRLGdCQUFnQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVMsZ0JBQWdCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLGNBQWM7QUFDbEMsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxrQkFBa0I7QUFDNUIsV0FBVyxrQkFBa0I7QUFDN0IsY0FBYztBQUNkLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSxtQkFBbUI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEOzs7QUFHQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBOztBQUVBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQztBQUMzQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsS0FBSztBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQ0FBcUM7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsS0FBSztBQUNMOztBQUVBLFdBQVc7QUFDWCxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEIsZ0RBQWdEO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakIsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0Esc0JBQXNCO0FBQ3RCLDJCQUEyQjs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHVCQUF1QjtBQUNsQyxXQUFXLHlCQUF5QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFEQUFxRDtBQUNyRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CLDREQUE0RCxlQUFlO0FBQzNFO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGNBQWMsc0RBQXNEO0FBQ3BFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0EsY0FBYyxtQ0FBbUM7QUFDakQsZUFBZSw2REFBNkQ7QUFDNUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLEVBQUU7QUFDRixDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQUE7QUFDRjs7Ozs7QUFLQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzVnVUQ7QUFBQTtBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSxlQUFlO0FBQzlCLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSwrQkFBK0IsMkJBQTJCO0FBQzFELDBDQUEwQyxlQUFlOztBQUV6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsdUJBQXVCOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLDRCQUE0QjtBQUMxQztBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSx1QkFBdUIsYUFBYSxHQUFHLFdBQVcsR0FBRyxhQUFhLEdBQUcsY0FBYztBQUNuRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBOztBQUVBLENBQUM7Ozs7Ozs7QUNuSkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUI7Ozs7OztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsZ0JBQWdCO0FBQ2hFLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsQ0FBQzs7Ozs7Ozs7QUMxREQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQzs7Ozs7Ozs7QUM3RkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUwsQ0FBQzs7Ozs7Ozs7QUM1SEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQiwyQkFBMkI7QUFDM0I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxzRkFBc0YsZUFBZTtBQUNyRzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlEQUFpRCxxREFBcUQ7QUFDdEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUgsQ0FBQzs7Ozs7Ozs7QUM1T0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjs7QUFFL0I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDbk5EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCOztBQUUzQjs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0VBQXNFLHNCQUFzQjtBQUM1RjtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7Ozs7Ozs7QUNwS0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLGdDQUFnQzs7QUFFekU7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSx5Q0FBeUMsZ0NBQWdDOztBQUV6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7O0FBRS9CO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLGtDQUFrQzs7QUFFcEc7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0EsR0FBRzs7QUFFSCxDQUFDOzs7Ozs7OztBQ2xWRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxpQ0FBaUMsS0FBSztBQUN0Qzs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MsaUJBQWlCLGtDQUFrQztBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlCQUF5Qjs7QUFFekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsb0NBQW9DO0FBQ2xEO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVFQUF1RTtBQUN2RSwwQkFBMEIsV0FBVyx3RUFBd0U7QUFDN0c7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsa0JBQWtCO0FBQ2hELHFCQUFxQjtBQUNyQiw4QkFBOEIsdURBQXVEOztBQUVyRixzQkFBc0I7QUFDdEI7O0FBRUE7QUFDQSxvQ0FBb0MsZ0ZBQWdGO0FBQ3BILG9DQUFvQyxnRkFBZ0Y7QUFDcEgsb0NBQW9DLGlGQUFpRjtBQUNySCxvQ0FBb0M7O0FBRXBDOztBQUVBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbURBQW1EO0FBQ25EO0FBQ0EsT0FBTyxrRkFBa0Y7QUFDekY7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0EsT0FBTyx1REFBdUQ7QUFDOUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7Ozs7Ozs7O0FDdmdCRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBOztBQUVBLGlDQUFpQzs7QUFFakM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOzs7Ozs7OztBQzNHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCw2QkFBNkIscUJBQXFCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCLEtBQUs7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDM0tEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOzs7Ozs7OztBQzFKRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDaktEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUFBO0FBQ0wsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSyx5QkFBeUI7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyx1QkFBdUI7QUFDOUIsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGNBQWM7QUFDZCxjQUFjO0FBQ2QsZ0JBQWdCO0FBQ2hCLGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEI7O0FBRUE7QUFDQSxVQUFVO0FBQ1YsU0FBUztBQUNULFNBQVM7QUFDVCxXQUFXO0FBQ1gsV0FBVztBQUNYLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxFQUFFO0FBQzVDO0FBQ0Esb0NBQW9DLEVBQUUsb0JBQW9CLEVBQUU7QUFDNUQsS0FBSztBQUNMO0FBQ0E7QUFDQSx5Q0FBeUMsRUFBRSwrQkFBK0IsRUFBRTtBQUM1RSxpREFBaUQsRUFBRSxxQ0FBcUMsRUFBRTtBQUMxRjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtSUFBbUk7QUFDbkk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7O0FBRXZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxvQ0FBb0M7QUFDcEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLEVBQUUsOENBQThDLEVBQUU7QUFDdkY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDhCQUE4QjtBQUM5Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiw4QkFBOEI7QUFDOUI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsMERBQTBELEVBQUU7QUFDNUQsNkRBQTZELEVBQUU7QUFDL0Q7QUFDQSx5QkFBeUIsSUFBSTtBQUM3QjtBQUNBO0FBQ0EsOENBQThDLElBQUk7QUFDbEQsb0RBQW9ELElBQUk7QUFDeEQ7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBLG9FQUFvRSxFQUFFO0FBQ3RFO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQSxxQkFBcUIsZUFBZTtBQUNwQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyx5REFBeUQ7QUFDM0YsdUNBQXVDLHdHQUF3RztBQUMvSTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxDQUFDOzs7QUFHRCxDQUFDOzs7Ozs7O0FDLzBERDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLDRCQUE0QjtBQUN2RDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLDhDQUE4QyxzQkFBc0I7QUFDcEU7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDLHNDQUFzQztBQUNuRiwyQ0FBMkMsMENBQTBDOztBQUVyRjtBQUNBOztBQUVBOztBQUVBLCtEQUErRCxzQkFBc0I7QUFDckYsS0FBSztBQUNMOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxrREFBa0Q7QUFDdkcsK0JBQStCLDBCQUEwQjtBQUN6RCxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw2QkFBNkIsd0RBQXdEO0FBQ3JGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw4Q0FBOEMsbUNBQW1DOztBQUVqRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDN1pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBcUQ7QUFDckQ7QUFDQTtBQUFBO0FBQUE7QUFBQSxxR0FBb0M7QUFDcEMsS0FBSyxPQUFPO0FBQ1osMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQSx3REFBd0Q7QUFDeEQsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsYUFBYTtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsT0FBTyxRQUFRLFFBQVE7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIscUJBQXFCLEdBQUcsZ0JBQWdCO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsZ0JBQWdCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLG9CQUFvQjtBQUMzQztBQUNBO0FBQ0Esa0VBQWtFO0FBQ2xFO0FBQ0EsNEZBQTRGLGNBQWM7QUFDMUc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSwyQ0FBMkM7QUFDM0Msb0NBQW9DO0FBQ3BDLG9DQUFvQztBQUNwQyxzQ0FBc0M7QUFDdEMsc0NBQXNDO0FBQ3RDLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsOEJBQThCO0FBQ3hEO0FBQ0EsYUFBYTtBQUNiLDBCQUEwQixxQ0FBcUM7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELE1BQU07QUFDdEQsd0RBQXdELE1BQU07QUFDOUQscURBQXFELE1BQU07QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsUUFBUTtBQUMvQjtBQUNBLDBDQUEwQyxNQUFNO0FBQ2hELHFCQUFxQixRQUFRO0FBQzdCO0FBQ0EseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEM7QUFDQTtBQUNBLHVCQUF1QixRQUFRLGdEQUFnRCxPQUFPLEdBQUcsT0FBTyxHQUFHLE9BQU8sR0FBRyxPQUFPO0FBQ3BILGtEQUFrRCxNQUFNO0FBQ3hELHNCQUFzQixNQUFNO0FBQzVCLGtDQUFrQyxVQUFVO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0EsOEVBQThFLE1BQU07QUFDcEY7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLEtBQUsseUJBQXlCLE1BQU0sVUFBVSxJQUFJO0FBQzVGLGtCQUFrQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDeEM7QUFDQSxrQ0FBa0MsS0FBSyx5QkFBeUIsTUFBTSxVQUFVLElBQUksR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDN0c7QUFDQSxzREFBc0QsSUFBSSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTTtBQUNuRjtBQUNBO0FBQ0Esd0RBQXdELElBQUk7QUFDNUQ7QUFDQTtBQUNBLGdFQUFnRSxjQUFjLFlBQVksWUFBWSxNQUFNO0FBQzVHLGdEQUFnRCxRQUFRO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxlQUFlLGdCQUFnQixLQUFLLEVBQUUsS0FBSztBQUM5RztBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxNQUFNO0FBQ3hDLGtDQUFrQyxRQUFRLHNEQUFzRCxRQUFRLEVBQUU7QUFDMUcsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBLDhCQUE4QixTQUFTO0FBQ3ZDO0FBQ0EsOERBQThELFFBQVEsR0FBRyxRQUFRLEtBQUssS0FBSztBQUMzRixzQkFBc0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRO0FBQ3JEO0FBQ0EseUJBQXlCLEtBQUs7QUFDOUI7QUFDQTtBQUNBLDBCQUEwQixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFLFlBQVk7QUFDdEYseUJBQXlCLFlBQVksR0FBRyxTQUFTLFFBQVEsRUFBRSxXQUFXO0FBQ3RFLDBFQUEwRSxZQUFZLFVBQVUsWUFBWTtBQUM1RyxrQkFBa0IsV0FBVztBQUM3QixzRUFBc0UsVUFBVTtBQUNoRix5QkFBeUIsVUFBVSxHQUFHLFNBQVM7QUFDL0MsMERBQTBELFVBQVUsVUFBVSxVQUFVLEdBQUcsU0FBUztBQUNwRyxxRUFBcUUsZUFBZSxHQUFHLFVBQVU7QUFDakcsdURBQXVELFdBQVcsT0FBTyxVQUFVLG1CQUFtQixVQUFVO0FBQ2hILGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0EsMkNBQTJDLFFBQVE7QUFDbkQsOEJBQThCLE9BQU87QUFDckMseUJBQXlCLFFBQVE7QUFDakMsNEVBQTRFLFFBQVE7QUFDcEYsbUJBQW1CLEtBQUs7QUFDeEIsaUNBQWlDLEtBQUsscURBQXFELFFBQVEsUUFBUSxRQUFRO0FBQ25IO0FBQ0EsaUZBQWlGLFFBQVE7QUFDekYsc0NBQXNDLEtBQUs7QUFDM0MsZ0ZBQWdGLE1BQU07QUFDdEYsMEJBQTBCLE9BQU8sZ0NBQWdDLEtBQUssU0FBUyxLQUFLO0FBQ3BGO0FBQ0EsOEdBQThHLEtBQUs7QUFDbkgsd0JBQXdCLEtBQUs7QUFDN0I7QUFDQSx5QkFBeUIsTUFBTSxXQUFXLE9BQU8sU0FBUyxLQUFLO0FBQy9EO0FBQ0EsbUVBQW1FLFFBQVEsU0FBUyxLQUFLLFNBQVMsS0FBSztBQUN2Ryx5QkFBeUIsTUFBTSxXQUFXLE9BQU8scUNBQXFDLFFBQVE7QUFDOUY7QUFDQSx5REFBeUQsS0FBSztBQUM5RCx5QkFBeUIsTUFBTSxXQUFXLE9BQU87QUFDakQ7QUFDQSwyRUFBMkUsWUFBWTtBQUN2RiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0EsNEJBQTRCLCtCQUErQjtBQUMzRCwyQkFBMkIsZ0NBQWdDO0FBQzNELDJCQUEyQixnQ0FBZ0M7QUFDM0QsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QixtREFBbUQ7QUFDL0UsNkJBQTZCLGVBQWU7QUFDNUMsMEJBQTBCLGdDQUFnQztBQUMxRCw0QkFBNEI7QUFDNUIsaUJBQWlCO0FBQ2pCO0FBQ0EsNEJBQTRCLHlFQUF5RTtBQUNyRztBQUNBO0FBQ0EsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QiwrQkFBK0I7QUFDM0QsNkJBQTZCLDBFQUEwRTtBQUN2RztBQUNBLDRCQUE0QjtBQUM1QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QyxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLHdDQUF3QywyQkFBMkI7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxvQkFBb0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsbUJBQW1CO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLGlCQUFpQjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0EsK0JBQStCLFNBQVM7QUFDeEM7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsOENBQThDLEtBQUs7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxFQUFFO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EscURBQXFELEVBQUUsZ0NBQWdDLE1BQU07QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EscURBQXFELFVBQVU7QUFDL0Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1QkFBdUIsa0JBQWtCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLDhCQUE4QixnQkFBZ0I7QUFDOUMscUNBQXFDLDBFQUEwRTtBQUMvRztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGtFQUFrRTtBQUNsRSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsc0NBQXNDO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLDJDQUEyQztBQUN0RixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHNEQUFzRCxFQUFFLGdCQUFnQixNQUFNO0FBQzlFLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLDJCQUEyQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUZBQXFGLHdCQUF3QjtBQUM3RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsc0JBQXNCO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNGQUFzRixVQUFVO0FBQ2hHO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0Esc0ZBQXNGO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0EsbUdBQW1HO0FBQ25HO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsR0FBRyxVQUFVO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QixxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsU0FBUztBQUN0RSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLFlBQVk7QUFDNUY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThELDJCQUEyQjtBQUN6RjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsaUNBQWlDO0FBQzlEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixTQUFTO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLDZFQUE2RSxFQUFFO0FBQy9FLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHFCQUFxQixJQUFJLFdBQVcsNEJBQTRCO0FBQzlHLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFlBQVk7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsS0FBSztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixzQkFBc0I7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRSxtQ0FBbUM7QUFDcEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxzQ0FBc0M7QUFDNUc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxNQUFNLG9CQUFvQixNQUFNO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsdURBQXVEO0FBQ3JHLGlCQUFpQjtBQUNqQiw4Q0FBOEMsb0VBQW9FO0FBQ2xIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxNQUFNO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCw2QkFBNkI7QUFDeEY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBLDJDQUEyQyxPQUFPO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsOEJBQThCO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsT0FBTztBQUNwRSxpQ0FBaUMsc0JBQXNCO0FBQ3ZEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QyxtRUFBbUU7QUFDM0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLGlEQUFpRDtBQUNqRjtBQUNBLDBEQUEwRCx1Q0FBdUM7QUFDakc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkVBQTZFLEtBQUs7QUFDbEYscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCw4Q0FBOEM7QUFDL0Y7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLDBDQUEwQztBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLGdCQUFnQjtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1RkFBdUY7QUFDdkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxxQkFBcUIsSUFBSSxXQUFXLDRCQUE0QjtBQUM5Ryw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0EsK0NBQStDLDBDQUEwQztBQUN6RixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCxFQUFFLGdDQUFnQyxFQUFFO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsd0RBQXdEO0FBQ3pGO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUNBQWlDLG9DQUFvQztBQUNyRTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFNBQVM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxRQUFRO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkMsa0NBQWtDO0FBQ2xDO0FBQ0EsMEVBQTBFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBLHdCQUF3QjtBQUN4Qiw4QkFBOEI7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxLQUFLLE9BQU8sS0FBSyxrREFBa0QsUUFBUTtBQUM1RyxpQ0FBaUMsS0FBSyxPQUFPLEtBQUssb0RBQW9ELFFBQVE7QUFDOUcsdURBQXVELEVBQUUsTUFBTSxNQUFNO0FBQ3JFLG1FQUFtRSxFQUFFLDJDQUEyQyxFQUFFO0FBQ2xILGlDQUFpQyxLQUFLO0FBQ3RDLDBFQUEwRSxLQUFLO0FBQy9FLG9DQUFvQyxLQUFLO0FBQ3pDLDJEQUEyRCxLQUFLO0FBQ2hFLHlFQUF5RSxLQUFLO0FBQzlFLDhFQUE4RSxLQUFLO0FBQ25GLHFEQUFxRCxLQUFLLFVBQVUsTUFBTTtBQUMxRSwrREFBK0QsS0FBSyxVQUFVLFdBQVc7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxNQUFNLEtBQUssTUFBTSxTQUFTO0FBQzdELG9DQUFvQyxNQUFNLEtBQUssTUFBTSxJQUFJLEtBQUssSUFBSSxRQUFRO0FBQzFFLHVCQUF1QixFQUFFLEVBQUUsTUFBTTtBQUNqQyx3REFBd0QsRUFBRTtBQUMxRCxtREFBbUQsS0FBSyxvQkFBb0IsS0FBSztBQUNqRixxREFBcUQsS0FBSyxvQkFBb0IsS0FBSztBQUNuRixtREFBbUQsS0FBSyxpQkFBaUIsS0FBSztBQUM5RSxxREFBcUQsS0FBSyxpQkFBaUIsS0FBSztBQUNoRjtBQUNBLHVFQUF1RSxPQUFPO0FBQzlFLHNEQUFzRCxVQUFVO0FBQ2hFLGdDQUFnQyxVQUFVO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsdURBQXVEO0FBQ3ZELHNEQUFzRCxNQUFNO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLENBQUMsRzs7Ozs7O0FDMzFIRCx5Qzs7Ozs7O0FDQUEseUM7Ozs7OztBQ0FBLHlDOzs7Ozs7QUNBQSx5QyIsImZpbGUiOiJtYWluLmJ1bmRsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbiBcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG4gXHRcdFx0XHRnZXQ6IGdldHRlclxuIFx0XHRcdH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDEpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIGYyYTMxYzJiYzBmN2Q5MTc3Y2IyIiwiLyohXG4gKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYzLjIuMVxuICogaHR0cHM6Ly9qcXVlcnkuY29tL1xuICpcbiAqIEluY2x1ZGVzIFNpenpsZS5qc1xuICogaHR0cHM6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IEpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKiBodHRwczovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTctMDMtMjBUMTg6NTlaXG4gKi9cbiggZnVuY3Rpb24oIGdsb2JhbCwgZmFjdG9yeSApIHtcblxuXHRcInVzZSBzdHJpY3RcIjtcblxuXHRpZiAoIHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0Ly8gRm9yIENvbW1vbkpTIGFuZCBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB3aGVyZSBhIHByb3BlciBgd2luZG93YFxuXHRcdC8vIGlzIHByZXNlbnQsIGV4ZWN1dGUgdGhlIGZhY3RvcnkgYW5kIGdldCBqUXVlcnkuXG5cdFx0Ly8gRm9yIGVudmlyb25tZW50cyB0aGF0IGRvIG5vdCBoYXZlIGEgYHdpbmRvd2Agd2l0aCBhIGBkb2N1bWVudGBcblx0XHQvLyAoc3VjaCBhcyBOb2RlLmpzKSwgZXhwb3NlIGEgZmFjdG9yeSBhcyBtb2R1bGUuZXhwb3J0cy5cblx0XHQvLyBUaGlzIGFjY2VudHVhdGVzIHRoZSBuZWVkIGZvciB0aGUgY3JlYXRpb24gb2YgYSByZWFsIGB3aW5kb3dgLlxuXHRcdC8vIGUuZy4gdmFyIGpRdWVyeSA9IHJlcXVpcmUoXCJqcXVlcnlcIikod2luZG93KTtcblx0XHQvLyBTZWUgdGlja2V0ICMxNDU0OSBmb3IgbW9yZSBpbmZvLlxuXHRcdG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsLmRvY3VtZW50ID9cblx0XHRcdGZhY3RvcnkoIGdsb2JhbCwgdHJ1ZSApIDpcblx0XHRcdGZ1bmN0aW9uKCB3ICkge1xuXHRcdFx0XHRpZiAoICF3LmRvY3VtZW50ICkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJqUXVlcnkgcmVxdWlyZXMgYSB3aW5kb3cgd2l0aCBhIGRvY3VtZW50XCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gZmFjdG9yeSggdyApO1xuXHRcdFx0fTtcblx0fSBlbHNlIHtcblx0XHRmYWN0b3J5KCBnbG9iYWwgKTtcblx0fVxuXG4vLyBQYXNzIHRoaXMgaWYgd2luZG93IGlzIG5vdCBkZWZpbmVkIHlldFxufSApKCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oIHdpbmRvdywgbm9HbG9iYWwgKSB7XG5cbi8vIEVkZ2UgPD0gMTIgLSAxMyssIEZpcmVmb3ggPD0xOCAtIDQ1KywgSUUgMTAgLSAxMSwgU2FmYXJpIDUuMSAtIDkrLCBpT1MgNiAtIDkuMVxuLy8gdGhyb3cgZXhjZXB0aW9ucyB3aGVuIG5vbi1zdHJpY3QgY29kZSAoZS5nLiwgQVNQLk5FVCA0LjUpIGFjY2Vzc2VzIHN0cmljdCBtb2RlXG4vLyBhcmd1bWVudHMuY2FsbGVlLmNhbGxlciAodHJhYy0xMzMzNSkuIEJ1dCBhcyBvZiBqUXVlcnkgMy4wICgyMDE2KSwgc3RyaWN0IG1vZGUgc2hvdWxkIGJlIGNvbW1vblxuLy8gZW5vdWdoIHRoYXQgYWxsIHN1Y2ggYXR0ZW1wdHMgYXJlIGd1YXJkZWQgaW4gYSB0cnkgYmxvY2suXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGFyciA9IFtdO1xuXG52YXIgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQ7XG5cbnZhciBnZXRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjtcblxudmFyIHNsaWNlID0gYXJyLnNsaWNlO1xuXG52YXIgY29uY2F0ID0gYXJyLmNvbmNhdDtcblxudmFyIHB1c2ggPSBhcnIucHVzaDtcblxudmFyIGluZGV4T2YgPSBhcnIuaW5kZXhPZjtcblxudmFyIGNsYXNzMnR5cGUgPSB7fTtcblxudmFyIHRvU3RyaW5nID0gY2xhc3MydHlwZS50b1N0cmluZztcblxudmFyIGhhc093biA9IGNsYXNzMnR5cGUuaGFzT3duUHJvcGVydHk7XG5cbnZhciBmblRvU3RyaW5nID0gaGFzT3duLnRvU3RyaW5nO1xuXG52YXIgT2JqZWN0RnVuY3Rpb25TdHJpbmcgPSBmblRvU3RyaW5nLmNhbGwoIE9iamVjdCApO1xuXG52YXIgc3VwcG9ydCA9IHt9O1xuXG5cblxuXHRmdW5jdGlvbiBET01FdmFsKCBjb2RlLCBkb2MgKSB7XG5cdFx0ZG9jID0gZG9jIHx8IGRvY3VtZW50O1xuXG5cdFx0dmFyIHNjcmlwdCA9IGRvYy5jcmVhdGVFbGVtZW50KCBcInNjcmlwdFwiICk7XG5cblx0XHRzY3JpcHQudGV4dCA9IGNvZGU7XG5cdFx0ZG9jLmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdCApLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHNjcmlwdCApO1xuXHR9XG4vKiBnbG9iYWwgU3ltYm9sICovXG4vLyBEZWZpbmluZyB0aGlzIGdsb2JhbCBpbiAuZXNsaW50cmMuanNvbiB3b3VsZCBjcmVhdGUgYSBkYW5nZXIgb2YgdXNpbmcgdGhlIGdsb2JhbFxuLy8gdW5ndWFyZGVkIGluIGFub3RoZXIgcGxhY2UsIGl0IHNlZW1zIHNhZmVyIHRvIGRlZmluZSBnbG9iYWwgb25seSBmb3IgdGhpcyBtb2R1bGVcblxuXG5cbnZhclxuXHR2ZXJzaW9uID0gXCIzLjIuMVwiLFxuXG5cdC8vIERlZmluZSBhIGxvY2FsIGNvcHkgb2YgalF1ZXJ5XG5cdGpRdWVyeSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblxuXHRcdC8vIFRoZSBqUXVlcnkgb2JqZWN0IGlzIGFjdHVhbGx5IGp1c3QgdGhlIGluaXQgY29uc3RydWN0b3IgJ2VuaGFuY2VkJ1xuXHRcdC8vIE5lZWQgaW5pdCBpZiBqUXVlcnkgaXMgY2FsbGVkIChqdXN0IGFsbG93IGVycm9yIHRvIGJlIHRocm93biBpZiBub3QgaW5jbHVkZWQpXG5cdFx0cmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHdlIHRyaW0gQk9NIGFuZCBOQlNQXG5cdHJ0cmltID0gL15bXFxzXFx1RkVGRlxceEEwXSt8W1xcc1xcdUZFRkZcXHhBMF0rJC9nLFxuXG5cdC8vIE1hdGNoZXMgZGFzaGVkIHN0cmluZyBmb3IgY2FtZWxpemluZ1xuXHRybXNQcmVmaXggPSAvXi1tcy0vLFxuXHRyZGFzaEFscGhhID0gLy0oW2Etel0pL2csXG5cblx0Ly8gVXNlZCBieSBqUXVlcnkuY2FtZWxDYXNlIGFzIGNhbGxiYWNrIHRvIHJlcGxhY2UoKVxuXHRmY2FtZWxDYXNlID0gZnVuY3Rpb24oIGFsbCwgbGV0dGVyICkge1xuXHRcdHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTtcblx0fTtcblxualF1ZXJ5LmZuID0galF1ZXJ5LnByb3RvdHlwZSA9IHtcblxuXHQvLyBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIGpRdWVyeSBiZWluZyB1c2VkXG5cdGpxdWVyeTogdmVyc2lvbixcblxuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LFxuXG5cdC8vIFRoZSBkZWZhdWx0IGxlbmd0aCBvZiBhIGpRdWVyeSBvYmplY3QgaXMgMFxuXHRsZW5ndGg6IDAsXG5cblx0dG9BcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SXG5cdC8vIEdldCB0aGUgd2hvbGUgbWF0Y2hlZCBlbGVtZW50IHNldCBhcyBhIGNsZWFuIGFycmF5XG5cdGdldDogZnVuY3Rpb24oIG51bSApIHtcblxuXHRcdC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGluIGEgY2xlYW4gYXJyYXlcblx0XHRpZiAoIG51bSA9PSBudWxsICkge1xuXHRcdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4ganVzdCB0aGUgb25lIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG5cdFx0cmV0dXJuIG51bSA8IDAgPyB0aGlzWyBudW0gKyB0aGlzLmxlbmd0aCBdIDogdGhpc1sgbnVtIF07XG5cdH0sXG5cblx0Ly8gVGFrZSBhbiBhcnJheSBvZiBlbGVtZW50cyBhbmQgcHVzaCBpdCBvbnRvIHRoZSBzdGFja1xuXHQvLyAocmV0dXJuaW5nIHRoZSBuZXcgbWF0Y2hlZCBlbGVtZW50IHNldClcblx0cHVzaFN0YWNrOiBmdW5jdGlvbiggZWxlbXMgKSB7XG5cblx0XHQvLyBCdWlsZCBhIG5ldyBqUXVlcnkgbWF0Y2hlZCBlbGVtZW50IHNldFxuXHRcdHZhciByZXQgPSBqUXVlcnkubWVyZ2UoIHRoaXMuY29uc3RydWN0b3IoKSwgZWxlbXMgKTtcblxuXHRcdC8vIEFkZCB0aGUgb2xkIG9iamVjdCBvbnRvIHRoZSBzdGFjayAoYXMgYSByZWZlcmVuY2UpXG5cdFx0cmV0LnByZXZPYmplY3QgPSB0aGlzO1xuXG5cdFx0Ly8gUmV0dXJuIHRoZSBuZXdseS1mb3JtZWQgZWxlbWVudCBzZXRcblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdC8vIEV4ZWN1dGUgYSBjYWxsYmFjayBmb3IgZXZlcnkgZWxlbWVudCBpbiB0aGUgbWF0Y2hlZCBzZXQuXG5cdGVhY2g6IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmVhY2goIHRoaXMsIGNhbGxiYWNrICk7XG5cdH0sXG5cblx0bWFwOiBmdW5jdGlvbiggY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkubWFwKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKCBlbGVtLCBpLCBlbGVtICk7XG5cdFx0fSApICk7XG5cdH0sXG5cblx0c2xpY2U6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggc2xpY2UuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApICk7XG5cdH0sXG5cblx0Zmlyc3Q6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVxKCAwICk7XG5cdH0sXG5cblx0bGFzdDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZXEoIC0xICk7XG5cdH0sXG5cblx0ZXE6IGZ1bmN0aW9uKCBpICkge1xuXHRcdHZhciBsZW4gPSB0aGlzLmxlbmd0aCxcblx0XHRcdGogPSAraSArICggaSA8IDAgPyBsZW4gOiAwICk7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqID49IDAgJiYgaiA8IGxlbiA/IFsgdGhpc1sgaiBdIF0gOiBbXSApO1xuXHR9LFxuXG5cdGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCk7XG5cdH0sXG5cblx0Ly8gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuXHQvLyBCZWhhdmVzIGxpa2UgYW4gQXJyYXkncyBtZXRob2QsIG5vdCBsaWtlIGEgalF1ZXJ5IG1ldGhvZC5cblx0cHVzaDogcHVzaCxcblx0c29ydDogYXJyLnNvcnQsXG5cdHNwbGljZTogYXJyLnNwbGljZVxufTtcblxualF1ZXJ5LmV4dGVuZCA9IGpRdWVyeS5mbi5leHRlbmQgPSBmdW5jdGlvbigpIHtcblx0dmFyIG9wdGlvbnMsIG5hbWUsIHNyYywgY29weSwgY29weUlzQXJyYXksIGNsb25lLFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgMCBdIHx8IHt9LFxuXHRcdGkgPSAxLFxuXHRcdGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cdFx0ZGVlcCA9IGZhbHNlO1xuXG5cdC8vIEhhbmRsZSBhIGRlZXAgY29weSBzaXR1YXRpb25cblx0aWYgKCB0eXBlb2YgdGFyZ2V0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRkZWVwID0gdGFyZ2V0O1xuXG5cdFx0Ly8gU2tpcCB0aGUgYm9vbGVhbiBhbmQgdGhlIHRhcmdldFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgaSBdIHx8IHt9O1xuXHRcdGkrKztcblx0fVxuXG5cdC8vIEhhbmRsZSBjYXNlIHdoZW4gdGFyZ2V0IGlzIGEgc3RyaW5nIG9yIHNvbWV0aGluZyAocG9zc2libGUgaW4gZGVlcCBjb3B5KVxuXHRpZiAoIHR5cGVvZiB0YXJnZXQgIT09IFwib2JqZWN0XCIgJiYgIWpRdWVyeS5pc0Z1bmN0aW9uKCB0YXJnZXQgKSApIHtcblx0XHR0YXJnZXQgPSB7fTtcblx0fVxuXG5cdC8vIEV4dGVuZCBqUXVlcnkgaXRzZWxmIGlmIG9ubHkgb25lIGFyZ3VtZW50IGlzIHBhc3NlZFxuXHRpZiAoIGkgPT09IGxlbmd0aCApIHtcblx0XHR0YXJnZXQgPSB0aGlzO1xuXHRcdGktLTtcblx0fVxuXG5cdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXG5cdFx0Ly8gT25seSBkZWFsIHdpdGggbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlc1xuXHRcdGlmICggKCBvcHRpb25zID0gYXJndW1lbnRzWyBpIF0gKSAhPSBudWxsICkge1xuXG5cdFx0XHQvLyBFeHRlbmQgdGhlIGJhc2Ugb2JqZWN0XG5cdFx0XHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRcdHNyYyA9IHRhcmdldFsgbmFtZSBdO1xuXHRcdFx0XHRjb3B5ID0gb3B0aW9uc1sgbmFtZSBdO1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbmV2ZXItZW5kaW5nIGxvb3Bcblx0XHRcdFx0aWYgKCB0YXJnZXQgPT09IGNvcHkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZWN1cnNlIGlmIHdlJ3JlIG1lcmdpbmcgcGxhaW4gb2JqZWN0cyBvciBhcnJheXNcblx0XHRcdFx0aWYgKCBkZWVwICYmIGNvcHkgJiYgKCBqUXVlcnkuaXNQbGFpbk9iamVjdCggY29weSApIHx8XG5cdFx0XHRcdFx0KCBjb3B5SXNBcnJheSA9IEFycmF5LmlzQXJyYXkoIGNvcHkgKSApICkgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGNvcHlJc0FycmF5ICkge1xuXHRcdFx0XHRcdFx0Y29weUlzQXJyYXkgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGNsb25lID0gc3JjICYmIEFycmF5LmlzQXJyYXkoIHNyYyApID8gc3JjIDogW107XG5cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIHNyYyApID8gc3JjIDoge307XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gTmV2ZXIgbW92ZSBvcmlnaW5hbCBvYmplY3RzLCBjbG9uZSB0aGVtXG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBqUXVlcnkuZXh0ZW5kKCBkZWVwLCBjbG9uZSwgY29weSApO1xuXG5cdFx0XHRcdC8vIERvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXNcblx0XHRcdFx0fSBlbHNlIGlmICggY29weSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHRhcmdldFsgbmFtZSBdID0gY29weTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbW9kaWZpZWQgb2JqZWN0XG5cdHJldHVybiB0YXJnZXQ7XG59O1xuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gVW5pcXVlIGZvciBlYWNoIGNvcHkgb2YgalF1ZXJ5IG9uIHRoZSBwYWdlXG5cdGV4cGFuZG86IFwialF1ZXJ5XCIgKyAoIHZlcnNpb24gKyBNYXRoLnJhbmRvbSgpICkucmVwbGFjZSggL1xcRC9nLCBcIlwiICksXG5cblx0Ly8gQXNzdW1lIGpRdWVyeSBpcyByZWFkeSB3aXRob3V0IHRoZSByZWFkeSBtb2R1bGVcblx0aXNSZWFkeTogdHJ1ZSxcblxuXHRlcnJvcjogZnVuY3Rpb24oIG1zZyApIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoIG1zZyApO1xuXHR9LFxuXG5cdG5vb3A6IGZ1bmN0aW9uKCkge30sXG5cblx0aXNGdW5jdGlvbjogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LnR5cGUoIG9iaiApID09PSBcImZ1bmN0aW9uXCI7XG5cdH0sXG5cblx0aXNXaW5kb3c6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0cmV0dXJuIG9iaiAhPSBudWxsICYmIG9iaiA9PT0gb2JqLndpbmRvdztcblx0fSxcblxuXHRpc051bWVyaWM6IGZ1bmN0aW9uKCBvYmogKSB7XG5cblx0XHQvLyBBcyBvZiBqUXVlcnkgMy4wLCBpc051bWVyaWMgaXMgbGltaXRlZCB0b1xuXHRcdC8vIHN0cmluZ3MgYW5kIG51bWJlcnMgKHByaW1pdGl2ZXMgb3Igb2JqZWN0cylcblx0XHQvLyB0aGF0IGNhbiBiZSBjb2VyY2VkIHRvIGZpbml0ZSBudW1iZXJzIChnaC0yNjYyKVxuXHRcdHZhciB0eXBlID0galF1ZXJ5LnR5cGUoIG9iaiApO1xuXHRcdHJldHVybiAoIHR5cGUgPT09IFwibnVtYmVyXCIgfHwgdHlwZSA9PT0gXCJzdHJpbmdcIiApICYmXG5cblx0XHRcdC8vIHBhcnNlRmxvYXQgTmFOcyBudW1lcmljLWNhc3QgZmFsc2UgcG9zaXRpdmVzIChcIlwiKVxuXHRcdFx0Ly8gLi4uYnV0IG1pc2ludGVycHJldHMgbGVhZGluZy1udW1iZXIgc3RyaW5ncywgcGFydGljdWxhcmx5IGhleCBsaXRlcmFscyAoXCIweC4uLlwiKVxuXHRcdFx0Ly8gc3VidHJhY3Rpb24gZm9yY2VzIGluZmluaXRpZXMgdG8gTmFOXG5cdFx0XHQhaXNOYU4oIG9iaiAtIHBhcnNlRmxvYXQoIG9iaiApICk7XG5cdH0sXG5cblx0aXNQbGFpbk9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHR2YXIgcHJvdG8sIEN0b3I7XG5cblx0XHQvLyBEZXRlY3Qgb2J2aW91cyBuZWdhdGl2ZXNcblx0XHQvLyBVc2UgdG9TdHJpbmcgaW5zdGVhZCBvZiBqUXVlcnkudHlwZSB0byBjYXRjaCBob3N0IG9iamVjdHNcblx0XHRpZiAoICFvYmogfHwgdG9TdHJpbmcuY2FsbCggb2JqICkgIT09IFwiW29iamVjdCBPYmplY3RdXCIgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cHJvdG8gPSBnZXRQcm90byggb2JqICk7XG5cblx0XHQvLyBPYmplY3RzIHdpdGggbm8gcHJvdG90eXBlIChlLmcuLCBgT2JqZWN0LmNyZWF0ZSggbnVsbCApYCkgYXJlIHBsYWluXG5cdFx0aWYgKCAhcHJvdG8gKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBPYmplY3RzIHdpdGggcHJvdG90eXBlIGFyZSBwbGFpbiBpZmYgdGhleSB3ZXJlIGNvbnN0cnVjdGVkIGJ5IGEgZ2xvYmFsIE9iamVjdCBmdW5jdGlvblxuXHRcdEN0b3IgPSBoYXNPd24uY2FsbCggcHJvdG8sIFwiY29uc3RydWN0b3JcIiApICYmIHByb3RvLmNvbnN0cnVjdG9yO1xuXHRcdHJldHVybiB0eXBlb2YgQ3RvciA9PT0gXCJmdW5jdGlvblwiICYmIGZuVG9TdHJpbmcuY2FsbCggQ3RvciApID09PSBPYmplY3RGdW5jdGlvblN0cmluZztcblx0fSxcblxuXHRpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiggb2JqICkge1xuXG5cdFx0LyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cblx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzbGludC9lc2xpbnQvaXNzdWVzLzYxMjVcblx0XHR2YXIgbmFtZTtcblxuXHRcdGZvciAoIG5hbWUgaW4gb2JqICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSxcblxuXHR0eXBlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdGlmICggb2JqID09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gb2JqICsgXCJcIjtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9Mi4zIG9ubHkgKGZ1bmN0aW9uaXNoIFJlZ0V4cClcblx0XHRyZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgP1xuXHRcdFx0Y2xhc3MydHlwZVsgdG9TdHJpbmcuY2FsbCggb2JqICkgXSB8fCBcIm9iamVjdFwiIDpcblx0XHRcdHR5cGVvZiBvYmo7XG5cdH0sXG5cblx0Ly8gRXZhbHVhdGVzIGEgc2NyaXB0IGluIGEgZ2xvYmFsIGNvbnRleHRcblx0Z2xvYmFsRXZhbDogZnVuY3Rpb24oIGNvZGUgKSB7XG5cdFx0RE9NRXZhbCggY29kZSApO1xuXHR9LFxuXG5cdC8vIENvbnZlcnQgZGFzaGVkIHRvIGNhbWVsQ2FzZTsgdXNlZCBieSB0aGUgY3NzIGFuZCBkYXRhIG1vZHVsZXNcblx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHQvLyBNaWNyb3NvZnQgZm9yZ290IHRvIGh1bXAgdGhlaXIgdmVuZG9yIHByZWZpeCAoIzk1NzIpXG5cdGNhbWVsQ2FzZTogZnVuY3Rpb24oIHN0cmluZyApIHtcblx0XHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoIHJtc1ByZWZpeCwgXCJtcy1cIiApLnJlcGxhY2UoIHJkYXNoQWxwaGEsIGZjYW1lbENhc2UgKTtcblx0fSxcblxuXHRlYWNoOiBmdW5jdGlvbiggb2JqLCBjYWxsYmFjayApIHtcblx0XHR2YXIgbGVuZ3RoLCBpID0gMDtcblxuXHRcdGlmICggaXNBcnJheUxpa2UoIG9iaiApICkge1xuXHRcdFx0bGVuZ3RoID0gb2JqLmxlbmd0aDtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIG9iaiApIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjay5jYWxsKCBvYmpbIGkgXSwgaSwgb2JqWyBpIF0gKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gb2JqO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seVxuXHR0cmltOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRyZXR1cm4gdGV4dCA9PSBudWxsID9cblx0XHRcdFwiXCIgOlxuXHRcdFx0KCB0ZXh0ICsgXCJcIiApLnJlcGxhY2UoIHJ0cmltLCBcIlwiICk7XG5cdH0sXG5cblx0Ly8gcmVzdWx0cyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYWtlQXJyYXk6IGZ1bmN0aW9uKCBhcnIsIHJlc3VsdHMgKSB7XG5cdFx0dmFyIHJldCA9IHJlc3VsdHMgfHwgW107XG5cblx0XHRpZiAoIGFyciAhPSBudWxsICkge1xuXHRcdFx0aWYgKCBpc0FycmF5TGlrZSggT2JqZWN0KCBhcnIgKSApICkge1xuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIHJldCxcblx0XHRcdFx0XHR0eXBlb2YgYXJyID09PSBcInN0cmluZ1wiID9cblx0XHRcdFx0XHRbIGFyciBdIDogYXJyXG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmNhbGwoIHJldCwgYXJyICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldDtcblx0fSxcblxuXHRpbkFycmF5OiBmdW5jdGlvbiggZWxlbSwgYXJyLCBpICkge1xuXHRcdHJldHVybiBhcnIgPT0gbnVsbCA/IC0xIDogaW5kZXhPZi5jYWxsKCBhcnIsIGVsZW0sIGkgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRtZXJnZTogZnVuY3Rpb24oIGZpcnN0LCBzZWNvbmQgKSB7XG5cdFx0dmFyIGxlbiA9ICtzZWNvbmQubGVuZ3RoLFxuXHRcdFx0aiA9IDAsXG5cdFx0XHRpID0gZmlyc3QubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRmaXJzdFsgaSsrIF0gPSBzZWNvbmRbIGogXTtcblx0XHR9XG5cblx0XHRmaXJzdC5sZW5ndGggPSBpO1xuXG5cdFx0cmV0dXJuIGZpcnN0O1xuXHR9LFxuXG5cdGdyZXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGludmVydCApIHtcblx0XHR2YXIgY2FsbGJhY2tJbnZlcnNlLFxuXHRcdFx0bWF0Y2hlcyA9IFtdLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsZW5ndGggPSBlbGVtcy5sZW5ndGgsXG5cdFx0XHRjYWxsYmFja0V4cGVjdCA9ICFpbnZlcnQ7XG5cblx0XHQvLyBHbyB0aHJvdWdoIHRoZSBhcnJheSwgb25seSBzYXZpbmcgdGhlIGl0ZW1zXG5cdFx0Ly8gdGhhdCBwYXNzIHRoZSB2YWxpZGF0b3IgZnVuY3Rpb25cblx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdGNhbGxiYWNrSW52ZXJzZSA9ICFjYWxsYmFjayggZWxlbXNbIGkgXSwgaSApO1xuXHRcdFx0aWYgKCBjYWxsYmFja0ludmVyc2UgIT09IGNhbGxiYWNrRXhwZWN0ICkge1xuXHRcdFx0XHRtYXRjaGVzLnB1c2goIGVsZW1zWyBpIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbWF0Y2hlcztcblx0fSxcblxuXHQvLyBhcmcgaXMgZm9yIGludGVybmFsIHVzYWdlIG9ubHlcblx0bWFwOiBmdW5jdGlvbiggZWxlbXMsIGNhbGxiYWNrLCBhcmcgKSB7XG5cdFx0dmFyIGxlbmd0aCwgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdHJldCA9IFtdO1xuXG5cdFx0Ly8gR28gdGhyb3VnaCB0aGUgYXJyYXksIHRyYW5zbGF0aW5nIGVhY2ggb2YgdGhlIGl0ZW1zIHRvIHRoZWlyIG5ldyB2YWx1ZXNcblx0XHRpZiAoIGlzQXJyYXlMaWtlKCBlbGVtcyApICkge1xuXHRcdFx0bGVuZ3RoID0gZWxlbXMubGVuZ3RoO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhbHVlID0gY2FsbGJhY2soIGVsZW1zWyBpIF0sIGksIGFyZyApO1xuXG5cdFx0XHRcdGlmICggdmFsdWUgIT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXQucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gR28gdGhyb3VnaCBldmVyeSBrZXkgb24gdGhlIG9iamVjdCxcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yICggaSBpbiBlbGVtcyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmxhdHRlbiBhbnkgbmVzdGVkIGFycmF5c1xuXHRcdHJldHVybiBjb25jYXQuYXBwbHkoIFtdLCByZXQgKTtcblx0fSxcblxuXHQvLyBBIGdsb2JhbCBHVUlEIGNvdW50ZXIgZm9yIG9iamVjdHNcblx0Z3VpZDogMSxcblxuXHQvLyBCaW5kIGEgZnVuY3Rpb24gdG8gYSBjb250ZXh0LCBvcHRpb25hbGx5IHBhcnRpYWxseSBhcHBseWluZyBhbnlcblx0Ly8gYXJndW1lbnRzLlxuXHRwcm94eTogZnVuY3Rpb24oIGZuLCBjb250ZXh0ICkge1xuXHRcdHZhciB0bXAsIGFyZ3MsIHByb3h5O1xuXG5cdFx0aWYgKCB0eXBlb2YgY29udGV4dCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRtcCA9IGZuWyBjb250ZXh0IF07XG5cdFx0XHRjb250ZXh0ID0gZm47XG5cdFx0XHRmbiA9IHRtcDtcblx0XHR9XG5cblx0XHQvLyBRdWljayBjaGVjayB0byBkZXRlcm1pbmUgaWYgdGFyZ2V0IGlzIGNhbGxhYmxlLCBpbiB0aGUgc3BlY1xuXHRcdC8vIHRoaXMgdGhyb3dzIGEgVHlwZUVycm9yLCBidXQgd2Ugd2lsbCBqdXN0IHJldHVybiB1bmRlZmluZWQuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIGZuICkgKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIFNpbXVsYXRlZCBiaW5kXG5cdFx0YXJncyA9IHNsaWNlLmNhbGwoIGFyZ3VtZW50cywgMiApO1xuXHRcdHByb3h5ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gZm4uYXBwbHkoIGNvbnRleHQgfHwgdGhpcywgYXJncy5jb25jYXQoIHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApICkgKTtcblx0XHR9O1xuXG5cdFx0Ly8gU2V0IHRoZSBndWlkIG9mIHVuaXF1ZSBoYW5kbGVyIHRvIHRoZSBzYW1lIG9mIG9yaWdpbmFsIGhhbmRsZXIsIHNvIGl0IGNhbiBiZSByZW1vdmVkXG5cdFx0cHJveHkuZ3VpZCA9IGZuLmd1aWQgPSBmbi5ndWlkIHx8IGpRdWVyeS5ndWlkKys7XG5cblx0XHRyZXR1cm4gcHJveHk7XG5cdH0sXG5cblx0bm93OiBEYXRlLm5vdyxcblxuXHQvLyBqUXVlcnkuc3VwcG9ydCBpcyBub3QgdXNlZCBpbiBDb3JlIGJ1dCBvdGhlciBwcm9qZWN0cyBhdHRhY2ggdGhlaXJcblx0Ly8gcHJvcGVydGllcyB0byBpdCBzbyBpdCBuZWVkcyB0byBleGlzdC5cblx0c3VwcG9ydDogc3VwcG9ydFxufSApO1xuXG5pZiAoIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiApIHtcblx0alF1ZXJ5LmZuWyBTeW1ib2wuaXRlcmF0b3IgXSA9IGFyclsgU3ltYm9sLml0ZXJhdG9yIF07XG59XG5cbi8vIFBvcHVsYXRlIHRoZSBjbGFzczJ0eXBlIG1hcFxualF1ZXJ5LmVhY2goIFwiQm9vbGVhbiBOdW1iZXIgU3RyaW5nIEZ1bmN0aW9uIEFycmF5IERhdGUgUmVnRXhwIE9iamVjdCBFcnJvciBTeW1ib2xcIi5zcGxpdCggXCIgXCIgKSxcbmZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRjbGFzczJ0eXBlWyBcIltvYmplY3QgXCIgKyBuYW1lICsgXCJdXCIgXSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbn0gKTtcblxuZnVuY3Rpb24gaXNBcnJheUxpa2UoIG9iaiApIHtcblxuXHQvLyBTdXBwb3J0OiByZWFsIGlPUyA4LjIgb25seSAobm90IHJlcHJvZHVjaWJsZSBpbiBzaW11bGF0b3IpXG5cdC8vIGBpbmAgY2hlY2sgdXNlZCB0byBwcmV2ZW50IEpJVCBlcnJvciAoZ2gtMjE0NSlcblx0Ly8gaGFzT3duIGlzbid0IHVzZWQgaGVyZSBkdWUgdG8gZmFsc2UgbmVnYXRpdmVzXG5cdC8vIHJlZ2FyZGluZyBOb2RlbGlzdCBsZW5ndGggaW4gSUVcblx0dmFyIGxlbmd0aCA9ICEhb2JqICYmIFwibGVuZ3RoXCIgaW4gb2JqICYmIG9iai5sZW5ndGgsXG5cdFx0dHlwZSA9IGpRdWVyeS50eXBlKCBvYmogKTtcblxuXHRpZiAoIHR5cGUgPT09IFwiZnVuY3Rpb25cIiB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHJldHVybiB0eXBlID09PSBcImFycmF5XCIgfHwgbGVuZ3RoID09PSAwIHx8XG5cdFx0dHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIiAmJiBsZW5ndGggPiAwICYmICggbGVuZ3RoIC0gMSApIGluIG9iajtcbn1cbnZhciBTaXp6bGUgPVxuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2Mi4zLjNcbiAqIGh0dHBzOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcbiAqXG4gKiBEYXRlOiAyMDE2LTA4LTA4XG4gKi9cbihmdW5jdGlvbiggd2luZG93ICkge1xuXG52YXIgaSxcblx0c3VwcG9ydCxcblx0RXhwcixcblx0Z2V0VGV4dCxcblx0aXNYTUwsXG5cdHRva2VuaXplLFxuXHRjb21waWxlLFxuXHRzZWxlY3QsXG5cdG91dGVybW9zdENvbnRleHQsXG5cdHNvcnRJbnB1dCxcblx0aGFzRHVwbGljYXRlLFxuXG5cdC8vIExvY2FsIGRvY3VtZW50IHZhcnNcblx0c2V0RG9jdW1lbnQsXG5cdGRvY3VtZW50LFxuXHRkb2NFbGVtLFxuXHRkb2N1bWVudElzSFRNTCxcblx0cmJ1Z2d5UVNBLFxuXHRyYnVnZ3lNYXRjaGVzLFxuXHRtYXRjaGVzLFxuXHRjb250YWlucyxcblxuXHQvLyBJbnN0YW5jZS1zcGVjaWZpYyBkYXRhXG5cdGV4cGFuZG8gPSBcInNpenpsZVwiICsgMSAqIG5ldyBEYXRlKCksXG5cdHByZWZlcnJlZERvYyA9IHdpbmRvdy5kb2N1bWVudCxcblx0ZGlycnVucyA9IDAsXG5cdGRvbmUgPSAwLFxuXHRjbGFzc0NhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0dG9rZW5DYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdGNvbXBpbGVyQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHRzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHtcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gMDtcblx0fSxcblxuXHQvLyBJbnN0YW5jZSBtZXRob2RzXG5cdGhhc093biA9ICh7fSkuaGFzT3duUHJvcGVydHksXG5cdGFyciA9IFtdLFxuXHRwb3AgPSBhcnIucG9wLFxuXHRwdXNoX25hdGl2ZSA9IGFyci5wdXNoLFxuXHRwdXNoID0gYXJyLnB1c2gsXG5cdHNsaWNlID0gYXJyLnNsaWNlLFxuXHQvLyBVc2UgYSBzdHJpcHBlZC1kb3duIGluZGV4T2YgYXMgaXQncyBmYXN0ZXIgdGhhbiBuYXRpdmVcblx0Ly8gaHR0cHM6Ly9qc3BlcmYuY29tL3Rob3ItaW5kZXhvZi12cy1mb3IvNVxuXHRpbmRleE9mID0gZnVuY3Rpb24oIGxpc3QsIGVsZW0gKSB7XG5cdFx0dmFyIGkgPSAwLFxuXHRcdFx0bGVuID0gbGlzdC5sZW5ndGg7XG5cdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRpZiAoIGxpc3RbaV0gPT09IGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gLTE7XG5cdH0sXG5cblx0Ym9vbGVhbnMgPSBcImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkXCIsXG5cblx0Ly8gUmVndWxhciBleHByZXNzaW9uc1xuXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc2VsZWN0b3JzLyN3aGl0ZXNwYWNlXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvQ1NTMjEvc3luZGF0YS5odG1sI3ZhbHVlLWRlZi1pZGVudGlmaWVyXG5cdGlkZW50aWZpZXIgPSBcIig/OlxcXFxcXFxcLnxbXFxcXHctXXxbXlxcMC1cXFxceGEwXSkrXCIsXG5cblx0Ly8gQXR0cmlidXRlIHNlbGVjdG9yczogaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNhdHRyaWJ1dGUtc2VsZWN0b3JzXG5cdGF0dHJpYnV0ZXMgPSBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFwiICsgaWRlbnRpZmllciArIFwiKSg/OlwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gT3BlcmF0b3IgKGNhcHR1cmUgMilcblx0XHRcIiooWypeJHwhfl0/PSlcIiArIHdoaXRlc3BhY2UgK1xuXHRcdC8vIFwiQXR0cmlidXRlIHZhbHVlcyBtdXN0IGJlIENTUyBpZGVudGlmaWVycyBbY2FwdHVyZSA1XSBvciBzdHJpbmdzIFtjYXB0dXJlIDMgb3IgY2FwdHVyZSA0XVwiXG5cdFx0XCIqKD86JygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwifChcIiArIGlkZW50aWZpZXIgKyBcIikpfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKlxcXFxdXCIsXG5cblx0cHNldWRvcyA9IFwiOihcIiArIGlkZW50aWZpZXIgKyBcIikoPzpcXFxcKChcIiArXG5cdFx0Ly8gVG8gcmVkdWNlIHRoZSBudW1iZXIgb2Ygc2VsZWN0b3JzIG5lZWRpbmcgdG9rZW5pemUgaW4gdGhlIHByZUZpbHRlciwgcHJlZmVyIGFyZ3VtZW50czpcblx0XHQvLyAxLiBxdW90ZWQgKGNhcHR1cmUgMzsgY2FwdHVyZSA0IG9yIGNhcHR1cmUgNSlcblx0XHRcIignKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJ10pKiknfFxcXCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFxcXFwiXSkqKVxcXCIpfFwiICtcblx0XHQvLyAyLiBzaW1wbGUgKGNhcHR1cmUgNilcblx0XHRcIigoPzpcXFxcXFxcXC58W15cXFxcXFxcXCgpW1xcXFxdXXxcIiArIGF0dHJpYnV0ZXMgKyBcIikqKXxcIiArXG5cdFx0Ly8gMy4gYW55dGhpbmcgZWxzZSAoY2FwdHVyZSAyKVxuXHRcdFwiLipcIiArXG5cdFx0XCIpXFxcXCl8KVwiLFxuXG5cdC8vIExlYWRpbmcgYW5kIG5vbi1lc2NhcGVkIHRyYWlsaW5nIHdoaXRlc3BhY2UsIGNhcHR1cmluZyBzb21lIG5vbi13aGl0ZXNwYWNlIGNoYXJhY3RlcnMgcHJlY2VkaW5nIHRoZSBsYXR0ZXJcblx0cndoaXRlc3BhY2UgPSBuZXcgUmVnRXhwKCB3aGl0ZXNwYWNlICsgXCIrXCIsIFwiZ1wiICksXG5cdHJ0cmltID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIrfCgoPzpefFteXFxcXFxcXFxdKSg/OlxcXFxcXFxcLikqKVwiICsgd2hpdGVzcGFjZSArIFwiKyRcIiwgXCJnXCIgKSxcblxuXHRyY29tbWEgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiosXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblx0cmNvbWJpbmF0b3JzID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFs+K35dfFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgd2hpdGVzcGFjZSArIFwiKlwiICksXG5cblx0cmF0dHJpYnV0ZVF1b3RlcyA9IG5ldyBSZWdFeHAoIFwiPVwiICsgd2hpdGVzcGFjZSArIFwiKihbXlxcXFxdJ1xcXCJdKj8pXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXF1cIiwgXCJnXCIgKSxcblxuXHRycHNldWRvID0gbmV3IFJlZ0V4cCggcHNldWRvcyApLFxuXHRyaWRlbnRpZmllciA9IG5ldyBSZWdFeHAoIFwiXlwiICsgaWRlbnRpZmllciArIFwiJFwiICksXG5cblx0bWF0Y2hFeHByID0ge1xuXHRcdFwiSURcIjogbmV3IFJlZ0V4cCggXCJeIyhcIiArIGlkZW50aWZpZXIgKyBcIilcIiApLFxuXHRcdFwiQ0xBU1NcIjogbmV3IFJlZ0V4cCggXCJeXFxcXC4oXCIgKyBpZGVudGlmaWVyICsgXCIpXCIgKSxcblx0XHRcIlRBR1wiOiBuZXcgUmVnRXhwKCBcIl4oXCIgKyBpZGVudGlmaWVyICsgXCJ8WypdKVwiICksXG5cdFx0XCJBVFRSXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgYXR0cmlidXRlcyApLFxuXHRcdFwiUFNFVURPXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgcHNldWRvcyApLFxuXHRcdFwiQ0hJTERcIjogbmV3IFJlZ0V4cCggXCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXFxcKFwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooZXZlbnxvZGR8KChbKy1dfCkoXFxcXGQqKW58KVwiICsgd2hpdGVzcGFjZSArIFwiKig/OihbKy1dfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFx0XCIqKFxcXFxkKyl8KSlcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpXCIsIFwiaVwiICksXG5cdFx0XCJib29sXCI6IG5ldyBSZWdFeHAoIFwiXig/OlwiICsgYm9vbGVhbnMgKyBcIikkXCIsIFwiaVwiICksXG5cdFx0Ly8gRm9yIHVzZSBpbiBsaWJyYXJpZXMgaW1wbGVtZW50aW5nIC5pcygpXG5cdFx0Ly8gV2UgdXNlIHRoaXMgZm9yIFBPUyBtYXRjaGluZyBpbiBgc2VsZWN0YFxuXHRcdFwibmVlZHNDb250ZXh0XCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFxcXChcIiArXG5cdFx0XHR3aGl0ZXNwYWNlICsgXCIqKCg/Oi1cXFxcZCk/XFxcXGQqKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfCkoPz1bXi1dfCQpXCIsIFwiaVwiIClcblx0fSxcblxuXHRyaW5wdXRzID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxcblx0cmhlYWRlciA9IC9eaFxcZCQvaSxcblxuXHRybmF0aXZlID0gL15bXntdK1xce1xccypcXFtuYXRpdmUgXFx3LyxcblxuXHQvLyBFYXNpbHktcGFyc2VhYmxlL3JldHJpZXZhYmxlIElEIG9yIFRBRyBvciBDTEFTUyBzZWxlY3RvcnNcblx0cnF1aWNrRXhwciA9IC9eKD86IyhbXFx3LV0rKXwoXFx3Kyl8XFwuKFtcXHctXSspKSQvLFxuXG5cdHJzaWJsaW5nID0gL1srfl0vLFxuXG5cdC8vIENTUyBlc2NhcGVzXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL0NTUzIxL3N5bmRhdGEuaHRtbCNlc2NhcGVkLWNoYXJhY3RlcnNcblx0cnVuZXNjYXBlID0gbmV3IFJlZ0V4cCggXCJcXFxcXFxcXChbXFxcXGRhLWZdezEsNn1cIiArIHdoaXRlc3BhY2UgKyBcIj98KFwiICsgd2hpdGVzcGFjZSArIFwiKXwuKVwiLCBcImlnXCIgKSxcblx0ZnVuZXNjYXBlID0gZnVuY3Rpb24oIF8sIGVzY2FwZWQsIGVzY2FwZWRXaGl0ZXNwYWNlICkge1xuXHRcdHZhciBoaWdoID0gXCIweFwiICsgZXNjYXBlZCAtIDB4MTAwMDA7XG5cdFx0Ly8gTmFOIG1lYW5zIG5vbi1jb2RlcG9pbnRcblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94PDI0XG5cdFx0Ly8gV29ya2Fyb3VuZCBlcnJvbmVvdXMgbnVtZXJpYyBpbnRlcnByZXRhdGlvbiBvZiArXCIweFwiXG5cdFx0cmV0dXJuIGhpZ2ggIT09IGhpZ2ggfHwgZXNjYXBlZFdoaXRlc3BhY2UgP1xuXHRcdFx0ZXNjYXBlZCA6XG5cdFx0XHRoaWdoIDwgMCA/XG5cdFx0XHRcdC8vIEJNUCBjb2RlcG9pbnRcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCArIDB4MTAwMDAgKSA6XG5cdFx0XHRcdC8vIFN1cHBsZW1lbnRhbCBQbGFuZSBjb2RlcG9pbnQgKHN1cnJvZ2F0ZSBwYWlyKVxuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoID4+IDEwIHwgMHhEODAwLCBoaWdoICYgMHgzRkYgfCAweERDMDAgKTtcblx0fSxcblxuXHQvLyBDU1Mgc3RyaW5nL2lkZW50aWZpZXIgc2VyaWFsaXphdGlvblxuXHQvLyBodHRwczovL2RyYWZ0cy5jc3N3Zy5vcmcvY3Nzb20vI2NvbW1vbi1zZXJpYWxpemluZy1pZGlvbXNcblx0cmNzc2VzY2FwZSA9IC8oW1xcMC1cXHgxZlxceDdmXXxeLT9cXGQpfF4tJHxbXlxcMC1cXHgxZlxceDdmLVxcdUZGRkZcXHctXS9nLFxuXHRmY3NzZXNjYXBlID0gZnVuY3Rpb24oIGNoLCBhc0NvZGVQb2ludCApIHtcblx0XHRpZiAoIGFzQ29kZVBvaW50ICkge1xuXG5cdFx0XHQvLyBVKzAwMDAgTlVMTCBiZWNvbWVzIFUrRkZGRCBSRVBMQUNFTUVOVCBDSEFSQUNURVJcblx0XHRcdGlmICggY2ggPT09IFwiXFwwXCIgKSB7XG5cdFx0XHRcdHJldHVybiBcIlxcdUZGRkRcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udHJvbCBjaGFyYWN0ZXJzIGFuZCAoZGVwZW5kZW50IHVwb24gcG9zaXRpb24pIG51bWJlcnMgZ2V0IGVzY2FwZWQgYXMgY29kZSBwb2ludHNcblx0XHRcdHJldHVybiBjaC5zbGljZSggMCwgLTEgKSArIFwiXFxcXFwiICsgY2guY2hhckNvZGVBdCggY2gubGVuZ3RoIC0gMSApLnRvU3RyaW5nKCAxNiApICsgXCIgXCI7XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXIgcG90ZW50aWFsbHktc3BlY2lhbCBBU0NJSSBjaGFyYWN0ZXJzIGdldCBiYWNrc2xhc2gtZXNjYXBlZFxuXHRcdHJldHVybiBcIlxcXFxcIiArIGNoO1xuXHR9LFxuXG5cdC8vIFVzZWQgZm9yIGlmcmFtZXNcblx0Ly8gU2VlIHNldERvY3VtZW50KClcblx0Ly8gUmVtb3ZpbmcgdGhlIGZ1bmN0aW9uIHdyYXBwZXIgY2F1c2VzIGEgXCJQZXJtaXNzaW9uIERlbmllZFwiXG5cdC8vIGVycm9yIGluIElFXG5cdHVubG9hZEhhbmRsZXIgPSBmdW5jdGlvbigpIHtcblx0XHRzZXREb2N1bWVudCgpO1xuXHR9LFxuXG5cdGRpc2FibGVkQW5jZXN0b3IgPSBhZGRDb21iaW5hdG9yKFxuXHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IHRydWUgJiYgKFwiZm9ybVwiIGluIGVsZW0gfHwgXCJsYWJlbFwiIGluIGVsZW0pO1xuXHRcdH0sXG5cdFx0eyBkaXI6IFwicGFyZW50Tm9kZVwiLCBuZXh0OiBcImxlZ2VuZFwiIH1cblx0KTtcblxuLy8gT3B0aW1pemUgZm9yIHB1c2guYXBwbHkoIF8sIE5vZGVMaXN0IClcbnRyeSB7XG5cdHB1c2guYXBwbHkoXG5cdFx0KGFyciA9IHNsaWNlLmNhbGwoIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzICkpLFxuXHRcdHByZWZlcnJlZERvYy5jaGlsZE5vZGVzXG5cdCk7XG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8NC4wXG5cdC8vIERldGVjdCBzaWxlbnRseSBmYWlsaW5nIHB1c2guYXBwbHlcblx0YXJyWyBwcmVmZXJyZWREb2MuY2hpbGROb2Rlcy5sZW5ndGggXS5ub2RlVHlwZTtcbn0gY2F0Y2ggKCBlICkge1xuXHRwdXNoID0geyBhcHBseTogYXJyLmxlbmd0aCA/XG5cblx0XHQvLyBMZXZlcmFnZSBzbGljZSBpZiBwb3NzaWJsZVxuXHRcdGZ1bmN0aW9uKCB0YXJnZXQsIGVscyApIHtcblx0XHRcdHB1c2hfbmF0aXZlLmFwcGx5KCB0YXJnZXQsIHNsaWNlLmNhbGwoZWxzKSApO1xuXHRcdH0gOlxuXG5cdFx0Ly8gU3VwcG9ydDogSUU8OVxuXHRcdC8vIE90aGVyd2lzZSBhcHBlbmQgZGlyZWN0bHlcblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHR2YXIgaiA9IHRhcmdldC5sZW5ndGgsXG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0Ly8gQ2FuJ3QgdHJ1c3QgTm9kZUxpc3QubGVuZ3RoXG5cdFx0XHR3aGlsZSAoICh0YXJnZXRbaisrXSA9IGVsc1tpKytdKSApIHt9XG5cdFx0XHR0YXJnZXQubGVuZ3RoID0gaiAtIDE7XG5cdFx0fVxuXHR9O1xufVxuXG5mdW5jdGlvbiBTaXp6bGUoIHNlbGVjdG9yLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICkge1xuXHR2YXIgbSwgaSwgZWxlbSwgbmlkLCBtYXRjaCwgZ3JvdXBzLCBuZXdTZWxlY3Rvcixcblx0XHRuZXdDb250ZXh0ID0gY29udGV4dCAmJiBjb250ZXh0Lm93bmVyRG9jdW1lbnQsXG5cblx0XHQvLyBub2RlVHlwZSBkZWZhdWx0cyB0byA5LCBzaW5jZSBjb250ZXh0IGRlZmF1bHRzIHRvIGRvY3VtZW50XG5cdFx0bm9kZVR5cGUgPSBjb250ZXh0ID8gY29udGV4dC5ub2RlVHlwZSA6IDk7XG5cblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0Ly8gUmV0dXJuIGVhcmx5IGZyb20gY2FsbHMgd2l0aCBpbnZhbGlkIHNlbGVjdG9yIG9yIGNvbnRleHRcblx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgfHwgIXNlbGVjdG9yIHx8XG5cdFx0bm9kZVR5cGUgIT09IDEgJiYgbm9kZVR5cGUgIT09IDkgJiYgbm9kZVR5cGUgIT09IDExICkge1xuXG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvLyBUcnkgdG8gc2hvcnRjdXQgZmluZCBvcGVyYXRpb25zIChhcyBvcHBvc2VkIHRvIGZpbHRlcnMpIGluIEhUTUwgZG9jdW1lbnRzXG5cdGlmICggIXNlZWQgKSB7XG5cblx0XHRpZiAoICggY29udGV4dCA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogcHJlZmVycmVkRG9jICkgIT09IGRvY3VtZW50ICkge1xuXHRcdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0XHR9XG5cdFx0Y29udGV4dCA9IGNvbnRleHQgfHwgZG9jdW1lbnQ7XG5cblx0XHRpZiAoIGRvY3VtZW50SXNIVE1MICkge1xuXG5cdFx0XHQvLyBJZiB0aGUgc2VsZWN0b3IgaXMgc3VmZmljaWVudGx5IHNpbXBsZSwgdHJ5IHVzaW5nIGEgXCJnZXQqQnkqXCIgRE9NIG1ldGhvZFxuXHRcdFx0Ly8gKGV4Y2VwdGluZyBEb2N1bWVudEZyYWdtZW50IGNvbnRleHQsIHdoZXJlIHRoZSBtZXRob2RzIGRvbid0IGV4aXN0KVxuXHRcdFx0aWYgKCBub2RlVHlwZSAhPT0gMTEgJiYgKG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHQvLyBJRCBzZWxlY3RvclxuXHRcdFx0XHRpZiAoIChtID0gbWF0Y2hbMV0pICkge1xuXG5cdFx0XHRcdFx0Ly8gRG9jdW1lbnQgY29udGV4dFxuXHRcdFx0XHRcdGlmICggbm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApKSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0XHQvLyBUT0RPOiBpZGVudGlmeSB2ZXJzaW9uc1xuXHRcdFx0XHRcdFx0XHQvLyBnZXRFbGVtZW50QnlJZCBjYW4gbWF0Y2ggZWxlbWVudHMgYnkgbmFtZSBpbnN0ZWFkIG9mIElEXG5cdFx0XHRcdFx0XHRcdGlmICggZWxlbS5pZCA9PT0gbSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBFbGVtZW50IGNvbnRleHRcblx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0Ly8gVE9ETzogaWRlbnRpZnkgdmVyc2lvbnNcblx0XHRcdFx0XHRcdC8vIGdldEVsZW1lbnRCeUlkIGNhbiBtYXRjaCBlbGVtZW50cyBieSBuYW1lIGluc3RlYWQgb2YgSURcblx0XHRcdFx0XHRcdGlmICggbmV3Q29udGV4dCAmJiAoZWxlbSA9IG5ld0NvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIG0gKSkgJiZcblx0XHRcdFx0XHRcdFx0Y29udGFpbnMoIGNvbnRleHQsIGVsZW0gKSAmJlxuXHRcdFx0XHRcdFx0XHRlbGVtLmlkID09PSBtICkge1xuXG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHlwZSBzZWxlY3RvclxuXHRcdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFsyXSApIHtcblx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCBzZWxlY3RvciApICk7XG5cdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdFx0Ly8gQ2xhc3Mgc2VsZWN0b3Jcblx0XHRcdFx0fSBlbHNlIGlmICggKG0gPSBtYXRjaFszXSkgJiYgc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmXG5cdFx0XHRcdFx0Y29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICkge1xuXG5cdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCBtICkgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUYWtlIGFkdmFudGFnZSBvZiBxdWVyeVNlbGVjdG9yQWxsXG5cdFx0XHRpZiAoIHN1cHBvcnQucXNhICYmXG5cdFx0XHRcdCFjb21waWxlckNhY2hlWyBzZWxlY3RvciArIFwiIFwiIF0gJiZcblx0XHRcdFx0KCFyYnVnZ3lRU0EgfHwgIXJidWdneVFTQS50ZXN0KCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHRpZiAoIG5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0XHRcdG5ld1NlbGVjdG9yID0gc2VsZWN0b3I7XG5cblx0XHRcdFx0Ly8gcVNBIGxvb2tzIG91dHNpZGUgRWxlbWVudCBjb250ZXh0LCB3aGljaCBpcyBub3Qgd2hhdCB3ZSB3YW50XG5cdFx0XHRcdC8vIFRoYW5rcyB0byBBbmRyZXcgRHVwb250IGZvciB0aGlzIHdvcmthcm91bmQgdGVjaG5pcXVlXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OFxuXHRcdFx0XHQvLyBFeGNsdWRlIG9iamVjdCBlbGVtZW50c1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHRcdFx0XHQvLyBDYXB0dXJlIHRoZSBjb250ZXh0IElELCBzZXR0aW5nIGl0IGZpcnN0IGlmIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdGlmICggKG5pZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKCBcImlkXCIgKSkgKSB7XG5cdFx0XHRcdFx0XHRuaWQgPSBuaWQucmVwbGFjZSggcmNzc2VzY2FwZSwgZmNzc2VzY2FwZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb250ZXh0LnNldEF0dHJpYnV0ZSggXCJpZFwiLCAobmlkID0gZXhwYW5kbykgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBQcmVmaXggZXZlcnkgc2VsZWN0b3IgaW4gdGhlIGxpc3Rcblx0XHRcdFx0XHRncm91cHMgPSB0b2tlbml6ZSggc2VsZWN0b3IgKTtcblx0XHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGdyb3Vwc1tpXSA9IFwiI1wiICsgbmlkICsgXCIgXCIgKyB0b1NlbGVjdG9yKCBncm91cHNbaV0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bmV3U2VsZWN0b3IgPSBncm91cHMuam9pbiggXCIsXCIgKTtcblxuXHRcdFx0XHRcdC8vIEV4cGFuZCBjb250ZXh0IGZvciBzaWJsaW5nIHNlbGVjdG9yc1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSByc2libGluZy50ZXN0KCBzZWxlY3RvciApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fFxuXHRcdFx0XHRcdFx0Y29udGV4dDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggbmV3U2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRcdG5ld0NvbnRleHQucXVlcnlTZWxlY3RvckFsbCggbmV3U2VsZWN0b3IgKVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKCBxc2FFcnJvciApIHtcblx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0aWYgKCBuaWQgPT09IGV4cGFuZG8gKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRleHQucmVtb3ZlQXR0cmlidXRlKCBcImlkXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBBbGwgb3RoZXJzXG5cdHJldHVybiBzZWxlY3QoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBrZXktdmFsdWUgY2FjaGVzIG9mIGxpbWl0ZWQgc2l6ZVxuICogQHJldHVybnMge2Z1bmN0aW9uKHN0cmluZywgb2JqZWN0KX0gUmV0dXJucyB0aGUgT2JqZWN0IGRhdGEgYWZ0ZXIgc3RvcmluZyBpdCBvbiBpdHNlbGYgd2l0aFxuICpcdHByb3BlcnR5IG5hbWUgdGhlIChzcGFjZS1zdWZmaXhlZCkgc3RyaW5nIGFuZCAoaWYgdGhlIGNhY2hlIGlzIGxhcmdlciB0aGFuIEV4cHIuY2FjaGVMZW5ndGgpXG4gKlx0ZGVsZXRpbmcgdGhlIG9sZGVzdCBlbnRyeVxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWNoZSgpIHtcblx0dmFyIGtleXMgPSBbXTtcblxuXHRmdW5jdGlvbiBjYWNoZSgga2V5LCB2YWx1ZSApIHtcblx0XHQvLyBVc2UgKGtleSArIFwiIFwiKSB0byBhdm9pZCBjb2xsaXNpb24gd2l0aCBuYXRpdmUgcHJvdG90eXBlIHByb3BlcnRpZXMgKHNlZSBJc3N1ZSAjMTU3KVxuXHRcdGlmICgga2V5cy5wdXNoKCBrZXkgKyBcIiBcIiApID4gRXhwci5jYWNoZUxlbmd0aCApIHtcblx0XHRcdC8vIE9ubHkga2VlcCB0aGUgbW9zdCByZWNlbnQgZW50cmllc1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBlbGVtZW50IGFuZCByZXR1cm5zIGEgYm9vbGVhbiByZXN1bHRcbiAqL1xuZnVuY3Rpb24gYXNzZXJ0KCBmbiApIHtcblx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImZpZWxkc2V0XCIpO1xuXG5cdHRyeSB7XG5cdFx0cmV0dXJuICEhZm4oIGVsICk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0gZmluYWxseSB7XG5cdFx0Ly8gUmVtb3ZlIGZyb20gaXRzIHBhcmVudCBieSBkZWZhdWx0XG5cdFx0aWYgKCBlbC5wYXJlbnROb2RlICkge1xuXHRcdFx0ZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggZWwgKTtcblx0XHR9XG5cdFx0Ly8gcmVsZWFzZSBtZW1vcnkgaW4gSUVcblx0XHRlbCA9IG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSBzYW1lIGhhbmRsZXIgZm9yIGFsbCBvZiB0aGUgc3BlY2lmaWVkIGF0dHJzXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cnMgUGlwZS1zZXBhcmF0ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIFRoZSBtZXRob2QgdGhhdCB3aWxsIGJlIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gYWRkSGFuZGxlKCBhdHRycywgaGFuZGxlciApIHtcblx0dmFyIGFyciA9IGF0dHJzLnNwbGl0KFwifFwiKSxcblx0XHRpID0gYXJyLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRFeHByLmF0dHJIYW5kbGVbIGFycltpXSBdID0gaGFuZGxlcjtcblx0fVxufVxuXG4vKipcbiAqIENoZWNrcyBkb2N1bWVudCBvcmRlciBvZiB0d28gc2libGluZ3NcbiAqIEBwYXJhbSB7RWxlbWVudH0gYVxuICogQHBhcmFtIHtFbGVtZW50fSBiXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIGxlc3MgdGhhbiAwIGlmIGEgcHJlY2VkZXMgYiwgZ3JlYXRlciB0aGFuIDAgaWYgYSBmb2xsb3dzIGJcbiAqL1xuZnVuY3Rpb24gc2libGluZ0NoZWNrKCBhLCBiICkge1xuXHR2YXIgY3VyID0gYiAmJiBhLFxuXHRcdGRpZmYgPSBjdXIgJiYgYS5ub2RlVHlwZSA9PT0gMSAmJiBiLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRhLnNvdXJjZUluZGV4IC0gYi5zb3VyY2VJbmRleDtcblxuXHQvLyBVc2UgSUUgc291cmNlSW5kZXggaWYgYXZhaWxhYmxlIG9uIGJvdGggbm9kZXNcblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0Ly8gQ2hlY2sgaWYgYiBmb2xsb3dzIGFcblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIDplbmFibGVkLzpkaXNhYmxlZFxuICogQHBhcmFtIHtCb29sZWFufSBkaXNhYmxlZCB0cnVlIGZvciA6ZGlzYWJsZWQ7IGZhbHNlIGZvciA6ZW5hYmxlZFxuICovXG5mdW5jdGlvbiBjcmVhdGVEaXNhYmxlZFBzZXVkbyggZGlzYWJsZWQgKSB7XG5cblx0Ly8gS25vd24gOmRpc2FibGVkIGZhbHNlIHBvc2l0aXZlczogZmllbGRzZXRbZGlzYWJsZWRdID4gbGVnZW5kOm50aC1vZi10eXBlKG4rMikgOmNhbi1kaXNhYmxlXG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE9ubHkgY2VydGFpbiBlbGVtZW50cyBjYW4gbWF0Y2ggOmVuYWJsZWQgb3IgOmRpc2FibGVkXG5cdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc2NyaXB0aW5nLmh0bWwjc2VsZWN0b3ItZW5hYmxlZFxuXHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3NjcmlwdGluZy5odG1sI3NlbGVjdG9yLWRpc2FibGVkXG5cdFx0aWYgKCBcImZvcm1cIiBpbiBlbGVtICkge1xuXG5cdFx0XHQvLyBDaGVjayBmb3IgaW5oZXJpdGVkIGRpc2FibGVkbmVzcyBvbiByZWxldmFudCBub24tZGlzYWJsZWQgZWxlbWVudHM6XG5cdFx0XHQvLyAqIGxpc3RlZCBmb3JtLWFzc29jaWF0ZWQgZWxlbWVudHMgaW4gYSBkaXNhYmxlZCBmaWVsZHNldFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NhdGVnb3J5LWxpc3RlZFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NvbmNlcHQtZmUtZGlzYWJsZWRcblx0XHRcdC8vICogb3B0aW9uIGVsZW1lbnRzIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdC8vICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvZm9ybXMuaHRtbCNjb25jZXB0LW9wdGlvbi1kaXNhYmxlZFxuXHRcdFx0Ly8gQWxsIHN1Y2ggZWxlbWVudHMgaGF2ZSBhIFwiZm9ybVwiIHByb3BlcnR5LlxuXHRcdFx0aWYgKCBlbGVtLnBhcmVudE5vZGUgJiYgZWxlbS5kaXNhYmxlZCA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdFx0Ly8gT3B0aW9uIGVsZW1lbnRzIGRlZmVyIHRvIGEgcGFyZW50IG9wdGdyb3VwIGlmIHByZXNlbnRcblx0XHRcdFx0aWYgKCBcImxhYmVsXCIgaW4gZWxlbSApIHtcblx0XHRcdFx0XHRpZiAoIFwibGFiZWxcIiBpbiBlbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5wYXJlbnROb2RlLmRpc2FibGVkID09PSBkaXNhYmxlZDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDYgLSAxMVxuXHRcdFx0XHQvLyBVc2UgdGhlIGlzRGlzYWJsZWQgc2hvcnRjdXQgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGRpc2FibGVkIGZpZWxkc2V0IGFuY2VzdG9yc1xuXHRcdFx0XHRyZXR1cm4gZWxlbS5pc0Rpc2FibGVkID09PSBkaXNhYmxlZCB8fFxuXG5cdFx0XHRcdFx0Ly8gV2hlcmUgdGhlcmUgaXMgbm8gaXNEaXNhYmxlZCwgY2hlY2sgbWFudWFsbHlcblx0XHRcdFx0XHQvKiBqc2hpbnQgLVcwMTggKi9cblx0XHRcdFx0XHRlbGVtLmlzRGlzYWJsZWQgIT09ICFkaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0ZGlzYWJsZWRBbmNlc3RvciggZWxlbSApID09PSBkaXNhYmxlZDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXG5cdFx0Ly8gVHJ5IHRvIHdpbm5vdyBvdXQgZWxlbWVudHMgdGhhdCBjYW4ndCBiZSBkaXNhYmxlZCBiZWZvcmUgdHJ1c3RpbmcgdGhlIGRpc2FibGVkIHByb3BlcnR5LlxuXHRcdC8vIFNvbWUgdmljdGltcyBnZXQgY2F1Z2h0IGluIG91ciBuZXQgKGxhYmVsLCBsZWdlbmQsIG1lbnUsIHRyYWNrKSwgYnV0IGl0IHNob3VsZG4ndFxuXHRcdC8vIGV2ZW4gZXhpc3Qgb24gdGhlbSwgbGV0IGFsb25lIGhhdmUgYSBib29sZWFuIHZhbHVlLlxuXHRcdH0gZWxzZSBpZiAoIFwibGFiZWxcIiBpbiBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdH1cblxuXHRcdC8vIFJlbWFpbmluZyBlbGVtZW50cyBhcmUgbmVpdGhlciA6ZW5hYmxlZCBub3IgOmRpc2FibGVkXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgcG9zaXRpb25hbHNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oIGZuICkge1xuXHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBhcmd1bWVudCApIHtcblx0XHRhcmd1bWVudCA9ICthcmd1bWVudDtcblx0XHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0dmFyIGosXG5cdFx0XHRcdG1hdGNoSW5kZXhlcyA9IGZuKCBbXSwgc2VlZC5sZW5ndGgsIGFyZ3VtZW50ICksXG5cdFx0XHRcdGkgPSBtYXRjaEluZGV4ZXMubGVuZ3RoO1xuXG5cdFx0XHQvLyBNYXRjaCBlbGVtZW50cyBmb3VuZCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4ZXNcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoIHNlZWRbIChqID0gbWF0Y2hJbmRleGVzW2ldKSBdICkge1xuXHRcdFx0XHRcdHNlZWRbal0gPSAhKG1hdGNoZXNbal0gPSBzZWVkW2pdKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBub2RlIGZvciB2YWxpZGl0eSBhcyBhIFNpenpsZSBjb250ZXh0XG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0PX0gY29udGV4dFxuICogQHJldHVybnMge0VsZW1lbnR8T2JqZWN0fEJvb2xlYW59IFRoZSBpbnB1dCBub2RlIGlmIGFjY2VwdGFibGUsIG90aGVyd2lzZSBhIGZhbHN5IHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHRlc3RDb250ZXh0KCBjb250ZXh0ICkge1xuXHRyZXR1cm4gY29udGV4dCAmJiB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjb250ZXh0O1xufVxuXG4vLyBFeHBvc2Ugc3VwcG9ydCB2YXJzIGZvciBjb252ZW5pZW5jZVxuc3VwcG9ydCA9IFNpenpsZS5zdXBwb3J0ID0ge307XG5cbi8qKlxuICogRGV0ZWN0cyBYTUwgbm9kZXNcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IGVsZW0gQW4gZWxlbWVudCBvciBhIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZmYgZWxlbSBpcyBhIG5vbi1IVE1MIFhNTCBub2RlXG4gKi9cbmlzWE1MID0gU2l6emxlLmlzWE1MID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdC8vIGRvY3VtZW50RWxlbWVudCBpcyB2ZXJpZmllZCBmb3IgY2FzZXMgd2hlcmUgaXQgZG9lc24ndCB5ZXQgZXhpc3Rcblx0Ly8gKHN1Y2ggYXMgbG9hZGluZyBpZnJhbWVzIGluIElFIC0gIzQ4MzMpXG5cdHZhciBkb2N1bWVudEVsZW1lbnQgPSBlbGVtICYmIChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSkuZG9jdW1lbnRFbGVtZW50O1xuXHRyZXR1cm4gZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lICE9PSBcIkhUTUxcIiA6IGZhbHNlO1xufTtcblxuLyoqXG4gKiBTZXRzIGRvY3VtZW50LXJlbGF0ZWQgdmFyaWFibGVzIG9uY2UgYmFzZWQgb24gdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IFtkb2NdIEFuIGVsZW1lbnQgb3IgZG9jdW1lbnQgb2JqZWN0IHRvIHVzZSB0byBzZXQgdGhlIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKi9cbnNldERvY3VtZW50ID0gU2l6emxlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oIG5vZGUgKSB7XG5cdHZhciBoYXNDb21wYXJlLCBzdWJXaW5kb3csXG5cdFx0ZG9jID0gbm9kZSA/IG5vZGUub3duZXJEb2N1bWVudCB8fCBub2RlIDogcHJlZmVycmVkRG9jO1xuXG5cdC8vIFJldHVybiBlYXJseSBpZiBkb2MgaXMgaW52YWxpZCBvciBhbHJlYWR5IHNlbGVjdGVkXG5cdGlmICggZG9jID09PSBkb2N1bWVudCB8fCBkb2Mubm9kZVR5cGUgIT09IDkgfHwgIWRvYy5kb2N1bWVudEVsZW1lbnQgKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50O1xuXHR9XG5cblx0Ly8gVXBkYXRlIGdsb2JhbCB2YXJpYWJsZXNcblx0ZG9jdW1lbnQgPSBkb2M7XG5cdGRvY0VsZW0gPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdGRvY3VtZW50SXNIVE1MID0gIWlzWE1MKCBkb2N1bWVudCApO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDktMTEsIEVkZ2Vcblx0Ly8gQWNjZXNzaW5nIGlmcmFtZSBkb2N1bWVudHMgYWZ0ZXIgdW5sb2FkIHRocm93cyBcInBlcm1pc3Npb24gZGVuaWVkXCIgZXJyb3JzIChqUXVlcnkgIzEzOTM2KVxuXHRpZiAoIHByZWZlcnJlZERvYyAhPT0gZG9jdW1lbnQgJiZcblx0XHQoc3ViV2luZG93ID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcpICYmIHN1YldpbmRvdy50b3AgIT09IHN1YldpbmRvdyApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDExLCBFZGdlXG5cdFx0aWYgKCBzdWJXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lciApIHtcblx0XHRcdHN1YldpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcInVubG9hZFwiLCB1bmxvYWRIYW5kbGVyLCBmYWxzZSApO1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgOSAtIDEwIG9ubHlcblx0XHR9IGVsc2UgaWYgKCBzdWJXaW5kb3cuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRzdWJXaW5kb3cuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgdW5sb2FkSGFuZGxlciApO1xuXHRcdH1cblx0fVxuXG5cdC8qIEF0dHJpYnV0ZXNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIFN1cHBvcnQ6IElFPDhcblx0Ly8gVmVyaWZ5IHRoYXQgZ2V0QXR0cmlidXRlIHJlYWxseSByZXR1cm5zIGF0dHJpYnV0ZXMgYW5kIG5vdCBwcm9wZXJ0aWVzXG5cdC8vIChleGNlcHRpbmcgSUU4IGJvb2xlYW5zKVxuXHRzdXBwb3J0LmF0dHJpYnV0ZXMgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmNsYXNzTmFtZSA9IFwiaVwiO1xuXHRcdHJldHVybiAhZWwuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpO1xuXHR9KTtcblxuXHQvKiBnZXRFbGVtZW50KHMpQnkqXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBDaGVjayBpZiBnZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikgcmV0dXJucyBvbmx5IGVsZW1lbnRzXG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVDb21tZW50KFwiXCIpICk7XG5cdFx0cmV0dXJuICFlbC5nZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBTdXBwb3J0OiBJRTw5XG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApO1xuXG5cdC8vIFN1cHBvcnQ6IElFPDEwXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRCeUlkIHJldHVybnMgZWxlbWVudHMgYnkgbmFtZVxuXHQvLyBUaGUgYnJva2VuIGdldEVsZW1lbnRCeUlkIG1ldGhvZHMgZG9uJ3QgcGljayB1cCBwcm9ncmFtbWF0aWNhbGx5LXNldCBuYW1lcyxcblx0Ly8gc28gdXNlIGEgcm91bmRhYm91dCBnZXRFbGVtZW50c0J5TmFtZSB0ZXN0XG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pZCA9IGV4cGFuZG87XG5cdFx0cmV0dXJuICFkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoIGV4cGFuZG8gKS5sZW5ndGg7XG5cdH0pO1xuXG5cdC8vIElEIGZpbHRlciBhbmQgZmluZFxuXHRpZiAoIHN1cHBvcnQuZ2V0QnlJZCApIHtcblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmdldEF0dHJpYnV0ZShcImlkXCIpID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cdFx0XHRcdHJldHVybiBlbGVtID8gWyBlbGVtIF0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSAgZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBub2RlID0gdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlTm9kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuXHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRyZXR1cm4gbm9kZSAmJiBub2RlLnZhbHVlID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA2IC0gNyBvbmx5XG5cdFx0Ly8gZ2V0RWxlbWVudEJ5SWQgaXMgbm90IHJlbGlhYmxlIGFzIGEgZmluZCBzaG9ydGN1dFxuXHRcdEV4cHIuZmluZFtcIklEXCJdID0gZnVuY3Rpb24oIGlkLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50QnlJZCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdFx0dmFyIG5vZGUsIGksIGVsZW1zLFxuXHRcdFx0XHRcdGVsZW0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBpZCApO1xuXG5cdFx0XHRcdGlmICggZWxlbSApIHtcblxuXHRcdFx0XHRcdC8vIFZlcmlmeSB0aGUgaWQgYXR0cmlidXRlXG5cdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdGlmICggbm9kZSAmJiBub2RlLnZhbHVlID09PSBpZCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBbIGVsZW0gXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBGYWxsIGJhY2sgb24gZ2V0RWxlbWVudHNCeU5hbWVcblx0XHRcdFx0XHRlbGVtcyA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeU5hbWUoIGlkICk7XG5cdFx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1zW2krK10pICkge1xuXHRcdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdFx0aWYgKCBub2RlICYmIG5vZGUudmFsdWUgPT09IGlkICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gWyBlbGVtIF07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvLyBUYWdcblx0RXhwci5maW5kW1wiVEFHXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/XG5cdFx0ZnVuY3Rpb24oIHRhZywgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRG9jdW1lbnRGcmFnbWVudCBub2RlcyBkb24ndCBoYXZlIGdFQlROXG5cdFx0XHR9IGVsc2UgaWYgKCBzdXBwb3J0LnFzYSApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCggdGFnICk7XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdHRtcCA9IFtdLFxuXHRcdFx0XHRpID0gMCxcblx0XHRcdFx0Ly8gQnkgaGFwcHkgY29pbmNpZGVuY2UsIGEgKGJyb2tlbikgZ0VCVE4gYXBwZWFycyBvbiBEb2N1bWVudEZyYWdtZW50IG5vZGVzIHRvb1xuXHRcdFx0XHRyZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnICk7XG5cblx0XHRcdC8vIEZpbHRlciBvdXQgcG9zc2libGUgY29tbWVudHNcblx0XHRcdGlmICggdGFnID09PSBcIipcIiApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRcdFx0dG1wLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdG1wO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0fTtcblxuXHQvLyBDbGFzc1xuXHRFeHByLmZpbmRbXCJDTEFTU1wiXSA9IHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBmdW5jdGlvbiggY2xhc3NOYW1lLCBjb250ZXh0ICkge1xuXHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIGNsYXNzTmFtZSApO1xuXHRcdH1cblx0fTtcblxuXHQvKiBRU0EvbWF0Y2hlc1NlbGVjdG9yXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBRU0EgYW5kIG1hdGNoZXNTZWxlY3RvciBzdXBwb3J0XG5cblx0Ly8gbWF0Y2hlc1NlbGVjdG9yKDphY3RpdmUpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChJRTkvT3BlcmEgMTEuNSlcblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdC8vIHFTYSg6Zm9jdXMpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChDaHJvbWUgMjEpXG5cdC8vIFdlIGFsbG93IHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBJRTgvOSB0aGF0IHRocm93cyBhbiBlcnJvclxuXHQvLyB3aGVuZXZlciBgZG9jdW1lbnQuYWN0aXZlRWxlbWVudGAgaXMgYWNjZXNzZWQgb24gYW4gaWZyYW1lXG5cdC8vIFNvLCB3ZSBhbGxvdyA6Zm9jdXMgdG8gcGFzcyB0aHJvdWdoIFFTQSBhbGwgdGhlIHRpbWUgdG8gYXZvaWQgdGhlIElFIGVycm9yXG5cdC8vIFNlZSBodHRwczovL2J1Z3MuanF1ZXJ5LmNvbS90aWNrZXQvMTMzNzhcblx0cmJ1Z2d5UVNBID0gW107XG5cblx0aWYgKCAoc3VwcG9ydC5xc2EgPSBybmF0aXZlLnRlc3QoIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwgKSkgKSB7XG5cdFx0Ly8gQnVpbGQgUVNBIHJlZ2V4XG5cdFx0Ly8gUmVnZXggc3RyYXRlZ3kgYWRvcHRlZCBmcm9tIERpZWdvIFBlcmluaVxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBTZWxlY3QgaXMgc2V0IHRvIGVtcHR5IHN0cmluZyBvbiBwdXJwb3NlXG5cdFx0XHQvLyBUaGlzIGlzIHRvIHRlc3QgSUUncyB0cmVhdG1lbnQgb2Ygbm90IGV4cGxpY2l0bHlcblx0XHRcdC8vIHNldHRpbmcgYSBib29sZWFuIGNvbnRlbnQgYXR0cmlidXRlLFxuXHRcdFx0Ly8gc2luY2UgaXRzIHByZXNlbmNlIHNob3VsZCBiZSBlbm91Z2hcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjM1OVxuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pbm5lckhUTUwgPSBcIjxhIGlkPSdcIiArIGV4cGFuZG8gKyBcIic+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGlkPSdcIiArIGV4cGFuZG8gKyBcIi1cXHJcXFxcJyBtc2FsbG93Y2FwdHVyZT0nJz5cIiArXG5cdFx0XHRcdFwiPG9wdGlvbiBzZWxlY3RlZD0nJz48L29wdGlvbj48L3NlbGVjdD5cIjtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4LCBPcGVyYSAxMS0xMi4xNlxuXHRcdFx0Ly8gTm90aGluZyBzaG91bGQgYmUgc2VsZWN0ZWQgd2hlbiBlbXB0eSBzdHJpbmdzIGZvbGxvdyBePSBvciAkPSBvciAqPVxuXHRcdFx0Ly8gVGhlIHRlc3QgYXR0cmlidXRlIG11c3QgYmUgdW5rbm93biBpbiBPcGVyYSBidXQgXCJzYWZlXCIgZm9yIFdpblJUXG5cdFx0XHQvLyBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2hoNDY1Mzg4LmFzcHgjYXR0cmlidXRlX3NlY3Rpb25cblx0XHRcdGlmICggZWwucXVlcnlTZWxlY3RvckFsbChcIlttc2FsbG93Y2FwdHVyZV49JyddXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiWypeJF09XCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86Jyd8XFxcIlxcXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4XG5cdFx0XHQvLyBCb29sZWFuIGF0dHJpYnV0ZXMgYW5kIFwidmFsdWVcIiBhcmUgbm90IHRyZWF0ZWQgY29ycmVjdGx5XG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW3NlbGVjdGVkXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86dmFsdWV8XCIgKyBib29sZWFucyArIFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IENocm9tZTwyOSwgQW5kcm9pZDw0LjQsIFNhZmFyaTw3LjArLCBpT1M8Ny4wKywgUGhhbnRvbUpTPDEuOS44K1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbCggXCJbaWR+PVwiICsgZXhwYW5kbyArIFwiLV1cIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCJ+PVwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gV2Via2l0L09wZXJhIC0gOmNoZWNrZWQgc2hvdWxkIHJldHVybiBzZWxlY3RlZCBvcHRpb24gZWxlbWVudHNcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMTEvUkVDLWNzczMtc2VsZWN0b3JzLTIwMTEwOTI5LyNjaGVja2VkXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbChcIjpjaGVja2VkXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCI6Y2hlY2tlZFwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogU2FmYXJpIDgrLCBpT1MgOCtcblx0XHRcdC8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzY4NTFcblx0XHRcdC8vIEluLXBhZ2UgYHNlbGVjdG9yI2lkIHNpYmxpbmctY29tYmluYXRvciBzZWxlY3RvcmAgZmFpbHNcblx0XHRcdGlmICggIWVsLnF1ZXJ5U2VsZWN0b3JBbGwoIFwiYSNcIiArIGV4cGFuZG8gKyBcIisqXCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKFwiLiMuK1srfl1cIik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdFx0ZWwuaW5uZXJIVE1MID0gXCI8YSBocmVmPScnIGRpc2FibGVkPSdkaXNhYmxlZCc+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGRpc2FibGVkPSdkaXNhYmxlZCc+PG9wdGlvbi8+PC9zZWxlY3Q+XCI7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IFdpbmRvd3MgOCBOYXRpdmUgQXBwc1xuXHRcdFx0Ly8gVGhlIHR5cGUgYW5kIG5hbWUgYXR0cmlidXRlcyBhcmUgcmVzdHJpY3RlZCBkdXJpbmcgLmlubmVySFRNTCBhc3NpZ25tZW50XG5cdFx0XHR2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG5cdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwidHlwZVwiLCBcImhpZGRlblwiICk7XG5cdFx0XHRlbC5hcHBlbmRDaGlsZCggaW5wdXQgKS5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcIkRcIiApO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRThcblx0XHRcdC8vIEVuZm9yY2UgY2FzZS1zZW5zaXRpdml0eSBvZiBuYW1lIGF0dHJpYnV0ZVxuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW25hbWU9ZF1cIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCJuYW1lXCIgKyB3aGl0ZXNwYWNlICsgXCIqWypeJHwhfl0/PVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZGIDMuNSAtIDplbmFibGVkLzpkaXNhYmxlZCBhbmQgaGlkZGVuIGVsZW1lbnRzIChoaWRkZW4gZWxlbWVudHMgYXJlIHN0aWxsIGVuYWJsZWQpXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiOmVuYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOS0xMStcblx0XHRcdC8vIElFJ3MgOmRpc2FibGVkIHNlbGVjdG9yIGRvZXMgbm90IHBpY2sgdXAgdGhlIGNoaWxkcmVuIG9mIGRpc2FibGVkIGZpZWxkc2V0c1xuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZGlzYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9wZXJhIDEwLTExIGRvZXMgbm90IHRocm93IG9uIHBvc3QtY29tbWEgaW52YWxpZCBwc2V1ZG9zXG5cdFx0XHRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiKiw6eFwiKTtcblx0XHRcdHJidWdneVFTQS5wdXNoKFwiLC4qOlwiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmICggKHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yID0gcm5hdGl2ZS50ZXN0KCAobWF0Y2hlcyA9IGRvY0VsZW0ubWF0Y2hlcyB8fFxuXHRcdGRvY0VsZW0ud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0ZG9jRWxlbS5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm9NYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1zTWF0Y2hlc1NlbGVjdG9yKSApKSApIHtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBDaGVjayB0byBzZWUgaWYgaXQncyBwb3NzaWJsZSB0byBkbyBtYXRjaGVzU2VsZWN0b3Jcblx0XHRcdC8vIG9uIGEgZGlzY29ubmVjdGVkIG5vZGUgKElFIDkpXG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBlbCwgXCIqXCIgKTtcblxuXHRcdFx0Ly8gVGhpcyBzaG91bGQgZmFpbCB3aXRoIGFuIGV4Y2VwdGlvblxuXHRcdFx0Ly8gR2Vja28gZG9lcyBub3QgZXJyb3IsIHJldHVybnMgZmFsc2UgaW5zdGVhZFxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBlbCwgXCJbcyE9JyddOnhcIiApO1xuXHRcdFx0cmJ1Z2d5TWF0Y2hlcy5wdXNoKCBcIiE9XCIsIHBzZXVkb3MgKTtcblx0XHR9KTtcblx0fVxuXG5cdHJidWdneVFTQSA9IHJidWdneVFTQS5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5UVNBLmpvaW4oXCJ8XCIpICk7XG5cdHJidWdneU1hdGNoZXMgPSByYnVnZ3lNYXRjaGVzLmxlbmd0aCAmJiBuZXcgUmVnRXhwKCByYnVnZ3lNYXRjaGVzLmpvaW4oXCJ8XCIpICk7XG5cblx0LyogQ29udGFpbnNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXHRoYXNDb21wYXJlID0gcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICk7XG5cblx0Ly8gRWxlbWVudCBjb250YWlucyBhbm90aGVyXG5cdC8vIFB1cnBvc2VmdWxseSBzZWxmLWV4Y2x1c2l2ZVxuXHQvLyBBcyBpbiwgYW4gZWxlbWVudCBkb2VzIG5vdCBjb250YWluIGl0c2VsZlxuXHRjb250YWlucyA9IGhhc0NvbXBhcmUgfHwgcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbnRhaW5zICkgP1xuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0dmFyIGFkb3duID0gYS5ub2RlVHlwZSA9PT0gOSA/IGEuZG9jdW1lbnRFbGVtZW50IDogYSxcblx0XHRcdFx0YnVwID0gYiAmJiBiLnBhcmVudE5vZGU7XG5cdFx0XHRyZXR1cm4gYSA9PT0gYnVwIHx8ICEhKCBidXAgJiYgYnVwLm5vZGVUeXBlID09PSAxICYmIChcblx0XHRcdFx0YWRvd24uY29udGFpbnMgP1xuXHRcdFx0XHRcdGFkb3duLmNvbnRhaW5zKCBidXAgKSA6XG5cdFx0XHRcdFx0YS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBidXAgKSAmIDE2XG5cdFx0XHQpKTtcblx0XHR9IDpcblx0XHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHRcdGlmICggYiApIHtcblx0XHRcdFx0d2hpbGUgKCAoYiA9IGIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBiID09PSBhICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcblxuXHQvKiBTb3J0aW5nXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBEb2N1bWVudCBvcmRlciBzb3J0aW5nXG5cdHNvcnRPcmRlciA9IGhhc0NvbXBhcmUgP1xuXHRmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdC8vIEZsYWcgZm9yIGR1cGxpY2F0ZSByZW1vdmFsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdC8vIFNvcnQgb24gbWV0aG9kIGV4aXN0ZW5jZSBpZiBvbmx5IG9uZSBpbnB1dCBoYXMgY29tcGFyZURvY3VtZW50UG9zaXRpb25cblx0XHR2YXIgY29tcGFyZSA9ICFhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uIC0gIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247XG5cdFx0aWYgKCBjb21wYXJlICkge1xuXHRcdFx0cmV0dXJuIGNvbXBhcmU7XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsY3VsYXRlIHBvc2l0aW9uIGlmIGJvdGggaW5wdXRzIGJlbG9uZyB0byB0aGUgc2FtZSBkb2N1bWVudFxuXHRcdGNvbXBhcmUgPSAoIGEub3duZXJEb2N1bWVudCB8fCBhICkgPT09ICggYi5vd25lckRvY3VtZW50IHx8IGIgKSA/XG5cdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBiICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugd2Uga25vdyB0aGV5IGFyZSBkaXNjb25uZWN0ZWRcblx0XHRcdDE7XG5cblx0XHQvLyBEaXNjb25uZWN0ZWQgbm9kZXNcblx0XHRpZiAoIGNvbXBhcmUgJiAxIHx8XG5cdFx0XHQoIXN1cHBvcnQuc29ydERldGFjaGVkICYmIGIuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGEgKSA9PT0gY29tcGFyZSkgKSB7XG5cblx0XHRcdC8vIENob29zZSB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IGlzIHJlbGF0ZWQgdG8gb3VyIHByZWZlcnJlZCBkb2N1bWVudFxuXHRcdFx0aWYgKCBhID09PSBkb2N1bWVudCB8fCBhLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGEpICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGIgPT09IGRvY3VtZW50IHx8IGIub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYikgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWludGFpbiBvcmlnaW5hbCBvcmRlclxuXHRcdFx0cmV0dXJuIHNvcnRJbnB1dCA/XG5cdFx0XHRcdCggaW5kZXhPZiggc29ydElucHV0LCBhICkgLSBpbmRleE9mKCBzb3J0SW5wdXQsIGIgKSApIDpcblx0XHRcdFx0MDtcblx0XHR9XG5cblx0XHRyZXR1cm4gY29tcGFyZSAmIDQgPyAtMSA6IDE7XG5cdH0gOlxuXHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHQvLyBFeGl0IGVhcmx5IGlmIHRoZSBub2RlcyBhcmUgaWRlbnRpY2FsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHZhciBjdXIsXG5cdFx0XHRpID0gMCxcblx0XHRcdGF1cCA9IGEucGFyZW50Tm9kZSxcblx0XHRcdGJ1cCA9IGIucGFyZW50Tm9kZSxcblx0XHRcdGFwID0gWyBhIF0sXG5cdFx0XHRicCA9IFsgYiBdO1xuXG5cdFx0Ly8gUGFyZW50bGVzcyBub2RlcyBhcmUgZWl0aGVyIGRvY3VtZW50cyBvciBkaXNjb25uZWN0ZWRcblx0XHRpZiAoICFhdXAgfHwgIWJ1cCApIHtcblx0XHRcdHJldHVybiBhID09PSBkb2N1bWVudCA/IC0xIDpcblx0XHRcdFx0YiA9PT0gZG9jdW1lbnQgPyAxIDpcblx0XHRcdFx0YXVwID8gLTEgOlxuXHRcdFx0XHRidXAgPyAxIDpcblx0XHRcdFx0c29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0Ly8gSWYgdGhlIG5vZGVzIGFyZSBzaWJsaW5ncywgd2UgY2FuIGRvIGEgcXVpY2sgY2hlY2tcblx0XHR9IGVsc2UgaWYgKCBhdXAgPT09IGJ1cCApIHtcblx0XHRcdHJldHVybiBzaWJsaW5nQ2hlY2soIGEsIGIgKTtcblx0XHR9XG5cblx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCBmdWxsIGxpc3RzIG9mIHRoZWlyIGFuY2VzdG9ycyBmb3IgY29tcGFyaXNvblxuXHRcdGN1ciA9IGE7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YXAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXHRcdGN1ciA9IGI7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YnAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXG5cdFx0Ly8gV2FsayBkb3duIHRoZSB0cmVlIGxvb2tpbmcgZm9yIGEgZGlzY3JlcGFuY3lcblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHQvLyBEbyBhIHNpYmxpbmcgY2hlY2sgaWYgdGhlIG5vZGVzIGhhdmUgYSBjb21tb24gYW5jZXN0b3Jcblx0XHRcdHNpYmxpbmdDaGVjayggYXBbaV0sIGJwW2ldICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugbm9kZXMgaW4gb3VyIGRvY3VtZW50IHNvcnQgZmlyc3Rcblx0XHRcdGFwW2ldID09PSBwcmVmZXJyZWREb2MgPyAtMSA6XG5cdFx0XHRicFtpXSA9PT0gcHJlZmVycmVkRG9jID8gMSA6XG5cdFx0XHQwO1xuXHR9O1xuXG5cdHJldHVybiBkb2N1bWVudDtcbn07XG5cblNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1lbnRzICkge1xuXHRyZXR1cm4gU2l6emxlKCBleHByLCBudWxsLCBudWxsLCBlbGVtZW50cyApO1xufTtcblxuU2l6emxlLm1hdGNoZXNTZWxlY3RvciA9IGZ1bmN0aW9uKCBlbGVtLCBleHByICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHQvLyBNYWtlIHN1cmUgdGhhdCBhdHRyaWJ1dGUgc2VsZWN0b3JzIGFyZSBxdW90ZWRcblx0ZXhwciA9IGV4cHIucmVwbGFjZSggcmF0dHJpYnV0ZVF1b3RlcywgXCI9JyQxJ11cIiApO1xuXG5cdGlmICggc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgJiYgZG9jdW1lbnRJc0hUTUwgJiZcblx0XHQhY29tcGlsZXJDYWNoZVsgZXhwciArIFwiIFwiIF0gJiZcblx0XHQoICFyYnVnZ3lNYXRjaGVzIHx8ICFyYnVnZ3lNYXRjaGVzLnRlc3QoIGV4cHIgKSApICYmXG5cdFx0KCAhcmJ1Z2d5UVNBICAgICB8fCAhcmJ1Z2d5UVNBLnRlc3QoIGV4cHIgKSApICkge1xuXG5cdFx0dHJ5IHtcblx0XHRcdHZhciByZXQgPSBtYXRjaGVzLmNhbGwoIGVsZW0sIGV4cHIgKTtcblxuXHRcdFx0Ly8gSUUgOSdzIG1hdGNoZXNTZWxlY3RvciByZXR1cm5zIGZhbHNlIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdFx0aWYgKCByZXQgfHwgc3VwcG9ydC5kaXNjb25uZWN0ZWRNYXRjaCB8fFxuXHRcdFx0XHRcdC8vIEFzIHdlbGwsIGRpc2Nvbm5lY3RlZCBub2RlcyBhcmUgc2FpZCB0byBiZSBpbiBhIGRvY3VtZW50XG5cdFx0XHRcdFx0Ly8gZnJhZ21lbnQgaW4gSUUgOVxuXHRcdFx0XHRcdGVsZW0uZG9jdW1lbnQgJiYgZWxlbS5kb2N1bWVudC5ub2RlVHlwZSAhPT0gMTEgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge31cblx0fVxuXG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIGRvY3VtZW50LCBudWxsLCBbIGVsZW0gXSApLmxlbmd0aCA+IDA7XG59O1xuXG5TaXp6bGUuY29udGFpbnMgPSBmdW5jdGlvbiggY29udGV4dCwgZWxlbSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgfHwgY29udGV4dCApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHR9XG5cdHJldHVybiBjb250YWlucyggY29udGV4dCwgZWxlbSApO1xufTtcblxuU2l6emxlLmF0dHIgPSBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHR9XG5cblx0dmFyIGZuID0gRXhwci5hdHRySGFuZGxlWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSxcblx0XHQvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IE9iamVjdC5wcm90b3R5cGUgcHJvcGVydGllcyAoalF1ZXJ5ICMxMzgwNylcblx0XHR2YWwgPSBmbiAmJiBoYXNPd24uY2FsbCggRXhwci5hdHRySGFuZGxlLCBuYW1lLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRmbiggZWxlbSwgbmFtZSwgIWRvY3VtZW50SXNIVE1MICkgOlxuXHRcdFx0dW5kZWZpbmVkO1xuXG5cdHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/XG5cdFx0dmFsIDpcblx0XHRzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWRvY3VtZW50SXNIVE1MID9cblx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICkgOlxuXHRcdFx0KHZhbCA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShuYW1lKSkgJiYgdmFsLnNwZWNpZmllZCA/XG5cdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG59O1xuXG5TaXp6bGUuZXNjYXBlID0gZnVuY3Rpb24oIHNlbCApIHtcblx0cmV0dXJuIChzZWwgKyBcIlwiKS5yZXBsYWNlKCByY3NzZXNjYXBlLCBmY3NzZXNjYXBlICk7XG59O1xuXG5TaXp6bGUuZXJyb3IgPSBmdW5jdGlvbiggbXNnICkge1xuXHR0aHJvdyBuZXcgRXJyb3IoIFwiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogXCIgKyBtc2cgKTtcbn07XG5cbi8qKlxuICogRG9jdW1lbnQgc29ydGluZyBhbmQgcmVtb3ZpbmcgZHVwbGljYXRlc1xuICogQHBhcmFtIHtBcnJheUxpa2V9IHJlc3VsdHNcbiAqL1xuU2l6emxlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbiggcmVzdWx0cyApIHtcblx0dmFyIGVsZW0sXG5cdFx0ZHVwbGljYXRlcyA9IFtdLFxuXHRcdGogPSAwLFxuXHRcdGkgPSAwO1xuXG5cdC8vIFVubGVzcyB3ZSAqa25vdyogd2UgY2FuIGRldGVjdCBkdXBsaWNhdGVzLCBhc3N1bWUgdGhlaXIgcHJlc2VuY2Vcblx0aGFzRHVwbGljYXRlID0gIXN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcztcblx0c29ydElucHV0ID0gIXN1cHBvcnQuc29ydFN0YWJsZSAmJiByZXN1bHRzLnNsaWNlKCAwICk7XG5cdHJlc3VsdHMuc29ydCggc29ydE9yZGVyICk7XG5cblx0aWYgKCBoYXNEdXBsaWNhdGUgKSB7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRpZiAoIGVsZW0gPT09IHJlc3VsdHNbIGkgXSApIHtcblx0XHRcdFx0aiA9IGR1cGxpY2F0ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdHJlc3VsdHMuc3BsaWNlKCBkdXBsaWNhdGVzWyBqIF0sIDEgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDbGVhciBpbnB1dCBhZnRlciBzb3J0aW5nIHRvIHJlbGVhc2Ugb2JqZWN0c1xuXHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9zaXp6bGUvcHVsbC8yMjVcblx0c29ydElucHV0ID0gbnVsbDtcblxuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiBmb3IgcmV0cmlldmluZyB0aGUgdGV4dCB2YWx1ZSBvZiBhbiBhcnJheSBvZiBET00gbm9kZXNcbiAqIEBwYXJhbSB7QXJyYXl8RWxlbWVudH0gZWxlbVxuICovXG5nZXRUZXh0ID0gU2l6emxlLmdldFRleHQgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0dmFyIG5vZGUsXG5cdFx0cmV0ID0gXCJcIixcblx0XHRpID0gMCxcblx0XHRub2RlVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0aWYgKCAhbm9kZVR5cGUgKSB7XG5cdFx0Ly8gSWYgbm8gbm9kZVR5cGUsIHRoaXMgaXMgZXhwZWN0ZWQgdG8gYmUgYW4gYXJyYXlcblx0XHR3aGlsZSAoIChub2RlID0gZWxlbVtpKytdKSApIHtcblx0XHRcdC8vIERvIG5vdCB0cmF2ZXJzZSBjb21tZW50IG5vZGVzXG5cdFx0XHRyZXQgKz0gZ2V0VGV4dCggbm9kZSApO1xuXHRcdH1cblx0fSBlbHNlIGlmICggbm9kZVR5cGUgPT09IDEgfHwgbm9kZVR5cGUgPT09IDkgfHwgbm9kZVR5cGUgPT09IDExICkge1xuXHRcdC8vIFVzZSB0ZXh0Q29udGVudCBmb3IgZWxlbWVudHNcblx0XHQvLyBpbm5lclRleHQgdXNhZ2UgcmVtb3ZlZCBmb3IgY29uc2lzdGVuY3kgb2YgbmV3IGxpbmVzIChqUXVlcnkgIzExMTUzKVxuXHRcdGlmICggdHlwZW9mIGVsZW0udGV4dENvbnRlbnQgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS50ZXh0Q29udGVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gVHJhdmVyc2UgaXRzIGNoaWxkcmVuXG5cdFx0XHRmb3IgKCBlbGVtID0gZWxlbS5maXJzdENoaWxkOyBlbGVtOyBlbGVtID0gZWxlbS5uZXh0U2libGluZyApIHtcblx0XHRcdFx0cmV0ICs9IGdldFRleHQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAzIHx8IG5vZGVUeXBlID09PSA0ICkge1xuXHRcdHJldHVybiBlbGVtLm5vZGVWYWx1ZTtcblx0fVxuXHQvLyBEbyBub3QgaW5jbHVkZSBjb21tZW50IG9yIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gbm9kZXNcblxuXHRyZXR1cm4gcmV0O1xufTtcblxuRXhwciA9IFNpenpsZS5zZWxlY3RvcnMgPSB7XG5cblx0Ly8gQ2FuIGJlIGFkanVzdGVkIGJ5IHRoZSB1c2VyXG5cdGNhY2hlTGVuZ3RoOiA1MCxcblxuXHRjcmVhdGVQc2V1ZG86IG1hcmtGdW5jdGlvbixcblxuXHRtYXRjaDogbWF0Y2hFeHByLFxuXG5cdGF0dHJIYW5kbGU6IHt9LFxuXG5cdGZpbmQ6IHt9LFxuXG5cdHJlbGF0aXZlOiB7XG5cdFx0XCI+XCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIiBcIjogeyBkaXI6IFwicGFyZW50Tm9kZVwiIH0sXG5cdFx0XCIrXCI6IHsgZGlyOiBcInByZXZpb3VzU2libGluZ1wiLCBmaXJzdDogdHJ1ZSB9LFxuXHRcdFwiflwiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiB9XG5cdH0sXG5cblx0cHJlRmlsdGVyOiB7XG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0Ly8gTW92ZSB0aGUgZ2l2ZW4gdmFsdWUgdG8gbWF0Y2hbM10gd2hldGhlciBxdW90ZWQgb3IgdW5xdW90ZWRcblx0XHRcdG1hdGNoWzNdID0gKCBtYXRjaFszXSB8fCBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiICkucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsyXSA9PT0gXCJ+PVwiICkge1xuXHRcdFx0XHRtYXRjaFszXSA9IFwiIFwiICsgbWF0Y2hbM10gKyBcIiBcIjtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCA0ICk7XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0LyogbWF0Y2hlcyBmcm9tIG1hdGNoRXhwcltcIkNISUxEXCJdXG5cdFx0XHRcdDEgdHlwZSAob25seXxudGh8Li4uKVxuXHRcdFx0XHQyIHdoYXQgKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdDMgYXJndW1lbnQgKGV2ZW58b2RkfFxcZCp8XFxkKm4oWystXVxcZCspP3wuLi4pXG5cdFx0XHRcdDQgeG4tY29tcG9uZW50IG9mIHhuK3kgYXJndW1lbnQgKFsrLV0/XFxkKm58KVxuXHRcdFx0XHQ1IHNpZ24gb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDYgeCBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NyBzaWduIG9mIHktY29tcG9uZW50XG5cdFx0XHRcdDggeSBvZiB5LWNvbXBvbmVudFxuXHRcdFx0Ki9cblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsxXS5zbGljZSggMCwgMyApID09PSBcIm50aFwiICkge1xuXHRcdFx0XHQvLyBudGgtKiByZXF1aXJlcyBhcmd1bWVudFxuXHRcdFx0XHRpZiAoICFtYXRjaFszXSApIHtcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBudW1lcmljIHggYW5kIHkgcGFyYW1ldGVycyBmb3IgRXhwci5maWx0ZXIuQ0hJTERcblx0XHRcdFx0Ly8gcmVtZW1iZXIgdGhhdCBmYWxzZS90cnVlIGNhc3QgcmVzcGVjdGl2ZWx5IHRvIDAvMVxuXHRcdFx0XHRtYXRjaFs0XSA9ICsoIG1hdGNoWzRdID8gbWF0Y2hbNV0gKyAobWF0Y2hbNl0gfHwgMSkgOiAyICogKCBtYXRjaFszXSA9PT0gXCJldmVuXCIgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKSApO1xuXHRcdFx0XHRtYXRjaFs1XSA9ICsoICggbWF0Y2hbN10gKyBtYXRjaFs4XSApIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICk7XG5cblx0XHRcdC8vIG90aGVyIHR5cGVzIHByb2hpYml0IGFyZ3VtZW50c1xuXHRcdFx0fSBlbHNlIGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdFNpenpsZS5lcnJvciggbWF0Y2hbMF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoO1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHR2YXIgZXhjZXNzLFxuXHRcdFx0XHR1bnF1b3RlZCA9ICFtYXRjaFs2XSAmJiBtYXRjaFsyXTtcblxuXHRcdFx0aWYgKCBtYXRjaEV4cHJbXCJDSElMRFwiXS50ZXN0KCBtYXRjaFswXSApICkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWNjZXB0IHF1b3RlZCBhcmd1bWVudHMgYXMtaXNcblx0XHRcdGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdG1hdGNoWzJdID0gbWF0Y2hbNF0gfHwgbWF0Y2hbNV0gfHwgXCJcIjtcblxuXHRcdFx0Ly8gU3RyaXAgZXhjZXNzIGNoYXJhY3RlcnMgZnJvbSB1bnF1b3RlZCBhcmd1bWVudHNcblx0XHRcdH0gZWxzZSBpZiAoIHVucXVvdGVkICYmIHJwc2V1ZG8udGVzdCggdW5xdW90ZWQgKSAmJlxuXHRcdFx0XHQvLyBHZXQgZXhjZXNzIGZyb20gdG9rZW5pemUgKHJlY3Vyc2l2ZWx5KVxuXHRcdFx0XHQoZXhjZXNzID0gdG9rZW5pemUoIHVucXVvdGVkLCB0cnVlICkpICYmXG5cdFx0XHRcdC8vIGFkdmFuY2UgdG8gdGhlIG5leHQgY2xvc2luZyBwYXJlbnRoZXNpc1xuXHRcdFx0XHQoZXhjZXNzID0gdW5xdW90ZWQuaW5kZXhPZiggXCIpXCIsIHVucXVvdGVkLmxlbmd0aCAtIGV4Y2VzcyApIC0gdW5xdW90ZWQubGVuZ3RoKSApIHtcblxuXHRcdFx0XHQvLyBleGNlc3MgaXMgYSBuZWdhdGl2ZSBpbmRleFxuXHRcdFx0XHRtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwLCBleGNlc3MgKTtcblx0XHRcdFx0bWF0Y2hbMl0gPSB1bnF1b3RlZC5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldHVybiBvbmx5IGNhcHR1cmVzIG5lZWRlZCBieSB0aGUgcHNldWRvIGZpbHRlciBtZXRob2QgKHR5cGUgYW5kIGFyZ3VtZW50KVxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCAzICk7XG5cdFx0fVxuXHR9LFxuXG5cdGZpbHRlcjoge1xuXG5cdFx0XCJUQUdcIjogZnVuY3Rpb24oIG5vZGVOYW1lU2VsZWN0b3IgKSB7XG5cdFx0XHR2YXIgbm9kZU5hbWUgPSBub2RlTmFtZVNlbGVjdG9yLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICkudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBub2RlTmFtZVNlbGVjdG9yID09PSBcIipcIiA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfSA6XG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbm9kZU5hbWU7XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0xBU1NcIjogZnVuY3Rpb24oIGNsYXNzTmFtZSApIHtcblx0XHRcdHZhciBwYXR0ZXJuID0gY2xhc3NDYWNoZVsgY2xhc3NOYW1lICsgXCIgXCIgXTtcblxuXHRcdFx0cmV0dXJuIHBhdHRlcm4gfHxcblx0XHRcdFx0KHBhdHRlcm4gPSBuZXcgUmVnRXhwKCBcIihefFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgY2xhc3NOYW1lICsgXCIoXCIgKyB3aGl0ZXNwYWNlICsgXCJ8JClcIiApKSAmJlxuXHRcdFx0XHRjbGFzc0NhY2hlKCBjbGFzc05hbWUsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXR0ZXJuLnRlc3QoIHR5cGVvZiBlbGVtLmNsYXNzTmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBlbGVtLmNsYXNzTmFtZSB8fCB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGUgIT09IFwidW5kZWZpbmVkXCIgJiYgZWxlbS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKSB8fCBcIlwiICk7XG5cdFx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRcIkFUVFJcIjogZnVuY3Rpb24oIG5hbWUsIG9wZXJhdG9yLCBjaGVjayApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IFNpenpsZS5hdHRyKCBlbGVtLCBuYW1lICk7XG5cblx0XHRcdFx0aWYgKCByZXN1bHQgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiIT1cIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoICFvcGVyYXRvciApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlc3VsdCArPSBcIlwiO1xuXG5cdFx0XHRcdHJldHVybiBvcGVyYXRvciA9PT0gXCI9XCIgPyByZXN1bHQgPT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIhPVwiID8gcmVzdWx0ICE9PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiXj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID09PSAwIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIqPVwiID8gY2hlY2sgJiYgcmVzdWx0LmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiJD1cIiA/IGNoZWNrICYmIHJlc3VsdC5zbGljZSggLWNoZWNrLmxlbmd0aCApID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifj1cIiA/ICggXCIgXCIgKyByZXN1bHQucmVwbGFjZSggcndoaXRlc3BhY2UsIFwiIFwiICkgKyBcIiBcIiApLmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifD1cIiA/IHJlc3VsdCA9PT0gY2hlY2sgfHwgcmVzdWx0LnNsaWNlKCAwLCBjaGVjay5sZW5ndGggKyAxICkgPT09IGNoZWNrICsgXCItXCIgOlxuXHRcdFx0XHRcdGZhbHNlO1xuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDSElMRFwiOiBmdW5jdGlvbiggdHlwZSwgd2hhdCwgYXJndW1lbnQsIGZpcnN0LCBsYXN0ICkge1xuXHRcdFx0dmFyIHNpbXBsZSA9IHR5cGUuc2xpY2UoIDAsIDMgKSAhPT0gXCJudGhcIixcblx0XHRcdFx0Zm9yd2FyZCA9IHR5cGUuc2xpY2UoIC00ICkgIT09IFwibGFzdFwiLFxuXHRcdFx0XHRvZlR5cGUgPSB3aGF0ID09PSBcIm9mLXR5cGVcIjtcblxuXHRcdFx0cmV0dXJuIGZpcnN0ID09PSAxICYmIGxhc3QgPT09IDAgP1xuXG5cdFx0XHRcdC8vIFNob3J0Y3V0IGZvciA6bnRoLSoobilcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuICEhZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0XHR9IDpcblxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBjYWNoZSwgdW5pcXVlQ2FjaGUsIG91dGVyQ2FjaGUsIG5vZGUsIG5vZGVJbmRleCwgc3RhcnQsXG5cdFx0XHRcdFx0XHRkaXIgPSBzaW1wbGUgIT09IGZvcndhcmQgPyBcIm5leHRTaWJsaW5nXCIgOiBcInByZXZpb3VzU2libGluZ1wiLFxuXHRcdFx0XHRcdFx0cGFyZW50ID0gZWxlbS5wYXJlbnROb2RlLFxuXHRcdFx0XHRcdFx0bmFtZSA9IG9mVHlwZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRcdFx0XHR1c2VDYWNoZSA9ICF4bWwgJiYgIW9mVHlwZSxcblx0XHRcdFx0XHRcdGRpZmYgPSBmYWxzZTtcblxuXHRcdFx0XHRcdGlmICggcGFyZW50ICkge1xuXG5cdFx0XHRcdFx0XHQvLyA6KGZpcnN0fGxhc3R8b25seSktKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdFx0XHRpZiAoIHNpbXBsZSApIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCBkaXIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW07XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9IG5vZGVbIGRpciBdKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggb2ZUeXBlID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDpcblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vIFJldmVyc2UgZGlyZWN0aW9uIGZvciA6b25seS0qIChpZiB3ZSBoYXZlbid0IHlldCBkb25lIHNvKVxuXHRcdFx0XHRcdFx0XHRcdHN0YXJ0ID0gZGlyID0gdHlwZSA9PT0gXCJvbmx5XCIgJiYgIXN0YXJ0ICYmIFwibmV4dFNpYmxpbmdcIjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0c3RhcnQgPSBbIGZvcndhcmQgPyBwYXJlbnQuZmlyc3RDaGlsZCA6IHBhcmVudC5sYXN0Q2hpbGQgXTtcblxuXHRcdFx0XHRcdFx0Ly8gbm9uLXhtbCA6bnRoLWNoaWxkKC4uLikgc3RvcmVzIGNhY2hlIGRhdGEgb24gYHBhcmVudGBcblx0XHRcdFx0XHRcdGlmICggZm9yd2FyZCAmJiB1c2VDYWNoZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTZWVrIGBlbGVtYCBmcm9tIGEgcHJldmlvdXNseS1jYWNoZWQgaW5kZXhcblxuXHRcdFx0XHRcdFx0XHQvLyAuLi5pbiBhIGd6aXAtZnJpZW5kbHkgd2F5XG5cdFx0XHRcdFx0XHRcdG5vZGUgPSBwYXJlbnQ7XG5cdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0Y2FjaGUgPSB1bmlxdWVDYWNoZVsgdHlwZSBdIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVsgMCBdID09PSBkaXJydW5zICYmIGNhY2hlWyAxIF07XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXggJiYgY2FjaGVbIDIgXTtcblx0XHRcdFx0XHRcdFx0bm9kZSA9IG5vZGVJbmRleCAmJiBwYXJlbnQuY2hpbGROb2Rlc1sgbm9kZUluZGV4IF07XG5cblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIHNlZWtpbmcgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBXaGVuIGZvdW5kLCBjYWNoZSBpbmRleGVzIG9uIGBwYXJlbnRgIGFuZCBicmVha1xuXHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSAmJiArK2RpZmYgJiYgbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIG5vZGVJbmRleCwgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFVzZSBwcmV2aW91c2x5LWNhY2hlZCBlbGVtZW50IGluZGV4IGlmIGF2YWlsYWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLmluIGEgZ3ppcC1mcmllbmRseSB3YXlcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gZWxlbTtcblx0XHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gbm9kZVsgZXhwYW5kbyBdIHx8IChub2RlWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHRjYWNoZSA9IHVuaXF1ZUNhY2hlWyB0eXBlIF0gfHwgW107XG5cdFx0XHRcdFx0XHRcdFx0bm9kZUluZGV4ID0gY2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBjYWNoZVsgMSBdO1xuXHRcdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXg7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvLyB4bWwgOm50aC1jaGlsZCguLi4pXG5cdFx0XHRcdFx0XHRcdC8vIG9yIDpudGgtbGFzdC1jaGlsZCguLi4pIG9yIDpudGgoLWxhc3QpPy1vZi10eXBlKC4uLilcblx0XHRcdFx0XHRcdFx0aWYgKCBkaWZmID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBVc2UgdGhlIHNhbWUgbG9vcCBhcyBhYm92ZSB0byBzZWVrIGBlbGVtYCBmcm9tIHRoZSBzdGFydFxuXHRcdFx0XHRcdFx0XHRcdHdoaWxlICggKG5vZGUgPSArK25vZGVJbmRleCAmJiBub2RlICYmIG5vZGVbIGRpciBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCAoIG9mVHlwZSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZSA6XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZVR5cGUgPT09IDEgKSAmJlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQrK2RpZmYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FjaGUgdGhlIGluZGV4IG9mIGVhY2ggZW5jb3VudGVyZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZlbmQgYWdhaW5zdCBjbG9uZWQgYXR0cm9wZXJ0aWVzIChqUXVlcnkgZ2gtMTcwOSlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIGRpZmYgXTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQvLyBJbmNvcnBvcmF0ZSB0aGUgb2Zmc2V0LCB0aGVuIGNoZWNrIGFnYWluc3QgY3ljbGUgc2l6ZVxuXHRcdFx0XHRcdFx0ZGlmZiAtPSBsYXN0O1xuXHRcdFx0XHRcdFx0cmV0dXJuIGRpZmYgPT09IGZpcnN0IHx8ICggZGlmZiAlIGZpcnN0ID09PSAwICYmIGRpZmYgLyBmaXJzdCA+PSAwICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggcHNldWRvLCBhcmd1bWVudCApIHtcblx0XHRcdC8vIHBzZXVkby1jbGFzcyBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZVxuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNwc2V1ZG8tY2xhc3Nlc1xuXHRcdFx0Ly8gUHJpb3JpdGl6ZSBieSBjYXNlIHNlbnNpdGl2aXR5IGluIGNhc2UgY3VzdG9tIHBzZXVkb3MgYXJlIGFkZGVkIHdpdGggdXBwZXJjYXNlIGxldHRlcnNcblx0XHRcdC8vIFJlbWVtYmVyIHRoYXQgc2V0RmlsdGVycyBpbmhlcml0cyBmcm9tIHBzZXVkb3Ncblx0XHRcdHZhciBhcmdzLFxuXHRcdFx0XHRmbiA9IEV4cHIucHNldWRvc1sgcHNldWRvIF0gfHwgRXhwci5zZXRGaWx0ZXJzWyBwc2V1ZG8udG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIHBzZXVkbzogXCIgKyBwc2V1ZG8gKTtcblxuXHRcdFx0Ly8gVGhlIHVzZXIgbWF5IHVzZSBjcmVhdGVQc2V1ZG8gdG8gaW5kaWNhdGUgdGhhdFxuXHRcdFx0Ly8gYXJndW1lbnRzIGFyZSBuZWVkZWQgdG8gY3JlYXRlIHRoZSBmaWx0ZXIgZnVuY3Rpb25cblx0XHRcdC8vIGp1c3QgYXMgU2l6emxlIGRvZXNcblx0XHRcdGlmICggZm5bIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZuKCBhcmd1bWVudCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBCdXQgbWFpbnRhaW4gc3VwcG9ydCBmb3Igb2xkIHNpZ25hdHVyZXNcblx0XHRcdGlmICggZm4ubGVuZ3RoID4gMSApIHtcblx0XHRcdFx0YXJncyA9IFsgcHNldWRvLCBwc2V1ZG8sIFwiXCIsIGFyZ3VtZW50IF07XG5cdFx0XHRcdHJldHVybiBFeHByLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoIHBzZXVkby50b0xvd2VyQ2FzZSgpICkgP1xuXHRcdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdFx0XHRcdHZhciBpZHgsXG5cdFx0XHRcdFx0XHRcdG1hdGNoZWQgPSBmbiggc2VlZCwgYXJndW1lbnQgKSxcblx0XHRcdFx0XHRcdFx0aSA9IG1hdGNoZWQubGVuZ3RoO1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlkeCA9IGluZGV4T2YoIHNlZWQsIG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdFx0c2VlZFsgaWR4IF0gPSAhKCBtYXRjaGVzWyBpZHggXSA9IG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZm4oIGVsZW0sIDAsIGFyZ3MgKTtcblx0XHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZm47XG5cdFx0fVxuXHR9LFxuXG5cdHBzZXVkb3M6IHtcblx0XHQvLyBQb3RlbnRpYWxseSBjb21wbGV4IHBzZXVkb3Ncblx0XHRcIm5vdFwiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0Ly8gVHJpbSB0aGUgc2VsZWN0b3IgcGFzc2VkIHRvIGNvbXBpbGVcblx0XHRcdC8vIHRvIGF2b2lkIHRyZWF0aW5nIGxlYWRpbmcgYW5kIHRyYWlsaW5nXG5cdFx0XHQvLyBzcGFjZXMgYXMgY29tYmluYXRvcnNcblx0XHRcdHZhciBpbnB1dCA9IFtdLFxuXHRcdFx0XHRyZXN1bHRzID0gW10sXG5cdFx0XHRcdG1hdGNoZXIgPSBjb21waWxlKCBzZWxlY3Rvci5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICkgKTtcblxuXHRcdFx0cmV0dXJuIG1hdGNoZXJbIGV4cGFuZG8gXSA/XG5cdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcywgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBlbGVtLFxuXHRcdFx0XHRcdFx0dW5tYXRjaGVkID0gbWF0Y2hlciggc2VlZCwgbnVsbCwgeG1sLCBbXSApLFxuXHRcdFx0XHRcdFx0aSA9IHNlZWQubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Ly8gTWF0Y2ggZWxlbWVudHMgdW5tYXRjaGVkIGJ5IGBtYXRjaGVyYFxuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdHNlZWRbaV0gPSAhKG1hdGNoZXNbaV0gPSBlbGVtKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pIDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdFx0XHRpbnB1dFswXSA9IGVsZW07XG5cdFx0XHRcdFx0bWF0Y2hlciggaW5wdXQsIG51bGwsIHhtbCwgcmVzdWx0cyApO1xuXHRcdFx0XHRcdC8vIERvbid0IGtlZXAgdGhlIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRcdFx0aW5wdXRbMF0gPSBudWxsO1xuXHRcdFx0XHRcdHJldHVybiAhcmVzdWx0cy5wb3AoKTtcblx0XHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiaGFzXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBTaXp6bGUoIHNlbGVjdG9yLCBlbGVtICkubGVuZ3RoID4gMDtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHRcImNvbnRhaW5zXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdHRleHQgPSB0ZXh0LnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lclRleHQgfHwgZ2V0VGV4dCggZWxlbSApICkuaW5kZXhPZiggdGV4dCApID4gLTE7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gXCJXaGV0aGVyIGFuIGVsZW1lbnQgaXMgcmVwcmVzZW50ZWQgYnkgYSA6bGFuZygpIHNlbGVjdG9yXG5cdFx0Ly8gaXMgYmFzZWQgc29sZWx5IG9uIHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWVcblx0XHQvLyBiZWluZyBlcXVhbCB0byB0aGUgaWRlbnRpZmllciBDLFxuXHRcdC8vIG9yIGJlZ2lubmluZyB3aXRoIHRoZSBpZGVudGlmaWVyIEMgaW1tZWRpYXRlbHkgZm9sbG93ZWQgYnkgXCItXCIuXG5cdFx0Ly8gVGhlIG1hdGNoaW5nIG9mIEMgYWdhaW5zdCB0aGUgZWxlbWVudCdzIGxhbmd1YWdlIHZhbHVlIGlzIHBlcmZvcm1lZCBjYXNlLWluc2Vuc2l0aXZlbHkuXG5cdFx0Ly8gVGhlIGlkZW50aWZpZXIgQyBkb2VzIG5vdCBoYXZlIHRvIGJlIGEgdmFsaWQgbGFuZ3VhZ2UgbmFtZS5cIlxuXHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jbGFuZy1wc2V1ZG9cblx0XHRcImxhbmdcIjogbWFya0Z1bmN0aW9uKCBmdW5jdGlvbiggbGFuZyApIHtcblx0XHRcdC8vIGxhbmcgdmFsdWUgbXVzdCBiZSBhIHZhbGlkIGlkZW50aWZpZXJcblx0XHRcdGlmICggIXJpZGVudGlmaWVyLnRlc3QobGFuZyB8fCBcIlwiKSApIHtcblx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIGxhbmc6IFwiICsgbGFuZyApO1xuXHRcdFx0fVxuXHRcdFx0bGFuZyA9IGxhbmcucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgZWxlbUxhbmc7XG5cdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtTGFuZyA9IGRvY3VtZW50SXNIVE1MID9cblx0XHRcdFx0XHRcdGVsZW0ubGFuZyA6XG5cdFx0XHRcdFx0XHRlbGVtLmdldEF0dHJpYnV0ZShcInhtbDpsYW5nXCIpIHx8IGVsZW0uZ2V0QXR0cmlidXRlKFwibGFuZ1wiKSkgKSB7XG5cblx0XHRcdFx0XHRcdGVsZW1MYW5nID0gZWxlbUxhbmcudG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtTGFuZyA9PT0gbGFuZyB8fCBlbGVtTGFuZy5pbmRleE9mKCBsYW5nICsgXCItXCIgKSA9PT0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gd2hpbGUgKCAoZWxlbSA9IGVsZW0ucGFyZW50Tm9kZSkgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gTWlzY2VsbGFuZW91c1xuXHRcdFwidGFyZ2V0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGhhc2ggPSB3aW5kb3cubG9jYXRpb24gJiYgd2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0XHRyZXR1cm4gaGFzaCAmJiBoYXNoLnNsaWNlKCAxICkgPT09IGVsZW0uaWQ7XG5cdFx0fSxcblxuXHRcdFwicm9vdFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBkb2NFbGVtO1xuXHRcdH0sXG5cblx0XHRcImZvY3VzXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKCFkb2N1bWVudC5oYXNGb2N1cyB8fCBkb2N1bWVudC5oYXNGb2N1cygpKSAmJiAhIShlbGVtLnR5cGUgfHwgZWxlbS5ocmVmIHx8IH5lbGVtLnRhYkluZGV4KTtcblx0XHR9LFxuXG5cdFx0Ly8gQm9vbGVhbiBwcm9wZXJ0aWVzXG5cdFx0XCJlbmFibGVkXCI6IGNyZWF0ZURpc2FibGVkUHNldWRvKCBmYWxzZSApLFxuXHRcdFwiZGlzYWJsZWRcIjogY3JlYXRlRGlzYWJsZWRQc2V1ZG8oIHRydWUgKSxcblxuXHRcdFwiY2hlY2tlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEluIENTUzMsIDpjaGVja2VkIHNob3VsZCByZXR1cm4gYm90aCBjaGVja2VkIGFuZCBzZWxlY3RlZCBlbGVtZW50c1xuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvMjAxMS9SRUMtY3NzMy1zZWxlY3RvcnMtMjAxMTA5MjkvI2NoZWNrZWRcblx0XHRcdHZhciBub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiAobm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiAhIWVsZW0uY2hlY2tlZCkgfHwgKG5vZGVOYW1lID09PSBcIm9wdGlvblwiICYmICEhZWxlbS5zZWxlY3RlZCk7XG5cdFx0fSxcblxuXHRcdFwic2VsZWN0ZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBBY2Nlc3NpbmcgdGhpcyBwcm9wZXJ0eSBtYWtlcyBzZWxlY3RlZC1ieS1kZWZhdWx0XG5cdFx0XHQvLyBvcHRpb25zIGluIFNhZmFyaSB3b3JrIHByb3Blcmx5XG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBlbGVtLnNlbGVjdGVkID09PSB0cnVlO1xuXHRcdH0sXG5cblx0XHQvLyBDb250ZW50c1xuXHRcdFwiZW1wdHlcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2VtcHR5LXBzZXVkb1xuXHRcdFx0Ly8gOmVtcHR5IGlzIG5lZ2F0ZWQgYnkgZWxlbWVudCAoMSkgb3IgY29udGVudCBub2RlcyAodGV4dDogMzsgY2RhdGE6IDQ7IGVudGl0eSByZWY6IDUpLFxuXHRcdFx0Ly8gICBidXQgbm90IGJ5IG90aGVycyAoY29tbWVudDogODsgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbjogNzsgZXRjLilcblx0XHRcdC8vIG5vZGVUeXBlIDwgNiB3b3JrcyBiZWNhdXNlIGF0dHJpYnV0ZXMgKDIpIGRvIG5vdCBhcHBlYXIgYXMgY2hpbGRyZW5cblx0XHRcdGZvciAoIGVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7IGVsZW07IGVsZW0gPSBlbGVtLm5leHRTaWJsaW5nICkge1xuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPCA2ICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblxuXHRcdFwicGFyZW50XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICFFeHByLnBzZXVkb3NbXCJlbXB0eVwiXSggZWxlbSApO1xuXHRcdH0sXG5cblx0XHQvLyBFbGVtZW50L2lucHV0IHR5cGVzXG5cdFx0XCJoZWFkZXJcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmhlYWRlci50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiaW5wdXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmlucHV0cy50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiYnV0dG9uXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIG5hbWUgPSBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gXCJidXR0b25cIiB8fCBuYW1lID09PSBcImJ1dHRvblwiO1xuXHRcdH0sXG5cblx0XHRcInRleHRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgYXR0cjtcblx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaW5wdXRcIiAmJlxuXHRcdFx0XHRlbGVtLnR5cGUgPT09IFwidGV4dFwiICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUU8OFxuXHRcdFx0XHQvLyBOZXcgSFRNTDUgYXR0cmlidXRlIHZhbHVlcyAoZS5nLiwgXCJzZWFyY2hcIikgYXBwZWFyIHdpdGggZWxlbS50eXBlID09PSBcInRleHRcIlxuXHRcdFx0XHQoIChhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpKSA9PSBudWxsIHx8IGF0dHIudG9Mb3dlckNhc2UoKSA9PT0gXCJ0ZXh0XCIgKTtcblx0XHR9LFxuXG5cdFx0Ly8gUG9zaXRpb24taW4tY29sbGVjdGlvblxuXHRcdFwiZmlyc3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBbIDAgXTtcblx0XHR9KSxcblxuXHRcdFwibGFzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHJldHVybiBbIGxlbmd0aCAtIDEgXTtcblx0XHR9KSxcblxuXHRcdFwiZXFcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0cmV0dXJuIFsgYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJldmVuXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0dmFyIGkgPSAwO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpICs9IDIgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJvZGRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDE7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcImx0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHZhciBpID0gYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudDtcblx0XHRcdGZvciAoIDsgLS1pID49IDA7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwiZ3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyArK2kgPCBsZW5ndGg7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KVxuXHR9XG59O1xuXG5FeHByLnBzZXVkb3NbXCJudGhcIl0gPSBFeHByLnBzZXVkb3NbXCJlcVwiXTtcblxuLy8gQWRkIGJ1dHRvbi9pbnB1dCB0eXBlIHBzZXVkb3NcbmZvciAoIGkgaW4geyByYWRpbzogdHJ1ZSwgY2hlY2tib3g6IHRydWUsIGZpbGU6IHRydWUsIHBhc3N3b3JkOiB0cnVlLCBpbWFnZTogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUlucHV0UHNldWRvKCBpICk7XG59XG5mb3IgKCBpIGluIHsgc3VibWl0OiB0cnVlLCByZXNldDogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUJ1dHRvblBzZXVkbyggaSApO1xufVxuXG4vLyBFYXN5IEFQSSBmb3IgY3JlYXRpbmcgbmV3IHNldEZpbHRlcnNcbmZ1bmN0aW9uIHNldEZpbHRlcnMoKSB7fVxuc2V0RmlsdGVycy5wcm90b3R5cGUgPSBFeHByLmZpbHRlcnMgPSBFeHByLnBzZXVkb3M7XG5FeHByLnNldEZpbHRlcnMgPSBuZXcgc2V0RmlsdGVycygpO1xuXG50b2tlbml6ZSA9IFNpenpsZS50b2tlbml6ZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgcGFyc2VPbmx5ICkge1xuXHR2YXIgbWF0Y2hlZCwgbWF0Y2gsIHRva2VucywgdHlwZSxcblx0XHRzb0ZhciwgZ3JvdXBzLCBwcmVGaWx0ZXJzLFxuXHRcdGNhY2hlZCA9IHRva2VuQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXTtcblxuXHRpZiAoIGNhY2hlZCApIHtcblx0XHRyZXR1cm4gcGFyc2VPbmx5ID8gMCA6IGNhY2hlZC5zbGljZSggMCApO1xuXHR9XG5cblx0c29GYXIgPSBzZWxlY3Rvcjtcblx0Z3JvdXBzID0gW107XG5cdHByZUZpbHRlcnMgPSBFeHByLnByZUZpbHRlcjtcblxuXHR3aGlsZSAoIHNvRmFyICkge1xuXG5cdFx0Ly8gQ29tbWEgYW5kIGZpcnN0IHJ1blxuXHRcdGlmICggIW1hdGNoZWQgfHwgKG1hdGNoID0gcmNvbW1hLmV4ZWMoIHNvRmFyICkpICkge1xuXHRcdFx0aWYgKCBtYXRjaCApIHtcblx0XHRcdFx0Ly8gRG9uJ3QgY29uc3VtZSB0cmFpbGluZyBjb21tYXMgYXMgdmFsaWRcblx0XHRcdFx0c29GYXIgPSBzb0Zhci5zbGljZSggbWF0Y2hbMF0ubGVuZ3RoICkgfHwgc29GYXI7XG5cdFx0XHR9XG5cdFx0XHRncm91cHMucHVzaCggKHRva2VucyA9IFtdKSApO1xuXHRcdH1cblxuXHRcdG1hdGNoZWQgPSBmYWxzZTtcblxuXHRcdC8vIENvbWJpbmF0b3JzXG5cdFx0aWYgKCAobWF0Y2ggPSByY29tYmluYXRvcnMuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0dmFsdWU6IG1hdGNoZWQsXG5cdFx0XHRcdC8vIENhc3QgZGVzY2VuZGFudCBjb21iaW5hdG9ycyB0byBzcGFjZVxuXHRcdFx0XHR0eXBlOiBtYXRjaFswXS5yZXBsYWNlKCBydHJpbSwgXCIgXCIgKVxuXHRcdFx0fSk7XG5cdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdH1cblxuXHRcdC8vIEZpbHRlcnNcblx0XHRmb3IgKCB0eXBlIGluIEV4cHIuZmlsdGVyICkge1xuXHRcdFx0aWYgKCAobWF0Y2ggPSBtYXRjaEV4cHJbIHR5cGUgXS5leGVjKCBzb0ZhciApKSAmJiAoIXByZUZpbHRlcnNbIHR5cGUgXSB8fFxuXHRcdFx0XHQobWF0Y2ggPSBwcmVGaWx0ZXJzWyB0eXBlIF0oIG1hdGNoICkpKSApIHtcblx0XHRcdFx0bWF0Y2hlZCA9IG1hdGNoLnNoaWZ0KCk7XG5cdFx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRcdG1hdGNoZXM6IG1hdGNoXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIW1hdGNoZWQgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHQvLyBSZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgaW52YWxpZCBleGNlc3Ncblx0Ly8gaWYgd2UncmUganVzdCBwYXJzaW5nXG5cdC8vIE90aGVyd2lzZSwgdGhyb3cgYW4gZXJyb3Igb3IgcmV0dXJuIHRva2Vuc1xuXHRyZXR1cm4gcGFyc2VPbmx5ID9cblx0XHRzb0Zhci5sZW5ndGggOlxuXHRcdHNvRmFyID9cblx0XHRcdFNpenpsZS5lcnJvciggc2VsZWN0b3IgKSA6XG5cdFx0XHQvLyBDYWNoZSB0aGUgdG9rZW5zXG5cdFx0XHR0b2tlbkNhY2hlKCBzZWxlY3RvciwgZ3JvdXBzICkuc2xpY2UoIDAgKTtcbn07XG5cbmZ1bmN0aW9uIHRvU2VsZWN0b3IoIHRva2VucyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGxlbiA9IHRva2Vucy5sZW5ndGgsXG5cdFx0c2VsZWN0b3IgPSBcIlwiO1xuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRzZWxlY3RvciArPSB0b2tlbnNbaV0udmFsdWU7XG5cdH1cblx0cmV0dXJuIHNlbGVjdG9yO1xufVxuXG5mdW5jdGlvbiBhZGRDb21iaW5hdG9yKCBtYXRjaGVyLCBjb21iaW5hdG9yLCBiYXNlICkge1xuXHR2YXIgZGlyID0gY29tYmluYXRvci5kaXIsXG5cdFx0c2tpcCA9IGNvbWJpbmF0b3IubmV4dCxcblx0XHRrZXkgPSBza2lwIHx8IGRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBrZXkgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGNsb3Nlc3QgYW5jZXN0b3IvcHJlY2VkaW5nIGVsZW1lbnRcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSA6XG5cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGFsbCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudHNcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCB1bmlxdWVDYWNoZSwgb3V0ZXJDYWNoZSxcblx0XHRcdFx0bmV3Q2FjaGUgPSBbIGRpcnJ1bnMsIGRvbmVOYW1lIF07XG5cblx0XHRcdC8vIFdlIGNhbid0IHNldCBhcmJpdHJhcnkgZGF0YSBvbiBYTUwgbm9kZXMsIHNvIHRoZXkgZG9uJ3QgYmVuZWZpdCBmcm9tIGNvbWJpbmF0b3IgY2FjaGluZ1xuXHRcdFx0aWYgKCB4bWwgKSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBlbGVtLnVuaXF1ZUlEIF0gfHwgKG91dGVyQ2FjaGVbIGVsZW0udW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0aWYgKCBza2lwICYmIHNraXAgPT09IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSApIHtcblx0XHRcdFx0XHRcdFx0ZWxlbSA9IGVsZW1bIGRpciBdIHx8IGVsZW07XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCAob2xkQ2FjaGUgPSB1bmlxdWVDYWNoZVsga2V5IF0pICYmXG5cdFx0XHRcdFx0XHRcdG9sZENhY2hlWyAwIF0gPT09IGRpcnJ1bnMgJiYgb2xkQ2FjaGVbIDEgXSA9PT0gZG9uZU5hbWUgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQXNzaWduIHRvIG5ld0NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0cmV0dXJuIChuZXdDYWNoZVsgMiBdID0gb2xkQ2FjaGVbIDIgXSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXVzZSBuZXdjYWNoZSBzbyByZXN1bHRzIGJhY2stcHJvcGFnYXRlIHRvIHByZXZpb3VzIGVsZW1lbnRzXG5cdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyBrZXkgXSA9IG5ld0NhY2hlO1xuXG5cdFx0XHRcdFx0XHRcdC8vIEEgbWF0Y2ggbWVhbnMgd2UncmUgZG9uZTsgYSBmYWlsIG1lYW5zIHdlIGhhdmUgdG8ga2VlcCBjaGVja2luZ1xuXHRcdFx0XHRcdFx0XHRpZiAoIChuZXdDYWNoZVsgMiBdID0gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkpICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcbn1cblxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICkge1xuXHRyZXR1cm4gbWF0Y2hlcnMubGVuZ3RoID4gMSA/XG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciBpID0gbWF0Y2hlcnMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggIW1hdGNoZXJzW2ldKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gOlxuXHRcdG1hdGNoZXJzWzBdO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciwgY29udGV4dHMsIHJlc3VsdHMgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBjb250ZXh0cy5sZW5ndGg7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHRzW2ldLCByZXN1bHRzICk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdHM7XG59XG5cbmZ1bmN0aW9uIGNvbmRlbnNlKCB1bm1hdGNoZWQsIG1hcCwgZmlsdGVyLCBjb250ZXh0LCB4bWwgKSB7XG5cdHZhciBlbGVtLFxuXHRcdG5ld1VubWF0Y2hlZCA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGxlbiA9IHVubWF0Y2hlZC5sZW5ndGgsXG5cdFx0bWFwcGVkID0gbWFwICE9IG51bGw7XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRpZiAoICFmaWx0ZXIgfHwgZmlsdGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0bmV3VW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0aWYgKCBtYXBwZWQgKSB7XG5cdFx0XHRcdFx0bWFwLnB1c2goIGkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBuZXdVbm1hdGNoZWQ7XG59XG5cbmZ1bmN0aW9uIHNldE1hdGNoZXIoIHByZUZpbHRlciwgc2VsZWN0b3IsIG1hdGNoZXIsIHBvc3RGaWx0ZXIsIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApIHtcblx0aWYgKCBwb3N0RmlsdGVyICYmICFwb3N0RmlsdGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbHRlciA9IHNldE1hdGNoZXIoIHBvc3RGaWx0ZXIgKTtcblx0fVxuXHRpZiAoIHBvc3RGaW5kZXIgJiYgIXBvc3RGaW5kZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmluZGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICk7XG5cdH1cblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgcmVzdWx0cywgY29udGV4dCwgeG1sICkge1xuXHRcdHZhciB0ZW1wLCBpLCBlbGVtLFxuXHRcdFx0cHJlTWFwID0gW10sXG5cdFx0XHRwb3N0TWFwID0gW10sXG5cdFx0XHRwcmVleGlzdGluZyA9IHJlc3VsdHMubGVuZ3RoLFxuXG5cdFx0XHQvLyBHZXQgaW5pdGlhbCBlbGVtZW50cyBmcm9tIHNlZWQgb3IgY29udGV4dFxuXHRcdFx0ZWxlbXMgPSBzZWVkIHx8IG11bHRpcGxlQ29udGV4dHMoIHNlbGVjdG9yIHx8IFwiKlwiLCBjb250ZXh0Lm5vZGVUeXBlID8gWyBjb250ZXh0IF0gOiBjb250ZXh0LCBbXSApLFxuXG5cdFx0XHQvLyBQcmVmaWx0ZXIgdG8gZ2V0IG1hdGNoZXIgaW5wdXQsIHByZXNlcnZpbmcgYSBtYXAgZm9yIHNlZWQtcmVzdWx0cyBzeW5jaHJvbml6YXRpb25cblx0XHRcdG1hdGNoZXJJbiA9IHByZUZpbHRlciAmJiAoIHNlZWQgfHwgIXNlbGVjdG9yICkgP1xuXHRcdFx0XHRjb25kZW5zZSggZWxlbXMsIHByZU1hcCwgcHJlRmlsdGVyLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdGVsZW1zLFxuXG5cdFx0XHRtYXRjaGVyT3V0ID0gbWF0Y2hlciA/XG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgYSBwb3N0RmluZGVyLCBvciBmaWx0ZXJlZCBzZWVkLCBvciBub24tc2VlZCBwb3N0RmlsdGVyIG9yIHByZWV4aXN0aW5nIHJlc3VsdHMsXG5cdFx0XHRcdHBvc3RGaW5kZXIgfHwgKCBzZWVkID8gcHJlRmlsdGVyIDogcHJlZXhpc3RpbmcgfHwgcG9zdEZpbHRlciApID9cblxuXHRcdFx0XHRcdC8vIC4uLmludGVybWVkaWF0ZSBwcm9jZXNzaW5nIGlzIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdFtdIDpcblxuXHRcdFx0XHRcdC8vIC4uLm90aGVyd2lzZSB1c2UgcmVzdWx0cyBkaXJlY3RseVxuXHRcdFx0XHRcdHJlc3VsdHMgOlxuXHRcdFx0XHRtYXRjaGVySW47XG5cblx0XHQvLyBGaW5kIHByaW1hcnkgbWF0Y2hlc1xuXHRcdGlmICggbWF0Y2hlciApIHtcblx0XHRcdG1hdGNoZXIoIG1hdGNoZXJJbiwgbWF0Y2hlck91dCwgY29udGV4dCwgeG1sICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgcG9zdEZpbHRlclxuXHRcdGlmICggcG9zdEZpbHRlciApIHtcblx0XHRcdHRlbXAgPSBjb25kZW5zZSggbWF0Y2hlck91dCwgcG9zdE1hcCApO1xuXHRcdFx0cG9zdEZpbHRlciggdGVtcCwgW10sIGNvbnRleHQsIHhtbCApO1xuXG5cdFx0XHQvLyBVbi1tYXRjaCBmYWlsaW5nIGVsZW1lbnRzIGJ5IG1vdmluZyB0aGVtIGJhY2sgdG8gbWF0Y2hlckluXG5cdFx0XHRpID0gdGVtcC5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAoZWxlbSA9IHRlbXBbaV0pICkge1xuXHRcdFx0XHRcdG1hdGNoZXJPdXRbIHBvc3RNYXBbaV0gXSA9ICEobWF0Y2hlckluWyBwb3N0TWFwW2ldIF0gPSBlbGVtKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggc2VlZCApIHtcblx0XHRcdGlmICggcG9zdEZpbmRlciB8fCBwcmVGaWx0ZXIgKSB7XG5cdFx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIGZpbmFsIG1hdGNoZXJPdXQgYnkgY29uZGVuc2luZyB0aGlzIGludGVybWVkaWF0ZSBpbnRvIHBvc3RGaW5kZXIgY29udGV4dHNcblx0XHRcdFx0XHR0ZW1wID0gW107XG5cdFx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIG1hdGNoZXJJbiBzaW5jZSBlbGVtIGlzIG5vdCB5ZXQgYSBmaW5hbCBtYXRjaFxuXHRcdFx0XHRcdFx0XHR0ZW1wLnB1c2goIChtYXRjaGVySW5baV0gPSBlbGVtKSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCAobWF0Y2hlck91dCA9IFtdKSwgdGVtcCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBNb3ZlIG1hdGNoZWQgZWxlbWVudHMgZnJvbSBzZWVkIHRvIHJlc3VsdHMgdG8ga2VlcCB0aGVtIHN5bmNocm9uaXplZFxuXHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSAmJlxuXHRcdFx0XHRcdFx0KHRlbXAgPSBwb3N0RmluZGVyID8gaW5kZXhPZiggc2VlZCwgZWxlbSApIDogcHJlTWFwW2ldKSA+IC0xICkge1xuXG5cdFx0XHRcdFx0XHRzZWVkW3RlbXBdID0gIShyZXN1bHRzW3RlbXBdID0gZWxlbSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBBZGQgZWxlbWVudHMgdG8gcmVzdWx0cywgdGhyb3VnaCBwb3N0RmluZGVyIGlmIGRlZmluZWRcblx0XHR9IGVsc2Uge1xuXHRcdFx0bWF0Y2hlck91dCA9IGNvbmRlbnNlKFxuXHRcdFx0XHRtYXRjaGVyT3V0ID09PSByZXN1bHRzID9cblx0XHRcdFx0XHRtYXRjaGVyT3V0LnNwbGljZSggcHJlZXhpc3RpbmcsIG1hdGNoZXJPdXQubGVuZ3RoICkgOlxuXHRcdFx0XHRcdG1hdGNoZXJPdXRcblx0XHRcdCk7XG5cdFx0XHRpZiAoIHBvc3RGaW5kZXIgKSB7XG5cdFx0XHRcdHBvc3RGaW5kZXIoIG51bGwsIHJlc3VsdHMsIG1hdGNoZXJPdXQsIHhtbCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgbWF0Y2hlck91dCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMgKSB7XG5cdHZhciBjaGVja0NvbnRleHQsIG1hdGNoZXIsIGosXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRsZWFkaW5nUmVsYXRpdmUgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbMF0udHlwZSBdLFxuXHRcdGltcGxpY2l0UmVsYXRpdmUgPSBsZWFkaW5nUmVsYXRpdmUgfHwgRXhwci5yZWxhdGl2ZVtcIiBcIl0sXG5cdFx0aSA9IGxlYWRpbmdSZWxhdGl2ZSA/IDEgOiAwLFxuXG5cdFx0Ly8gVGhlIGZvdW5kYXRpb25hbCBtYXRjaGVyIGVuc3VyZXMgdGhhdCBlbGVtZW50cyBhcmUgcmVhY2hhYmxlIGZyb20gdG9wLWxldmVsIGNvbnRleHQocylcblx0XHRtYXRjaENvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBjaGVja0NvbnRleHQ7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoQW55Q29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YoIGNoZWNrQ29udGV4dCwgZWxlbSApID4gLTE7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoZXJzID0gWyBmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIHJldCA9ICggIWxlYWRpbmdSZWxhdGl2ZSAmJiAoIHhtbCB8fCBjb250ZXh0ICE9PSBvdXRlcm1vc3RDb250ZXh0ICkgKSB8fCAoXG5cdFx0XHRcdChjaGVja0NvbnRleHQgPSBjb250ZXh0KS5ub2RlVHlwZSA/XG5cdFx0XHRcdFx0bWF0Y2hDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdFx0bWF0Y2hBbnlDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSApO1xuXHRcdFx0Ly8gQXZvaWQgaGFuZ2luZyBvbnRvIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRjaGVja0NvbnRleHQgPSBudWxsO1xuXHRcdFx0cmV0dXJuIHJldDtcblx0XHR9IF07XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAobWF0Y2hlciA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1tpXS50eXBlIF0pICkge1xuXHRcdFx0bWF0Y2hlcnMgPSBbIGFkZENvbWJpbmF0b3IoZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksIG1hdGNoZXIpIF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hdGNoZXIgPSBFeHByLmZpbHRlclsgdG9rZW5zW2ldLnR5cGUgXS5hcHBseSggbnVsbCwgdG9rZW5zW2ldLm1hdGNoZXMgKTtcblxuXHRcdFx0Ly8gUmV0dXJuIHNwZWNpYWwgdXBvbiBzZWVpbmcgYSBwb3NpdGlvbmFsIG1hdGNoZXJcblx0XHRcdGlmICggbWF0Y2hlclsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHQvLyBGaW5kIHRoZSBuZXh0IHJlbGF0aXZlIG9wZXJhdG9yIChpZiBhbnkpIGZvciBwcm9wZXIgaGFuZGxpbmdcblx0XHRcdFx0aiA9ICsraTtcblx0XHRcdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyB0b2tlbnNbal0udHlwZSBdICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBzZXRNYXRjaGVyKFxuXHRcdFx0XHRcdGkgPiAxICYmIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLFxuXHRcdFx0XHRcdGkgPiAxICYmIHRvU2VsZWN0b3IoXG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgcHJlY2VkaW5nIHRva2VuIHdhcyBhIGRlc2NlbmRhbnQgY29tYmluYXRvciwgaW5zZXJ0IGFuIGltcGxpY2l0IGFueS1lbGVtZW50IGAqYFxuXHRcdFx0XHRcdFx0dG9rZW5zLnNsaWNlKCAwLCBpIC0gMSApLmNvbmNhdCh7IHZhbHVlOiB0b2tlbnNbIGkgLSAyIF0udHlwZSA9PT0gXCIgXCIgPyBcIipcIiA6IFwiXCIgfSlcblx0XHRcdFx0XHQpLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSxcblx0XHRcdFx0XHRtYXRjaGVyLFxuXHRcdFx0XHRcdGkgPCBqICYmIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMuc2xpY2UoIGksIGogKSApLFxuXHRcdFx0XHRcdGogPCBsZW4gJiYgbWF0Y2hlckZyb21Ub2tlbnMoICh0b2tlbnMgPSB0b2tlbnMuc2xpY2UoIGogKSkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIHRvU2VsZWN0b3IoIHRva2VucyApXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVycy5wdXNoKCBtYXRjaGVyICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSB7XG5cdHZhciBieVNldCA9IHNldE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0YnlFbGVtZW50ID0gZWxlbWVudE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0c3VwZXJNYXRjaGVyID0gZnVuY3Rpb24oIHNlZWQsIGNvbnRleHQsIHhtbCwgcmVzdWx0cywgb3V0ZXJtb3N0ICkge1xuXHRcdFx0dmFyIGVsZW0sIGosIG1hdGNoZXIsXG5cdFx0XHRcdG1hdGNoZWRDb3VudCA9IDAsXG5cdFx0XHRcdGkgPSBcIjBcIixcblx0XHRcdFx0dW5tYXRjaGVkID0gc2VlZCAmJiBbXSxcblx0XHRcdFx0c2V0TWF0Y2hlZCA9IFtdLFxuXHRcdFx0XHRjb250ZXh0QmFja3VwID0gb3V0ZXJtb3N0Q29udGV4dCxcblx0XHRcdFx0Ly8gV2UgbXVzdCBhbHdheXMgaGF2ZSBlaXRoZXIgc2VlZCBlbGVtZW50cyBvciBvdXRlcm1vc3QgY29udGV4dFxuXHRcdFx0XHRlbGVtcyA9IHNlZWQgfHwgYnlFbGVtZW50ICYmIEV4cHIuZmluZFtcIlRBR1wiXSggXCIqXCIsIG91dGVybW9zdCApLFxuXHRcdFx0XHQvLyBVc2UgaW50ZWdlciBkaXJydW5zIGlmZiB0aGlzIGlzIHRoZSBvdXRlcm1vc3QgbWF0Y2hlclxuXHRcdFx0XHRkaXJydW5zVW5pcXVlID0gKGRpcnJ1bnMgKz0gY29udGV4dEJhY2t1cCA9PSBudWxsID8gMSA6IE1hdGgucmFuZG9tKCkgfHwgMC4xKSxcblx0XHRcdFx0bGVuID0gZWxlbXMubGVuZ3RoO1xuXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0b3V0ZXJtb3N0Q29udGV4dCA9IGNvbnRleHQgPT09IGRvY3VtZW50IHx8IGNvbnRleHQgfHwgb3V0ZXJtb3N0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgZWxlbWVudHMgcGFzc2luZyBlbGVtZW50TWF0Y2hlcnMgZGlyZWN0bHkgdG8gcmVzdWx0c1xuXHRcdFx0Ly8gU3VwcG9ydDogSUU8OSwgU2FmYXJpXG5cdFx0XHQvLyBUb2xlcmF0ZSBOb2RlTGlzdCBwcm9wZXJ0aWVzIChJRTogXCJsZW5ndGhcIjsgU2FmYXJpOiA8bnVtYmVyPikgbWF0Y2hpbmcgZWxlbWVudHMgYnkgaWRcblx0XHRcdGZvciAoIDsgaSAhPT0gbGVuICYmIChlbGVtID0gZWxlbXNbaV0pICE9IG51bGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBieUVsZW1lbnQgJiYgZWxlbSApIHtcblx0XHRcdFx0XHRqID0gMDtcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0ICYmIGVsZW0ub3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHRcdFx0XHRcdFx0eG1sID0gIWRvY3VtZW50SXNIVE1MO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR3aGlsZSAoIChtYXRjaGVyID0gZWxlbWVudE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVyKCBlbGVtLCBjb250ZXh0IHx8IGRvY3VtZW50LCB4bWwpICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHJhY2sgdW5tYXRjaGVkIGVsZW1lbnRzIGZvciBzZXQgZmlsdGVyc1xuXHRcdFx0XHRpZiAoIGJ5U2V0ICkge1xuXHRcdFx0XHRcdC8vIFRoZXkgd2lsbCBoYXZlIGdvbmUgdGhyb3VnaCBhbGwgcG9zc2libGUgbWF0Y2hlcnNcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBMZW5ndGhlbiB0aGUgYXJyYXkgZm9yIGV2ZXJ5IGVsZW1lbnQsIG1hdGNoZWQgb3Igbm90XG5cdFx0XHRcdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0XHRcdFx0dW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYGlgIGlzIG5vdyB0aGUgY291bnQgb2YgZWxlbWVudHMgdmlzaXRlZCBhYm92ZSwgYW5kIGFkZGluZyBpdCB0byBgbWF0Y2hlZENvdW50YFxuXHRcdFx0Ly8gbWFrZXMgdGhlIGxhdHRlciBub25uZWdhdGl2ZS5cblx0XHRcdG1hdGNoZWRDb3VudCArPSBpO1xuXG5cdFx0XHQvLyBBcHBseSBzZXQgZmlsdGVycyB0byB1bm1hdGNoZWQgZWxlbWVudHNcblx0XHRcdC8vIE5PVEU6IFRoaXMgY2FuIGJlIHNraXBwZWQgaWYgdGhlcmUgYXJlIG5vIHVubWF0Y2hlZCBlbGVtZW50cyAoaS5lLiwgYG1hdGNoZWRDb3VudGBcblx0XHRcdC8vIGVxdWFscyBgaWApLCB1bmxlc3Mgd2UgZGlkbid0IHZpc2l0IF9hbnlfIGVsZW1lbnRzIGluIHRoZSBhYm92ZSBsb29wIGJlY2F1c2Ugd2UgaGF2ZVxuXHRcdFx0Ly8gbm8gZWxlbWVudCBtYXRjaGVycyBhbmQgbm8gc2VlZC5cblx0XHRcdC8vIEluY3JlbWVudGluZyBhbiBpbml0aWFsbHktc3RyaW5nIFwiMFwiIGBpYCBhbGxvd3MgYGlgIHRvIHJlbWFpbiBhIHN0cmluZyBvbmx5IGluIHRoYXRcblx0XHRcdC8vIGNhc2UsIHdoaWNoIHdpbGwgcmVzdWx0IGluIGEgXCIwMFwiIGBtYXRjaGVkQ291bnRgIHRoYXQgZGlmZmVycyBmcm9tIGBpYCBidXQgaXMgYWxzb1xuXHRcdFx0Ly8gbnVtZXJpY2FsbHkgemVyby5cblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0Ly8gUmVpbnRlZ3JhdGUgZWxlbWVudCBtYXRjaGVzIHRvIGVsaW1pbmF0ZSB0aGUgbmVlZCBmb3Igc29ydGluZ1xuXHRcdFx0XHRcdGlmICggbWF0Y2hlZENvdW50ID4gMCApIHtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoICEodW5tYXRjaGVkW2ldIHx8IHNldE1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRcdHNldE1hdGNoZWRbaV0gPSBwb3AuY2FsbCggcmVzdWx0cyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRGlzY2FyZCBpbmRleCBwbGFjZWhvbGRlciB2YWx1ZXMgdG8gZ2V0IG9ubHkgYWN0dWFsIG1hdGNoZXNcblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBtYXRjaGVzIHRvIHJlc3VsdHNcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2V0TWF0Y2hlZCApO1xuXG5cdFx0XHRcdC8vIFNlZWRsZXNzIHNldCBtYXRjaGVzIHN1Y2NlZWRpbmcgbXVsdGlwbGUgc3VjY2Vzc2Z1bCBtYXRjaGVycyBzdGlwdWxhdGUgc29ydGluZ1xuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gT3ZlcnJpZGUgbWFuaXB1bGF0aW9uIG9mIGdsb2JhbHMgYnkgbmVzdGVkIG1hdGNoZXJzXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0QmFja3VwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdW5tYXRjaGVkO1xuXHRcdH07XG5cblx0cmV0dXJuIGJ5U2V0ID9cblx0XHRtYXJrRnVuY3Rpb24oIHN1cGVyTWF0Y2hlciApIDpcblx0XHRzdXBlck1hdGNoZXI7XG59XG5cbmNvbXBpbGUgPSBTaXp6bGUuY29tcGlsZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgbWF0Y2ggLyogSW50ZXJuYWwgVXNlIE9ubHkgKi8gKSB7XG5cdHZhciBpLFxuXHRcdHNldE1hdGNoZXJzID0gW10sXG5cdFx0ZWxlbWVudE1hdGNoZXJzID0gW10sXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggIWNhY2hlZCApIHtcblx0XHQvLyBHZW5lcmF0ZSBhIGZ1bmN0aW9uIG9mIHJlY3Vyc2l2ZSBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBjaGVjayBlYWNoIGVsZW1lbnRcblx0XHRpZiAoICFtYXRjaCApIHtcblx0XHRcdG1hdGNoID0gdG9rZW5pemUoIHNlbGVjdG9yICk7XG5cdFx0fVxuXHRcdGkgPSBtYXRjaC5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRjYWNoZWQgPSBtYXRjaGVyRnJvbVRva2VucyggbWF0Y2hbaV0gKTtcblx0XHRcdGlmICggY2FjaGVkWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdHNldE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENhY2hlIHRoZSBjb21waWxlZCBmdW5jdGlvblxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGUoIHNlbGVjdG9yLCBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSApO1xuXG5cdFx0Ly8gU2F2ZSBzZWxlY3RvciBhbmQgdG9rZW5pemF0aW9uXG5cdFx0Y2FjaGVkLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdH1cblx0cmV0dXJuIGNhY2hlZDtcbn07XG5cbi8qKlxuICogQSBsb3ctbGV2ZWwgc2VsZWN0aW9uIGZ1bmN0aW9uIHRoYXQgd29ya3Mgd2l0aCBTaXp6bGUncyBjb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHNlbGVjdG9yIEEgc2VsZWN0b3Igb3IgYSBwcmUtY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbiBidWlsdCB3aXRoIFNpenpsZS5jb21waWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHRzXVxuICogQHBhcmFtIHtBcnJheX0gW3NlZWRdIEEgc2V0IG9mIGVsZW1lbnRzIHRvIG1hdGNoIGFnYWluc3RcbiAqL1xuc2VsZWN0ID0gU2l6emxlLnNlbGVjdCA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIGksIHRva2VucywgdG9rZW4sIHR5cGUsIGZpbmQsXG5cdFx0Y29tcGlsZWQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiAmJiBzZWxlY3Rvcixcblx0XHRtYXRjaCA9ICFzZWVkICYmIHRva2VuaXplKCAoc2VsZWN0b3IgPSBjb21waWxlZC5zZWxlY3RvciB8fCBzZWxlY3RvcikgKTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBUcnkgdG8gbWluaW1pemUgb3BlcmF0aW9ucyBpZiB0aGVyZSBpcyBvbmx5IG9uZSBzZWxlY3RvciBpbiB0aGUgbGlzdCBhbmQgbm8gc2VlZFxuXHQvLyAodGhlIGxhdHRlciBvZiB3aGljaCBndWFyYW50ZWVzIHVzIGNvbnRleHQpXG5cdGlmICggbWF0Y2gubGVuZ3RoID09PSAxICkge1xuXG5cdFx0Ly8gUmVkdWNlIGNvbnRleHQgaWYgdGhlIGxlYWRpbmcgY29tcG91bmQgc2VsZWN0b3IgaXMgYW4gSURcblx0XHR0b2tlbnMgPSBtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwICk7XG5cdFx0aWYgKCB0b2tlbnMubGVuZ3RoID4gMiAmJiAodG9rZW4gPSB0b2tlbnNbMF0pLnR5cGUgPT09IFwiSURcIiAmJlxuXHRcdFx0XHRjb250ZXh0Lm5vZGVUeXBlID09PSA5ICYmIGRvY3VtZW50SXNIVE1MICYmIEV4cHIucmVsYXRpdmVbIHRva2Vuc1sxXS50eXBlIF0gKSB7XG5cblx0XHRcdGNvbnRleHQgPSAoIEV4cHIuZmluZFtcIklEXCJdKCB0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UocnVuZXNjYXBlLCBmdW5lc2NhcGUpLCBjb250ZXh0ICkgfHwgW10gKVswXTtcblx0XHRcdGlmICggIWNvbnRleHQgKSB7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXG5cdFx0XHQvLyBQcmVjb21waWxlZCBtYXRjaGVycyB3aWxsIHN0aWxsIHZlcmlmeSBhbmNlc3RyeSwgc28gc3RlcCB1cCBhIGxldmVsXG5cdFx0XHR9IGVsc2UgaWYgKCBjb21waWxlZCApIHtcblx0XHRcdFx0Y29udGV4dCA9IGNvbnRleHQucGFyZW50Tm9kZTtcblx0XHRcdH1cblxuXHRcdFx0c2VsZWN0b3IgPSBzZWxlY3Rvci5zbGljZSggdG9rZW5zLnNoaWZ0KCkudmFsdWUubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmV0Y2ggYSBzZWVkIHNldCBmb3IgcmlnaHQtdG8tbGVmdCBtYXRjaGluZ1xuXHRcdGkgPSBtYXRjaEV4cHJbXCJuZWVkc0NvbnRleHRcIl0udGVzdCggc2VsZWN0b3IgKSA/IDAgOiB0b2tlbnMubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG9rZW4gPSB0b2tlbnNbaV07XG5cblx0XHRcdC8vIEFib3J0IGlmIHdlIGhpdCBhIGNvbWJpbmF0b3Jcblx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgKHR5cGUgPSB0b2tlbi50eXBlKSBdICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggKGZpbmQgPSBFeHByLmZpbmRbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdC8vIFNlYXJjaCwgZXhwYW5kaW5nIGNvbnRleHQgZm9yIGxlYWRpbmcgc2libGluZyBjb21iaW5hdG9yc1xuXHRcdFx0XHRpZiAoIChzZWVkID0gZmluZChcblx0XHRcdFx0XHR0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICksXG5cdFx0XHRcdFx0cnNpYmxpbmcudGVzdCggdG9rZW5zWzBdLnR5cGUgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHRcdFx0XHQpKSApIHtcblxuXHRcdFx0XHRcdC8vIElmIHNlZWQgaXMgZW1wdHkgb3Igbm8gdG9rZW5zIHJlbWFpbiwgd2UgY2FuIHJldHVybiBlYXJseVxuXHRcdFx0XHRcdHRva2Vucy5zcGxpY2UoIGksIDEgKTtcblx0XHRcdFx0XHRzZWxlY3RvciA9IHNlZWQubGVuZ3RoICYmIHRvU2VsZWN0b3IoIHRva2VucyApO1xuXHRcdFx0XHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2VlZCApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDb21waWxlIGFuZCBleGVjdXRlIGEgZmlsdGVyaW5nIGZ1bmN0aW9uIGlmIG9uZSBpcyBub3QgcHJvdmlkZWRcblx0Ly8gUHJvdmlkZSBgbWF0Y2hgIHRvIGF2b2lkIHJldG9rZW5pemF0aW9uIGlmIHdlIG1vZGlmaWVkIHRoZSBzZWxlY3RvciBhYm92ZVxuXHQoIGNvbXBpbGVkIHx8IGNvbXBpbGUoIHNlbGVjdG9yLCBtYXRjaCApICkoXG5cdFx0c2VlZCxcblx0XHRjb250ZXh0LFxuXHRcdCFkb2N1bWVudElzSFRNTCxcblx0XHRyZXN1bHRzLFxuXHRcdCFjb250ZXh0IHx8IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHRcblx0KTtcblx0cmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vLyBPbmUtdGltZSBhc3NpZ25tZW50c1xuXG4vLyBTb3J0IHN0YWJpbGl0eVxuc3VwcG9ydC5zb3J0U3RhYmxlID0gZXhwYW5kby5zcGxpdChcIlwiKS5zb3J0KCBzb3J0T3JkZXIgKS5qb2luKFwiXCIpID09PSBleHBhbmRvO1xuXG4vLyBTdXBwb3J0OiBDaHJvbWUgMTQtMzUrXG4vLyBBbHdheXMgYXNzdW1lIGR1cGxpY2F0ZXMgaWYgdGhleSBhcmVuJ3QgcGFzc2VkIHRvIHRoZSBjb21wYXJpc29uIGZ1bmN0aW9uXG5zdXBwb3J0LmRldGVjdER1cGxpY2F0ZXMgPSAhIWhhc0R1cGxpY2F0ZTtcblxuLy8gSW5pdGlhbGl6ZSBhZ2FpbnN0IHRoZSBkZWZhdWx0IGRvY3VtZW50XG5zZXREb2N1bWVudCgpO1xuXG4vLyBTdXBwb3J0OiBXZWJraXQ8NTM3LjMyIC0gU2FmYXJpIDYuMC4zL0Nocm9tZSAyNSAoZml4ZWQgaW4gQ2hyb21lIDI3KVxuLy8gRGV0YWNoZWQgbm9kZXMgY29uZm91bmRpbmdseSBmb2xsb3cgKmVhY2ggb3RoZXIqXG5zdXBwb3J0LnNvcnREZXRhY2hlZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdC8vIFNob3VsZCByZXR1cm4gMSwgYnV0IHJldHVybnMgNCAoZm9sbG93aW5nKVxuXHRyZXR1cm4gZWwuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJmaWVsZHNldFwiKSApICYgMTtcbn0pO1xuXG4vLyBTdXBwb3J0OiBJRTw4XG4vLyBQcmV2ZW50IGF0dHJpYnV0ZS9wcm9wZXJ0eSBcImludGVycG9sYXRpb25cIlxuLy8gaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNjQyOSUyOFZTLjg1JTI5LmFzcHhcbmlmICggIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGEgaHJlZj0nIyc+PC9hPlwiO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZGVmYXVsdFZhbHVlIGluIHBsYWNlIG9mIGdldEF0dHJpYnV0ZShcInZhbHVlXCIpXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGlucHV0Lz5cIjtcblx0ZWwuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiApID09PSBcIlwiO1xufSkgKSB7XG5cdGFkZEhhbmRsZSggXCJ2YWx1ZVwiLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0aWYgKCAhaXNYTUwgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlucHV0XCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kZWZhdWx0VmFsdWU7XG5cdFx0fVxuXHR9KTtcbn1cblxuLy8gU3VwcG9ydDogSUU8OVxuLy8gVXNlIGdldEF0dHJpYnV0ZU5vZGUgdG8gZmV0Y2ggYm9vbGVhbnMgd2hlbiBnZXRBdHRyaWJ1dGUgbGllc1xuaWYgKCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0cmV0dXJuIGVsLmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxucmV0dXJuIFNpenpsZTtcblxufSkoIHdpbmRvdyApO1xuXG5cblxualF1ZXJ5LmZpbmQgPSBTaXp6bGU7XG5qUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7XG5cbi8vIERlcHJlY2F0ZWRcbmpRdWVyeS5leHByWyBcIjpcIiBdID0galF1ZXJ5LmV4cHIucHNldWRvcztcbmpRdWVyeS51bmlxdWVTb3J0ID0galF1ZXJ5LnVuaXF1ZSA9IFNpenpsZS51bmlxdWVTb3J0O1xualF1ZXJ5LnRleHQgPSBTaXp6bGUuZ2V0VGV4dDtcbmpRdWVyeS5pc1hNTERvYyA9IFNpenpsZS5pc1hNTDtcbmpRdWVyeS5jb250YWlucyA9IFNpenpsZS5jb250YWlucztcbmpRdWVyeS5lc2NhcGVTZWxlY3RvciA9IFNpenpsZS5lc2NhcGU7XG5cblxuXG5cbnZhciBkaXIgPSBmdW5jdGlvbiggZWxlbSwgZGlyLCB1bnRpbCApIHtcblx0dmFyIG1hdGNoZWQgPSBbXSxcblx0XHR0cnVuY2F0ZSA9IHVudGlsICE9PSB1bmRlZmluZWQ7XG5cblx0d2hpbGUgKCAoIGVsZW0gPSBlbGVtWyBkaXIgXSApICYmIGVsZW0ubm9kZVR5cGUgIT09IDkgKSB7XG5cdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0aWYgKCB0cnVuY2F0ZSAmJiBqUXVlcnkoIGVsZW0gKS5pcyggdW50aWwgKSApIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG1hdGNoZWQ7XG59O1xuXG5cbnZhciBzaWJsaW5ncyA9IGZ1bmN0aW9uKCBuLCBlbGVtICkge1xuXHR2YXIgbWF0Y2hlZCA9IFtdO1xuXG5cdGZvciAoIDsgbjsgbiA9IG4ubmV4dFNpYmxpbmcgKSB7XG5cdFx0aWYgKCBuLm5vZGVUeXBlID09PSAxICYmIG4gIT09IGVsZW0gKSB7XG5cdFx0XHRtYXRjaGVkLnB1c2goIG4gKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbWF0Y2hlZDtcbn07XG5cblxudmFyIHJuZWVkc0NvbnRleHQgPSBqUXVlcnkuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQ7XG5cblxuXG5mdW5jdGlvbiBub2RlTmFtZSggZWxlbSwgbmFtZSApIHtcblxuICByZXR1cm4gZWxlbS5ub2RlTmFtZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUudG9Mb3dlckNhc2UoKTtcblxufTtcbnZhciByc2luZ2xlVGFnID0gKCAvXjwoW2Etel1bXlxcL1xcMD46XFx4MjBcXHRcXHJcXG5cXGZdKilbXFx4MjBcXHRcXHJcXG5cXGZdKlxcLz8+KD86PFxcL1xcMT58KSQvaSApO1xuXG5cblxudmFyIHJpc1NpbXBsZSA9IC9eLlteOiNcXFtcXC4sXSokLztcblxuLy8gSW1wbGVtZW50IHRoZSBpZGVudGljYWwgZnVuY3Rpb25hbGl0eSBmb3IgZmlsdGVyIGFuZCBub3RcbmZ1bmN0aW9uIHdpbm5vdyggZWxlbWVudHMsIHF1YWxpZmllciwgbm90ICkge1xuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiAhIXF1YWxpZmllci5jYWxsKCBlbGVtLCBpLCBlbGVtICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBTaW5nbGUgZWxlbWVudFxuXHRpZiAoIHF1YWxpZmllci5ub2RlVHlwZSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGVsZW0gPT09IHF1YWxpZmllciApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gQXJyYXlsaWtlIG9mIGVsZW1lbnRzIChqUXVlcnksIGFyZ3VtZW50cywgQXJyYXkpXG5cdGlmICggdHlwZW9mIHF1YWxpZmllciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gU2ltcGxlIHNlbGVjdG9yIHRoYXQgY2FuIGJlIGZpbHRlcmVkIGRpcmVjdGx5LCByZW1vdmluZyBub24tRWxlbWVudHNcblx0aWYgKCByaXNTaW1wbGUudGVzdCggcXVhbGlmaWVyICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5maWx0ZXIoIHF1YWxpZmllciwgZWxlbWVudHMsIG5vdCApO1xuXHR9XG5cblx0Ly8gQ29tcGxleCBzZWxlY3RvciwgY29tcGFyZSB0aGUgdHdvIHNldHMsIHJlbW92aW5nIG5vbi1FbGVtZW50c1xuXHRxdWFsaWZpZXIgPSBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzICk7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3QgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMTtcblx0fSApO1xufVxuXG5qUXVlcnkuZmlsdGVyID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1zLCBub3QgKSB7XG5cdHZhciBlbGVtID0gZWxlbXNbIDAgXTtcblxuXHRpZiAoIG5vdCApIHtcblx0XHRleHByID0gXCI6bm90KFwiICsgZXhwciArIFwiKVwiO1xuXHR9XG5cblx0aWYgKCBlbGVtcy5sZW5ndGggPT09IDEgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBlbGVtLCBleHByICkgPyBbIGVsZW0gXSA6IFtdO1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeS5maW5kLm1hdGNoZXMoIGV4cHIsIGpRdWVyeS5ncmVwKCBlbGVtcywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7XG5cdH0gKSApO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmaW5kOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dmFyIGksIHJldCxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0c2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5KCBzZWxlY3RvciApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHNlbGZbIGkgXSwgdGhpcyApICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICkgKTtcblx0XHR9XG5cblx0XHRyZXQgPSB0aGlzLnB1c2hTdGFjayggW10gKTtcblxuXHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRqUXVlcnkuZmluZCggc2VsZWN0b3IsIHNlbGZbIGkgXSwgcmV0ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGxlbiA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggcmV0ICkgOiByZXQ7XG5cdH0sXG5cdGZpbHRlcjogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KCB0aGlzLCBzZWxlY3RvciB8fCBbXSwgZmFsc2UgKSApO1xuXHR9LFxuXHRub3Q6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHdpbm5vdyggdGhpcywgc2VsZWN0b3IgfHwgW10sIHRydWUgKSApO1xuXHR9LFxuXHRpczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiAhIXdpbm5vdyhcblx0XHRcdHRoaXMsXG5cblx0XHRcdC8vIElmIHRoaXMgaXMgYSBwb3NpdGlvbmFsL3JlbGF0aXZlIHNlbGVjdG9yLCBjaGVjayBtZW1iZXJzaGlwIGluIHRoZSByZXR1cm5lZCBzZXRcblx0XHRcdC8vIHNvICQoXCJwOmZpcnN0XCIpLmlzKFwicDpsYXN0XCIpIHdvbid0IHJldHVybiB0cnVlIGZvciBhIGRvYyB3aXRoIHR3byBcInBcIi5cblx0XHRcdHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiAmJiBybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICkgP1xuXHRcdFx0XHRqUXVlcnkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHRzZWxlY3RvciB8fCBbXSxcblx0XHRcdGZhbHNlXG5cdFx0KS5sZW5ndGg7XG5cdH1cbn0gKTtcblxuXG4vLyBJbml0aWFsaXplIGEgalF1ZXJ5IG9iamVjdFxuXG5cbi8vIEEgY2VudHJhbCByZWZlcmVuY2UgdG8gdGhlIHJvb3QgalF1ZXJ5KGRvY3VtZW50KVxudmFyIHJvb3RqUXVlcnksXG5cblx0Ly8gQSBzaW1wbGUgd2F5IHRvIGNoZWNrIGZvciBIVE1MIHN0cmluZ3Ncblx0Ly8gUHJpb3JpdGl6ZSAjaWQgb3ZlciA8dGFnPiB0byBhdm9pZCBYU1MgdmlhIGxvY2F0aW9uLmhhc2ggKCM5NTIxKVxuXHQvLyBTdHJpY3QgSFRNTCByZWNvZ25pdGlvbiAoIzExMjkwOiBtdXN0IHN0YXJ0IHdpdGggPClcblx0Ly8gU2hvcnRjdXQgc2ltcGxlICNpZCBjYXNlIGZvciBzcGVlZFxuXHRycXVpY2tFeHByID0gL14oPzpcXHMqKDxbXFx3XFxXXSs+KVtePl0qfCMoW1xcdy1dKykpJC8sXG5cblx0aW5pdCA9IGpRdWVyeS5mbi5pbml0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0LCByb290ICkge1xuXHRcdHZhciBtYXRjaCwgZWxlbTtcblxuXHRcdC8vIEhBTkRMRTogJChcIlwiKSwgJChudWxsKSwgJCh1bmRlZmluZWQpLCAkKGZhbHNlKVxuXHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Ly8gTWV0aG9kIGluaXQoKSBhY2NlcHRzIGFuIGFsdGVybmF0ZSByb290alF1ZXJ5XG5cdFx0Ly8gc28gbWlncmF0ZSBjYW4gc3VwcG9ydCBqUXVlcnkuc3ViIChnaC0yMTAxKVxuXHRcdHJvb3QgPSByb290IHx8IHJvb3RqUXVlcnk7XG5cblx0XHQvLyBIYW5kbGUgSFRNTCBzdHJpbmdzXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRpZiAoIHNlbGVjdG9yWyAwIF0gPT09IFwiPFwiICYmXG5cdFx0XHRcdHNlbGVjdG9yWyBzZWxlY3Rvci5sZW5ndGggLSAxIF0gPT09IFwiPlwiICYmXG5cdFx0XHRcdHNlbGVjdG9yLmxlbmd0aCA+PSAzICkge1xuXG5cdFx0XHRcdC8vIEFzc3VtZSB0aGF0IHN0cmluZ3MgdGhhdCBzdGFydCBhbmQgZW5kIHdpdGggPD4gYXJlIEhUTUwgYW5kIHNraXAgdGhlIHJlZ2V4IGNoZWNrXG5cdFx0XHRcdG1hdGNoID0gWyBudWxsLCBzZWxlY3RvciwgbnVsbCBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXRjaCA9IHJxdWlja0V4cHIuZXhlYyggc2VsZWN0b3IgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWF0Y2ggaHRtbCBvciBtYWtlIHN1cmUgbm8gY29udGV4dCBpcyBzcGVjaWZpZWQgZm9yICNpZFxuXHRcdFx0aWYgKCBtYXRjaCAmJiAoIG1hdGNoWyAxIF0gfHwgIWNvbnRleHQgKSApIHtcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCkgLT4gJChhcnJheSlcblx0XHRcdFx0aWYgKCBtYXRjaFsgMSBdICkge1xuXHRcdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgalF1ZXJ5ID8gY29udGV4dFsgMCBdIDogY29udGV4dDtcblxuXHRcdFx0XHRcdC8vIE9wdGlvbiB0byBydW4gc2NyaXB0cyBpcyB0cnVlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRcdC8vIEludGVudGlvbmFsbHkgbGV0IHRoZSBlcnJvciBiZSB0aHJvd24gaWYgcGFyc2VIVE1MIGlzIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLCBqUXVlcnkucGFyc2VIVE1MKFxuXHRcdFx0XHRcdFx0bWF0Y2hbIDEgXSxcblx0XHRcdFx0XHRcdGNvbnRleHQgJiYgY29udGV4dC5ub2RlVHlwZSA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogZG9jdW1lbnQsXG5cdFx0XHRcdFx0XHR0cnVlXG5cdFx0XHRcdFx0KSApO1xuXG5cdFx0XHRcdFx0Ly8gSEFORExFOiAkKGh0bWwsIHByb3BzKVxuXHRcdFx0XHRcdGlmICggcnNpbmdsZVRhZy50ZXN0KCBtYXRjaFsgMSBdICkgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGNvbnRleHQgKSApIHtcblx0XHRcdFx0XHRcdGZvciAoIG1hdGNoIGluIGNvbnRleHQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gUHJvcGVydGllcyBvZiBjb250ZXh0IGFyZSBjYWxsZWQgYXMgbWV0aG9kcyBpZiBwb3NzaWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB0aGlzWyBtYXRjaCBdICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpc1sgbWF0Y2ggXSggY29udGV4dFsgbWF0Y2ggXSApO1xuXG5cdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBvdGhlcndpc2Ugc2V0IGFzIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmF0dHIoIG1hdGNoLCBjb250ZXh0WyBtYXRjaCBdICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoI2lkKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggbWF0Y2hbIDIgXSApO1xuXG5cdFx0XHRcdFx0aWYgKCBlbGVtICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJbmplY3QgdGhlIGVsZW1lbnQgZGlyZWN0bHkgaW50byB0aGUgalF1ZXJ5IG9iamVjdFxuXHRcdFx0XHRcdFx0dGhpc1sgMCBdID0gZWxlbTtcblx0XHRcdFx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gSEFORExFOiAkKGV4cHIsICQoLi4uKSlcblx0XHRcdH0gZWxzZSBpZiAoICFjb250ZXh0IHx8IGNvbnRleHQuanF1ZXJ5ICkge1xuXHRcdFx0XHRyZXR1cm4gKCBjb250ZXh0IHx8IHJvb3QgKS5maW5kKCBzZWxlY3RvciApO1xuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgY29udGV4dClcblx0XHRcdC8vICh3aGljaCBpcyBqdXN0IGVxdWl2YWxlbnQgdG86ICQoY29udGV4dCkuZmluZChleHByKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29uc3RydWN0b3IoIGNvbnRleHQgKS5maW5kKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0Ly8gSEFORExFOiAkKERPTUVsZW1lbnQpXG5cdFx0fSBlbHNlIGlmICggc2VsZWN0b3Iubm9kZVR5cGUgKSB7XG5cdFx0XHR0aGlzWyAwIF0gPSBzZWxlY3Rvcjtcblx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0Ly8gSEFORExFOiAkKGZ1bmN0aW9uKVxuXHRcdC8vIFNob3J0Y3V0IGZvciBkb2N1bWVudCByZWFkeVxuXHRcdH0gZWxzZSBpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBzZWxlY3RvciApICkge1xuXHRcdFx0cmV0dXJuIHJvb3QucmVhZHkgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdHJvb3QucmVhZHkoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIEV4ZWN1dGUgaW1tZWRpYXRlbHkgaWYgcmVhZHkgaXMgbm90IHByZXNlbnRcblx0XHRcdFx0c2VsZWN0b3IoIGpRdWVyeSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciwgdGhpcyApO1xuXHR9O1xuXG4vLyBHaXZlIHRoZSBpbml0IGZ1bmN0aW9uIHRoZSBqUXVlcnkgcHJvdG90eXBlIGZvciBsYXRlciBpbnN0YW50aWF0aW9uXG5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjtcblxuLy8gSW5pdGlhbGl6ZSBjZW50cmFsIHJlZmVyZW5jZVxucm9vdGpRdWVyeSA9IGpRdWVyeSggZG9jdW1lbnQgKTtcblxuXG52YXIgcnBhcmVudHNwcmV2ID0gL14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sXG5cblx0Ly8gTWV0aG9kcyBndWFyYW50ZWVkIHRvIHByb2R1Y2UgYSB1bmlxdWUgc2V0IHdoZW4gc3RhcnRpbmcgZnJvbSBhIHVuaXF1ZSBzZXRcblx0Z3VhcmFudGVlZFVuaXF1ZSA9IHtcblx0XHRjaGlsZHJlbjogdHJ1ZSxcblx0XHRjb250ZW50czogdHJ1ZSxcblx0XHRuZXh0OiB0cnVlLFxuXHRcdHByZXY6IHRydWVcblx0fTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRoYXM6IGZ1bmN0aW9uKCB0YXJnZXQgKSB7XG5cdFx0dmFyIHRhcmdldHMgPSBqUXVlcnkoIHRhcmdldCwgdGhpcyApLFxuXHRcdFx0bCA9IHRhcmdldHMubGVuZ3RoO1xuXG5cdFx0cmV0dXJuIHRoaXMuZmlsdGVyKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpID0gMDtcblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHRoaXMsIHRhcmdldHNbIGkgXSApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGNsb3Nlc3Q6IGZ1bmN0aW9uKCBzZWxlY3RvcnMsIGNvbnRleHQgKSB7XG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0bWF0Y2hlZCA9IFtdLFxuXHRcdFx0dGFyZ2V0cyA9IHR5cGVvZiBzZWxlY3RvcnMgIT09IFwic3RyaW5nXCIgJiYgalF1ZXJ5KCBzZWxlY3RvcnMgKTtcblxuXHRcdC8vIFBvc2l0aW9uYWwgc2VsZWN0b3JzIG5ldmVyIG1hdGNoLCBzaW5jZSB0aGVyZSdzIG5vIF9zZWxlY3Rpb25fIGNvbnRleHRcblx0XHRpZiAoICFybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9ycyApICkge1xuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRmb3IgKCBjdXIgPSB0aGlzWyBpIF07IGN1ciAmJiBjdXIgIT09IGNvbnRleHQ7IGN1ciA9IGN1ci5wYXJlbnROb2RlICkge1xuXG5cdFx0XHRcdFx0Ly8gQWx3YXlzIHNraXAgZG9jdW1lbnQgZnJhZ21lbnRzXG5cdFx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPCAxMSAmJiAoIHRhcmdldHMgP1xuXHRcdFx0XHRcdFx0dGFyZ2V0cy5pbmRleCggY3VyICkgPiAtMSA6XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IHBhc3Mgbm9uLWVsZW1lbnRzIHRvIFNpenpsZVxuXHRcdFx0XHRcdFx0Y3VyLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kLm1hdGNoZXNTZWxlY3RvciggY3VyLCBzZWxlY3RvcnMgKSApICkge1xuXG5cdFx0XHRcdFx0XHRtYXRjaGVkLnB1c2goIGN1ciApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBtYXRjaGVkLmxlbmd0aCA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApIDogbWF0Y2hlZCApO1xuXHR9LFxuXG5cdC8vIERldGVybWluZSB0aGUgcG9zaXRpb24gb2YgYW4gZWxlbWVudCB3aXRoaW4gdGhlIHNldFxuXHRpbmRleDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHQvLyBObyBhcmd1bWVudCwgcmV0dXJuIGluZGV4IGluIHBhcmVudFxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gKCB0aGlzWyAwIF0gJiYgdGhpc1sgMCBdLnBhcmVudE5vZGUgKSA/IHRoaXMuZmlyc3QoKS5wcmV2QWxsKCkubGVuZ3RoIDogLTE7XG5cdFx0fVxuXG5cdFx0Ly8gSW5kZXggaW4gc2VsZWN0b3Jcblx0XHRpZiAoIHR5cGVvZiBlbGVtID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggalF1ZXJ5KCBlbGVtICksIHRoaXNbIDAgXSApO1xuXHRcdH1cblxuXHRcdC8vIExvY2F0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGRlc2lyZWQgZWxlbWVudFxuXHRcdHJldHVybiBpbmRleE9mLmNhbGwoIHRoaXMsXG5cblx0XHRcdC8vIElmIGl0IHJlY2VpdmVzIGEgalF1ZXJ5IG9iamVjdCwgdGhlIGZpcnN0IGVsZW1lbnQgaXMgdXNlZFxuXHRcdFx0ZWxlbS5qcXVlcnkgPyBlbGVtWyAwIF0gOiBlbGVtXG5cdFx0KTtcblx0fSxcblxuXHRhZGQ6IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soXG5cdFx0XHRqUXVlcnkudW5pcXVlU29ydChcblx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLmdldCgpLCBqUXVlcnkoIHNlbGVjdG9yLCBjb250ZXh0ICkgKVxuXHRcdFx0KVxuXHRcdCk7XG5cdH0sXG5cblx0YWRkQmFjazogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLmFkZCggc2VsZWN0b3IgPT0gbnVsbCA/XG5cdFx0XHR0aGlzLnByZXZPYmplY3QgOiB0aGlzLnByZXZPYmplY3QuZmlsdGVyKCBzZWxlY3RvciApXG5cdFx0KTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBzaWJsaW5nKCBjdXIsIGRpciApIHtcblx0d2hpbGUgKCAoIGN1ciA9IGN1clsgZGlyIF0gKSAmJiBjdXIubm9kZVR5cGUgIT09IDEgKSB7fVxuXHRyZXR1cm4gY3VyO1xufVxuXG5qUXVlcnkuZWFjaCgge1xuXHRwYXJlbnQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGU7XG5cdFx0cmV0dXJuIHBhcmVudCAmJiBwYXJlbnQubm9kZVR5cGUgIT09IDExID8gcGFyZW50IDogbnVsbDtcblx0fSxcblx0cGFyZW50czogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIgKTtcblx0fSxcblx0cGFyZW50c1VudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIsIHVudGlsICk7XG5cdH0sXG5cdG5leHQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5nKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmcoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dEFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiICk7XG5cdH0sXG5cdHByZXZBbGw6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBkaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dFVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRwcmV2VW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInByZXZpb3VzU2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRzaWJsaW5nczogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmdzKCAoIGVsZW0ucGFyZW50Tm9kZSB8fCB7fSApLmZpcnN0Q2hpbGQsIGVsZW0gKTtcblx0fSxcblx0Y2hpbGRyZW46IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5ncyggZWxlbS5maXJzdENoaWxkICk7XG5cdH0sXG5cdGNvbnRlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAgICAgaWYgKCBub2RlTmFtZSggZWxlbSwgXCJpZnJhbWVcIiApICkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0uY29udGVudERvY3VtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHksIGlPUyA3IG9ubHksIEFuZHJvaWQgQnJvd3NlciA8PTQuMyBvbmx5XG4gICAgICAgIC8vIFRyZWF0IHRoZSB0ZW1wbGF0ZSBlbGVtZW50IGFzIGEgcmVndWxhciBvbmUgaW4gYnJvd3NlcnMgdGhhdFxuICAgICAgICAvLyBkb24ndCBzdXBwb3J0IGl0LlxuICAgICAgICBpZiAoIG5vZGVOYW1lKCBlbGVtLCBcInRlbXBsYXRlXCIgKSApIHtcbiAgICAgICAgICAgIGVsZW0gPSBlbGVtLmNvbnRlbnQgfHwgZWxlbTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBlbGVtLmNoaWxkTm9kZXMgKTtcblx0fVxufSwgZnVuY3Rpb24oIG5hbWUsIGZuICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCB1bnRpbCwgc2VsZWN0b3IgKSB7XG5cdFx0dmFyIG1hdGNoZWQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiwgdW50aWwgKTtcblxuXHRcdGlmICggbmFtZS5zbGljZSggLTUgKSAhPT0gXCJVbnRpbFwiICkge1xuXHRcdFx0c2VsZWN0b3IgPSB1bnRpbDtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG1hdGNoZWQgPSBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgbWF0Y2hlZCApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sZW5ndGggPiAxICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgZHVwbGljYXRlc1xuXHRcdFx0aWYgKCAhZ3VhcmFudGVlZFVuaXF1ZVsgbmFtZSBdICkge1xuXHRcdFx0XHRqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXZlcnNlIG9yZGVyIGZvciBwYXJlbnRzKiBhbmQgcHJldi1kZXJpdmF0aXZlc1xuXHRcdFx0aWYgKCBycGFyZW50c3ByZXYudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRtYXRjaGVkLnJldmVyc2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQgKTtcblx0fTtcbn0gKTtcbnZhciBybm90aHRtbHdoaXRlID0gKCAvW15cXHgyMFxcdFxcclxcblxcZl0rL2cgKTtcblxuXG5cbi8vIENvbnZlcnQgU3RyaW5nLWZvcm1hdHRlZCBvcHRpb25zIGludG8gT2JqZWN0LWZvcm1hdHRlZCBvbmVzXG5mdW5jdGlvbiBjcmVhdGVPcHRpb25zKCBvcHRpb25zICkge1xuXHR2YXIgb2JqZWN0ID0ge307XG5cdGpRdWVyeS5lYWNoKCBvcHRpb25zLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10sIGZ1bmN0aW9uKCBfLCBmbGFnICkge1xuXHRcdG9iamVjdFsgZmxhZyBdID0gdHJ1ZTtcblx0fSApO1xuXHRyZXR1cm4gb2JqZWN0O1xufVxuXG4vKlxuICogQ3JlYXRlIGEgY2FsbGJhY2sgbGlzdCB1c2luZyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gKlxuICpcdG9wdGlvbnM6IGFuIG9wdGlvbmFsIGxpc3Qgb2Ygc3BhY2Utc2VwYXJhdGVkIG9wdGlvbnMgdGhhdCB3aWxsIGNoYW5nZSBob3dcbiAqXHRcdFx0dGhlIGNhbGxiYWNrIGxpc3QgYmVoYXZlcyBvciBhIG1vcmUgdHJhZGl0aW9uYWwgb3B0aW9uIG9iamVjdFxuICpcbiAqIEJ5IGRlZmF1bHQgYSBjYWxsYmFjayBsaXN0IHdpbGwgYWN0IGxpa2UgYW4gZXZlbnQgY2FsbGJhY2sgbGlzdCBhbmQgY2FuIGJlXG4gKiBcImZpcmVkXCIgbXVsdGlwbGUgdGltZXMuXG4gKlxuICogUG9zc2libGUgb3B0aW9uczpcbiAqXG4gKlx0b25jZTpcdFx0XHR3aWxsIGVuc3VyZSB0aGUgY2FsbGJhY2sgbGlzdCBjYW4gb25seSBiZSBmaXJlZCBvbmNlIChsaWtlIGEgRGVmZXJyZWQpXG4gKlxuICpcdG1lbW9yeTpcdFx0XHR3aWxsIGtlZXAgdHJhY2sgb2YgcHJldmlvdXMgdmFsdWVzIGFuZCB3aWxsIGNhbGwgYW55IGNhbGxiYWNrIGFkZGVkXG4gKlx0XHRcdFx0XHRhZnRlciB0aGUgbGlzdCBoYXMgYmVlbiBmaXJlZCByaWdodCBhd2F5IHdpdGggdGhlIGxhdGVzdCBcIm1lbW9yaXplZFwiXG4gKlx0XHRcdFx0XHR2YWx1ZXMgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0dW5pcXVlOlx0XHRcdHdpbGwgZW5zdXJlIGEgY2FsbGJhY2sgY2FuIG9ubHkgYmUgYWRkZWQgb25jZSAobm8gZHVwbGljYXRlIGluIHRoZSBsaXN0KVxuICpcbiAqXHRzdG9wT25GYWxzZTpcdGludGVycnVwdCBjYWxsaW5ncyB3aGVuIGEgY2FsbGJhY2sgcmV0dXJucyBmYWxzZVxuICpcbiAqL1xualF1ZXJ5LkNhbGxiYWNrcyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdC8vIENvbnZlcnQgb3B0aW9ucyBmcm9tIFN0cmluZy1mb3JtYXR0ZWQgdG8gT2JqZWN0LWZvcm1hdHRlZCBpZiBuZWVkZWRcblx0Ly8gKHdlIGNoZWNrIGluIGNhY2hlIGZpcnN0KVxuXHRvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIgP1xuXHRcdGNyZWF0ZU9wdGlvbnMoIG9wdGlvbnMgKSA6XG5cdFx0alF1ZXJ5LmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgLy8gRmxhZyB0byBrbm93IGlmIGxpc3QgaXMgY3VycmVudGx5IGZpcmluZ1xuXHRcdGZpcmluZyxcblxuXHRcdC8vIExhc3QgZmlyZSB2YWx1ZSBmb3Igbm9uLWZvcmdldHRhYmxlIGxpc3RzXG5cdFx0bWVtb3J5LFxuXG5cdFx0Ly8gRmxhZyB0byBrbm93IGlmIGxpc3Qgd2FzIGFscmVhZHkgZmlyZWRcblx0XHRmaXJlZCxcblxuXHRcdC8vIEZsYWcgdG8gcHJldmVudCBmaXJpbmdcblx0XHRsb2NrZWQsXG5cblx0XHQvLyBBY3R1YWwgY2FsbGJhY2sgbGlzdFxuXHRcdGxpc3QgPSBbXSxcblxuXHRcdC8vIFF1ZXVlIG9mIGV4ZWN1dGlvbiBkYXRhIGZvciByZXBlYXRhYmxlIGxpc3RzXG5cdFx0cXVldWUgPSBbXSxcblxuXHRcdC8vIEluZGV4IG9mIGN1cnJlbnRseSBmaXJpbmcgY2FsbGJhY2sgKG1vZGlmaWVkIGJ5IGFkZC9yZW1vdmUgYXMgbmVlZGVkKVxuXHRcdGZpcmluZ0luZGV4ID0gLTEsXG5cblx0XHQvLyBGaXJlIGNhbGxiYWNrc1xuXHRcdGZpcmUgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRW5mb3JjZSBzaW5nbGUtZmlyaW5nXG5cdFx0XHRsb2NrZWQgPSBsb2NrZWQgfHwgb3B0aW9ucy5vbmNlO1xuXG5cdFx0XHQvLyBFeGVjdXRlIGNhbGxiYWNrcyBmb3IgYWxsIHBlbmRpbmcgZXhlY3V0aW9ucyxcblx0XHRcdC8vIHJlc3BlY3RpbmcgZmlyaW5nSW5kZXggb3ZlcnJpZGVzIGFuZCBydW50aW1lIGNoYW5nZXNcblx0XHRcdGZpcmVkID0gZmlyaW5nID0gdHJ1ZTtcblx0XHRcdGZvciAoIDsgcXVldWUubGVuZ3RoOyBmaXJpbmdJbmRleCA9IC0xICkge1xuXHRcdFx0XHRtZW1vcnkgPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHR3aGlsZSAoICsrZmlyaW5nSW5kZXggPCBsaXN0Lmxlbmd0aCApIHtcblxuXHRcdFx0XHRcdC8vIFJ1biBjYWxsYmFjayBhbmQgY2hlY2sgZm9yIGVhcmx5IHRlcm1pbmF0aW9uXG5cdFx0XHRcdFx0aWYgKCBsaXN0WyBmaXJpbmdJbmRleCBdLmFwcGx5KCBtZW1vcnlbIDAgXSwgbWVtb3J5WyAxIF0gKSA9PT0gZmFsc2UgJiZcblx0XHRcdFx0XHRcdG9wdGlvbnMuc3RvcE9uRmFsc2UgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEp1bXAgdG8gZW5kIGFuZCBmb3JnZXQgdGhlIGRhdGEgc28gLmFkZCBkb2Vzbid0IHJlLWZpcmVcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRcdFx0XHRtZW1vcnkgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gRm9yZ2V0IHRoZSBkYXRhIGlmIHdlJ3JlIGRvbmUgd2l0aCBpdFxuXHRcdFx0aWYgKCAhb3B0aW9ucy5tZW1vcnkgKSB7XG5cdFx0XHRcdG1lbW9yeSA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRmaXJpbmcgPSBmYWxzZTtcblxuXHRcdFx0Ly8gQ2xlYW4gdXAgaWYgd2UncmUgZG9uZSBmaXJpbmcgZm9yIGdvb2Rcblx0XHRcdGlmICggbG9ja2VkICkge1xuXG5cdFx0XHRcdC8vIEtlZXAgYW4gZW1wdHkgbGlzdCBpZiB3ZSBoYXZlIGRhdGEgZm9yIGZ1dHVyZSBhZGQgY2FsbHNcblx0XHRcdFx0aWYgKCBtZW1vcnkgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IFtdO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSwgdGhpcyBvYmplY3QgaXMgc3BlbnRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsaXN0ID0gXCJcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvLyBBY3R1YWwgQ2FsbGJhY2tzIG9iamVjdFxuXHRcdHNlbGYgPSB7XG5cblx0XHRcdC8vIEFkZCBhIGNhbGxiYWNrIG9yIGEgY29sbGVjdGlvbiBvZiBjYWxsYmFja3MgdG8gdGhlIGxpc3Rcblx0XHRcdGFkZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblxuXHRcdFx0XHRcdC8vIElmIHdlIGhhdmUgbWVtb3J5IGZyb20gYSBwYXN0IHJ1biwgd2Ugc2hvdWxkIGZpcmUgYWZ0ZXIgYWRkaW5nXG5cdFx0XHRcdFx0aWYgKCBtZW1vcnkgJiYgIWZpcmluZyApIHtcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGggLSAxO1xuXHRcdFx0XHRcdFx0cXVldWUucHVzaCggbWVtb3J5ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0KCBmdW5jdGlvbiBhZGQoIGFyZ3MgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZWFjaCggYXJncywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYXJnICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhb3B0aW9ucy51bmlxdWUgfHwgIXNlbGYuaGFzKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGxpc3QucHVzaCggYXJnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBhcmcgJiYgYXJnLmxlbmd0aCAmJiBqUXVlcnkudHlwZSggYXJnICkgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBJbnNwZWN0IHJlY3Vyc2l2ZWx5XG5cdFx0XHRcdFx0XHRcdFx0YWRkKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gKSggYXJndW1lbnRzICk7XG5cblx0XHRcdFx0XHRpZiAoIG1lbW9yeSAmJiAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIFJlbW92ZSBhIGNhbGxiYWNrIGZyb20gdGhlIGxpc3Rcblx0XHRcdHJlbW92ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBfLCBhcmcgKSB7XG5cdFx0XHRcdFx0dmFyIGluZGV4O1xuXHRcdFx0XHRcdHdoaWxlICggKCBpbmRleCA9IGpRdWVyeS5pbkFycmF5KCBhcmcsIGxpc3QsIGluZGV4ICkgKSA+IC0xICkge1xuXHRcdFx0XHRcdFx0bGlzdC5zcGxpY2UoIGluZGV4LCAxICk7XG5cblx0XHRcdFx0XHRcdC8vIEhhbmRsZSBmaXJpbmcgaW5kZXhlc1xuXHRcdFx0XHRcdFx0aWYgKCBpbmRleCA8PSBmaXJpbmdJbmRleCApIHtcblx0XHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXgtLTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDaGVjayBpZiBhIGdpdmVuIGNhbGxiYWNrIGlzIGluIHRoZSBsaXN0LlxuXHRcdFx0Ly8gSWYgbm8gYXJndW1lbnQgaXMgZ2l2ZW4sIHJldHVybiB3aGV0aGVyIG9yIG5vdCBsaXN0IGhhcyBjYWxsYmFja3MgYXR0YWNoZWQuXG5cdFx0XHRoYXM6IGZ1bmN0aW9uKCBmbiApIHtcblx0XHRcdFx0cmV0dXJuIGZuID9cblx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggZm4sIGxpc3QgKSA+IC0xIDpcblx0XHRcdFx0XHRsaXN0Lmxlbmd0aCA+IDA7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBSZW1vdmUgYWxsIGNhbGxiYWNrcyBmcm9tIHRoZSBsaXN0XG5cdFx0XHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblx0XHRcdFx0XHRsaXN0ID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBEaXNhYmxlIC5maXJlIGFuZCAuYWRkXG5cdFx0XHQvLyBBYm9ydCBhbnkgY3VycmVudC9wZW5kaW5nIGV4ZWN1dGlvbnNcblx0XHRcdC8vIENsZWFyIGFsbCBjYWxsYmFja3MgYW5kIHZhbHVlc1xuXHRcdFx0ZGlzYWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGxvY2tlZCA9IHF1ZXVlID0gW107XG5cdFx0XHRcdGxpc3QgPSBtZW1vcnkgPSBcIlwiO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHRkaXNhYmxlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhbGlzdDtcblx0XHRcdH0sXG5cblx0XHRcdC8vIERpc2FibGUgLmZpcmVcblx0XHRcdC8vIEFsc28gZGlzYWJsZSAuYWRkIHVubGVzcyB3ZSBoYXZlIG1lbW9yeSAoc2luY2UgaXQgd291bGQgaGF2ZSBubyBlZmZlY3QpXG5cdFx0XHQvLyBBYm9ydCBhbnkgcGVuZGluZyBleGVjdXRpb25zXG5cdFx0XHRsb2NrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0bG9ja2VkID0gcXVldWUgPSBbXTtcblx0XHRcdFx0aWYgKCAhbWVtb3J5ICYmICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IG1lbW9yeSA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0bG9ja2VkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICEhbG9ja2VkO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhbGwgY2FsbGJhY2tzIHdpdGggdGhlIGdpdmVuIGNvbnRleHQgYW5kIGFyZ3VtZW50c1xuXHRcdFx0ZmlyZVdpdGg6IGZ1bmN0aW9uKCBjb250ZXh0LCBhcmdzICkge1xuXHRcdFx0XHRpZiAoICFsb2NrZWQgKSB7XG5cdFx0XHRcdFx0YXJncyA9IGFyZ3MgfHwgW107XG5cdFx0XHRcdFx0YXJncyA9IFsgY29udGV4dCwgYXJncy5zbGljZSA/IGFyZ3Muc2xpY2UoKSA6IGFyZ3MgXTtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBhcmdzICk7XG5cdFx0XHRcdFx0aWYgKCAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIENhbGwgYWxsIHRoZSBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gYXJndW1lbnRzXG5cdFx0XHRmaXJlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0c2VsZi5maXJlV2l0aCggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gVG8ga25vdyBpZiB0aGUgY2FsbGJhY2tzIGhhdmUgYWxyZWFkeSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlXG5cdFx0XHRmaXJlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhIWZpcmVkO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0cmV0dXJuIHNlbGY7XG59O1xuXG5cbmZ1bmN0aW9uIElkZW50aXR5KCB2ICkge1xuXHRyZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIFRocm93ZXIoIGV4ICkge1xuXHR0aHJvdyBleDtcbn1cblxuZnVuY3Rpb24gYWRvcHRWYWx1ZSggdmFsdWUsIHJlc29sdmUsIHJlamVjdCwgbm9WYWx1ZSApIHtcblx0dmFyIG1ldGhvZDtcblxuXHR0cnkge1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIHByb21pc2UgYXNwZWN0IGZpcnN0IHRvIHByaXZpbGVnZSBzeW5jaHJvbm91cyBiZWhhdmlvclxuXHRcdGlmICggdmFsdWUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oICggbWV0aG9kID0gdmFsdWUucHJvbWlzZSApICkgKSB7XG5cdFx0XHRtZXRob2QuY2FsbCggdmFsdWUgKS5kb25lKCByZXNvbHZlICkuZmFpbCggcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciB0aGVuYWJsZXNcblx0XHR9IGVsc2UgaWYgKCB2YWx1ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggKCBtZXRob2QgPSB2YWx1ZS50aGVuICkgKSApIHtcblx0XHRcdG1ldGhvZC5jYWxsKCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciBub24tdGhlbmFibGVzXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQ29udHJvbCBgcmVzb2x2ZWAgYXJndW1lbnRzIGJ5IGxldHRpbmcgQXJyYXkjc2xpY2UgY2FzdCBib29sZWFuIGBub1ZhbHVlYCB0byBpbnRlZ2VyOlxuXHRcdFx0Ly8gKiBmYWxzZTogWyB2YWx1ZSBdLnNsaWNlKCAwICkgPT4gcmVzb2x2ZSggdmFsdWUgKVxuXHRcdFx0Ly8gKiB0cnVlOiBbIHZhbHVlIF0uc2xpY2UoIDEgKSA9PiByZXNvbHZlKClcblx0XHRcdHJlc29sdmUuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdLnNsaWNlKCBub1ZhbHVlICkgKTtcblx0XHR9XG5cblx0Ly8gRm9yIFByb21pc2VzL0ErLCBjb252ZXJ0IGV4Y2VwdGlvbnMgaW50byByZWplY3Rpb25zXG5cdC8vIFNpbmNlIGpRdWVyeS53aGVuIGRvZXNuJ3QgdW53cmFwIHRoZW5hYmxlcywgd2UgY2FuIHNraXAgdGhlIGV4dHJhIGNoZWNrcyBhcHBlYXJpbmcgaW5cblx0Ly8gRGVmZXJyZWQjdGhlbiB0byBjb25kaXRpb25hbGx5IHN1cHByZXNzIHJlamVjdGlvbi5cblx0fSBjYXRjaCAoIHZhbHVlICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgb25seVxuXHRcdC8vIFN0cmljdCBtb2RlIGZ1bmN0aW9ucyBpbnZva2VkIHdpdGhvdXQgLmNhbGwvLmFwcGx5IGdldCBnbG9iYWwtb2JqZWN0IGNvbnRleHRcblx0XHRyZWplY3QuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdICk7XG5cdH1cbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdERlZmVycmVkOiBmdW5jdGlvbiggZnVuYyApIHtcblx0XHR2YXIgdHVwbGVzID0gW1xuXG5cdFx0XHRcdC8vIGFjdGlvbiwgYWRkIGxpc3RlbmVyLCBjYWxsYmFja3MsXG5cdFx0XHRcdC8vIC4uLiAudGhlbiBoYW5kbGVycywgYXJndW1lbnQgaW5kZXgsIFtmaW5hbCBzdGF0ZV1cblx0XHRcdFx0WyBcIm5vdGlmeVwiLCBcInByb2dyZXNzXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwibWVtb3J5XCIgKSxcblx0XHRcdFx0XHRqUXVlcnkuQ2FsbGJhY2tzKCBcIm1lbW9yeVwiICksIDIgXSxcblx0XHRcdFx0WyBcInJlc29sdmVcIiwgXCJkb25lXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXHRcdFx0XHRcdGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLCAwLCBcInJlc29sdmVkXCIgXSxcblx0XHRcdFx0WyBcInJlamVjdFwiLCBcImZhaWxcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cdFx0XHRcdFx0alF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksIDEsIFwicmVqZWN0ZWRcIiBdXG5cdFx0XHRdLFxuXHRcdFx0c3RhdGUgPSBcInBlbmRpbmdcIixcblx0XHRcdHByb21pc2UgPSB7XG5cdFx0XHRcdHN0YXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gc3RhdGU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGFsd2F5czogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQuZG9uZSggYXJndW1lbnRzICkuZmFpbCggYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFwiY2F0Y2hcIjogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlLnRoZW4oIG51bGwsIGZuICk7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gS2VlcCBwaXBlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRwaXBlOiBmdW5jdGlvbiggLyogZm5Eb25lLCBmbkZhaWwsIGZuUHJvZ3Jlc3MgKi8gKSB7XG5cdFx0XHRcdFx0dmFyIGZucyA9IGFyZ3VtZW50cztcblxuXHRcdFx0XHRcdHJldHVybiBqUXVlcnkuRGVmZXJyZWQoIGZ1bmN0aW9uKCBuZXdEZWZlciApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCB0dXBsZXMsIGZ1bmN0aW9uKCBpLCB0dXBsZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBNYXAgdHVwbGVzIChwcm9ncmVzcywgZG9uZSwgZmFpbCkgdG8gYXJndW1lbnRzIChkb25lLCBmYWlsLCBwcm9ncmVzcylcblx0XHRcdFx0XHRcdFx0dmFyIGZuID0galF1ZXJ5LmlzRnVuY3Rpb24oIGZuc1sgdHVwbGVbIDQgXSBdICkgJiYgZm5zWyB0dXBsZVsgNCBdIF07XG5cblx0XHRcdFx0XHRcdFx0Ly8gZGVmZXJyZWQucHJvZ3Jlc3MoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIubm90aWZ5IH0pXG5cdFx0XHRcdFx0XHRcdC8vIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIucmVzb2x2ZSB9KVxuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZC5mYWlsKGZ1bmN0aW9uKCkgeyBiaW5kIHRvIG5ld0RlZmVyIG9yIG5ld0RlZmVyLnJlamVjdCB9KVxuXHRcdFx0XHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDEgXSBdKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmV0dXJuZWQgPSBmbiAmJiBmbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCAmJiBqUXVlcnkuaXNGdW5jdGlvbiggcmV0dXJuZWQucHJvbWlzZSApICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQucHJvbWlzZSgpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5wcm9ncmVzcyggbmV3RGVmZXIubm90aWZ5IClcblx0XHRcdFx0XHRcdFx0XHRcdFx0LmRvbmUoIG5ld0RlZmVyLnJlc29sdmUgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZmFpbCggbmV3RGVmZXIucmVqZWN0ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyWyB0dXBsZVsgMCBdICsgXCJXaXRoXCIgXShcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm4gPyBbIHJldHVybmVkIF0gOiBhcmd1bWVudHNcblx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRmbnMgPSBudWxsO1xuXHRcdFx0XHRcdH0gKS5wcm9taXNlKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRoZW46IGZ1bmN0aW9uKCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb25Qcm9ncmVzcyApIHtcblx0XHRcdFx0XHR2YXIgbWF4RGVwdGggPSAwO1xuXHRcdFx0XHRcdGZ1bmN0aW9uIHJlc29sdmUoIGRlcHRoLCBkZWZlcnJlZCwgaGFuZGxlciwgc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHRoYXQgPSB0aGlzLFxuXHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBhcmd1bWVudHMsXG5cdFx0XHRcdFx0XHRcdFx0bWlnaHRUaHJvdyA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIHJldHVybmVkLCB0aGVuO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4zLjMuM1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBkb3VibGUtcmVzb2x1dGlvbiBhdHRlbXB0c1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCA8IG1heERlcHRoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkID0gaGFuZGxlci5hcHBseSggdGhhdCwgYXJncyApO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4xXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC00OFxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCA9PT0gZGVmZXJyZWQucHJvbWlzZSgpICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCBcIlRoZW5hYmxlIHNlbGYtcmVzb2x1dGlvblwiICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb25zIDIuMy4zLjEsIDMuNVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTRcblx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTc1XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBSZXRyaWV2ZSBgdGhlbmAgb25seSBvbmNlXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGVuID0gcmV0dXJuZWQgJiZcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy40XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTY0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgY2hlY2sgb2JqZWN0cyBhbmQgZnVuY3Rpb25zIGZvciB0aGVuYWJpbGl0eVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHR5cGVvZiByZXR1cm5lZCA9PT0gXCJvYmplY3RcIiB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHR5cGVvZiByZXR1cm5lZCA9PT0gXCJmdW5jdGlvblwiICkgJiZcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQudGhlbjtcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGEgcmV0dXJuZWQgdGhlbmFibGVcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHRoZW4gKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTcGVjaWFsIHByb2Nlc3NvcnMgKG5vdGlmeSkganVzdCB3YWl0IGZvciByZXNvbHV0aW9uXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGVuLmNhbGwoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgVGhyb3dlciwgc3BlY2lhbCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBOb3JtYWwgcHJvY2Vzc29ycyAocmVzb2x2ZSkgYWxzbyBob29rIGludG8gcHJvZ3Jlc3Ncblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBkaXNyZWdhcmQgb2xkZXIgcmVzb2x1dGlvbiB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtYXhEZXB0aCsrO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhlbi5jYWxsKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIElkZW50aXR5LCBzcGVjaWFsICksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIFRocm93ZXIsIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGFsbCBvdGhlciByZXR1cm5lZCB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gT25seSBzdWJzdGl0dXRlIGhhbmRsZXJzIHBhc3Mgb24gY29udGV4dFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBoYW5kbGVyICE9PSBJZGVudGl0eSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGF0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBbIHJldHVybmVkIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBQcm9jZXNzIHRoZSB2YWx1ZShzKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZhdWx0IHByb2Nlc3MgaXMgcmVzb2x2ZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHNwZWNpYWwgfHwgZGVmZXJyZWQucmVzb2x2ZVdpdGggKSggdGhhdCwgYXJncyApO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IG5vcm1hbCBwcm9jZXNzb3JzIChyZXNvbHZlKSBjYXRjaCBhbmQgcmVqZWN0IGV4Y2VwdGlvbnNcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzID0gc3BlY2lhbCA/XG5cdFx0XHRcdFx0XHRcdFx0XHRtaWdodFRocm93IDpcblx0XHRcdFx0XHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1pZ2h0VGhyb3coKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5leGNlcHRpb25Ib29rICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LkRlZmVycmVkLmV4Y2VwdGlvbkhvb2soIGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb2Nlc3Muc3RhY2tUcmFjZSApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy40LjFcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC02MVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBwb3N0LXJlc29sdXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggZGVwdGggKyAxID49IG1heERlcHRoICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IHN1YnN0aXR1dGUgaGFuZGxlcnMgcGFzcyBvbiBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggaGFuZGxlciAhPT0gVGhyb3dlciApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhhdCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YXJncyA9IFsgZSBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy4xXG5cdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTU3XG5cdFx0XHRcdFx0XHRcdC8vIFJlLXJlc29sdmUgcHJvbWlzZXMgaW1tZWRpYXRlbHkgdG8gZG9kZ2UgZmFsc2UgcmVqZWN0aW9uIGZyb21cblx0XHRcdFx0XHRcdFx0Ly8gc3Vic2VxdWVudCBlcnJvcnNcblx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCApIHtcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDYWxsIGFuIG9wdGlvbmFsIGhvb2sgdG8gcmVjb3JkIHRoZSBzdGFjaywgaW4gY2FzZSBvZiBleGNlcHRpb25cblx0XHRcdFx0XHRcdFx0XHQvLyBzaW5jZSBpdCdzIG90aGVyd2lzZSBsb3N0IHdoZW4gZXhlY3V0aW9uIGdvZXMgYXN5bmNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5nZXRTdGFja0hvb2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzLnN0YWNrVHJhY2UgPSBqUXVlcnkuRGVmZXJyZWQuZ2V0U3RhY2tIb29rKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBwcm9jZXNzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZCggZnVuY3Rpb24oIG5ld0RlZmVyICkge1xuXG5cdFx0XHRcdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDAgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvblByb2dyZXNzICkgP1xuXHRcdFx0XHRcdFx0XHRcdFx0b25Qcm9ncmVzcyA6XG5cdFx0XHRcdFx0XHRcdFx0XHRJZGVudGl0eSxcblx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlci5ub3RpZnlXaXRoXG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDEgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvbkZ1bGZpbGxlZCApID9cblx0XHRcdFx0XHRcdFx0XHRcdG9uRnVsZmlsbGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdElkZW50aXR5XG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIHJlamVjdGVkX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMiBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uUmVqZWN0ZWQgKSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRvblJlamVjdGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdFRocm93ZXJcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9ICkucHJvbWlzZSgpO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIEdldCBhIHByb21pc2UgZm9yIHRoaXMgZGVmZXJyZWRcblx0XHRcdFx0Ly8gSWYgb2JqIGlzIHByb3ZpZGVkLCB0aGUgcHJvbWlzZSBhc3BlY3QgaXMgYWRkZWQgdG8gdGhlIG9iamVjdFxuXHRcdFx0XHRwcm9taXNlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdFx0XHRcdHJldHVybiBvYmogIT0gbnVsbCA/IGpRdWVyeS5leHRlbmQoIG9iaiwgcHJvbWlzZSApIDogcHJvbWlzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlZmVycmVkID0ge307XG5cblx0XHQvLyBBZGQgbGlzdC1zcGVjaWZpYyBtZXRob2RzXG5cdFx0alF1ZXJ5LmVhY2goIHR1cGxlcywgZnVuY3Rpb24oIGksIHR1cGxlICkge1xuXHRcdFx0dmFyIGxpc3QgPSB0dXBsZVsgMiBdLFxuXHRcdFx0XHRzdGF0ZVN0cmluZyA9IHR1cGxlWyA1IF07XG5cblx0XHRcdC8vIHByb21pc2UucHJvZ3Jlc3MgPSBsaXN0LmFkZFxuXHRcdFx0Ly8gcHJvbWlzZS5kb25lID0gbGlzdC5hZGRcblx0XHRcdC8vIHByb21pc2UuZmFpbCA9IGxpc3QuYWRkXG5cdFx0XHRwcm9taXNlWyB0dXBsZVsgMSBdIF0gPSBsaXN0LmFkZDtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0YXRlXG5cdFx0XHRpZiAoIHN0YXRlU3RyaW5nICkge1xuXHRcdFx0XHRsaXN0LmFkZChcblx0XHRcdFx0XHRmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gc3RhdGUgPSBcInJlc29sdmVkXCIgKGkuZS4sIGZ1bGZpbGxlZClcblx0XHRcdFx0XHRcdC8vIHN0YXRlID0gXCJyZWplY3RlZFwiXG5cdFx0XHRcdFx0XHRzdGF0ZSA9IHN0YXRlU3RyaW5nO1xuXHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHQvLyByZWplY3RlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdHR1cGxlc1sgMyAtIGkgXVsgMiBdLmRpc2FibGUsXG5cblx0XHRcdFx0XHQvLyBwcm9ncmVzc19jYWxsYmFja3MubG9ja1xuXHRcdFx0XHRcdHR1cGxlc1sgMCBdWyAyIF0ubG9ja1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5maXJlXG5cdFx0XHQvLyBmdWxmaWxsZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0Ly8gcmVqZWN0ZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0bGlzdC5hZGQoIHR1cGxlWyAzIF0uZmlyZSApO1xuXG5cdFx0XHQvLyBkZWZlcnJlZC5ub3RpZnkgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQubm90aWZ5V2l0aCguLi4pIH1cblx0XHRcdC8vIGRlZmVycmVkLnJlc29sdmUgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVzb2x2ZVdpdGgoLi4uKSB9XG5cdFx0XHQvLyBkZWZlcnJlZC5yZWplY3QgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVqZWN0V2l0aCguLi4pIH1cblx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMCBdIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGVmZXJyZWRbIHR1cGxlWyAwIF0gKyBcIldpdGhcIiBdKCB0aGlzID09PSBkZWZlcnJlZCA/IHVuZGVmaW5lZCA6IHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH07XG5cblx0XHRcdC8vIGRlZmVycmVkLm5vdGlmeVdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHQvLyBkZWZlcnJlZC5yZXNvbHZlV2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdC8vIGRlZmVycmVkLnJlamVjdFdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0gPSBsaXN0LmZpcmVXaXRoO1xuXHRcdH0gKTtcblxuXHRcdC8vIE1ha2UgdGhlIGRlZmVycmVkIGEgcHJvbWlzZVxuXHRcdHByb21pc2UucHJvbWlzZSggZGVmZXJyZWQgKTtcblxuXHRcdC8vIENhbGwgZ2l2ZW4gZnVuYyBpZiBhbnlcblx0XHRpZiAoIGZ1bmMgKSB7XG5cdFx0XHRmdW5jLmNhbGwoIGRlZmVycmVkLCBkZWZlcnJlZCApO1xuXHRcdH1cblxuXHRcdC8vIEFsbCBkb25lIVxuXHRcdHJldHVybiBkZWZlcnJlZDtcblx0fSxcblxuXHQvLyBEZWZlcnJlZCBoZWxwZXJcblx0d2hlbjogZnVuY3Rpb24oIHNpbmdsZVZhbHVlICkge1xuXHRcdHZhclxuXG5cdFx0XHQvLyBjb3VudCBvZiB1bmNvbXBsZXRlZCBzdWJvcmRpbmF0ZXNcblx0XHRcdHJlbWFpbmluZyA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cblx0XHRcdC8vIGNvdW50IG9mIHVucHJvY2Vzc2VkIGFyZ3VtZW50c1xuXHRcdFx0aSA9IHJlbWFpbmluZyxcblxuXHRcdFx0Ly8gc3Vib3JkaW5hdGUgZnVsZmlsbG1lbnQgZGF0YVxuXHRcdFx0cmVzb2x2ZUNvbnRleHRzID0gQXJyYXkoIGkgKSxcblx0XHRcdHJlc29sdmVWYWx1ZXMgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSxcblxuXHRcdFx0Ly8gdGhlIG1hc3RlciBEZWZlcnJlZFxuXHRcdFx0bWFzdGVyID0galF1ZXJ5LkRlZmVycmVkKCksXG5cblx0XHRcdC8vIHN1Ym9yZGluYXRlIGNhbGxiYWNrIGZhY3Rvcnlcblx0XHRcdHVwZGF0ZUZ1bmMgPSBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXNvbHZlQ29udGV4dHNbIGkgXSA9IHRoaXM7XG5cdFx0XHRcdFx0cmVzb2x2ZVZhbHVlc1sgaSBdID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSA6IHZhbHVlO1xuXHRcdFx0XHRcdGlmICggISggLS1yZW1haW5pbmcgKSApIHtcblx0XHRcdFx0XHRcdG1hc3Rlci5yZXNvbHZlV2l0aCggcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fTtcblxuXHRcdC8vIFNpbmdsZS0gYW5kIGVtcHR5IGFyZ3VtZW50cyBhcmUgYWRvcHRlZCBsaWtlIFByb21pc2UucmVzb2x2ZVxuXHRcdGlmICggcmVtYWluaW5nIDw9IDEgKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCBzaW5nbGVWYWx1ZSwgbWFzdGVyLmRvbmUoIHVwZGF0ZUZ1bmMoIGkgKSApLnJlc29sdmUsIG1hc3Rlci5yZWplY3QsXG5cdFx0XHRcdCFyZW1haW5pbmcgKTtcblxuXHRcdFx0Ly8gVXNlIC50aGVuKCkgdG8gdW53cmFwIHNlY29uZGFyeSB0aGVuYWJsZXMgKGNmLiBnaC0zMDAwKVxuXHRcdFx0aWYgKCBtYXN0ZXIuc3RhdGUoKSA9PT0gXCJwZW5kaW5nXCIgfHxcblx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHJlc29sdmVWYWx1ZXNbIGkgXSAmJiByZXNvbHZlVmFsdWVzWyBpIF0udGhlbiApICkge1xuXG5cdFx0XHRcdHJldHVybiBtYXN0ZXIudGhlbigpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE11bHRpcGxlIGFyZ3VtZW50cyBhcmUgYWdncmVnYXRlZCBsaWtlIFByb21pc2UuYWxsIGFycmF5IGVsZW1lbnRzXG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCByZXNvbHZlVmFsdWVzWyBpIF0sIHVwZGF0ZUZ1bmMoIGkgKSwgbWFzdGVyLnJlamVjdCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBtYXN0ZXIucHJvbWlzZSgpO1xuXHR9XG59ICk7XG5cblxuLy8gVGhlc2UgdXN1YWxseSBpbmRpY2F0ZSBhIHByb2dyYW1tZXIgbWlzdGFrZSBkdXJpbmcgZGV2ZWxvcG1lbnQsXG4vLyB3YXJuIGFib3V0IHRoZW0gQVNBUCByYXRoZXIgdGhhbiBzd2FsbG93aW5nIHRoZW0gYnkgZGVmYXVsdC5cbnZhciByZXJyb3JOYW1lcyA9IC9eKEV2YWx8SW50ZXJuYWx8UmFuZ2V8UmVmZXJlbmNlfFN5bnRheHxUeXBlfFVSSSlFcnJvciQvO1xuXG5qUXVlcnkuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayA9IGZ1bmN0aW9uKCBlcnJvciwgc3RhY2sgKSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgOCAtIDkgb25seVxuXHQvLyBDb25zb2xlIGV4aXN0cyB3aGVuIGRldiB0b29scyBhcmUgb3Blbiwgd2hpY2ggY2FuIGhhcHBlbiBhdCBhbnkgdGltZVxuXHRpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLndhcm4gJiYgZXJyb3IgJiYgcmVycm9yTmFtZXMudGVzdCggZXJyb3IubmFtZSApICkge1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4oIFwialF1ZXJ5LkRlZmVycmVkIGV4Y2VwdGlvbjogXCIgKyBlcnJvci5tZXNzYWdlLCBlcnJvci5zdGFjaywgc3RhY2sgKTtcblx0fVxufTtcblxuXG5cblxualF1ZXJ5LnJlYWR5RXhjZXB0aW9uID0gZnVuY3Rpb24oIGVycm9yICkge1xuXHR3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXJyb3I7XG5cdH0gKTtcbn07XG5cblxuXG5cbi8vIFRoZSBkZWZlcnJlZCB1c2VkIG9uIERPTSByZWFkeVxudmFyIHJlYWR5TGlzdCA9IGpRdWVyeS5EZWZlcnJlZCgpO1xuXG5qUXVlcnkuZm4ucmVhZHkgPSBmdW5jdGlvbiggZm4gKSB7XG5cblx0cmVhZHlMaXN0XG5cdFx0LnRoZW4oIGZuIClcblxuXHRcdC8vIFdyYXAgalF1ZXJ5LnJlYWR5RXhjZXB0aW9uIGluIGEgZnVuY3Rpb24gc28gdGhhdCB0aGUgbG9va3VwXG5cdFx0Ly8gaGFwcGVucyBhdCB0aGUgdGltZSBvZiBlcnJvciBoYW5kbGluZyBpbnN0ZWFkIG9mIGNhbGxiYWNrXG5cdFx0Ly8gcmVnaXN0cmF0aW9uLlxuXHRcdC5jYXRjaCggZnVuY3Rpb24oIGVycm9yICkge1xuXHRcdFx0alF1ZXJ5LnJlYWR5RXhjZXB0aW9uKCBlcnJvciApO1xuXHRcdH0gKTtcblxuXHRyZXR1cm4gdGhpcztcbn07XG5cbmpRdWVyeS5leHRlbmQoIHtcblxuXHQvLyBJcyB0aGUgRE9NIHJlYWR5IHRvIGJlIHVzZWQ/IFNldCB0byB0cnVlIG9uY2UgaXQgb2NjdXJzLlxuXHRpc1JlYWR5OiBmYWxzZSxcblxuXHQvLyBBIGNvdW50ZXIgdG8gdHJhY2sgaG93IG1hbnkgaXRlbXMgdG8gd2FpdCBmb3IgYmVmb3JlXG5cdC8vIHRoZSByZWFkeSBldmVudCBmaXJlcy4gU2VlICM2NzgxXG5cdHJlYWR5V2FpdDogMSxcblxuXHQvLyBIYW5kbGUgd2hlbiB0aGUgRE9NIGlzIHJlYWR5XG5cdHJlYWR5OiBmdW5jdGlvbiggd2FpdCApIHtcblxuXHRcdC8vIEFib3J0IGlmIHRoZXJlIGFyZSBwZW5kaW5nIGhvbGRzIG9yIHdlJ3JlIGFscmVhZHkgcmVhZHlcblx0XHRpZiAoIHdhaXQgPT09IHRydWUgPyAtLWpRdWVyeS5yZWFkeVdhaXQgOiBqUXVlcnkuaXNSZWFkeSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBSZW1lbWJlciB0aGF0IHRoZSBET00gaXMgcmVhZHlcblx0XHRqUXVlcnkuaXNSZWFkeSA9IHRydWU7XG5cblx0XHQvLyBJZiBhIG5vcm1hbCBET00gUmVhZHkgZXZlbnQgZmlyZWQsIGRlY3JlbWVudCwgYW5kIHdhaXQgaWYgbmVlZCBiZVxuXHRcdGlmICggd2FpdCAhPT0gdHJ1ZSAmJiAtLWpRdWVyeS5yZWFkeVdhaXQgPiAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIElmIHRoZXJlIGFyZSBmdW5jdGlvbnMgYm91bmQsIHRvIGV4ZWN1dGVcblx0XHRyZWFkeUxpc3QucmVzb2x2ZVdpdGgoIGRvY3VtZW50LCBbIGpRdWVyeSBdICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LnJlYWR5LnRoZW4gPSByZWFkeUxpc3QudGhlbjtcblxuLy8gVGhlIHJlYWR5IGV2ZW50IGhhbmRsZXIgYW5kIHNlbGYgY2xlYW51cCBtZXRob2RcbmZ1bmN0aW9uIGNvbXBsZXRlZCgpIHtcblx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJsb2FkXCIsIGNvbXBsZXRlZCApO1xuXHRqUXVlcnkucmVhZHkoKTtcbn1cblxuLy8gQ2F0Y2ggY2FzZXMgd2hlcmUgJChkb2N1bWVudCkucmVhZHkoKSBpcyBjYWxsZWRcbi8vIGFmdGVyIHRoZSBicm93c2VyIGV2ZW50IGhhcyBhbHJlYWR5IG9jY3VycmVkLlxuLy8gU3VwcG9ydDogSUUgPD05IC0gMTAgb25seVxuLy8gT2xkZXIgSUUgc29tZXRpbWVzIHNpZ25hbHMgXCJpbnRlcmFjdGl2ZVwiIHRvbyBzb29uXG5pZiAoIGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIiB8fFxuXHQoIGRvY3VtZW50LnJlYWR5U3RhdGUgIT09IFwibG9hZGluZ1wiICYmICFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGwgKSApIHtcblxuXHQvLyBIYW5kbGUgaXQgYXN5bmNocm9ub3VzbHkgdG8gYWxsb3cgc2NyaXB0cyB0aGUgb3Bwb3J0dW5pdHkgdG8gZGVsYXkgcmVhZHlcblx0d2luZG93LnNldFRpbWVvdXQoIGpRdWVyeS5yZWFkeSApO1xuXG59IGVsc2Uge1xuXG5cdC8vIFVzZSB0aGUgaGFuZHkgZXZlbnQgY2FsbGJhY2tcblx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXG5cdC8vIEEgZmFsbGJhY2sgdG8gd2luZG93Lm9ubG9hZCwgdGhhdCB3aWxsIGFsd2F5cyB3b3JrXG5cdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkICk7XG59XG5cblxuXG5cbi8vIE11bHRpZnVuY3Rpb25hbCBtZXRob2QgdG8gZ2V0IGFuZCBzZXQgdmFsdWVzIG9mIGEgY29sbGVjdGlvblxuLy8gVGhlIHZhbHVlL3MgY2FuIG9wdGlvbmFsbHkgYmUgZXhlY3V0ZWQgaWYgaXQncyBhIGZ1bmN0aW9uXG52YXIgYWNjZXNzID0gZnVuY3Rpb24oIGVsZW1zLCBmbiwga2V5LCB2YWx1ZSwgY2hhaW5hYmxlLCBlbXB0eUdldCwgcmF3ICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gZWxlbXMubGVuZ3RoLFxuXHRcdGJ1bGsgPSBrZXkgPT0gbnVsbDtcblxuXHQvLyBTZXRzIG1hbnkgdmFsdWVzXG5cdGlmICggalF1ZXJ5LnR5cGUoIGtleSApID09PSBcIm9iamVjdFwiICkge1xuXHRcdGNoYWluYWJsZSA9IHRydWU7XG5cdFx0Zm9yICggaSBpbiBrZXkgKSB7XG5cdFx0XHRhY2Nlc3MoIGVsZW1zLCBmbiwgaSwga2V5WyBpIF0sIHRydWUsIGVtcHR5R2V0LCByYXcgKTtcblx0XHR9XG5cblx0Ly8gU2V0cyBvbmUgdmFsdWVcblx0fSBlbHNlIGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRjaGFpbmFibGUgPSB0cnVlO1xuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyYXcgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggYnVsayApIHtcblxuXHRcdFx0Ly8gQnVsayBvcGVyYXRpb25zIHJ1biBhZ2FpbnN0IHRoZSBlbnRpcmUgc2V0XG5cdFx0XHRpZiAoIHJhdyApIHtcblx0XHRcdFx0Zm4uY2FsbCggZWxlbXMsIHZhbHVlICk7XG5cdFx0XHRcdGZuID0gbnVsbDtcblxuXHRcdFx0Ly8gLi4uZXhjZXB0IHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uIHZhbHVlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YnVsayA9IGZuO1xuXHRcdFx0XHRmbiA9IGZ1bmN0aW9uKCBlbGVtLCBrZXksIHZhbHVlICkge1xuXHRcdFx0XHRcdHJldHVybiBidWxrLmNhbGwoIGpRdWVyeSggZWxlbSApLCB2YWx1ZSApO1xuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggZm4gKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0Zm4oXG5cdFx0XHRcdFx0ZWxlbXNbIGkgXSwga2V5LCByYXcgP1xuXHRcdFx0XHRcdHZhbHVlIDpcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCBlbGVtc1sgaSBdLCBpLCBmbiggZWxlbXNbIGkgXSwga2V5ICkgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggY2hhaW5hYmxlICkge1xuXHRcdHJldHVybiBlbGVtcztcblx0fVxuXG5cdC8vIEdldHNcblx0aWYgKCBidWxrICkge1xuXHRcdHJldHVybiBmbi5jYWxsKCBlbGVtcyApO1xuXHR9XG5cblx0cmV0dXJuIGxlbiA/IGZuKCBlbGVtc1sgMCBdLCBrZXkgKSA6IGVtcHR5R2V0O1xufTtcbnZhciBhY2NlcHREYXRhID0gZnVuY3Rpb24oIG93bmVyICkge1xuXG5cdC8vIEFjY2VwdHMgb25seTpcblx0Ly8gIC0gTm9kZVxuXHQvLyAgICAtIE5vZGUuRUxFTUVOVF9OT0RFXG5cdC8vICAgIC0gTm9kZS5ET0NVTUVOVF9OT0RFXG5cdC8vICAtIE9iamVjdFxuXHQvLyAgICAtIEFueVxuXHRyZXR1cm4gb3duZXIubm9kZVR5cGUgPT09IDEgfHwgb3duZXIubm9kZVR5cGUgPT09IDkgfHwgISggK293bmVyLm5vZGVUeXBlICk7XG59O1xuXG5cblxuXG5mdW5jdGlvbiBEYXRhKCkge1xuXHR0aGlzLmV4cGFuZG8gPSBqUXVlcnkuZXhwYW5kbyArIERhdGEudWlkKys7XG59XG5cbkRhdGEudWlkID0gMTtcblxuRGF0YS5wcm90b3R5cGUgPSB7XG5cblx0Y2FjaGU6IGZ1bmN0aW9uKCBvd25lciApIHtcblxuXHRcdC8vIENoZWNrIGlmIHRoZSBvd25lciBvYmplY3QgYWxyZWFkeSBoYXMgYSBjYWNoZVxuXHRcdHZhciB2YWx1ZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdC8vIElmIG5vdCwgY3JlYXRlIG9uZVxuXHRcdGlmICggIXZhbHVlICkge1xuXHRcdFx0dmFsdWUgPSB7fTtcblxuXHRcdFx0Ly8gV2UgY2FuIGFjY2VwdCBkYXRhIGZvciBub24tZWxlbWVudCBub2RlcyBpbiBtb2Rlcm4gYnJvd3NlcnMsXG5cdFx0XHQvLyBidXQgd2Ugc2hvdWxkIG5vdCwgc2VlICM4MzM1LlxuXHRcdFx0Ly8gQWx3YXlzIHJldHVybiBhbiBlbXB0eSBvYmplY3QuXG5cdFx0XHRpZiAoIGFjY2VwdERhdGEoIG93bmVyICkgKSB7XG5cblx0XHRcdFx0Ly8gSWYgaXQgaXMgYSBub2RlIHVubGlrZWx5IHRvIGJlIHN0cmluZ2lmeS1lZCBvciBsb29wZWQgb3ZlclxuXHRcdFx0XHQvLyB1c2UgcGxhaW4gYXNzaWdubWVudFxuXHRcdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSA9IHZhbHVlO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBzZWN1cmUgaXQgaW4gYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eVxuXHRcdFx0XHQvLyBjb25maWd1cmFibGUgbXVzdCBiZSB0cnVlIHRvIGFsbG93IHRoZSBwcm9wZXJ0eSB0byBiZVxuXHRcdFx0XHQvLyBkZWxldGVkIHdoZW4gZGF0YSBpcyByZW1vdmVkXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KCBvd25lciwgdGhpcy5leHBhbmRvLCB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogdmFsdWUsXG5cdFx0XHRcdFx0XHRjb25maWd1cmFibGU6IHRydWVcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdmFsdWU7XG5cdH0sXG5cdHNldDogZnVuY3Rpb24oIG93bmVyLCBkYXRhLCB2YWx1ZSApIHtcblx0XHR2YXIgcHJvcCxcblx0XHRcdGNhY2hlID0gdGhpcy5jYWNoZSggb3duZXIgKTtcblxuXHRcdC8vIEhhbmRsZTogWyBvd25lciwga2V5LCB2YWx1ZSBdIGFyZ3Ncblx0XHQvLyBBbHdheXMgdXNlIGNhbWVsQ2FzZSBrZXkgKGdoLTIyNTcpXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGNhY2hlWyBqUXVlcnkuY2FtZWxDYXNlKCBkYXRhICkgXSA9IHZhbHVlO1xuXG5cdFx0Ly8gSGFuZGxlOiBbIG93bmVyLCB7IHByb3BlcnRpZXMgfSBdIGFyZ3Ncblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBDb3B5IHRoZSBwcm9wZXJ0aWVzIG9uZS1ieS1vbmUgdG8gdGhlIGNhY2hlIG9iamVjdFxuXHRcdFx0Zm9yICggcHJvcCBpbiBkYXRhICkge1xuXHRcdFx0XHRjYWNoZVsgalF1ZXJ5LmNhbWVsQ2FzZSggcHJvcCApIF0gPSBkYXRhWyBwcm9wIF07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZTtcblx0fSxcblx0Z2V0OiBmdW5jdGlvbiggb3duZXIsIGtleSApIHtcblx0XHRyZXR1cm4ga2V5ID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcy5jYWNoZSggb3duZXIgKSA6XG5cblx0XHRcdC8vIEFsd2F5cyB1c2UgY2FtZWxDYXNlIGtleSAoZ2gtMjI1Nylcblx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSAmJiBvd25lclsgdGhpcy5leHBhbmRvIF1bIGpRdWVyeS5jYW1lbENhc2UoIGtleSApIF07XG5cdH0sXG5cdGFjY2VzczogZnVuY3Rpb24oIG93bmVyLCBrZXksIHZhbHVlICkge1xuXG5cdFx0Ly8gSW4gY2FzZXMgd2hlcmUgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBObyBrZXkgd2FzIHNwZWNpZmllZFxuXHRcdC8vICAgMi4gQSBzdHJpbmcga2V5IHdhcyBzcGVjaWZpZWQsIGJ1dCBubyB2YWx1ZSBwcm92aWRlZFxuXHRcdC8vXG5cdFx0Ly8gVGFrZSB0aGUgXCJyZWFkXCIgcGF0aCBhbmQgYWxsb3cgdGhlIGdldCBtZXRob2QgdG8gZGV0ZXJtaW5lXG5cdFx0Ly8gd2hpY2ggdmFsdWUgdG8gcmV0dXJuLCByZXNwZWN0aXZlbHkgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBUaGUgZW50aXJlIGNhY2hlIG9iamVjdFxuXHRcdC8vICAgMi4gVGhlIGRhdGEgc3RvcmVkIGF0IHRoZSBrZXlcblx0XHQvL1xuXHRcdGlmICgga2V5ID09PSB1bmRlZmluZWQgfHxcblx0XHRcdFx0KCAoIGtleSAmJiB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICkgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApICkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoIG93bmVyLCBrZXkgKTtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHRoZSBrZXkgaXMgbm90IGEgc3RyaW5nLCBvciBib3RoIGEga2V5IGFuZCB2YWx1ZVxuXHRcdC8vIGFyZSBzcGVjaWZpZWQsIHNldCBvciBleHRlbmQgKGV4aXN0aW5nIG9iamVjdHMpIHdpdGggZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBBbiBvYmplY3Qgb2YgcHJvcGVydGllc1xuXHRcdC8vICAgMi4gQSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly9cblx0XHR0aGlzLnNldCggb3duZXIsIGtleSwgdmFsdWUgKTtcblxuXHRcdC8vIFNpbmNlIHRoZSBcInNldFwiIHBhdGggY2FuIGhhdmUgdHdvIHBvc3NpYmxlIGVudHJ5IHBvaW50c1xuXHRcdC8vIHJldHVybiB0aGUgZXhwZWN0ZWQgZGF0YSBiYXNlZCBvbiB3aGljaCBwYXRoIHdhcyB0YWtlblsqXVxuXHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiBrZXk7XG5cdH0sXG5cdHJlbW92ZTogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0dmFyIGksXG5cdFx0XHRjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdGlmICggY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGtleSAhPT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHQvLyBTdXBwb3J0IGFycmF5IG9yIHNwYWNlIHNlcGFyYXRlZCBzdHJpbmcgb2Yga2V5c1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBrZXkgKSApIHtcblxuXHRcdFx0XHQvLyBJZiBrZXkgaXMgYW4gYXJyYXkgb2Yga2V5cy4uLlxuXHRcdFx0XHQvLyBXZSBhbHdheXMgc2V0IGNhbWVsQ2FzZSBrZXlzLCBzbyByZW1vdmUgdGhhdC5cblx0XHRcdFx0a2V5ID0ga2V5Lm1hcCggalF1ZXJ5LmNhbWVsQ2FzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0a2V5ID0galF1ZXJ5LmNhbWVsQ2FzZSgga2V5ICk7XG5cblx0XHRcdFx0Ly8gSWYgYSBrZXkgd2l0aCB0aGUgc3BhY2VzIGV4aXN0cywgdXNlIGl0LlxuXHRcdFx0XHQvLyBPdGhlcndpc2UsIGNyZWF0ZSBhbiBhcnJheSBieSBtYXRjaGluZyBub24td2hpdGVzcGFjZVxuXHRcdFx0XHRrZXkgPSBrZXkgaW4gY2FjaGUgP1xuXHRcdFx0XHRcdFsga2V5IF0gOlxuXHRcdFx0XHRcdCgga2V5Lm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10gKTtcblx0XHRcdH1cblxuXHRcdFx0aSA9IGtleS5sZW5ndGg7XG5cblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRkZWxldGUgY2FjaGVbIGtleVsgaSBdIF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIHRoZSBleHBhbmRvIGlmIHRoZXJlJ3Mgbm8gbW9yZSBkYXRhXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fCBqUXVlcnkuaXNFbXB0eU9iamVjdCggY2FjaGUgKSApIHtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NVxuXHRcdFx0Ly8gV2Via2l0ICYgQmxpbmsgcGVyZm9ybWFuY2Ugc3VmZmVycyB3aGVuIGRlbGV0aW5nIHByb3BlcnRpZXNcblx0XHRcdC8vIGZyb20gRE9NIG5vZGVzLCBzbyBzZXQgdG8gdW5kZWZpbmVkIGluc3RlYWRcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTM3ODYwNyAoYnVnIHJlc3RyaWN0ZWQpXG5cdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRvd25lclsgdGhpcy5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWxldGUgb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0aGFzRGF0YTogZnVuY3Rpb24oIG93bmVyICkge1xuXHRcdHZhciBjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblx0XHRyZXR1cm4gY2FjaGUgIT09IHVuZGVmaW5lZCAmJiAhalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGNhY2hlICk7XG5cdH1cbn07XG52YXIgZGF0YVByaXYgPSBuZXcgRGF0YSgpO1xuXG52YXIgZGF0YVVzZXIgPSBuZXcgRGF0YSgpO1xuXG5cblxuLy9cdEltcGxlbWVudGF0aW9uIFN1bW1hcnlcbi8vXG4vL1x0MS4gRW5mb3JjZSBBUEkgc3VyZmFjZSBhbmQgc2VtYW50aWMgY29tcGF0aWJpbGl0eSB3aXRoIDEuOS54IGJyYW5jaFxuLy9cdDIuIEltcHJvdmUgdGhlIG1vZHVsZSdzIG1haW50YWluYWJpbGl0eSBieSByZWR1Y2luZyB0aGUgc3RvcmFnZVxuLy9cdFx0cGF0aHMgdG8gYSBzaW5nbGUgbWVjaGFuaXNtLlxuLy9cdDMuIFVzZSB0aGUgc2FtZSBzaW5nbGUgbWVjaGFuaXNtIHRvIHN1cHBvcnQgXCJwcml2YXRlXCIgYW5kIFwidXNlclwiIGRhdGEuXG4vL1x0NC4gX05ldmVyXyBleHBvc2UgXCJwcml2YXRlXCIgZGF0YSB0byB1c2VyIGNvZGUgKFRPRE86IERyb3AgX2RhdGEsIF9yZW1vdmVEYXRhKVxuLy9cdDUuIEF2b2lkIGV4cG9zaW5nIGltcGxlbWVudGF0aW9uIGRldGFpbHMgb24gdXNlciBvYmplY3RzIChlZy4gZXhwYW5kbyBwcm9wZXJ0aWVzKVxuLy9cdDYuIFByb3ZpZGUgYSBjbGVhciBwYXRoIGZvciBpbXBsZW1lbnRhdGlvbiB1cGdyYWRlIHRvIFdlYWtNYXAgaW4gMjAxNFxuXG52YXIgcmJyYWNlID0gL14oPzpcXHtbXFx3XFxXXSpcXH18XFxbW1xcd1xcV10qXFxdKSQvLFxuXHRybXVsdGlEYXNoID0gL1tBLVpdL2c7XG5cbmZ1bmN0aW9uIGdldERhdGEoIGRhdGEgKSB7XG5cdGlmICggZGF0YSA9PT0gXCJ0cnVlXCIgKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwiZmFsc2VcIiApIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwibnVsbFwiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gT25seSBjb252ZXJ0IHRvIGEgbnVtYmVyIGlmIGl0IGRvZXNuJ3QgY2hhbmdlIHRoZSBzdHJpbmdcblx0aWYgKCBkYXRhID09PSArZGF0YSArIFwiXCIgKSB7XG5cdFx0cmV0dXJuICtkYXRhO1xuXHR9XG5cblx0aWYgKCByYnJhY2UudGVzdCggZGF0YSApICkge1xuXHRcdHJldHVybiBKU09OLnBhcnNlKCBkYXRhICk7XG5cdH1cblxuXHRyZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gZGF0YUF0dHIoIGVsZW0sIGtleSwgZGF0YSApIHtcblx0dmFyIG5hbWU7XG5cblx0Ly8gSWYgbm90aGluZyB3YXMgZm91bmQgaW50ZXJuYWxseSwgdHJ5IHRvIGZldGNoIGFueVxuXHQvLyBkYXRhIGZyb20gdGhlIEhUTUw1IGRhdGEtKiBhdHRyaWJ1dGVcblx0aWYgKCBkYXRhID09PSB1bmRlZmluZWQgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRuYW1lID0gXCJkYXRhLVwiICsga2V5LnJlcGxhY2UoIHJtdWx0aURhc2gsIFwiLSQmXCIgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGRhdGEgPSBlbGVtLmdldEF0dHJpYnV0ZSggbmFtZSApO1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBnZXREYXRhKCBkYXRhICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHt9XG5cblx0XHRcdC8vIE1ha2Ugc3VyZSB3ZSBzZXQgdGhlIGRhdGEgc28gaXQgaXNuJ3QgY2hhbmdlZCBsYXRlclxuXHRcdFx0ZGF0YVVzZXIuc2V0KCBlbGVtLCBrZXksIGRhdGEgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aGFzRGF0YTogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmhhc0RhdGEoIGVsZW0gKSB8fCBkYXRhUHJpdi5oYXNEYXRhKCBlbGVtICk7XG5cdH0sXG5cblx0ZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdHJlbW92ZURhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHRcdGRhdGFVc2VyLnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9LFxuXG5cdC8vIFRPRE86IE5vdyB0aGF0IGFsbCBjYWxscyB0byBfZGF0YSBhbmQgX3JlbW92ZURhdGEgaGF2ZSBiZWVuIHJlcGxhY2VkXG5cdC8vIHdpdGggZGlyZWN0IGNhbGxzIHRvIGRhdGFQcml2IG1ldGhvZHMsIHRoZXNlIGNhbiBiZSBkZXByZWNhdGVkLlxuXHRfZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFQcml2LmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdF9yZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIG5hbWUgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRhdGE6IGZ1bmN0aW9uKCBrZXksIHZhbHVlICkge1xuXHRcdHZhciBpLCBuYW1lLCBkYXRhLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGF0dHJzID0gZWxlbSAmJiBlbGVtLmF0dHJpYnV0ZXM7XG5cblx0XHQvLyBHZXRzIGFsbCB2YWx1ZXNcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdFx0ZGF0YSA9IGRhdGFVc2VyLmdldCggZWxlbSApO1xuXG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAhZGF0YVByaXYuZ2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiICkgKSB7XG5cdFx0XHRcdFx0aSA9IGF0dHJzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0XHRcdFx0Ly8gVGhlIGF0dHJzIGVsZW1lbnRzIGNhbiBiZSBudWxsICgjMTQ4OTQpXG5cdFx0XHRcdFx0XHRpZiAoIGF0dHJzWyBpIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG5hbWUgPSBhdHRyc1sgaSBdLm5hbWU7XG5cdFx0XHRcdFx0XHRcdGlmICggbmFtZS5pbmRleE9mKCBcImRhdGEtXCIgKSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZS5zbGljZSggNSApICk7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUF0dHIoIGVsZW0sIG5hbWUsIGRhdGFbIG5hbWUgXSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFQcml2LnNldCggZWxlbSwgXCJoYXNEYXRhQXR0cnNcIiwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdH1cblxuXHRcdC8vIFNldHMgbXVsdGlwbGUgdmFsdWVzXG5cdFx0aWYgKCB0eXBlb2Yga2V5ID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFVc2VyLnNldCggdGhpcywga2V5ICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGRhdGE7XG5cblx0XHRcdC8vIFRoZSBjYWxsaW5nIGpRdWVyeSBvYmplY3QgKGVsZW1lbnQgbWF0Y2hlcykgaXMgbm90IGVtcHR5XG5cdFx0XHQvLyAoYW5kIHRoZXJlZm9yZSBoYXMgYW4gZWxlbWVudCBhcHBlYXJzIGF0IHRoaXNbIDAgXSkgYW5kIHRoZVxuXHRcdFx0Ly8gYHZhbHVlYCBwYXJhbWV0ZXIgd2FzIG5vdCB1bmRlZmluZWQuIEFuIGVtcHR5IGpRdWVyeSBvYmplY3Rcblx0XHRcdC8vIHdpbGwgcmVzdWx0IGluIGB1bmRlZmluZWRgIGZvciBlbGVtID0gdGhpc1sgMCBdIHdoaWNoIHdpbGxcblx0XHRcdC8vIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBhbiBhdHRlbXB0IHRvIHJlYWQgYSBkYXRhIGNhY2hlIGlzIG1hZGUuXG5cdFx0XHRpZiAoIGVsZW0gJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHQvLyBBdHRlbXB0IHRvIGdldCBkYXRhIGZyb20gdGhlIGNhY2hlXG5cdFx0XHRcdC8vIFRoZSBrZXkgd2lsbCBhbHdheXMgYmUgY2FtZWxDYXNlZCBpbiBEYXRhXG5cdFx0XHRcdGRhdGEgPSBkYXRhVXNlci5nZXQoIGVsZW0sIGtleSApO1xuXHRcdFx0XHRpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gXCJkaXNjb3ZlclwiIHRoZSBkYXRhIGluXG5cdFx0XHRcdC8vIEhUTUw1IGN1c3RvbSBkYXRhLSogYXR0cnNcblx0XHRcdFx0ZGF0YSA9IGRhdGFBdHRyKCBlbGVtLCBrZXkgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB0cmllZCByZWFsbHkgaGFyZCwgYnV0IHRoZSBkYXRhIGRvZXNuJ3QgZXhpc3QuXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IHRoZSBkYXRhLi4uXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdC8vIFdlIGFsd2F5cyBzdG9yZSB0aGUgY2FtZWxDYXNlZCBrZXlcblx0XHRcdFx0ZGF0YVVzZXIuc2V0KCB0aGlzLCBrZXksIHZhbHVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fSwgbnVsbCwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxLCBudWxsLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlRGF0YTogZnVuY3Rpb24oIGtleSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGRhdGFVc2VyLnJlbW92ZSggdGhpcywga2V5ICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHF1ZXVlO1xuXG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0dHlwZSA9ICggdHlwZSB8fCBcImZ4XCIgKSArIFwicXVldWVcIjtcblx0XHRcdHF1ZXVlID0gZGF0YVByaXYuZ2V0KCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdC8vIFNwZWVkIHVwIGRlcXVldWUgYnkgZ2V0dGluZyBvdXQgcXVpY2tseSBpZiB0aGlzIGlzIGp1c3QgYSBsb29rdXBcblx0XHRcdGlmICggZGF0YSApIHtcblx0XHRcdFx0aWYgKCAhcXVldWUgfHwgQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdHF1ZXVlID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCB0eXBlLCBqUXVlcnkubWFrZUFycmF5KCBkYXRhICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBxdWV1ZSB8fCBbXTtcblx0XHR9XG5cdH0sXG5cblx0ZGVxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0dmFyIHF1ZXVlID0galF1ZXJ5LnF1ZXVlKCBlbGVtLCB0eXBlICksXG5cdFx0XHRzdGFydExlbmd0aCA9IHF1ZXVlLmxlbmd0aCxcblx0XHRcdGZuID0gcXVldWUuc2hpZnQoKSxcblx0XHRcdGhvb2tzID0galF1ZXJ5Ll9xdWV1ZUhvb2tzKCBlbGVtLCB0eXBlICksXG5cdFx0XHRuZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCBlbGVtLCB0eXBlICk7XG5cdFx0XHR9O1xuXG5cdFx0Ly8gSWYgdGhlIGZ4IHF1ZXVlIGlzIGRlcXVldWVkLCBhbHdheXMgcmVtb3ZlIHRoZSBwcm9ncmVzcyBzZW50aW5lbFxuXHRcdGlmICggZm4gPT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0c3RhcnRMZW5ndGgtLTtcblx0XHR9XG5cblx0XHRpZiAoIGZuICkge1xuXG5cdFx0XHQvLyBBZGQgYSBwcm9ncmVzcyBzZW50aW5lbCB0byBwcmV2ZW50IHRoZSBmeCBxdWV1ZSBmcm9tIGJlaW5nXG5cdFx0XHQvLyBhdXRvbWF0aWNhbGx5IGRlcXVldWVkXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiApIHtcblx0XHRcdFx0cXVldWUudW5zaGlmdCggXCJpbnByb2dyZXNzXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2xlYXIgdXAgdGhlIGxhc3QgcXVldWUgc3RvcCBmdW5jdGlvblxuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRmbi5jYWxsKCBlbGVtLCBuZXh0LCBob29rcyApO1xuXHRcdH1cblxuXHRcdGlmICggIXN0YXJ0TGVuZ3RoICYmIGhvb2tzICkge1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBOb3QgcHVibGljIC0gZ2VuZXJhdGUgYSBxdWV1ZUhvb2tzIG9iamVjdCwgb3IgcmV0dXJuIHRoZSBjdXJyZW50IG9uZVxuXHRfcXVldWVIb29rczogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dmFyIGtleSA9IHR5cGUgKyBcInF1ZXVlSG9va3NcIjtcblx0XHRyZXR1cm4gZGF0YVByaXYuZ2V0KCBlbGVtLCBrZXkgKSB8fCBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIGtleSwge1xuXHRcdFx0ZW1wdHk6IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLmFkZCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgWyB0eXBlICsgXCJxdWV1ZVwiLCBrZXkgXSApO1xuXHRcdFx0fSApXG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0cXVldWU6IGZ1bmN0aW9uKCB0eXBlLCBkYXRhICkge1xuXHRcdHZhciBzZXR0ZXIgPSAyO1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGRhdGEgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IFwiZnhcIjtcblx0XHRcdHNldHRlci0tO1xuXHRcdH1cblxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCA8IHNldHRlciApIHtcblx0XHRcdHJldHVybiBqUXVlcnkucXVldWUoIHRoaXNbIDAgXSwgdHlwZSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRhID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcyA6XG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIHRoaXMsIHR5cGUsIGRhdGEgKTtcblxuXHRcdFx0XHQvLyBFbnN1cmUgYSBob29rcyBmb3IgdGhpcyBxdWV1ZVxuXHRcdFx0XHRqUXVlcnkuX3F1ZXVlSG9va3MoIHRoaXMsIHR5cGUgKTtcblxuXHRcdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiAmJiBxdWV1ZVsgMCBdICE9PSBcImlucHJvZ3Jlc3NcIiApIHtcblx0XHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdH0sXG5cdGRlcXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIHR5cGUgKTtcblx0XHR9ICk7XG5cdH0sXG5cdGNsZWFyUXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0fSxcblxuXHQvLyBHZXQgYSBwcm9taXNlIHJlc29sdmVkIHdoZW4gcXVldWVzIG9mIGEgY2VydGFpbiB0eXBlXG5cdC8vIGFyZSBlbXB0aWVkIChmeCBpcyB0aGUgdHlwZSBieSBkZWZhdWx0KVxuXHRwcm9taXNlOiBmdW5jdGlvbiggdHlwZSwgb2JqICkge1xuXHRcdHZhciB0bXAsXG5cdFx0XHRjb3VudCA9IDEsXG5cdFx0XHRkZWZlciA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0ZWxlbWVudHMgPSB0aGlzLFxuXHRcdFx0aSA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0cmVzb2x2ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICEoIC0tY291bnQgKSApIHtcblx0XHRcdFx0XHRkZWZlci5yZXNvbHZlV2l0aCggZWxlbWVudHMsIFsgZWxlbWVudHMgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG9iaiA9IHR5cGU7XG5cdFx0XHR0eXBlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdHRtcCA9IGRhdGFQcml2LmdldCggZWxlbWVudHNbIGkgXSwgdHlwZSArIFwicXVldWVIb29rc1wiICk7XG5cdFx0XHRpZiAoIHRtcCAmJiB0bXAuZW1wdHkgKSB7XG5cdFx0XHRcdGNvdW50Kys7XG5cdFx0XHRcdHRtcC5lbXB0eS5hZGQoIHJlc29sdmUgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVzb2x2ZSgpO1xuXHRcdHJldHVybiBkZWZlci5wcm9taXNlKCBvYmogKTtcblx0fVxufSApO1xudmFyIHBudW0gPSAoIC9bKy1dPyg/OlxcZCpcXC58KVxcZCsoPzpbZUVdWystXT9cXGQrfCkvICkuc291cmNlO1xuXG52YXIgcmNzc051bSA9IG5ldyBSZWdFeHAoIFwiXig/OihbKy1dKT18KShcIiArIHBudW0gKyBcIikoW2EteiVdKikkXCIsIFwiaVwiICk7XG5cblxudmFyIGNzc0V4cGFuZCA9IFsgXCJUb3BcIiwgXCJSaWdodFwiLCBcIkJvdHRvbVwiLCBcIkxlZnRcIiBdO1xuXG52YXIgaXNIaWRkZW5XaXRoaW5UcmVlID0gZnVuY3Rpb24oIGVsZW0sIGVsICkge1xuXG5cdFx0Ly8gaXNIaWRkZW5XaXRoaW5UcmVlIG1pZ2h0IGJlIGNhbGxlZCBmcm9tIGpRdWVyeSNmaWx0ZXIgZnVuY3Rpb247XG5cdFx0Ly8gaW4gdGhhdCBjYXNlLCBlbGVtZW50IHdpbGwgYmUgc2Vjb25kIGFyZ3VtZW50XG5cdFx0ZWxlbSA9IGVsIHx8IGVsZW07XG5cblx0XHQvLyBJbmxpbmUgc3R5bGUgdHJ1bXBzIGFsbFxuXHRcdHJldHVybiBlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwibm9uZVwiIHx8XG5cdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwiXCIgJiZcblxuXHRcdFx0Ly8gT3RoZXJ3aXNlLCBjaGVjayBjb21wdXRlZCBzdHlsZVxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCA8PTQzIC0gNDVcblx0XHRcdC8vIERpc2Nvbm5lY3RlZCBlbGVtZW50cyBjYW4gaGF2ZSBjb21wdXRlZCBkaXNwbGF5OiBub25lLCBzbyBmaXJzdCBjb25maXJtIHRoYXQgZWxlbSBpc1xuXHRcdFx0Ly8gaW4gdGhlIGRvY3VtZW50LlxuXHRcdFx0alF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKSAmJlxuXG5cdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApID09PSBcIm5vbmVcIjtcblx0fTtcblxudmFyIHN3YXAgPSBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgY2FsbGJhY2ssIGFyZ3MgKSB7XG5cdHZhciByZXQsIG5hbWUsXG5cdFx0b2xkID0ge307XG5cblx0Ly8gUmVtZW1iZXIgdGhlIG9sZCB2YWx1ZXMsIGFuZCBpbnNlcnQgdGhlIG5ldyBvbmVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRvbGRbIG5hbWUgXSA9IGVsZW0uc3R5bGVbIG5hbWUgXTtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvcHRpb25zWyBuYW1lIF07XG5cdH1cblxuXHRyZXQgPSBjYWxsYmFjay5hcHBseSggZWxlbSwgYXJncyB8fCBbXSApO1xuXG5cdC8vIFJldmVydCB0aGUgb2xkIHZhbHVlc1xuXHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0ZWxlbS5zdHlsZVsgbmFtZSBdID0gb2xkWyBuYW1lIF07XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufTtcblxuXG5cblxuZnVuY3Rpb24gYWRqdXN0Q1NTKCBlbGVtLCBwcm9wLCB2YWx1ZVBhcnRzLCB0d2VlbiApIHtcblx0dmFyIGFkanVzdGVkLFxuXHRcdHNjYWxlID0gMSxcblx0XHRtYXhJdGVyYXRpb25zID0gMjAsXG5cdFx0Y3VycmVudFZhbHVlID0gdHdlZW4gP1xuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiB0d2Vlbi5jdXIoKTtcblx0XHRcdH0gOlxuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wLCBcIlwiICk7XG5cdFx0XHR9LFxuXHRcdGluaXRpYWwgPSBjdXJyZW50VmFsdWUoKSxcblx0XHR1bml0ID0gdmFsdWVQYXJ0cyAmJiB2YWx1ZVBhcnRzWyAzIF0gfHwgKCBqUXVlcnkuY3NzTnVtYmVyWyBwcm9wIF0gPyBcIlwiIDogXCJweFwiICksXG5cblx0XHQvLyBTdGFydGluZyB2YWx1ZSBjb21wdXRhdGlvbiBpcyByZXF1aXJlZCBmb3IgcG90ZW50aWFsIHVuaXQgbWlzbWF0Y2hlc1xuXHRcdGluaXRpYWxJblVuaXQgPSAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSB8fCB1bml0ICE9PSBcInB4XCIgJiYgK2luaXRpYWwgKSAmJlxuXHRcdFx0cmNzc051bS5leGVjKCBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wICkgKTtcblxuXHRpZiAoIGluaXRpYWxJblVuaXQgJiYgaW5pdGlhbEluVW5pdFsgMyBdICE9PSB1bml0ICkge1xuXG5cdFx0Ly8gVHJ1c3QgdW5pdHMgcmVwb3J0ZWQgYnkgalF1ZXJ5LmNzc1xuXHRcdHVuaXQgPSB1bml0IHx8IGluaXRpYWxJblVuaXRbIDMgXTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB3ZSB1cGRhdGUgdGhlIHR3ZWVuIHByb3BlcnRpZXMgbGF0ZXIgb25cblx0XHR2YWx1ZVBhcnRzID0gdmFsdWVQYXJ0cyB8fCBbXTtcblxuXHRcdC8vIEl0ZXJhdGl2ZWx5IGFwcHJveGltYXRlIGZyb20gYSBub256ZXJvIHN0YXJ0aW5nIHBvaW50XG5cdFx0aW5pdGlhbEluVW5pdCA9ICtpbml0aWFsIHx8IDE7XG5cblx0XHRkbyB7XG5cblx0XHRcdC8vIElmIHByZXZpb3VzIGl0ZXJhdGlvbiB6ZXJvZWQgb3V0LCBkb3VibGUgdW50aWwgd2UgZ2V0ICpzb21ldGhpbmcqLlxuXHRcdFx0Ly8gVXNlIHN0cmluZyBmb3IgZG91Ymxpbmcgc28gd2UgZG9uJ3QgYWNjaWRlbnRhbGx5IHNlZSBzY2FsZSBhcyB1bmNoYW5nZWQgYmVsb3dcblx0XHRcdHNjYWxlID0gc2NhbGUgfHwgXCIuNVwiO1xuXG5cdFx0XHQvLyBBZGp1c3QgYW5kIGFwcGx5XG5cdFx0XHRpbml0aWFsSW5Vbml0ID0gaW5pdGlhbEluVW5pdCAvIHNjYWxlO1xuXHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wLCBpbml0aWFsSW5Vbml0ICsgdW5pdCApO1xuXG5cdFx0Ly8gVXBkYXRlIHNjYWxlLCB0b2xlcmF0aW5nIHplcm8gb3IgTmFOIGZyb20gdHdlZW4uY3VyKClcblx0XHQvLyBCcmVhayB0aGUgbG9vcCBpZiBzY2FsZSBpcyB1bmNoYW5nZWQgb3IgcGVyZmVjdCwgb3IgaWYgd2UndmUganVzdCBoYWQgZW5vdWdoLlxuXHRcdH0gd2hpbGUgKFxuXHRcdFx0c2NhbGUgIT09ICggc2NhbGUgPSBjdXJyZW50VmFsdWUoKSAvIGluaXRpYWwgKSAmJiBzY2FsZSAhPT0gMSAmJiAtLW1heEl0ZXJhdGlvbnNcblx0XHQpO1xuXHR9XG5cblx0aWYgKCB2YWx1ZVBhcnRzICkge1xuXHRcdGluaXRpYWxJblVuaXQgPSAraW5pdGlhbEluVW5pdCB8fCAraW5pdGlhbCB8fCAwO1xuXG5cdFx0Ly8gQXBwbHkgcmVsYXRpdmUgb2Zmc2V0ICgrPS8tPSkgaWYgc3BlY2lmaWVkXG5cdFx0YWRqdXN0ZWQgPSB2YWx1ZVBhcnRzWyAxIF0gP1xuXHRcdFx0aW5pdGlhbEluVW5pdCArICggdmFsdWVQYXJ0c1sgMSBdICsgMSApICogdmFsdWVQYXJ0c1sgMiBdIDpcblx0XHRcdCt2YWx1ZVBhcnRzWyAyIF07XG5cdFx0aWYgKCB0d2VlbiApIHtcblx0XHRcdHR3ZWVuLnVuaXQgPSB1bml0O1xuXHRcdFx0dHdlZW4uc3RhcnQgPSBpbml0aWFsSW5Vbml0O1xuXHRcdFx0dHdlZW4uZW5kID0gYWRqdXN0ZWQ7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBhZGp1c3RlZDtcbn1cblxuXG52YXIgZGVmYXVsdERpc3BsYXlNYXAgPSB7fTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKSB7XG5cdHZhciB0ZW1wLFxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudCxcblx0XHRub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUsXG5cdFx0ZGlzcGxheSA9IGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdO1xuXG5cdGlmICggZGlzcGxheSApIHtcblx0XHRyZXR1cm4gZGlzcGxheTtcblx0fVxuXG5cdHRlbXAgPSBkb2MuYm9keS5hcHBlbmRDaGlsZCggZG9jLmNyZWF0ZUVsZW1lbnQoIG5vZGVOYW1lICkgKTtcblx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIHRlbXAsIFwiZGlzcGxheVwiICk7XG5cblx0dGVtcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCB0ZW1wICk7XG5cblx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRkaXNwbGF5ID0gXCJibG9ja1wiO1xuXHR9XG5cdGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdID0gZGlzcGxheTtcblxuXHRyZXR1cm4gZGlzcGxheTtcbn1cblxuZnVuY3Rpb24gc2hvd0hpZGUoIGVsZW1lbnRzLCBzaG93ICkge1xuXHR2YXIgZGlzcGxheSwgZWxlbSxcblx0XHR2YWx1ZXMgPSBbXSxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoO1xuXG5cdC8vIERldGVybWluZSBuZXcgZGlzcGxheSB2YWx1ZSBmb3IgZWxlbWVudHMgdGhhdCBuZWVkIHRvIGNoYW5nZVxuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGVsZW0gPSBlbGVtZW50c1sgaW5kZXggXTtcblx0XHRpZiAoICFlbGVtLnN0eWxlICkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0ZGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheTtcblx0XHRpZiAoIHNob3cgKSB7XG5cblx0XHRcdC8vIFNpbmNlIHdlIGZvcmNlIHZpc2liaWxpdHkgdXBvbiBjYXNjYWRlLWhpZGRlbiBlbGVtZW50cywgYW4gaW1tZWRpYXRlIChhbmQgc2xvdylcblx0XHRcdC8vIGNoZWNrIGlzIHJlcXVpcmVkIGluIHRoaXMgZmlyc3QgbG9vcCB1bmxlc3Mgd2UgaGF2ZSBhIG5vbmVtcHR5IGRpc3BsYXkgdmFsdWUgKGVpdGhlclxuXHRcdFx0Ly8gaW5saW5lIG9yIGFib3V0LXRvLWJlLXJlc3RvcmVkKVxuXHRcdFx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApIHx8IG51bGw7XG5cdFx0XHRcdGlmICggIXZhbHVlc1sgaW5kZXggXSApIHtcblx0XHRcdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJcIiAmJiBpc0hpZGRlbldpdGhpblRyZWUoIGVsZW0gKSApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBkaXNwbGF5ICE9PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gXCJub25lXCI7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgd2hhdCB3ZSdyZSBvdmVyd3JpdGluZ1xuXHRcdFx0XHRkYXRhUHJpdi5zZXQoIGVsZW0sIFwiZGlzcGxheVwiLCBkaXNwbGF5ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gU2V0IHRoZSBkaXNwbGF5IG9mIHRoZSBlbGVtZW50cyBpbiBhIHNlY29uZCBsb29wIHRvIGF2b2lkIGNvbnN0YW50IHJlZmxvd1xuXHRmb3IgKCBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGlmICggdmFsdWVzWyBpbmRleCBdICE9IG51bGwgKSB7XG5cdFx0XHRlbGVtZW50c1sgaW5kZXggXS5zdHlsZS5kaXNwbGF5ID0gdmFsdWVzWyBpbmRleCBdO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50cztcbn1cblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRzaG93OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMsIHRydWUgKTtcblx0fSxcblx0aGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNob3dIaWRlKCB0aGlzICk7XG5cdH0sXG5cdHRvZ2dsZTogZnVuY3Rpb24oIHN0YXRlICkge1xuXHRcdGlmICggdHlwZW9mIHN0YXRlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdHJldHVybiBzdGF0ZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGlzSGlkZGVuV2l0aGluVHJlZSggdGhpcyApICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5zaG93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG52YXIgcmNoZWNrYWJsZVR5cGUgPSAoIC9eKD86Y2hlY2tib3h8cmFkaW8pJC9pICk7XG5cbnZhciBydGFnTmFtZSA9ICggLzwoW2Etel1bXlxcL1xcMD5cXHgyMFxcdFxcclxcblxcZl0rKS9pICk7XG5cbnZhciByc2NyaXB0VHlwZSA9ICggL14kfFxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSApO1xuXG5cblxuLy8gV2UgaGF2ZSB0byBjbG9zZSB0aGVzZSB0YWdzIHRvIHN1cHBvcnQgWEhUTUwgKCMxMzIwMClcbnZhciB3cmFwTWFwID0ge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdG9wdGlvbjogWyAxLCBcIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz5cIiwgXCI8L3NlbGVjdD5cIiBdLFxuXG5cdC8vIFhIVE1MIHBhcnNlcnMgZG8gbm90IG1hZ2ljYWxseSBpbnNlcnQgZWxlbWVudHMgaW4gdGhlXG5cdC8vIHNhbWUgd2F5IHRoYXQgdGFnIHNvdXAgcGFyc2VycyBkby4gU28gd2UgY2Fubm90IHNob3J0ZW5cblx0Ly8gdGhpcyBieSBvbWl0dGluZyA8dGJvZHk+IG9yIG90aGVyIHJlcXVpcmVkIGVsZW1lbnRzLlxuXHR0aGVhZDogWyAxLCBcIjx0YWJsZT5cIiwgXCI8L3RhYmxlPlwiIF0sXG5cdGNvbDogWyAyLCBcIjx0YWJsZT48Y29sZ3JvdXA+XCIsIFwiPC9jb2xncm91cD48L3RhYmxlPlwiIF0sXG5cdHRyOiBbIDIsIFwiPHRhYmxlPjx0Ym9keT5cIiwgXCI8L3Rib2R5PjwvdGFibGU+XCIgXSxcblx0dGQ6IFsgMywgXCI8dGFibGU+PHRib2R5Pjx0cj5cIiwgXCI8L3RyPjwvdGJvZHk+PC90YWJsZT5cIiBdLFxuXG5cdF9kZWZhdWx0OiBbIDAsIFwiXCIsIFwiXCIgXVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbndyYXBNYXAub3B0Z3JvdXAgPSB3cmFwTWFwLm9wdGlvbjtcblxud3JhcE1hcC50Ym9keSA9IHdyYXBNYXAudGZvb3QgPSB3cmFwTWFwLmNvbGdyb3VwID0gd3JhcE1hcC5jYXB0aW9uID0gd3JhcE1hcC50aGVhZDtcbndyYXBNYXAudGggPSB3cmFwTWFwLnRkO1xuXG5cbmZ1bmN0aW9uIGdldEFsbCggY29udGV4dCwgdGFnICkge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0Ly8gVXNlIHR5cGVvZiB0byBhdm9pZCB6ZXJvLWFyZ3VtZW50IG1ldGhvZCBpbnZvY2F0aW9uIG9uIGhvc3Qgb2JqZWN0cyAoIzE1MTUxKVxuXHR2YXIgcmV0O1xuXG5cdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0cmV0ID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnIHx8IFwiKlwiICk7XG5cblx0fSBlbHNlIGlmICggdHlwZW9mIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRyZXQgPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIHRhZyB8fCBcIipcIiApO1xuXG5cdH0gZWxzZSB7XG5cdFx0cmV0ID0gW107XG5cdH1cblxuXHRpZiAoIHRhZyA9PT0gdW5kZWZpbmVkIHx8IHRhZyAmJiBub2RlTmFtZSggY29udGV4dCwgdGFnICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5tZXJnZSggWyBjb250ZXh0IF0sIHJldCApO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuXG4vLyBNYXJrIHNjcmlwdHMgYXMgaGF2aW5nIGFscmVhZHkgYmVlbiBldmFsdWF0ZWRcbmZ1bmN0aW9uIHNldEdsb2JhbEV2YWwoIGVsZW1zLCByZWZFbGVtZW50cyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdGRhdGFQcml2LnNldChcblx0XHRcdGVsZW1zWyBpIF0sXG5cdFx0XHRcImdsb2JhbEV2YWxcIixcblx0XHRcdCFyZWZFbGVtZW50cyB8fCBkYXRhUHJpdi5nZXQoIHJlZkVsZW1lbnRzWyBpIF0sIFwiZ2xvYmFsRXZhbFwiIClcblx0XHQpO1xuXHR9XG59XG5cblxudmFyIHJodG1sID0gLzx8JiM/XFx3KzsvO1xuXG5mdW5jdGlvbiBidWlsZEZyYWdtZW50KCBlbGVtcywgY29udGV4dCwgc2NyaXB0cywgc2VsZWN0aW9uLCBpZ25vcmVkICkge1xuXHR2YXIgZWxlbSwgdG1wLCB0YWcsIHdyYXAsIGNvbnRhaW5zLCBqLFxuXHRcdGZyYWdtZW50ID0gY29udGV4dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksXG5cdFx0bm9kZXMgPSBbXSxcblx0XHRpID0gMCxcblx0XHRsID0gZWxlbXMubGVuZ3RoO1xuXG5cdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRlbGVtID0gZWxlbXNbIGkgXTtcblxuXHRcdGlmICggZWxlbSB8fCBlbGVtID09PSAwICkge1xuXG5cdFx0XHQvLyBBZGQgbm9kZXMgZGlyZWN0bHlcblx0XHRcdGlmICggalF1ZXJ5LnR5cGUoIGVsZW0gKSA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0XHRcdFx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIG5vZGVzLCBlbGVtLm5vZGVUeXBlID8gWyBlbGVtIF0gOiBlbGVtICk7XG5cblx0XHRcdC8vIENvbnZlcnQgbm9uLWh0bWwgaW50byBhIHRleHQgbm9kZVxuXHRcdFx0fSBlbHNlIGlmICggIXJodG1sLnRlc3QoIGVsZW0gKSApIHtcblx0XHRcdFx0bm9kZXMucHVzaCggY29udGV4dC5jcmVhdGVUZXh0Tm9kZSggZWxlbSApICk7XG5cblx0XHRcdC8vIENvbnZlcnQgaHRtbCBpbnRvIERPTSBub2Rlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dG1wID0gdG1wIHx8IGZyYWdtZW50LmFwcGVuZENoaWxkKCBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSApO1xuXG5cdFx0XHRcdC8vIERlc2VyaWFsaXplIGEgc3RhbmRhcmQgcmVwcmVzZW50YXRpb25cblx0XHRcdFx0dGFnID0gKCBydGFnTmFtZS5leGVjKCBlbGVtICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdHdyYXAgPSB3cmFwTWFwWyB0YWcgXSB8fCB3cmFwTWFwLl9kZWZhdWx0O1xuXHRcdFx0XHR0bXAuaW5uZXJIVE1MID0gd3JhcFsgMSBdICsgalF1ZXJ5Lmh0bWxQcmVmaWx0ZXIoIGVsZW0gKSArIHdyYXBbIDIgXTtcblxuXHRcdFx0XHQvLyBEZXNjZW5kIHRocm91Z2ggd3JhcHBlcnMgdG8gdGhlIHJpZ2h0IGNvbnRlbnRcblx0XHRcdFx0aiA9IHdyYXBbIDAgXTtcblx0XHRcdFx0d2hpbGUgKCBqLS0gKSB7XG5cdFx0XHRcdFx0dG1wID0gdG1wLmxhc3RDaGlsZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIHRtcC5jaGlsZE5vZGVzICk7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgdGhlIHRvcC1sZXZlbCBjb250YWluZXJcblx0XHRcdFx0dG1wID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuXHRcdFx0XHQvLyBFbnN1cmUgdGhlIGNyZWF0ZWQgbm9kZXMgYXJlIG9ycGhhbmVkICgjMTIzOTIpXG5cdFx0XHRcdHRtcC50ZXh0Q29udGVudCA9IFwiXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmVtb3ZlIHdyYXBwZXIgZnJvbSBmcmFnbWVudFxuXHRmcmFnbWVudC50ZXh0Q29udGVudCA9IFwiXCI7XG5cblx0aSA9IDA7XG5cdHdoaWxlICggKCBlbGVtID0gbm9kZXNbIGkrKyBdICkgKSB7XG5cblx0XHQvLyBTa2lwIGVsZW1lbnRzIGFscmVhZHkgaW4gdGhlIGNvbnRleHQgY29sbGVjdGlvbiAodHJhYy00MDg3KVxuXHRcdGlmICggc2VsZWN0aW9uICYmIGpRdWVyeS5pbkFycmF5KCBlbGVtLCBzZWxlY3Rpb24gKSA+IC0xICkge1xuXHRcdFx0aWYgKCBpZ25vcmVkICkge1xuXHRcdFx0XHRpZ25vcmVkLnB1c2goIGVsZW0gKTtcblx0XHRcdH1cblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblxuXHRcdGNvbnRhaW5zID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdC8vIEFwcGVuZCB0byBmcmFnbWVudFxuXHRcdHRtcCA9IGdldEFsbCggZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGVsZW0gKSwgXCJzY3JpcHRcIiApO1xuXG5cdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdGlmICggY29udGFpbnMgKSB7XG5cdFx0XHRzZXRHbG9iYWxFdmFsKCB0bXAgKTtcblx0XHR9XG5cblx0XHQvLyBDYXB0dXJlIGV4ZWN1dGFibGVzXG5cdFx0aWYgKCBzY3JpcHRzICkge1xuXHRcdFx0aiA9IDA7XG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRtcFsgaisrIF0gKSApIHtcblx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBlbGVtLnR5cGUgfHwgXCJcIiApICkge1xuXHRcdFx0XHRcdHNjcmlwdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGZyYWdtZW50O1xufVxuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRkaXYgPSBmcmFnbWVudC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApICksXG5cdFx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCAtIDQuMyBvbmx5XG5cdC8vIENoZWNrIHN0YXRlIGxvc3QgaWYgdGhlIG5hbWUgaXMgc2V0ICgjMTEyMTcpXG5cdC8vIFN1cHBvcnQ6IFdpbmRvd3MgV2ViIEFwcHMgKFdXQSlcblx0Ly8gYG5hbWVgIGFuZCBgdHlwZWAgbXVzdCB1c2UgLnNldEF0dHJpYnV0ZSBmb3IgV1dBICgjMTQ5MDEpXG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIFwicmFkaW9cIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwiY2hlY2tlZFwiLCBcImNoZWNrZWRcIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcInRcIiApO1xuXG5cdGRpdi5hcHBlbmRDaGlsZCggaW5wdXQgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4xIG9ubHlcblx0Ly8gT2xkZXIgV2ViS2l0IGRvZXNuJ3QgY2xvbmUgY2hlY2tlZCBzdGF0ZSBjb3JyZWN0bHkgaW4gZnJhZ21lbnRzXG5cdHN1cHBvcnQuY2hlY2tDbG9uZSA9IGRpdi5jbG9uZU5vZGUoIHRydWUgKS5jbG9uZU5vZGUoIHRydWUgKS5sYXN0Q2hpbGQuY2hlY2tlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHRleHRhcmVhIChhbmQgY2hlY2tib3gpIGRlZmF1bHRWYWx1ZSBpcyBwcm9wZXJseSBjbG9uZWRcblx0ZGl2LmlubmVySFRNTCA9IFwiPHRleHRhcmVhPng8L3RleHRhcmVhPlwiO1xuXHRzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkID0gISFkaXYuY2xvbmVOb2RlKCB0cnVlICkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZTtcbn0gKSgpO1xudmFyIGRvY3VtZW50RWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuXG5cbnZhclxuXHRya2V5RXZlbnQgPSAvXmtleS8sXG5cdHJtb3VzZUV2ZW50ID0gL14oPzptb3VzZXxwb2ludGVyfGNvbnRleHRtZW51fGRyYWd8ZHJvcCl8Y2xpY2svLFxuXHRydHlwZW5hbWVzcGFjZSA9IC9eKFteLl0qKSg/OlxcLiguKyl8KS87XG5cbmZ1bmN0aW9uIHJldHVyblRydWUoKSB7XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZXR1cm5GYWxzZSgpIHtcblx0cmV0dXJuIGZhbHNlO1xufVxuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuLy8gU2VlICMxMzM5MyBmb3IgbW9yZSBpbmZvXG5mdW5jdGlvbiBzYWZlQWN0aXZlRWxlbWVudCgpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblx0fSBjYXRjaCAoIGVyciApIHsgfVxufVxuXG5mdW5jdGlvbiBvbiggZWxlbSwgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgb25lICkge1xuXHR2YXIgb3JpZ0ZuLCB0eXBlO1xuXG5cdC8vIFR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xuXHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdC8vICggdHlwZXMtT2JqZWN0LCBzZWxlY3RvciwgZGF0YSApXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMtT2JqZWN0LCBkYXRhIClcblx0XHRcdGRhdGEgPSBkYXRhIHx8IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRvbiggZWxlbSwgdHlwZSwgc2VsZWN0b3IsIGRhdGEsIHR5cGVzWyB0eXBlIF0sIG9uZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbTtcblx0fVxuXG5cdGlmICggZGF0YSA9PSBudWxsICYmIGZuID09IG51bGwgKSB7XG5cblx0XHQvLyAoIHR5cGVzLCBmbiApXG5cdFx0Zm4gPSBzZWxlY3Rvcjtcblx0XHRkYXRhID0gc2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdH0gZWxzZSBpZiAoIGZuID09IG51bGwgKSB7XG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMsIHNlbGVjdG9yLCBmbiApXG5cdFx0XHRmbiA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vICggdHlwZXMsIGRhdGEsIGZuIClcblx0XHRcdGZuID0gZGF0YTtcblx0XHRcdGRhdGEgPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRpZiAoIGZuID09PSBmYWxzZSApIHtcblx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHR9IGVsc2UgaWYgKCAhZm4gKSB7XG5cdFx0cmV0dXJuIGVsZW07XG5cdH1cblxuXHRpZiAoIG9uZSA9PT0gMSApIHtcblx0XHRvcmlnRm4gPSBmbjtcblx0XHRmbiA9IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0Ly8gQ2FuIHVzZSBhbiBlbXB0eSBzZXQsIHNpbmNlIGV2ZW50IGNvbnRhaW5zIHRoZSBpbmZvXG5cdFx0XHRqUXVlcnkoKS5vZmYoIGV2ZW50ICk7XG5cdFx0XHRyZXR1cm4gb3JpZ0ZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9O1xuXG5cdFx0Ly8gVXNlIHNhbWUgZ3VpZCBzbyBjYWxsZXIgY2FuIHJlbW92ZSB1c2luZyBvcmlnRm5cblx0XHRmbi5ndWlkID0gb3JpZ0ZuLmd1aWQgfHwgKCBvcmlnRm4uZ3VpZCA9IGpRdWVyeS5ndWlkKysgKTtcblx0fVxuXHRyZXR1cm4gZWxlbS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRqUXVlcnkuZXZlbnQuYWRkKCB0aGlzLCB0eXBlcywgZm4sIGRhdGEsIHNlbGVjdG9yICk7XG5cdH0gKTtcbn1cblxuLypcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIG1hbmFnaW5nIGV2ZW50cyAtLSBub3QgcGFydCBvZiB0aGUgcHVibGljIGludGVyZmFjZS5cbiAqIFByb3BzIHRvIERlYW4gRWR3YXJkcycgYWRkRXZlbnQgbGlicmFyeSBmb3IgbWFueSBvZiB0aGUgaWRlYXMuXG4gKi9cbmpRdWVyeS5ldmVudCA9IHtcblxuXHRnbG9iYWw6IHt9LFxuXG5cdGFkZDogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBkYXRhLCBzZWxlY3RvciApIHtcblxuXHRcdHZhciBoYW5kbGVPYmpJbiwgZXZlbnRIYW5kbGUsIHRtcCxcblx0XHRcdGV2ZW50cywgdCwgaGFuZGxlT2JqLFxuXHRcdFx0c3BlY2lhbCwgaGFuZGxlcnMsIHR5cGUsIG5hbWVzcGFjZXMsIG9yaWdUeXBlLFxuXHRcdFx0ZWxlbURhdGEgPSBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdC8vIERvbid0IGF0dGFjaCBldmVudHMgdG8gbm9EYXRhIG9yIHRleHQvY29tbWVudCBub2RlcyAoYnV0IGFsbG93IHBsYWluIG9iamVjdHMpXG5cdFx0aWYgKCAhZWxlbURhdGEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGVyIGNhbiBwYXNzIGluIGFuIG9iamVjdCBvZiBjdXN0b20gZGF0YSBpbiBsaWV1IG9mIHRoZSBoYW5kbGVyXG5cdFx0aWYgKCBoYW5kbGVyLmhhbmRsZXIgKSB7XG5cdFx0XHRoYW5kbGVPYmpJbiA9IGhhbmRsZXI7XG5cdFx0XHRoYW5kbGVyID0gaGFuZGxlT2JqSW4uaGFuZGxlcjtcblx0XHRcdHNlbGVjdG9yID0gaGFuZGxlT2JqSW4uc2VsZWN0b3I7XG5cdFx0fVxuXG5cdFx0Ly8gRW5zdXJlIHRoYXQgaW52YWxpZCBzZWxlY3RvcnMgdGhyb3cgZXhjZXB0aW9ucyBhdCBhdHRhY2ggdGltZVxuXHRcdC8vIEV2YWx1YXRlIGFnYWluc3QgZG9jdW1lbnRFbGVtZW50IGluIGNhc2UgZWxlbSBpcyBhIG5vbi1lbGVtZW50IG5vZGUgKGUuZy4sIGRvY3VtZW50KVxuXHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRqUXVlcnkuZmluZC5tYXRjaGVzU2VsZWN0b3IoIGRvY3VtZW50RWxlbWVudCwgc2VsZWN0b3IgKTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB0aGUgaGFuZGxlciBoYXMgYSB1bmlxdWUgSUQsIHVzZWQgdG8gZmluZC9yZW1vdmUgaXQgbGF0ZXJcblx0XHRpZiAoICFoYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRoYW5kbGVyLmd1aWQgPSBqUXVlcnkuZ3VpZCsrO1xuXHRcdH1cblxuXHRcdC8vIEluaXQgdGhlIGVsZW1lbnQncyBldmVudCBzdHJ1Y3R1cmUgYW5kIG1haW4gaGFuZGxlciwgaWYgdGhpcyBpcyB0aGUgZmlyc3Rcblx0XHRpZiAoICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0ZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzID0ge307XG5cdFx0fVxuXHRcdGlmICggISggZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgKSApIHtcblx0XHRcdGV2ZW50SGFuZGxlID0gZWxlbURhdGEuaGFuZGxlID0gZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdFx0Ly8gRGlzY2FyZCB0aGUgc2Vjb25kIGV2ZW50IG9mIGEgalF1ZXJ5LmV2ZW50LnRyaWdnZXIoKSBhbmRcblx0XHRcdFx0Ly8gd2hlbiBhbiBldmVudCBpcyBjYWxsZWQgYWZ0ZXIgYSBwYWdlIGhhcyB1bmxvYWRlZFxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICE9PSBlLnR5cGUgP1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5kaXNwYXRjaC5hcHBseSggZWxlbSwgYXJndW1lbnRzICkgOiB1bmRlZmluZWQ7XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIEhhbmRsZSBtdWx0aXBsZSBldmVudHMgc2VwYXJhdGVkIGJ5IGEgc3BhY2Vcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVGhlcmUgKm11c3QqIGJlIGEgdHlwZSwgbm8gYXR0YWNoaW5nIG5hbWVzcGFjZS1vbmx5IGhhbmRsZXJzXG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgZXZlbnQgY2hhbmdlcyBpdHMgdHlwZSwgdXNlIHRoZSBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgY2hhbmdlZCB0eXBlXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblxuXHRcdFx0Ly8gSWYgc2VsZWN0b3IgZGVmaW5lZCwgZGV0ZXJtaW5lIHNwZWNpYWwgZXZlbnQgYXBpIHR5cGUsIG90aGVyd2lzZSBnaXZlbiB0eXBlXG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cblx0XHRcdC8vIFVwZGF0ZSBzcGVjaWFsIGJhc2VkIG9uIG5ld2x5IHJlc2V0IHR5cGVcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXG5cdFx0XHQvLyBoYW5kbGVPYmogaXMgcGFzc2VkIHRvIGFsbCBldmVudCBoYW5kbGVyc1xuXHRcdFx0aGFuZGxlT2JqID0galF1ZXJ5LmV4dGVuZCgge1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRvcmlnVHlwZTogb3JpZ1R5cGUsXG5cdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdGhhbmRsZXI6IGhhbmRsZXIsXG5cdFx0XHRcdGd1aWQ6IGhhbmRsZXIuZ3VpZCxcblx0XHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0XHRuZWVkc0NvbnRleHQ6IHNlbGVjdG9yICYmIGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KCBzZWxlY3RvciApLFxuXHRcdFx0XHRuYW1lc3BhY2U6IG5hbWVzcGFjZXMuam9pbiggXCIuXCIgKVxuXHRcdFx0fSwgaGFuZGxlT2JqSW4gKTtcblxuXHRcdFx0Ly8gSW5pdCB0aGUgZXZlbnQgaGFuZGxlciBxdWV1ZSBpZiB3ZSdyZSB0aGUgZmlyc3Rcblx0XHRcdGlmICggISggaGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSApICkge1xuXHRcdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdID0gW107XG5cdFx0XHRcdGhhbmRsZXJzLmRlbGVnYXRlQ291bnQgPSAwO1xuXG5cdFx0XHRcdC8vIE9ubHkgdXNlIGFkZEV2ZW50TGlzdGVuZXIgaWYgdGhlIHNwZWNpYWwgZXZlbnRzIGhhbmRsZXIgcmV0dXJucyBmYWxzZVxuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnNldHVwIHx8XG5cdFx0XHRcdFx0c3BlY2lhbC5zZXR1cC5jYWxsKCBlbGVtLCBkYXRhLCBuYW1lc3BhY2VzLCBldmVudEhhbmRsZSApID09PSBmYWxzZSApIHtcblxuXHRcdFx0XHRcdGlmICggZWxlbS5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5hZGRFdmVudExpc3RlbmVyKCB0eXBlLCBldmVudEhhbmRsZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHNwZWNpYWwuYWRkICkge1xuXHRcdFx0XHRzcGVjaWFsLmFkZC5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblxuXHRcdFx0XHRpZiAoICFoYW5kbGVPYmouaGFuZGxlci5ndWlkICkge1xuXHRcdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyLmd1aWQgPSBoYW5kbGVyLmd1aWQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIHRvIHRoZSBlbGVtZW50J3MgaGFuZGxlciBsaXN0LCBkZWxlZ2F0ZXMgaW4gZnJvbnRcblx0XHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaGFuZGxlcnMuZGVsZWdhdGVDb3VudCsrLCAwLCBoYW5kbGVPYmogKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGhhbmRsZXJzLnB1c2goIGhhbmRsZU9iaiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBLZWVwIHRyYWNrIG9mIHdoaWNoIGV2ZW50cyBoYXZlIGV2ZXIgYmVlbiB1c2VkLCBmb3IgZXZlbnQgb3B0aW1pemF0aW9uXG5cdFx0XHRqUXVlcnkuZXZlbnQuZ2xvYmFsWyB0eXBlIF0gPSB0cnVlO1xuXHRcdH1cblxuXHR9LFxuXG5cdC8vIERldGFjaCBhbiBldmVudCBvciBzZXQgb2YgZXZlbnRzIGZyb20gYW4gZWxlbWVudFxuXHRyZW1vdmU6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlcywgaGFuZGxlciwgc2VsZWN0b3IsIG1hcHBlZFR5cGVzICkge1xuXG5cdFx0dmFyIGosIG9yaWdDb3VudCwgdG1wLFxuXHRcdFx0ZXZlbnRzLCB0LCBoYW5kbGVPYmosXG5cdFx0XHRzcGVjaWFsLCBoYW5kbGVycywgdHlwZSwgbmFtZXNwYWNlcywgb3JpZ1R5cGUsXG5cdFx0XHRlbGVtRGF0YSA9IGRhdGFQcml2Lmhhc0RhdGEoIGVsZW0gKSAmJiBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdGlmICggIWVsZW1EYXRhIHx8ICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIE9uY2UgZm9yIGVhY2ggdHlwZS5uYW1lc3BhY2UgaW4gdHlwZXM7IHR5cGUgbWF5IGJlIG9taXR0ZWRcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVW5iaW5kIGFsbCBldmVudHMgKG9uIHRoaXMgbmFtZXNwYWNlLCBpZiBwcm92aWRlZCkgZm9yIHRoZSBlbGVtZW50XG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCBlbGVtLCB0eXBlICsgdHlwZXNbIHQgXSwgaGFuZGxlciwgc2VsZWN0b3IsIHRydWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdIHx8IFtdO1xuXHRcdFx0dG1wID0gdG1wWyAyIF0gJiZcblx0XHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICk7XG5cblx0XHRcdC8vIFJlbW92ZSBtYXRjaGluZyBldmVudHNcblx0XHRcdG9yaWdDb3VudCA9IGogPSBoYW5kbGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGogXTtcblxuXHRcdFx0XHRpZiAoICggbWFwcGVkVHlwZXMgfHwgb3JpZ1R5cGUgPT09IGhhbmRsZU9iai5vcmlnVHlwZSApICYmXG5cdFx0XHRcdFx0KCAhaGFuZGxlciB8fCBoYW5kbGVyLmd1aWQgPT09IGhhbmRsZU9iai5ndWlkICkgJiZcblx0XHRcdFx0XHQoICF0bXAgfHwgdG1wLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApICYmXG5cdFx0XHRcdFx0KCAhc2VsZWN0b3IgfHwgc2VsZWN0b3IgPT09IGhhbmRsZU9iai5zZWxlY3RvciB8fFxuXHRcdFx0XHRcdFx0c2VsZWN0b3IgPT09IFwiKipcIiAmJiBoYW5kbGVPYmouc2VsZWN0b3IgKSApIHtcblx0XHRcdFx0XHRoYW5kbGVycy5zcGxpY2UoIGosIDEgKTtcblxuXHRcdFx0XHRcdGlmICggaGFuZGxlT2JqLnNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudC0tO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIHNwZWNpYWwucmVtb3ZlICkge1xuXHRcdFx0XHRcdFx0c3BlY2lhbC5yZW1vdmUuY2FsbCggZWxlbSwgaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlbW92ZSBnZW5lcmljIGV2ZW50IGhhbmRsZXIgaWYgd2UgcmVtb3ZlZCBzb21ldGhpbmcgYW5kIG5vIG1vcmUgaGFuZGxlcnMgZXhpc3Rcblx0XHRcdC8vIChhdm9pZHMgcG90ZW50aWFsIGZvciBlbmRsZXNzIHJlY3Vyc2lvbiBkdXJpbmcgcmVtb3ZhbCBvZiBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzKVxuXHRcdFx0aWYgKCBvcmlnQ291bnQgJiYgIWhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0aWYgKCAhc3BlY2lhbC50ZWFyZG93biB8fFxuXHRcdFx0XHRcdHNwZWNpYWwudGVhcmRvd24uY2FsbCggZWxlbSwgbmFtZXNwYWNlcywgZWxlbURhdGEuaGFuZGxlICkgPT09IGZhbHNlICkge1xuXG5cdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBlbGVtRGF0YS5oYW5kbGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlbGV0ZSBldmVudHNbIHR5cGUgXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgZGF0YSBhbmQgdGhlIGV4cGFuZG8gaWYgaXQncyBubyBsb25nZXIgdXNlZFxuXHRcdGlmICggalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGV2ZW50cyApICkge1xuXHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBlbGVtLCBcImhhbmRsZSBldmVudHNcIiApO1xuXHRcdH1cblx0fSxcblxuXHRkaXNwYXRjaDogZnVuY3Rpb24oIG5hdGl2ZUV2ZW50ICkge1xuXG5cdFx0Ly8gTWFrZSBhIHdyaXRhYmxlIGpRdWVyeS5FdmVudCBmcm9tIHRoZSBuYXRpdmUgZXZlbnQgb2JqZWN0XG5cdFx0dmFyIGV2ZW50ID0galF1ZXJ5LmV2ZW50LmZpeCggbmF0aXZlRXZlbnQgKTtcblxuXHRcdHZhciBpLCBqLCByZXQsIG1hdGNoZWQsIGhhbmRsZU9iaiwgaGFuZGxlclF1ZXVlLFxuXHRcdFx0YXJncyA9IG5ldyBBcnJheSggYXJndW1lbnRzLmxlbmd0aCApLFxuXHRcdFx0aGFuZGxlcnMgPSAoIGRhdGFQcml2LmdldCggdGhpcywgXCJldmVudHNcIiApIHx8IHt9IClbIGV2ZW50LnR5cGUgXSB8fCBbXSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZXZlbnQudHlwZSBdIHx8IHt9O1xuXG5cdFx0Ly8gVXNlIHRoZSBmaXgtZWQgalF1ZXJ5LkV2ZW50IHJhdGhlciB0aGFuIHRoZSAocmVhZC1vbmx5KSBuYXRpdmUgZXZlbnRcblx0XHRhcmdzWyAwIF0gPSBldmVudDtcblxuXHRcdGZvciAoIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0YXJnc1sgaSBdID0gYXJndW1lbnRzWyBpIF07XG5cdFx0fVxuXG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSB0aGlzO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgcHJlRGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlLCBhbmQgbGV0IGl0IGJhaWwgaWYgZGVzaXJlZFxuXHRcdGlmICggc3BlY2lhbC5wcmVEaXNwYXRjaCAmJiBzcGVjaWFsLnByZURpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBoYW5kbGVyc1xuXHRcdGhhbmRsZXJRdWV1ZSA9IGpRdWVyeS5ldmVudC5oYW5kbGVycy5jYWxsKCB0aGlzLCBldmVudCwgaGFuZGxlcnMgKTtcblxuXHRcdC8vIFJ1biBkZWxlZ2F0ZXMgZmlyc3Q7IHRoZXkgbWF5IHdhbnQgdG8gc3RvcCBwcm9wYWdhdGlvbiBiZW5lYXRoIHVzXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoIG1hdGNoZWQgPSBoYW5kbGVyUXVldWVbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cdFx0XHRldmVudC5jdXJyZW50VGFyZ2V0ID0gbWF0Y2hlZC5lbGVtO1xuXG5cdFx0XHRqID0gMDtcblx0XHRcdHdoaWxlICggKCBoYW5kbGVPYmogPSBtYXRjaGVkLmhhbmRsZXJzWyBqKysgXSApICYmXG5cdFx0XHRcdCFldmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpICkge1xuXG5cdFx0XHRcdC8vIFRyaWdnZXJlZCBldmVudCBtdXN0IGVpdGhlciAxKSBoYXZlIG5vIG5hbWVzcGFjZSwgb3IgMikgaGF2ZSBuYW1lc3BhY2Uocylcblx0XHRcdFx0Ly8gYSBzdWJzZXQgb3IgZXF1YWwgdG8gdGhvc2UgaW4gdGhlIGJvdW5kIGV2ZW50IChib3RoIGNhbiBoYXZlIG5vIG5hbWVzcGFjZSkuXG5cdFx0XHRcdGlmICggIWV2ZW50LnJuYW1lc3BhY2UgfHwgZXZlbnQucm5hbWVzcGFjZS50ZXN0KCBoYW5kbGVPYmoubmFtZXNwYWNlICkgKSB7XG5cblx0XHRcdFx0XHRldmVudC5oYW5kbGVPYmogPSBoYW5kbGVPYmo7XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSA9IGhhbmRsZU9iai5kYXRhO1xuXG5cdFx0XHRcdFx0cmV0ID0gKCAoIGpRdWVyeS5ldmVudC5zcGVjaWFsWyBoYW5kbGVPYmoub3JpZ1R5cGUgXSB8fCB7fSApLmhhbmRsZSB8fFxuXHRcdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIgKS5hcHBseSggbWF0Y2hlZC5lbGVtLCBhcmdzICk7XG5cblx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoIGV2ZW50LnJlc3VsdCA9IHJldCApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbCB0aGUgcG9zdERpc3BhdGNoIGhvb2sgZm9yIHRoZSBtYXBwZWQgdHlwZVxuXHRcdGlmICggc3BlY2lhbC5wb3N0RGlzcGF0Y2ggKSB7XG5cdFx0XHRzcGVjaWFsLnBvc3REaXNwYXRjaC5jYWxsKCB0aGlzLCBldmVudCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBldmVudC5yZXN1bHQ7XG5cdH0sXG5cblx0aGFuZGxlcnM6IGZ1bmN0aW9uKCBldmVudCwgaGFuZGxlcnMgKSB7XG5cdFx0dmFyIGksIGhhbmRsZU9iaiwgc2VsLCBtYXRjaGVkSGFuZGxlcnMsIG1hdGNoZWRTZWxlY3RvcnMsXG5cdFx0XHRoYW5kbGVyUXVldWUgPSBbXSxcblx0XHRcdGRlbGVnYXRlQ291bnQgPSBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LFxuXHRcdFx0Y3VyID0gZXZlbnQudGFyZ2V0O1xuXG5cdFx0Ly8gRmluZCBkZWxlZ2F0ZSBoYW5kbGVyc1xuXHRcdGlmICggZGVsZWdhdGVDb3VudCAmJlxuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTlcblx0XHRcdC8vIEJsYWNrLWhvbGUgU1ZHIDx1c2U+IGluc3RhbmNlIHRyZWVzICh0cmFjLTEzMTgwKVxuXHRcdFx0Y3VyLm5vZGVUeXBlICYmXG5cblx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggPD00MlxuXHRcdFx0Ly8gU3VwcHJlc3Mgc3BlYy12aW9sYXRpbmcgY2xpY2tzIGluZGljYXRpbmcgYSBub24tcHJpbWFyeSBwb2ludGVyIGJ1dHRvbiAodHJhYy0zODYxKVxuXHRcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnQtdHlwZS1jbGlja1xuXHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0Ly8gLi4uYnV0IG5vdCBhcnJvdyBrZXkgXCJjbGlja3NcIiBvZiByYWRpbyBpbnB1dHMsIHdoaWNoIGNhbiBoYXZlIGBidXR0b25gIC0xIChnaC0yMzQzKVxuXHRcdFx0ISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGV2ZW50LmJ1dHRvbiA+PSAxICkgKSB7XG5cblx0XHRcdGZvciAoIDsgY3VyICE9PSB0aGlzOyBjdXIgPSBjdXIucGFyZW50Tm9kZSB8fCB0aGlzICkge1xuXG5cdFx0XHRcdC8vIERvbid0IGNoZWNrIG5vbi1lbGVtZW50cyAoIzEzMjA4KVxuXHRcdFx0XHQvLyBEb24ndCBwcm9jZXNzIGNsaWNrcyBvbiBkaXNhYmxlZCBlbGVtZW50cyAoIzY5MTEsICM4MTY1LCAjMTEzODIsICMxMTc2NClcblx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPT09IDEgJiYgISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGN1ci5kaXNhYmxlZCA9PT0gdHJ1ZSApICkge1xuXHRcdFx0XHRcdG1hdGNoZWRIYW5kbGVycyA9IFtdO1xuXHRcdFx0XHRcdG1hdGNoZWRTZWxlY3RvcnMgPSB7fTtcblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGRlbGVnYXRlQ291bnQ7IGkrKyApIHtcblx0XHRcdFx0XHRcdGhhbmRsZU9iaiA9IGhhbmRsZXJzWyBpIF07XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IGNvbmZsaWN0IHdpdGggT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzICgjMTMyMDMpXG5cdFx0XHRcdFx0XHRzZWwgPSBoYW5kbGVPYmouc2VsZWN0b3IgKyBcIiBcIjtcblxuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9IGhhbmRsZU9iai5uZWVkc0NvbnRleHQgP1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggc2VsLCB0aGlzICkuaW5kZXgoIGN1ciApID4gLTEgOlxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kKCBzZWwsIHRoaXMsIG51bGwsIFsgY3VyIF0gKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkSGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggbWF0Y2hlZEhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdGhhbmRsZXJRdWV1ZS5wdXNoKCB7IGVsZW06IGN1ciwgaGFuZGxlcnM6IG1hdGNoZWRIYW5kbGVycyB9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIHRoZSByZW1haW5pbmcgKGRpcmVjdGx5LWJvdW5kKSBoYW5kbGVyc1xuXHRcdGN1ciA9IHRoaXM7XG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50IDwgaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goIHsgZWxlbTogY3VyLCBoYW5kbGVyczogaGFuZGxlcnMuc2xpY2UoIGRlbGVnYXRlQ291bnQgKSB9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGhhbmRsZXJRdWV1ZTtcblx0fSxcblxuXHRhZGRQcm9wOiBmdW5jdGlvbiggbmFtZSwgaG9vayApIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIGpRdWVyeS5FdmVudC5wcm90b3R5cGUsIG5hbWUsIHtcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cblx0XHRcdGdldDogalF1ZXJ5LmlzRnVuY3Rpb24oIGhvb2sgKSA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaG9vayggdGhpcy5vcmlnaW5hbEV2ZW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IDpcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnRbIG5hbWUgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cblx0XHRcdHNldDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIHRoaXMsIG5hbWUsIHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRmaXg6IGZ1bmN0aW9uKCBvcmlnaW5hbEV2ZW50ICkge1xuXHRcdHJldHVybiBvcmlnaW5hbEV2ZW50WyBqUXVlcnkuZXhwYW5kbyBdID9cblx0XHRcdG9yaWdpbmFsRXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggb3JpZ2luYWxFdmVudCApO1xuXHR9LFxuXG5cdHNwZWNpYWw6IHtcblx0XHRsb2FkOiB7XG5cblx0XHRcdC8vIFByZXZlbnQgdHJpZ2dlcmVkIGltYWdlLmxvYWQgZXZlbnRzIGZyb20gYnViYmxpbmcgdG8gd2luZG93LmxvYWRcblx0XHRcdG5vQnViYmxlOiB0cnVlXG5cdFx0fSxcblx0XHRmb2N1czoge1xuXG5cdFx0XHQvLyBGaXJlIG5hdGl2ZSBldmVudCBpZiBwb3NzaWJsZSBzbyBibHVyL2ZvY3VzIHNlcXVlbmNlIGlzIGNvcnJlY3Rcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMgIT09IHNhZmVBY3RpdmVFbGVtZW50KCkgJiYgdGhpcy5mb2N1cyApIHtcblx0XHRcdFx0XHR0aGlzLmZvY3VzKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3VzaW5cIlxuXHRcdH0sXG5cdFx0Ymx1cjoge1xuXHRcdFx0dHJpZ2dlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdGhpcyA9PT0gc2FmZUFjdGl2ZUVsZW1lbnQoKSAmJiB0aGlzLmJsdXIgKSB7XG5cdFx0XHRcdFx0dGhpcy5ibHVyKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3Vzb3V0XCJcblx0XHR9LFxuXHRcdGNsaWNrOiB7XG5cblx0XHRcdC8vIEZvciBjaGVja2JveCwgZmlyZSBuYXRpdmUgZXZlbnQgc28gY2hlY2tlZCBzdGF0ZSB3aWxsIGJlIHJpZ2h0XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzLnR5cGUgPT09IFwiY2hlY2tib3hcIiAmJiB0aGlzLmNsaWNrICYmIG5vZGVOYW1lKCB0aGlzLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR0aGlzLmNsaWNrKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGb3IgY3Jvc3MtYnJvd3NlciBjb25zaXN0ZW5jeSwgZG9uJ3QgZmlyZSBuYXRpdmUgLmNsaWNrKCkgb24gbGlua3Ncblx0XHRcdF9kZWZhdWx0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHJldHVybiBub2RlTmFtZSggZXZlbnQudGFyZ2V0LCBcImFcIiApO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRiZWZvcmV1bmxvYWQ6IHtcblx0XHRcdHBvc3REaXNwYXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggMjArXG5cdFx0XHRcdC8vIEZpcmVmb3ggZG9lc24ndCBhbGVydCBpZiB0aGUgcmV0dXJuVmFsdWUgZmllbGQgaXMgbm90IHNldC5cblx0XHRcdFx0aWYgKCBldmVudC5yZXN1bHQgIT09IHVuZGVmaW5lZCAmJiBldmVudC5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdGV2ZW50Lm9yaWdpbmFsRXZlbnQucmV0dXJuVmFsdWUgPSBldmVudC5yZXN1bHQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn07XG5cbmpRdWVyeS5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCBoYW5kbGUgKSB7XG5cblx0Ly8gVGhpcyBcImlmXCIgaXMgbmVlZGVkIGZvciBwbGFpbiBvYmplY3RzXG5cdGlmICggZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyICkge1xuXHRcdGVsZW0ucmVtb3ZlRXZlbnRMaXN0ZW5lciggdHlwZSwgaGFuZGxlICk7XG5cdH1cbn07XG5cbmpRdWVyeS5FdmVudCA9IGZ1bmN0aW9uKCBzcmMsIHByb3BzICkge1xuXG5cdC8vIEFsbG93IGluc3RhbnRpYXRpb24gd2l0aG91dCB0aGUgJ25ldycga2V5d29yZFxuXHRpZiAoICEoIHRoaXMgaW5zdGFuY2VvZiBqUXVlcnkuRXZlbnQgKSApIHtcblx0XHRyZXR1cm4gbmV3IGpRdWVyeS5FdmVudCggc3JjLCBwcm9wcyApO1xuXHR9XG5cblx0Ly8gRXZlbnQgb2JqZWN0XG5cdGlmICggc3JjICYmIHNyYy50eXBlICkge1xuXHRcdHRoaXMub3JpZ2luYWxFdmVudCA9IHNyYztcblx0XHR0aGlzLnR5cGUgPSBzcmMudHlwZTtcblxuXHRcdC8vIEV2ZW50cyBidWJibGluZyB1cCB0aGUgZG9jdW1lbnQgbWF5IGhhdmUgYmVlbiBtYXJrZWQgYXMgcHJldmVudGVkXG5cdFx0Ly8gYnkgYSBoYW5kbGVyIGxvd2VyIGRvd24gdGhlIHRyZWU7IHJlZmxlY3QgdGhlIGNvcnJlY3QgdmFsdWUuXG5cdFx0dGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBzcmMuZGVmYXVsdFByZXZlbnRlZCB8fFxuXHRcdFx0XHRzcmMuZGVmYXVsdFByZXZlbnRlZCA9PT0gdW5kZWZpbmVkICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTIuMyBvbmx5XG5cdFx0XHRcdHNyYy5yZXR1cm5WYWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0cmV0dXJuVHJ1ZSA6XG5cdFx0XHRyZXR1cm5GYWxzZTtcblxuXHRcdC8vIENyZWF0ZSB0YXJnZXQgcHJvcGVydGllc1xuXHRcdC8vIFN1cHBvcnQ6IFNhZmFyaSA8PTYgLSA3IG9ubHlcblx0XHQvLyBUYXJnZXQgc2hvdWxkIG5vdCBiZSBhIHRleHQgbm9kZSAoIzUwNCwgIzEzMTQzKVxuXHRcdHRoaXMudGFyZ2V0ID0gKCBzcmMudGFyZ2V0ICYmIHNyYy50YXJnZXQubm9kZVR5cGUgPT09IDMgKSA/XG5cdFx0XHRzcmMudGFyZ2V0LnBhcmVudE5vZGUgOlxuXHRcdFx0c3JjLnRhcmdldDtcblxuXHRcdHRoaXMuY3VycmVudFRhcmdldCA9IHNyYy5jdXJyZW50VGFyZ2V0O1xuXHRcdHRoaXMucmVsYXRlZFRhcmdldCA9IHNyYy5yZWxhdGVkVGFyZ2V0O1xuXG5cdC8vIEV2ZW50IHR5cGVcblx0fSBlbHNlIHtcblx0XHR0aGlzLnR5cGUgPSBzcmM7XG5cdH1cblxuXHQvLyBQdXQgZXhwbGljaXRseSBwcm92aWRlZCBwcm9wZXJ0aWVzIG9udG8gdGhlIGV2ZW50IG9iamVjdFxuXHRpZiAoIHByb3BzICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRoaXMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSB0aW1lc3RhbXAgaWYgaW5jb21pbmcgZXZlbnQgZG9lc24ndCBoYXZlIG9uZVxuXHR0aGlzLnRpbWVTdGFtcCA9IHNyYyAmJiBzcmMudGltZVN0YW1wIHx8IGpRdWVyeS5ub3coKTtcblxuXHQvLyBNYXJrIGl0IGFzIGZpeGVkXG5cdHRoaXNbIGpRdWVyeS5leHBhbmRvIF0gPSB0cnVlO1xufTtcblxuLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nXG4vLyBodHRwczovL3d3dy53My5vcmcvVFIvMjAwMy9XRC1ET00tTGV2ZWwtMy1FdmVudHMtMjAwMzAzMzEvZWNtYS1zY3JpcHQtYmluZGluZy5odG1sXG5qUXVlcnkuRXZlbnQucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LkV2ZW50LFxuXHRpc0RlZmF1bHRQcmV2ZW50ZWQ6IHJldHVybkZhbHNlLFxuXHRpc1Byb3BhZ2F0aW9uU3RvcHBlZDogcmV0dXJuRmFsc2UsXG5cdGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNTaW11bGF0ZWQ6IGZhbHNlLFxuXG5cdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9LFxuXHRzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0dGhpcy5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9IHJldHVyblRydWU7XG5cblx0XHRpZiAoIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgKSB7XG5cdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdH1cblxuXHRcdHRoaXMuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdH1cbn07XG5cbi8vIEluY2x1ZGVzIGFsbCBjb21tb24gZXZlbnQgcHJvcHMgaW5jbHVkaW5nIEtleUV2ZW50IGFuZCBNb3VzZUV2ZW50IHNwZWNpZmljIHByb3BzXG5qUXVlcnkuZWFjaCgge1xuXHRhbHRLZXk6IHRydWUsXG5cdGJ1YmJsZXM6IHRydWUsXG5cdGNhbmNlbGFibGU6IHRydWUsXG5cdGNoYW5nZWRUb3VjaGVzOiB0cnVlLFxuXHRjdHJsS2V5OiB0cnVlLFxuXHRkZXRhaWw6IHRydWUsXG5cdGV2ZW50UGhhc2U6IHRydWUsXG5cdG1ldGFLZXk6IHRydWUsXG5cdHBhZ2VYOiB0cnVlLFxuXHRwYWdlWTogdHJ1ZSxcblx0c2hpZnRLZXk6IHRydWUsXG5cdHZpZXc6IHRydWUsXG5cdFwiY2hhclwiOiB0cnVlLFxuXHRjaGFyQ29kZTogdHJ1ZSxcblx0a2V5OiB0cnVlLFxuXHRrZXlDb2RlOiB0cnVlLFxuXHRidXR0b246IHRydWUsXG5cdGJ1dHRvbnM6IHRydWUsXG5cdGNsaWVudFg6IHRydWUsXG5cdGNsaWVudFk6IHRydWUsXG5cdG9mZnNldFg6IHRydWUsXG5cdG9mZnNldFk6IHRydWUsXG5cdHBvaW50ZXJJZDogdHJ1ZSxcblx0cG9pbnRlclR5cGU6IHRydWUsXG5cdHNjcmVlblg6IHRydWUsXG5cdHNjcmVlblk6IHRydWUsXG5cdHRhcmdldFRvdWNoZXM6IHRydWUsXG5cdHRvRWxlbWVudDogdHJ1ZSxcblx0dG91Y2hlczogdHJ1ZSxcblxuXHR3aGljaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdHZhciBidXR0b24gPSBldmVudC5idXR0b247XG5cblx0XHQvLyBBZGQgd2hpY2ggZm9yIGtleSBldmVudHNcblx0XHRpZiAoIGV2ZW50LndoaWNoID09IG51bGwgJiYgcmtleUV2ZW50LnRlc3QoIGV2ZW50LnR5cGUgKSApIHtcblx0XHRcdHJldHVybiBldmVudC5jaGFyQ29kZSAhPSBudWxsID8gZXZlbnQuY2hhckNvZGUgOiBldmVudC5rZXlDb2RlO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB3aGljaCBmb3IgY2xpY2s6IDEgPT09IGxlZnQ7IDIgPT09IG1pZGRsZTsgMyA9PT0gcmlnaHRcblx0XHRpZiAoICFldmVudC53aGljaCAmJiBidXR0b24gIT09IHVuZGVmaW5lZCAmJiBybW91c2VFdmVudC50ZXN0KCBldmVudC50eXBlICkgKSB7XG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDEgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDIgKSB7XG5cdFx0XHRcdHJldHVybiAzO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDQgKSB7XG5cdFx0XHRcdHJldHVybiAyO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnQud2hpY2g7XG5cdH1cbn0sIGpRdWVyeS5ldmVudC5hZGRQcm9wICk7XG5cbi8vIENyZWF0ZSBtb3VzZWVudGVyL2xlYXZlIGV2ZW50cyB1c2luZyBtb3VzZW92ZXIvb3V0IGFuZCBldmVudC10aW1lIGNoZWNrc1xuLy8gc28gdGhhdCBldmVudCBkZWxlZ2F0aW9uIHdvcmtzIGluIGpRdWVyeS5cbi8vIERvIHRoZSBzYW1lIGZvciBwb2ludGVyZW50ZXIvcG9pbnRlcmxlYXZlIGFuZCBwb2ludGVyb3Zlci9wb2ludGVyb3V0XG4vL1xuLy8gU3VwcG9ydDogU2FmYXJpIDcgb25seVxuLy8gU2FmYXJpIHNlbmRzIG1vdXNlZW50ZXIgdG9vIG9mdGVuOyBzZWU6XG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NzAyNThcbi8vIGZvciB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGJ1ZyAoaXQgZXhpc3RlZCBpbiBvbGRlciBDaHJvbWUgdmVyc2lvbnMgYXMgd2VsbCkuXG5qUXVlcnkuZWFjaCgge1xuXHRtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuXHRtb3VzZWxlYXZlOiBcIm1vdXNlb3V0XCIsXG5cdHBvaW50ZXJlbnRlcjogXCJwb2ludGVyb3ZlclwiLFxuXHRwb2ludGVybGVhdmU6IFwicG9pbnRlcm91dFwiXG59LCBmdW5jdGlvbiggb3JpZywgZml4ICkge1xuXHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgb3JpZyBdID0ge1xuXHRcdGRlbGVnYXRlVHlwZTogZml4LFxuXHRcdGJpbmRUeXBlOiBmaXgsXG5cblx0XHRoYW5kbGU6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdHZhciByZXQsXG5cdFx0XHRcdHRhcmdldCA9IHRoaXMsXG5cdFx0XHRcdHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0LFxuXHRcdFx0XHRoYW5kbGVPYmogPSBldmVudC5oYW5kbGVPYmo7XG5cblx0XHRcdC8vIEZvciBtb3VzZWVudGVyL2xlYXZlIGNhbGwgdGhlIGhhbmRsZXIgaWYgcmVsYXRlZCBpcyBvdXRzaWRlIHRoZSB0YXJnZXQuXG5cdFx0XHQvLyBOQjogTm8gcmVsYXRlZFRhcmdldCBpZiB0aGUgbW91c2UgbGVmdC9lbnRlcmVkIHRoZSBicm93c2VyIHdpbmRvd1xuXHRcdFx0aWYgKCAhcmVsYXRlZCB8fCAoIHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhalF1ZXJ5LmNvbnRhaW5zKCB0YXJnZXQsIHJlbGF0ZWQgKSApICkge1xuXHRcdFx0XHRldmVudC50eXBlID0gaGFuZGxlT2JqLm9yaWdUeXBlO1xuXHRcdFx0XHRyZXQgPSBoYW5kbGVPYmouaGFuZGxlci5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBmaXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXG5cdG9uOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4gKTtcblx0fSxcblx0b25lOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4sIDEgKTtcblx0fSxcblx0b2ZmOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBmbiApIHtcblx0XHR2YXIgaGFuZGxlT2JqLCB0eXBlO1xuXHRcdGlmICggdHlwZXMgJiYgdHlwZXMucHJldmVudERlZmF1bHQgJiYgdHlwZXMuaGFuZGxlT2JqICkge1xuXG5cdFx0XHQvLyAoIGV2ZW50ICkgIGRpc3BhdGNoZWQgalF1ZXJ5LkV2ZW50XG5cdFx0XHRoYW5kbGVPYmogPSB0eXBlcy5oYW5kbGVPYmo7XG5cdFx0XHRqUXVlcnkoIHR5cGVzLmRlbGVnYXRlVGFyZ2V0ICkub2ZmKFxuXHRcdFx0XHRoYW5kbGVPYmoubmFtZXNwYWNlID9cblx0XHRcdFx0XHRoYW5kbGVPYmoub3JpZ1R5cGUgKyBcIi5cIiArIGhhbmRsZU9iai5uYW1lc3BhY2UgOlxuXHRcdFx0XHRcdGhhbmRsZU9iai5vcmlnVHlwZSxcblx0XHRcdFx0aGFuZGxlT2JqLnNlbGVjdG9yLFxuXHRcdFx0XHRoYW5kbGVPYmouaGFuZGxlclxuXHRcdFx0KTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcy1vYmplY3QgWywgc2VsZWN0b3JdIClcblx0XHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRcdHRoaXMub2ZmKCB0eXBlLCBzZWxlY3RvciwgdHlwZXNbIHR5cGUgXSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggc2VsZWN0b3IgPT09IGZhbHNlIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICkge1xuXG5cdFx0XHQvLyAoIHR5cGVzIFssIGZuXSApXG5cdFx0XHRmbiA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGlmICggZm4gPT09IGZhbHNlICkge1xuXHRcdFx0Zm4gPSByZXR1cm5GYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCB0aGlzLCB0eXBlcywgZm4sIHNlbGVjdG9yICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxudmFyXG5cblx0LyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuXG5cdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZXNsaW50L2VzbGludC9pc3N1ZXMvMzIyOVxuXHRyeGh0bWxUYWcgPSAvPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbYS16XVteXFwvXFwwPlxceDIwXFx0XFxyXFxuXFxmXSopW14+XSopXFwvPi9naSxcblxuXHQvKiBlc2xpbnQtZW5hYmxlICovXG5cblx0Ly8gU3VwcG9ydDogSUUgPD0xMCAtIDExLCBFZGdlIDEyIC0gMTNcblx0Ly8gSW4gSUUvRWRnZSB1c2luZyByZWdleCBncm91cHMgaGVyZSBjYXVzZXMgc2V2ZXJlIHNsb3dkb3ducy5cblx0Ly8gU2VlIGh0dHBzOi8vY29ubmVjdC5taWNyb3NvZnQuY29tL0lFL2ZlZWRiYWNrL2RldGFpbHMvMTczNjUxMi9cblx0cm5vSW5uZXJodG1sID0gLzxzY3JpcHR8PHN0eWxlfDxsaW5rL2ksXG5cblx0Ly8gY2hlY2tlZD1cImNoZWNrZWRcIiBvciBjaGVja2VkXG5cdHJjaGVja2VkID0gL2NoZWNrZWRcXHMqKD86W149XXw9XFxzKi5jaGVja2VkLikvaSxcblx0cnNjcmlwdFR5cGVNYXNrZWQgPSAvXnRydWVcXC8oLiopLyxcblx0cmNsZWFuU2NyaXB0ID0gL15cXHMqPCEoPzpcXFtDREFUQVxcW3wtLSl8KD86XFxdXFxdfC0tKT5cXHMqJC9nO1xuXG4vLyBQcmVmZXIgYSB0Ym9keSBvdmVyIGl0cyBwYXJlbnQgdGFibGUgZm9yIGNvbnRhaW5pbmcgbmV3IHJvd3NcbmZ1bmN0aW9uIG1hbmlwdWxhdGlvblRhcmdldCggZWxlbSwgY29udGVudCApIHtcblx0aWYgKCBub2RlTmFtZSggZWxlbSwgXCJ0YWJsZVwiICkgJiZcblx0XHRub2RlTmFtZSggY29udGVudC5ub2RlVHlwZSAhPT0gMTEgPyBjb250ZW50IDogY29udGVudC5maXJzdENoaWxkLCBcInRyXCIgKSApIHtcblxuXHRcdHJldHVybiBqUXVlcnkoIFwiPnRib2R5XCIsIGVsZW0gKVsgMCBdIHx8IGVsZW07XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxuLy8gUmVwbGFjZS9yZXN0b3JlIHRoZSB0eXBlIGF0dHJpYnV0ZSBvZiBzY3JpcHQgZWxlbWVudHMgZm9yIHNhZmUgRE9NIG1hbmlwdWxhdGlvblxuZnVuY3Rpb24gZGlzYWJsZVNjcmlwdCggZWxlbSApIHtcblx0ZWxlbS50eXBlID0gKCBlbGVtLmdldEF0dHJpYnV0ZSggXCJ0eXBlXCIgKSAhPT0gbnVsbCApICsgXCIvXCIgKyBlbGVtLnR5cGU7XG5cdHJldHVybiBlbGVtO1xufVxuZnVuY3Rpb24gcmVzdG9yZVNjcmlwdCggZWxlbSApIHtcblx0dmFyIG1hdGNoID0gcnNjcmlwdFR5cGVNYXNrZWQuZXhlYyggZWxlbS50eXBlICk7XG5cblx0aWYgKCBtYXRjaCApIHtcblx0XHRlbGVtLnR5cGUgPSBtYXRjaFsgMSBdO1xuXHR9IGVsc2Uge1xuXHRcdGVsZW0ucmVtb3ZlQXR0cmlidXRlKCBcInR5cGVcIiApO1xuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmZ1bmN0aW9uIGNsb25lQ29weUV2ZW50KCBzcmMsIGRlc3QgKSB7XG5cdHZhciBpLCBsLCB0eXBlLCBwZGF0YU9sZCwgcGRhdGFDdXIsIHVkYXRhT2xkLCB1ZGF0YUN1ciwgZXZlbnRzO1xuXG5cdGlmICggZGVzdC5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyAxLiBDb3B5IHByaXZhdGUgZGF0YTogZXZlbnRzLCBoYW5kbGVycywgZXRjLlxuXHRpZiAoIGRhdGFQcml2Lmhhc0RhdGEoIHNyYyApICkge1xuXHRcdHBkYXRhT2xkID0gZGF0YVByaXYuYWNjZXNzKCBzcmMgKTtcblx0XHRwZGF0YUN1ciA9IGRhdGFQcml2LnNldCggZGVzdCwgcGRhdGFPbGQgKTtcblx0XHRldmVudHMgPSBwZGF0YU9sZC5ldmVudHM7XG5cblx0XHRpZiAoIGV2ZW50cyApIHtcblx0XHRcdGRlbGV0ZSBwZGF0YUN1ci5oYW5kbGU7XG5cdFx0XHRwZGF0YUN1ci5ldmVudHMgPSB7fTtcblxuXHRcdFx0Zm9yICggdHlwZSBpbiBldmVudHMgKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwLCBsID0gZXZlbnRzWyB0eXBlIF0ubGVuZ3RoOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5hZGQoIGRlc3QsIHR5cGUsIGV2ZW50c1sgdHlwZSBdWyBpIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIDIuIENvcHkgdXNlciBkYXRhXG5cdGlmICggZGF0YVVzZXIuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0dWRhdGFPbGQgPSBkYXRhVXNlci5hY2Nlc3MoIHNyYyApO1xuXHRcdHVkYXRhQ3VyID0galF1ZXJ5LmV4dGVuZCgge30sIHVkYXRhT2xkICk7XG5cblx0XHRkYXRhVXNlci5zZXQoIGRlc3QsIHVkYXRhQ3VyICk7XG5cdH1cbn1cblxuLy8gRml4IElFIGJ1Z3MsIHNlZSBzdXBwb3J0IHRlc3RzXG5mdW5jdGlvbiBmaXhJbnB1dCggc3JjLCBkZXN0ICkge1xuXHR2YXIgbm9kZU5hbWUgPSBkZXN0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0Ly8gRmFpbHMgdG8gcGVyc2lzdCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiBhIGNsb25lZCBjaGVja2JveCBvciByYWRpbyBidXR0b24uXG5cdGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiByY2hlY2thYmxlVHlwZS50ZXN0KCBzcmMudHlwZSApICkge1xuXHRcdGRlc3QuY2hlY2tlZCA9IHNyYy5jaGVja2VkO1xuXG5cdC8vIEZhaWxzIHRvIHJldHVybiB0aGUgc2VsZWN0ZWQgb3B0aW9uIHRvIHRoZSBkZWZhdWx0IHNlbGVjdGVkIHN0YXRlIHdoZW4gY2xvbmluZyBvcHRpb25zXG5cdH0gZWxzZSBpZiAoIG5vZGVOYW1lID09PSBcImlucHV0XCIgfHwgbm9kZU5hbWUgPT09IFwidGV4dGFyZWFcIiApIHtcblx0XHRkZXN0LmRlZmF1bHRWYWx1ZSA9IHNyYy5kZWZhdWx0VmFsdWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gZG9tTWFuaXAoIGNvbGxlY3Rpb24sIGFyZ3MsIGNhbGxiYWNrLCBpZ25vcmVkICkge1xuXG5cdC8vIEZsYXR0ZW4gYW55IG5lc3RlZCBhcnJheXNcblx0YXJncyA9IGNvbmNhdC5hcHBseSggW10sIGFyZ3MgKTtcblxuXHR2YXIgZnJhZ21lbnQsIGZpcnN0LCBzY3JpcHRzLCBoYXNTY3JpcHRzLCBub2RlLCBkb2MsXG5cdFx0aSA9IDAsXG5cdFx0bCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuXHRcdGlOb0Nsb25lID0gbCAtIDEsXG5cdFx0dmFsdWUgPSBhcmdzWyAwIF0sXG5cdFx0aXNGdW5jdGlvbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApO1xuXG5cdC8vIFdlIGNhbid0IGNsb25lTm9kZSBmcmFnbWVudHMgdGhhdCBjb250YWluIGNoZWNrZWQsIGluIFdlYktpdFxuXHRpZiAoIGlzRnVuY3Rpb24gfHxcblx0XHRcdCggbCA+IDEgJiYgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmXG5cdFx0XHRcdCFzdXBwb3J0LmNoZWNrQ2xvbmUgJiYgcmNoZWNrZWQudGVzdCggdmFsdWUgKSApICkge1xuXHRcdHJldHVybiBjb2xsZWN0aW9uLmVhY2goIGZ1bmN0aW9uKCBpbmRleCApIHtcblx0XHRcdHZhciBzZWxmID0gY29sbGVjdGlvbi5lcSggaW5kZXggKTtcblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0YXJnc1sgMCBdID0gdmFsdWUuY2FsbCggdGhpcywgaW5kZXgsIHNlbGYuaHRtbCgpICk7XG5cdFx0XHR9XG5cdFx0XHRkb21NYW5pcCggc2VsZiwgYXJncywgY2FsbGJhY2ssIGlnbm9yZWQgKTtcblx0XHR9ICk7XG5cdH1cblxuXHRpZiAoIGwgKSB7XG5cdFx0ZnJhZ21lbnQgPSBidWlsZEZyYWdtZW50KCBhcmdzLCBjb2xsZWN0aW9uWyAwIF0ub3duZXJEb2N1bWVudCwgZmFsc2UsIGNvbGxlY3Rpb24sIGlnbm9yZWQgKTtcblx0XHRmaXJzdCA9IGZyYWdtZW50LmZpcnN0Q2hpbGQ7XG5cblx0XHRpZiAoIGZyYWdtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAxICkge1xuXHRcdFx0ZnJhZ21lbnQgPSBmaXJzdDtcblx0XHR9XG5cblx0XHQvLyBSZXF1aXJlIGVpdGhlciBuZXcgY29udGVudCBvciBhbiBpbnRlcmVzdCBpbiBpZ25vcmVkIGVsZW1lbnRzIHRvIGludm9rZSB0aGUgY2FsbGJhY2tcblx0XHRpZiAoIGZpcnN0IHx8IGlnbm9yZWQgKSB7XG5cdFx0XHRzY3JpcHRzID0galF1ZXJ5Lm1hcCggZ2V0QWxsKCBmcmFnbWVudCwgXCJzY3JpcHRcIiApLCBkaXNhYmxlU2NyaXB0ICk7XG5cdFx0XHRoYXNTY3JpcHRzID0gc2NyaXB0cy5sZW5ndGg7XG5cblx0XHRcdC8vIFVzZSB0aGUgb3JpZ2luYWwgZnJhZ21lbnQgZm9yIHRoZSBsYXN0IGl0ZW1cblx0XHRcdC8vIGluc3RlYWQgb2YgdGhlIGZpcnN0IGJlY2F1c2UgaXQgY2FuIGVuZCB1cFxuXHRcdFx0Ly8gYmVpbmcgZW1wdGllZCBpbmNvcnJlY3RseSBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgKCM4MDcwKS5cblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0bm9kZSA9IGZyYWdtZW50O1xuXG5cdFx0XHRcdGlmICggaSAhPT0gaU5vQ2xvbmUgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IGpRdWVyeS5jbG9uZSggbm9kZSwgdHJ1ZSwgdHJ1ZSApO1xuXG5cdFx0XHRcdFx0Ly8gS2VlcCByZWZlcmVuY2VzIHRvIGNsb25lZCBzY3JpcHRzIGZvciBsYXRlciByZXN0b3JhdGlvblxuXHRcdFx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIHNjcmlwdHMsIGdldEFsbCggbm9kZSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FsbGJhY2suY2FsbCggY29sbGVjdGlvblsgaSBdLCBub2RlLCBpICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblx0XHRcdFx0ZG9jID0gc2NyaXB0c1sgc2NyaXB0cy5sZW5ndGggLSAxIF0ub3duZXJEb2N1bWVudDtcblxuXHRcdFx0XHQvLyBSZWVuYWJsZSBzY3JpcHRzXG5cdFx0XHRcdGpRdWVyeS5tYXAoIHNjcmlwdHMsIHJlc3RvcmVTY3JpcHQgKTtcblxuXHRcdFx0XHQvLyBFdmFsdWF0ZSBleGVjdXRhYmxlIHNjcmlwdHMgb24gZmlyc3QgZG9jdW1lbnQgaW5zZXJ0aW9uXG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgaGFzU2NyaXB0czsgaSsrICkge1xuXHRcdFx0XHRcdG5vZGUgPSBzY3JpcHRzWyBpIF07XG5cdFx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBub2RlLnR5cGUgfHwgXCJcIiApICYmXG5cdFx0XHRcdFx0XHQhZGF0YVByaXYuYWNjZXNzKCBub2RlLCBcImdsb2JhbEV2YWxcIiApICYmXG5cdFx0XHRcdFx0XHRqUXVlcnkuY29udGFpbnMoIGRvYywgbm9kZSApICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIG5vZGUuc3JjICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIE9wdGlvbmFsIEFKQVggZGVwZW5kZW5jeSwgYnV0IHdvbid0IHJ1biBzY3JpcHRzIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5Ll9ldmFsVXJsICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5fZXZhbFVybCggbm9kZS5zcmMgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0RE9NRXZhbCggbm9kZS50ZXh0Q29udGVudC5yZXBsYWNlKCByY2xlYW5TY3JpcHQsIFwiXCIgKSwgZG9jICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGNvbGxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSggZWxlbSwgc2VsZWN0b3IsIGtlZXBEYXRhICkge1xuXHR2YXIgbm9kZSxcblx0XHRub2RlcyA9IHNlbGVjdG9yID8galF1ZXJ5LmZpbHRlciggc2VsZWN0b3IsIGVsZW0gKSA6IGVsZW0sXG5cdFx0aSA9IDA7XG5cblx0Zm9yICggOyAoIG5vZGUgPSBub2Rlc1sgaSBdICkgIT0gbnVsbDsgaSsrICkge1xuXHRcdGlmICggIWtlZXBEYXRhICYmIG5vZGUubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIG5vZGUgKSApO1xuXHRcdH1cblxuXHRcdGlmICggbm9kZS5wYXJlbnROb2RlICkge1xuXHRcdFx0aWYgKCBrZWVwRGF0YSAmJiBqUXVlcnkuY29udGFpbnMoIG5vZGUub3duZXJEb2N1bWVudCwgbm9kZSApICkge1xuXHRcdFx0XHRzZXRHbG9iYWxFdmFsKCBnZXRBbGwoIG5vZGUsIFwic2NyaXB0XCIgKSApO1xuXHRcdFx0fVxuXHRcdFx0bm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBub2RlICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aHRtbFByZWZpbHRlcjogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0cmV0dXJuIGh0bWwucmVwbGFjZSggcnhodG1sVGFnLCBcIjwkMT48LyQyPlwiICk7XG5cdH0sXG5cblx0Y2xvbmU6IGZ1bmN0aW9uKCBlbGVtLCBkYXRhQW5kRXZlbnRzLCBkZWVwRGF0YUFuZEV2ZW50cyApIHtcblx0XHR2YXIgaSwgbCwgc3JjRWxlbWVudHMsIGRlc3RFbGVtZW50cyxcblx0XHRcdGNsb25lID0gZWxlbS5jbG9uZU5vZGUoIHRydWUgKSxcblx0XHRcdGluUGFnZSA9IGpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICk7XG5cblx0XHQvLyBGaXggSUUgY2xvbmluZyBpc3N1ZXNcblx0XHRpZiAoICFzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkICYmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBlbGVtLm5vZGVUeXBlID09PSAxMSApICYmXG5cdFx0XHRcdCFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblxuXHRcdFx0Ly8gV2UgZXNjaGV3IFNpenpsZSBoZXJlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zOiBodHRwczovL2pzcGVyZi5jb20vZ2V0YWxsLXZzLXNpenpsZS8yXG5cdFx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lICk7XG5cdFx0XHRzcmNFbGVtZW50cyA9IGdldEFsbCggZWxlbSApO1xuXG5cdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0Zml4SW5wdXQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ29weSB0aGUgZXZlbnRzIGZyb20gdGhlIG9yaWdpbmFsIHRvIHRoZSBjbG9uZVxuXHRcdGlmICggZGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdGlmICggZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0XHRcdHNyY0VsZW1lbnRzID0gc3JjRWxlbWVudHMgfHwgZ2V0QWxsKCBlbGVtICk7XG5cdFx0XHRcdGRlc3RFbGVtZW50cyA9IGRlc3RFbGVtZW50cyB8fCBnZXRBbGwoIGNsb25lICk7XG5cblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBzcmNFbGVtZW50cy5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNsb25lQ29weUV2ZW50KCBlbGVtLCBjbG9uZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIHNjcmlwdCBldmFsdWF0aW9uIGhpc3Rvcnlcblx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lLCBcInNjcmlwdFwiICk7XG5cdFx0aWYgKCBkZXN0RWxlbWVudHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIGRlc3RFbGVtZW50cywgIWluUGFnZSAmJiBnZXRBbGwoIGVsZW0sIFwic2NyaXB0XCIgKSApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0aGUgY2xvbmVkIHNldFxuXHRcdHJldHVybiBjbG9uZTtcblx0fSxcblxuXHRjbGVhbkRhdGE6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblx0XHR2YXIgZGF0YSwgZWxlbSwgdHlwZSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbCxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoIGVsZW0gPSBlbGVtc1sgaSBdICkgIT09IHVuZGVmaW5lZDsgaSsrICkge1xuXHRcdFx0aWYgKCBhY2NlcHREYXRhKCBlbGVtICkgKSB7XG5cdFx0XHRcdGlmICggKCBkYXRhID0gZWxlbVsgZGF0YVByaXYuZXhwYW5kbyBdICkgKSB7XG5cdFx0XHRcdFx0aWYgKCBkYXRhLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdGZvciAoIHR5cGUgaW4gZGF0YS5ldmVudHMgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbFsgdHlwZSBdICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIGVsZW0sIHR5cGUgKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYXZvaWQgalF1ZXJ5LmV2ZW50LnJlbW92ZSdzIG92ZXJoZWFkXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBkYXRhLmhhbmRsZSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NStcblx0XHRcdFx0XHQvLyBBc3NpZ24gdW5kZWZpbmVkIGluc3RlYWQgb2YgdXNpbmcgZGVsZXRlLCBzZWUgRGF0YSNyZW1vdmVcblx0XHRcdFx0XHRlbGVtWyBkYXRhUHJpdi5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBlbGVtWyBkYXRhVXNlci5leHBhbmRvIF0gKSB7XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1K1xuXHRcdFx0XHRcdC8vIEFzc2lnbiB1bmRlZmluZWQgaW5zdGVhZCBvZiB1c2luZyBkZWxldGUsIHNlZSBEYXRhI3JlbW92ZVxuXHRcdFx0XHRcdGVsZW1bIGRhdGFVc2VyLmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRldGFjaDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiByZW1vdmUoIHRoaXMsIHNlbGVjdG9yLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHJlbW92ZSggdGhpcywgc2VsZWN0b3IgKTtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkudGV4dCggdGhpcyApIDpcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdFx0dGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0YXBwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0dmFyIHRhcmdldCA9IG1hbmlwdWxhdGlvblRhcmdldCggdGhpcywgZWxlbSApO1xuXHRcdFx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0cHJlcGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBtYW5pcHVsYXRpb25UYXJnZXQoIHRoaXMsIGVsZW0gKTtcblx0XHRcdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSggZWxlbSwgdGFyZ2V0LmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0YmVmb3JlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRhZnRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoIGVsZW0sIHRoaXMubmV4dFNpYmxpbmcgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0ZW1wdHk6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7ICggZWxlbSA9IHRoaXNbIGkgXSApICE9IG51bGw7IGkrKyApIHtcblx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHQvLyBQcmV2ZW50IG1lbW9yeSBsZWFrc1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIGVsZW0sIGZhbHNlICkgKTtcblxuXHRcdFx0XHQvLyBSZW1vdmUgYW55IHJlbWFpbmluZyBub2Rlc1xuXHRcdFx0XHRlbGVtLnRleHRDb250ZW50ID0gXCJcIjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRjbG9uZTogZnVuY3Rpb24oIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICkge1xuXHRcdGRhdGFBbmRFdmVudHMgPSBkYXRhQW5kRXZlbnRzID09IG51bGwgPyBmYWxzZSA6IGRhdGFBbmRFdmVudHM7XG5cdFx0ZGVlcERhdGFBbmRFdmVudHMgPSBkZWVwRGF0YUFuZEV2ZW50cyA9PSBudWxsID8gZGF0YUFuZEV2ZW50cyA6IGRlZXBEYXRhQW5kRXZlbnRzO1xuXG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBqUXVlcnkuY2xvbmUoIHRoaXMsIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdGh0bWw6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXSB8fCB7fSxcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdGwgPSB0aGlzLmxlbmd0aDtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmlubmVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2VlIGlmIHdlIGNhbiB0YWtlIGEgc2hvcnRjdXQgYW5kIGp1c3QgdXNlIGlubmVySFRNTFxuXHRcdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgIXJub0lubmVyaHRtbC50ZXN0KCB2YWx1ZSApICYmXG5cdFx0XHRcdCF3cmFwTWFwWyAoIHJ0YWdOYW1lLmV4ZWMoIHZhbHVlICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCkgXSApIHtcblxuXHRcdFx0XHR2YWx1ZSA9IGpRdWVyeS5odG1sUHJlZmlsdGVyKCB2YWx1ZSApO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdFx0ZWxlbSA9IHRoaXNbIGkgXSB8fCB7fTtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXHRcdFx0XHRcdFx0XHRlbGVtLmlubmVySFRNTCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsZW0gPSAwO1xuXG5cdFx0XHRcdC8vIElmIHVzaW5nIGlubmVySFRNTCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB1c2UgdGhlIGZhbGxiYWNrIG1ldGhvZFxuXHRcdFx0XHR9IGNhdGNoICggZSApIHt9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZWxlbSApIHtcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmFwcGVuZCggdmFsdWUgKTtcblx0XHRcdH1cblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCApO1xuXHR9LFxuXG5cdHJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaWdub3JlZCA9IFtdO1xuXG5cdFx0Ly8gTWFrZSB0aGUgY2hhbmdlcywgcmVwbGFjaW5nIGVhY2ggbm9uLWlnbm9yZWQgY29udGV4dCBlbGVtZW50IHdpdGggdGhlIG5ldyBjb250ZW50XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIHBhcmVudCA9IHRoaXMucGFyZW50Tm9kZTtcblxuXHRcdFx0aWYgKCBqUXVlcnkuaW5BcnJheSggdGhpcywgaWdub3JlZCApIDwgMCApIHtcblx0XHRcdFx0alF1ZXJ5LmNsZWFuRGF0YSggZ2V0QWxsKCB0aGlzICkgKTtcblx0XHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cdFx0XHRcdFx0cGFyZW50LnJlcGxhY2VDaGlsZCggZWxlbSwgdGhpcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBGb3JjZSBjYWxsYmFjayBpbnZvY2F0aW9uXG5cdFx0fSwgaWdub3JlZCApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCB7XG5cdGFwcGVuZFRvOiBcImFwcGVuZFwiLFxuXHRwcmVwZW5kVG86IFwicHJlcGVuZFwiLFxuXHRpbnNlcnRCZWZvcmU6IFwiYmVmb3JlXCIsXG5cdGluc2VydEFmdGVyOiBcImFmdGVyXCIsXG5cdHJlcGxhY2VBbGw6IFwicmVwbGFjZVdpdGhcIlxufSwgZnVuY3Rpb24oIG5hbWUsIG9yaWdpbmFsICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgZWxlbXMsXG5cdFx0XHRyZXQgPSBbXSxcblx0XHRcdGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKSxcblx0XHRcdGxhc3QgPSBpbnNlcnQubGVuZ3RoIC0gMSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyBpIDw9IGxhc3Q7IGkrKyApIHtcblx0XHRcdGVsZW1zID0gaSA9PT0gbGFzdCA/IHRoaXMgOiB0aGlzLmNsb25lKCB0cnVlICk7XG5cdFx0XHRqUXVlcnkoIGluc2VydFsgaSBdIClbIG9yaWdpbmFsIF0oIGVsZW1zICk7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0Ly8gLmdldCgpIGJlY2F1c2UgcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0cHVzaC5hcHBseSggcmV0LCBlbGVtcy5nZXQoKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggcmV0ICk7XG5cdH07XG59ICk7XG52YXIgcm1hcmdpbiA9ICggL15tYXJnaW4vICk7XG5cbnZhciBybnVtbm9ucHggPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBwbnVtICsgXCIpKD8hcHgpW2EteiVdKyRcIiwgXCJpXCIgKTtcblxudmFyIGdldFN0eWxlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5LCBGaXJlZm94IDw9MzAgKCMxNTA5OCwgIzE0MTUwKVxuXHRcdC8vIElFIHRocm93cyBvbiBlbGVtZW50cyBjcmVhdGVkIGluIHBvcHVwc1xuXHRcdC8vIEZGIG1lYW53aGlsZSB0aHJvd3Mgb24gZnJhbWUgZWxlbWVudHMgdGhyb3VnaCBcImRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGVcIlxuXHRcdHZhciB2aWV3ID0gZWxlbS5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3O1xuXG5cdFx0aWYgKCAhdmlldyB8fCAhdmlldy5vcGVuZXIgKSB7XG5cdFx0XHR2aWV3ID0gd2luZG93O1xuXHRcdH1cblxuXHRcdHJldHVybiB2aWV3LmdldENvbXB1dGVkU3R5bGUoIGVsZW0gKTtcblx0fTtcblxuXG5cbiggZnVuY3Rpb24oKSB7XG5cblx0Ly8gRXhlY3V0aW5nIGJvdGggcGl4ZWxQb3NpdGlvbiAmIGJveFNpemluZ1JlbGlhYmxlIHRlc3RzIHJlcXVpcmUgb25seSBvbmUgbGF5b3V0XG5cdC8vIHNvIHRoZXkncmUgZXhlY3V0ZWQgYXQgdGhlIHNhbWUgdGltZSB0byBzYXZlIHRoZSBzZWNvbmQgY29tcHV0YXRpb24uXG5cdGZ1bmN0aW9uIGNvbXB1dGVTdHlsZVRlc3RzKCkge1xuXG5cdFx0Ly8gVGhpcyBpcyBhIHNpbmdsZXRvbiwgd2UgbmVlZCB0byBleGVjdXRlIGl0IG9ubHkgb25jZVxuXHRcdGlmICggIWRpdiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRkaXYuc3R5bGUuY3NzVGV4dCA9XG5cdFx0XHRcImJveC1zaXppbmc6Ym9yZGVyLWJveDtcIiArXG5cdFx0XHRcInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7XCIgK1xuXHRcdFx0XCJtYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O1wiICtcblx0XHRcdFwidG9wOjElO3dpZHRoOjUwJVwiO1xuXHRcdGRpdi5pbm5lckhUTUwgPSBcIlwiO1xuXHRcdGRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHR2YXIgZGl2U3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSggZGl2ICk7XG5cdFx0cGl4ZWxQb3NpdGlvblZhbCA9IGRpdlN0eWxlLnRvcCAhPT0gXCIxJVwiO1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgLSA0LjMgb25seSwgRmlyZWZveCA8PTMgLSA0NFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdFZhbCA9IGRpdlN0eWxlLm1hcmdpbkxlZnQgPT09IFwiMnB4XCI7XG5cdFx0Ym94U2l6aW5nUmVsaWFibGVWYWwgPSBkaXZTdHlsZS53aWR0aCA9PT0gXCI0cHhcIjtcblxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgNC4wIC0gNC4zIG9ubHlcblx0XHQvLyBTb21lIHN0eWxlcyBjb21lIGJhY2sgd2l0aCBwZXJjZW50YWdlIHZhbHVlcywgZXZlbiB0aG91Z2ggdGhleSBzaG91bGRuJ3Rcblx0XHRkaXYuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjUwJVwiO1xuXHRcdHBpeGVsTWFyZ2luUmlnaHRWYWwgPSBkaXZTdHlsZS5tYXJnaW5SaWdodCA9PT0gXCI0cHhcIjtcblxuXHRcdGRvY3VtZW50RWxlbWVudC5yZW1vdmVDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHQvLyBOdWxsaWZ5IHRoZSBkaXYgc28gaXQgd291bGRuJ3QgYmUgc3RvcmVkIGluIHRoZSBtZW1vcnkgYW5kXG5cdFx0Ly8gaXQgd2lsbCBhbHNvIGJlIGEgc2lnbiB0aGF0IGNoZWNrcyBhbHJlYWR5IHBlcmZvcm1lZFxuXHRcdGRpdiA9IG51bGw7XG5cdH1cblxuXHR2YXIgcGl4ZWxQb3NpdGlvblZhbCwgYm94U2l6aW5nUmVsaWFibGVWYWwsIHBpeGVsTWFyZ2luUmlnaHRWYWwsIHJlbGlhYmxlTWFyZ2luTGVmdFZhbCxcblx0XHRjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICksXG5cdFx0ZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApO1xuXG5cdC8vIEZpbmlzaCBlYXJseSBpbiBsaW1pdGVkIChub24tYnJvd3NlcikgZW52aXJvbm1lbnRzXG5cdGlmICggIWRpdi5zdHlsZSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSBvbmx5XG5cdC8vIFN0eWxlIG9mIGNsb25lZCBlbGVtZW50IGFmZmVjdHMgc291cmNlIGVsZW1lbnQgY2xvbmVkICgjODkwOClcblx0ZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID0gXCJjb250ZW50LWJveFwiO1xuXHRkaXYuY2xvbmVOb2RlKCB0cnVlICkuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcIlwiO1xuXHRzdXBwb3J0LmNsZWFyQ2xvbmVTdHlsZSA9IGRpdi5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9PT0gXCJjb250ZW50LWJveFwiO1xuXG5cdGNvbnRhaW5lci5zdHlsZS5jc3NUZXh0ID0gXCJib3JkZXI6MDt3aWR0aDo4cHg7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4O1wiICtcblx0XHRcInBhZGRpbmc6MDttYXJnaW4tdG9wOjFweDtwb3NpdGlvbjphYnNvbHV0ZVwiO1xuXHRjb250YWluZXIuYXBwZW5kQ2hpbGQoIGRpdiApO1xuXG5cdGpRdWVyeS5leHRlbmQoIHN1cHBvcnQsIHtcblx0XHRwaXhlbFBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxQb3NpdGlvblZhbDtcblx0XHR9LFxuXHRcdGJveFNpemluZ1JlbGlhYmxlOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gYm94U2l6aW5nUmVsaWFibGVWYWw7XG5cdFx0fSxcblx0XHRwaXhlbE1hcmdpblJpZ2h0OiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxNYXJnaW5SaWdodFZhbDtcblx0XHR9LFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRjb21wdXRlU3R5bGVUZXN0cygpO1xuXHRcdFx0cmV0dXJuIHJlbGlhYmxlTWFyZ2luTGVmdFZhbDtcblx0XHR9XG5cdH0gKTtcbn0gKSgpO1xuXG5cbmZ1bmN0aW9uIGN1ckNTUyggZWxlbSwgbmFtZSwgY29tcHV0ZWQgKSB7XG5cdHZhciB3aWR0aCwgbWluV2lkdGgsIG1heFdpZHRoLCByZXQsXG5cblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDUxK1xuXHRcdC8vIFJldHJpZXZpbmcgc3R5bGUgYmVmb3JlIGNvbXB1dGVkIHNvbWVob3dcblx0XHQvLyBmaXhlcyBhbiBpc3N1ZSB3aXRoIGdldHRpbmcgd3JvbmcgdmFsdWVzXG5cdFx0Ly8gb24gZGV0YWNoZWQgZWxlbWVudHNcblx0XHRzdHlsZSA9IGVsZW0uc3R5bGU7XG5cblx0Y29tcHV0ZWQgPSBjb21wdXRlZCB8fCBnZXRTdHlsZXMoIGVsZW0gKTtcblxuXHQvLyBnZXRQcm9wZXJ0eVZhbHVlIGlzIG5lZWRlZCBmb3I6XG5cdC8vICAgLmNzcygnZmlsdGVyJykgKElFIDkgb25seSwgIzEyNTM3KVxuXHQvLyAgIC5jc3MoJy0tY3VzdG9tUHJvcGVydHkpICgjMzE0NClcblx0aWYgKCBjb21wdXRlZCApIHtcblx0XHRyZXQgPSBjb21wdXRlZC5nZXRQcm9wZXJ0eVZhbHVlKCBuYW1lICkgfHwgY29tcHV0ZWRbIG5hbWUgXTtcblxuXHRcdGlmICggcmV0ID09PSBcIlwiICYmICFqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICkge1xuXHRcdFx0cmV0ID0galF1ZXJ5LnN0eWxlKCBlbGVtLCBuYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gQSB0cmlidXRlIHRvIHRoZSBcImF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHNcIlxuXHRcdC8vIEFuZHJvaWQgQnJvd3NlciByZXR1cm5zIHBlcmNlbnRhZ2UgZm9yIHNvbWUgdmFsdWVzLFxuXHRcdC8vIGJ1dCB3aWR0aCBzZWVtcyB0byBiZSByZWxpYWJseSBwaXhlbHMuXG5cdFx0Ly8gVGhpcyBpcyBhZ2FpbnN0IHRoZSBDU1NPTSBkcmFmdCBzcGVjOlxuXHRcdC8vIGh0dHBzOi8vZHJhZnRzLmNzc3dnLm9yZy9jc3NvbS8jcmVzb2x2ZWQtdmFsdWVzXG5cdFx0aWYgKCAhc3VwcG9ydC5waXhlbE1hcmdpblJpZ2h0KCkgJiYgcm51bW5vbnB4LnRlc3QoIHJldCApICYmIHJtYXJnaW4udGVzdCggbmFtZSApICkge1xuXG5cdFx0XHQvLyBSZW1lbWJlciB0aGUgb3JpZ2luYWwgdmFsdWVzXG5cdFx0XHR3aWR0aCA9IHN0eWxlLndpZHRoO1xuXHRcdFx0bWluV2lkdGggPSBzdHlsZS5taW5XaWR0aDtcblx0XHRcdG1heFdpZHRoID0gc3R5bGUubWF4V2lkdGg7XG5cblx0XHRcdC8vIFB1dCBpbiB0aGUgbmV3IHZhbHVlcyB0byBnZXQgYSBjb21wdXRlZCB2YWx1ZSBvdXRcblx0XHRcdHN0eWxlLm1pbldpZHRoID0gc3R5bGUubWF4V2lkdGggPSBzdHlsZS53aWR0aCA9IHJldDtcblx0XHRcdHJldCA9IGNvbXB1dGVkLndpZHRoO1xuXG5cdFx0XHQvLyBSZXZlcnQgdGhlIGNoYW5nZWQgdmFsdWVzXG5cdFx0XHRzdHlsZS53aWR0aCA9IHdpZHRoO1xuXHRcdFx0c3R5bGUubWluV2lkdGggPSBtaW5XaWR0aDtcblx0XHRcdHN0eWxlLm1heFdpZHRoID0gbWF4V2lkdGg7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHJldCAhPT0gdW5kZWZpbmVkID9cblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0XHQvLyBJRSByZXR1cm5zIHpJbmRleCB2YWx1ZSBhcyBhbiBpbnRlZ2VyLlxuXHRcdHJldCArIFwiXCIgOlxuXHRcdHJldDtcbn1cblxuXG5mdW5jdGlvbiBhZGRHZXRIb29rSWYoIGNvbmRpdGlvbkZuLCBob29rRm4gKSB7XG5cblx0Ly8gRGVmaW5lIHRoZSBob29rLCB3ZSdsbCBjaGVjayBvbiB0aGUgZmlyc3QgcnVuIGlmIGl0J3MgcmVhbGx5IG5lZWRlZC5cblx0cmV0dXJuIHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCBjb25kaXRpb25GbigpICkge1xuXG5cdFx0XHRcdC8vIEhvb2sgbm90IG5lZWRlZCAob3IgaXQncyBub3QgcG9zc2libGUgdG8gdXNlIGl0IGR1ZVxuXHRcdFx0XHQvLyB0byBtaXNzaW5nIGRlcGVuZGVuY3kpLCByZW1vdmUgaXQuXG5cdFx0XHRcdGRlbGV0ZSB0aGlzLmdldDtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBIb29rIG5lZWRlZDsgcmVkZWZpbmUgaXQgc28gdGhhdCB0aGUgc3VwcG9ydCB0ZXN0IGlzIG5vdCBleGVjdXRlZCBhZ2Fpbi5cblx0XHRcdHJldHVybiAoIHRoaXMuZ2V0ID0gaG9va0ZuICkuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0fTtcbn1cblxuXG52YXJcblxuXHQvLyBTd2FwcGFibGUgaWYgZGlzcGxheSBpcyBub25lIG9yIHN0YXJ0cyB3aXRoIHRhYmxlXG5cdC8vIGV4Y2VwdCBcInRhYmxlXCIsIFwidGFibGUtY2VsbFwiLCBvciBcInRhYmxlLWNhcHRpb25cIlxuXHQvLyBTZWUgaGVyZSBmb3IgZGlzcGxheSB2YWx1ZXM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvQ1NTL2Rpc3BsYXlcblx0cmRpc3BsYXlzd2FwID0gL14obm9uZXx0YWJsZSg/IS1jW2VhXSkuKykvLFxuXHRyY3VzdG9tUHJvcCA9IC9eLS0vLFxuXHRjc3NTaG93ID0geyBwb3NpdGlvbjogXCJhYnNvbHV0ZVwiLCB2aXNpYmlsaXR5OiBcImhpZGRlblwiLCBkaXNwbGF5OiBcImJsb2NrXCIgfSxcblx0Y3NzTm9ybWFsVHJhbnNmb3JtID0ge1xuXHRcdGxldHRlclNwYWNpbmc6IFwiMFwiLFxuXHRcdGZvbnRXZWlnaHQ6IFwiNDAwXCJcblx0fSxcblxuXHRjc3NQcmVmaXhlcyA9IFsgXCJXZWJraXRcIiwgXCJNb3pcIiwgXCJtc1wiIF0sXG5cdGVtcHR5U3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkuc3R5bGU7XG5cbi8vIFJldHVybiBhIGNzcyBwcm9wZXJ0eSBtYXBwZWQgdG8gYSBwb3RlbnRpYWxseSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHlcbmZ1bmN0aW9uIHZlbmRvclByb3BOYW1lKCBuYW1lICkge1xuXG5cdC8vIFNob3J0Y3V0IGZvciBuYW1lcyB0aGF0IGFyZSBub3QgdmVuZG9yIHByZWZpeGVkXG5cdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdHJldHVybiBuYW1lO1xuXHR9XG5cblx0Ly8gQ2hlY2sgZm9yIHZlbmRvciBwcmVmaXhlZCBuYW1lc1xuXHR2YXIgY2FwTmFtZSA9IG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApLFxuXHRcdGkgPSBjc3NQcmVmaXhlcy5sZW5ndGg7XG5cblx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0bmFtZSA9IGNzc1ByZWZpeGVzWyBpIF0gKyBjYXBOYW1lO1xuXHRcdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdFx0cmV0dXJuIG5hbWU7XG5cdFx0fVxuXHR9XG59XG5cbi8vIFJldHVybiBhIHByb3BlcnR5IG1hcHBlZCBhbG9uZyB3aGF0IGpRdWVyeS5jc3NQcm9wcyBzdWdnZXN0cyBvciB0b1xuLy8gYSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHkuXG5mdW5jdGlvbiBmaW5hbFByb3BOYW1lKCBuYW1lICkge1xuXHR2YXIgcmV0ID0galF1ZXJ5LmNzc1Byb3BzWyBuYW1lIF07XG5cdGlmICggIXJldCApIHtcblx0XHRyZXQgPSBqUXVlcnkuY3NzUHJvcHNbIG5hbWUgXSA9IHZlbmRvclByb3BOYW1lKCBuYW1lICkgfHwgbmFtZTtcblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICkge1xuXG5cdC8vIEFueSByZWxhdGl2ZSAoKy8tKSB2YWx1ZXMgaGF2ZSBhbHJlYWR5IGJlZW5cblx0Ly8gbm9ybWFsaXplZCBhdCB0aGlzIHBvaW50XG5cdHZhciBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApO1xuXHRyZXR1cm4gbWF0Y2hlcyA/XG5cblx0XHQvLyBHdWFyZCBhZ2FpbnN0IHVuZGVmaW5lZCBcInN1YnRyYWN0XCIsIGUuZy4sIHdoZW4gdXNlZCBhcyBpbiBjc3NIb29rc1xuXHRcdE1hdGgubWF4KCAwLCBtYXRjaGVzWyAyIF0gLSAoIHN1YnRyYWN0IHx8IDAgKSApICsgKCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgOlxuXHRcdHZhbHVlO1xufVxuXG5mdW5jdGlvbiBhdWdtZW50V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEsIGlzQm9yZGVyQm94LCBzdHlsZXMgKSB7XG5cdHZhciBpLFxuXHRcdHZhbCA9IDA7XG5cblx0Ly8gSWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBtZWFzdXJlbWVudCwgYXZvaWQgYXVnbWVudGF0aW9uXG5cdGlmICggZXh0cmEgPT09ICggaXNCb3JkZXJCb3ggPyBcImJvcmRlclwiIDogXCJjb250ZW50XCIgKSApIHtcblx0XHRpID0gNDtcblxuXHQvLyBPdGhlcndpc2UgaW5pdGlhbGl6ZSBmb3IgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBwcm9wZXJ0aWVzXG5cdH0gZWxzZSB7XG5cdFx0aSA9IG5hbWUgPT09IFwid2lkdGhcIiA/IDEgOiAwO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgNDsgaSArPSAyICkge1xuXG5cdFx0Ly8gQm90aCBib3ggbW9kZWxzIGV4Y2x1ZGUgbWFyZ2luLCBzbyBhZGQgaXQgaWYgd2Ugd2FudCBpdFxuXHRcdGlmICggZXh0cmEgPT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHR2YWwgKz0galF1ZXJ5LmNzcyggZWxlbSwgZXh0cmEgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpc0JvcmRlckJveCApIHtcblxuXHRcdFx0Ly8gYm9yZGVyLWJveCBpbmNsdWRlcyBwYWRkaW5nLCBzbyByZW1vdmUgaXQgaWYgd2Ugd2FudCBjb250ZW50XG5cdFx0XHRpZiAoIGV4dHJhID09PSBcImNvbnRlbnRcIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBib3JkZXIgbm9yIG1hcmdpbiwgc28gcmVtb3ZlIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJtYXJnaW5cIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCwgc28gYWRkIHBhZGRpbmdcblx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBhZGRpbmdcIiArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCBub3IgcGFkZGluZywgc28gYWRkIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJwYWRkaW5nXCIgKSB7XG5cdFx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcImJvcmRlclwiICsgY3NzRXhwYW5kWyBpIF0gKyBcIldpZHRoXCIsIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICkge1xuXG5cdC8vIFN0YXJ0IHdpdGggY29tcHV0ZWQgc3R5bGVcblx0dmFyIHZhbHVlSXNCb3JkZXJCb3gsXG5cdFx0c3R5bGVzID0gZ2V0U3R5bGVzKCBlbGVtICksXG5cdFx0dmFsID0gY3VyQ1NTKCBlbGVtLCBuYW1lLCBzdHlsZXMgKSxcblx0XHRpc0JvcmRlckJveCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm94U2l6aW5nXCIsIGZhbHNlLCBzdHlsZXMgKSA9PT0gXCJib3JkZXItYm94XCI7XG5cblx0Ly8gQ29tcHV0ZWQgdW5pdCBpcyBub3QgcGl4ZWxzLiBTdG9wIGhlcmUgYW5kIHJldHVybi5cblx0aWYgKCBybnVtbm9ucHgudGVzdCggdmFsICkgKSB7XG5cdFx0cmV0dXJuIHZhbDtcblx0fVxuXG5cdC8vIENoZWNrIGZvciBzdHlsZSBpbiBjYXNlIGEgYnJvd3NlciB3aGljaCByZXR1cm5zIHVucmVsaWFibGUgdmFsdWVzXG5cdC8vIGZvciBnZXRDb21wdXRlZFN0eWxlIHNpbGVudGx5IGZhbGxzIGJhY2sgdG8gdGhlIHJlbGlhYmxlIGVsZW0uc3R5bGVcblx0dmFsdWVJc0JvcmRlckJveCA9IGlzQm9yZGVyQm94ICYmXG5cdFx0KCBzdXBwb3J0LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgdmFsID09PSBlbGVtLnN0eWxlWyBuYW1lIF0gKTtcblxuXHQvLyBGYWxsIGJhY2sgdG8gb2Zmc2V0V2lkdGgvSGVpZ2h0IHdoZW4gdmFsdWUgaXMgXCJhdXRvXCJcblx0Ly8gVGhpcyBoYXBwZW5zIGZvciBpbmxpbmUgZWxlbWVudHMgd2l0aCBubyBleHBsaWNpdCBzZXR0aW5nIChnaC0zNTcxKVxuXHRpZiAoIHZhbCA9PT0gXCJhdXRvXCIgKSB7XG5cdFx0dmFsID0gZWxlbVsgXCJvZmZzZXRcIiArIG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApIF07XG5cdH1cblxuXHQvLyBOb3JtYWxpemUgXCJcIiwgYXV0bywgYW5kIHByZXBhcmUgZm9yIGV4dHJhXG5cdHZhbCA9IHBhcnNlRmxvYXQoIHZhbCApIHx8IDA7XG5cblx0Ly8gVXNlIHRoZSBhY3RpdmUgYm94LXNpemluZyBtb2RlbCB0byBhZGQvc3VidHJhY3QgaXJyZWxldmFudCBzdHlsZXNcblx0cmV0dXJuICggdmFsICtcblx0XHRhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdGVsZW0sXG5cdFx0XHRuYW1lLFxuXHRcdFx0ZXh0cmEgfHwgKCBpc0JvcmRlckJveCA/IFwiYm9yZGVyXCIgOiBcImNvbnRlbnRcIiApLFxuXHRcdFx0dmFsdWVJc0JvcmRlckJveCxcblx0XHRcdHN0eWxlc1xuXHRcdClcblx0KSArIFwicHhcIjtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIEFkZCBpbiBzdHlsZSBwcm9wZXJ0eSBob29rcyBmb3Igb3ZlcnJpZGluZyB0aGUgZGVmYXVsdFxuXHQvLyBiZWhhdmlvciBvZiBnZXR0aW5nIGFuZCBzZXR0aW5nIGEgc3R5bGUgcHJvcGVydHlcblx0Y3NzSG9va3M6IHtcblx0XHRvcGFjaXR5OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblxuXHRcdFx0XHRcdC8vIFdlIHNob3VsZCBhbHdheXMgZ2V0IGEgbnVtYmVyIGJhY2sgZnJvbSBvcGFjaXR5XG5cdFx0XHRcdFx0dmFyIHJldCA9IGN1ckNTUyggZWxlbSwgXCJvcGFjaXR5XCIgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmV0ID09PSBcIlwiID8gXCIxXCIgOiByZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0Ly8gRG9uJ3QgYXV0b21hdGljYWxseSBhZGQgXCJweFwiIHRvIHRoZXNlIHBvc3NpYmx5LXVuaXRsZXNzIHByb3BlcnRpZXNcblx0Y3NzTnVtYmVyOiB7XG5cdFx0XCJhbmltYXRpb25JdGVyYXRpb25Db3VudFwiOiB0cnVlLFxuXHRcdFwiY29sdW1uQ291bnRcIjogdHJ1ZSxcblx0XHRcImZpbGxPcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJmbGV4R3Jvd1wiOiB0cnVlLFxuXHRcdFwiZmxleFNocmlua1wiOiB0cnVlLFxuXHRcdFwiZm9udFdlaWdodFwiOiB0cnVlLFxuXHRcdFwibGluZUhlaWdodFwiOiB0cnVlLFxuXHRcdFwib3BhY2l0eVwiOiB0cnVlLFxuXHRcdFwib3JkZXJcIjogdHJ1ZSxcblx0XHRcIm9ycGhhbnNcIjogdHJ1ZSxcblx0XHRcIndpZG93c1wiOiB0cnVlLFxuXHRcdFwiekluZGV4XCI6IHRydWUsXG5cdFx0XCJ6b29tXCI6IHRydWVcblx0fSxcblxuXHQvLyBBZGQgaW4gcHJvcGVydGllcyB3aG9zZSBuYW1lcyB5b3Ugd2lzaCB0byBmaXggYmVmb3JlXG5cdC8vIHNldHRpbmcgb3IgZ2V0dGluZyB0aGUgdmFsdWVcblx0Y3NzUHJvcHM6IHtcblx0XHRcImZsb2F0XCI6IFwiY3NzRmxvYXRcIlxuXHR9LFxuXG5cdC8vIEdldCBhbmQgc2V0IHRoZSBzdHlsZSBwcm9wZXJ0eSBvbiBhIERPTSBOb2RlXG5cdHN0eWxlOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUsIGV4dHJhICkge1xuXG5cdFx0Ly8gRG9uJ3Qgc2V0IHN0eWxlcyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBlbGVtLm5vZGVUeXBlID09PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT09IDggfHwgIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lXG5cdFx0dmFyIHJldCwgdHlwZSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKSxcblx0XHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIHF1ZXJ5IHRoZSB2YWx1ZSBpZiBpdCBpcyBhIENTUyBjdXN0b20gcHJvcGVydHlcblx0XHQvLyBzaW5jZSB0aGV5IGFyZSB1c2VyLWRlZmluZWQuXG5cdFx0aWYgKCAhaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0bmFtZSA9IGZpbmFsUHJvcE5hbWUoIG9yaWdOYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0cyBob29rIGZvciB0aGUgcHJlZml4ZWQgdmVyc2lvbiwgdGhlbiB1bnByZWZpeGVkIHZlcnNpb25cblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIENoZWNrIGlmIHdlJ3JlIHNldHRpbmcgYSB2YWx1ZVxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cblx0XHRcdC8vIENvbnZlcnQgXCIrPVwiIG9yIFwiLT1cIiB0byByZWxhdGl2ZSBudW1iZXJzICgjNzM0NSlcblx0XHRcdGlmICggdHlwZSA9PT0gXCJzdHJpbmdcIiAmJiAoIHJldCA9IHJjc3NOdW0uZXhlYyggdmFsdWUgKSApICYmIHJldFsgMSBdICkge1xuXHRcdFx0XHR2YWx1ZSA9IGFkanVzdENTUyggZWxlbSwgbmFtZSwgcmV0ICk7XG5cblx0XHRcdFx0Ly8gRml4ZXMgYnVnICM5MjM3XG5cdFx0XHRcdHR5cGUgPSBcIm51bWJlclwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgdGhhdCBudWxsIGFuZCBOYU4gdmFsdWVzIGFyZW4ndCBzZXQgKCM3MTE2KVxuXHRcdFx0aWYgKCB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBhIG51bWJlciB3YXMgcGFzc2VkIGluLCBhZGQgdGhlIHVuaXQgKGV4Y2VwdCBmb3IgY2VydGFpbiBDU1MgcHJvcGVydGllcylcblx0XHRcdGlmICggdHlwZSA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsdWUgKz0gcmV0ICYmIHJldFsgMyBdIHx8ICggalF1ZXJ5LmNzc051bWJlclsgb3JpZ05hbWUgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gYmFja2dyb3VuZC0qIHByb3BzIGFmZmVjdCBvcmlnaW5hbCBjbG9uZSdzIHZhbHVlc1xuXHRcdFx0aWYgKCAhc3VwcG9ydC5jbGVhckNsb25lU3R5bGUgJiYgdmFsdWUgPT09IFwiXCIgJiYgbmFtZS5pbmRleE9mKCBcImJhY2tncm91bmRcIiApID09PSAwICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gXCJpbmhlcml0XCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0IHZhbHVlLCBvdGhlcndpc2UganVzdCBzZXQgdGhlIHNwZWNpZmllZCB2YWx1ZVxuXHRcdFx0aWYgKCAhaG9va3MgfHwgISggXCJzZXRcIiBpbiBob29rcyApIHx8XG5cdFx0XHRcdCggdmFsdWUgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBleHRyYSApICkgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHRpZiAoIGlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdFx0XHRzdHlsZS5zZXRQcm9wZXJ0eSggbmFtZSwgdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBub24tY29tcHV0ZWQgdmFsdWUgZnJvbSB0aGVyZVxuXHRcdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBmYWxzZSwgZXh0cmEgKSApICE9PSB1bmRlZmluZWQgKSB7XG5cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gT3RoZXJ3aXNlIGp1c3QgZ2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBzdHlsZSBvYmplY3Rcblx0XHRcdHJldHVybiBzdHlsZVsgbmFtZSBdO1xuXHRcdH1cblx0fSxcblxuXHRjc3M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBleHRyYSwgc3R5bGVzICkge1xuXHRcdHZhciB2YWwsIG51bSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIG1vZGlmeSB0aGUgdmFsdWUgaWYgaXQgaXMgYSBDU1MgY3VzdG9tIHByb3BlcnR5XG5cdFx0Ly8gc2luY2UgdGhleSBhcmUgdXNlci1kZWZpbmVkLlxuXHRcdGlmICggIWlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdG5hbWUgPSBmaW5hbFByb3BOYW1lKCBvcmlnTmFtZSApO1xuXHRcdH1cblxuXHRcdC8vIFRyeSBwcmVmaXhlZCBuYW1lIGZvbGxvd2VkIGJ5IHRoZSB1bnByZWZpeGVkIG5hbWVcblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsID0gaG9va3MuZ2V0KCBlbGVtLCB0cnVlLCBleHRyYSApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSwgaWYgYSB3YXkgdG8gZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbCA9IGN1ckNTUyggZWxlbSwgbmFtZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udmVydCBcIm5vcm1hbFwiIHRvIGNvbXB1dGVkIHZhbHVlXG5cdFx0aWYgKCB2YWwgPT09IFwibm9ybWFsXCIgJiYgbmFtZSBpbiBjc3NOb3JtYWxUcmFuc2Zvcm0gKSB7XG5cdFx0XHR2YWwgPSBjc3NOb3JtYWxUcmFuc2Zvcm1bIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIG51bWVyaWMgaWYgZm9yY2VkIG9yIGEgcXVhbGlmaWVyIHdhcyBwcm92aWRlZCBhbmQgdmFsIGxvb2tzIG51bWVyaWNcblx0XHRpZiAoIGV4dHJhID09PSBcIlwiIHx8IGV4dHJhICkge1xuXHRcdFx0bnVtID0gcGFyc2VGbG9hdCggdmFsICk7XG5cdFx0XHRyZXR1cm4gZXh0cmEgPT09IHRydWUgfHwgaXNGaW5pdGUoIG51bSApID8gbnVtIHx8IDAgOiB2YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbDtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImhlaWdodFwiLCBcIndpZHRoXCIgXSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdID0ge1xuXHRcdGdldDogZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkLCBleHRyYSApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cblx0XHRcdFx0Ly8gQ2VydGFpbiBlbGVtZW50cyBjYW4gaGF2ZSBkaW1lbnNpb24gaW5mbyBpZiB3ZSBpbnZpc2libHkgc2hvdyB0aGVtXG5cdFx0XHRcdC8vIGJ1dCBpdCBtdXN0IGhhdmUgYSBjdXJyZW50IGRpc3BsYXkgc3R5bGUgdGhhdCB3b3VsZCBiZW5lZml0XG5cdFx0XHRcdHJldHVybiByZGlzcGxheXN3YXAudGVzdCggalF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKSApICYmXG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCtcblx0XHRcdFx0XHQvLyBUYWJsZSBjb2x1bW5zIGluIFNhZmFyaSBoYXZlIG5vbi16ZXJvIG9mZnNldFdpZHRoICYgemVyb1xuXHRcdFx0XHRcdC8vIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIHVubGVzcyBkaXNwbGF5IGlzIGNoYW5nZWQuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0XHRcdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYSBkaXNjb25uZWN0ZWQgbm9kZVxuXHRcdFx0XHRcdC8vIGluIElFIHRocm93cyBhbiBlcnJvci5cblx0XHRcdFx0XHQoICFlbGVtLmdldENsaWVudFJlY3RzKCkubGVuZ3RoIHx8ICFlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoICkgP1xuXHRcdFx0XHRcdFx0c3dhcCggZWxlbSwgY3NzU2hvdywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBnZXRXaWR0aE9ySGVpZ2h0KCBlbGVtLCBuYW1lLCBleHRyYSApO1xuXHRcdFx0XHRcdFx0fSApIDpcblx0XHRcdFx0XHRcdGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBleHRyYSApIHtcblx0XHRcdHZhciBtYXRjaGVzLFxuXHRcdFx0XHRzdHlsZXMgPSBleHRyYSAmJiBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHRcdFx0c3VidHJhY3QgPSBleHRyYSAmJiBhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdFx0XHRlbGVtLFxuXHRcdFx0XHRcdG5hbWUsXG5cdFx0XHRcdFx0ZXh0cmEsXG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIixcblx0XHRcdFx0XHRzdHlsZXNcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gQ29udmVydCB0byBwaXhlbHMgaWYgdmFsdWUgYWRqdXN0bWVudCBpcyBuZWVkZWRcblx0XHRcdGlmICggc3VidHJhY3QgJiYgKCBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApICkgJiZcblx0XHRcdFx0KCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgIT09IFwicHhcIiApIHtcblxuXHRcdFx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdFx0dmFsdWUgPSBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICk7XG5cdFx0fVxuXHR9O1xufSApO1xuXG5qUXVlcnkuY3NzSG9va3MubWFyZ2luTGVmdCA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5yZWxpYWJsZU1hcmdpbkxlZnQsXG5cdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRpZiAoIGNvbXB1dGVkICkge1xuXHRcdFx0cmV0dXJuICggcGFyc2VGbG9hdCggY3VyQ1NTKCBlbGVtLCBcIm1hcmdpbkxlZnRcIiApICkgfHxcblx0XHRcdFx0ZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC1cblx0XHRcdFx0XHRzd2FwKCBlbGVtLCB7IG1hcmdpbkxlZnQ6IDAgfSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuXHRcdFx0XHRcdH0gKVxuXHRcdFx0XHQpICsgXCJweFwiO1xuXHRcdH1cblx0fVxuKTtcblxuLy8gVGhlc2UgaG9va3MgYXJlIHVzZWQgYnkgYW5pbWF0ZSB0byBleHBhbmQgcHJvcGVydGllc1xualF1ZXJ5LmVhY2goIHtcblx0bWFyZ2luOiBcIlwiLFxuXHRwYWRkaW5nOiBcIlwiLFxuXHRib3JkZXI6IFwiV2lkdGhcIlxufSwgZnVuY3Rpb24oIHByZWZpeCwgc3VmZml4ICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdID0ge1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGkgPSAwLFxuXHRcdFx0XHRleHBhbmRlZCA9IHt9LFxuXG5cdFx0XHRcdC8vIEFzc3VtZXMgYSBzaW5nbGUgbnVtYmVyIGlmIG5vdCBhIHN0cmluZ1xuXHRcdFx0XHRwYXJ0cyA9IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlLnNwbGl0KCBcIiBcIiApIDogWyB2YWx1ZSBdO1xuXG5cdFx0XHRmb3IgKCA7IGkgPCA0OyBpKysgKSB7XG5cdFx0XHRcdGV4cGFuZGVkWyBwcmVmaXggKyBjc3NFeHBhbmRbIGkgXSArIHN1ZmZpeCBdID1cblx0XHRcdFx0XHRwYXJ0c1sgaSBdIHx8IHBhcnRzWyBpIC0gMiBdIHx8IHBhcnRzWyAwIF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBleHBhbmRlZDtcblx0XHR9XG5cdH07XG5cblx0aWYgKCAhcm1hcmdpbi50ZXN0KCBwcmVmaXggKSApIHtcblx0XHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdLnNldCA9IHNldFBvc2l0aXZlTnVtYmVyO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0Y3NzOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0dmFyIHN0eWxlcywgbGVuLFxuXHRcdFx0XHRtYXAgPSB7fSxcblx0XHRcdFx0aSA9IDA7XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggbmFtZSApICkge1xuXHRcdFx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKTtcblx0XHRcdFx0bGVuID0gbmFtZS5sZW5ndGg7XG5cblx0XHRcdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0bWFwWyBuYW1lWyBpIF0gXSA9IGpRdWVyeS5jc3MoIGVsZW0sIG5hbWVbIGkgXSwgZmFsc2UsIHN0eWxlcyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIG1hcDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUsIHZhbHVlICkgOlxuXHRcdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0fSwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH1cbn0gKTtcblxuXG5mdW5jdGlvbiBUd2VlbiggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKSB7XG5cdHJldHVybiBuZXcgVHdlZW4ucHJvdG90eXBlLmluaXQoIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nICk7XG59XG5qUXVlcnkuVHdlZW4gPSBUd2VlbjtcblxuVHdlZW4ucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogVHdlZW4sXG5cdGluaXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZywgdW5pdCApIHtcblx0XHR0aGlzLmVsZW0gPSBlbGVtO1xuXHRcdHRoaXMucHJvcCA9IHByb3A7XG5cdFx0dGhpcy5lYXNpbmcgPSBlYXNpbmcgfHwgalF1ZXJ5LmVhc2luZy5fZGVmYXVsdDtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHRcdHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCk7XG5cdFx0dGhpcy5lbmQgPSBlbmQ7XG5cdFx0dGhpcy51bml0ID0gdW5pdCB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0fSxcblx0Y3VyOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0cmV0dXJuIGhvb2tzICYmIGhvb2tzLmdldCA/XG5cdFx0XHRob29rcy5nZXQoIHRoaXMgKSA6XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuZ2V0KCB0aGlzICk7XG5cdH0sXG5cdHJ1bjogZnVuY3Rpb24oIHBlcmNlbnQgKSB7XG5cdFx0dmFyIGVhc2VkLFxuXHRcdFx0aG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0galF1ZXJ5LmVhc2luZ1sgdGhpcy5lYXNpbmcgXShcblx0XHRcdFx0cGVyY2VudCwgdGhpcy5vcHRpb25zLmR1cmF0aW9uICogcGVyY2VudCwgMCwgMSwgdGhpcy5vcHRpb25zLmR1cmF0aW9uXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0gcGVyY2VudDtcblx0XHR9XG5cdFx0dGhpcy5ub3cgPSAoIHRoaXMuZW5kIC0gdGhpcy5zdGFydCApICogZWFzZWQgKyB0aGlzLnN0YXJ0O1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc3RlcCApIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zdGVwLmNhbGwoIHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMgKTtcblx0XHR9XG5cblx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnNldCApIHtcblx0XHRcdGhvb2tzLnNldCggdGhpcyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KCB0aGlzICk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59O1xuXG5Ud2Vlbi5wcm90b3R5cGUuaW5pdC5wcm90b3R5cGUgPSBUd2Vlbi5wcm90b3R5cGU7XG5cblR3ZWVuLnByb3BIb29rcyA9IHtcblx0X2RlZmF1bHQ6IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRcdHZhciByZXN1bHQ7XG5cblx0XHRcdC8vIFVzZSBhIHByb3BlcnR5IG9uIHRoZSBlbGVtZW50IGRpcmVjdGx5IHdoZW4gaXQgaXMgbm90IGEgRE9NIGVsZW1lbnQsXG5cdFx0XHQvLyBvciB3aGVuIHRoZXJlIGlzIG5vIG1hdGNoaW5nIHN0eWxlIHByb3BlcnR5IHRoYXQgZXhpc3RzLlxuXHRcdFx0aWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlICE9PSAxIHx8XG5cdFx0XHRcdHR3ZWVuLmVsZW1bIHR3ZWVuLnByb3AgXSAhPSBudWxsICYmIHR3ZWVuLmVsZW0uc3R5bGVbIHR3ZWVuLnByb3AgXSA9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gdHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQYXNzaW5nIGFuIGVtcHR5IHN0cmluZyBhcyBhIDNyZCBwYXJhbWV0ZXIgdG8gLmNzcyB3aWxsIGF1dG9tYXRpY2FsbHlcblx0XHRcdC8vIGF0dGVtcHQgYSBwYXJzZUZsb2F0IGFuZCBmYWxsYmFjayB0byBhIHN0cmluZyBpZiB0aGUgcGFyc2UgZmFpbHMuXG5cdFx0XHQvLyBTaW1wbGUgdmFsdWVzIHN1Y2ggYXMgXCIxMHB4XCIgYXJlIHBhcnNlZCB0byBGbG9hdDtcblx0XHRcdC8vIGNvbXBsZXggdmFsdWVzIHN1Y2ggYXMgXCJyb3RhdGUoMXJhZClcIiBhcmUgcmV0dXJuZWQgYXMtaXMuXG5cdFx0XHRyZXN1bHQgPSBqUXVlcnkuY3NzKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCBcIlwiICk7XG5cblx0XHRcdC8vIEVtcHR5IHN0cmluZ3MsIG51bGwsIHVuZGVmaW5lZCBhbmQgXCJhdXRvXCIgYXJlIGNvbnZlcnRlZCB0byAwLlxuXHRcdFx0cmV0dXJuICFyZXN1bHQgfHwgcmVzdWx0ID09PSBcImF1dG9cIiA/IDAgOiByZXN1bHQ7XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblxuXHRcdFx0Ly8gVXNlIHN0ZXAgaG9vayBmb3IgYmFjayBjb21wYXQuXG5cdFx0XHQvLyBVc2UgY3NzSG9vayBpZiBpdHMgdGhlcmUuXG5cdFx0XHQvLyBVc2UgLnN0eWxlIGlmIGF2YWlsYWJsZSBhbmQgdXNlIHBsYWluIHByb3BlcnRpZXMgd2hlcmUgYXZhaWxhYmxlLlxuXHRcdFx0aWYgKCBqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdICkge1xuXHRcdFx0XHRqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdKCB0d2VlbiApO1xuXHRcdFx0fSBlbHNlIGlmICggdHdlZW4uZWxlbS5ub2RlVHlwZSA9PT0gMSAmJlxuXHRcdFx0XHQoIHR3ZWVuLmVsZW0uc3R5bGVbIGpRdWVyeS5jc3NQcm9wc1sgdHdlZW4ucHJvcCBdIF0gIT0gbnVsbCB8fFxuXHRcdFx0XHRcdGpRdWVyeS5jc3NIb29rc1sgdHdlZW4ucHJvcCBdICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgdHdlZW4ucHJvcCwgdHdlZW4ubm93ICsgdHdlZW4udW5pdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbi8vIFBhbmljIGJhc2VkIGFwcHJvYWNoIHRvIHNldHRpbmcgdGhpbmdzIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuVHdlZW4ucHJvcEhvb2tzLnNjcm9sbFRvcCA9IFR3ZWVuLnByb3BIb29rcy5zY3JvbGxMZWZ0ID0ge1xuXHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRpZiAoIHR3ZWVuLmVsZW0ubm9kZVR5cGUgJiYgdHdlZW4uZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmVhc2luZyA9IHtcblx0bGluZWFyOiBmdW5jdGlvbiggcCApIHtcblx0XHRyZXR1cm4gcDtcblx0fSxcblx0c3dpbmc6IGZ1bmN0aW9uKCBwICkge1xuXHRcdHJldHVybiAwLjUgLSBNYXRoLmNvcyggcCAqIE1hdGguUEkgKSAvIDI7XG5cdH0sXG5cdF9kZWZhdWx0OiBcInN3aW5nXCJcbn07XG5cbmpRdWVyeS5meCA9IFR3ZWVuLnByb3RvdHlwZS5pbml0O1xuXG4vLyBCYWNrIGNvbXBhdCA8MS44IGV4dGVuc2lvbiBwb2ludFxualF1ZXJ5LmZ4LnN0ZXAgPSB7fTtcblxuXG5cblxudmFyXG5cdGZ4Tm93LCBpblByb2dyZXNzLFxuXHRyZnh0eXBlcyA9IC9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxcblx0cnJ1biA9IC9xdWV1ZUhvb2tzJC87XG5cbmZ1bmN0aW9uIHNjaGVkdWxlKCkge1xuXHRpZiAoIGluUHJvZ3Jlc3MgKSB7XG5cdFx0aWYgKCBkb2N1bWVudC5oaWRkZW4gPT09IGZhbHNlICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgKSB7XG5cdFx0XHR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBzY2hlZHVsZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCggc2NoZWR1bGUsIGpRdWVyeS5meC5pbnRlcnZhbCApO1xuXHRcdH1cblxuXHRcdGpRdWVyeS5meC50aWNrKCk7XG5cdH1cbn1cblxuLy8gQW5pbWF0aW9ucyBjcmVhdGVkIHN5bmNocm9ub3VzbHkgd2lsbCBydW4gc3luY2hyb25vdXNseVxuZnVuY3Rpb24gY3JlYXRlRnhOb3coKSB7XG5cdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRmeE5vdyA9IHVuZGVmaW5lZDtcblx0fSApO1xuXHRyZXR1cm4gKCBmeE5vdyA9IGpRdWVyeS5ub3coKSApO1xufVxuXG4vLyBHZW5lcmF0ZSBwYXJhbWV0ZXJzIHRvIGNyZWF0ZSBhIHN0YW5kYXJkIGFuaW1hdGlvblxuZnVuY3Rpb24gZ2VuRngoIHR5cGUsIGluY2x1ZGVXaWR0aCApIHtcblx0dmFyIHdoaWNoLFxuXHRcdGkgPSAwLFxuXHRcdGF0dHJzID0geyBoZWlnaHQ6IHR5cGUgfTtcblxuXHQvLyBJZiB3ZSBpbmNsdWRlIHdpZHRoLCBzdGVwIHZhbHVlIGlzIDEgdG8gZG8gYWxsIGNzc0V4cGFuZCB2YWx1ZXMsXG5cdC8vIG90aGVyd2lzZSBzdGVwIHZhbHVlIGlzIDIgdG8gc2tpcCBvdmVyIExlZnQgYW5kIFJpZ2h0XG5cdGluY2x1ZGVXaWR0aCA9IGluY2x1ZGVXaWR0aCA/IDEgOiAwO1xuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgLSBpbmNsdWRlV2lkdGggKSB7XG5cdFx0d2hpY2ggPSBjc3NFeHBhbmRbIGkgXTtcblx0XHRhdHRyc1sgXCJtYXJnaW5cIiArIHdoaWNoIF0gPSBhdHRyc1sgXCJwYWRkaW5nXCIgKyB3aGljaCBdID0gdHlwZTtcblx0fVxuXG5cdGlmICggaW5jbHVkZVdpZHRoICkge1xuXHRcdGF0dHJzLm9wYWNpdHkgPSBhdHRycy53aWR0aCA9IHR5cGU7XG5cdH1cblxuXHRyZXR1cm4gYXR0cnM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR3ZWVuKCB2YWx1ZSwgcHJvcCwgYW5pbWF0aW9uICkge1xuXHR2YXIgdHdlZW4sXG5cdFx0Y29sbGVjdGlvbiA9ICggQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW10gKS5jb25jYXQoIEFuaW1hdGlvbi50d2VlbmVyc1sgXCIqXCIgXSApLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRpZiAoICggdHdlZW4gPSBjb2xsZWN0aW9uWyBpbmRleCBdLmNhbGwoIGFuaW1hdGlvbiwgcHJvcCwgdmFsdWUgKSApICkge1xuXG5cdFx0XHQvLyBXZSdyZSBkb25lIHdpdGggdGhpcyBwcm9wZXJ0eVxuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBkZWZhdWx0UHJlZmlsdGVyKCBlbGVtLCBwcm9wcywgb3B0cyApIHtcblx0dmFyIHByb3AsIHZhbHVlLCB0b2dnbGUsIGhvb2tzLCBvbGRmaXJlLCBwcm9wVHdlZW4sIHJlc3RvcmVEaXNwbGF5LCBkaXNwbGF5LFxuXHRcdGlzQm94ID0gXCJ3aWR0aFwiIGluIHByb3BzIHx8IFwiaGVpZ2h0XCIgaW4gcHJvcHMsXG5cdFx0YW5pbSA9IHRoaXMsXG5cdFx0b3JpZyA9IHt9LFxuXHRcdHN0eWxlID0gZWxlbS5zdHlsZSxcblx0XHRoaWRkZW4gPSBlbGVtLm5vZGVUeXBlICYmIGlzSGlkZGVuV2l0aGluVHJlZSggZWxlbSApLFxuXHRcdGRhdGFTaG93ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImZ4c2hvd1wiICk7XG5cblx0Ly8gUXVldWUtc2tpcHBpbmcgYW5pbWF0aW9ucyBoaWphY2sgdGhlIGZ4IGhvb2tzXG5cdGlmICggIW9wdHMucXVldWUgKSB7XG5cdFx0aG9va3MgPSBqUXVlcnkuX3F1ZXVlSG9va3MoIGVsZW0sIFwiZnhcIiApO1xuXHRcdGlmICggaG9va3MudW5xdWV1ZWQgPT0gbnVsbCApIHtcblx0XHRcdGhvb2tzLnVucXVldWVkID0gMDtcblx0XHRcdG9sZGZpcmUgPSBob29rcy5lbXB0eS5maXJlO1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICFob29rcy51bnF1ZXVlZCApIHtcblx0XHRcdFx0XHRvbGRmaXJlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fVxuXHRcdGhvb2tzLnVucXVldWVkKys7XG5cblx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIEVuc3VyZSB0aGUgY29tcGxldGUgaGFuZGxlciBpcyBjYWxsZWQgYmVmb3JlIHRoaXMgY29tcGxldGVzXG5cdFx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGhvb2tzLnVucXVldWVkLS07XG5cdFx0XHRcdGlmICggIWpRdWVyeS5xdWV1ZSggZWxlbSwgXCJmeFwiICkubGVuZ3RoICkge1xuXHRcdFx0XHRcdGhvb2tzLmVtcHR5LmZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIERldGVjdCBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRmb3IgKCBwcm9wIGluIHByb3BzICkge1xuXHRcdHZhbHVlID0gcHJvcHNbIHByb3AgXTtcblx0XHRpZiAoIHJmeHR5cGVzLnRlc3QoIHZhbHVlICkgKSB7XG5cdFx0XHRkZWxldGUgcHJvcHNbIHByb3AgXTtcblx0XHRcdHRvZ2dsZSA9IHRvZ2dsZSB8fCB2YWx1ZSA9PT0gXCJ0b2dnbGVcIjtcblx0XHRcdGlmICggdmFsdWUgPT09ICggaGlkZGVuID8gXCJoaWRlXCIgOiBcInNob3dcIiApICkge1xuXG5cdFx0XHRcdC8vIFByZXRlbmQgdG8gYmUgaGlkZGVuIGlmIHRoaXMgaXMgYSBcInNob3dcIiBhbmRcblx0XHRcdFx0Ly8gdGhlcmUgaXMgc3RpbGwgZGF0YSBmcm9tIGEgc3RvcHBlZCBzaG93L2hpZGVcblx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gXCJzaG93XCIgJiYgZGF0YVNob3cgJiYgZGF0YVNob3dbIHByb3AgXSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdGhpZGRlbiA9IHRydWU7XG5cblx0XHRcdFx0Ly8gSWdub3JlIGFsbCBvdGhlciBuby1vcCBzaG93L2hpZGUgZGF0YVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvcmlnWyBwcm9wIF0gPSBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdIHx8IGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIEJhaWwgb3V0IGlmIHRoaXMgaXMgYSBuby1vcCBsaWtlIC5oaWRlKCkuaGlkZSgpXG5cdHByb3BUd2VlbiA9ICFqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcHMgKTtcblx0aWYgKCAhcHJvcFR3ZWVuICYmIGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBvcmlnICkgKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Ly8gUmVzdHJpY3QgXCJvdmVyZmxvd1wiIGFuZCBcImRpc3BsYXlcIiBzdHlsZXMgZHVyaW5nIGJveCBhbmltYXRpb25zXG5cdGlmICggaXNCb3ggJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExLCBFZGdlIDEyIC0gMTNcblx0XHQvLyBSZWNvcmQgYWxsIDMgb3ZlcmZsb3cgYXR0cmlidXRlcyBiZWNhdXNlIElFIGRvZXMgbm90IGluZmVyIHRoZSBzaG9ydGhhbmRcblx0XHQvLyBmcm9tIGlkZW50aWNhbGx5LXZhbHVlZCBvdmVyZmxvd1ggYW5kIG92ZXJmbG93WVxuXHRcdG9wdHMub3ZlcmZsb3cgPSBbIHN0eWxlLm92ZXJmbG93LCBzdHlsZS5vdmVyZmxvd1gsIHN0eWxlLm92ZXJmbG93WSBdO1xuXG5cdFx0Ly8gSWRlbnRpZnkgYSBkaXNwbGF5IHR5cGUsIHByZWZlcnJpbmcgb2xkIHNob3cvaGlkZSBkYXRhIG92ZXIgdGhlIENTUyBjYXNjYWRlXG5cdFx0cmVzdG9yZURpc3BsYXkgPSBkYXRhU2hvdyAmJiBkYXRhU2hvdy5kaXNwbGF5O1xuXHRcdGlmICggcmVzdG9yZURpc3BsYXkgPT0gbnVsbCApIHtcblx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApO1xuXHRcdH1cblx0XHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKTtcblx0XHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSApIHtcblx0XHRcdFx0ZGlzcGxheSA9IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHQvLyBHZXQgbm9uZW1wdHkgdmFsdWUocykgYnkgdGVtcG9yYXJpbHkgZm9yY2luZyB2aXNpYmlsaXR5XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSwgdHJ1ZSApO1xuXHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheSB8fCByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFuaW1hdGUgaW5saW5lIGVsZW1lbnRzIGFzIGlubGluZS1ibG9ja1xuXHRcdGlmICggZGlzcGxheSA9PT0gXCJpbmxpbmVcIiB8fCBkaXNwbGF5ID09PSBcImlubGluZS1ibG9ja1wiICYmIHJlc3RvcmVEaXNwbGF5ICE9IG51bGwgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwiZmxvYXRcIiApID09PSBcIm5vbmVcIiApIHtcblxuXHRcdFx0XHQvLyBSZXN0b3JlIHRoZSBvcmlnaW5hbCBkaXNwbGF5IHZhbHVlIGF0IHRoZSBlbmQgb2YgcHVyZSBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRcdFx0XHRpZiAoICFwcm9wVHdlZW4gKSB7XG5cdFx0XHRcdFx0YW5pbS5kb25lKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0ZGlzcGxheSA9IHN0eWxlLmRpc3BsYXk7XG5cdFx0XHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGRpc3BsYXkgPT09IFwibm9uZVwiID8gXCJcIiA6IGRpc3BsYXk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggb3B0cy5vdmVyZmxvdyApIHtcblx0XHRzdHlsZS5vdmVyZmxvdyA9IFwiaGlkZGVuXCI7XG5cdFx0YW5pbS5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0c3R5bGUub3ZlcmZsb3cgPSBvcHRzLm92ZXJmbG93WyAwIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1ggPSBvcHRzLm92ZXJmbG93WyAxIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1kgPSBvcHRzLm92ZXJmbG93WyAyIF07XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50IHNob3cvaGlkZSBhbmltYXRpb25zXG5cdHByb3BUd2VlbiA9IGZhbHNlO1xuXHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cblx0XHQvLyBHZW5lcmFsIHNob3cvaGlkZSBzZXR1cCBmb3IgdGhpcyBlbGVtZW50IGFuaW1hdGlvblxuXHRcdGlmICggIXByb3BUd2VlbiApIHtcblx0XHRcdGlmICggZGF0YVNob3cgKSB7XG5cdFx0XHRcdGlmICggXCJoaWRkZW5cIiBpbiBkYXRhU2hvdyApIHtcblx0XHRcdFx0XHRoaWRkZW4gPSBkYXRhU2hvdy5oaWRkZW47XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFTaG93ID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCBcImZ4c2hvd1wiLCB7IGRpc3BsYXk6IHJlc3RvcmVEaXNwbGF5IH0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RvcmUgaGlkZGVuL3Zpc2libGUgZm9yIHRvZ2dsZSBzbyBgLnN0b3AoKS50b2dnbGUoKWAgXCJyZXZlcnNlc1wiXG5cdFx0XHRpZiAoIHRvZ2dsZSApIHtcblx0XHRcdFx0ZGF0YVNob3cuaGlkZGVuID0gIWhpZGRlbjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2hvdyBlbGVtZW50cyBiZWZvcmUgYW5pbWF0aW5nIHRoZW1cblx0XHRcdGlmICggaGlkZGVuICkge1xuXHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0sIHRydWUgKTtcblx0XHRcdH1cblxuXHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdGFuaW0uZG9uZSggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdFx0Ly8gVGhlIGZpbmFsIHN0ZXAgb2YgYSBcImhpZGVcIiBhbmltYXRpb24gaXMgYWN0dWFsbHkgaGlkaW5nIHRoZSBlbGVtZW50XG5cdFx0XHRcdGlmICggIWhpZGRlbiApIHtcblx0XHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIFwiZnhzaG93XCIgKTtcblx0XHRcdFx0Zm9yICggcHJvcCBpbiBvcmlnICkge1xuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCwgb3JpZ1sgcHJvcCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHQvLyBQZXItcHJvcGVydHkgc2V0dXBcblx0XHRwcm9wVHdlZW4gPSBjcmVhdGVUd2VlbiggaGlkZGVuID8gZGF0YVNob3dbIHByb3AgXSA6IDAsIHByb3AsIGFuaW0gKTtcblx0XHRpZiAoICEoIHByb3AgaW4gZGF0YVNob3cgKSApIHtcblx0XHRcdGRhdGFTaG93WyBwcm9wIF0gPSBwcm9wVHdlZW4uc3RhcnQ7XG5cdFx0XHRpZiAoIGhpZGRlbiApIHtcblx0XHRcdFx0cHJvcFR3ZWVuLmVuZCA9IHByb3BUd2Vlbi5zdGFydDtcblx0XHRcdFx0cHJvcFR3ZWVuLnN0YXJ0ID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJvcEZpbHRlciggcHJvcHMsIHNwZWNpYWxFYXNpbmcgKSB7XG5cdHZhciBpbmRleCwgbmFtZSwgZWFzaW5nLCB2YWx1ZSwgaG9va3M7XG5cblx0Ly8gY2FtZWxDYXNlLCBzcGVjaWFsRWFzaW5nIGFuZCBleHBhbmQgY3NzSG9vayBwYXNzXG5cdGZvciAoIGluZGV4IGluIHByb3BzICkge1xuXHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBpbmRleCApO1xuXHRcdGVhc2luZyA9IHNwZWNpYWxFYXNpbmdbIG5hbWUgXTtcblx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdO1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsdWUgKSApIHtcblx0XHRcdGVhc2luZyA9IHZhbHVlWyAxIF07XG5cdFx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdID0gdmFsdWVbIDAgXTtcblx0XHR9XG5cblx0XHRpZiAoIGluZGV4ICE9PSBuYW1lICkge1xuXHRcdFx0cHJvcHNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0ZGVsZXRlIHByb3BzWyBpbmRleCBdO1xuXHRcdH1cblxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF07XG5cdFx0aWYgKCBob29rcyAmJiBcImV4cGFuZFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsdWUgPSBob29rcy5leHBhbmQoIHZhbHVlICk7XG5cdFx0XHRkZWxldGUgcHJvcHNbIG5hbWUgXTtcblxuXHRcdFx0Ly8gTm90IHF1aXRlICQuZXh0ZW5kLCB0aGlzIHdvbid0IG92ZXJ3cml0ZSBleGlzdGluZyBrZXlzLlxuXHRcdFx0Ly8gUmV1c2luZyAnaW5kZXgnIGJlY2F1c2Ugd2UgaGF2ZSB0aGUgY29ycmVjdCBcIm5hbWVcIlxuXHRcdFx0Zm9yICggaW5kZXggaW4gdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggISggaW5kZXggaW4gcHJvcHMgKSApIHtcblx0XHRcdFx0XHRwcm9wc1sgaW5kZXggXSA9IHZhbHVlWyBpbmRleCBdO1xuXHRcdFx0XHRcdHNwZWNpYWxFYXNpbmdbIGluZGV4IF0gPSBlYXNpbmc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0c3BlY2lhbEVhc2luZ1sgbmFtZSBdID0gZWFzaW5nO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBBbmltYXRpb24oIGVsZW0sIHByb3BlcnRpZXMsIG9wdGlvbnMgKSB7XG5cdHZhciByZXN1bHQsXG5cdFx0c3RvcHBlZCxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gQW5pbWF0aW9uLnByZWZpbHRlcnMubGVuZ3RoLFxuXHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCkuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRG9uJ3QgbWF0Y2ggZWxlbSBpbiB0aGUgOmFuaW1hdGVkIHNlbGVjdG9yXG5cdFx0XHRkZWxldGUgdGljay5lbGVtO1xuXHRcdH0gKSxcblx0XHR0aWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50VGltZSA9IGZ4Tm93IHx8IGNyZWF0ZUZ4Tm93KCksXG5cdFx0XHRcdHJlbWFpbmluZyA9IE1hdGgubWF4KCAwLCBhbmltYXRpb24uc3RhcnRUaW1lICsgYW5pbWF0aW9uLmR1cmF0aW9uIC0gY3VycmVudFRpbWUgKSxcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDIuMyBvbmx5XG5cdFx0XHRcdC8vIEFyY2hhaWMgY3Jhc2ggYnVnIHdvbid0IGFsbG93IHVzIHRvIHVzZSBgMSAtICggMC41IHx8IDAgKWAgKCMxMjQ5Nylcblx0XHRcdFx0dGVtcCA9IHJlbWFpbmluZyAvIGFuaW1hdGlvbi5kdXJhdGlvbiB8fCAwLFxuXHRcdFx0XHRwZXJjZW50ID0gMSAtIHRlbXAsXG5cdFx0XHRcdGluZGV4ID0gMCxcblx0XHRcdFx0bGVuZ3RoID0gYW5pbWF0aW9uLnR3ZWVucy5sZW5ndGg7XG5cblx0XHRcdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCBwZXJjZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBwZXJjZW50LCByZW1haW5pbmcgXSApO1xuXG5cdFx0XHQvLyBJZiB0aGVyZSdzIG1vcmUgdG8gZG8sIHlpZWxkXG5cdFx0XHRpZiAoIHBlcmNlbnQgPCAxICYmIGxlbmd0aCApIHtcblx0XHRcdFx0cmV0dXJuIHJlbWFpbmluZztcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgdGhpcyB3YXMgYW4gZW1wdHkgYW5pbWF0aW9uLCBzeW50aGVzaXplIGEgZmluYWwgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uXG5cdFx0XHRpZiAoICFsZW5ndGggKSB7XG5cdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCAxLCAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVzb2x2ZSB0aGUgYW5pbWF0aW9uIGFuZCByZXBvcnQgaXRzIGNvbmNsdXNpb25cblx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiBdICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSxcblx0XHRhbmltYXRpb24gPSBkZWZlcnJlZC5wcm9taXNlKCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0cHJvcHM6IGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wZXJ0aWVzICksXG5cdFx0XHRvcHRzOiBqUXVlcnkuZXh0ZW5kKCB0cnVlLCB7XG5cdFx0XHRcdHNwZWNpYWxFYXNpbmc6IHt9LFxuXHRcdFx0XHRlYXNpbmc6IGpRdWVyeS5lYXNpbmcuX2RlZmF1bHRcblx0XHRcdH0sIG9wdGlvbnMgKSxcblx0XHRcdG9yaWdpbmFsUHJvcGVydGllczogcHJvcGVydGllcyxcblx0XHRcdG9yaWdpbmFsT3B0aW9uczogb3B0aW9ucyxcblx0XHRcdHN0YXJ0VGltZTogZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuXHRcdFx0dHdlZW5zOiBbXSxcblx0XHRcdGNyZWF0ZVR3ZWVuOiBmdW5jdGlvbiggcHJvcCwgZW5kICkge1xuXHRcdFx0XHR2YXIgdHdlZW4gPSBqUXVlcnkuVHdlZW4oIGVsZW0sIGFuaW1hdGlvbi5vcHRzLCBwcm9wLCBlbmQsXG5cdFx0XHRcdFx0XHRhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nWyBwcm9wIF0gfHwgYW5pbWF0aW9uLm9wdHMuZWFzaW5nICk7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnMucHVzaCggdHdlZW4gKTtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdFx0fSxcblx0XHRcdHN0b3A6IGZ1bmN0aW9uKCBnb3RvRW5kICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwLFxuXG5cdFx0XHRcdFx0Ly8gSWYgd2UgYXJlIGdvaW5nIHRvIHRoZSBlbmQsIHdlIHdhbnQgdG8gcnVuIGFsbCB0aGUgdHdlZW5zXG5cdFx0XHRcdFx0Ly8gb3RoZXJ3aXNlIHdlIHNraXAgdGhpcyBwYXJ0XG5cdFx0XHRcdFx0bGVuZ3RoID0gZ290b0VuZCA/IGFuaW1hdGlvbi50d2VlbnMubGVuZ3RoIDogMDtcblx0XHRcdFx0aWYgKCBzdG9wcGVkICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCAxICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZXNvbHZlIHdoZW4gd2UgcGxheWVkIHRoZSBsYXN0IGZyYW1lOyBvdGhlcndpc2UsIHJlamVjdFxuXHRcdFx0XHRpZiAoIGdvdG9FbmQgKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIDEsIDAgXSApO1xuXHRcdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgZ290b0VuZCBdICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIGdvdG9FbmQgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH0gKSxcblx0XHRwcm9wcyA9IGFuaW1hdGlvbi5wcm9wcztcblxuXHRwcm9wRmlsdGVyKCBwcm9wcywgYW5pbWF0aW9uLm9wdHMuc3BlY2lhbEVhc2luZyApO1xuXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0cmVzdWx0ID0gQW5pbWF0aW9uLnByZWZpbHRlcnNbIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBlbGVtLCBwcm9wcywgYW5pbWF0aW9uLm9wdHMgKTtcblx0XHRpZiAoIHJlc3VsdCApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHJlc3VsdC5zdG9wICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggYW5pbWF0aW9uLmVsZW0sIGFuaW1hdGlvbi5vcHRzLnF1ZXVlICkuc3RvcCA9XG5cdFx0XHRcdFx0alF1ZXJ5LnByb3h5KCByZXN1bHQuc3RvcCwgcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblx0fVxuXG5cdGpRdWVyeS5tYXAoIHByb3BzLCBjcmVhdGVUd2VlbiwgYW5pbWF0aW9uICk7XG5cblx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYW5pbWF0aW9uLm9wdHMuc3RhcnQgKSApIHtcblx0XHRhbmltYXRpb24ub3B0cy5zdGFydC5jYWxsKCBlbGVtLCBhbmltYXRpb24gKTtcblx0fVxuXG5cdC8vIEF0dGFjaCBjYWxsYmFja3MgZnJvbSBvcHRpb25zXG5cdGFuaW1hdGlvblxuXHRcdC5wcm9ncmVzcyggYW5pbWF0aW9uLm9wdHMucHJvZ3Jlc3MgKVxuXHRcdC5kb25lKCBhbmltYXRpb24ub3B0cy5kb25lLCBhbmltYXRpb24ub3B0cy5jb21wbGV0ZSApXG5cdFx0LmZhaWwoIGFuaW1hdGlvbi5vcHRzLmZhaWwgKVxuXHRcdC5hbHdheXMoIGFuaW1hdGlvbi5vcHRzLmFsd2F5cyApO1xuXG5cdGpRdWVyeS5meC50aW1lcihcblx0XHRqUXVlcnkuZXh0ZW5kKCB0aWNrLCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0YW5pbTogYW5pbWF0aW9uLFxuXHRcdFx0cXVldWU6IGFuaW1hdGlvbi5vcHRzLnF1ZXVlXG5cdFx0fSApXG5cdCk7XG5cblx0cmV0dXJuIGFuaW1hdGlvbjtcbn1cblxualF1ZXJ5LkFuaW1hdGlvbiA9IGpRdWVyeS5leHRlbmQoIEFuaW1hdGlvbiwge1xuXG5cdHR3ZWVuZXJzOiB7XG5cdFx0XCIqXCI6IFsgZnVuY3Rpb24oIHByb3AsIHZhbHVlICkge1xuXHRcdFx0dmFyIHR3ZWVuID0gdGhpcy5jcmVhdGVUd2VlbiggcHJvcCwgdmFsdWUgKTtcblx0XHRcdGFkanVzdENTUyggdHdlZW4uZWxlbSwgcHJvcCwgcmNzc051bS5leGVjKCB2YWx1ZSApLCB0d2VlbiApO1xuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH0gXVxuXHR9LFxuXG5cdHR3ZWVuZXI6IGZ1bmN0aW9uKCBwcm9wcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcHJvcHMgKSApIHtcblx0XHRcdGNhbGxiYWNrID0gcHJvcHM7XG5cdFx0XHRwcm9wcyA9IFsgXCIqXCIgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvcHMgPSBwcm9wcy5tYXRjaCggcm5vdGh0bWx3aGl0ZSApO1xuXHRcdH1cblxuXHRcdHZhciBwcm9wLFxuXHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0bGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdHByb3AgPSBwcm9wc1sgaW5kZXggXTtcblx0XHRcdEFuaW1hdGlvbi50d2VlbmVyc1sgcHJvcCBdID0gQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW107XG5cdFx0XHRBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXS51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH1cblx0fSxcblxuXHRwcmVmaWx0ZXJzOiBbIGRlZmF1bHRQcmVmaWx0ZXIgXSxcblxuXHRwcmVmaWx0ZXI6IGZ1bmN0aW9uKCBjYWxsYmFjaywgcHJlcGVuZCApIHtcblx0XHRpZiAoIHByZXBlbmQgKSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy5wdXNoKCBjYWxsYmFjayApO1xuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuc3BlZWQgPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgZm4gKSB7XG5cdHZhciBvcHQgPSBzcGVlZCAmJiB0eXBlb2Ygc3BlZWQgPT09IFwib2JqZWN0XCIgPyBqUXVlcnkuZXh0ZW5kKCB7fSwgc3BlZWQgKSA6IHtcblx0XHRjb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fFxuXHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHNwZWVkICkgJiYgc3BlZWQsXG5cdFx0ZHVyYXRpb246IHNwZWVkLFxuXHRcdGVhc2luZzogZm4gJiYgZWFzaW5nIHx8IGVhc2luZyAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIGVhc2luZyApICYmIGVhc2luZ1xuXHR9O1xuXG5cdC8vIEdvIHRvIHRoZSBlbmQgc3RhdGUgaWYgZnggYXJlIG9mZlxuXHRpZiAoIGpRdWVyeS5meC5vZmYgKSB7XG5cdFx0b3B0LmR1cmF0aW9uID0gMDtcblxuXHR9IGVsc2Uge1xuXHRcdGlmICggdHlwZW9mIG9wdC5kdXJhdGlvbiAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdGlmICggb3B0LmR1cmF0aW9uIGluIGpRdWVyeS5meC5zcGVlZHMgKSB7XG5cdFx0XHRcdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5zcGVlZHNbIG9wdC5kdXJhdGlvbiBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvcHQuZHVyYXRpb24gPSBqUXVlcnkuZnguc3BlZWRzLl9kZWZhdWx0O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBvcHQucXVldWUgLSB0cnVlL3VuZGVmaW5lZC9udWxsIC0+IFwiZnhcIlxuXHRpZiAoIG9wdC5xdWV1ZSA9PSBudWxsIHx8IG9wdC5xdWV1ZSA9PT0gdHJ1ZSApIHtcblx0XHRvcHQucXVldWUgPSBcImZ4XCI7XG5cdH1cblxuXHQvLyBRdWV1ZWluZ1xuXHRvcHQub2xkID0gb3B0LmNvbXBsZXRlO1xuXG5cdG9wdC5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIG9wdC5vbGQgKSApIHtcblx0XHRcdG9wdC5vbGQuY2FsbCggdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0LnF1ZXVlICkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIG9wdC5xdWV1ZSApO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gb3B0O1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmYWRlVG86IGZ1bmN0aW9uKCBzcGVlZCwgdG8sIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cblx0XHQvLyBTaG93IGFueSBoaWRkZW4gZWxlbWVudHMgYWZ0ZXIgc2V0dGluZyBvcGFjaXR5IHRvIDBcblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGlzSGlkZGVuV2l0aGluVHJlZSApLmNzcyggXCJvcGFjaXR5XCIsIDAgKS5zaG93KClcblxuXHRcdFx0Ly8gQW5pbWF0ZSB0byB0aGUgdmFsdWUgc3BlY2lmaWVkXG5cdFx0XHQuZW5kKCkuYW5pbWF0ZSggeyBvcGFjaXR5OiB0byB9LCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9LFxuXHRhbmltYXRlOiBmdW5jdGlvbiggcHJvcCwgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0dmFyIGVtcHR5ID0galF1ZXJ5LmlzRW1wdHlPYmplY3QoIHByb3AgKSxcblx0XHRcdG9wdGFsbCA9IGpRdWVyeS5zcGVlZCggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSxcblx0XHRcdGRvQW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0Ly8gT3BlcmF0ZSBvbiBhIGNvcHkgb2YgcHJvcCBzbyBwZXItcHJvcGVydHkgZWFzaW5nIHdvbid0IGJlIGxvc3Rcblx0XHRcdFx0dmFyIGFuaW0gPSBBbmltYXRpb24oIHRoaXMsIGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wICksIG9wdGFsbCApO1xuXG5cdFx0XHRcdC8vIEVtcHR5IGFuaW1hdGlvbnMsIG9yIGZpbmlzaGluZyByZXNvbHZlcyBpbW1lZGlhdGVseVxuXHRcdFx0XHRpZiAoIGVtcHR5IHx8IGRhdGFQcml2LmdldCggdGhpcywgXCJmaW5pc2hcIiApICkge1xuXHRcdFx0XHRcdGFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0ZG9BbmltYXRpb24uZmluaXNoID0gZG9BbmltYXRpb247XG5cblx0XHRyZXR1cm4gZW1wdHkgfHwgb3B0YWxsLnF1ZXVlID09PSBmYWxzZSA/XG5cdFx0XHR0aGlzLmVhY2goIGRvQW5pbWF0aW9uICkgOlxuXHRcdFx0dGhpcy5xdWV1ZSggb3B0YWxsLnF1ZXVlLCBkb0FuaW1hdGlvbiApO1xuXHR9LFxuXHRzdG9wOiBmdW5jdGlvbiggdHlwZSwgY2xlYXJRdWV1ZSwgZ290b0VuZCApIHtcblx0XHR2YXIgc3RvcFF1ZXVlID0gZnVuY3Rpb24oIGhvb2tzICkge1xuXHRcdFx0dmFyIHN0b3AgPSBob29rcy5zdG9wO1xuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRzdG9wKCBnb3RvRW5kICk7XG5cdFx0fTtcblxuXHRcdGlmICggdHlwZW9mIHR5cGUgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRnb3RvRW5kID0gY2xlYXJRdWV1ZTtcblx0XHRcdGNsZWFyUXVldWUgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKCBjbGVhclF1ZXVlICYmIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dGhpcy5xdWV1ZSggdHlwZSB8fCBcImZ4XCIsIFtdICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgZGVxdWV1ZSA9IHRydWUsXG5cdFx0XHRcdGluZGV4ID0gdHlwZSAhPSBudWxsICYmIHR5cGUgKyBcInF1ZXVlSG9va3NcIixcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApO1xuXG5cdFx0XHRpZiAoIGluZGV4ICkge1xuXHRcdFx0XHRpZiAoIGRhdGFbIGluZGV4IF0gJiYgZGF0YVsgaW5kZXggXS5zdG9wICkge1xuXHRcdFx0XHRcdHN0b3BRdWV1ZSggZGF0YVsgaW5kZXggXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCBpbmRleCBpbiBkYXRhICkge1xuXHRcdFx0XHRcdGlmICggZGF0YVsgaW5kZXggXSAmJiBkYXRhWyBpbmRleCBdLnN0b3AgJiYgcnJ1bi50ZXN0KCBpbmRleCApICkge1xuXHRcdFx0XHRcdFx0c3RvcFF1ZXVlKCBkYXRhWyBpbmRleCBdICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGluZGV4ID0gdGltZXJzLmxlbmd0aDsgaW5kZXgtLTsgKSB7XG5cdFx0XHRcdGlmICggdGltZXJzWyBpbmRleCBdLmVsZW0gPT09IHRoaXMgJiZcblx0XHRcdFx0XHQoIHR5cGUgPT0gbnVsbCB8fCB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSApIHtcblxuXHRcdFx0XHRcdHRpbWVyc1sgaW5kZXggXS5hbmltLnN0b3AoIGdvdG9FbmQgKTtcblx0XHRcdFx0XHRkZXF1ZXVlID0gZmFsc2U7XG5cdFx0XHRcdFx0dGltZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFydCB0aGUgbmV4dCBpbiB0aGUgcXVldWUgaWYgdGhlIGxhc3Qgc3RlcCB3YXNuJ3QgZm9yY2VkLlxuXHRcdFx0Ly8gVGltZXJzIGN1cnJlbnRseSB3aWxsIGNhbGwgdGhlaXIgY29tcGxldGUgY2FsbGJhY2tzLCB3aGljaFxuXHRcdFx0Ly8gd2lsbCBkZXF1ZXVlIGJ1dCBvbmx5IGlmIHRoZXkgd2VyZSBnb3RvRW5kLlxuXHRcdFx0aWYgKCBkZXF1ZXVlIHx8ICFnb3RvRW5kICkge1xuXHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblx0ZmluaXNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRpZiAoIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpbmRleCxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApLFxuXHRcdFx0XHRxdWV1ZSA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlXCIgXSxcblx0XHRcdFx0aG9va3MgPSBkYXRhWyB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgXSxcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0bGVuZ3RoID0gcXVldWUgPyBxdWV1ZS5sZW5ndGggOiAwO1xuXG5cdFx0XHQvLyBFbmFibGUgZmluaXNoaW5nIGZsYWcgb24gcHJpdmF0ZSBkYXRhXG5cdFx0XHRkYXRhLmZpbmlzaCA9IHRydWU7XG5cblx0XHRcdC8vIEVtcHR5IHRoZSBxdWV1ZSBmaXJzdFxuXHRcdFx0alF1ZXJ5LnF1ZXVlKCB0aGlzLCB0eXBlLCBbXSApO1xuXG5cdFx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnN0b3AgKSB7XG5cdFx0XHRcdGhvb2tzLnN0b3AuY2FsbCggdGhpcywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYWN0aXZlIGFuaW1hdGlvbnMsIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJiB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSB7XG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTG9vayBmb3IgYW55IGFuaW1hdGlvbnMgaW4gdGhlIG9sZCBxdWV1ZSBhbmQgZmluaXNoIHRoZW1cblx0XHRcdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGlmICggcXVldWVbIGluZGV4IF0gJiYgcXVldWVbIGluZGV4IF0uZmluaXNoICkge1xuXHRcdFx0XHRcdHF1ZXVlWyBpbmRleCBdLmZpbmlzaC5jYWxsKCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVHVybiBvZmYgZmluaXNoaW5nIGZsYWdcblx0XHRcdGRlbGV0ZSBkYXRhLmZpbmlzaDtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmVhY2goIFsgXCJ0b2dnbGVcIiwgXCJzaG93XCIsIFwiaGlkZVwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgY3NzRm4gPSBqUXVlcnkuZm5bIG5hbWUgXTtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHNwZWVkID09IG51bGwgfHwgdHlwZW9mIHNwZWVkID09PSBcImJvb2xlYW5cIiA/XG5cdFx0XHRjc3NGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOlxuXHRcdFx0dGhpcy5hbmltYXRlKCBnZW5GeCggbmFtZSwgdHJ1ZSApLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG4vLyBHZW5lcmF0ZSBzaG9ydGN1dHMgZm9yIGN1c3RvbSBhbmltYXRpb25zXG5qUXVlcnkuZWFjaCgge1xuXHRzbGlkZURvd246IGdlbkZ4KCBcInNob3dcIiApLFxuXHRzbGlkZVVwOiBnZW5GeCggXCJoaWRlXCIgKSxcblx0c2xpZGVUb2dnbGU6IGdlbkZ4KCBcInRvZ2dsZVwiICksXG5cdGZhZGVJbjogeyBvcGFjaXR5OiBcInNob3dcIiB9LFxuXHRmYWRlT3V0OiB7IG9wYWNpdHk6IFwiaGlkZVwiIH0sXG5cdGZhZGVUb2dnbGU6IHsgb3BhY2l0eTogXCJ0b2dnbGVcIiB9XG59LCBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLmFuaW1hdGUoIHByb3BzLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG5qUXVlcnkudGltZXJzID0gW107XG5qUXVlcnkuZngudGljayA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgdGltZXIsXG5cdFx0aSA9IDAsXG5cdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycztcblxuXHRmeE5vdyA9IGpRdWVyeS5ub3coKTtcblxuXHRmb3IgKCA7IGkgPCB0aW1lcnMubGVuZ3RoOyBpKysgKSB7XG5cdFx0dGltZXIgPSB0aW1lcnNbIGkgXTtcblxuXHRcdC8vIFJ1biB0aGUgdGltZXIgYW5kIHNhZmVseSByZW1vdmUgaXQgd2hlbiBkb25lIChhbGxvd2luZyBmb3IgZXh0ZXJuYWwgcmVtb3ZhbClcblx0XHRpZiAoICF0aW1lcigpICYmIHRpbWVyc1sgaSBdID09PSB0aW1lciApIHtcblx0XHRcdHRpbWVycy5zcGxpY2UoIGktLSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIXRpbWVycy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0b3AoKTtcblx0fVxuXHRmeE5vdyA9IHVuZGVmaW5lZDtcbn07XG5cbmpRdWVyeS5meC50aW1lciA9IGZ1bmN0aW9uKCB0aW1lciApIHtcblx0alF1ZXJ5LnRpbWVycy5wdXNoKCB0aW1lciApO1xuXHRqUXVlcnkuZnguc3RhcnQoKTtcbn07XG5cbmpRdWVyeS5meC5pbnRlcnZhbCA9IDEzO1xualF1ZXJ5LmZ4LnN0YXJ0ID0gZnVuY3Rpb24oKSB7XG5cdGlmICggaW5Qcm9ncmVzcyApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpblByb2dyZXNzID0gdHJ1ZTtcblx0c2NoZWR1bGUoKTtcbn07XG5cbmpRdWVyeS5meC5zdG9wID0gZnVuY3Rpb24oKSB7XG5cdGluUHJvZ3Jlc3MgPSBudWxsO1xufTtcblxualF1ZXJ5LmZ4LnNwZWVkcyA9IHtcblx0c2xvdzogNjAwLFxuXHRmYXN0OiAyMDAsXG5cblx0Ly8gRGVmYXVsdCBzcGVlZFxuXHRfZGVmYXVsdDogNDAwXG59O1xuXG5cbi8vIEJhc2VkIG9mZiBvZiB0aGUgcGx1Z2luIGJ5IENsaW50IEhlbGZlcnMsIHdpdGggcGVybWlzc2lvbi5cbi8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDEwMDMyNDAxNDc0Ny9odHRwOi8vYmxpbmRzaWduYWxzLmNvbS9pbmRleC5waHAvMjAwOS8wNy9qcXVlcnktZGVsYXkvXG5qUXVlcnkuZm4uZGVsYXkgPSBmdW5jdGlvbiggdGltZSwgdHlwZSApIHtcblx0dGltZSA9IGpRdWVyeS5meCA/IGpRdWVyeS5meC5zcGVlZHNbIHRpbWUgXSB8fCB0aW1lIDogdGltZTtcblx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlLCBmdW5jdGlvbiggbmV4dCwgaG9va3MgKSB7XG5cdFx0dmFyIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCggbmV4dCwgdGltZSApO1xuXHRcdGhvb2tzLnN0b3AgPSBmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5jbGVhclRpbWVvdXQoIHRpbWVvdXQgKTtcblx0XHR9O1xuXHR9ICk7XG59O1xuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApLFxuXHRcdHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwic2VsZWN0XCIgKSxcblx0XHRvcHQgPSBzZWxlY3QuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwib3B0aW9uXCIgKSApO1xuXG5cdGlucHV0LnR5cGUgPSBcImNoZWNrYm94XCI7XG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMyBvbmx5XG5cdC8vIERlZmF1bHQgdmFsdWUgZm9yIGEgY2hlY2tib3ggc2hvdWxkIGJlIFwib25cIlxuXHRzdXBwb3J0LmNoZWNrT24gPSBpbnB1dC52YWx1ZSAhPT0gXCJcIjtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTXVzdCBhY2Nlc3Mgc2VsZWN0ZWRJbmRleCB0byBtYWtlIGRlZmF1bHQgb3B0aW9ucyBzZWxlY3Rcblx0c3VwcG9ydC5vcHRTZWxlY3RlZCA9IG9wdC5zZWxlY3RlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gQW4gaW5wdXQgbG9zZXMgaXRzIHZhbHVlIGFmdGVyIGJlY29taW5nIGEgcmFkaW9cblx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblx0aW5wdXQudmFsdWUgPSBcInRcIjtcblx0aW5wdXQudHlwZSA9IFwicmFkaW9cIjtcblx0c3VwcG9ydC5yYWRpb1ZhbHVlID0gaW5wdXQudmFsdWUgPT09IFwidFwiO1xufSApKCk7XG5cblxudmFyIGJvb2xIb29rLFxuXHRhdHRySGFuZGxlID0galF1ZXJ5LmV4cHIuYXR0ckhhbmRsZTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgalF1ZXJ5LmF0dHIsIG5hbWUsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoID4gMSApO1xuXHR9LFxuXG5cdHJlbW92ZUF0dHI6IGZ1bmN0aW9uKCBuYW1lICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIHRoaXMsIG5hbWUgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBEb24ndCBnZXQvc2V0IGF0dHJpYnV0ZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBGYWxsYmFjayB0byBwcm9wIHdoZW4gYXR0cmlidXRlcyBhcmUgbm90IHN1cHBvcnRlZFxuXHRcdGlmICggdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlID09PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5wcm9wKCBlbGVtLCBuYW1lLCB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdC8vIEF0dHJpYnV0ZSBob29rcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgbG93ZXJjYXNlIHZlcnNpb25cblx0XHQvLyBHcmFiIG5lY2Vzc2FyeSBob29rIGlmIG9uZSBpcyBkZWZpbmVkXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5hdHRySG9va3NbIG5hbWUudG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdCggalF1ZXJ5LmV4cHIubWF0Y2guYm9vbC50ZXN0KCBuYW1lICkgPyBib29sSG9vayA6IHVuZGVmaW5lZCApO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGlmICggdmFsdWUgPT09IG51bGwgKSB7XG5cdFx0XHRcdGpRdWVyeS5yZW1vdmVBdHRyKCBlbGVtLCBuYW1lICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBob29rcyAmJiBcInNldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3Muc2V0KCBlbGVtLCB2YWx1ZSwgbmFtZSApICkgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIG5hbWUsIHZhbHVlICsgXCJcIiApO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdC8vIE5vbi1leGlzdGVudCBhdHRyaWJ1dGVzIHJldHVybiBudWxsLCB3ZSBub3JtYWxpemUgdG8gdW5kZWZpbmVkXG5cdFx0cmV0dXJuIHJldCA9PSBudWxsID8gdW5kZWZpbmVkIDogcmV0O1xuXHR9LFxuXG5cdGF0dHJIb29rczoge1xuXHRcdHR5cGU6IHtcblx0XHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0XHRpZiAoICFzdXBwb3J0LnJhZGlvVmFsdWUgJiYgdmFsdWUgPT09IFwicmFkaW9cIiAmJlxuXHRcdFx0XHRcdG5vZGVOYW1lKCBlbGVtLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsID0gZWxlbS52YWx1ZTtcblx0XHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLnZhbHVlID0gdmFsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cmVtb3ZlQXR0cjogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdHZhciBuYW1lLFxuXHRcdFx0aSA9IDAsXG5cblx0XHRcdC8vIEF0dHJpYnV0ZSBuYW1lcyBjYW4gY29udGFpbiBub24tSFRNTCB3aGl0ZXNwYWNlIGNoYXJhY3RlcnNcblx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3N5bnRheC5odG1sI2F0dHJpYnV0ZXMtMlxuXHRcdFx0YXR0ck5hbWVzID0gdmFsdWUgJiYgdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKTtcblxuXHRcdGlmICggYXR0ck5hbWVzICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHR3aGlsZSAoICggbmFtZSA9IGF0dHJOYW1lc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIG5hbWUgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSG9va3MgZm9yIGJvb2xlYW4gYXR0cmlidXRlc1xuYm9vbEhvb2sgPSB7XG5cdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBuYW1lICkge1xuXHRcdGlmICggdmFsdWUgPT09IGZhbHNlICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgYm9vbGVhbiBhdHRyaWJ1dGVzIHdoZW4gc2V0IHRvIGZhbHNlXG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggZWxlbSwgbmFtZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgbmFtZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxufTtcblxualF1ZXJ5LmVhY2goIGpRdWVyeS5leHByLm1hdGNoLmJvb2wuc291cmNlLm1hdGNoKCAvXFx3Ky9nICksIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgZ2V0dGVyID0gYXR0ckhhbmRsZVsgbmFtZSBdIHx8IGpRdWVyeS5maW5kLmF0dHI7XG5cblx0YXR0ckhhbmRsZVsgbmFtZSBdID0gZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciByZXQsIGhhbmRsZSxcblx0XHRcdGxvd2VyY2FzZU5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAoICFpc1hNTCApIHtcblxuXHRcdFx0Ly8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcCBieSB0ZW1wb3JhcmlseSByZW1vdmluZyB0aGlzIGZ1bmN0aW9uIGZyb20gdGhlIGdldHRlclxuXHRcdFx0aGFuZGxlID0gYXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdO1xuXHRcdFx0YXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdID0gcmV0O1xuXHRcdFx0cmV0ID0gZ2V0dGVyKCBlbGVtLCBuYW1lLCBpc1hNTCApICE9IG51bGwgP1xuXHRcdFx0XHRsb3dlcmNhc2VOYW1lIDpcblx0XHRcdFx0bnVsbDtcblx0XHRcdGF0dHJIYW5kbGVbIGxvd2VyY2FzZU5hbWUgXSA9IGhhbmRsZTtcblx0XHR9XG5cdFx0cmV0dXJuIHJldDtcblx0fTtcbn0gKTtcblxuXG5cblxudmFyIHJmb2N1c2FibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFxuXHRyY2xpY2thYmxlID0gL14oPzphfGFyZWEpJC9pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHByb3A6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBqUXVlcnkucHJvcCwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH0sXG5cblx0cmVtb3ZlUHJvcDogZnVuY3Rpb24oIG5hbWUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRkZWxldGUgdGhpc1sgalF1ZXJ5LnByb3BGaXhbIG5hbWUgXSB8fCBuYW1lIF07XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0cHJvcDogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdHZhciByZXQsIGhvb2tzLFxuXHRcdFx0blR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuXG5cdFx0Ly8gRG9uJ3QgZ2V0L3NldCBwcm9wZXJ0aWVzIG9uIHRleHQsIGNvbW1lbnQgYW5kIGF0dHJpYnV0ZSBub2Rlc1xuXHRcdGlmICggblR5cGUgPT09IDMgfHwgblR5cGUgPT09IDggfHwgblR5cGUgPT09IDIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cblx0XHRcdC8vIEZpeCBuYW1lIGFuZCBhdHRhY2ggaG9va3Ncblx0XHRcdG5hbWUgPSBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWU7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5wcm9wSG9va3NbIG5hbWUgXTtcblx0XHR9XG5cblx0XHRpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIGhvb2tzICYmIFwic2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gKCBlbGVtWyBuYW1lIF0gPSB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldHVybiBlbGVtWyBuYW1lIF07XG5cdH0sXG5cblx0cHJvcEhvb2tzOiB7XG5cdFx0dGFiSW5kZXg6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHRcdFx0XHQvLyBlbGVtLnRhYkluZGV4IGRvZXNuJ3QgYWx3YXlzIHJldHVybiB0aGVcblx0XHRcdFx0Ly8gY29ycmVjdCB2YWx1ZSB3aGVuIGl0IGhhc24ndCBiZWVuIGV4cGxpY2l0bHkgc2V0XG5cdFx0XHRcdC8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDE0MTExNjIzMzM0Ny9odHRwOi8vZmx1aWRwcm9qZWN0Lm9yZy9ibG9nLzIwMDgvMDEvMDkvZ2V0dGluZy1zZXR0aW5nLWFuZC1yZW1vdmluZy10YWJpbmRleC12YWx1ZXMtd2l0aC1qYXZhc2NyaXB0L1xuXHRcdFx0XHQvLyBVc2UgcHJvcGVyIGF0dHJpYnV0ZSByZXRyaWV2YWwoIzEyMDcyKVxuXHRcdFx0XHR2YXIgdGFiaW5kZXggPSBqUXVlcnkuZmluZC5hdHRyKCBlbGVtLCBcInRhYmluZGV4XCIgKTtcblxuXHRcdFx0XHRpZiAoIHRhYmluZGV4ICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXJzZUludCggdGFiaW5kZXgsIDEwICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0cmZvY3VzYWJsZS50ZXN0KCBlbGVtLm5vZGVOYW1lICkgfHxcblx0XHRcdFx0XHRyY2xpY2thYmxlLnRlc3QoIGVsZW0ubm9kZU5hbWUgKSAmJlxuXHRcdFx0XHRcdGVsZW0uaHJlZlxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cHJvcEZpeDoge1xuXHRcdFwiZm9yXCI6IFwiaHRtbEZvclwiLFxuXHRcdFwiY2xhc3NcIjogXCJjbGFzc05hbWVcIlxuXHR9XG59ICk7XG5cbi8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuLy8gQWNjZXNzaW5nIHRoZSBzZWxlY3RlZEluZGV4IHByb3BlcnR5XG4vLyBmb3JjZXMgdGhlIGJyb3dzZXIgdG8gcmVzcGVjdCBzZXR0aW5nIHNlbGVjdGVkXG4vLyBvbiB0aGUgb3B0aW9uXG4vLyBUaGUgZ2V0dGVyIGVuc3VyZXMgYSBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZFxuLy8gd2hlbiBpbiBhbiBvcHRncm91cFxuLy8gZXNsaW50IHJ1bGUgXCJuby11bnVzZWQtZXhwcmVzc2lvbnNcIiBpcyBkaXNhYmxlZCBmb3IgdGhpcyBjb2RlXG4vLyBzaW5jZSBpdCBjb25zaWRlcnMgc3VjaCBhY2Nlc3Npb25zIG5vb3BcbmlmICggIXN1cHBvcnQub3B0U2VsZWN0ZWQgKSB7XG5cdGpRdWVyeS5wcm9wSG9va3Muc2VsZWN0ZWQgPSB7XG5cdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0LyogZXNsaW50IG5vLXVudXNlZC1leHByZXNzaW9uczogXCJvZmZcIiAqL1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgJiYgcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9LFxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdC8qIGVzbGludCBuby11bnVzZWQtZXhwcmVzc2lvbnM6IFwib2ZmXCIgKi9cblxuXHRcdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRcdGlmICggcGFyZW50ICkge1xuXHRcdFx0XHRwYXJlbnQuc2VsZWN0ZWRJbmRleDtcblxuXHRcdFx0XHRpZiAoIHBhcmVudC5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbmpRdWVyeS5lYWNoKCBbXG5cdFwidGFiSW5kZXhcIixcblx0XCJyZWFkT25seVwiLFxuXHRcIm1heExlbmd0aFwiLFxuXHRcImNlbGxTcGFjaW5nXCIsXG5cdFwiY2VsbFBhZGRpbmdcIixcblx0XCJyb3dTcGFuXCIsXG5cdFwiY29sU3BhblwiLFxuXHRcInVzZU1hcFwiLFxuXHRcImZyYW1lQm9yZGVyXCIsXG5cdFwiY29udGVudEVkaXRhYmxlXCJcbl0sIGZ1bmN0aW9uKCkge1xuXHRqUXVlcnkucHJvcEZpeFsgdGhpcy50b0xvd2VyQ2FzZSgpIF0gPSB0aGlzO1xufSApO1xuXG5cblxuXG5cdC8vIFN0cmlwIGFuZCBjb2xsYXBzZSB3aGl0ZXNwYWNlIGFjY29yZGluZyB0byBIVE1MIHNwZWNcblx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvaW5mcmFzdHJ1Y3R1cmUuaHRtbCNzdHJpcC1hbmQtY29sbGFwc2Utd2hpdGVzcGFjZVxuXHRmdW5jdGlvbiBzdHJpcEFuZENvbGxhcHNlKCB2YWx1ZSApIHtcblx0XHR2YXIgdG9rZW5zID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblx0XHRyZXR1cm4gdG9rZW5zLmpvaW4oIFwiIFwiICk7XG5cdH1cblxuXG5mdW5jdGlvbiBnZXRDbGFzcyggZWxlbSApIHtcblx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlICYmIGVsZW0uZ2V0QXR0cmlidXRlKCBcImNsYXNzXCIgKSB8fCBcIlwiO1xufVxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGFkZENsYXNzOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGNsYXNzZXMsIGVsZW0sIGN1ciwgY3VyVmFsdWUsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmFkZENsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCBnZXRDbGFzcyggdGhpcyApICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZSApIHtcblx0XHRcdGNsYXNzZXMgPSB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRoaXNbIGkrKyBdICkgKSB7XG5cdFx0XHRcdGN1clZhbHVlID0gZ2V0Q2xhc3MoIGVsZW0gKTtcblx0XHRcdFx0Y3VyID0gZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAoIFwiIFwiICsgc3RyaXBBbmRDb2xsYXBzZSggY3VyVmFsdWUgKSArIFwiIFwiICk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGNsYXp6ID0gY2xhc3Nlc1sgaisrIF0gKSApIHtcblx0XHRcdFx0XHRcdGlmICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApIDwgMCApIHtcblx0XHRcdFx0XHRcdFx0Y3VyICs9IGNsYXp6ICsgXCIgXCI7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVDbGFzczogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBjbGFzc2VzLCBlbGVtLCBjdXIsIGN1clZhbHVlLCBjbGF6eiwgaiwgZmluYWxWYWx1ZSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBqICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZW1vdmVDbGFzcyggdmFsdWUuY2FsbCggdGhpcywgaiwgZ2V0Q2xhc3MoIHRoaXMgKSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiB0aGlzLmF0dHIoIFwiY2xhc3NcIiwgXCJcIiApO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlICkge1xuXHRcdFx0Y2xhc3NlcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdHdoaWxlICggKCBlbGVtID0gdGhpc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0Y3VyVmFsdWUgPSBnZXRDbGFzcyggZWxlbSApO1xuXG5cdFx0XHRcdC8vIFRoaXMgZXhwcmVzc2lvbiBpcyBoZXJlIGZvciBiZXR0ZXIgY29tcHJlc3NpYmlsaXR5IChzZWUgYWRkQ2xhc3MpXG5cdFx0XHRcdGN1ciA9IGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgKCBcIiBcIiArIHN0cmlwQW5kQ29sbGFwc2UoIGN1clZhbHVlICkgKyBcIiBcIiApO1xuXG5cdFx0XHRcdGlmICggY3VyICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKCBjbGF6eiA9IGNsYXNzZXNbIGorKyBdICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIFJlbW92ZSAqYWxsKiBpbnN0YW5jZXNcblx0XHRcdFx0XHRcdHdoaWxlICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApID4gLTEgKSB7XG5cdFx0XHRcdFx0XHRcdGN1ciA9IGN1ci5yZXBsYWNlKCBcIiBcIiArIGNsYXp6ICsgXCIgXCIsIFwiIFwiICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR0b2dnbGVDbGFzczogZnVuY3Rpb24oIHZhbHVlLCBzdGF0ZVZhbCApIHtcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdGlmICggdHlwZW9mIHN0YXRlVmFsID09PSBcImJvb2xlYW5cIiAmJiB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlVmFsID8gdGhpcy5hZGRDbGFzcyggdmFsdWUgKSA6IHRoaXMucmVtb3ZlQ2xhc3MoIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS50b2dnbGVDbGFzcyhcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCB0aGlzLCBpLCBnZXRDbGFzcyggdGhpcyApLCBzdGF0ZVZhbCApLFxuXHRcdFx0XHRcdHN0YXRlVmFsXG5cdFx0XHRcdCk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2xhc3NOYW1lLCBpLCBzZWxmLCBjbGFzc05hbWVzO1xuXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0Ly8gVG9nZ2xlIGluZGl2aWR1YWwgY2xhc3MgbmFtZXNcblx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdHNlbGYgPSBqUXVlcnkoIHRoaXMgKTtcblx0XHRcdFx0Y2xhc3NOYW1lcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdFx0d2hpbGUgKCAoIGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbIGkrKyBdICkgKSB7XG5cblx0XHRcdFx0XHQvLyBDaGVjayBlYWNoIGNsYXNzTmFtZSBnaXZlbiwgc3BhY2Ugc2VwYXJhdGVkIGxpc3Rcblx0XHRcdFx0XHRpZiAoIHNlbGYuaGFzQ2xhc3MoIGNsYXNzTmFtZSApICkge1xuXHRcdFx0XHRcdFx0c2VsZi5yZW1vdmVDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuYWRkQ2xhc3MoIGNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb2dnbGUgd2hvbGUgY2xhc3MgbmFtZVxuXHRcdFx0fSBlbHNlIGlmICggdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdFx0Y2xhc3NOYW1lID0gZ2V0Q2xhc3MoIHRoaXMgKTtcblx0XHRcdFx0aWYgKCBjbGFzc05hbWUgKSB7XG5cblx0XHRcdFx0XHQvLyBTdG9yZSBjbGFzc05hbWUgaWYgc2V0XG5cdFx0XHRcdFx0ZGF0YVByaXYuc2V0KCB0aGlzLCBcIl9fY2xhc3NOYW1lX19cIiwgY2xhc3NOYW1lICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBJZiB0aGUgZWxlbWVudCBoYXMgYSBjbGFzcyBuYW1lIG9yIGlmIHdlJ3JlIHBhc3NlZCBgZmFsc2VgLFxuXHRcdFx0XHQvLyB0aGVuIHJlbW92ZSB0aGUgd2hvbGUgY2xhc3NuYW1lIChpZiB0aGVyZSB3YXMgb25lLCB0aGUgYWJvdmUgc2F2ZWQgaXQpLlxuXHRcdFx0XHQvLyBPdGhlcndpc2UgYnJpbmcgYmFjayB3aGF0ZXZlciB3YXMgcHJldmlvdXNseSBzYXZlZCAoaWYgYW55dGhpbmcpLFxuXHRcdFx0XHQvLyBmYWxsaW5nIGJhY2sgdG8gdGhlIGVtcHR5IHN0cmluZyBpZiBub3RoaW5nIHdhcyBzdG9yZWQuXG5cdFx0XHRcdGlmICggdGhpcy5zZXRBdHRyaWJ1dGUgKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIixcblx0XHRcdFx0XHRcdGNsYXNzTmFtZSB8fCB2YWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0XHRcdFx0XCJcIiA6XG5cdFx0XHRcdFx0XHRkYXRhUHJpdi5nZXQoIHRoaXMsIFwiX19jbGFzc05hbWVfX1wiICkgfHwgXCJcIlxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0aGFzQ2xhc3M6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgY2xhc3NOYW1lLCBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRjbGFzc05hbWUgPSBcIiBcIiArIHNlbGVjdG9yICsgXCIgXCI7XG5cdFx0d2hpbGUgKCAoIGVsZW0gPSB0aGlzWyBpKysgXSApICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdCggXCIgXCIgKyBzdHJpcEFuZENvbGxhcHNlKCBnZXRDbGFzcyggZWxlbSApICkgKyBcIiBcIiApLmluZGV4T2YoIGNsYXNzTmFtZSApID4gLTEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBycmV0dXJuID0gL1xcci9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHZhbDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBob29rcywgcmV0LCBpc0Z1bmN0aW9uLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRcdGhvb2tzID0galF1ZXJ5LnZhbEhvb2tzWyBlbGVtLnR5cGUgXSB8fFxuXHRcdFx0XHRcdGpRdWVyeS52YWxIb29rc1sgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdFx0aWYgKCBob29rcyAmJlxuXHRcdFx0XHRcdFwiZ2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0XHQoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgXCJ2YWx1ZVwiICkgKSAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXQgPSBlbGVtLnZhbHVlO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSBtb3N0IGNvbW1vbiBzdHJpbmcgY2FzZXNcblx0XHRcdFx0aWYgKCB0eXBlb2YgcmV0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHRcdHJldHVybiByZXQucmVwbGFjZSggcnJldHVybiwgXCJcIiApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gSGFuZGxlIGNhc2VzIHdoZXJlIHZhbHVlIGlzIG51bGwvdW5kZWYgb3IgbnVtYmVyXG5cdFx0XHRcdHJldHVybiByZXQgPT0gbnVsbCA/IFwiXCIgOiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdHZhciB2YWw7XG5cblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGlzRnVuY3Rpb24gKSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlLmNhbGwoIHRoaXMsIGksIGpRdWVyeSggdGhpcyApLnZhbCgpICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVHJlYXQgbnVsbC91bmRlZmluZWQgYXMgXCJcIjsgY29udmVydCBudW1iZXJzIHRvIHN0cmluZ1xuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0dmFsID0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggdHlwZW9mIHZhbCA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsICs9IFwiXCI7XG5cblx0XHRcdH0gZWxzZSBpZiAoIEFycmF5LmlzQXJyYXkoIHZhbCApICkge1xuXHRcdFx0XHR2YWwgPSBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSArIFwiXCI7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0aG9va3MgPSBqUXVlcnkudmFsSG9va3NbIHRoaXMudHlwZSBdIHx8IGpRdWVyeS52YWxIb29rc1sgdGhpcy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdC8vIElmIHNldCByZXR1cm5zIHVuZGVmaW5lZCwgZmFsbCBiYWNrIHRvIG5vcm1hbCBzZXR0aW5nXG5cdFx0XHRpZiAoICFob29rcyB8fCAhKCBcInNldFwiIGluIGhvb2tzICkgfHwgaG9va3Muc2V0KCB0aGlzLCB2YWwsIFwidmFsdWVcIiApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMudmFsdWUgPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0dmFsSG9va3M6IHtcblx0XHRvcHRpb246IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0dmFyIHZhbCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIFwidmFsdWVcIiApO1xuXHRcdFx0XHRyZXR1cm4gdmFsICE9IG51bGwgP1xuXHRcdFx0XHRcdHZhbCA6XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTEwIC0gMTEgb25seVxuXHRcdFx0XHRcdC8vIG9wdGlvbi50ZXh0IHRocm93cyBleGNlcHRpb25zICgjMTQ2ODYsICMxNDg1OClcblx0XHRcdFx0XHQvLyBTdHJpcCBhbmQgY29sbGFwc2Ugd2hpdGVzcGFjZVxuXHRcdFx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvI3N0cmlwLWFuZC1jb2xsYXBzZS13aGl0ZXNwYWNlXG5cdFx0XHRcdFx0c3RyaXBBbmRDb2xsYXBzZSggalF1ZXJ5LnRleHQoIGVsZW0gKSApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c2VsZWN0OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgdmFsdWUsIG9wdGlvbiwgaSxcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdGluZGV4ID0gZWxlbS5zZWxlY3RlZEluZGV4LFxuXHRcdFx0XHRcdG9uZSA9IGVsZW0udHlwZSA9PT0gXCJzZWxlY3Qtb25lXCIsXG5cdFx0XHRcdFx0dmFsdWVzID0gb25lID8gbnVsbCA6IFtdLFxuXHRcdFx0XHRcdG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdGlmICggaW5kZXggPCAwICkge1xuXHRcdFx0XHRcdGkgPSBtYXg7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpID0gb25lID8gaW5kZXggOiAwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTG9vcCB0aHJvdWdoIGFsbCB0aGUgc2VsZWN0ZWQgb3B0aW9uc1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBtYXg7IGkrKyApIHtcblx0XHRcdFx0XHRvcHRpb24gPSBvcHRpb25zWyBpIF07XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuXHRcdFx0XHRcdC8vIElFOC05IGRvZXNuJ3QgdXBkYXRlIHNlbGVjdGVkIGFmdGVyIGZvcm0gcmVzZXQgKCMyNTUxKVxuXHRcdFx0XHRcdGlmICggKCBvcHRpb24uc2VsZWN0ZWQgfHwgaSA9PT0gaW5kZXggKSAmJlxuXG5cdFx0XHRcdFx0XHRcdC8vIERvbid0IHJldHVybiBvcHRpb25zIHRoYXQgYXJlIGRpc2FibGVkIG9yIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdFx0XHRcdFx0IW9wdGlvbi5kaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0XHQoICFvcHRpb24ucGFyZW50Tm9kZS5kaXNhYmxlZCB8fFxuXHRcdFx0XHRcdFx0XHRcdCFub2RlTmFtZSggb3B0aW9uLnBhcmVudE5vZGUsIFwib3B0Z3JvdXBcIiApICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEdldCB0aGUgc3BlY2lmaWMgdmFsdWUgZm9yIHRoZSBvcHRpb25cblx0XHRcdFx0XHRcdHZhbHVlID0galF1ZXJ5KCBvcHRpb24gKS52YWwoKTtcblxuXHRcdFx0XHRcdFx0Ly8gV2UgZG9uJ3QgbmVlZCBhbiBhcnJheSBmb3Igb25lIHNlbGVjdHNcblx0XHRcdFx0XHRcdGlmICggb25lICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIE11bHRpLVNlbGVjdHMgcmV0dXJuIGFuIGFycmF5XG5cdFx0XHRcdFx0XHR2YWx1ZXMucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fSxcblxuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBvcHRpb25TZXQsIG9wdGlvbixcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdHZhbHVlcyA9IGpRdWVyeS5tYWtlQXJyYXkoIHZhbHVlICksXG5cdFx0XHRcdFx0aSA9IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG5cblx0XHRcdFx0XHRpZiAoIG9wdGlvbi5zZWxlY3RlZCA9XG5cdFx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggalF1ZXJ5LnZhbEhvb2tzLm9wdGlvbi5nZXQoIG9wdGlvbiApLCB2YWx1ZXMgKSA+IC0xXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRvcHRpb25TZXQgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tY29uZC1hc3NpZ24gKi9cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcmNlIGJyb3dzZXJzIHRvIGJlaGF2ZSBjb25zaXN0ZW50bHkgd2hlbiBub24tbWF0Y2hpbmcgdmFsdWUgaXMgc2V0XG5cdFx0XHRcdGlmICggIW9wdGlvblNldCApIHtcblx0XHRcdFx0XHRlbGVtLnNlbGVjdGVkSW5kZXggPSAtMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG4vLyBSYWRpb3MgYW5kIGNoZWNrYm94ZXMgZ2V0dGVyL3NldHRlclxualF1ZXJ5LmVhY2goIFsgXCJyYWRpb1wiLCBcImNoZWNrYm94XCIgXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdID0ge1xuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWx1ZSApICkge1xuXHRcdFx0XHRyZXR1cm4gKCBlbGVtLmNoZWNrZWQgPSBqUXVlcnkuaW5BcnJheSggalF1ZXJ5KCBlbGVtICkudmFsKCksIHZhbHVlICkgPiAtMSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0aWYgKCAhc3VwcG9ydC5jaGVja09uICkge1xuXHRcdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdLmdldCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gbnVsbCA/IFwib25cIiA6IGVsZW0udmFsdWU7XG5cdFx0fTtcblx0fVxufSApO1xuXG5cblxuXG4vLyBSZXR1cm4galF1ZXJ5IGZvciBhdHRyaWJ1dGVzLW9ubHkgaW5jbHVzaW9uXG5cblxudmFyIHJmb2N1c01vcnBoID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvO1xuXG5qUXVlcnkuZXh0ZW5kKCBqUXVlcnkuZXZlbnQsIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggZXZlbnQsIGRhdGEsIGVsZW0sIG9ubHlIYW5kbGVycyApIHtcblxuXHRcdHZhciBpLCBjdXIsIHRtcCwgYnViYmxlVHlwZSwgb250eXBlLCBoYW5kbGUsIHNwZWNpYWwsXG5cdFx0XHRldmVudFBhdGggPSBbIGVsZW0gfHwgZG9jdW1lbnQgXSxcblx0XHRcdHR5cGUgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwidHlwZVwiICkgPyBldmVudC50eXBlIDogZXZlbnQsXG5cdFx0XHRuYW1lc3BhY2VzID0gaGFzT3duLmNhbGwoIGV2ZW50LCBcIm5hbWVzcGFjZVwiICkgPyBldmVudC5uYW1lc3BhY2Uuc3BsaXQoIFwiLlwiICkgOiBbXTtcblxuXHRcdGN1ciA9IHRtcCA9IGVsZW0gPSBlbGVtIHx8IGRvY3VtZW50O1xuXG5cdFx0Ly8gRG9uJ3QgZG8gZXZlbnRzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBmb2N1cy9ibHVyIG1vcnBocyB0byBmb2N1c2luL291dDsgZW5zdXJlIHdlJ3JlIG5vdCBmaXJpbmcgdGhlbSByaWdodCBub3dcblx0XHRpZiAoIHJmb2N1c01vcnBoLnRlc3QoIHR5cGUgKyBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlLmluZGV4T2YoIFwiLlwiICkgPiAtMSApIHtcblxuXHRcdFx0Ly8gTmFtZXNwYWNlZCB0cmlnZ2VyOyBjcmVhdGUgYSByZWdleHAgdG8gbWF0Y2ggZXZlbnQgdHlwZSBpbiBoYW5kbGUoKVxuXHRcdFx0bmFtZXNwYWNlcyA9IHR5cGUuc3BsaXQoIFwiLlwiICk7XG5cdFx0XHR0eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpO1xuXHRcdFx0bmFtZXNwYWNlcy5zb3J0KCk7XG5cdFx0fVxuXHRcdG9udHlwZSA9IHR5cGUuaW5kZXhPZiggXCI6XCIgKSA8IDAgJiYgXCJvblwiICsgdHlwZTtcblxuXHRcdC8vIENhbGxlciBjYW4gcGFzcyBpbiBhIGpRdWVyeS5FdmVudCBvYmplY3QsIE9iamVjdCwgb3IganVzdCBhbiBldmVudCB0eXBlIHN0cmluZ1xuXHRcdGV2ZW50ID0gZXZlbnRbIGpRdWVyeS5leHBhbmRvIF0gP1xuXHRcdFx0ZXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggdHlwZSwgdHlwZW9mIGV2ZW50ID09PSBcIm9iamVjdFwiICYmIGV2ZW50ICk7XG5cblx0XHQvLyBUcmlnZ2VyIGJpdG1hc2s6ICYgMSBmb3IgbmF0aXZlIGhhbmRsZXJzOyAmIDIgZm9yIGpRdWVyeSAoYWx3YXlzIHRydWUpXG5cdFx0ZXZlbnQuaXNUcmlnZ2VyID0gb25seUhhbmRsZXJzID8gMiA6IDM7XG5cdFx0ZXZlbnQubmFtZXNwYWNlID0gbmFtZXNwYWNlcy5qb2luKCBcIi5cIiApO1xuXHRcdGV2ZW50LnJuYW1lc3BhY2UgPSBldmVudC5uYW1lc3BhY2UgP1xuXHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICkgOlxuXHRcdFx0bnVsbDtcblxuXHRcdC8vIENsZWFuIHVwIHRoZSBldmVudCBpbiBjYXNlIGl0IGlzIGJlaW5nIHJldXNlZFxuXHRcdGV2ZW50LnJlc3VsdCA9IHVuZGVmaW5lZDtcblx0XHRpZiAoICFldmVudC50YXJnZXQgKSB7XG5cdFx0XHRldmVudC50YXJnZXQgPSBlbGVtO1xuXHRcdH1cblxuXHRcdC8vIENsb25lIGFueSBpbmNvbWluZyBkYXRhIGFuZCBwcmVwZW5kIHRoZSBldmVudCwgY3JlYXRpbmcgdGhlIGhhbmRsZXIgYXJnIGxpc3Rcblx0XHRkYXRhID0gZGF0YSA9PSBudWxsID9cblx0XHRcdFsgZXZlbnQgXSA6XG5cdFx0XHRqUXVlcnkubWFrZUFycmF5KCBkYXRhLCBbIGV2ZW50IF0gKTtcblxuXHRcdC8vIEFsbG93IHNwZWNpYWwgZXZlbnRzIHRvIGRyYXcgb3V0c2lkZSB0aGUgbGluZXNcblx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgc3BlY2lhbC50cmlnZ2VyICYmIHNwZWNpYWwudHJpZ2dlci5hcHBseSggZWxlbSwgZGF0YSApID09PSBmYWxzZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgZXZlbnQgcHJvcGFnYXRpb24gcGF0aCBpbiBhZHZhbmNlLCBwZXIgVzNDIGV2ZW50cyBzcGVjICgjOTk1MSlcblx0XHQvLyBCdWJibGUgdXAgdG8gZG9jdW1lbnQsIHRoZW4gdG8gd2luZG93OyB3YXRjaCBmb3IgYSBnbG9iYWwgb3duZXJEb2N1bWVudCB2YXIgKCM5NzI0KVxuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhc3BlY2lhbC5ub0J1YmJsZSAmJiAhalF1ZXJ5LmlzV2luZG93KCBlbGVtICkgKSB7XG5cblx0XHRcdGJ1YmJsZVR5cGUgPSBzcGVjaWFsLmRlbGVnYXRlVHlwZSB8fCB0eXBlO1xuXHRcdFx0aWYgKCAhcmZvY3VzTW9ycGgudGVzdCggYnViYmxlVHlwZSArIHR5cGUgKSApIHtcblx0XHRcdFx0Y3VyID0gY3VyLnBhcmVudE5vZGU7XG5cdFx0XHR9XG5cdFx0XHRmb3IgKCA7IGN1cjsgY3VyID0gY3VyLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdGV2ZW50UGF0aC5wdXNoKCBjdXIgKTtcblx0XHRcdFx0dG1wID0gY3VyO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPbmx5IGFkZCB3aW5kb3cgaWYgd2UgZ290IHRvIGRvY3VtZW50IChlLmcuLCBub3QgcGxhaW4gb2JqIG9yIGRldGFjaGVkIERPTSlcblx0XHRcdGlmICggdG1wID09PSAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudCApICkge1xuXHRcdFx0XHRldmVudFBhdGgucHVzaCggdG1wLmRlZmF1bHRWaWV3IHx8IHRtcC5wYXJlbnRXaW5kb3cgfHwgd2luZG93ICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZSBoYW5kbGVycyBvbiB0aGUgZXZlbnQgcGF0aFxuXHRcdGkgPSAwO1xuXHRcdHdoaWxlICggKCBjdXIgPSBldmVudFBhdGhbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdGV2ZW50LnR5cGUgPSBpID4gMSA/XG5cdFx0XHRcdGJ1YmJsZVR5cGUgOlxuXHRcdFx0XHRzcGVjaWFsLmJpbmRUeXBlIHx8IHR5cGU7XG5cblx0XHRcdC8vIGpRdWVyeSBoYW5kbGVyXG5cdFx0XHRoYW5kbGUgPSAoIGRhdGFQcml2LmdldCggY3VyLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdICYmXG5cdFx0XHRcdGRhdGFQcml2LmdldCggY3VyLCBcImhhbmRsZVwiICk7XG5cdFx0XHRpZiAoIGhhbmRsZSApIHtcblx0XHRcdFx0aGFuZGxlLmFwcGx5KCBjdXIsIGRhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTmF0aXZlIGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9IG9udHlwZSAmJiBjdXJbIG9udHlwZSBdO1xuXHRcdFx0aWYgKCBoYW5kbGUgJiYgaGFuZGxlLmFwcGx5ICYmIGFjY2VwdERhdGEoIGN1ciApICkge1xuXHRcdFx0XHRldmVudC5yZXN1bHQgPSBoYW5kbGUuYXBwbHkoIGN1ciwgZGF0YSApO1xuXHRcdFx0XHRpZiAoIGV2ZW50LnJlc3VsdCA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRldmVudC50eXBlID0gdHlwZTtcblxuXHRcdC8vIElmIG5vYm9keSBwcmV2ZW50ZWQgdGhlIGRlZmF1bHQgYWN0aW9uLCBkbyBpdCBub3dcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgIWV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpICkge1xuXG5cdFx0XHRpZiAoICggIXNwZWNpYWwuX2RlZmF1bHQgfHxcblx0XHRcdFx0c3BlY2lhbC5fZGVmYXVsdC5hcHBseSggZXZlbnRQYXRoLnBvcCgpLCBkYXRhICkgPT09IGZhbHNlICkgJiZcblx0XHRcdFx0YWNjZXB0RGF0YSggZWxlbSApICkge1xuXG5cdFx0XHRcdC8vIENhbGwgYSBuYXRpdmUgRE9NIG1ldGhvZCBvbiB0aGUgdGFyZ2V0IHdpdGggdGhlIHNhbWUgbmFtZSBhcyB0aGUgZXZlbnQuXG5cdFx0XHRcdC8vIERvbid0IGRvIGRlZmF1bHQgYWN0aW9ucyBvbiB3aW5kb3csIHRoYXQncyB3aGVyZSBnbG9iYWwgdmFyaWFibGVzIGJlICgjNjE3MClcblx0XHRcdFx0aWYgKCBvbnR5cGUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIGVsZW1bIHR5cGUgXSApICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vIERvbid0IHJlLXRyaWdnZXIgYW4gb25GT08gZXZlbnQgd2hlbiB3ZSBjYWxsIGl0cyBGT08oKSBtZXRob2Rcblx0XHRcdFx0XHR0bXAgPSBlbGVtWyBvbnR5cGUgXTtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSBudWxsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZXZlbnQgcmUtdHJpZ2dlcmluZyBvZiB0aGUgc2FtZSBldmVudCwgc2luY2Ugd2UgYWxyZWFkeSBidWJibGVkIGl0IGFib3ZlXG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHR5cGU7XG5cdFx0XHRcdFx0ZWxlbVsgdHlwZSBdKCk7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSB0bXA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHQvLyBQaWdneWJhY2sgb24gYSBkb25vciBldmVudCB0byBzaW11bGF0ZSBhIGRpZmZlcmVudCBvbmVcblx0Ly8gVXNlZCBvbmx5IGZvciBgZm9jdXMoaW4gfCBvdXQpYCBldmVudHNcblx0c2ltdWxhdGU6IGZ1bmN0aW9uKCB0eXBlLCBlbGVtLCBldmVudCApIHtcblx0XHR2YXIgZSA9IGpRdWVyeS5leHRlbmQoXG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCksXG5cdFx0XHRldmVudCxcblx0XHRcdHtcblx0XHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdFx0aXNTaW11bGF0ZWQ6IHRydWVcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIGUsIG51bGwsIGVsZW0gKTtcblx0fVxuXG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7XG5cdFx0fSApO1xuXHR9LFxuXHR0cmlnZ2VySGFuZGxlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIGVsZW0gPSB0aGlzWyAwIF07XG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCBlbGVtLCB0cnVlICk7XG5cdFx0fVxuXHR9XG59ICk7XG5cblxualF1ZXJ5LmVhY2goICggXCJibHVyIGZvY3VzIGZvY3VzaW4gZm9jdXNvdXQgcmVzaXplIHNjcm9sbCBjbGljayBkYmxjbGljayBcIiArXG5cdFwibW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgXCIgK1xuXHRcImNoYW5nZSBzZWxlY3Qgc3VibWl0IGtleWRvd24ga2V5cHJlc3Mga2V5dXAgY29udGV4dG1lbnVcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRmdW5jdGlvbiggaSwgbmFtZSApIHtcblxuXHQvLyBIYW5kbGUgZXZlbnQgYmluZGluZ1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDAgP1xuXHRcdFx0dGhpcy5vbiggbmFtZSwgbnVsbCwgZGF0YSwgZm4gKSA6XG5cdFx0XHR0aGlzLnRyaWdnZXIoIG5hbWUgKTtcblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRob3ZlcjogZnVuY3Rpb24oIGZuT3ZlciwgZm5PdXQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubW91c2VlbnRlciggZm5PdmVyICkubW91c2VsZWF2ZSggZm5PdXQgfHwgZm5PdmVyICk7XG5cdH1cbn0gKTtcblxuXG5cblxuc3VwcG9ydC5mb2N1c2luID0gXCJvbmZvY3VzaW5cIiBpbiB3aW5kb3c7XG5cblxuLy8gU3VwcG9ydDogRmlyZWZveCA8PTQ0XG4vLyBGaXJlZm94IGRvZXNuJ3QgaGF2ZSBmb2N1cyhpbiB8IG91dCkgZXZlbnRzXG4vLyBSZWxhdGVkIHRpY2tldCAtIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY4Nzc4N1xuLy9cbi8vIFN1cHBvcnQ6IENocm9tZSA8PTQ4IC0gNDksIFNhZmFyaSA8PTkuMCAtIDkuMVxuLy8gZm9jdXMoaW4gfCBvdXQpIGV2ZW50cyBmaXJlIGFmdGVyIGZvY3VzICYgYmx1ciBldmVudHMsXG4vLyB3aGljaCBpcyBzcGVjIHZpb2xhdGlvbiAtIGh0dHA6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnRzLWZvY3VzZXZlbnQtZXZlbnQtb3JkZXJcbi8vIFJlbGF0ZWQgdGlja2V0IC0gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQ5ODU3XG5pZiAoICFzdXBwb3J0LmZvY3VzaW4gKSB7XG5cdGpRdWVyeS5lYWNoKCB7IGZvY3VzOiBcImZvY3VzaW5cIiwgYmx1cjogXCJmb2N1c291dFwiIH0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cblx0XHQvLyBBdHRhY2ggYSBzaW5nbGUgY2FwdHVyaW5nIGhhbmRsZXIgb24gdGhlIGRvY3VtZW50IHdoaWxlIHNvbWVvbmUgd2FudHMgZm9jdXNpbi9mb2N1c291dFxuXHRcdHZhciBoYW5kbGVyID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnNpbXVsYXRlKCBmaXgsIGV2ZW50LnRhcmdldCwgalF1ZXJ5LmV2ZW50LmZpeCggZXZlbnQgKSApO1xuXHRcdH07XG5cblx0XHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZml4IF0gPSB7XG5cdFx0XHRzZXR1cDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBkb2MgPSB0aGlzLm93bmVyRG9jdW1lbnQgfHwgdGhpcyxcblx0XHRcdFx0XHRhdHRhY2hlcyA9IGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXggKTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MuYWRkRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsICggYXR0YWNoZXMgfHwgMCApICsgMSApO1xuXHRcdFx0fSxcblx0XHRcdHRlYXJkb3duOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCApIC0gMTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZG9jLCBmaXggKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsIGF0dGFjaGVzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9ICk7XG59XG52YXIgbG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb247XG5cbnZhciBub25jZSA9IGpRdWVyeS5ub3coKTtcblxudmFyIHJxdWVyeSA9ICggL1xcPy8gKTtcblxuXG5cbi8vIENyb3NzLWJyb3dzZXIgeG1sIHBhcnNpbmdcbmpRdWVyeS5wYXJzZVhNTCA9IGZ1bmN0aW9uKCBkYXRhICkge1xuXHR2YXIgeG1sO1xuXHRpZiAoICFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHlcblx0Ly8gSUUgdGhyb3dzIG9uIHBhcnNlRnJvbVN0cmluZyB3aXRoIGludmFsaWQgaW5wdXQuXG5cdHRyeSB7XG5cdFx0eG1sID0gKCBuZXcgd2luZG93LkRPTVBhcnNlcigpICkucGFyc2VGcm9tU3RyaW5nKCBkYXRhLCBcInRleHQveG1sXCIgKTtcblx0fSBjYXRjaCAoIGUgKSB7XG5cdFx0eG1sID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0aWYgKCAheG1sIHx8IHhtbC5nZXRFbGVtZW50c0J5VGFnTmFtZSggXCJwYXJzZXJlcnJvclwiICkubGVuZ3RoICkge1xuXHRcdGpRdWVyeS5lcnJvciggXCJJbnZhbGlkIFhNTDogXCIgKyBkYXRhICk7XG5cdH1cblx0cmV0dXJuIHhtbDtcbn07XG5cblxudmFyXG5cdHJicmFja2V0ID0gL1xcW1xcXSQvLFxuXHRyQ1JMRiA9IC9cXHI/XFxuL2csXG5cdHJzdWJtaXR0ZXJUeXBlcyA9IC9eKD86c3VibWl0fGJ1dHRvbnxpbWFnZXxyZXNldHxmaWxlKSQvaSxcblx0cnN1Ym1pdHRhYmxlID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pO1xuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyggcHJlZml4LCBvYmosIHRyYWRpdGlvbmFsLCBhZGQgKSB7XG5cdHZhciBuYW1lO1xuXG5cdGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgYXJyYXkgaXRlbS5cblx0XHRqUXVlcnkuZWFjaCggb2JqLCBmdW5jdGlvbiggaSwgdiApIHtcblx0XHRcdGlmICggdHJhZGl0aW9uYWwgfHwgcmJyYWNrZXQudGVzdCggcHJlZml4ICkgKSB7XG5cblx0XHRcdFx0Ly8gVHJlYXQgZWFjaCBhcnJheSBpdGVtIGFzIGEgc2NhbGFyLlxuXHRcdFx0XHRhZGQoIHByZWZpeCwgdiApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIEl0ZW0gaXMgbm9uLXNjYWxhciAoYXJyYXkgb3Igb2JqZWN0KSwgZW5jb2RlIGl0cyBudW1lcmljIGluZGV4LlxuXHRcdFx0XHRidWlsZFBhcmFtcyhcblx0XHRcdFx0XHRwcmVmaXggKyBcIltcIiArICggdHlwZW9mIHYgPT09IFwib2JqZWN0XCIgJiYgdiAhPSBudWxsID8gaSA6IFwiXCIgKSArIFwiXVwiLFxuXHRcdFx0XHRcdHYsXG5cdFx0XHRcdFx0dHJhZGl0aW9uYWwsXG5cdFx0XHRcdFx0YWRkXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdH0gZWxzZSBpZiAoICF0cmFkaXRpb25hbCAmJiBqUXVlcnkudHlwZSggb2JqICkgPT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgb2JqZWN0IGl0ZW0uXG5cdFx0Zm9yICggbmFtZSBpbiBvYmogKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4ICsgXCJbXCIgKyBuYW1lICsgXCJdXCIsIG9ialsgbmFtZSBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXG5cdH0gZWxzZSB7XG5cblx0XHQvLyBTZXJpYWxpemUgc2NhbGFyIGl0ZW0uXG5cdFx0YWRkKCBwcmVmaXgsIG9iaiApO1xuXHR9XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzIG9yIGEgc2V0IG9mXG4vLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmdcbmpRdWVyeS5wYXJhbSA9IGZ1bmN0aW9uKCBhLCB0cmFkaXRpb25hbCApIHtcblx0dmFyIHByZWZpeCxcblx0XHRzID0gW10sXG5cdFx0YWRkID0gZnVuY3Rpb24oIGtleSwgdmFsdWVPckZ1bmN0aW9uICkge1xuXG5cdFx0XHQvLyBJZiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCBpbnZva2UgaXQgYW5kIHVzZSBpdHMgcmV0dXJuIHZhbHVlXG5cdFx0XHR2YXIgdmFsdWUgPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWVPckZ1bmN0aW9uICkgP1xuXHRcdFx0XHR2YWx1ZU9yRnVuY3Rpb24oKSA6XG5cdFx0XHRcdHZhbHVlT3JGdW5jdGlvbjtcblxuXHRcdFx0c1sgcy5sZW5ndGggXSA9IGVuY29kZVVSSUNvbXBvbmVudCgga2V5ICkgKyBcIj1cIiArXG5cdFx0XHRcdGVuY29kZVVSSUNvbXBvbmVudCggdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSApO1xuXHRcdH07XG5cblx0Ly8gSWYgYW4gYXJyYXkgd2FzIHBhc3NlZCBpbiwgYXNzdW1lIHRoYXQgaXQgaXMgYW4gYXJyYXkgb2YgZm9ybSBlbGVtZW50cy5cblx0aWYgKCBBcnJheS5pc0FycmF5KCBhICkgfHwgKCBhLmpxdWVyeSAmJiAhalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGEgKSApICkge1xuXG5cdFx0Ly8gU2VyaWFsaXplIHRoZSBmb3JtIGVsZW1lbnRzXG5cdFx0alF1ZXJ5LmVhY2goIGEsIGZ1bmN0aW9uKCkge1xuXHRcdFx0YWRkKCB0aGlzLm5hbWUsIHRoaXMudmFsdWUgKTtcblx0XHR9ICk7XG5cblx0fSBlbHNlIHtcblxuXHRcdC8vIElmIHRyYWRpdGlvbmFsLCBlbmNvZGUgdGhlIFwib2xkXCIgd2F5ICh0aGUgd2F5IDEuMy4yIG9yIG9sZGVyXG5cdFx0Ly8gZGlkIGl0KSwgb3RoZXJ3aXNlIGVuY29kZSBwYXJhbXMgcmVjdXJzaXZlbHkuXG5cdFx0Zm9yICggcHJlZml4IGluIGEgKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4LCBhWyBwcmVmaXggXSwgdHJhZGl0aW9uYWwsIGFkZCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgcmVzdWx0aW5nIHNlcmlhbGl6YXRpb25cblx0cmV0dXJuIHMuam9pbiggXCImXCIgKTtcbn07XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0c2VyaWFsaXplOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4galF1ZXJ5LnBhcmFtKCB0aGlzLnNlcmlhbGl6ZUFycmF5KCkgKTtcblx0fSxcblx0c2VyaWFsaXplQXJyYXk6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIENhbiBhZGQgcHJvcEhvb2sgZm9yIFwiZWxlbWVudHNcIiB0byBmaWx0ZXIgb3IgYWRkIGZvcm0gZWxlbWVudHNcblx0XHRcdHZhciBlbGVtZW50cyA9IGpRdWVyeS5wcm9wKCB0aGlzLCBcImVsZW1lbnRzXCIgKTtcblx0XHRcdHJldHVybiBlbGVtZW50cyA/IGpRdWVyeS5tYWtlQXJyYXkoIGVsZW1lbnRzICkgOiB0aGlzO1xuXHRcdH0gKVxuXHRcdC5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLnR5cGU7XG5cblx0XHRcdC8vIFVzZSAuaXMoIFwiOmRpc2FibGVkXCIgKSBzbyB0aGF0IGZpZWxkc2V0W2Rpc2FibGVkXSB3b3Jrc1xuXHRcdFx0cmV0dXJuIHRoaXMubmFtZSAmJiAhalF1ZXJ5KCB0aGlzICkuaXMoIFwiOmRpc2FibGVkXCIgKSAmJlxuXHRcdFx0XHRyc3VibWl0dGFibGUudGVzdCggdGhpcy5ub2RlTmFtZSApICYmICFyc3VibWl0dGVyVHlwZXMudGVzdCggdHlwZSApICYmXG5cdFx0XHRcdCggdGhpcy5jaGVja2VkIHx8ICFyY2hlY2thYmxlVHlwZS50ZXN0KCB0eXBlICkgKTtcblx0XHR9IClcblx0XHQubWFwKCBmdW5jdGlvbiggaSwgZWxlbSApIHtcblx0XHRcdHZhciB2YWwgPSBqUXVlcnkoIHRoaXMgKS52YWwoKTtcblxuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsICkgKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHsgbmFtZTogZWxlbS5uYW1lLCB2YWx1ZTogdmFsLnJlcGxhY2UoIHJDUkxGLCBcIlxcclxcblwiICkgfTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4geyBuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWwucmVwbGFjZSggckNSTEYsIFwiXFxyXFxuXCIgKSB9O1xuXHRcdH0gKS5nZXQoKTtcblx0fVxufSApO1xuXG5cbnZhclxuXHRyMjAgPSAvJTIwL2csXG5cdHJoYXNoID0gLyMuKiQvLFxuXHRyYW50aUNhY2hlID0gLyhbPyZdKV89W14mXSovLFxuXHRyaGVhZGVycyA9IC9eKC4qPyk6WyBcXHRdKihbXlxcclxcbl0qKSQvbWcsXG5cblx0Ly8gIzc2NTMsICM4MTI1LCAjODE1MjogbG9jYWwgcHJvdG9jb2wgZGV0ZWN0aW9uXG5cdHJsb2NhbFByb3RvY29sID0gL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8sXG5cdHJub0NvbnRlbnQgPSAvXig/OkdFVHxIRUFEKSQvLFxuXHRycHJvdG9jb2wgPSAvXlxcL1xcLy8sXG5cblx0LyogUHJlZmlsdGVyc1xuXHQgKiAxKSBUaGV5IGFyZSB1c2VmdWwgdG8gaW50cm9kdWNlIGN1c3RvbSBkYXRhVHlwZXMgKHNlZSBhamF4L2pzb25wLmpzIGZvciBhbiBleGFtcGxlKVxuXHQgKiAyKSBUaGVzZSBhcmUgY2FsbGVkOlxuXHQgKiAgICAtIEJFRk9SRSBhc2tpbmcgZm9yIGEgdHJhbnNwb3J0XG5cdCAqICAgIC0gQUZURVIgcGFyYW0gc2VyaWFsaXphdGlvbiAocy5kYXRhIGlzIGEgc3RyaW5nIGlmIHMucHJvY2Vzc0RhdGEgaXMgdHJ1ZSlcblx0ICogMykga2V5IGlzIHRoZSBkYXRhVHlwZVxuXHQgKiA0KSB0aGUgY2F0Y2hhbGwgc3ltYm9sIFwiKlwiIGNhbiBiZSB1c2VkXG5cdCAqIDUpIGV4ZWN1dGlvbiB3aWxsIHN0YXJ0IHdpdGggdHJhbnNwb3J0IGRhdGFUeXBlIGFuZCBUSEVOIGNvbnRpbnVlIGRvd24gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHRwcmVmaWx0ZXJzID0ge30sXG5cblx0LyogVHJhbnNwb3J0cyBiaW5kaW5nc1xuXHQgKiAxKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDIpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogMykgc2VsZWN0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gZ28gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHR0cmFuc3BvcnRzID0ge30sXG5cblx0Ly8gQXZvaWQgY29tbWVudC1wcm9sb2cgY2hhciBzZXF1ZW5jZSAoIzEwMDk4KTsgbXVzdCBhcHBlYXNlIGxpbnQgYW5kIGV2YWRlIGNvbXByZXNzaW9uXG5cdGFsbFR5cGVzID0gXCIqL1wiLmNvbmNhdCggXCIqXCIgKSxcblxuXHQvLyBBbmNob3IgdGFnIGZvciBwYXJzaW5nIHRoZSBkb2N1bWVudCBvcmlnaW5cblx0b3JpZ2luQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblx0b3JpZ2luQW5jaG9yLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXG4vLyBCYXNlIFwiY29uc3RydWN0b3JcIiBmb3IgalF1ZXJ5LmFqYXhQcmVmaWx0ZXIgYW5kIGpRdWVyeS5hamF4VHJhbnNwb3J0XG5mdW5jdGlvbiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHN0cnVjdHVyZSApIHtcblxuXHQvLyBkYXRhVHlwZUV4cHJlc3Npb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIFwiKlwiXG5cdHJldHVybiBmdW5jdGlvbiggZGF0YVR5cGVFeHByZXNzaW9uLCBmdW5jICkge1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVFeHByZXNzaW9uICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZnVuYyA9IGRhdGFUeXBlRXhwcmVzc2lvbjtcblx0XHRcdGRhdGFUeXBlRXhwcmVzc2lvbiA9IFwiKlwiO1xuXHRcdH1cblxuXHRcdHZhciBkYXRhVHlwZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0ZGF0YVR5cGVzID0gZGF0YVR5cGVFeHByZXNzaW9uLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGZ1bmMgKSApIHtcblxuXHRcdFx0Ly8gRm9yIGVhY2ggZGF0YVR5cGUgaW4gdGhlIGRhdGFUeXBlRXhwcmVzc2lvblxuXHRcdFx0d2hpbGUgKCAoIGRhdGFUeXBlID0gZGF0YVR5cGVzWyBpKysgXSApICkge1xuXG5cdFx0XHRcdC8vIFByZXBlbmQgaWYgcmVxdWVzdGVkXG5cdFx0XHRcdGlmICggZGF0YVR5cGVbIDAgXSA9PT0gXCIrXCIgKSB7XG5cdFx0XHRcdFx0ZGF0YVR5cGUgPSBkYXRhVHlwZS5zbGljZSggMSApIHx8IFwiKlwiO1xuXHRcdFx0XHRcdCggc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdICkudW5zaGlmdCggZnVuYyApO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBhcHBlbmRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQoIHN0cnVjdHVyZVsgZGF0YVR5cGUgXSA9IHN0cnVjdHVyZVsgZGF0YVR5cGUgXSB8fCBbXSApLnB1c2goIGZ1bmMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxuLy8gQmFzZSBpbnNwZWN0aW9uIGZ1bmN0aW9uIGZvciBwcmVmaWx0ZXJzIGFuZCB0cmFuc3BvcnRzXG5mdW5jdGlvbiBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlLCBvcHRpb25zLCBvcmlnaW5hbE9wdGlvbnMsIGpxWEhSICkge1xuXG5cdHZhciBpbnNwZWN0ZWQgPSB7fSxcblx0XHRzZWVraW5nVHJhbnNwb3J0ID0gKCBzdHJ1Y3R1cmUgPT09IHRyYW5zcG9ydHMgKTtcblxuXHRmdW5jdGlvbiBpbnNwZWN0KCBkYXRhVHlwZSApIHtcblx0XHR2YXIgc2VsZWN0ZWQ7XG5cdFx0aW5zcGVjdGVkWyBkYXRhVHlwZSBdID0gdHJ1ZTtcblx0XHRqUXVlcnkuZWFjaCggc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdLCBmdW5jdGlvbiggXywgcHJlZmlsdGVyT3JGYWN0b3J5ICkge1xuXHRcdFx0dmFyIGRhdGFUeXBlT3JUcmFuc3BvcnQgPSBwcmVmaWx0ZXJPckZhY3RvcnkoIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKTtcblx0XHRcdGlmICggdHlwZW9mIGRhdGFUeXBlT3JUcmFuc3BvcnQgPT09IFwic3RyaW5nXCIgJiZcblx0XHRcdFx0IXNlZWtpbmdUcmFuc3BvcnQgJiYgIWluc3BlY3RlZFsgZGF0YVR5cGVPclRyYW5zcG9ydCBdICkge1xuXG5cdFx0XHRcdG9wdGlvbnMuZGF0YVR5cGVzLnVuc2hpZnQoIGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdFx0aW5zcGVjdCggZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCBzZWVraW5nVHJhbnNwb3J0ICkge1xuXHRcdFx0XHRyZXR1cm4gISggc2VsZWN0ZWQgPSBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcdHJldHVybiBzZWxlY3RlZDtcblx0fVxuXG5cdHJldHVybiBpbnNwZWN0KCBvcHRpb25zLmRhdGFUeXBlc1sgMCBdICkgfHwgIWluc3BlY3RlZFsgXCIqXCIgXSAmJiBpbnNwZWN0KCBcIipcIiApO1xufVxuXG4vLyBBIHNwZWNpYWwgZXh0ZW5kIGZvciBhamF4IG9wdGlvbnNcbi8vIHRoYXQgdGFrZXMgXCJmbGF0XCIgb3B0aW9ucyAobm90IHRvIGJlIGRlZXAgZXh0ZW5kZWQpXG4vLyBGaXhlcyAjOTg4N1xuZnVuY3Rpb24gYWpheEV4dGVuZCggdGFyZ2V0LCBzcmMgKSB7XG5cdHZhciBrZXksIGRlZXAsXG5cdFx0ZmxhdE9wdGlvbnMgPSBqUXVlcnkuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zIHx8IHt9O1xuXG5cdGZvciAoIGtleSBpbiBzcmMgKSB7XG5cdFx0aWYgKCBzcmNbIGtleSBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHQoIGZsYXRPcHRpb25zWyBrZXkgXSA/IHRhcmdldCA6ICggZGVlcCB8fCAoIGRlZXAgPSB7fSApICkgKVsga2V5IF0gPSBzcmNbIGtleSBdO1xuXHRcdH1cblx0fVxuXHRpZiAoIGRlZXAgKSB7XG5cdFx0alF1ZXJ5LmV4dGVuZCggdHJ1ZSwgdGFyZ2V0LCBkZWVwICk7XG5cdH1cblxuXHRyZXR1cm4gdGFyZ2V0O1xufVxuXG4vKiBIYW5kbGVzIHJlc3BvbnNlcyB0byBhbiBhamF4IHJlcXVlc3Q6XG4gKiAtIGZpbmRzIHRoZSByaWdodCBkYXRhVHlwZSAobWVkaWF0ZXMgYmV0d2VlbiBjb250ZW50LXR5cGUgYW5kIGV4cGVjdGVkIGRhdGFUeXBlKVxuICogLSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG4gKi9cbmZ1bmN0aW9uIGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKSB7XG5cblx0dmFyIGN0LCB0eXBlLCBmaW5hbERhdGFUeXBlLCBmaXJzdERhdGFUeXBlLFxuXHRcdGNvbnRlbnRzID0gcy5jb250ZW50cyxcblx0XHRkYXRhVHlwZXMgPSBzLmRhdGFUeXBlcztcblxuXHQvLyBSZW1vdmUgYXV0byBkYXRhVHlwZSBhbmQgZ2V0IGNvbnRlbnQtdHlwZSBpbiB0aGUgcHJvY2Vzc1xuXHR3aGlsZSAoIGRhdGFUeXBlc1sgMCBdID09PSBcIipcIiApIHtcblx0XHRkYXRhVHlwZXMuc2hpZnQoKTtcblx0XHRpZiAoIGN0ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRjdCA9IHMubWltZVR5cGUgfHwganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiQ29udGVudC1UeXBlXCIgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayBpZiB3ZSdyZSBkZWFsaW5nIHdpdGggYSBrbm93biBjb250ZW50LXR5cGVcblx0aWYgKCBjdCApIHtcblx0XHRmb3IgKCB0eXBlIGluIGNvbnRlbnRzICkge1xuXHRcdFx0aWYgKCBjb250ZW50c1sgdHlwZSBdICYmIGNvbnRlbnRzWyB0eXBlIF0udGVzdCggY3QgKSApIHtcblx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHR5cGUgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSByZXNwb25zZSBmb3IgdGhlIGV4cGVjdGVkIGRhdGFUeXBlXG5cdGlmICggZGF0YVR5cGVzWyAwIF0gaW4gcmVzcG9uc2VzICkge1xuXHRcdGZpbmFsRGF0YVR5cGUgPSBkYXRhVHlwZXNbIDAgXTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIFRyeSBjb252ZXJ0aWJsZSBkYXRhVHlwZXNcblx0XHRmb3IgKCB0eXBlIGluIHJlc3BvbnNlcyApIHtcblx0XHRcdGlmICggIWRhdGFUeXBlc1sgMCBdIHx8IHMuY29udmVydGVyc1sgdHlwZSArIFwiIFwiICsgZGF0YVR5cGVzWyAwIF0gXSApIHtcblx0XHRcdFx0ZmluYWxEYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAhZmlyc3REYXRhVHlwZSApIHtcblx0XHRcdFx0Zmlyc3REYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gT3IganVzdCB1c2UgZmlyc3Qgb25lXG5cdFx0ZmluYWxEYXRhVHlwZSA9IGZpbmFsRGF0YVR5cGUgfHwgZmlyc3REYXRhVHlwZTtcblx0fVxuXG5cdC8vIElmIHdlIGZvdW5kIGEgZGF0YVR5cGVcblx0Ly8gV2UgYWRkIHRoZSBkYXRhVHlwZSB0byB0aGUgbGlzdCBpZiBuZWVkZWRcblx0Ly8gYW5kIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyByZXNwb25zZVxuXHRpZiAoIGZpbmFsRGF0YVR5cGUgKSB7XG5cdFx0aWYgKCBmaW5hbERhdGFUeXBlICE9PSBkYXRhVHlwZXNbIDAgXSApIHtcblx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCBmaW5hbERhdGFUeXBlICk7XG5cdFx0fVxuXHRcdHJldHVybiByZXNwb25zZXNbIGZpbmFsRGF0YVR5cGUgXTtcblx0fVxufVxuXG4vKiBDaGFpbiBjb252ZXJzaW9ucyBnaXZlbiB0aGUgcmVxdWVzdCBhbmQgdGhlIG9yaWdpbmFsIHJlc3BvbnNlXG4gKiBBbHNvIHNldHMgdGhlIHJlc3BvbnNlWFhYIGZpZWxkcyBvbiB0aGUganFYSFIgaW5zdGFuY2VcbiAqL1xuZnVuY3Rpb24gYWpheENvbnZlcnQoIHMsIHJlc3BvbnNlLCBqcVhIUiwgaXNTdWNjZXNzICkge1xuXHR2YXIgY29udjIsIGN1cnJlbnQsIGNvbnYsIHRtcCwgcHJldixcblx0XHRjb252ZXJ0ZXJzID0ge30sXG5cblx0XHQvLyBXb3JrIHdpdGggYSBjb3B5IG9mIGRhdGFUeXBlcyBpbiBjYXNlIHdlIG5lZWQgdG8gbW9kaWZ5IGl0IGZvciBjb252ZXJzaW9uXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXMuc2xpY2UoKTtcblxuXHQvLyBDcmVhdGUgY29udmVydGVycyBtYXAgd2l0aCBsb3dlcmNhc2VkIGtleXNcblx0aWYgKCBkYXRhVHlwZXNbIDEgXSApIHtcblx0XHRmb3IgKCBjb252IGluIHMuY29udmVydGVycyApIHtcblx0XHRcdGNvbnZlcnRlcnNbIGNvbnYudG9Mb3dlckNhc2UoKSBdID0gcy5jb252ZXJ0ZXJzWyBjb252IF07XG5cdFx0fVxuXHR9XG5cblx0Y3VycmVudCA9IGRhdGFUeXBlcy5zaGlmdCgpO1xuXG5cdC8vIENvbnZlcnQgdG8gZWFjaCBzZXF1ZW50aWFsIGRhdGFUeXBlXG5cdHdoaWxlICggY3VycmVudCApIHtcblxuXHRcdGlmICggcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdICkge1xuXHRcdFx0anFYSFJbIHMucmVzcG9uc2VGaWVsZHNbIGN1cnJlbnQgXSBdID0gcmVzcG9uc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgdGhlIGRhdGFGaWx0ZXIgaWYgcHJvdmlkZWRcblx0XHRpZiAoICFwcmV2ICYmIGlzU3VjY2VzcyAmJiBzLmRhdGFGaWx0ZXIgKSB7XG5cdFx0XHRyZXNwb25zZSA9IHMuZGF0YUZpbHRlciggcmVzcG9uc2UsIHMuZGF0YVR5cGUgKTtcblx0XHR9XG5cblx0XHRwcmV2ID0gY3VycmVudDtcblx0XHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0XHRpZiAoIGN1cnJlbnQgKSB7XG5cblx0XHRcdC8vIFRoZXJlJ3Mgb25seSB3b3JrIHRvIGRvIGlmIGN1cnJlbnQgZGF0YVR5cGUgaXMgbm9uLWF1dG9cblx0XHRcdGlmICggY3VycmVudCA9PT0gXCIqXCIgKSB7XG5cblx0XHRcdFx0Y3VycmVudCA9IHByZXY7XG5cblx0XHRcdC8vIENvbnZlcnQgcmVzcG9uc2UgaWYgcHJldiBkYXRhVHlwZSBpcyBub24tYXV0byBhbmQgZGlmZmVycyBmcm9tIGN1cnJlbnRcblx0XHRcdH0gZWxzZSBpZiAoIHByZXYgIT09IFwiKlwiICYmIHByZXYgIT09IGN1cnJlbnQgKSB7XG5cblx0XHRcdFx0Ly8gU2VlayBhIGRpcmVjdCBjb252ZXJ0ZXJcblx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIGN1cnJlbnQgXSB8fCBjb252ZXJ0ZXJzWyBcIiogXCIgKyBjdXJyZW50IF07XG5cblx0XHRcdFx0Ly8gSWYgbm9uZSBmb3VuZCwgc2VlayBhIHBhaXJcblx0XHRcdFx0aWYgKCAhY29udiApIHtcblx0XHRcdFx0XHRmb3IgKCBjb252MiBpbiBjb252ZXJ0ZXJzICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJZiBjb252MiBvdXRwdXRzIGN1cnJlbnRcblx0XHRcdFx0XHRcdHRtcCA9IGNvbnYyLnNwbGl0KCBcIiBcIiApO1xuXHRcdFx0XHRcdFx0aWYgKCB0bXBbIDEgXSA9PT0gY3VycmVudCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBJZiBwcmV2IGNhbiBiZSBjb252ZXJ0ZWQgdG8gYWNjZXB0ZWQgaW5wdXRcblx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIHRtcFsgMCBdIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRjb252ZXJ0ZXJzWyBcIiogXCIgKyB0bXBbIDAgXSBdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDb25kZW5zZSBlcXVpdmFsZW5jZSBjb252ZXJ0ZXJzXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBjb252ID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIGNvbnYyIF07XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPdGhlcndpc2UsIGluc2VydCB0aGUgaW50ZXJtZWRpYXRlIGRhdGFUeXBlXG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udmVydGVyc1sgY29udjIgXSAhPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGN1cnJlbnQgPSB0bXBbIDAgXTtcblx0XHRcdFx0XHRcdFx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCB0bXBbIDEgXSApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFwcGx5IGNvbnZlcnRlciAoaWYgbm90IGFuIGVxdWl2YWxlbmNlKVxuXHRcdFx0XHRpZiAoIGNvbnYgIT09IHRydWUgKSB7XG5cblx0XHRcdFx0XHQvLyBVbmxlc3MgZXJyb3JzIGFyZSBhbGxvd2VkIHRvIGJ1YmJsZSwgY2F0Y2ggYW5kIHJldHVybiB0aGVtXG5cdFx0XHRcdFx0aWYgKCBjb252ICYmIHMudGhyb3dzICkge1xuXHRcdFx0XHRcdFx0cmVzcG9uc2UgPSBjb252KCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdFx0XHRzdGF0ZTogXCJwYXJzZXJlcnJvclwiLFxuXHRcdFx0XHRcdFx0XHRcdGVycm9yOiBjb252ID8gZSA6IFwiTm8gY29udmVyc2lvbiBmcm9tIFwiICsgcHJldiArIFwiIHRvIFwiICsgY3VycmVudFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7IHN0YXRlOiBcInN1Y2Nlc3NcIiwgZGF0YTogcmVzcG9uc2UgfTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIENvdW50ZXIgZm9yIGhvbGRpbmcgdGhlIG51bWJlciBvZiBhY3RpdmUgcXVlcmllc1xuXHRhY3RpdmU6IDAsXG5cblx0Ly8gTGFzdC1Nb2RpZmllZCBoZWFkZXIgY2FjaGUgZm9yIG5leHQgcmVxdWVzdFxuXHRsYXN0TW9kaWZpZWQ6IHt9LFxuXHRldGFnOiB7fSxcblxuXHRhamF4U2V0dGluZ3M6IHtcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYsXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRpc0xvY2FsOiBybG9jYWxQcm90b2NvbC50ZXN0KCBsb2NhdGlvbi5wcm90b2NvbCApLFxuXHRcdGdsb2JhbDogdHJ1ZSxcblx0XHRwcm9jZXNzRGF0YTogdHJ1ZSxcblx0XHRhc3luYzogdHJ1ZSxcblx0XHRjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIixcblxuXHRcdC8qXG5cdFx0dGltZW91dDogMCxcblx0XHRkYXRhOiBudWxsLFxuXHRcdGRhdGFUeXBlOiBudWxsLFxuXHRcdHVzZXJuYW1lOiBudWxsLFxuXHRcdHBhc3N3b3JkOiBudWxsLFxuXHRcdGNhY2hlOiBudWxsLFxuXHRcdHRocm93czogZmFsc2UsXG5cdFx0dHJhZGl0aW9uYWw6IGZhbHNlLFxuXHRcdGhlYWRlcnM6IHt9LFxuXHRcdCovXG5cblx0XHRhY2NlcHRzOiB7XG5cdFx0XHRcIipcIjogYWxsVHlwZXMsXG5cdFx0XHR0ZXh0OiBcInRleHQvcGxhaW5cIixcblx0XHRcdGh0bWw6IFwidGV4dC9odG1sXCIsXG5cdFx0XHR4bWw6IFwiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbFwiLFxuXHRcdFx0anNvbjogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIlxuXHRcdH0sXG5cblx0XHRjb250ZW50czoge1xuXHRcdFx0eG1sOiAvXFxieG1sXFxiLyxcblx0XHRcdGh0bWw6IC9cXGJodG1sLyxcblx0XHRcdGpzb246IC9cXGJqc29uXFxiL1xuXHRcdH0sXG5cblx0XHRyZXNwb25zZUZpZWxkczoge1xuXHRcdFx0eG1sOiBcInJlc3BvbnNlWE1MXCIsXG5cdFx0XHR0ZXh0OiBcInJlc3BvbnNlVGV4dFwiLFxuXHRcdFx0anNvbjogXCJyZXNwb25zZUpTT05cIlxuXHRcdH0sXG5cblx0XHQvLyBEYXRhIGNvbnZlcnRlcnNcblx0XHQvLyBLZXlzIHNlcGFyYXRlIHNvdXJjZSAob3IgY2F0Y2hhbGwgXCIqXCIpIGFuZCBkZXN0aW5hdGlvbiB0eXBlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG5cdFx0Y29udmVydGVyczoge1xuXG5cdFx0XHQvLyBDb252ZXJ0IGFueXRoaW5nIHRvIHRleHRcblx0XHRcdFwiKiB0ZXh0XCI6IFN0cmluZyxcblxuXHRcdFx0Ly8gVGV4dCB0byBodG1sICh0cnVlID0gbm8gdHJhbnNmb3JtYXRpb24pXG5cdFx0XHRcInRleHQgaHRtbFwiOiB0cnVlLFxuXG5cdFx0XHQvLyBFdmFsdWF0ZSB0ZXh0IGFzIGEganNvbiBleHByZXNzaW9uXG5cdFx0XHRcInRleHQganNvblwiOiBKU09OLnBhcnNlLFxuXG5cdFx0XHQvLyBQYXJzZSB0ZXh0IGFzIHhtbFxuXHRcdFx0XCJ0ZXh0IHhtbFwiOiBqUXVlcnkucGFyc2VYTUxcblx0XHR9LFxuXG5cdFx0Ly8gRm9yIG9wdGlvbnMgdGhhdCBzaG91bGRuJ3QgYmUgZGVlcCBleHRlbmRlZDpcblx0XHQvLyB5b3UgY2FuIGFkZCB5b3VyIG93biBjdXN0b20gb3B0aW9ucyBoZXJlIGlmXG5cdFx0Ly8gYW5kIHdoZW4geW91IGNyZWF0ZSBvbmUgdGhhdCBzaG91bGRuJ3QgYmVcblx0XHQvLyBkZWVwIGV4dGVuZGVkIChzZWUgYWpheEV4dGVuZClcblx0XHRmbGF0T3B0aW9uczoge1xuXHRcdFx0dXJsOiB0cnVlLFxuXHRcdFx0Y29udGV4dDogdHJ1ZVxuXHRcdH1cblx0fSxcblxuXHQvLyBDcmVhdGVzIGEgZnVsbCBmbGVkZ2VkIHNldHRpbmdzIG9iamVjdCBpbnRvIHRhcmdldFxuXHQvLyB3aXRoIGJvdGggYWpheFNldHRpbmdzIGFuZCBzZXR0aW5ncyBmaWVsZHMuXG5cdC8vIElmIHRhcmdldCBpcyBvbWl0dGVkLCB3cml0ZXMgaW50byBhamF4U2V0dGluZ3MuXG5cdGFqYXhTZXR1cDogZnVuY3Rpb24oIHRhcmdldCwgc2V0dGluZ3MgKSB7XG5cdFx0cmV0dXJuIHNldHRpbmdzID9cblxuXHRcdFx0Ly8gQnVpbGRpbmcgYSBzZXR0aW5ncyBvYmplY3Rcblx0XHRcdGFqYXhFeHRlbmQoIGFqYXhFeHRlbmQoIHRhcmdldCwgalF1ZXJ5LmFqYXhTZXR0aW5ncyApLCBzZXR0aW5ncyApIDpcblxuXHRcdFx0Ly8gRXh0ZW5kaW5nIGFqYXhTZXR0aW5nc1xuXHRcdFx0YWpheEV4dGVuZCggalF1ZXJ5LmFqYXhTZXR0aW5ncywgdGFyZ2V0ICk7XG5cdH0sXG5cblx0YWpheFByZWZpbHRlcjogYWRkVG9QcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBwcmVmaWx0ZXJzICksXG5cdGFqYXhUcmFuc3BvcnQ6IGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cyApLFxuXG5cdC8vIE1haW4gbWV0aG9kXG5cdGFqYXg6IGZ1bmN0aW9uKCB1cmwsIG9wdGlvbnMgKSB7XG5cblx0XHQvLyBJZiB1cmwgaXMgYW4gb2JqZWN0LCBzaW11bGF0ZSBwcmUtMS41IHNpZ25hdHVyZVxuXHRcdGlmICggdHlwZW9mIHVybCA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdG9wdGlvbnMgPSB1cmw7XG5cdFx0XHR1cmwgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gRm9yY2Ugb3B0aW9ucyB0byBiZSBhbiBvYmplY3Rcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdHZhciB0cmFuc3BvcnQsXG5cblx0XHRcdC8vIFVSTCB3aXRob3V0IGFudGktY2FjaGUgcGFyYW1cblx0XHRcdGNhY2hlVVJMLFxuXG5cdFx0XHQvLyBSZXNwb25zZSBoZWFkZXJzXG5cdFx0XHRyZXNwb25zZUhlYWRlcnNTdHJpbmcsXG5cdFx0XHRyZXNwb25zZUhlYWRlcnMsXG5cblx0XHRcdC8vIHRpbWVvdXQgaGFuZGxlXG5cdFx0XHR0aW1lb3V0VGltZXIsXG5cblx0XHRcdC8vIFVybCBjbGVhbnVwIHZhclxuXHRcdFx0dXJsQW5jaG9yLFxuXG5cdFx0XHQvLyBSZXF1ZXN0IHN0YXRlIChiZWNvbWVzIGZhbHNlIHVwb24gc2VuZCBhbmQgdHJ1ZSB1cG9uIGNvbXBsZXRpb24pXG5cdFx0XHRjb21wbGV0ZWQsXG5cblx0XHRcdC8vIFRvIGtub3cgaWYgZ2xvYmFsIGV2ZW50cyBhcmUgdG8gYmUgZGlzcGF0Y2hlZFxuXHRcdFx0ZmlyZUdsb2JhbHMsXG5cblx0XHRcdC8vIExvb3AgdmFyaWFibGVcblx0XHRcdGksXG5cblx0XHRcdC8vIHVuY2FjaGVkIHBhcnQgb2YgdGhlIHVybFxuXHRcdFx0dW5jYWNoZWQsXG5cblx0XHRcdC8vIENyZWF0ZSB0aGUgZmluYWwgb3B0aW9ucyBvYmplY3Rcblx0XHRcdHMgPSBqUXVlcnkuYWpheFNldHVwKCB7fSwgb3B0aW9ucyApLFxuXG5cdFx0XHQvLyBDYWxsYmFja3MgY29udGV4dFxuXHRcdFx0Y2FsbGJhY2tDb250ZXh0ID0gcy5jb250ZXh0IHx8IHMsXG5cblx0XHRcdC8vIENvbnRleHQgZm9yIGdsb2JhbCBldmVudHMgaXMgY2FsbGJhY2tDb250ZXh0IGlmIGl0IGlzIGEgRE9NIG5vZGUgb3IgalF1ZXJ5IGNvbGxlY3Rpb25cblx0XHRcdGdsb2JhbEV2ZW50Q29udGV4dCA9IHMuY29udGV4dCAmJlxuXHRcdFx0XHQoIGNhbGxiYWNrQ29udGV4dC5ub2RlVHlwZSB8fCBjYWxsYmFja0NvbnRleHQuanF1ZXJ5ICkgP1xuXHRcdFx0XHRcdGpRdWVyeSggY2FsbGJhY2tDb250ZXh0ICkgOlxuXHRcdFx0XHRcdGpRdWVyeS5ldmVudCxcblxuXHRcdFx0Ly8gRGVmZXJyZWRzXG5cdFx0XHRkZWZlcnJlZCA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZCA9IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXG5cdFx0XHQvLyBTdGF0dXMtZGVwZW5kZW50IGNhbGxiYWNrc1xuXHRcdFx0c3RhdHVzQ29kZSA9IHMuc3RhdHVzQ29kZSB8fCB7fSxcblxuXHRcdFx0Ly8gSGVhZGVycyAodGhleSBhcmUgc2VudCBhbGwgYXQgb25jZSlcblx0XHRcdHJlcXVlc3RIZWFkZXJzID0ge30sXG5cdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzID0ge30sXG5cblx0XHRcdC8vIERlZmF1bHQgYWJvcnQgbWVzc2FnZVxuXHRcdFx0c3RyQWJvcnQgPSBcImNhbmNlbGVkXCIsXG5cblx0XHRcdC8vIEZha2UgeGhyXG5cdFx0XHRqcVhIUiA9IHtcblx0XHRcdFx0cmVhZHlTdGF0ZTogMCxcblxuXHRcdFx0XHQvLyBCdWlsZHMgaGVhZGVycyBoYXNodGFibGUgaWYgbmVlZGVkXG5cdFx0XHRcdGdldFJlc3BvbnNlSGVhZGVyOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdFx0XHRcdHZhciBtYXRjaDtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHRcdGlmICggIXJlc3BvbnNlSGVhZGVycyApIHtcblx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzID0ge307XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggKCBtYXRjaCA9IHJoZWFkZXJzLmV4ZWMoIHJlc3BvbnNlSGVhZGVyc1N0cmluZyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzWyBtYXRjaFsgMSBdLnRvTG93ZXJDYXNlKCkgXSA9IG1hdGNoWyAyIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1hdGNoID0gcmVzcG9uc2VIZWFkZXJzWyBrZXkudG9Mb3dlckNhc2UoKSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2ggPT0gbnVsbCA/IG51bGwgOiBtYXRjaDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBSYXcgc3RyaW5nXG5cdFx0XHRcdGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNvbXBsZXRlZCA/IHJlc3BvbnNlSGVhZGVyc1N0cmluZyA6IG51bGw7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gQ2FjaGVzIHRoZSBoZWFkZXJcblx0XHRcdFx0c2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRuYW1lID0gcmVxdWVzdEhlYWRlcnNOYW1lc1sgbmFtZS50b0xvd2VyQ2FzZSgpIF0gPVxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSB8fCBuYW1lO1xuXHRcdFx0XHRcdFx0cmVxdWVzdEhlYWRlcnNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBPdmVycmlkZXMgcmVzcG9uc2UgY29udGVudC10eXBlIGhlYWRlclxuXHRcdFx0XHRvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0cy5taW1lVHlwZSA9IHR5cGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRcdHN0YXR1c0NvZGU6IGZ1bmN0aW9uKCBtYXAgKSB7XG5cdFx0XHRcdFx0dmFyIGNvZGU7XG5cdFx0XHRcdFx0aWYgKCBtYXAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBFeGVjdXRlIHRoZSBhcHByb3ByaWF0ZSBjYWxsYmFja3Ncblx0XHRcdFx0XHRcdFx0anFYSFIuYWx3YXlzKCBtYXBbIGpxWEhSLnN0YXR1cyBdICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdC8vIExhenktYWRkIHRoZSBuZXcgY2FsbGJhY2tzIGluIGEgd2F5IHRoYXQgcHJlc2VydmVzIG9sZCBvbmVzXG5cdFx0XHRcdFx0XHRcdGZvciAoIGNvZGUgaW4gbWFwICkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0NvZGVbIGNvZGUgXSA9IFsgc3RhdHVzQ29kZVsgY29kZSBdLCBtYXBbIGNvZGUgXSBdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIENhbmNlbCB0aGUgcmVxdWVzdFxuXHRcdFx0XHRhYm9ydDogZnVuY3Rpb24oIHN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0dmFyIGZpbmFsVGV4dCA9IHN0YXR1c1RleHQgfHwgc3RyQWJvcnQ7XG5cdFx0XHRcdFx0aWYgKCB0cmFuc3BvcnQgKSB7XG5cdFx0XHRcdFx0XHR0cmFuc3BvcnQuYWJvcnQoIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkb25lKCAwLCBmaW5hbFRleHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdC8vIEF0dGFjaCBkZWZlcnJlZHNcblx0XHRkZWZlcnJlZC5wcm9taXNlKCBqcVhIUiApO1xuXG5cdFx0Ly8gQWRkIHByb3RvY29sIGlmIG5vdCBwcm92aWRlZCAocHJlZmlsdGVycyBtaWdodCBleHBlY3QgaXQpXG5cdFx0Ly8gSGFuZGxlIGZhbHN5IHVybCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0ICgjMTAwOTM6IGNvbnNpc3RlbmN5IHdpdGggb2xkIHNpZ25hdHVyZSlcblx0XHQvLyBXZSBhbHNvIHVzZSB0aGUgdXJsIHBhcmFtZXRlciBpZiBhdmFpbGFibGVcblx0XHRzLnVybCA9ICggKCB1cmwgfHwgcy51cmwgfHwgbG9jYXRpb24uaHJlZiApICsgXCJcIiApXG5cdFx0XHQucmVwbGFjZSggcnByb3RvY29sLCBsb2NhdGlvbi5wcm90b2NvbCArIFwiLy9cIiApO1xuXG5cdFx0Ly8gQWxpYXMgbWV0aG9kIG9wdGlvbiB0byB0eXBlIGFzIHBlciB0aWNrZXQgIzEyMDA0XG5cdFx0cy50eXBlID0gb3B0aW9ucy5tZXRob2QgfHwgb3B0aW9ucy50eXBlIHx8IHMubWV0aG9kIHx8IHMudHlwZTtcblxuXHRcdC8vIEV4dHJhY3QgZGF0YVR5cGVzIGxpc3Rcblx0XHRzLmRhdGFUeXBlcyA9ICggcy5kYXRhVHlwZSB8fCBcIipcIiApLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblxuXHRcdC8vIEEgY3Jvc3MtZG9tYWluIHJlcXVlc3QgaXMgaW4gb3JkZXIgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgb3JpZ2luLlxuXHRcdGlmICggcy5jcm9zc0RvbWFpbiA9PSBudWxsICkge1xuXHRcdFx0dXJsQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHRcdFx0Ly8gSUUgdGhyb3dzIGV4Y2VwdGlvbiBvbiBhY2Nlc3NpbmcgdGhlIGhyZWYgcHJvcGVydHkgaWYgdXJsIGlzIG1hbGZvcm1lZCxcblx0XHRcdC8vIGUuZy4gaHR0cDovL2V4YW1wbGUuY29tOjgweC9cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHVybEFuY2hvci5ocmVmID0gcy51cmw7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEgb25seVxuXHRcdFx0XHQvLyBBbmNob3IncyBob3N0IHByb3BlcnR5IGlzbid0IGNvcnJlY3RseSBzZXQgd2hlbiBzLnVybCBpcyByZWxhdGl2ZVxuXHRcdFx0XHR1cmxBbmNob3IuaHJlZiA9IHVybEFuY2hvci5ocmVmO1xuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gb3JpZ2luQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgb3JpZ2luQW5jaG9yLmhvc3QgIT09XG5cdFx0XHRcdFx0dXJsQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgdXJsQW5jaG9yLmhvc3Q7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhbiBlcnJvciBwYXJzaW5nIHRoZSBVUkwsIGFzc3VtZSBpdCBpcyBjcm9zc0RvbWFpbixcblx0XHRcdFx0Ly8gaXQgY2FuIGJlIHJlamVjdGVkIGJ5IHRoZSB0cmFuc3BvcnQgaWYgaXQgaXMgaW52YWxpZFxuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcblx0XHRpZiAoIHMuZGF0YSAmJiBzLnByb2Nlc3NEYXRhICYmIHR5cGVvZiBzLmRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRzLmRhdGEgPSBqUXVlcnkucGFyYW0oIHMuZGF0YSwgcy50cmFkaXRpb25hbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHByZWZpbHRlcnNcblx0XHRpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGEgcHJlZmlsdGVyLCBzdG9wIHRoZXJlXG5cdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4ganFYSFI7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgY2FuIGZpcmUgZ2xvYmFsIGV2ZW50cyBhcyBvZiBub3cgaWYgYXNrZWQgdG9cblx0XHQvLyBEb24ndCBmaXJlIGV2ZW50cyBpZiBqUXVlcnkuZXZlbnQgaXMgdW5kZWZpbmVkIGluIGFuIEFNRC11c2FnZSBzY2VuYXJpbyAoIzE1MTE4KVxuXHRcdGZpcmVHbG9iYWxzID0galF1ZXJ5LmV2ZW50ICYmIHMuZ2xvYmFsO1xuXG5cdFx0Ly8gV2F0Y2ggZm9yIGEgbmV3IHNldCBvZiByZXF1ZXN0c1xuXHRcdGlmICggZmlyZUdsb2JhbHMgJiYgalF1ZXJ5LmFjdGl2ZSsrID09PSAwICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIFwiYWpheFN0YXJ0XCIgKTtcblx0XHR9XG5cblx0XHQvLyBVcHBlcmNhc2UgdGhlIHR5cGVcblx0XHRzLnR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTtcblxuXHRcdC8vIERldGVybWluZSBpZiByZXF1ZXN0IGhhcyBjb250ZW50XG5cdFx0cy5oYXNDb250ZW50ID0gIXJub0NvbnRlbnQudGVzdCggcy50eXBlICk7XG5cblx0XHQvLyBTYXZlIHRoZSBVUkwgaW4gY2FzZSB3ZSdyZSB0b3lpbmcgd2l0aCB0aGUgSWYtTW9kaWZpZWQtU2luY2Vcblx0XHQvLyBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIgbGF0ZXIgb25cblx0XHQvLyBSZW1vdmUgaGFzaCB0byBzaW1wbGlmeSB1cmwgbWFuaXB1bGF0aW9uXG5cdFx0Y2FjaGVVUkwgPSBzLnVybC5yZXBsYWNlKCByaGFzaCwgXCJcIiApO1xuXG5cdFx0Ly8gTW9yZSBvcHRpb25zIGhhbmRsaW5nIGZvciByZXF1ZXN0cyB3aXRoIG5vIGNvbnRlbnRcblx0XHRpZiAoICFzLmhhc0NvbnRlbnQgKSB7XG5cblx0XHRcdC8vIFJlbWVtYmVyIHRoZSBoYXNoIHNvIHdlIGNhbiBwdXQgaXQgYmFja1xuXHRcdFx0dW5jYWNoZWQgPSBzLnVybC5zbGljZSggY2FjaGVVUkwubGVuZ3RoICk7XG5cblx0XHRcdC8vIElmIGRhdGEgaXMgYXZhaWxhYmxlLCBhcHBlbmQgZGF0YSB0byB1cmxcblx0XHRcdGlmICggcy5kYXRhICkge1xuXHRcdFx0XHRjYWNoZVVSTCArPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgcy5kYXRhO1xuXG5cdFx0XHRcdC8vICM5NjgyOiByZW1vdmUgZGF0YSBzbyB0aGF0IGl0J3Mgbm90IHVzZWQgaW4gYW4gZXZlbnR1YWwgcmV0cnlcblx0XHRcdFx0ZGVsZXRlIHMuZGF0YTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9yIHVwZGF0ZSBhbnRpLWNhY2hlIHBhcmFtIGlmIG5lZWRlZFxuXHRcdFx0aWYgKCBzLmNhY2hlID09PSBmYWxzZSApIHtcblx0XHRcdFx0Y2FjaGVVUkwgPSBjYWNoZVVSTC5yZXBsYWNlKCByYW50aUNhY2hlLCBcIiQxXCIgKTtcblx0XHRcdFx0dW5jYWNoZWQgPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgXCJfPVwiICsgKCBub25jZSsrICkgKyB1bmNhY2hlZDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUHV0IGhhc2ggYW5kIGFudGktY2FjaGUgb24gdGhlIFVSTCB0aGF0IHdpbGwgYmUgcmVxdWVzdGVkIChnaC0xNzMyKVxuXHRcdFx0cy51cmwgPSBjYWNoZVVSTCArIHVuY2FjaGVkO1xuXG5cdFx0Ly8gQ2hhbmdlICclMjAnIHRvICcrJyBpZiB0aGlzIGlzIGVuY29kZWQgZm9ybSBib2R5IGNvbnRlbnQgKGdoLTI2NTgpXG5cdFx0fSBlbHNlIGlmICggcy5kYXRhICYmIHMucHJvY2Vzc0RhdGEgJiZcblx0XHRcdCggcy5jb250ZW50VHlwZSB8fCBcIlwiICkuaW5kZXhPZiggXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiApID09PSAwICkge1xuXHRcdFx0cy5kYXRhID0gcy5kYXRhLnJlcGxhY2UoIHIyMCwgXCIrXCIgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdGhlIElmLU1vZGlmaWVkLVNpbmNlIGFuZC9vciBJZi1Ob25lLU1hdGNoIGhlYWRlciwgaWYgaW4gaWZNb2RpZmllZCBtb2RlLlxuXHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0aWYgKCBqUXVlcnkubGFzdE1vZGlmaWVkWyBjYWNoZVVSTCBdICkge1xuXHRcdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIklmLU1vZGlmaWVkLVNpbmNlXCIsIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKTtcblx0XHRcdH1cblx0XHRcdGlmICggalF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTm9uZS1NYXRjaFwiLCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgY29ycmVjdCBoZWFkZXIsIGlmIGRhdGEgaXMgYmVpbmcgc2VudFxuXHRcdGlmICggcy5kYXRhICYmIHMuaGFzQ29udGVudCAmJiBzLmNvbnRlbnRUeXBlICE9PSBmYWxzZSB8fCBvcHRpb25zLmNvbnRlbnRUeXBlICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJDb250ZW50LVR5cGVcIiwgcy5jb250ZW50VHlwZSApO1xuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgQWNjZXB0cyBoZWFkZXIgZm9yIHRoZSBzZXJ2ZXIsIGRlcGVuZGluZyBvbiB0aGUgZGF0YVR5cGVcblx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKFxuXHRcdFx0XCJBY2NlcHRcIixcblx0XHRcdHMuZGF0YVR5cGVzWyAwIF0gJiYgcy5hY2NlcHRzWyBzLmRhdGFUeXBlc1sgMCBdIF0gP1xuXHRcdFx0XHRzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWyAwIF0gXSArXG5cdFx0XHRcdFx0KCBzLmRhdGFUeXBlc1sgMCBdICE9PSBcIipcIiA/IFwiLCBcIiArIGFsbFR5cGVzICsgXCI7IHE9MC4wMVwiIDogXCJcIiApIDpcblx0XHRcdFx0cy5hY2NlcHRzWyBcIipcIiBdXG5cdFx0KTtcblxuXHRcdC8vIENoZWNrIGZvciBoZWFkZXJzIG9wdGlvblxuXHRcdGZvciAoIGkgaW4gcy5oZWFkZXJzICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggaSwgcy5oZWFkZXJzWyBpIF0gKTtcblx0XHR9XG5cblx0XHQvLyBBbGxvdyBjdXN0b20gaGVhZGVycy9taW1ldHlwZXMgYW5kIGVhcmx5IGFib3J0XG5cdFx0aWYgKCBzLmJlZm9yZVNlbmQgJiZcblx0XHRcdCggcy5iZWZvcmVTZW5kLmNhbGwoIGNhbGxiYWNrQ29udGV4dCwganFYSFIsIHMgKSA9PT0gZmFsc2UgfHwgY29tcGxldGVkICkgKSB7XG5cblx0XHRcdC8vIEFib3J0IGlmIG5vdCBkb25lIGFscmVhZHkgYW5kIHJldHVyblxuXHRcdFx0cmV0dXJuIGpxWEhSLmFib3J0KCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWJvcnRpbmcgaXMgbm8gbG9uZ2VyIGEgY2FuY2VsbGF0aW9uXG5cdFx0c3RyQWJvcnQgPSBcImFib3J0XCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrcyBvbiBkZWZlcnJlZHNcblx0XHRjb21wbGV0ZURlZmVycmVkLmFkZCggcy5jb21wbGV0ZSApO1xuXHRcdGpxWEhSLmRvbmUoIHMuc3VjY2VzcyApO1xuXHRcdGpxWEhSLmZhaWwoIHMuZXJyb3IgKTtcblxuXHRcdC8vIEdldCB0cmFuc3BvcnRcblx0XHR0cmFuc3BvcnQgPSBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIG5vIHRyYW5zcG9ydCwgd2UgYXV0by1hYm9ydFxuXHRcdGlmICggIXRyYW5zcG9ydCApIHtcblx0XHRcdGRvbmUoIC0xLCBcIk5vIFRyYW5zcG9ydFwiICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSAxO1xuXG5cdFx0XHQvLyBTZW5kIGdsb2JhbCBldmVudFxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheFNlbmRcIiwgWyBqcVhIUiwgcyBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGFqYXhTZW5kLCBzdG9wIHRoZXJlXG5cdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0cmV0dXJuIGpxWEhSO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaW1lb3V0XG5cdFx0XHRpZiAoIHMuYXN5bmMgJiYgcy50aW1lb3V0ID4gMCApIHtcblx0XHRcdFx0dGltZW91dFRpbWVyID0gd2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGpxWEhSLmFib3J0KCBcInRpbWVvdXRcIiApO1xuXHRcdFx0XHR9LCBzLnRpbWVvdXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29tcGxldGVkID0gZmFsc2U7XG5cdFx0XHRcdHRyYW5zcG9ydC5zZW5kKCByZXF1ZXN0SGVhZGVycywgZG9uZSApO1xuXHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0Ly8gUmV0aHJvdyBwb3N0LWNvbXBsZXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHR0aHJvdyBlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUHJvcGFnYXRlIG90aGVycyBhcyByZXN1bHRzXG5cdFx0XHRcdGRvbmUoIC0xLCBlICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGJhY2sgZm9yIHdoZW4gZXZlcnl0aGluZyBpcyBkb25lXG5cdFx0ZnVuY3Rpb24gZG9uZSggc3RhdHVzLCBuYXRpdmVTdGF0dXNUZXh0LCByZXNwb25zZXMsIGhlYWRlcnMgKSB7XG5cdFx0XHR2YXIgaXNTdWNjZXNzLCBzdWNjZXNzLCBlcnJvciwgcmVzcG9uc2UsIG1vZGlmaWVkLFxuXHRcdFx0XHRzdGF0dXNUZXh0ID0gbmF0aXZlU3RhdHVzVGV4dDtcblxuXHRcdFx0Ly8gSWdub3JlIHJlcGVhdCBpbnZvY2F0aW9uc1xuXHRcdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gQ2xlYXIgdGltZW91dCBpZiBpdCBleGlzdHNcblx0XHRcdGlmICggdGltZW91dFRpbWVyICkge1xuXHRcdFx0XHR3aW5kb3cuY2xlYXJUaW1lb3V0KCB0aW1lb3V0VGltZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRGVyZWZlcmVuY2UgdHJhbnNwb3J0IGZvciBlYXJseSBnYXJiYWdlIGNvbGxlY3Rpb25cblx0XHRcdC8vIChubyBtYXR0ZXIgaG93IGxvbmcgdGhlIGpxWEhSIG9iamVjdCB3aWxsIGJlIHVzZWQpXG5cdFx0XHR0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHRcdC8vIENhY2hlIHJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyA9IGhlYWRlcnMgfHwgXCJcIjtcblxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGVcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSBzdGF0dXMgPiAwID8gNCA6IDA7XG5cblx0XHRcdC8vIERldGVybWluZSBpZiBzdWNjZXNzZnVsXG5cdFx0XHRpc1N1Y2Nlc3MgPSBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDtcblxuXHRcdFx0Ly8gR2V0IHJlc3BvbnNlIGRhdGFcblx0XHRcdGlmICggcmVzcG9uc2VzICkge1xuXHRcdFx0XHRyZXNwb25zZSA9IGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udmVydCBubyBtYXR0ZXIgd2hhdCAodGhhdCB3YXkgcmVzcG9uc2VYWFggZmllbGRzIGFyZSBhbHdheXMgc2V0KVxuXHRcdFx0cmVzcG9uc2UgPSBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKTtcblxuXHRcdFx0Ly8gSWYgc3VjY2Vzc2Z1bCwgaGFuZGxlIHR5cGUgY2hhaW5pbmdcblx0XHRcdGlmICggaXNTdWNjZXNzICkge1xuXG5cdFx0XHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0XHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiTGFzdC1Nb2RpZmllZFwiICk7XG5cdFx0XHRcdFx0aWYgKCBtb2RpZmllZCApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bW9kaWZpZWQgPSBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJldGFnXCIgKTtcblx0XHRcdFx0XHRpZiAoIG1vZGlmaWVkICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpZiBubyBjb250ZW50XG5cdFx0XHRcdGlmICggc3RhdHVzID09PSAyMDQgfHwgcy50eXBlID09PSBcIkhFQURcIiApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub2NvbnRlbnRcIjtcblxuXHRcdFx0XHQvLyBpZiBub3QgbW9kaWZpZWRcblx0XHRcdFx0fSBlbHNlIGlmICggc3RhdHVzID09PSAzMDQgKSB7XG5cdFx0XHRcdFx0c3RhdHVzVGV4dCA9IFwibm90bW9kaWZpZWRcIjtcblxuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGRhdGEsIGxldCdzIGNvbnZlcnQgaXRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gcmVzcG9uc2Uuc3RhdGU7XG5cdFx0XHRcdFx0c3VjY2VzcyA9IHJlc3BvbnNlLmRhdGE7XG5cdFx0XHRcdFx0ZXJyb3IgPSByZXNwb25zZS5lcnJvcjtcblx0XHRcdFx0XHRpc1N1Y2Nlc3MgPSAhZXJyb3I7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gRXh0cmFjdCBlcnJvciBmcm9tIHN0YXR1c1RleHQgYW5kIG5vcm1hbGl6ZSBmb3Igbm9uLWFib3J0c1xuXHRcdFx0XHRlcnJvciA9IHN0YXR1c1RleHQ7XG5cdFx0XHRcdGlmICggc3RhdHVzIHx8ICFzdGF0dXNUZXh0ICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcImVycm9yXCI7XG5cdFx0XHRcdFx0aWYgKCBzdGF0dXMgPCAwICkge1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGRhdGEgZm9yIHRoZSBmYWtlIHhociBvYmplY3Rcblx0XHRcdGpxWEhSLnN0YXR1cyA9IHN0YXR1cztcblx0XHRcdGpxWEhSLnN0YXR1c1RleHQgPSAoIG5hdGl2ZVN0YXR1c1RleHQgfHwgc3RhdHVzVGV4dCApICsgXCJcIjtcblxuXHRcdFx0Ly8gU3VjY2Vzcy9FcnJvclxuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsgc3VjY2Vzcywgc3RhdHVzVGV4dCwganFYSFIgXSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0LCBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRqcVhIUi5zdGF0dXNDb2RlKCBzdGF0dXNDb2RlICk7XG5cdFx0XHRzdGF0dXNDb2RlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggaXNTdWNjZXNzID8gXCJhamF4U3VjY2Vzc1wiIDogXCJhamF4RXJyb3JcIixcblx0XHRcdFx0XHRbIGpxWEhSLCBzLCBpc1N1Y2Nlc3MgPyBzdWNjZXNzIDogZXJyb3IgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb21wbGV0ZVxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZC5maXJlV2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0IF0gKTtcblxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheENvbXBsZXRlXCIsIFsganFYSFIsIHMgXSApO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSB0aGUgZ2xvYmFsIEFKQVggY291bnRlclxuXHRcdFx0XHRpZiAoICEoIC0talF1ZXJ5LmFjdGl2ZSApICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCBcImFqYXhTdG9wXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBqcVhIUjtcblx0fSxcblxuXHRnZXRKU09OOiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdldCggdXJsLCBkYXRhLCBjYWxsYmFjaywgXCJqc29uXCIgKTtcblx0fSxcblxuXHRnZXRTY3JpcHQ6IGZ1bmN0aW9uKCB1cmwsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIHVuZGVmaW5lZCwgY2FsbGJhY2ssIFwic2NyaXB0XCIgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImdldFwiLCBcInBvc3RcIiBdLCBmdW5jdGlvbiggaSwgbWV0aG9kICkge1xuXHRqUXVlcnlbIG1ldGhvZCBdID0gZnVuY3Rpb24oIHVybCwgZGF0YSwgY2FsbGJhY2ssIHR5cGUgKSB7XG5cblx0XHQvLyBTaGlmdCBhcmd1bWVudHMgaWYgZGF0YSBhcmd1bWVudCB3YXMgb21pdHRlZFxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGRhdGEgKSApIHtcblx0XHRcdHR5cGUgPSB0eXBlIHx8IGNhbGxiYWNrO1xuXHRcdFx0Y2FsbGJhY2sgPSBkYXRhO1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBUaGUgdXJsIGNhbiBiZSBhbiBvcHRpb25zIG9iamVjdCAod2hpY2ggdGhlbiBtdXN0IGhhdmUgLnVybClcblx0XHRyZXR1cm4galF1ZXJ5LmFqYXgoIGpRdWVyeS5leHRlbmQoIHtcblx0XHRcdHVybDogdXJsLFxuXHRcdFx0dHlwZTogbWV0aG9kLFxuXHRcdFx0ZGF0YVR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhOiBkYXRhLFxuXHRcdFx0c3VjY2VzczogY2FsbGJhY2tcblx0XHR9LCBqUXVlcnkuaXNQbGFpbk9iamVjdCggdXJsICkgJiYgdXJsICkgKTtcblx0fTtcbn0gKTtcblxuXG5qUXVlcnkuX2V2YWxVcmwgPSBmdW5jdGlvbiggdXJsICkge1xuXHRyZXR1cm4galF1ZXJ5LmFqYXgoIHtcblx0XHR1cmw6IHVybCxcblxuXHRcdC8vIE1ha2UgdGhpcyBleHBsaWNpdCwgc2luY2UgdXNlciBjYW4gb3ZlcnJpZGUgdGhpcyB0aHJvdWdoIGFqYXhTZXR1cCAoIzExMjY0KVxuXHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0ZGF0YVR5cGU6IFwic2NyaXB0XCIsXG5cdFx0Y2FjaGU6IHRydWUsXG5cdFx0YXN5bmM6IGZhbHNlLFxuXHRcdGdsb2JhbDogZmFsc2UsXG5cdFx0XCJ0aHJvd3NcIjogdHJ1ZVxuXHR9ICk7XG59O1xuXG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0d3JhcEFsbDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIHdyYXA7XG5cblx0XHRpZiAoIHRoaXNbIDAgXSApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdFx0aHRtbCA9IGh0bWwuY2FsbCggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoZSBlbGVtZW50cyB0byB3cmFwIHRoZSB0YXJnZXQgYXJvdW5kXG5cdFx0XHR3cmFwID0galF1ZXJ5KCBodG1sLCB0aGlzWyAwIF0ub3duZXJEb2N1bWVudCApLmVxKCAwICkuY2xvbmUoIHRydWUgKTtcblxuXHRcdFx0aWYgKCB0aGlzWyAwIF0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0d3JhcC5pbnNlcnRCZWZvcmUoIHRoaXNbIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHR3cmFwLm1hcCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBlbGVtID0gdGhpcztcblxuXHRcdFx0XHR3aGlsZSAoIGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQgKSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gZWxlbTtcblx0XHRcdH0gKS5hcHBlbmQoIHRoaXMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwSW5uZXIoIGh0bWwuY2FsbCggdGhpcywgaSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgc2VsZiA9IGpRdWVyeSggdGhpcyApLFxuXHRcdFx0XHRjb250ZW50cyA9IHNlbGYuY29udGVudHMoKTtcblxuXHRcdFx0aWYgKCBjb250ZW50cy5sZW5ndGggKSB7XG5cdFx0XHRcdGNvbnRlbnRzLndyYXBBbGwoIGh0bWwgKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi5hcHBlbmQoIGh0bWwgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0d3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwQWxsKCBpc0Z1bmN0aW9uID8gaHRtbC5jYWxsKCB0aGlzLCBpICkgOiBodG1sICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdHVud3JhcDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHRoaXMucGFyZW50KCBzZWxlY3RvciApLm5vdCggXCJib2R5XCIgKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLnJlcGxhY2VXaXRoKCB0aGlzLmNoaWxkTm9kZXMgKTtcblx0XHR9ICk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gIWpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSggZWxlbSApO1xufTtcbmpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gISEoIGVsZW0ub2Zmc2V0V2lkdGggfHwgZWxlbS5vZmZzZXRIZWlnaHQgfHwgZWxlbS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCApO1xufTtcblxuXG5cblxualF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIgPSBmdW5jdGlvbigpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbmV3IHdpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuXHR9IGNhdGNoICggZSApIHt9XG59O1xuXG52YXIgeGhyU3VjY2Vzc1N0YXR1cyA9IHtcblxuXHRcdC8vIEZpbGUgcHJvdG9jb2wgYWx3YXlzIHlpZWxkcyBzdGF0dXMgY29kZSAwLCBhc3N1bWUgMjAwXG5cdFx0MDogMjAwLFxuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHQvLyAjMTQ1MDogc29tZXRpbWVzIElFIHJldHVybnMgMTIyMyB3aGVuIGl0IHNob3VsZCBiZSAyMDRcblx0XHQxMjIzOiAyMDRcblx0fSxcblx0eGhyU3VwcG9ydGVkID0galF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIoKTtcblxuc3VwcG9ydC5jb3JzID0gISF4aHJTdXBwb3J0ZWQgJiYgKCBcIndpdGhDcmVkZW50aWFsc1wiIGluIHhoclN1cHBvcnRlZCApO1xuc3VwcG9ydC5hamF4ID0geGhyU3VwcG9ydGVkID0gISF4aHJTdXBwb3J0ZWQ7XG5cbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0dmFyIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrO1xuXG5cdC8vIENyb3NzIGRvbWFpbiBvbmx5IGFsbG93ZWQgaWYgc3VwcG9ydGVkIHRocm91Z2ggWE1MSHR0cFJlcXVlc3Rcblx0aWYgKCBzdXBwb3J0LmNvcnMgfHwgeGhyU3VwcG9ydGVkICYmICFvcHRpb25zLmNyb3NzRG9tYWluICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRzZW5kOiBmdW5jdGlvbiggaGVhZGVycywgY29tcGxldGUgKSB7XG5cdFx0XHRcdHZhciBpLFxuXHRcdFx0XHRcdHhociA9IG9wdGlvbnMueGhyKCk7XG5cblx0XHRcdFx0eGhyLm9wZW4oXG5cdFx0XHRcdFx0b3B0aW9ucy50eXBlLFxuXHRcdFx0XHRcdG9wdGlvbnMudXJsLFxuXHRcdFx0XHRcdG9wdGlvbnMuYXN5bmMsXG5cdFx0XHRcdFx0b3B0aW9ucy51c2VybmFtZSxcblx0XHRcdFx0XHRvcHRpb25zLnBhc3N3b3JkXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gQXBwbHkgY3VzdG9tIGZpZWxkcyBpZiBwcm92aWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMueGhyRmllbGRzICkge1xuXHRcdFx0XHRcdGZvciAoIGkgaW4gb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0XHR4aHJbIGkgXSA9IG9wdGlvbnMueGhyRmllbGRzWyBpIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gT3ZlcnJpZGUgbWltZSB0eXBlIGlmIG5lZWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMubWltZVR5cGUgJiYgeGhyLm92ZXJyaWRlTWltZVR5cGUgKSB7XG5cdFx0XHRcdFx0eGhyLm92ZXJyaWRlTWltZVR5cGUoIG9wdGlvbnMubWltZVR5cGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFgtUmVxdWVzdGVkLVdpdGggaGVhZGVyXG5cdFx0XHRcdC8vIEZvciBjcm9zcy1kb21haW4gcmVxdWVzdHMsIHNlZWluZyBhcyBjb25kaXRpb25zIGZvciBhIHByZWZsaWdodCBhcmVcblx0XHRcdFx0Ly8gYWtpbiB0byBhIGppZ3NhdyBwdXp6bGUsIHdlIHNpbXBseSBuZXZlciBzZXQgaXQgdG8gYmUgc3VyZS5cblx0XHRcdFx0Ly8gKGl0IGNhbiBhbHdheXMgYmUgc2V0IG9uIGEgcGVyLXJlcXVlc3QgYmFzaXMgb3IgZXZlbiB1c2luZyBhamF4U2V0dXApXG5cdFx0XHRcdC8vIEZvciBzYW1lLWRvbWFpbiByZXF1ZXN0cywgd29uJ3QgY2hhbmdlIGhlYWRlciBpZiBhbHJlYWR5IHByb3ZpZGVkLlxuXHRcdFx0XHRpZiAoICFvcHRpb25zLmNyb3NzRG9tYWluICYmICFoZWFkZXJzWyBcIlgtUmVxdWVzdGVkLVdpdGhcIiBdICkge1xuXHRcdFx0XHRcdGhlYWRlcnNbIFwiWC1SZXF1ZXN0ZWQtV2l0aFwiIF0gPSBcIlhNTEh0dHBSZXF1ZXN0XCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBTZXQgaGVhZGVyc1xuXHRcdFx0XHRmb3IgKCBpIGluIGhlYWRlcnMgKSB7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoIGksIGhlYWRlcnNbIGkgXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQ2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRjYWxsYmFjayA9IGVycm9yQ2FsbGJhY2sgPSB4aHIub25sb2FkID1cblx0XHRcdFx0XHRcdFx0XHR4aHIub25lcnJvciA9IHhoci5vbmFib3J0ID0geGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSBcImFib3J0XCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0eGhyLmFib3J0KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHR5cGUgPT09IFwiZXJyb3JcIiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gT24gYSBtYW51YWwgbmF0aXZlIGFib3J0LCBJRTkgdGhyb3dzXG5cdFx0XHRcdFx0XHRcdFx0Ly8gZXJyb3JzIG9uIGFueSBwcm9wZXJ0eSBhY2Nlc3MgdGhhdCBpcyBub3QgcmVhZHlTdGF0ZVxuXHRcdFx0XHRcdFx0XHRcdGlmICggdHlwZW9mIHhoci5zdGF0dXMgIT09IFwibnVtYmVyXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggMCwgXCJlcnJvclwiICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKFxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEZpbGU6IHByb3RvY29sIGFsd2F5cyB5aWVsZHMgc3RhdHVzIDA7IHNlZSAjODYwNSwgIzE0MjA3XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXMsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXNUZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZShcblx0XHRcdFx0XHRcdFx0XHRcdHhoclN1Y2Nlc3NTdGF0dXNbIHhoci5zdGF0dXMgXSB8fCB4aHIuc3RhdHVzLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHQsXG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBJRTkgaGFzIG5vIFhIUjIgYnV0IHRocm93cyBvbiBiaW5hcnkgKHRyYWMtMTE0MjYpXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBGb3IgWEhSMiBub24tdGV4dCwgbGV0IHRoZSBjYWxsZXIgaGFuZGxlIGl0IChnaC0yNDk4KVxuXHRcdFx0XHRcdFx0XHRcdFx0KCB4aHIucmVzcG9uc2VUeXBlIHx8IFwidGV4dFwiICkgIT09IFwidGV4dFwiICB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0dHlwZW9mIHhoci5yZXNwb25zZVRleHQgIT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IGJpbmFyeTogeGhyLnJlc3BvbnNlIH0gOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IHRleHQ6IHhoci5yZXNwb25zZVRleHQgfSxcblx0XHRcdFx0XHRcdFx0XHRcdHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKVxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIExpc3RlbiB0byBldmVudHNcblx0XHRcdFx0eGhyLm9ubG9hZCA9IGNhbGxiYWNrKCk7XG5cdFx0XHRcdGVycm9yQ2FsbGJhY2sgPSB4aHIub25lcnJvciA9IGNhbGxiYWNrKCBcImVycm9yXCIgKTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA5IG9ubHlcblx0XHRcdFx0Ly8gVXNlIG9ucmVhZHlzdGF0ZWNoYW5nZSB0byByZXBsYWNlIG9uYWJvcnRcblx0XHRcdFx0Ly8gdG8gaGFuZGxlIHVuY2F1Z2h0IGFib3J0c1xuXHRcdFx0XHRpZiAoIHhoci5vbmFib3J0ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0eGhyLm9uYWJvcnQgPSBlcnJvckNhbGxiYWNrO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgcmVhZHlTdGF0ZSBiZWZvcmUgdGltZW91dCBhcyBpdCBjaGFuZ2VzXG5cdFx0XHRcdFx0XHRpZiAoIHhoci5yZWFkeVN0YXRlID09PSA0ICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIEFsbG93IG9uZXJyb3IgdG8gYmUgY2FsbGVkIGZpcnN0LFxuXHRcdFx0XHRcdFx0XHQvLyBidXQgdGhhdCB3aWxsIG5vdCBoYW5kbGUgYSBuYXRpdmUgYWJvcnRcblx0XHRcdFx0XHRcdFx0Ly8gQWxzbywgc2F2ZSBlcnJvckNhbGxiYWNrIHRvIGEgdmFyaWFibGVcblx0XHRcdFx0XHRcdFx0Ly8gYXMgeGhyLm9uZXJyb3IgY2Fubm90IGJlIGFjY2Vzc2VkXG5cdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JDYWxsYmFjaygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDcmVhdGUgdGhlIGFib3J0IGNhbGxiYWNrXG5cdFx0XHRcdGNhbGxiYWNrID0gY2FsbGJhY2soIFwiYWJvcnRcIiApO1xuXG5cdFx0XHRcdHRyeSB7XG5cblx0XHRcdFx0XHQvLyBEbyBzZW5kIHRoZSByZXF1ZXN0ICh0aGlzIG1heSByYWlzZSBhbiBleGNlcHRpb24pXG5cdFx0XHRcdFx0eGhyLnNlbmQoIG9wdGlvbnMuaGFzQ29udGVudCAmJiBvcHRpb25zLmRhdGEgfHwgbnVsbCApO1xuXHRcdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHRcdC8vICMxNDY4MzogT25seSByZXRocm93IGlmIHRoaXMgaGFzbid0IGJlZW4gbm90aWZpZWQgYXMgYW4gZXJyb3IgeWV0XG5cdFx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRcdHRocm93IGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0gKTtcblxuXG5cblxuLy8gUHJldmVudCBhdXRvLWV4ZWN1dGlvbiBvZiBzY3JpcHRzIHdoZW4gbm8gZXhwbGljaXQgZGF0YVR5cGUgd2FzIHByb3ZpZGVkIChTZWUgZ2gtMjQzMilcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBmdW5jdGlvbiggcyApIHtcblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMuY29udGVudHMuc2NyaXB0ID0gZmFsc2U7XG5cdH1cbn0gKTtcblxuLy8gSW5zdGFsbCBzY3JpcHQgZGF0YVR5cGVcbmpRdWVyeS5hamF4U2V0dXAoIHtcblx0YWNjZXB0czoge1xuXHRcdHNjcmlwdDogXCJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIFwiICtcblx0XHRcdFwiYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0XCJcblx0fSxcblx0Y29udGVudHM6IHtcblx0XHRzY3JpcHQ6IC9cXGIoPzpqYXZhfGVjbWEpc2NyaXB0XFxiL1xuXHR9LFxuXHRjb252ZXJ0ZXJzOiB7XG5cdFx0XCJ0ZXh0IHNjcmlwdFwiOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdGpRdWVyeS5nbG9iYWxFdmFsKCB0ZXh0ICk7XG5cdFx0XHRyZXR1cm4gdGV4dDtcblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSGFuZGxlIGNhY2hlJ3Mgc3BlY2lhbCBjYXNlIGFuZCBjcm9zc0RvbWFpblxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIFwic2NyaXB0XCIsIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzLmNhY2hlID0gZmFsc2U7XG5cdH1cblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMudHlwZSA9IFwiR0VUXCI7XG5cdH1cbn0gKTtcblxuLy8gQmluZCBzY3JpcHQgdGFnIGhhY2sgdHJhbnNwb3J0XG5qUXVlcnkuYWpheFRyYW5zcG9ydCggXCJzY3JpcHRcIiwgZnVuY3Rpb24oIHMgKSB7XG5cblx0Ly8gVGhpcyB0cmFuc3BvcnQgb25seSBkZWFscyB3aXRoIGNyb3NzIGRvbWFpbiByZXF1ZXN0c1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0dmFyIHNjcmlwdCwgY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBfLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0c2NyaXB0ID0galF1ZXJ5KCBcIjxzY3JpcHQ+XCIgKS5wcm9wKCB7XG5cdFx0XHRcdFx0Y2hhcnNldDogcy5zY3JpcHRDaGFyc2V0LFxuXHRcdFx0XHRcdHNyYzogcy51cmxcblx0XHRcdFx0fSApLm9uKFxuXHRcdFx0XHRcdFwibG9hZCBlcnJvclwiLFxuXHRcdFx0XHRcdGNhbGxiYWNrID0gZnVuY3Rpb24oIGV2dCApIHtcblx0XHRcdFx0XHRcdHNjcmlwdC5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdGNhbGxiYWNrID0gbnVsbDtcblx0XHRcdFx0XHRcdGlmICggZXZ0ICkge1xuXHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggZXZ0LnR5cGUgPT09IFwiZXJyb3JcIiA/IDQwNCA6IDIwMCwgZXZ0LnR5cGUgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gVXNlIG5hdGl2ZSBET00gbWFuaXB1bGF0aW9uIHRvIGF2b2lkIG91ciBkb21NYW5pcCBBSkFYIHRyaWNrZXJ5XG5cdFx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdFsgMCBdICk7XG5cdFx0XHR9LFxuXHRcdFx0YWJvcnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBvbGRDYWxsYmFja3MgPSBbXSxcblx0cmpzb25wID0gLyg9KVxcPyg/PSZ8JCl8XFw/XFw/LztcblxuLy8gRGVmYXVsdCBqc29ucCBzZXR0aW5nc1xualF1ZXJ5LmFqYXhTZXR1cCgge1xuXHRqc29ucDogXCJjYWxsYmFja1wiLFxuXHRqc29ucENhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgY2FsbGJhY2sgPSBvbGRDYWxsYmFja3MucG9wKCkgfHwgKCBqUXVlcnkuZXhwYW5kbyArIFwiX1wiICsgKCBub25jZSsrICkgKTtcblx0XHR0aGlzWyBjYWxsYmFjayBdID0gdHJ1ZTtcblx0XHRyZXR1cm4gY2FsbGJhY2s7XG5cdH1cbn0gKTtcblxuLy8gRGV0ZWN0LCBub3JtYWxpemUgb3B0aW9ucyBhbmQgaW5zdGFsbCBjYWxsYmFja3MgZm9yIGpzb25wIHJlcXVlc3RzXG5qUXVlcnkuYWpheFByZWZpbHRlciggXCJqc29uIGpzb25wXCIsIGZ1bmN0aW9uKCBzLCBvcmlnaW5hbFNldHRpbmdzLCBqcVhIUiApIHtcblxuXHR2YXIgY2FsbGJhY2tOYW1lLCBvdmVyd3JpdHRlbiwgcmVzcG9uc2VDb250YWluZXIsXG5cdFx0anNvblByb3AgPSBzLmpzb25wICE9PSBmYWxzZSAmJiAoIHJqc29ucC50ZXN0KCBzLnVybCApID9cblx0XHRcdFwidXJsXCIgOlxuXHRcdFx0dHlwZW9mIHMuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHQoIHMuY29udGVudFR5cGUgfHwgXCJcIiApXG5cdFx0XHRcdFx0LmluZGV4T2YoIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgKSA9PT0gMCAmJlxuXHRcdFx0XHRyanNvbnAudGVzdCggcy5kYXRhICkgJiYgXCJkYXRhXCJcblx0XHQpO1xuXG5cdC8vIEhhbmRsZSBpZmYgdGhlIGV4cGVjdGVkIGRhdGEgdHlwZSBpcyBcImpzb25wXCIgb3Igd2UgaGF2ZSBhIHBhcmFtZXRlciB0byBzZXRcblx0aWYgKCBqc29uUHJvcCB8fCBzLmRhdGFUeXBlc1sgMCBdID09PSBcImpzb25wXCIgKSB7XG5cblx0XHQvLyBHZXQgY2FsbGJhY2sgbmFtZSwgcmVtZW1iZXJpbmcgcHJlZXhpc3RpbmcgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGl0XG5cdFx0Y2FsbGJhY2tOYW1lID0gcy5qc29ucENhbGxiYWNrID0galF1ZXJ5LmlzRnVuY3Rpb24oIHMuanNvbnBDYWxsYmFjayApID9cblx0XHRcdHMuanNvbnBDYWxsYmFjaygpIDpcblx0XHRcdHMuanNvbnBDYWxsYmFjaztcblxuXHRcdC8vIEluc2VydCBjYWxsYmFjayBpbnRvIHVybCBvciBmb3JtIGRhdGFcblx0XHRpZiAoIGpzb25Qcm9wICkge1xuXHRcdFx0c1sganNvblByb3AgXSA9IHNbIGpzb25Qcm9wIF0ucmVwbGFjZSggcmpzb25wLCBcIiQxXCIgKyBjYWxsYmFja05hbWUgKTtcblx0XHR9IGVsc2UgaWYgKCBzLmpzb25wICE9PSBmYWxzZSApIHtcblx0XHRcdHMudXJsICs9ICggcnF1ZXJ5LnRlc3QoIHMudXJsICkgPyBcIiZcIiA6IFwiP1wiICkgKyBzLmpzb25wICsgXCI9XCIgKyBjYWxsYmFja05hbWU7XG5cdFx0fVxuXG5cdFx0Ly8gVXNlIGRhdGEgY29udmVydGVyIHRvIHJldHJpZXZlIGpzb24gYWZ0ZXIgc2NyaXB0IGV4ZWN1dGlvblxuXHRcdHMuY29udmVydGVyc1sgXCJzY3JpcHQganNvblwiIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggIXJlc3BvbnNlQ29udGFpbmVyICkge1xuXHRcdFx0XHRqUXVlcnkuZXJyb3IoIGNhbGxiYWNrTmFtZSArIFwiIHdhcyBub3QgY2FsbGVkXCIgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXNwb25zZUNvbnRhaW5lclsgMCBdO1xuXHRcdH07XG5cblx0XHQvLyBGb3JjZSBqc29uIGRhdGFUeXBlXG5cdFx0cy5kYXRhVHlwZXNbIDAgXSA9IFwianNvblwiO1xuXG5cdFx0Ly8gSW5zdGFsbCBjYWxsYmFja1xuXHRcdG92ZXJ3cml0dGVuID0gd2luZG93WyBjYWxsYmFja05hbWUgXTtcblx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXNwb25zZUNvbnRhaW5lciA9IGFyZ3VtZW50cztcblx0XHR9O1xuXG5cdFx0Ly8gQ2xlYW4tdXAgZnVuY3Rpb24gKGZpcmVzIGFmdGVyIGNvbnZlcnRlcnMpXG5cdFx0anFYSFIuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gSWYgcHJldmlvdXMgdmFsdWUgZGlkbid0IGV4aXN0IC0gcmVtb3ZlIGl0XG5cdFx0XHRpZiAoIG92ZXJ3cml0dGVuID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpRdWVyeSggd2luZG93ICkucmVtb3ZlUHJvcCggY2FsbGJhY2tOYW1lICk7XG5cblx0XHRcdC8vIE90aGVyd2lzZSByZXN0b3JlIHByZWV4aXN0aW5nIHZhbHVlXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gb3ZlcndyaXR0ZW47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNhdmUgYmFjayBhcyBmcmVlXG5cdFx0XHRpZiAoIHNbIGNhbGxiYWNrTmFtZSBdICkge1xuXG5cdFx0XHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHJlLXVzaW5nIHRoZSBvcHRpb25zIGRvZXNuJ3Qgc2NyZXcgdGhpbmdzIGFyb3VuZFxuXHRcdFx0XHRzLmpzb25wQ2FsbGJhY2sgPSBvcmlnaW5hbFNldHRpbmdzLmpzb25wQ2FsbGJhY2s7XG5cblx0XHRcdFx0Ly8gU2F2ZSB0aGUgY2FsbGJhY2sgbmFtZSBmb3IgZnV0dXJlIHVzZVxuXHRcdFx0XHRvbGRDYWxsYmFja3MucHVzaCggY2FsbGJhY2tOYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENhbGwgaWYgaXQgd2FzIGEgZnVuY3Rpb24gYW5kIHdlIGhhdmUgYSByZXNwb25zZVxuXHRcdFx0aWYgKCByZXNwb25zZUNvbnRhaW5lciAmJiBqUXVlcnkuaXNGdW5jdGlvbiggb3ZlcndyaXR0ZW4gKSApIHtcblx0XHRcdFx0b3ZlcndyaXR0ZW4oIHJlc3BvbnNlQ29udGFpbmVyWyAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmVzcG9uc2VDb250YWluZXIgPSBvdmVyd3JpdHRlbiA9IHVuZGVmaW5lZDtcblx0XHR9ICk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBzY3JpcHRcblx0XHRyZXR1cm4gXCJzY3JpcHRcIjtcblx0fVxufSApO1xuXG5cblxuXG4vLyBTdXBwb3J0OiBTYWZhcmkgOCBvbmx5XG4vLyBJbiBTYWZhcmkgOCBkb2N1bWVudHMgY3JlYXRlZCB2aWEgZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50XG4vLyBjb2xsYXBzZSBzaWJsaW5nIGZvcm1zOiB0aGUgc2Vjb25kIG9uZSBiZWNvbWVzIGEgY2hpbGQgb2YgdGhlIGZpcnN0IG9uZS5cbi8vIEJlY2F1c2Ugb2YgdGhhdCwgdGhpcyBzZWN1cml0eSBtZWFzdXJlIGhhcyB0byBiZSBkaXNhYmxlZCBpbiBTYWZhcmkgOC5cbi8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzczMzdcbnN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ID0gKCBmdW5jdGlvbigpIHtcblx0dmFyIGJvZHkgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoIFwiXCIgKS5ib2R5O1xuXHRib2R5LmlubmVySFRNTCA9IFwiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT5cIjtcblx0cmV0dXJuIGJvZHkuY2hpbGROb2Rlcy5sZW5ndGggPT09IDI7XG59ICkoKTtcblxuXG4vLyBBcmd1bWVudCBcImRhdGFcIiBzaG91bGQgYmUgc3RyaW5nIG9mIGh0bWxcbi8vIGNvbnRleHQgKG9wdGlvbmFsKTogSWYgc3BlY2lmaWVkLCB0aGUgZnJhZ21lbnQgd2lsbCBiZSBjcmVhdGVkIGluIHRoaXMgY29udGV4dCxcbi8vIGRlZmF1bHRzIHRvIGRvY3VtZW50XG4vLyBrZWVwU2NyaXB0cyAob3B0aW9uYWwpOiBJZiB0cnVlLCB3aWxsIGluY2x1ZGUgc2NyaXB0cyBwYXNzZWQgaW4gdGhlIGh0bWwgc3RyaW5nXG5qUXVlcnkucGFyc2VIVE1MID0gZnVuY3Rpb24oIGRhdGEsIGNvbnRleHQsIGtlZXBTY3JpcHRzICkge1xuXHRpZiAoIHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBbXTtcblx0fVxuXHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRrZWVwU2NyaXB0cyA9IGNvbnRleHQ7XG5cdFx0Y29udGV4dCA9IGZhbHNlO1xuXHR9XG5cblx0dmFyIGJhc2UsIHBhcnNlZCwgc2NyaXB0cztcblxuXHRpZiAoICFjb250ZXh0ICkge1xuXG5cdFx0Ly8gU3RvcCBzY3JpcHRzIG9yIGlubGluZSBldmVudCBoYW5kbGVycyBmcm9tIGJlaW5nIGV4ZWN1dGVkIGltbWVkaWF0ZWx5XG5cdFx0Ly8gYnkgdXNpbmcgZG9jdW1lbnQuaW1wbGVtZW50YXRpb25cblx0XHRpZiAoIHN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ICkge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCggXCJcIiApO1xuXG5cdFx0XHQvLyBTZXQgdGhlIGJhc2UgaHJlZiBmb3IgdGhlIGNyZWF0ZWQgZG9jdW1lbnRcblx0XHRcdC8vIHNvIGFueSBwYXJzZWQgZWxlbWVudHMgd2l0aCBVUkxzXG5cdFx0XHQvLyBhcmUgYmFzZWQgb24gdGhlIGRvY3VtZW50J3MgVVJMIChnaC0yOTY1KVxuXHRcdFx0YmFzZSA9IGNvbnRleHQuY3JlYXRlRWxlbWVudCggXCJiYXNlXCIgKTtcblx0XHRcdGJhc2UuaHJlZiA9IGRvY3VtZW50LmxvY2F0aW9uLmhyZWY7XG5cdFx0XHRjb250ZXh0LmhlYWQuYXBwZW5kQ2hpbGQoIGJhc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50O1xuXHRcdH1cblx0fVxuXG5cdHBhcnNlZCA9IHJzaW5nbGVUYWcuZXhlYyggZGF0YSApO1xuXHRzY3JpcHRzID0gIWtlZXBTY3JpcHRzICYmIFtdO1xuXG5cdC8vIFNpbmdsZSB0YWdcblx0aWYgKCBwYXJzZWQgKSB7XG5cdFx0cmV0dXJuIFsgY29udGV4dC5jcmVhdGVFbGVtZW50KCBwYXJzZWRbIDEgXSApIF07XG5cdH1cblxuXHRwYXJzZWQgPSBidWlsZEZyYWdtZW50KCBbIGRhdGEgXSwgY29udGV4dCwgc2NyaXB0cyApO1xuXG5cdGlmICggc2NyaXB0cyAmJiBzY3JpcHRzLmxlbmd0aCApIHtcblx0XHRqUXVlcnkoIHNjcmlwdHMgKS5yZW1vdmUoKTtcblx0fVxuXG5cdHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBwYXJzZWQuY2hpbGROb2RlcyApO1xufTtcblxuXG4vKipcbiAqIExvYWQgYSB1cmwgaW50byBhIHBhZ2VcbiAqL1xualF1ZXJ5LmZuLmxvYWQgPSBmdW5jdGlvbiggdXJsLCBwYXJhbXMsIGNhbGxiYWNrICkge1xuXHR2YXIgc2VsZWN0b3IsIHR5cGUsIHJlc3BvbnNlLFxuXHRcdHNlbGYgPSB0aGlzLFxuXHRcdG9mZiA9IHVybC5pbmRleE9mKCBcIiBcIiApO1xuXG5cdGlmICggb2ZmID4gLTEgKSB7XG5cdFx0c2VsZWN0b3IgPSBzdHJpcEFuZENvbGxhcHNlKCB1cmwuc2xpY2UoIG9mZiApICk7XG5cdFx0dXJsID0gdXJsLnNsaWNlKCAwLCBvZmYgKTtcblx0fVxuXG5cdC8vIElmIGl0J3MgYSBmdW5jdGlvblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwYXJhbXMgKSApIHtcblxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2sgPSBwYXJhbXM7XG5cdFx0cGFyYW1zID0gdW5kZWZpbmVkO1xuXG5cdC8vIE90aGVyd2lzZSwgYnVpbGQgYSBwYXJhbSBzdHJpbmdcblx0fSBlbHNlIGlmICggcGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0dHlwZSA9IFwiUE9TVFwiO1xuXHR9XG5cblx0Ly8gSWYgd2UgaGF2ZSBlbGVtZW50cyB0byBtb2RpZnksIG1ha2UgdGhlIHJlcXVlc3Rcblx0aWYgKCBzZWxmLmxlbmd0aCA+IDAgKSB7XG5cdFx0alF1ZXJ5LmFqYXgoIHtcblx0XHRcdHVybDogdXJsLFxuXG5cdFx0XHQvLyBJZiBcInR5cGVcIiB2YXJpYWJsZSBpcyB1bmRlZmluZWQsIHRoZW4gXCJHRVRcIiBtZXRob2Qgd2lsbCBiZSB1c2VkLlxuXHRcdFx0Ly8gTWFrZSB2YWx1ZSBvZiB0aGlzIGZpZWxkIGV4cGxpY2l0IHNpbmNlXG5cdFx0XHQvLyB1c2VyIGNhbiBvdmVycmlkZSBpdCB0aHJvdWdoIGFqYXhTZXR1cCBtZXRob2Rcblx0XHRcdHR5cGU6IHR5cGUgfHwgXCJHRVRcIixcblx0XHRcdGRhdGFUeXBlOiBcImh0bWxcIixcblx0XHRcdGRhdGE6IHBhcmFtc1xuXHRcdH0gKS5kb25lKCBmdW5jdGlvbiggcmVzcG9uc2VUZXh0ICkge1xuXG5cdFx0XHQvLyBTYXZlIHJlc3BvbnNlIGZvciB1c2UgaW4gY29tcGxldGUgY2FsbGJhY2tcblx0XHRcdHJlc3BvbnNlID0gYXJndW1lbnRzO1xuXG5cdFx0XHRzZWxmLmh0bWwoIHNlbGVjdG9yID9cblxuXHRcdFx0XHQvLyBJZiBhIHNlbGVjdG9yIHdhcyBzcGVjaWZpZWQsIGxvY2F0ZSB0aGUgcmlnaHQgZWxlbWVudHMgaW4gYSBkdW1teSBkaXZcblx0XHRcdFx0Ly8gRXhjbHVkZSBzY3JpcHRzIHRvIGF2b2lkIElFICdQZXJtaXNzaW9uIERlbmllZCcgZXJyb3JzXG5cdFx0XHRcdGpRdWVyeSggXCI8ZGl2PlwiICkuYXBwZW5kKCBqUXVlcnkucGFyc2VIVE1MKCByZXNwb25zZVRleHQgKSApLmZpbmQoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSB1c2UgdGhlIGZ1bGwgcmVzdWx0XG5cdFx0XHRcdHJlc3BvbnNlVGV4dCApO1xuXG5cdFx0Ly8gSWYgdGhlIHJlcXVlc3Qgc3VjY2VlZHMsIHRoaXMgZnVuY3Rpb24gZ2V0cyBcImRhdGFcIiwgXCJzdGF0dXNcIiwgXCJqcVhIUlwiXG5cdFx0Ly8gYnV0IHRoZXkgYXJlIGlnbm9yZWQgYmVjYXVzZSByZXNwb25zZSB3YXMgc2V0IGFib3ZlLlxuXHRcdC8vIElmIGl0IGZhaWxzLCB0aGlzIGZ1bmN0aW9uIGdldHMgXCJqcVhIUlwiLCBcInN0YXR1c1wiLCBcImVycm9yXCJcblx0XHR9ICkuYWx3YXlzKCBjYWxsYmFjayAmJiBmdW5jdGlvbigganFYSFIsIHN0YXR1cyApIHtcblx0XHRcdHNlbGYuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNhbGxiYWNrLmFwcGx5KCB0aGlzLCByZXNwb25zZSB8fCBbIGpxWEhSLnJlc3BvbnNlVGV4dCwgc3RhdHVzLCBqcVhIUiBdICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXM7XG59O1xuXG5cblxuXG4vLyBBdHRhY2ggYSBidW5jaCBvZiBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIGNvbW1vbiBBSkFYIGV2ZW50c1xualF1ZXJ5LmVhY2goIFtcblx0XCJhamF4U3RhcnRcIixcblx0XCJhamF4U3RvcFwiLFxuXHRcImFqYXhDb21wbGV0ZVwiLFxuXHRcImFqYXhFcnJvclwiLFxuXHRcImFqYXhTdWNjZXNzXCIsXG5cdFwiYWpheFNlbmRcIlxuXSwgZnVuY3Rpb24oIGksIHR5cGUgKSB7XG5cdGpRdWVyeS5mblsgdHlwZSBdID0gZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlLCBmbiApO1xuXHR9O1xufSApO1xuXG5cblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggalF1ZXJ5LnRpbWVycywgZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiBlbGVtID09PSBmbi5lbGVtO1xuXHR9ICkubGVuZ3RoO1xufTtcblxuXG5cblxualF1ZXJ5Lm9mZnNldCA9IHtcblx0c2V0T2Zmc2V0OiBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgaSApIHtcblx0XHR2YXIgY3VyUG9zaXRpb24sIGN1ckxlZnQsIGN1ckNTU1RvcCwgY3VyVG9wLCBjdXJPZmZzZXQsIGN1ckNTU0xlZnQsIGNhbGN1bGF0ZVBvc2l0aW9uLFxuXHRcdFx0cG9zaXRpb24gPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBvc2l0aW9uXCIgKSxcblx0XHRcdGN1ckVsZW0gPSBqUXVlcnkoIGVsZW0gKSxcblx0XHRcdHByb3BzID0ge307XG5cblx0XHQvLyBTZXQgcG9zaXRpb24gZmlyc3QsIGluLWNhc2UgdG9wL2xlZnQgYXJlIHNldCBldmVuIG9uIHN0YXRpYyBlbGVtXG5cdFx0aWYgKCBwb3NpdGlvbiA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdGVsZW0uc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cdFx0fVxuXG5cdFx0Y3VyT2Zmc2V0ID0gY3VyRWxlbS5vZmZzZXQoKTtcblx0XHRjdXJDU1NUb3AgPSBqUXVlcnkuY3NzKCBlbGVtLCBcInRvcFwiICk7XG5cdFx0Y3VyQ1NTTGVmdCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwibGVmdFwiICk7XG5cdFx0Y2FsY3VsYXRlUG9zaXRpb24gPSAoIHBvc2l0aW9uID09PSBcImFic29sdXRlXCIgfHwgcG9zaXRpb24gPT09IFwiZml4ZWRcIiApICYmXG5cdFx0XHQoIGN1ckNTU1RvcCArIGN1ckNTU0xlZnQgKS5pbmRleE9mKCBcImF1dG9cIiApID4gLTE7XG5cblx0XHQvLyBOZWVkIHRvIGJlIGFibGUgdG8gY2FsY3VsYXRlIHBvc2l0aW9uIGlmIGVpdGhlclxuXHRcdC8vIHRvcCBvciBsZWZ0IGlzIGF1dG8gYW5kIHBvc2l0aW9uIGlzIGVpdGhlciBhYnNvbHV0ZSBvciBmaXhlZFxuXHRcdGlmICggY2FsY3VsYXRlUG9zaXRpb24gKSB7XG5cdFx0XHRjdXJQb3NpdGlvbiA9IGN1ckVsZW0ucG9zaXRpb24oKTtcblx0XHRcdGN1clRvcCA9IGN1clBvc2l0aW9uLnRvcDtcblx0XHRcdGN1ckxlZnQgPSBjdXJQb3NpdGlvbi5sZWZ0O1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1clRvcCA9IHBhcnNlRmxvYXQoIGN1ckNTU1RvcCApIHx8IDA7XG5cdFx0XHRjdXJMZWZ0ID0gcGFyc2VGbG9hdCggY3VyQ1NTTGVmdCApIHx8IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0aW9ucyApICkge1xuXG5cdFx0XHQvLyBVc2UgalF1ZXJ5LmV4dGVuZCBoZXJlIHRvIGFsbG93IG1vZGlmaWNhdGlvbiBvZiBjb29yZGluYXRlcyBhcmd1bWVudCAoZ2gtMTg0OClcblx0XHRcdG9wdGlvbnMgPSBvcHRpb25zLmNhbGwoIGVsZW0sIGksIGpRdWVyeS5leHRlbmQoIHt9LCBjdXJPZmZzZXQgKSApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0aW9ucy50b3AgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLnRvcCA9ICggb3B0aW9ucy50b3AgLSBjdXJPZmZzZXQudG9wICkgKyBjdXJUb3A7XG5cdFx0fVxuXHRcdGlmICggb3B0aW9ucy5sZWZ0ICE9IG51bGwgKSB7XG5cdFx0XHRwcm9wcy5sZWZ0ID0gKCBvcHRpb25zLmxlZnQgLSBjdXJPZmZzZXQubGVmdCApICsgY3VyTGVmdDtcblx0XHR9XG5cblx0XHRpZiAoIFwidXNpbmdcIiBpbiBvcHRpb25zICkge1xuXHRcdFx0b3B0aW9ucy51c2luZy5jYWxsKCBlbGVtLCBwcm9wcyApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1ckVsZW0uY3NzKCBwcm9wcyApO1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRvZmZzZXQ6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdFx0Ly8gUHJlc2VydmUgY2hhaW5pbmcgZm9yIHNldHRlclxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiBvcHRpb25zID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHR0aGlzIDpcblx0XHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0XHRqUXVlcnkub2Zmc2V0LnNldE9mZnNldCggdGhpcywgb3B0aW9ucywgaSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRvYywgZG9jRWxlbSwgcmVjdCwgd2luLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHplcm9zIGZvciBkaXNjb25uZWN0ZWQgYW5kIGhpZGRlbiAoZGlzcGxheTogbm9uZSkgZWxlbWVudHMgKGdoLTIzMTApXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYVxuXHRcdC8vIGRpc2Nvbm5lY3RlZCBub2RlIGluIElFIHRocm93cyBhbiBlcnJvclxuXHRcdGlmICggIWVsZW0uZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblx0XHR9XG5cblx0XHRyZWN0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudDtcblx0XHRkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudDtcblx0XHR3aW4gPSBkb2MuZGVmYXVsdFZpZXc7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiByZWN0LnRvcCArIHdpbi5wYWdlWU9mZnNldCAtIGRvY0VsZW0uY2xpZW50VG9wLFxuXHRcdFx0bGVmdDogcmVjdC5sZWZ0ICsgd2luLnBhZ2VYT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRMZWZ0XG5cdFx0fTtcblx0fSxcblxuXHRwb3NpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCAhdGhpc1sgMCBdICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBvZmZzZXRQYXJlbnQsIG9mZnNldCxcblx0XHRcdGVsZW0gPSB0aGlzWyAwIF0sXG5cdFx0XHRwYXJlbnRPZmZzZXQgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xuXG5cdFx0Ly8gRml4ZWQgZWxlbWVudHMgYXJlIG9mZnNldCBmcm9tIHdpbmRvdyAocGFyZW50T2Zmc2V0ID0ge3RvcDowLCBsZWZ0OiAwfSxcblx0XHQvLyBiZWNhdXNlIGl0IGlzIGl0cyBvbmx5IG9mZnNldCBwYXJlbnRcblx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApID09PSBcImZpeGVkXCIgKSB7XG5cblx0XHRcdC8vIEFzc3VtZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgaXMgdGhlcmUgd2hlbiBjb21wdXRlZCBwb3NpdGlvbiBpcyBmaXhlZFxuXHRcdFx0b2Zmc2V0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIEdldCAqcmVhbCogb2Zmc2V0UGFyZW50XG5cdFx0XHRvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudCgpO1xuXG5cdFx0XHQvLyBHZXQgY29ycmVjdCBvZmZzZXRzXG5cdFx0XHRvZmZzZXQgPSB0aGlzLm9mZnNldCgpO1xuXHRcdFx0aWYgKCAhbm9kZU5hbWUoIG9mZnNldFBhcmVudFsgMCBdLCBcImh0bWxcIiApICkge1xuXHRcdFx0XHRwYXJlbnRPZmZzZXQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBvZmZzZXRQYXJlbnQgYm9yZGVyc1xuXHRcdFx0cGFyZW50T2Zmc2V0ID0ge1xuXHRcdFx0XHR0b3A6IHBhcmVudE9mZnNldC50b3AgKyBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnRbIDAgXSwgXCJib3JkZXJUb3BXaWR0aFwiLCB0cnVlICksXG5cdFx0XHRcdGxlZnQ6IHBhcmVudE9mZnNldC5sZWZ0ICsgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50WyAwIF0sIFwiYm9yZGVyTGVmdFdpZHRoXCIsIHRydWUgKVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHQvLyBTdWJ0cmFjdCBwYXJlbnQgb2Zmc2V0cyBhbmQgZWxlbWVudCBtYXJnaW5zXG5cdFx0cmV0dXJuIHtcblx0XHRcdHRvcDogb2Zmc2V0LnRvcCAtIHBhcmVudE9mZnNldC50b3AgLSBqUXVlcnkuY3NzKCBlbGVtLCBcIm1hcmdpblRvcFwiLCB0cnVlICksXG5cdFx0XHRsZWZ0OiBvZmZzZXQubGVmdCAtIHBhcmVudE9mZnNldC5sZWZ0IC0galF1ZXJ5LmNzcyggZWxlbSwgXCJtYXJnaW5MZWZ0XCIsIHRydWUgKVxuXHRcdH07XG5cdH0sXG5cblx0Ly8gVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gZG9jdW1lbnRFbGVtZW50IGluIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG5cdC8vIDEpIEZvciB0aGUgZWxlbWVudCBpbnNpZGUgdGhlIGlmcmFtZSB3aXRob3V0IG9mZnNldFBhcmVudCwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm5cblx0Ly8gICAgZG9jdW1lbnRFbGVtZW50IG9mIHRoZSBwYXJlbnQgd2luZG93XG5cdC8vIDIpIEZvciB0aGUgaGlkZGVuIG9yIGRldGFjaGVkIGVsZW1lbnRcblx0Ly8gMykgRm9yIGJvZHkgb3IgaHRtbCBlbGVtZW50LCBpLmUuIGluIGNhc2Ugb2YgdGhlIGh0bWwgbm9kZSAtIGl0IHdpbGwgcmV0dXJuIGl0c2VsZlxuXHQvL1xuXHQvLyBidXQgdGhvc2UgZXhjZXB0aW9ucyB3ZXJlIG5ldmVyIHByZXNlbnRlZCBhcyBhIHJlYWwgbGlmZSB1c2UtY2FzZXNcblx0Ly8gYW5kIG1pZ2h0IGJlIGNvbnNpZGVyZWQgYXMgbW9yZSBwcmVmZXJhYmxlIHJlc3VsdHMuXG5cdC8vXG5cdC8vIFRoaXMgbG9naWMsIGhvd2V2ZXIsIGlzIG5vdCBndWFyYW50ZWVkIGFuZCBjYW4gY2hhbmdlIGF0IGFueSBwb2ludCBpbiB0aGUgZnV0dXJlXG5cdG9mZnNldFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudDtcblxuXHRcdFx0d2hpbGUgKCBvZmZzZXRQYXJlbnQgJiYgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50LCBcInBvc2l0aW9uXCIgKSA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdFx0b2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG9mZnNldFBhcmVudCB8fCBkb2N1bWVudEVsZW1lbnQ7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbi8vIENyZWF0ZSBzY3JvbGxMZWZ0IGFuZCBzY3JvbGxUb3AgbWV0aG9kc1xualF1ZXJ5LmVhY2goIHsgc2Nyb2xsTGVmdDogXCJwYWdlWE9mZnNldFwiLCBzY3JvbGxUb3A6IFwicGFnZVlPZmZzZXRcIiB9LCBmdW5jdGlvbiggbWV0aG9kLCBwcm9wICkge1xuXHR2YXIgdG9wID0gXCJwYWdlWU9mZnNldFwiID09PSBwcm9wO1xuXG5cdGpRdWVyeS5mblsgbWV0aG9kIF0gPSBmdW5jdGlvbiggdmFsICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCBtZXRob2QsIHZhbCApIHtcblxuXHRcdFx0Ly8gQ29hbGVzY2UgZG9jdW1lbnRzIGFuZCB3aW5kb3dzXG5cdFx0XHR2YXIgd2luO1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblx0XHRcdFx0d2luID0gZWxlbTtcblx0XHRcdH0gZWxzZSBpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHdpbiA9IGVsZW0uZGVmYXVsdFZpZXc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdmFsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiB3aW4gPyB3aW5bIHByb3AgXSA6IGVsZW1bIG1ldGhvZCBdO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHdpbiApIHtcblx0XHRcdFx0d2luLnNjcm9sbFRvKFxuXHRcdFx0XHRcdCF0b3AgPyB2YWwgOiB3aW4ucGFnZVhPZmZzZXQsXG5cdFx0XHRcdFx0dG9wID8gdmFsIDogd2luLnBhZ2VZT2Zmc2V0XG5cdFx0XHRcdCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVsZW1bIG1ldGhvZCBdID0gdmFsO1xuXHRcdFx0fVxuXHRcdH0sIG1ldGhvZCwgdmFsLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH07XG59ICk7XG5cbi8vIFN1cHBvcnQ6IFNhZmFyaSA8PTcgLSA5LjEsIENocm9tZSA8PTM3IC0gNDlcbi8vIEFkZCB0aGUgdG9wL2xlZnQgY3NzSG9va3MgdXNpbmcgalF1ZXJ5LmZuLnBvc2l0aW9uXG4vLyBXZWJraXQgYnVnOiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkwODRcbi8vIEJsaW5rIGJ1ZzogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NTg5MzQ3XG4vLyBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgcGVyY2VudCB3aGVuIHNwZWNpZmllZCBmb3IgdG9wL2xlZnQvYm90dG9tL3JpZ2h0O1xuLy8gcmF0aGVyIHRoYW4gbWFrZSB0aGUgY3NzIG1vZHVsZSBkZXBlbmQgb24gdGhlIG9mZnNldCBtb2R1bGUsIGp1c3QgY2hlY2sgZm9yIGl0IGhlcmVcbmpRdWVyeS5lYWNoKCBbIFwidG9wXCIsIFwibGVmdFwiIF0sIGZ1bmN0aW9uKCBpLCBwcm9wICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByb3AgXSA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5waXhlbFBvc2l0aW9uLFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGNvbXB1dGVkID0gY3VyQ1NTKCBlbGVtLCBwcm9wICk7XG5cblx0XHRcdFx0Ly8gSWYgY3VyQ1NTIHJldHVybnMgcGVyY2VudGFnZSwgZmFsbGJhY2sgdG8gb2Zmc2V0XG5cdFx0XHRcdHJldHVybiBybnVtbm9ucHgudGVzdCggY29tcHV0ZWQgKSA/XG5cdFx0XHRcdFx0alF1ZXJ5KCBlbGVtICkucG9zaXRpb24oKVsgcHJvcCBdICsgXCJweFwiIDpcblx0XHRcdFx0XHRjb21wdXRlZDtcblx0XHRcdH1cblx0XHR9XG5cdCk7XG59ICk7XG5cblxuLy8gQ3JlYXRlIGlubmVySGVpZ2h0LCBpbm5lcldpZHRoLCBoZWlnaHQsIHdpZHRoLCBvdXRlckhlaWdodCBhbmQgb3V0ZXJXaWR0aCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBIZWlnaHQ6IFwiaGVpZ2h0XCIsIFdpZHRoOiBcIndpZHRoXCIgfSwgZnVuY3Rpb24oIG5hbWUsIHR5cGUgKSB7XG5cdGpRdWVyeS5lYWNoKCB7IHBhZGRpbmc6IFwiaW5uZXJcIiArIG5hbWUsIGNvbnRlbnQ6IHR5cGUsIFwiXCI6IFwib3V0ZXJcIiArIG5hbWUgfSxcblx0XHRmdW5jdGlvbiggZGVmYXVsdEV4dHJhLCBmdW5jTmFtZSApIHtcblxuXHRcdC8vIE1hcmdpbiBpcyBvbmx5IGZvciBvdXRlckhlaWdodCwgb3V0ZXJXaWR0aFxuXHRcdGpRdWVyeS5mblsgZnVuY05hbWUgXSA9IGZ1bmN0aW9uKCBtYXJnaW4sIHZhbHVlICkge1xuXHRcdFx0dmFyIGNoYWluYWJsZSA9IGFyZ3VtZW50cy5sZW5ndGggJiYgKCBkZWZhdWx0RXh0cmEgfHwgdHlwZW9mIG1hcmdpbiAhPT0gXCJib29sZWFuXCIgKSxcblx0XHRcdFx0ZXh0cmEgPSBkZWZhdWx0RXh0cmEgfHwgKCBtYXJnaW4gPT09IHRydWUgfHwgdmFsdWUgPT09IHRydWUgPyBcIm1hcmdpblwiIDogXCJib3JkZXJcIiApO1xuXG5cdFx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgdHlwZSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBkb2M7XG5cblx0XHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vICQoIHdpbmRvdyApLm91dGVyV2lkdGgvSGVpZ2h0IHJldHVybiB3L2ggaW5jbHVkaW5nIHNjcm9sbGJhcnMgKGdoLTE3MjkpXG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmNOYW1lLmluZGV4T2YoIFwib3V0ZXJcIiApID09PSAwID9cblx0XHRcdFx0XHRcdGVsZW1bIFwiaW5uZXJcIiArIG5hbWUgXSA6XG5cdFx0XHRcdFx0XHRlbGVtLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsgXCJjbGllbnRcIiArIG5hbWUgXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEdldCBkb2N1bWVudCB3aWR0aCBvciBoZWlnaHRcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdGRvYyA9IGVsZW0uZG9jdW1lbnRFbGVtZW50O1xuXG5cdFx0XHRcdFx0Ly8gRWl0aGVyIHNjcm9sbFtXaWR0aC9IZWlnaHRdIG9yIG9mZnNldFtXaWR0aC9IZWlnaHRdIG9yIGNsaWVudFtXaWR0aC9IZWlnaHRdLFxuXHRcdFx0XHRcdC8vIHdoaWNoZXZlciBpcyBncmVhdGVzdFxuXHRcdFx0XHRcdHJldHVybiBNYXRoLm1heChcblx0XHRcdFx0XHRcdGVsZW0uYm9keVsgXCJzY3JvbGxcIiArIG5hbWUgXSwgZG9jWyBcInNjcm9sbFwiICsgbmFtZSBdLFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcIm9mZnNldFwiICsgbmFtZSBdLCBkb2NbIFwib2Zmc2V0XCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRkb2NbIFwiY2xpZW50XCIgKyBuYW1lIF1cblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXG5cdFx0XHRcdFx0Ly8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudCwgcmVxdWVzdGluZyBidXQgbm90IGZvcmNpbmcgcGFyc2VGbG9hdFxuXHRcdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIHR5cGUsIGV4dHJhICkgOlxuXG5cdFx0XHRcdFx0Ly8gU2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudFxuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgdHlwZSwgdmFsdWUsIGV4dHJhICk7XG5cdFx0XHR9LCB0eXBlLCBjaGFpbmFibGUgPyBtYXJnaW4gOiB1bmRlZmluZWQsIGNoYWluYWJsZSApO1xuXHRcdH07XG5cdH0gKTtcbn0gKTtcblxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cblx0YmluZDogZnVuY3Rpb24oIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIG51bGwsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuYmluZDogZnVuY3Rpb24oIHR5cGVzLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYoIHR5cGVzLCBudWxsLCBmbiApO1xuXHR9LFxuXG5cdGRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHR1bmRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBmbiApIHtcblxuXHRcdC8vICggbmFtZXNwYWNlICkgb3IgKCBzZWxlY3RvciwgdHlwZXMgWywgZm5dIClcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/XG5cdFx0XHR0aGlzLm9mZiggc2VsZWN0b3IsIFwiKipcIiApIDpcblx0XHRcdHRoaXMub2ZmKCB0eXBlcywgc2VsZWN0b3IgfHwgXCIqKlwiLCBmbiApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5ob2xkUmVhZHkgPSBmdW5jdGlvbiggaG9sZCApIHtcblx0aWYgKCBob2xkICkge1xuXHRcdGpRdWVyeS5yZWFkeVdhaXQrKztcblx0fSBlbHNlIHtcblx0XHRqUXVlcnkucmVhZHkoIHRydWUgKTtcblx0fVxufTtcbmpRdWVyeS5pc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbmpRdWVyeS5wYXJzZUpTT04gPSBKU09OLnBhcnNlO1xualF1ZXJ5Lm5vZGVOYW1lID0gbm9kZU5hbWU7XG5cblxuXG5cbi8vIFJlZ2lzdGVyIGFzIGEgbmFtZWQgQU1EIG1vZHVsZSwgc2luY2UgalF1ZXJ5IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBvdGhlclxuLy8gZmlsZXMgdGhhdCBtYXkgdXNlIGRlZmluZSwgYnV0IG5vdCB2aWEgYSBwcm9wZXIgY29uY2F0ZW5hdGlvbiBzY3JpcHQgdGhhdFxuLy8gdW5kZXJzdGFuZHMgYW5vbnltb3VzIEFNRCBtb2R1bGVzLiBBIG5hbWVkIEFNRCBpcyBzYWZlc3QgYW5kIG1vc3Qgcm9idXN0XG4vLyB3YXkgdG8gcmVnaXN0ZXIuIExvd2VyY2FzZSBqcXVlcnkgaXMgdXNlZCBiZWNhdXNlIEFNRCBtb2R1bGUgbmFtZXMgYXJlXG4vLyBkZXJpdmVkIGZyb20gZmlsZSBuYW1lcywgYW5kIGpRdWVyeSBpcyBub3JtYWxseSBkZWxpdmVyZWQgaW4gYSBsb3dlcmNhc2Vcbi8vIGZpbGUgbmFtZS4gRG8gdGhpcyBhZnRlciBjcmVhdGluZyB0aGUgZ2xvYmFsIHNvIHRoYXQgaWYgYW4gQU1EIG1vZHVsZSB3YW50c1xuLy8gdG8gY2FsbCBub0NvbmZsaWN0IHRvIGhpZGUgdGhpcyB2ZXJzaW9uIG9mIGpRdWVyeSwgaXQgd2lsbCB3b3JrLlxuXG4vLyBOb3RlIHRoYXQgZm9yIG1heGltdW0gcG9ydGFiaWxpdHksIGxpYnJhcmllcyB0aGF0IGFyZSBub3QgalF1ZXJ5IHNob3VsZFxuLy8gZGVjbGFyZSB0aGVtc2VsdmVzIGFzIGFub255bW91cyBtb2R1bGVzLCBhbmQgYXZvaWQgc2V0dGluZyBhIGdsb2JhbCBpZiBhblxuLy8gQU1EIGxvYWRlciBpcyBwcmVzZW50LiBqUXVlcnkgaXMgYSBzcGVjaWFsIGNhc2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcmJ1cmtlL3JlcXVpcmVqcy93aWtpL1VwZGF0aW5nLWV4aXN0aW5nLWxpYnJhcmllcyN3aWtpLWFub25cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKCBcImpxdWVyeVwiLCBbXSwgZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGpRdWVyeTtcblx0fSApO1xufVxuXG5cblxuXG52YXJcblxuXHQvLyBNYXAgb3ZlciBqUXVlcnkgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0X2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksXG5cblx0Ly8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0XyQgPSB3aW5kb3cuJDtcblxualF1ZXJ5Lm5vQ29uZmxpY3QgPSBmdW5jdGlvbiggZGVlcCApIHtcblx0aWYgKCB3aW5kb3cuJCA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy4kID0gXyQ7XG5cdH1cblxuXHRpZiAoIGRlZXAgJiYgd2luZG93LmpRdWVyeSA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5O1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeTtcbn07XG5cbi8vIEV4cG9zZSBqUXVlcnkgYW5kICQgaWRlbnRpZmllcnMsIGV2ZW4gaW4gQU1EXG4vLyAoIzcxMDIjY29tbWVudDoxMCwgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvcHVsbC81NTcpXG4vLyBhbmQgQ29tbW9uSlMgZm9yIGJyb3dzZXIgZW11bGF0b3JzICgjMTM1NjYpXG5pZiAoICFub0dsb2JhbCApIHtcblx0d2luZG93LmpRdWVyeSA9IHdpbmRvdy4kID0galF1ZXJ5O1xufVxuXG5cblxuXG5yZXR1cm4galF1ZXJ5O1xufSApO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvanF1ZXJ5L2Rpc3QvanF1ZXJ5LmpzXG4vLyBtb2R1bGUgaWQgPSAwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIEphdmFzY3JpcHRcblxuaW1wb3J0ICQgZnJvbSAnanF1ZXJ5J1xuaW1wb3J0ICdib290c3RyYXAnO1xuaW1wb3J0ICdib290c3RyYXAtc2VsZWN0JztcbmltcG9ydCAnYm9vdHN0cmFwLXZhbGlkYXRvcic7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQnO1xuXG5cbi8vIENTU1xuXG5pbXBvcnQgJ2Jvb3RzdHJhcC9kaXN0L2Nzcy9ib290c3RyYXAuY3NzJztcbmltcG9ydCAnYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzcyc7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3MnO1xuaW1wb3J0ICcuL3N0eWxlLmNzcydcblxuJChmdW5jdGlvbiAoKSB7XG4gIFxuICAkKFwiI215SW5wdXRcIikub24oXCJrZXl1cFwiLCBmdW5jdGlvbihldmVudE9iamVjdCkge1xuICAgIFxuICAgIHZhciBpbnB1dCwgZmlsdGVyLCB1bCwgbGksIGEsIGk7XG5cbiAgICBpbnB1dCA9IGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQ7XG4gICAgZmlsdGVyID0gaW5wdXQudmFsdWUudG9VcHBlckNhc2UoKTtcbiAgICB1bCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXlVTFwiKTtcbiAgICBsaSA9IHVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdhJyk7XG5cbiAgICAvLyBMb29wIHRocm91Z2ggYWxsIGxpc3QgaXRlbXMsIGFuZCBoaWRlIHRob3NlIHdobyBkb24ndCBtYXRjaCB0aGUgc2VhcmNoIHF1ZXJ5XG4gICAgZm9yIChpID0gMDsgaSA8IGxpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhID0gbGlbaV07IC8vbGlbaV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJhXCIpWzBdO1xuICAgICAgaWYgKGEuaW5uZXJIVE1MLnRvVXBwZXJDYXNlKCkuaW5kZXhPZihmaWx0ZXIpID4gLTEpIHtcblx0bGlbaV0uc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICB9IGVsc2Uge1xuXHRsaVtpXS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICB9XG4gICAgfVxuXG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNoZWNrVXNlcm5hbWVJbnB1dEhhbmRsZXIoZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgaW5wdXRfZWwgPSAkKGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQpO1xuICAgIHZhciBkYXRhID0gSlNPTi5zdHJpbmdpZnkoe1widXNlcm5hbWVcIjogaW5wdXRfZWwudmFsKCl9KTtcbiAgICB2YXIgdXJsID0gYC90ZWFjaGVycy9jaGVja191c2VybmFtZS8ke2lucHV0X2VsLnZhbCgpfWBcbiAgICAgICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHRpZiAocmVzdWx0LmV4aXN0cykge1xuXHQgIGNvbnNvbGUubG9nKFwiVXNlcm5hbWUgZXhpc3RzXCIpO1xuXHR9XG4gICAgICB9LFxuICAgICAgXCJqc29uXCJcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gdXNlcm5hbWVHZW5lcmF0b3IoZXZlbnRPYmplY3QsIGZpcnN0bmFtZSwgc3VybmFtZSkge1xuICAgIHZhciBpbnB1dF9lbCA9ICQoZXZlbnRPYmplY3QuY3VycmVudFRhcmdldCk7XG4gICAgaW5wdXRfZWwudmFsKGZpcnN0bmFtZStcIi5cIitzdXJuYW1lKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlbGV0ZVJlbGF0aW9uSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgXG4gICAgICAkLmFqYXgoe1xuXHR1cmw6IHVybCxcblx0dHlwZTogJ0RFTEVURScsXG5cdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3VsdCkge1xuXHQgIGVsLmNsb3Nlc3QoXCIubGlzdC1ncm91cC1pdGVtXCIpLnJlbW92ZSgpO1xuXHQgIG1vZGFsRWwubW9kYWwoJ2hpZGUnKTtcblx0fVxuICAgICAgfSk7XG4gICAgICBcbiAgICB9KTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZnVuY3Rpb24gZGVsZXRlSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgICBcbiAgICAgICQuYWpheCh7XG5cdHVybDogdXJsLFxuXHR0eXBlOiAnREVMRVRFJyxcblx0c3VjY2VzczogZnVuY3Rpb24ocmVzdWx0KSB7XG5cdCAgbW9kYWxFbC5tb2RhbCgnaGlkZScpO1xuXHQgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKHJlc3VsdC5yZWRpcmVjdF91cmwpO1xuXHR9XG4gICAgICB9KTtcbiAgICAgIFxuICAgIH0pO1xuICAgIFxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgXG4gICQoXCIuYWpheC1wb3N0XCIpLm9uKFwiY2xpY2tcIiwgZnVuY3Rpb24oZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgc2VsZWN0X2VsID0gJChcIiNcIit0aGlzLmRhdGFzZXQuc2VsZWN0KS5maXJzdCgpO1xuICAgIHZhciBsaXN0Z3JvdXBfZWwgPSAkKFwiI1wiK3RoaXMuZGF0YXNldC5saXN0Z3JvdXApLmZpcnN0KCk7XG4gICAgdmFyIHVybCA9IHRoaXMuZGF0YXNldC51cmw7XG4gICAgdmFyIGRhdGEgPSBKU09OLnN0cmluZ2lmeSh7XCJpZHNcIjogc2VsZWN0X2VsLnZhbCgpfSk7XG4gICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHR2YXIgaTtcblx0aWYgKHJlc3VsdC5lbGVtZW50cyAhPSBudWxsKSB7XG5cdCAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5lbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHQgICAgdmFyIG5ld0l0ZW0gPSBgXG5cdFx0PGEgaHJlZj1cIiNcIiBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBjbGVhcmZpeFwiPlxuXHRcdDxzcGFuIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1ib29rXCI+PC9zcGFuPlxuXHRcdCR7cmVzdWx0LmVsZW1lbnRzW2ldLk5hbWV9XG5cdFx0PHNwYW4gY2xhc3M9XCJwdWxsLXJpZ2h0XCI+XG5cdFx0PGJ1dHRvbiBkYXRhLXVybD1cIi8ke3Jlc3VsdC5uYW1lMX0vJHtyZXN1bHQuaWQxfS8ke3Jlc3VsdC5uYW1lMn0vJHtyZXN1bHQuaWQyW2ldfS9kZWxldGVcIiBjbGFzcz1cImJ0biBidG4teHMgYnRuLXdhcm5pbmcga2FybWVuLWFqYXgtZGVsZXRlXCI+XG5cdFx0PHNwYW4gY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXRyYXNoXCI+PC9zcGFuPlxuXHRcdDwvYnV0dG9uPlxuXHQgICAgICA8L3NwYW4+XG5cdCAgICAgIGA7XG5cdCAgICAkKGxpc3Rncm91cF9lbCkuYXBwZW5kKG5ld0l0ZW0pO1xuXHQgICAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblx0ICB9XG5cdH1cbiAgICAgIFxuICAgICAgfSxcbiAgICAgIFwianNvblwiXG4gICAgKTtcblxuICAgIHNlbGVjdF9lbC52YWwoJ2RlZmF1bHQnKTtcbiAgICBzZWxlY3RfZWwuc2VsZWN0cGlja2VyKFwicmVmcmVzaFwiKTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gICAgXG4gIH0pO1xuXG4gICQoXCIua2FybWVuLWFqYXgtZGVsZXRlLXJlbGF0aW9uXCIpLm9uKFwiY2xpY2tcIiwgZGVsZXRlUmVsYXRpb25IYW5kbGVyKTtcbiAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblxufSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBUaGlzIGZpbGUgaXMgYXV0b2dlbmVyYXRlZCB2aWEgdGhlIGBjb21tb25qc2AgR3J1bnQgdGFzay4gWW91IGNhbiByZXF1aXJlKCkgdGhpcyBmaWxlIGluIGEgQ29tbW9uSlMgZW52aXJvbm1lbnQuXG5yZXF1aXJlKCcuLi8uLi9qcy90cmFuc2l0aW9uLmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL2FsZXJ0LmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL2J1dHRvbi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9jYXJvdXNlbC5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9jb2xsYXBzZS5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9kcm9wZG93bi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9tb2RhbC5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy90b29sdGlwLmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL3BvcG92ZXIuanMnKVxucmVxdWlyZSgnLi4vLi4vanMvc2Nyb2xsc3B5LmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL3RhYi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9hZmZpeC5qcycpXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvanMvbnBtLmpzXG4vLyBtb2R1bGUgaWQgPSAyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiB0cmFuc2l0aW9uLmpzIHYzLjMuN1xuICogaHR0cDovL2dldGJvb3RzdHJhcC5jb20vamF2YXNjcmlwdC8jdHJhbnNpdGlvbnNcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTEtMjAxNiBUd2l0dGVyLCBJbmMuXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cblxuK2Z1bmN0aW9uICgkKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBDU1MgVFJBTlNJVElPTiBTVVBQT1JUIChTaG91dG91dDogaHR0cDovL3d3dy5tb2Rlcm5penIuY29tLylcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gdHJhbnNpdGlvbkVuZCgpIHtcbiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib290c3RyYXAnKVxuXG4gICAgdmFyIHRyYW5zRW5kRXZlbnROYW1lcyA9IHtcbiAgICAgIFdlYmtpdFRyYW5zaXRpb24gOiAnd2Via2l0VHJhbnNpdGlvbkVuZCcsXG4gICAgICBNb3pUcmFuc2l0aW9uICAgIDogJ3RyYW5zaXRpb25lbmQnLFxuICAgICAgT1RyYW5zaXRpb24gICAgICA6ICdvVHJhbnNpdGlvbkVuZCBvdHJhbnNpdGlvbmVuZCcsXG4gICAgICB0cmFuc2l0aW9uICAgICAgIDogJ3RyYW5zaXRpb25lbmQnXG4gICAgfVxuXG4gICAgZm9yICh2YXIgbmFtZSBpbiB0cmFuc0VuZEV2ZW50TmFtZXMpIHtcbiAgICAgIGlmIChlbC5zdHlsZVtuYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB7IGVuZDogdHJhbnNFbmRFdmVudE5hbWVzW25hbWVdIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2UgLy8gZXhwbGljaXQgZm9yIGllOCAoICAuXy4pXG4gIH1cblxuICAvLyBodHRwOi8vYmxvZy5hbGV4bWFjY2F3LmNvbS9jc3MtdHJhbnNpdGlvbnNcbiAgJC5mbi5lbXVsYXRlVHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uIChkdXJhdGlvbikge1xuICAgIHZhciBjYWxsZWQgPSBmYWxzZVxuICAgIHZhciAkZWwgPSB0aGlzXG4gICAgJCh0aGlzKS5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGZ1bmN0aW9uICgpIHsgY2FsbGVkID0gdHJ1ZSB9KVxuICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHsgaWYgKCFjYWxsZWQpICQoJGVsKS50cmlnZ2VyKCQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZCkgfVxuICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIGR1cmF0aW9uKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAkKGZ1bmN0aW9uICgpIHtcbiAgICAkLnN1cHBvcnQudHJhbnNpdGlvbiA9IHRyYW5zaXRpb25FbmQoKVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuXG5cbiAgICAkLmV2ZW50LnNwZWNpYWwuYnNUcmFuc2l0aW9uRW5kID0ge1xuICAgICAgYmluZFR5cGU6ICQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZCxcbiAgICAgIGRlbGVnYXRlVHlwZTogJC5zdXBwb3J0LnRyYW5zaXRpb24uZW5kLFxuICAgICAgaGFuZGxlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoJChlLnRhcmdldCkuaXModGhpcykpIHJldHVybiBlLmhhbmRsZU9iai5oYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90cmFuc2l0aW9uLmpzXG4vLyBtb2R1bGUgaWQgPSAzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBhbGVydC5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI2FsZXJ0c1xuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIEFMRVJUIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBkaXNtaXNzID0gJ1tkYXRhLWRpc21pc3M9XCJhbGVydFwiXSdcbiAgdmFyIEFsZXJ0ICAgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAkKGVsKS5vbignY2xpY2snLCBkaXNtaXNzLCB0aGlzLmNsb3NlKVxuICB9XG5cbiAgQWxlcnQuVkVSU0lPTiA9ICczLjMuNydcblxuICBBbGVydC5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwXG5cbiAgQWxlcnQucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgJHRoaXMgICAgPSAkKHRoaXMpXG4gICAgdmFyIHNlbGVjdG9yID0gJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKVxuXG4gICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgc2VsZWN0b3IgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICAgIHNlbGVjdG9yID0gc2VsZWN0b3IgJiYgc2VsZWN0b3IucmVwbGFjZSgvLiooPz0jW15cXHNdKiQpLywgJycpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB9XG5cbiAgICB2YXIgJHBhcmVudCA9ICQoc2VsZWN0b3IgPT09ICcjJyA/IFtdIDogc2VsZWN0b3IpXG5cbiAgICBpZiAoZSkgZS5wcmV2ZW50RGVmYXVsdCgpXG5cbiAgICBpZiAoISRwYXJlbnQubGVuZ3RoKSB7XG4gICAgICAkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgnLmFsZXJ0JylcbiAgICB9XG5cbiAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ2Nsb3NlLmJzLmFsZXJ0JykpXG5cbiAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICAkcGFyZW50LnJlbW92ZUNsYXNzKCdpbicpXG5cbiAgICBmdW5jdGlvbiByZW1vdmVFbGVtZW50KCkge1xuICAgICAgLy8gZGV0YWNoIGZyb20gcGFyZW50LCBmaXJlIGV2ZW50IHRoZW4gY2xlYW4gdXAgZGF0YVxuICAgICAgJHBhcmVudC5kZXRhY2goKS50cmlnZ2VyKCdjbG9zZWQuYnMuYWxlcnQnKS5yZW1vdmUoKVxuICAgIH1cblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmICRwYXJlbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAkcGFyZW50XG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIHJlbW92ZUVsZW1lbnQpXG4gICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChBbGVydC5UUkFOU0lUSU9OX0RVUkFUSU9OKSA6XG4gICAgICByZW1vdmVFbGVtZW50KClcbiAgfVxuXG5cbiAgLy8gQUxFUlQgUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgPSAkdGhpcy5kYXRhKCdicy5hbGVydCcpXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMuYWxlcnQnLCAoZGF0YSA9IG5ldyBBbGVydCh0aGlzKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dLmNhbGwoJHRoaXMpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmFsZXJ0XG5cbiAgJC5mbi5hbGVydCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmFsZXJ0LkNvbnN0cnVjdG9yID0gQWxlcnRcblxuXG4gIC8vIEFMRVJUIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5hbGVydC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYWxlcnQgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBBTEVSVCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5hbGVydC5kYXRhLWFwaScsIGRpc21pc3MsIEFsZXJ0LnByb3RvdHlwZS5jbG9zZSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2FsZXJ0LmpzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBidXR0b24uanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNidXR0b25zXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQlVUVE9OIFBVQkxJQyBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBCdXR0b24gPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGVsZW1lbnQgID0gJChlbGVtZW50KVxuICAgIHRoaXMub3B0aW9ucyAgID0gJC5leHRlbmQoe30sIEJ1dHRvbi5ERUZBVUxUUywgb3B0aW9ucylcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlXG4gIH1cblxuICBCdXR0b24uVkVSU0lPTiAgPSAnMy4zLjcnXG5cbiAgQnV0dG9uLkRFRkFVTFRTID0ge1xuICAgIGxvYWRpbmdUZXh0OiAnbG9hZGluZy4uLidcbiAgfVxuXG4gIEJ1dHRvbi5wcm90b3R5cGUuc2V0U3RhdGUgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICB2YXIgZCAgICA9ICdkaXNhYmxlZCdcbiAgICB2YXIgJGVsICA9IHRoaXMuJGVsZW1lbnRcbiAgICB2YXIgdmFsICA9ICRlbC5pcygnaW5wdXQnKSA/ICd2YWwnIDogJ2h0bWwnXG4gICAgdmFyIGRhdGEgPSAkZWwuZGF0YSgpXG5cbiAgICBzdGF0ZSArPSAnVGV4dCdcblxuICAgIGlmIChkYXRhLnJlc2V0VGV4dCA9PSBudWxsKSAkZWwuZGF0YSgncmVzZXRUZXh0JywgJGVsW3ZhbF0oKSlcblxuICAgIC8vIHB1c2ggdG8gZXZlbnQgbG9vcCB0byBhbGxvdyBmb3JtcyB0byBzdWJtaXRcbiAgICBzZXRUaW1lb3V0KCQucHJveHkoZnVuY3Rpb24gKCkge1xuICAgICAgJGVsW3ZhbF0oZGF0YVtzdGF0ZV0gPT0gbnVsbCA/IHRoaXMub3B0aW9uc1tzdGF0ZV0gOiBkYXRhW3N0YXRlXSlcblxuICAgICAgaWYgKHN0YXRlID09ICdsb2FkaW5nVGV4dCcpIHtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlXG4gICAgICAgICRlbC5hZGRDbGFzcyhkKS5hdHRyKGQsIGQpLnByb3AoZCwgdHJ1ZSlcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0xvYWRpbmcpIHtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZVxuICAgICAgICAkZWwucmVtb3ZlQ2xhc3MoZCkucmVtb3ZlQXR0cihkKS5wcm9wKGQsIGZhbHNlKVxuICAgICAgfVxuICAgIH0sIHRoaXMpLCAwKVxuICB9XG5cbiAgQnV0dG9uLnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNoYW5nZWQgPSB0cnVlXG4gICAgdmFyICRwYXJlbnQgPSB0aGlzLiRlbGVtZW50LmNsb3Nlc3QoJ1tkYXRhLXRvZ2dsZT1cImJ1dHRvbnNcIl0nKVxuXG4gICAgaWYgKCRwYXJlbnQubGVuZ3RoKSB7XG4gICAgICB2YXIgJGlucHV0ID0gdGhpcy4kZWxlbWVudC5maW5kKCdpbnB1dCcpXG4gICAgICBpZiAoJGlucHV0LnByb3AoJ3R5cGUnKSA9PSAncmFkaW8nKSB7XG4gICAgICAgIGlmICgkaW5wdXQucHJvcCgnY2hlY2tlZCcpKSBjaGFuZ2VkID0gZmFsc2VcbiAgICAgICAgJHBhcmVudC5maW5kKCcuYWN0aXZlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICB9IGVsc2UgaWYgKCRpbnB1dC5wcm9wKCd0eXBlJykgPT0gJ2NoZWNrYm94Jykge1xuICAgICAgICBpZiAoKCRpbnB1dC5wcm9wKCdjaGVja2VkJykpICE9PSB0aGlzLiRlbGVtZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSkgY2hhbmdlZCA9IGZhbHNlXG4gICAgICAgIHRoaXMuJGVsZW1lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICB9XG4gICAgICAkaW5wdXQucHJvcCgnY2hlY2tlZCcsIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2FjdGl2ZScpKVxuICAgICAgaWYgKGNoYW5nZWQpICRpbnB1dC50cmlnZ2VyKCdjaGFuZ2UnKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLiRlbGVtZW50LmF0dHIoJ2FyaWEtcHJlc3NlZCcsICF0aGlzLiRlbGVtZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSlcbiAgICAgIHRoaXMuJGVsZW1lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgfVxuICB9XG5cblxuICAvLyBCVVRUT04gUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmJ1dHRvbicpXG4gICAgICB2YXIgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMuYnV0dG9uJywgKGRhdGEgPSBuZXcgQnV0dG9uKHRoaXMsIG9wdGlvbnMpKSlcblxuICAgICAgaWYgKG9wdGlvbiA9PSAndG9nZ2xlJykgZGF0YS50b2dnbGUoKVxuICAgICAgZWxzZSBpZiAob3B0aW9uKSBkYXRhLnNldFN0YXRlKG9wdGlvbilcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uYnV0dG9uXG5cbiAgJC5mbi5idXR0b24gICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5idXR0b24uQ29uc3RydWN0b3IgPSBCdXR0b25cblxuXG4gIC8vIEJVVFRPTiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLmJ1dHRvbi5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYnV0dG9uID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gQlVUVE9OIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpXG4gICAgLm9uKCdjbGljay5icy5idXR0b24uZGF0YS1hcGknLCAnW2RhdGEtdG9nZ2xlXj1cImJ1dHRvblwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgJGJ0biA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJy5idG4nKVxuICAgICAgUGx1Z2luLmNhbGwoJGJ0biwgJ3RvZ2dsZScpXG4gICAgICBpZiAoISgkKGUudGFyZ2V0KS5pcygnaW5wdXRbdHlwZT1cInJhZGlvXCJdLCBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0nKSkpIHtcbiAgICAgICAgLy8gUHJldmVudCBkb3VibGUgY2xpY2sgb24gcmFkaW9zLCBhbmQgdGhlIGRvdWJsZSBzZWxlY3Rpb25zIChzbyBjYW5jZWxsYXRpb24pIG9uIGNoZWNrYm94ZXNcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIC8vIFRoZSB0YXJnZXQgY29tcG9uZW50IHN0aWxsIHJlY2VpdmUgdGhlIGZvY3VzXG4gICAgICAgIGlmICgkYnRuLmlzKCdpbnB1dCxidXR0b24nKSkgJGJ0bi50cmlnZ2VyKCdmb2N1cycpXG4gICAgICAgIGVsc2UgJGJ0bi5maW5kKCdpbnB1dDp2aXNpYmxlLGJ1dHRvbjp2aXNpYmxlJykuZmlyc3QoKS50cmlnZ2VyKCdmb2N1cycpXG4gICAgICB9XG4gICAgfSlcbiAgICAub24oJ2ZvY3VzLmJzLmJ1dHRvbi5kYXRhLWFwaSBibHVyLmJzLmJ1dHRvbi5kYXRhLWFwaScsICdbZGF0YS10b2dnbGVePVwiYnV0dG9uXCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICQoZS50YXJnZXQpLmNsb3Nlc3QoJy5idG4nKS50b2dnbGVDbGFzcygnZm9jdXMnLCAvXmZvY3VzKGluKT8kLy50ZXN0KGUudHlwZSkpXG4gICAgfSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2J1dHRvbi5qc1xuLy8gbW9kdWxlIGlkID0gNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogY2Fyb3VzZWwuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNjYXJvdXNlbFxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIENBUk9VU0VMIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBDYXJvdXNlbCA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy4kZWxlbWVudCAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLiRpbmRpY2F0b3JzID0gdGhpcy4kZWxlbWVudC5maW5kKCcuY2Fyb3VzZWwtaW5kaWNhdG9ycycpXG4gICAgdGhpcy5vcHRpb25zICAgICA9IG9wdGlvbnNcbiAgICB0aGlzLnBhdXNlZCAgICAgID0gbnVsbFxuICAgIHRoaXMuc2xpZGluZyAgICAgPSBudWxsXG4gICAgdGhpcy5pbnRlcnZhbCAgICA9IG51bGxcbiAgICB0aGlzLiRhY3RpdmUgICAgID0gbnVsbFxuICAgIHRoaXMuJGl0ZW1zICAgICAgPSBudWxsXG5cbiAgICB0aGlzLm9wdGlvbnMua2V5Ym9hcmQgJiYgdGhpcy4kZWxlbWVudC5vbigna2V5ZG93bi5icy5jYXJvdXNlbCcsICQucHJveHkodGhpcy5rZXlkb3duLCB0aGlzKSlcblxuICAgIHRoaXMub3B0aW9ucy5wYXVzZSA9PSAnaG92ZXInICYmICEoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSAmJiB0aGlzLiRlbGVtZW50XG4gICAgICAub24oJ21vdXNlZW50ZXIuYnMuY2Fyb3VzZWwnLCAkLnByb3h5KHRoaXMucGF1c2UsIHRoaXMpKVxuICAgICAgLm9uKCdtb3VzZWxlYXZlLmJzLmNhcm91c2VsJywgJC5wcm94eSh0aGlzLmN5Y2xlLCB0aGlzKSlcbiAgfVxuXG4gIENhcm91c2VsLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIENhcm91c2VsLlRSQU5TSVRJT05fRFVSQVRJT04gPSA2MDBcblxuICBDYXJvdXNlbC5ERUZBVUxUUyA9IHtcbiAgICBpbnRlcnZhbDogNTAwMCxcbiAgICBwYXVzZTogJ2hvdmVyJyxcbiAgICB3cmFwOiB0cnVlLFxuICAgIGtleWJvYXJkOiB0cnVlXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUua2V5ZG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZS50YXJnZXQudGFnTmFtZSkpIHJldHVyblxuICAgIHN3aXRjaCAoZS53aGljaCkge1xuICAgICAgY2FzZSAzNzogdGhpcy5wcmV2KCk7IGJyZWFrXG4gICAgICBjYXNlIDM5OiB0aGlzLm5leHQoKTsgYnJlYWtcbiAgICAgIGRlZmF1bHQ6IHJldHVyblxuICAgIH1cblxuICAgIGUucHJldmVudERlZmF1bHQoKVxuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmN5Y2xlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBlIHx8ICh0aGlzLnBhdXNlZCA9IGZhbHNlKVxuXG4gICAgdGhpcy5pbnRlcnZhbCAmJiBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWwpXG5cbiAgICB0aGlzLm9wdGlvbnMuaW50ZXJ2YWxcbiAgICAgICYmICF0aGlzLnBhdXNlZFxuICAgICAgJiYgKHRoaXMuaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgkLnByb3h5KHRoaXMubmV4dCwgdGhpcyksIHRoaXMub3B0aW9ucy5pbnRlcnZhbCkpXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmdldEl0ZW1JbmRleCA9IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgdGhpcy4kaXRlbXMgPSBpdGVtLnBhcmVudCgpLmNoaWxkcmVuKCcuaXRlbScpXG4gICAgcmV0dXJuIHRoaXMuJGl0ZW1zLmluZGV4KGl0ZW0gfHwgdGhpcy4kYWN0aXZlKVxuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmdldEl0ZW1Gb3JEaXJlY3Rpb24gPSBmdW5jdGlvbiAoZGlyZWN0aW9uLCBhY3RpdmUpIHtcbiAgICB2YXIgYWN0aXZlSW5kZXggPSB0aGlzLmdldEl0ZW1JbmRleChhY3RpdmUpXG4gICAgdmFyIHdpbGxXcmFwID0gKGRpcmVjdGlvbiA9PSAncHJldicgJiYgYWN0aXZlSW5kZXggPT09IDApXG4gICAgICAgICAgICAgICAgfHwgKGRpcmVjdGlvbiA9PSAnbmV4dCcgJiYgYWN0aXZlSW5kZXggPT0gKHRoaXMuJGl0ZW1zLmxlbmd0aCAtIDEpKVxuICAgIGlmICh3aWxsV3JhcCAmJiAhdGhpcy5vcHRpb25zLndyYXApIHJldHVybiBhY3RpdmVcbiAgICB2YXIgZGVsdGEgPSBkaXJlY3Rpb24gPT0gJ3ByZXYnID8gLTEgOiAxXG4gICAgdmFyIGl0ZW1JbmRleCA9IChhY3RpdmVJbmRleCArIGRlbHRhKSAlIHRoaXMuJGl0ZW1zLmxlbmd0aFxuICAgIHJldHVybiB0aGlzLiRpdGVtcy5lcShpdGVtSW5kZXgpXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUudG8gPSBmdW5jdGlvbiAocG9zKSB7XG4gICAgdmFyIHRoYXQgICAgICAgID0gdGhpc1xuICAgIHZhciBhY3RpdmVJbmRleCA9IHRoaXMuZ2V0SXRlbUluZGV4KHRoaXMuJGFjdGl2ZSA9IHRoaXMuJGVsZW1lbnQuZmluZCgnLml0ZW0uYWN0aXZlJykpXG5cbiAgICBpZiAocG9zID4gKHRoaXMuJGl0ZW1zLmxlbmd0aCAtIDEpIHx8IHBvcyA8IDApIHJldHVyblxuXG4gICAgaWYgKHRoaXMuc2xpZGluZykgICAgICAgcmV0dXJuIHRoaXMuJGVsZW1lbnQub25lKCdzbGlkLmJzLmNhcm91c2VsJywgZnVuY3Rpb24gKCkgeyB0aGF0LnRvKHBvcykgfSkgLy8geWVzLCBcInNsaWRcIlxuICAgIGlmIChhY3RpdmVJbmRleCA9PSBwb3MpIHJldHVybiB0aGlzLnBhdXNlKCkuY3ljbGUoKVxuXG4gICAgcmV0dXJuIHRoaXMuc2xpZGUocG9zID4gYWN0aXZlSW5kZXggPyAnbmV4dCcgOiAncHJldicsIHRoaXMuJGl0ZW1zLmVxKHBvcykpXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoZSkge1xuICAgIGUgfHwgKHRoaXMucGF1c2VkID0gdHJ1ZSlcblxuICAgIGlmICh0aGlzLiRlbGVtZW50LmZpbmQoJy5uZXh0LCAucHJldicpLmxlbmd0aCAmJiAkLnN1cHBvcnQudHJhbnNpdGlvbikge1xuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZClcbiAgICAgIHRoaXMuY3ljbGUodHJ1ZSlcbiAgICB9XG5cbiAgICB0aGlzLmludGVydmFsID0gY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5uZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnNsaWRpbmcpIHJldHVyblxuICAgIHJldHVybiB0aGlzLnNsaWRlKCduZXh0JylcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnNsaWRpbmcpIHJldHVyblxuICAgIHJldHVybiB0aGlzLnNsaWRlKCdwcmV2JylcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5zbGlkZSA9IGZ1bmN0aW9uICh0eXBlLCBuZXh0KSB7XG4gICAgdmFyICRhY3RpdmUgICA9IHRoaXMuJGVsZW1lbnQuZmluZCgnLml0ZW0uYWN0aXZlJylcbiAgICB2YXIgJG5leHQgICAgID0gbmV4dCB8fCB0aGlzLmdldEl0ZW1Gb3JEaXJlY3Rpb24odHlwZSwgJGFjdGl2ZSlcbiAgICB2YXIgaXNDeWNsaW5nID0gdGhpcy5pbnRlcnZhbFxuICAgIHZhciBkaXJlY3Rpb24gPSB0eXBlID09ICduZXh0JyA/ICdsZWZ0JyA6ICdyaWdodCdcbiAgICB2YXIgdGhhdCAgICAgID0gdGhpc1xuXG4gICAgaWYgKCRuZXh0Lmhhc0NsYXNzKCdhY3RpdmUnKSkgcmV0dXJuICh0aGlzLnNsaWRpbmcgPSBmYWxzZSlcblxuICAgIHZhciByZWxhdGVkVGFyZ2V0ID0gJG5leHRbMF1cbiAgICB2YXIgc2xpZGVFdmVudCA9ICQuRXZlbnQoJ3NsaWRlLmJzLmNhcm91c2VsJywge1xuICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldCxcbiAgICAgIGRpcmVjdGlvbjogZGlyZWN0aW9uXG4gICAgfSlcbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc2xpZGVFdmVudClcbiAgICBpZiAoc2xpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLnNsaWRpbmcgPSB0cnVlXG5cbiAgICBpc0N5Y2xpbmcgJiYgdGhpcy5wYXVzZSgpXG5cbiAgICBpZiAodGhpcy4kaW5kaWNhdG9ycy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuJGluZGljYXRvcnMuZmluZCgnLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuICAgICAgdmFyICRuZXh0SW5kaWNhdG9yID0gJCh0aGlzLiRpbmRpY2F0b3JzLmNoaWxkcmVuKClbdGhpcy5nZXRJdGVtSW5kZXgoJG5leHQpXSlcbiAgICAgICRuZXh0SW5kaWNhdG9yICYmICRuZXh0SW5kaWNhdG9yLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgIH1cblxuICAgIHZhciBzbGlkRXZlbnQgPSAkLkV2ZW50KCdzbGlkLmJzLmNhcm91c2VsJywgeyByZWxhdGVkVGFyZ2V0OiByZWxhdGVkVGFyZ2V0LCBkaXJlY3Rpb246IGRpcmVjdGlvbiB9KSAvLyB5ZXMsIFwic2xpZFwiXG4gICAgaWYgKCQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ3NsaWRlJykpIHtcbiAgICAgICRuZXh0LmFkZENsYXNzKHR5cGUpXG4gICAgICAkbmV4dFswXS5vZmZzZXRXaWR0aCAvLyBmb3JjZSByZWZsb3dcbiAgICAgICRhY3RpdmUuYWRkQ2xhc3MoZGlyZWN0aW9uKVxuICAgICAgJG5leHQuYWRkQ2xhc3MoZGlyZWN0aW9uKVxuICAgICAgJGFjdGl2ZVxuICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgJG5leHQucmVtb3ZlQ2xhc3MoW3R5cGUsIGRpcmVjdGlvbl0uam9pbignICcpKS5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgICAgICAkYWN0aXZlLnJlbW92ZUNsYXNzKFsnYWN0aXZlJywgZGlyZWN0aW9uXS5qb2luKCcgJykpXG4gICAgICAgICAgdGhhdC5zbGlkaW5nID0gZmFsc2VcbiAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcihzbGlkRXZlbnQpXG4gICAgICAgICAgfSwgMClcbiAgICAgICAgfSlcbiAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKENhcm91c2VsLlRSQU5TSVRJT05fRFVSQVRJT04pXG4gICAgfSBlbHNlIHtcbiAgICAgICRhY3RpdmUucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAkbmV4dC5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgIHRoaXMuc2xpZGluZyA9IGZhbHNlXG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc2xpZEV2ZW50KVxuICAgIH1cblxuICAgIGlzQ3ljbGluZyAmJiB0aGlzLmN5Y2xlKClcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuXG4gIC8vIENBUk9VU0VMIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmNhcm91c2VsJylcbiAgICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sIENhcm91c2VsLkRFRkFVTFRTLCAkdGhpcy5kYXRhKCksIHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uKVxuICAgICAgdmFyIGFjdGlvbiAgPSB0eXBlb2Ygb3B0aW9uID09ICdzdHJpbmcnID8gb3B0aW9uIDogb3B0aW9ucy5zbGlkZVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmNhcm91c2VsJywgKGRhdGEgPSBuZXcgQ2Fyb3VzZWwodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ251bWJlcicpIGRhdGEudG8ob3B0aW9uKVxuICAgICAgZWxzZSBpZiAoYWN0aW9uKSBkYXRhW2FjdGlvbl0oKVxuICAgICAgZWxzZSBpZiAob3B0aW9ucy5pbnRlcnZhbCkgZGF0YS5wYXVzZSgpLmN5Y2xlKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uY2Fyb3VzZWxcblxuICAkLmZuLmNhcm91c2VsICAgICAgICAgICAgID0gUGx1Z2luXG4gICQuZm4uY2Fyb3VzZWwuQ29uc3RydWN0b3IgPSBDYXJvdXNlbFxuXG5cbiAgLy8gQ0FST1VTRUwgTk8gQ09ORkxJQ1RcbiAgLy8gPT09PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLmNhcm91c2VsLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5jYXJvdXNlbCA9IG9sZFxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuXG4gIC8vIENBUk9VU0VMIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgdmFyIGNsaWNrSGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIGhyZWZcbiAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICB2YXIgJHRhcmdldCA9ICQoJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKSB8fCAoaHJlZiA9ICR0aGlzLmF0dHIoJ2hyZWYnKSkgJiYgaHJlZi5yZXBsYWNlKC8uKig/PSNbXlxcc10rJCkvLCAnJykpIC8vIHN0cmlwIGZvciBpZTdcbiAgICBpZiAoISR0YXJnZXQuaGFzQ2xhc3MoJ2Nhcm91c2VsJykpIHJldHVyblxuICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sICR0YXJnZXQuZGF0YSgpLCAkdGhpcy5kYXRhKCkpXG4gICAgdmFyIHNsaWRlSW5kZXggPSAkdGhpcy5hdHRyKCdkYXRhLXNsaWRlLXRvJylcbiAgICBpZiAoc2xpZGVJbmRleCkgb3B0aW9ucy5pbnRlcnZhbCA9IGZhbHNlXG5cbiAgICBQbHVnaW4uY2FsbCgkdGFyZ2V0LCBvcHRpb25zKVxuXG4gICAgaWYgKHNsaWRlSW5kZXgpIHtcbiAgICAgICR0YXJnZXQuZGF0YSgnYnMuY2Fyb3VzZWwnKS50byhzbGlkZUluZGV4KVxuICAgIH1cblxuICAgIGUucHJldmVudERlZmF1bHQoKVxuICB9XG5cbiAgJChkb2N1bWVudClcbiAgICAub24oJ2NsaWNrLmJzLmNhcm91c2VsLmRhdGEtYXBpJywgJ1tkYXRhLXNsaWRlXScsIGNsaWNrSGFuZGxlcilcbiAgICAub24oJ2NsaWNrLmJzLmNhcm91c2VsLmRhdGEtYXBpJywgJ1tkYXRhLXNsaWRlLXRvXScsIGNsaWNrSGFuZGxlcilcblxuICAkKHdpbmRvdykub24oJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgJCgnW2RhdGEtcmlkZT1cImNhcm91c2VsXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJGNhcm91c2VsID0gJCh0aGlzKVxuICAgICAgUGx1Z2luLmNhbGwoJGNhcm91c2VsLCAkY2Fyb3VzZWwuZGF0YSgpKVxuICAgIH0pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9jYXJvdXNlbC5qc1xuLy8gbW9kdWxlIGlkID0gNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogY29sbGFwc2UuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNjb2xsYXBzZVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuLyoganNoaW50IGxhdGVkZWY6IGZhbHNlICovXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQ09MTEFQU0UgUFVCTElDIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgQ29sbGFwc2UgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGVsZW1lbnQgICAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLm9wdGlvbnMgICAgICAgPSAkLmV4dGVuZCh7fSwgQ29sbGFwc2UuREVGQVVMVFMsIG9wdGlvbnMpXG4gICAgdGhpcy4kdHJpZ2dlciAgICAgID0gJCgnW2RhdGEtdG9nZ2xlPVwiY29sbGFwc2VcIl1baHJlZj1cIiMnICsgZWxlbWVudC5pZCArICdcIl0sJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAnW2RhdGEtdG9nZ2xlPVwiY29sbGFwc2VcIl1bZGF0YS10YXJnZXQ9XCIjJyArIGVsZW1lbnQuaWQgKyAnXCJdJylcbiAgICB0aGlzLnRyYW5zaXRpb25pbmcgPSBudWxsXG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnBhcmVudCkge1xuICAgICAgdGhpcy4kcGFyZW50ID0gdGhpcy5nZXRQYXJlbnQoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyh0aGlzLiRlbGVtZW50LCB0aGlzLiR0cmlnZ2VyKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMudG9nZ2xlKSB0aGlzLnRvZ2dsZSgpXG4gIH1cblxuICBDb2xsYXBzZS5WRVJTSU9OICA9ICczLjMuNydcblxuICBDb2xsYXBzZS5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMzUwXG5cbiAgQ29sbGFwc2UuREVGQVVMVFMgPSB7XG4gICAgdG9nZ2xlOiB0cnVlXG4gIH1cblxuICBDb2xsYXBzZS5wcm90b3R5cGUuZGltZW5zaW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBoYXNXaWR0aCA9IHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ3dpZHRoJylcbiAgICByZXR1cm4gaGFzV2lkdGggPyAnd2lkdGgnIDogJ2hlaWdodCdcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnRyYW5zaXRpb25pbmcgfHwgdGhpcy4kZWxlbWVudC5oYXNDbGFzcygnaW4nKSkgcmV0dXJuXG5cbiAgICB2YXIgYWN0aXZlc0RhdGFcbiAgICB2YXIgYWN0aXZlcyA9IHRoaXMuJHBhcmVudCAmJiB0aGlzLiRwYXJlbnQuY2hpbGRyZW4oJy5wYW5lbCcpLmNoaWxkcmVuKCcuaW4sIC5jb2xsYXBzaW5nJylcblxuICAgIGlmIChhY3RpdmVzICYmIGFjdGl2ZXMubGVuZ3RoKSB7XG4gICAgICBhY3RpdmVzRGF0YSA9IGFjdGl2ZXMuZGF0YSgnYnMuY29sbGFwc2UnKVxuICAgICAgaWYgKGFjdGl2ZXNEYXRhICYmIGFjdGl2ZXNEYXRhLnRyYW5zaXRpb25pbmcpIHJldHVyblxuICAgIH1cblxuICAgIHZhciBzdGFydEV2ZW50ID0gJC5FdmVudCgnc2hvdy5icy5jb2xsYXBzZScpXG4gICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKHN0YXJ0RXZlbnQpXG4gICAgaWYgKHN0YXJ0RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgaWYgKGFjdGl2ZXMgJiYgYWN0aXZlcy5sZW5ndGgpIHtcbiAgICAgIFBsdWdpbi5jYWxsKGFjdGl2ZXMsICdoaWRlJylcbiAgICAgIGFjdGl2ZXNEYXRhIHx8IGFjdGl2ZXMuZGF0YSgnYnMuY29sbGFwc2UnLCBudWxsKVxuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb24gPSB0aGlzLmRpbWVuc2lvbigpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlJylcbiAgICAgIC5hZGRDbGFzcygnY29sbGFwc2luZycpW2RpbWVuc2lvbl0oMClcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSlcblxuICAgIHRoaXMuJHRyaWdnZXJcbiAgICAgIC5yZW1vdmVDbGFzcygnY29sbGFwc2VkJylcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSlcblxuICAgIHRoaXMudHJhbnNpdGlvbmluZyA9IDFcblxuICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLnJlbW92ZUNsYXNzKCdjb2xsYXBzaW5nJylcbiAgICAgICAgLmFkZENsYXNzKCdjb2xsYXBzZSBpbicpW2RpbWVuc2lvbl0oJycpXG4gICAgICB0aGlzLnRyYW5zaXRpb25pbmcgPSAwXG4gICAgICB0aGlzLiRlbGVtZW50XG4gICAgICAgIC50cmlnZ2VyKCdzaG93bi5icy5jb2xsYXBzZScpXG4gICAgfVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuIGNvbXBsZXRlLmNhbGwodGhpcylcblxuICAgIHZhciBzY3JvbGxTaXplID0gJC5jYW1lbENhc2UoWydzY3JvbGwnLCBkaW1lbnNpb25dLmpvaW4oJy0nKSlcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsICQucHJveHkoY29tcGxldGUsIHRoaXMpKVxuICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKENvbGxhcHNlLlRSQU5TSVRJT05fRFVSQVRJT04pW2RpbWVuc2lvbl0odGhpcy4kZWxlbWVudFswXVtzY3JvbGxTaXplXSlcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnRyYW5zaXRpb25pbmcgfHwgIXRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2luJykpIHJldHVyblxuXG4gICAgdmFyIHN0YXJ0RXZlbnQgPSAkLkV2ZW50KCdoaWRlLmJzLmNvbGxhcHNlJylcbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc3RhcnRFdmVudClcbiAgICBpZiAoc3RhcnRFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB2YXIgZGltZW5zaW9uID0gdGhpcy5kaW1lbnNpb24oKVxuXG4gICAgdGhpcy4kZWxlbWVudFtkaW1lbnNpb25dKHRoaXMuJGVsZW1lbnRbZGltZW5zaW9uXSgpKVswXS5vZmZzZXRIZWlnaHRcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIC5hZGRDbGFzcygnY29sbGFwc2luZycpXG4gICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlIGluJylcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgZmFsc2UpXG5cbiAgICB0aGlzLiR0cmlnZ2VyXG4gICAgICAuYWRkQ2xhc3MoJ2NvbGxhcHNlZCcpXG4gICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsIGZhbHNlKVxuXG4gICAgdGhpcy50cmFuc2l0aW9uaW5nID0gMVxuXG4gICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgdGhpcy50cmFuc2l0aW9uaW5nID0gMFxuICAgICAgdGhpcy4kZWxlbWVudFxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNpbmcnKVxuICAgICAgICAuYWRkQ2xhc3MoJ2NvbGxhcHNlJylcbiAgICAgICAgLnRyaWdnZXIoJ2hpZGRlbi5icy5jb2xsYXBzZScpXG4gICAgfVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuIGNvbXBsZXRlLmNhbGwodGhpcylcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIFtkaW1lbnNpb25dKDApXG4gICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCAkLnByb3h5KGNvbXBsZXRlLCB0aGlzKSlcbiAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChDb2xsYXBzZS5UUkFOU0lUSU9OX0RVUkFUSU9OKVxuICB9XG5cbiAgQ29sbGFwc2UucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzW3RoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2luJykgPyAnaGlkZScgOiAnc2hvdyddKClcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICQodGhpcy5vcHRpb25zLnBhcmVudClcbiAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXVtkYXRhLXBhcmVudD1cIicgKyB0aGlzLm9wdGlvbnMucGFyZW50ICsgJ1wiXScpXG4gICAgICAuZWFjaCgkLnByb3h5KGZ1bmN0aW9uIChpLCBlbGVtZW50KSB7XG4gICAgICAgIHZhciAkZWxlbWVudCA9ICQoZWxlbWVudClcbiAgICAgICAgdGhpcy5hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoZ2V0VGFyZ2V0RnJvbVRyaWdnZXIoJGVsZW1lbnQpLCAkZWxlbWVudClcbiAgICAgIH0sIHRoaXMpKVxuICAgICAgLmVuZCgpXG4gIH1cblxuICBDb2xsYXBzZS5wcm90b3R5cGUuYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzID0gZnVuY3Rpb24gKCRlbGVtZW50LCAkdHJpZ2dlcikge1xuICAgIHZhciBpc09wZW4gPSAkZWxlbWVudC5oYXNDbGFzcygnaW4nKVxuXG4gICAgJGVsZW1lbnQuYXR0cignYXJpYS1leHBhbmRlZCcsIGlzT3BlbilcbiAgICAkdHJpZ2dlclxuICAgICAgLnRvZ2dsZUNsYXNzKCdjb2xsYXBzZWQnLCAhaXNPcGVuKVxuICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBpc09wZW4pXG4gIH1cblxuICBmdW5jdGlvbiBnZXRUYXJnZXRGcm9tVHJpZ2dlcigkdHJpZ2dlcikge1xuICAgIHZhciBocmVmXG4gICAgdmFyIHRhcmdldCA9ICR0cmlnZ2VyLmF0dHIoJ2RhdGEtdGFyZ2V0JylcbiAgICAgIHx8IChocmVmID0gJHRyaWdnZXIuYXR0cignaHJlZicpKSAmJiBocmVmLnJlcGxhY2UoLy4qKD89I1teXFxzXSskKS8sICcnKSAvLyBzdHJpcCBmb3IgaWU3XG5cbiAgICByZXR1cm4gJCh0YXJnZXQpXG4gIH1cblxuXG4gIC8vIENPTExBUFNFIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmNvbGxhcHNlJylcbiAgICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sIENvbGxhcHNlLkRFRkFVTFRTLCAkdGhpcy5kYXRhKCksIHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uKVxuXG4gICAgICBpZiAoIWRhdGEgJiYgb3B0aW9ucy50b2dnbGUgJiYgL3Nob3d8aGlkZS8udGVzdChvcHRpb24pKSBvcHRpb25zLnRvZ2dsZSA9IGZhbHNlXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmNvbGxhcHNlJywgKGRhdGEgPSBuZXcgQ29sbGFwc2UodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmNvbGxhcHNlXG5cbiAgJC5mbi5jb2xsYXBzZSAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmNvbGxhcHNlLkNvbnN0cnVjdG9yID0gQ29sbGFwc2VcblxuXG4gIC8vIENPTExBUFNFIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5jb2xsYXBzZS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uY29sbGFwc2UgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBDT0xMQVBTRSBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5jb2xsYXBzZS5kYXRhLWFwaScsICdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG5cbiAgICBpZiAoISR0aGlzLmF0dHIoJ2RhdGEtdGFyZ2V0JykpIGUucHJldmVudERlZmF1bHQoKVxuXG4gICAgdmFyICR0YXJnZXQgPSBnZXRUYXJnZXRGcm9tVHJpZ2dlcigkdGhpcylcbiAgICB2YXIgZGF0YSAgICA9ICR0YXJnZXQuZGF0YSgnYnMuY29sbGFwc2UnKVxuICAgIHZhciBvcHRpb24gID0gZGF0YSA/ICd0b2dnbGUnIDogJHRoaXMuZGF0YSgpXG5cbiAgICBQbHVnaW4uY2FsbCgkdGFyZ2V0LCBvcHRpb24pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9jb2xsYXBzZS5qc1xuLy8gbW9kdWxlIGlkID0gN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogZHJvcGRvd24uanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNkcm9wZG93bnNcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTEtMjAxNiBUd2l0dGVyLCBJbmMuXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cblxuK2Z1bmN0aW9uICgkKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBEUk9QRE9XTiBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgYmFja2Ryb3AgPSAnLmRyb3Bkb3duLWJhY2tkcm9wJ1xuICB2YXIgdG9nZ2xlICAgPSAnW2RhdGEtdG9nZ2xlPVwiZHJvcGRvd25cIl0nXG4gIHZhciBEcm9wZG93biA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgJChlbGVtZW50KS5vbignY2xpY2suYnMuZHJvcGRvd24nLCB0aGlzLnRvZ2dsZSlcbiAgfVxuXG4gIERyb3Bkb3duLlZFUlNJT04gPSAnMy4zLjcnXG5cbiAgZnVuY3Rpb24gZ2V0UGFyZW50KCR0aGlzKSB7XG4gICAgdmFyIHNlbGVjdG9yID0gJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKVxuXG4gICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgc2VsZWN0b3IgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICAgIHNlbGVjdG9yID0gc2VsZWN0b3IgJiYgLyNbQS1aYS16XS8udGVzdChzZWxlY3RvcikgJiYgc2VsZWN0b3IucmVwbGFjZSgvLiooPz0jW15cXHNdKiQpLywgJycpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB9XG5cbiAgICB2YXIgJHBhcmVudCA9IHNlbGVjdG9yICYmICQoc2VsZWN0b3IpXG5cbiAgICByZXR1cm4gJHBhcmVudCAmJiAkcGFyZW50Lmxlbmd0aCA/ICRwYXJlbnQgOiAkdGhpcy5wYXJlbnQoKVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJNZW51cyhlKSB7XG4gICAgaWYgKGUgJiYgZS53aGljaCA9PT0gMykgcmV0dXJuXG4gICAgJChiYWNrZHJvcCkucmVtb3ZlKClcbiAgICAkKHRvZ2dsZSkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICAgICAgICA9ICQodGhpcylcbiAgICAgIHZhciAkcGFyZW50ICAgICAgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgICAgdmFyIHJlbGF0ZWRUYXJnZXQgPSB7IHJlbGF0ZWRUYXJnZXQ6IHRoaXMgfVxuXG4gICAgICBpZiAoISRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKSkgcmV0dXJuXG5cbiAgICAgIGlmIChlICYmIGUudHlwZSA9PSAnY2xpY2snICYmIC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZS50YXJnZXQudGFnTmFtZSkgJiYgJC5jb250YWlucygkcGFyZW50WzBdLCBlLnRhcmdldCkpIHJldHVyblxuXG4gICAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ2hpZGUuYnMuZHJvcGRvd24nLCByZWxhdGVkVGFyZ2V0KSlcblxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgICAkdGhpcy5hdHRyKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJylcbiAgICAgICRwYXJlbnQucmVtb3ZlQ2xhc3MoJ29wZW4nKS50cmlnZ2VyKCQuRXZlbnQoJ2hpZGRlbi5icy5kcm9wZG93bicsIHJlbGF0ZWRUYXJnZXQpKVxuICAgIH0pXG4gIH1cblxuICBEcm9wZG93bi5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG5cbiAgICBpZiAoJHRoaXMuaXMoJy5kaXNhYmxlZCwgOmRpc2FibGVkJykpIHJldHVyblxuXG4gICAgdmFyICRwYXJlbnQgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgIHZhciBpc0FjdGl2ZSA9ICRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKVxuXG4gICAgY2xlYXJNZW51cygpXG5cbiAgICBpZiAoIWlzQWN0aXZlKSB7XG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmICEkcGFyZW50LmNsb3Nlc3QoJy5uYXZiYXItbmF2JykubGVuZ3RoKSB7XG4gICAgICAgIC8vIGlmIG1vYmlsZSB3ZSB1c2UgYSBiYWNrZHJvcCBiZWNhdXNlIGNsaWNrIGV2ZW50cyBkb24ndCBkZWxlZ2F0ZVxuICAgICAgICAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKVxuICAgICAgICAgIC5hZGRDbGFzcygnZHJvcGRvd24tYmFja2Ryb3AnKVxuICAgICAgICAgIC5pbnNlcnRBZnRlcigkKHRoaXMpKVxuICAgICAgICAgIC5vbignY2xpY2snLCBjbGVhck1lbnVzKVxuICAgICAgfVxuXG4gICAgICB2YXIgcmVsYXRlZFRhcmdldCA9IHsgcmVsYXRlZFRhcmdldDogdGhpcyB9XG4gICAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ3Nob3cuYnMuZHJvcGRvd24nLCByZWxhdGVkVGFyZ2V0KSlcblxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgICAkdGhpc1xuICAgICAgICAudHJpZ2dlcignZm9jdXMnKVxuICAgICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsICd0cnVlJylcblxuICAgICAgJHBhcmVudFxuICAgICAgICAudG9nZ2xlQ2xhc3MoJ29wZW4nKVxuICAgICAgICAudHJpZ2dlcigkLkV2ZW50KCdzaG93bi5icy5kcm9wZG93bicsIHJlbGF0ZWRUYXJnZXQpKVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgRHJvcGRvd24ucHJvdG90eXBlLmtleWRvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmICghLygzOHw0MHwyN3wzMikvLnRlc3QoZS53aGljaCkgfHwgL2lucHV0fHRleHRhcmVhL2kudGVzdChlLnRhcmdldC50YWdOYW1lKSkgcmV0dXJuXG5cbiAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG5cbiAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpXG5cbiAgICBpZiAoJHRoaXMuaXMoJy5kaXNhYmxlZCwgOmRpc2FibGVkJykpIHJldHVyblxuXG4gICAgdmFyICRwYXJlbnQgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgIHZhciBpc0FjdGl2ZSA9ICRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKVxuXG4gICAgaWYgKCFpc0FjdGl2ZSAmJiBlLndoaWNoICE9IDI3IHx8IGlzQWN0aXZlICYmIGUud2hpY2ggPT0gMjcpIHtcbiAgICAgIGlmIChlLndoaWNoID09IDI3KSAkcGFyZW50LmZpbmQodG9nZ2xlKS50cmlnZ2VyKCdmb2N1cycpXG4gICAgICByZXR1cm4gJHRoaXMudHJpZ2dlcignY2xpY2snKVxuICAgIH1cblxuICAgIHZhciBkZXNjID0gJyBsaTpub3QoLmRpc2FibGVkKTp2aXNpYmxlIGEnXG4gICAgdmFyICRpdGVtcyA9ICRwYXJlbnQuZmluZCgnLmRyb3Bkb3duLW1lbnUnICsgZGVzYylcblxuICAgIGlmICghJGl0ZW1zLmxlbmd0aCkgcmV0dXJuXG5cbiAgICB2YXIgaW5kZXggPSAkaXRlbXMuaW5kZXgoZS50YXJnZXQpXG5cbiAgICBpZiAoZS53aGljaCA9PSAzOCAmJiBpbmRleCA+IDApICAgICAgICAgICAgICAgICBpbmRleC0tICAgICAgICAgLy8gdXBcbiAgICBpZiAoZS53aGljaCA9PSA0MCAmJiBpbmRleCA8ICRpdGVtcy5sZW5ndGggLSAxKSBpbmRleCsrICAgICAgICAgLy8gZG93blxuICAgIGlmICghfmluZGV4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gMFxuXG4gICAgJGl0ZW1zLmVxKGluZGV4KS50cmlnZ2VyKCdmb2N1cycpXG4gIH1cblxuXG4gIC8vIERST1BET1dOIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgdmFyIGRhdGEgID0gJHRoaXMuZGF0YSgnYnMuZHJvcGRvd24nKVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmRyb3Bkb3duJywgKGRhdGEgPSBuZXcgRHJvcGRvd24odGhpcykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXS5jYWxsKCR0aGlzKVxuICAgIH0pXG4gIH1cblxuICB2YXIgb2xkID0gJC5mbi5kcm9wZG93blxuXG4gICQuZm4uZHJvcGRvd24gICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5kcm9wZG93bi5Db25zdHJ1Y3RvciA9IERyb3Bkb3duXG5cblxuICAvLyBEUk9QRE9XTiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PVxuXG4gICQuZm4uZHJvcGRvd24ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkLmZuLmRyb3Bkb3duID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gQVBQTFkgVE8gU1RBTkRBUkQgRFJPUERPV04gRUxFTUVOVFNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAkKGRvY3VtZW50KVxuICAgIC5vbignY2xpY2suYnMuZHJvcGRvd24uZGF0YS1hcGknLCBjbGVhck1lbnVzKVxuICAgIC5vbignY2xpY2suYnMuZHJvcGRvd24uZGF0YS1hcGknLCAnLmRyb3Bkb3duIGZvcm0nLCBmdW5jdGlvbiAoZSkgeyBlLnN0b3BQcm9wYWdhdGlvbigpIH0pXG4gICAgLm9uKCdjbGljay5icy5kcm9wZG93bi5kYXRhLWFwaScsIHRvZ2dsZSwgRHJvcGRvd24ucHJvdG90eXBlLnRvZ2dsZSlcbiAgICAub24oJ2tleWRvd24uYnMuZHJvcGRvd24uZGF0YS1hcGknLCB0b2dnbGUsIERyb3Bkb3duLnByb3RvdHlwZS5rZXlkb3duKVxuICAgIC5vbigna2V5ZG93bi5icy5kcm9wZG93bi5kYXRhLWFwaScsICcuZHJvcGRvd24tbWVudScsIERyb3Bkb3duLnByb3RvdHlwZS5rZXlkb3duKVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvZHJvcGRvd24uanNcbi8vIG1vZHVsZSBpZCA9IDhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IG1vZGFsLmpzIHYzLjMuN1xuICogaHR0cDovL2dldGJvb3RzdHJhcC5jb20vamF2YXNjcmlwdC8jbW9kYWxzXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gTU9EQUwgQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIE1vZGFsID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgICAgICAgICAgICAgPSBvcHRpb25zXG4gICAgdGhpcy4kYm9keSAgICAgICAgICAgICAgID0gJChkb2N1bWVudC5ib2R5KVxuICAgIHRoaXMuJGVsZW1lbnQgICAgICAgICAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLiRkaWFsb2cgICAgICAgICAgICAgPSB0aGlzLiRlbGVtZW50LmZpbmQoJy5tb2RhbC1kaWFsb2cnKVxuICAgIHRoaXMuJGJhY2tkcm9wICAgICAgICAgICA9IG51bGxcbiAgICB0aGlzLmlzU2hvd24gICAgICAgICAgICAgPSBudWxsXG4gICAgdGhpcy5vcmlnaW5hbEJvZHlQYWQgICAgID0gbnVsbFxuICAgIHRoaXMuc2Nyb2xsYmFyV2lkdGggICAgICA9IDBcbiAgICB0aGlzLmlnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5yZW1vdGUpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLmZpbmQoJy5tb2RhbC1jb250ZW50JylcbiAgICAgICAgLmxvYWQodGhpcy5vcHRpb25zLnJlbW90ZSwgJC5wcm94eShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdsb2FkZWQuYnMubW9kYWwnKVxuICAgICAgICB9LCB0aGlzKSlcbiAgICB9XG4gIH1cblxuICBNb2RhbC5WRVJTSU9OICA9ICczLjMuNydcblxuICBNb2RhbC5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMzAwXG4gIE1vZGFsLkJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04gPSAxNTBcblxuICBNb2RhbC5ERUZBVUxUUyA9IHtcbiAgICBiYWNrZHJvcDogdHJ1ZSxcbiAgICBrZXlib2FyZDogdHJ1ZSxcbiAgICBzaG93OiB0cnVlXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gKF9yZWxhdGVkVGFyZ2V0KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNTaG93biA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KF9yZWxhdGVkVGFyZ2V0KVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoX3JlbGF0ZWRUYXJnZXQpIHtcbiAgICB2YXIgdGhhdCA9IHRoaXNcbiAgICB2YXIgZSAgICA9ICQuRXZlbnQoJ3Nob3cuYnMubW9kYWwnLCB7IHJlbGF0ZWRUYXJnZXQ6IF9yZWxhdGVkVGFyZ2V0IH0pXG5cbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgIGlmICh0aGlzLmlzU2hvd24gfHwgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLmlzU2hvd24gPSB0cnVlXG5cbiAgICB0aGlzLmNoZWNrU2Nyb2xsYmFyKClcbiAgICB0aGlzLnNldFNjcm9sbGJhcigpXG4gICAgdGhpcy4kYm9keS5hZGRDbGFzcygnbW9kYWwtb3BlbicpXG5cbiAgICB0aGlzLmVzY2FwZSgpXG4gICAgdGhpcy5yZXNpemUoKVxuXG4gICAgdGhpcy4kZWxlbWVudC5vbignY2xpY2suZGlzbWlzcy5icy5tb2RhbCcsICdbZGF0YS1kaXNtaXNzPVwibW9kYWxcIl0nLCAkLnByb3h5KHRoaXMuaGlkZSwgdGhpcykpXG5cbiAgICB0aGlzLiRkaWFsb2cub24oJ21vdXNlZG93bi5kaXNtaXNzLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgdGhhdC4kZWxlbWVudC5vbmUoJ21vdXNldXAuZGlzbWlzcy5icy5tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICgkKGUudGFyZ2V0KS5pcyh0aGF0LiRlbGVtZW50KSkgdGhhdC5pZ25vcmVCYWNrZHJvcENsaWNrID0gdHJ1ZVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgdGhpcy5iYWNrZHJvcChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvbiA9ICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoYXQuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKVxuXG4gICAgICBpZiAoIXRoYXQuJGVsZW1lbnQucGFyZW50KCkubGVuZ3RoKSB7XG4gICAgICAgIHRoYXQuJGVsZW1lbnQuYXBwZW5kVG8odGhhdC4kYm9keSkgLy8gZG9uJ3QgbW92ZSBtb2RhbHMgZG9tIHBvc2l0aW9uXG4gICAgICB9XG5cbiAgICAgIHRoYXQuJGVsZW1lbnRcbiAgICAgICAgLnNob3coKVxuICAgICAgICAuc2Nyb2xsVG9wKDApXG5cbiAgICAgIHRoYXQuYWRqdXN0RGlhbG9nKClcblxuICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgdGhhdC4kZWxlbWVudFswXS5vZmZzZXRXaWR0aCAvLyBmb3JjZSByZWZsb3dcbiAgICAgIH1cblxuICAgICAgdGhhdC4kZWxlbWVudC5hZGRDbGFzcygnaW4nKVxuXG4gICAgICB0aGF0LmVuZm9yY2VGb2N1cygpXG5cbiAgICAgIHZhciBlID0gJC5FdmVudCgnc2hvd24uYnMubW9kYWwnLCB7IHJlbGF0ZWRUYXJnZXQ6IF9yZWxhdGVkVGFyZ2V0IH0pXG5cbiAgICAgIHRyYW5zaXRpb24gP1xuICAgICAgICB0aGF0LiRkaWFsb2cgLy8gd2FpdCBmb3IgbW9kYWwgdG8gc2xpZGUgaW5cbiAgICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2ZvY3VzJykudHJpZ2dlcihlKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKE1vZGFsLlRSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdmb2N1cycpLnRyaWdnZXIoZSlcbiAgICB9KVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmIChlKSBlLnByZXZlbnREZWZhdWx0KClcblxuICAgIGUgPSAkLkV2ZW50KCdoaWRlLmJzLm1vZGFsJylcblxuICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcihlKVxuXG4gICAgaWYgKCF0aGlzLmlzU2hvd24gfHwgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLmlzU2hvd24gPSBmYWxzZVxuXG4gICAgdGhpcy5lc2NhcGUoKVxuICAgIHRoaXMucmVzaXplKClcblxuICAgICQoZG9jdW1lbnQpLm9mZignZm9jdXNpbi5icy5tb2RhbCcpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQ2xhc3MoJ2luJylcbiAgICAgIC5vZmYoJ2NsaWNrLmRpc21pc3MuYnMubW9kYWwnKVxuICAgICAgLm9mZignbW91c2V1cC5kaXNtaXNzLmJzLm1vZGFsJylcblxuICAgIHRoaXMuJGRpYWxvZy5vZmYoJ21vdXNlZG93bi5kaXNtaXNzLmJzLm1vZGFsJylcblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICB0aGlzLiRlbGVtZW50XG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsICQucHJveHkodGhpcy5oaWRlTW9kYWwsIHRoaXMpKVxuICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoTW9kYWwuVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgdGhpcy5oaWRlTW9kYWwoKVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLmVuZm9yY2VGb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKGRvY3VtZW50KVxuICAgICAgLm9mZignZm9jdXNpbi5icy5tb2RhbCcpIC8vIGd1YXJkIGFnYWluc3QgaW5maW5pdGUgZm9jdXMgbG9vcFxuICAgICAgLm9uKCdmb2N1c2luLmJzLm1vZGFsJywgJC5wcm94eShmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZG9jdW1lbnQgIT09IGUudGFyZ2V0ICYmXG4gICAgICAgICAgICB0aGlzLiRlbGVtZW50WzBdICE9PSBlLnRhcmdldCAmJlxuICAgICAgICAgICAgIXRoaXMuJGVsZW1lbnQuaGFzKGUudGFyZ2V0KS5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2ZvY3VzJylcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcykpXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUuZXNjYXBlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmlzU2hvd24gJiYgdGhpcy5vcHRpb25zLmtleWJvYXJkKSB7XG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdrZXlkb3duLmRpc21pc3MuYnMubW9kYWwnLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUud2hpY2ggPT0gMjcgJiYgdGhpcy5oaWRlKClcbiAgICAgIH0sIHRoaXMpKVxuICAgIH0gZWxzZSBpZiAoIXRoaXMuaXNTaG93bikge1xuICAgICAgdGhpcy4kZWxlbWVudC5vZmYoJ2tleWRvd24uZGlzbWlzcy5icy5tb2RhbCcpXG4gICAgfVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pc1Nob3duKSB7XG4gICAgICAkKHdpbmRvdykub24oJ3Jlc2l6ZS5icy5tb2RhbCcsICQucHJveHkodGhpcy5oYW5kbGVVcGRhdGUsIHRoaXMpKVxuICAgIH0gZWxzZSB7XG4gICAgICAkKHdpbmRvdykub2ZmKCdyZXNpemUuYnMubW9kYWwnKVxuICAgIH1cbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5oaWRlTW9kYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRoYXQgPSB0aGlzXG4gICAgdGhpcy4kZWxlbWVudC5oaWRlKClcbiAgICB0aGlzLmJhY2tkcm9wKGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoYXQuJGJvZHkucmVtb3ZlQ2xhc3MoJ21vZGFsLW9wZW4nKVxuICAgICAgdGhhdC5yZXNldEFkanVzdG1lbnRzKClcbiAgICAgIHRoYXQucmVzZXRTY3JvbGxiYXIoKVxuICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdoaWRkZW4uYnMubW9kYWwnKVxuICAgIH0pXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUucmVtb3ZlQmFja2Ryb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy4kYmFja2Ryb3AgJiYgdGhpcy4kYmFja2Ryb3AucmVtb3ZlKClcbiAgICB0aGlzLiRiYWNrZHJvcCA9IG51bGxcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5iYWNrZHJvcCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHZhciB0aGF0ID0gdGhpc1xuICAgIHZhciBhbmltYXRlID0gdGhpcy4kZWxlbWVudC5oYXNDbGFzcygnZmFkZScpID8gJ2ZhZGUnIDogJydcblxuICAgIGlmICh0aGlzLmlzU2hvd24gJiYgdGhpcy5vcHRpb25zLmJhY2tkcm9wKSB7XG4gICAgICB2YXIgZG9BbmltYXRlID0gJC5zdXBwb3J0LnRyYW5zaXRpb24gJiYgYW5pbWF0ZVxuXG4gICAgICB0aGlzLiRiYWNrZHJvcCA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpXG4gICAgICAgIC5hZGRDbGFzcygnbW9kYWwtYmFja2Ryb3AgJyArIGFuaW1hdGUpXG4gICAgICAgIC5hcHBlbmRUbyh0aGlzLiRib2R5KVxuXG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdjbGljay5kaXNtaXNzLmJzLm1vZGFsJywgJC5wcm94eShmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5pZ25vcmVCYWNrZHJvcENsaWNrKSB7XG4gICAgICAgICAgdGhpcy5pZ25vcmVCYWNrZHJvcENsaWNrID0gZmFsc2VcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBpZiAoZS50YXJnZXQgIT09IGUuY3VycmVudFRhcmdldCkgcmV0dXJuXG4gICAgICAgIHRoaXMub3B0aW9ucy5iYWNrZHJvcCA9PSAnc3RhdGljJ1xuICAgICAgICAgID8gdGhpcy4kZWxlbWVudFswXS5mb2N1cygpXG4gICAgICAgICAgOiB0aGlzLmhpZGUoKVxuICAgICAgfSwgdGhpcykpXG5cbiAgICAgIGlmIChkb0FuaW1hdGUpIHRoaXMuJGJhY2tkcm9wWzBdLm9mZnNldFdpZHRoIC8vIGZvcmNlIHJlZmxvd1xuXG4gICAgICB0aGlzLiRiYWNrZHJvcC5hZGRDbGFzcygnaW4nKVxuXG4gICAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm5cblxuICAgICAgZG9BbmltYXRlID9cbiAgICAgICAgdGhpcy4kYmFja2Ryb3BcbiAgICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBjYWxsYmFjaylcbiAgICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoTW9kYWwuQkFDS0RST1BfVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgICBjYWxsYmFjaygpXG5cbiAgICB9IGVsc2UgaWYgKCF0aGlzLmlzU2hvd24gJiYgdGhpcy4kYmFja2Ryb3ApIHtcbiAgICAgIHRoaXMuJGJhY2tkcm9wLnJlbW92ZUNsYXNzKCdpbicpXG5cbiAgICAgIHZhciBjYWxsYmFja1JlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5yZW1vdmVCYWNrZHJvcCgpXG4gICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKClcbiAgICAgIH1cbiAgICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAgIHRoaXMuJGJhY2tkcm9wXG4gICAgICAgICAgLm9uZSgnYnNUcmFuc2l0aW9uRW5kJywgY2FsbGJhY2tSZW1vdmUpXG4gICAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKE1vZGFsLkJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgY2FsbGJhY2tSZW1vdmUoKVxuXG4gICAgfSBlbHNlIGlmIChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2soKVxuICAgIH1cbiAgfVxuXG4gIC8vIHRoZXNlIGZvbGxvd2luZyBtZXRob2RzIGFyZSB1c2VkIHRvIGhhbmRsZSBvdmVyZmxvd2luZyBtb2RhbHNcblxuICBNb2RhbC5wcm90b3R5cGUuaGFuZGxlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYWRqdXN0RGlhbG9nKClcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5hZGp1c3REaWFsb2cgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG1vZGFsSXNPdmVyZmxvd2luZyA9IHRoaXMuJGVsZW1lbnRbMF0uc2Nyb2xsSGVpZ2h0ID4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodFxuXG4gICAgdGhpcy4kZWxlbWVudC5jc3Moe1xuICAgICAgcGFkZGluZ0xlZnQ6ICAhdGhpcy5ib2R5SXNPdmVyZmxvd2luZyAmJiBtb2RhbElzT3ZlcmZsb3dpbmcgPyB0aGlzLnNjcm9sbGJhcldpZHRoIDogJycsXG4gICAgICBwYWRkaW5nUmlnaHQ6IHRoaXMuYm9keUlzT3ZlcmZsb3dpbmcgJiYgIW1vZGFsSXNPdmVyZmxvd2luZyA/IHRoaXMuc2Nyb2xsYmFyV2lkdGggOiAnJ1xuICAgIH0pXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUucmVzZXRBZGp1c3RtZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRlbGVtZW50LmNzcyh7XG4gICAgICBwYWRkaW5nTGVmdDogJycsXG4gICAgICBwYWRkaW5nUmlnaHQ6ICcnXG4gICAgfSlcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5jaGVja1Njcm9sbGJhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZnVsbFdpbmRvd1dpZHRoID0gd2luZG93LmlubmVyV2lkdGhcbiAgICBpZiAoIWZ1bGxXaW5kb3dXaWR0aCkgeyAvLyB3b3JrYXJvdW5kIGZvciBtaXNzaW5nIHdpbmRvdy5pbm5lcldpZHRoIGluIElFOFxuICAgICAgdmFyIGRvY3VtZW50RWxlbWVudFJlY3QgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICAgIGZ1bGxXaW5kb3dXaWR0aCA9IGRvY3VtZW50RWxlbWVudFJlY3QucmlnaHQgLSBNYXRoLmFicyhkb2N1bWVudEVsZW1lbnRSZWN0LmxlZnQpXG4gICAgfVxuICAgIHRoaXMuYm9keUlzT3ZlcmZsb3dpbmcgPSBkb2N1bWVudC5ib2R5LmNsaWVudFdpZHRoIDwgZnVsbFdpbmRvd1dpZHRoXG4gICAgdGhpcy5zY3JvbGxiYXJXaWR0aCA9IHRoaXMubWVhc3VyZVNjcm9sbGJhcigpXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUuc2V0U2Nyb2xsYmFyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBib2R5UGFkID0gcGFyc2VJbnQoKHRoaXMuJGJvZHkuY3NzKCdwYWRkaW5nLXJpZ2h0JykgfHwgMCksIDEwKVxuICAgIHRoaXMub3JpZ2luYWxCb2R5UGFkID0gZG9jdW1lbnQuYm9keS5zdHlsZS5wYWRkaW5nUmlnaHQgfHwgJydcbiAgICBpZiAodGhpcy5ib2R5SXNPdmVyZmxvd2luZykgdGhpcy4kYm9keS5jc3MoJ3BhZGRpbmctcmlnaHQnLCBib2R5UGFkICsgdGhpcy5zY3JvbGxiYXJXaWR0aClcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5yZXNldFNjcm9sbGJhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRib2R5LmNzcygncGFkZGluZy1yaWdodCcsIHRoaXMub3JpZ2luYWxCb2R5UGFkKVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLm1lYXN1cmVTY3JvbGxiYXIgPSBmdW5jdGlvbiAoKSB7IC8vIHRoeCB3YWxzaFxuICAgIHZhciBzY3JvbGxEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHNjcm9sbERpdi5jbGFzc05hbWUgPSAnbW9kYWwtc2Nyb2xsYmFyLW1lYXN1cmUnXG4gICAgdGhpcy4kYm9keS5hcHBlbmQoc2Nyb2xsRGl2KVxuICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHNjcm9sbERpdi5vZmZzZXRXaWR0aCAtIHNjcm9sbERpdi5jbGllbnRXaWR0aFxuICAgIHRoaXMuJGJvZHlbMF0ucmVtb3ZlQ2hpbGQoc2Nyb2xsRGl2KVxuICAgIHJldHVybiBzY3JvbGxiYXJXaWR0aFxuICB9XG5cblxuICAvLyBNT0RBTCBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIFBsdWdpbihvcHRpb24sIF9yZWxhdGVkVGFyZ2V0KSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICAgIHZhciBkYXRhICAgID0gJHRoaXMuZGF0YSgnYnMubW9kYWwnKVxuICAgICAgdmFyIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgTW9kYWwuREVGQVVMVFMsICR0aGlzLmRhdGEoKSwgdHlwZW9mIG9wdGlvbiA9PSAnb2JqZWN0JyAmJiBvcHRpb24pXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMubW9kYWwnLCAoZGF0YSA9IG5ldyBNb2RhbCh0aGlzLCBvcHRpb25zKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKF9yZWxhdGVkVGFyZ2V0KVxuICAgICAgZWxzZSBpZiAob3B0aW9ucy5zaG93KSBkYXRhLnNob3coX3JlbGF0ZWRUYXJnZXQpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLm1vZGFsXG5cbiAgJC5mbi5tb2RhbCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLm1vZGFsLkNvbnN0cnVjdG9yID0gTW9kYWxcblxuXG4gIC8vIE1PREFMIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5tb2RhbC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4ubW9kYWwgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBNT0RBTCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5tb2RhbC5kYXRhLWFwaScsICdbZGF0YS10b2dnbGU9XCJtb2RhbFwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgdmFyIGhyZWYgICAgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICB2YXIgJHRhcmdldCA9ICQoJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKSB8fCAoaHJlZiAmJiBocmVmLnJlcGxhY2UoLy4qKD89I1teXFxzXSskKS8sICcnKSkpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB2YXIgb3B0aW9uICA9ICR0YXJnZXQuZGF0YSgnYnMubW9kYWwnKSA/ICd0b2dnbGUnIDogJC5leHRlbmQoeyByZW1vdGU6ICEvIy8udGVzdChocmVmKSAmJiBocmVmIH0sICR0YXJnZXQuZGF0YSgpLCAkdGhpcy5kYXRhKCkpXG5cbiAgICBpZiAoJHRoaXMuaXMoJ2EnKSkgZS5wcmV2ZW50RGVmYXVsdCgpXG5cbiAgICAkdGFyZ2V0Lm9uZSgnc2hvdy5icy5tb2RhbCcsIGZ1bmN0aW9uIChzaG93RXZlbnQpIHtcbiAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVybiAvLyBvbmx5IHJlZ2lzdGVyIGZvY3VzIHJlc3RvcmVyIGlmIG1vZGFsIHdpbGwgYWN0dWFsbHkgZ2V0IHNob3duXG4gICAgICAkdGFyZ2V0Lm9uZSgnaGlkZGVuLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkdGhpcy5pcygnOnZpc2libGUnKSAmJiAkdGhpcy50cmlnZ2VyKCdmb2N1cycpXG4gICAgICB9KVxuICAgIH0pXG4gICAgUGx1Z2luLmNhbGwoJHRhcmdldCwgb3B0aW9uLCB0aGlzKVxuICB9KVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvbW9kYWwuanNcbi8vIG1vZHVsZSBpZCA9IDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHRvb2x0aXAuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyN0b29sdGlwXG4gKiBJbnNwaXJlZCBieSB0aGUgb3JpZ2luYWwgalF1ZXJ5LnRpcHN5IGJ5IEphc29uIEZyYW1lXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVE9PTFRJUCBQVUJMSUMgQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIFRvb2x0aXAgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMudHlwZSAgICAgICA9IG51bGxcbiAgICB0aGlzLm9wdGlvbnMgICAgPSBudWxsXG4gICAgdGhpcy5lbmFibGVkICAgID0gbnVsbFxuICAgIHRoaXMudGltZW91dCAgICA9IG51bGxcbiAgICB0aGlzLmhvdmVyU3RhdGUgPSBudWxsXG4gICAgdGhpcy4kZWxlbWVudCAgID0gbnVsbFxuICAgIHRoaXMuaW5TdGF0ZSAgICA9IG51bGxcblxuICAgIHRoaXMuaW5pdCgndG9vbHRpcCcsIGVsZW1lbnQsIG9wdGlvbnMpXG4gIH1cblxuICBUb29sdGlwLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFRvb2x0aXAuVFJBTlNJVElPTl9EVVJBVElPTiA9IDE1MFxuXG4gIFRvb2x0aXAuREVGQVVMVFMgPSB7XG4gICAgYW5pbWF0aW9uOiB0cnVlLFxuICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgc2VsZWN0b3I6IGZhbHNlLFxuICAgIHRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRvb2x0aXBcIiByb2xlPVwidG9vbHRpcFwiPjxkaXYgY2xhc3M9XCJ0b29sdGlwLWFycm93XCI+PC9kaXY+PGRpdiBjbGFzcz1cInRvb2x0aXAtaW5uZXJcIj48L2Rpdj48L2Rpdj4nLFxuICAgIHRyaWdnZXI6ICdob3ZlciBmb2N1cycsXG4gICAgdGl0bGU6ICcnLFxuICAgIGRlbGF5OiAwLFxuICAgIGh0bWw6IGZhbHNlLFxuICAgIGNvbnRhaW5lcjogZmFsc2UsXG4gICAgdmlld3BvcnQ6IHtcbiAgICAgIHNlbGVjdG9yOiAnYm9keScsXG4gICAgICBwYWRkaW5nOiAwXG4gICAgfVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICh0eXBlLCBlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy5lbmFibGVkICAgPSB0cnVlXG4gICAgdGhpcy50eXBlICAgICAgPSB0eXBlXG4gICAgdGhpcy4kZWxlbWVudCAgPSAkKGVsZW1lbnQpXG4gICAgdGhpcy5vcHRpb25zICAgPSB0aGlzLmdldE9wdGlvbnMob3B0aW9ucylcbiAgICB0aGlzLiR2aWV3cG9ydCA9IHRoaXMub3B0aW9ucy52aWV3cG9ydCAmJiAkKCQuaXNGdW5jdGlvbih0aGlzLm9wdGlvbnMudmlld3BvcnQpID8gdGhpcy5vcHRpb25zLnZpZXdwb3J0LmNhbGwodGhpcywgdGhpcy4kZWxlbWVudCkgOiAodGhpcy5vcHRpb25zLnZpZXdwb3J0LnNlbGVjdG9yIHx8IHRoaXMub3B0aW9ucy52aWV3cG9ydCkpXG4gICAgdGhpcy5pblN0YXRlICAgPSB7IGNsaWNrOiBmYWxzZSwgaG92ZXI6IGZhbHNlLCBmb2N1czogZmFsc2UgfVxuXG4gICAgaWYgKHRoaXMuJGVsZW1lbnRbMF0gaW5zdGFuY2VvZiBkb2N1bWVudC5jb25zdHJ1Y3RvciAmJiAhdGhpcy5vcHRpb25zLnNlbGVjdG9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BzZWxlY3RvcmAgb3B0aW9uIG11c3QgYmUgc3BlY2lmaWVkIHdoZW4gaW5pdGlhbGl6aW5nICcgKyB0aGlzLnR5cGUgKyAnIG9uIHRoZSB3aW5kb3cuZG9jdW1lbnQgb2JqZWN0IScpXG4gICAgfVxuXG4gICAgdmFyIHRyaWdnZXJzID0gdGhpcy5vcHRpb25zLnRyaWdnZXIuc3BsaXQoJyAnKVxuXG4gICAgZm9yICh2YXIgaSA9IHRyaWdnZXJzLmxlbmd0aDsgaS0tOykge1xuICAgICAgdmFyIHRyaWdnZXIgPSB0cmlnZ2Vyc1tpXVxuXG4gICAgICBpZiAodHJpZ2dlciA9PSAnY2xpY2snKSB7XG4gICAgICAgIHRoaXMuJGVsZW1lbnQub24oJ2NsaWNrLicgKyB0aGlzLnR5cGUsIHRoaXMub3B0aW9ucy5zZWxlY3RvciwgJC5wcm94eSh0aGlzLnRvZ2dsZSwgdGhpcykpXG4gICAgICB9IGVsc2UgaWYgKHRyaWdnZXIgIT0gJ21hbnVhbCcpIHtcbiAgICAgICAgdmFyIGV2ZW50SW4gID0gdHJpZ2dlciA9PSAnaG92ZXInID8gJ21vdXNlZW50ZXInIDogJ2ZvY3VzaW4nXG4gICAgICAgIHZhciBldmVudE91dCA9IHRyaWdnZXIgPT0gJ2hvdmVyJyA/ICdtb3VzZWxlYXZlJyA6ICdmb2N1c291dCdcblxuICAgICAgICB0aGlzLiRlbGVtZW50Lm9uKGV2ZW50SW4gICsgJy4nICsgdGhpcy50eXBlLCB0aGlzLm9wdGlvbnMuc2VsZWN0b3IsICQucHJveHkodGhpcy5lbnRlciwgdGhpcykpXG4gICAgICAgIHRoaXMuJGVsZW1lbnQub24oZXZlbnRPdXQgKyAnLicgKyB0aGlzLnR5cGUsIHRoaXMub3B0aW9ucy5zZWxlY3RvciwgJC5wcm94eSh0aGlzLmxlYXZlLCB0aGlzKSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm9wdGlvbnMuc2VsZWN0b3IgP1xuICAgICAgKHRoaXMuX29wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zLCB7IHRyaWdnZXI6ICdtYW51YWwnLCBzZWxlY3RvcjogJycgfSkpIDpcbiAgICAgIHRoaXMuZml4VGl0bGUoKVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0RGVmYXVsdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFRvb2x0aXAuREVGQVVMVFNcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5nZXREZWZhdWx0cygpLCB0aGlzLiRlbGVtZW50LmRhdGEoKSwgb3B0aW9ucylcblxuICAgIGlmIChvcHRpb25zLmRlbGF5ICYmIHR5cGVvZiBvcHRpb25zLmRlbGF5ID09ICdudW1iZXInKSB7XG4gICAgICBvcHRpb25zLmRlbGF5ID0ge1xuICAgICAgICBzaG93OiBvcHRpb25zLmRlbGF5LFxuICAgICAgICBoaWRlOiBvcHRpb25zLmRlbGF5XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdGlvbnNcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmdldERlbGVnYXRlT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb3B0aW9ucyAgPSB7fVxuICAgIHZhciBkZWZhdWx0cyA9IHRoaXMuZ2V0RGVmYXVsdHMoKVxuXG4gICAgdGhpcy5fb3B0aW9ucyAmJiAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgIGlmIChkZWZhdWx0c1trZXldICE9IHZhbHVlKSBvcHRpb25zW2tleV0gPSB2YWx1ZVxuICAgIH0pXG5cbiAgICByZXR1cm4gb3B0aW9uc1xuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZW50ZXIgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIHNlbGYgPSBvYmogaW5zdGFuY2VvZiB0aGlzLmNvbnN0cnVjdG9yID9cbiAgICAgIG9iaiA6ICQob2JqLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2JzLicgKyB0aGlzLnR5cGUpXG5cbiAgICBpZiAoIXNlbGYpIHtcbiAgICAgIHNlbGYgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihvYmouY3VycmVudFRhcmdldCwgdGhpcy5nZXREZWxlZ2F0ZU9wdGlvbnMoKSlcbiAgICAgICQob2JqLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2JzLicgKyB0aGlzLnR5cGUsIHNlbGYpXG4gICAgfVxuXG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mICQuRXZlbnQpIHtcbiAgICAgIHNlbGYuaW5TdGF0ZVtvYmoudHlwZSA9PSAnZm9jdXNpbicgPyAnZm9jdXMnIDogJ2hvdmVyJ10gPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHNlbGYudGlwKCkuaGFzQ2xhc3MoJ2luJykgfHwgc2VsZi5ob3ZlclN0YXRlID09ICdpbicpIHtcbiAgICAgIHNlbGYuaG92ZXJTdGF0ZSA9ICdpbidcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNsZWFyVGltZW91dChzZWxmLnRpbWVvdXQpXG5cbiAgICBzZWxmLmhvdmVyU3RhdGUgPSAnaW4nXG5cbiAgICBpZiAoIXNlbGYub3B0aW9ucy5kZWxheSB8fCAhc2VsZi5vcHRpb25zLmRlbGF5LnNob3cpIHJldHVybiBzZWxmLnNob3coKVxuXG4gICAgc2VsZi50aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoc2VsZi5ob3ZlclN0YXRlID09ICdpbicpIHNlbGYuc2hvdygpXG4gICAgfSwgc2VsZi5vcHRpb25zLmRlbGF5LnNob3cpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5pc0luU3RhdGVUcnVlID0gZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmluU3RhdGUpIHtcbiAgICAgIGlmICh0aGlzLmluU3RhdGVba2V5XSkgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmxlYXZlID0gZnVuY3Rpb24gKG9iaikge1xuICAgIHZhciBzZWxmID0gb2JqIGluc3RhbmNlb2YgdGhpcy5jb25zdHJ1Y3RvciA/XG4gICAgICBvYmogOiAkKG9iai5jdXJyZW50VGFyZ2V0KS5kYXRhKCdicy4nICsgdGhpcy50eXBlKVxuXG4gICAgaWYgKCFzZWxmKSB7XG4gICAgICBzZWxmID0gbmV3IHRoaXMuY29uc3RydWN0b3Iob2JqLmN1cnJlbnRUYXJnZXQsIHRoaXMuZ2V0RGVsZWdhdGVPcHRpb25zKCkpXG4gICAgICAkKG9iai5jdXJyZW50VGFyZ2V0KS5kYXRhKCdicy4nICsgdGhpcy50eXBlLCBzZWxmKVxuICAgIH1cblxuICAgIGlmIChvYmogaW5zdGFuY2VvZiAkLkV2ZW50KSB7XG4gICAgICBzZWxmLmluU3RhdGVbb2JqLnR5cGUgPT0gJ2ZvY3Vzb3V0JyA/ICdmb2N1cycgOiAnaG92ZXInXSA9IGZhbHNlXG4gICAgfVxuXG4gICAgaWYgKHNlbGYuaXNJblN0YXRlVHJ1ZSgpKSByZXR1cm5cblxuICAgIGNsZWFyVGltZW91dChzZWxmLnRpbWVvdXQpXG5cbiAgICBzZWxmLmhvdmVyU3RhdGUgPSAnb3V0J1xuXG4gICAgaWYgKCFzZWxmLm9wdGlvbnMuZGVsYXkgfHwgIXNlbGYub3B0aW9ucy5kZWxheS5oaWRlKSByZXR1cm4gc2VsZi5oaWRlKClcblxuICAgIHNlbGYudGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKHNlbGYuaG92ZXJTdGF0ZSA9PSAnb3V0Jykgc2VsZi5oaWRlKClcbiAgICB9LCBzZWxmLm9wdGlvbnMuZGVsYXkuaGlkZSlcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGUgPSAkLkV2ZW50KCdzaG93LmJzLicgKyB0aGlzLnR5cGUpXG5cbiAgICBpZiAodGhpcy5oYXNDb250ZW50KCkgJiYgdGhpcy5lbmFibGVkKSB7XG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgICAgdmFyIGluRG9tID0gJC5jb250YWlucyh0aGlzLiRlbGVtZW50WzBdLm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLiRlbGVtZW50WzBdKVxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgIWluRG9tKSByZXR1cm5cbiAgICAgIHZhciB0aGF0ID0gdGhpc1xuXG4gICAgICB2YXIgJHRpcCA9IHRoaXMudGlwKClcblxuICAgICAgdmFyIHRpcElkID0gdGhpcy5nZXRVSUQodGhpcy50eXBlKVxuXG4gICAgICB0aGlzLnNldENvbnRlbnQoKVxuICAgICAgJHRpcC5hdHRyKCdpZCcsIHRpcElkKVxuICAgICAgdGhpcy4kZWxlbWVudC5hdHRyKCdhcmlhLWRlc2NyaWJlZGJ5JywgdGlwSWQpXG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuYW5pbWF0aW9uKSAkdGlwLmFkZENsYXNzKCdmYWRlJylcblxuICAgICAgdmFyIHBsYWNlbWVudCA9IHR5cGVvZiB0aGlzLm9wdGlvbnMucGxhY2VtZW50ID09ICdmdW5jdGlvbicgP1xuICAgICAgICB0aGlzLm9wdGlvbnMucGxhY2VtZW50LmNhbGwodGhpcywgJHRpcFswXSwgdGhpcy4kZWxlbWVudFswXSkgOlxuICAgICAgICB0aGlzLm9wdGlvbnMucGxhY2VtZW50XG5cbiAgICAgIHZhciBhdXRvVG9rZW4gPSAvXFxzP2F1dG8/XFxzPy9pXG4gICAgICB2YXIgYXV0b1BsYWNlID0gYXV0b1Rva2VuLnRlc3QocGxhY2VtZW50KVxuICAgICAgaWYgKGF1dG9QbGFjZSkgcGxhY2VtZW50ID0gcGxhY2VtZW50LnJlcGxhY2UoYXV0b1Rva2VuLCAnJykgfHwgJ3RvcCdcblxuICAgICAgJHRpcFxuICAgICAgICAuZGV0YWNoKClcbiAgICAgICAgLmNzcyh7IHRvcDogMCwgbGVmdDogMCwgZGlzcGxheTogJ2Jsb2NrJyB9KVxuICAgICAgICAuYWRkQ2xhc3MocGxhY2VtZW50KVxuICAgICAgICAuZGF0YSgnYnMuJyArIHRoaXMudHlwZSwgdGhpcylcblxuICAgICAgdGhpcy5vcHRpb25zLmNvbnRhaW5lciA/ICR0aXAuYXBwZW5kVG8odGhpcy5vcHRpb25zLmNvbnRhaW5lcikgOiAkdGlwLmluc2VydEFmdGVyKHRoaXMuJGVsZW1lbnQpXG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2luc2VydGVkLmJzLicgKyB0aGlzLnR5cGUpXG5cbiAgICAgIHZhciBwb3MgICAgICAgICAgPSB0aGlzLmdldFBvc2l0aW9uKClcbiAgICAgIHZhciBhY3R1YWxXaWR0aCAgPSAkdGlwWzBdLm9mZnNldFdpZHRoXG4gICAgICB2YXIgYWN0dWFsSGVpZ2h0ID0gJHRpcFswXS5vZmZzZXRIZWlnaHRcblxuICAgICAgaWYgKGF1dG9QbGFjZSkge1xuICAgICAgICB2YXIgb3JnUGxhY2VtZW50ID0gcGxhY2VtZW50XG4gICAgICAgIHZhciB2aWV3cG9ydERpbSA9IHRoaXMuZ2V0UG9zaXRpb24odGhpcy4kdmlld3BvcnQpXG5cbiAgICAgICAgcGxhY2VtZW50ID0gcGxhY2VtZW50ID09ICdib3R0b20nICYmIHBvcy5ib3R0b20gKyBhY3R1YWxIZWlnaHQgPiB2aWV3cG9ydERpbS5ib3R0b20gPyAndG9wJyAgICA6XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlbWVudCA9PSAndG9wJyAgICAmJiBwb3MudG9wICAgIC0gYWN0dWFsSGVpZ2h0IDwgdmlld3BvcnREaW0udG9wICAgID8gJ2JvdHRvbScgOlxuICAgICAgICAgICAgICAgICAgICBwbGFjZW1lbnQgPT0gJ3JpZ2h0JyAgJiYgcG9zLnJpZ2h0ICArIGFjdHVhbFdpZHRoICA+IHZpZXdwb3J0RGltLndpZHRoICA/ICdsZWZ0JyAgIDpcbiAgICAgICAgICAgICAgICAgICAgcGxhY2VtZW50ID09ICdsZWZ0JyAgICYmIHBvcy5sZWZ0ICAgLSBhY3R1YWxXaWR0aCAgPCB2aWV3cG9ydERpbS5sZWZ0ICAgPyAncmlnaHQnICA6XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlbWVudFxuXG4gICAgICAgICR0aXBcbiAgICAgICAgICAucmVtb3ZlQ2xhc3Mob3JnUGxhY2VtZW50KVxuICAgICAgICAgIC5hZGRDbGFzcyhwbGFjZW1lbnQpXG4gICAgICB9XG5cbiAgICAgIHZhciBjYWxjdWxhdGVkT2Zmc2V0ID0gdGhpcy5nZXRDYWxjdWxhdGVkT2Zmc2V0KHBsYWNlbWVudCwgcG9zLCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KVxuXG4gICAgICB0aGlzLmFwcGx5UGxhY2VtZW50KGNhbGN1bGF0ZWRPZmZzZXQsIHBsYWNlbWVudClcblxuICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJldkhvdmVyU3RhdGUgPSB0aGF0LmhvdmVyU3RhdGVcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdzaG93bi5icy4nICsgdGhhdC50eXBlKVxuICAgICAgICB0aGF0LmhvdmVyU3RhdGUgPSBudWxsXG5cbiAgICAgICAgaWYgKHByZXZIb3ZlclN0YXRlID09ICdvdXQnKSB0aGF0LmxlYXZlKHRoYXQpXG4gICAgICB9XG5cbiAgICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJHRpcC5oYXNDbGFzcygnZmFkZScpID9cbiAgICAgICAgJHRpcFxuICAgICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGNvbXBsZXRlKVxuICAgICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChUb29sdGlwLlRSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgY29tcGxldGUoKVxuICAgIH1cbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmFwcGx5UGxhY2VtZW50ID0gZnVuY3Rpb24gKG9mZnNldCwgcGxhY2VtZW50KSB7XG4gICAgdmFyICR0aXAgICA9IHRoaXMudGlwKClcbiAgICB2YXIgd2lkdGggID0gJHRpcFswXS5vZmZzZXRXaWR0aFxuICAgIHZhciBoZWlnaHQgPSAkdGlwWzBdLm9mZnNldEhlaWdodFxuXG4gICAgLy8gbWFudWFsbHkgcmVhZCBtYXJnaW5zIGJlY2F1c2UgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IGluY2x1ZGVzIGRpZmZlcmVuY2VcbiAgICB2YXIgbWFyZ2luVG9wID0gcGFyc2VJbnQoJHRpcC5jc3MoJ21hcmdpbi10b3AnKSwgMTApXG4gICAgdmFyIG1hcmdpbkxlZnQgPSBwYXJzZUludCgkdGlwLmNzcygnbWFyZ2luLWxlZnQnKSwgMTApXG5cbiAgICAvLyB3ZSBtdXN0IGNoZWNrIGZvciBOYU4gZm9yIGllIDgvOVxuICAgIGlmIChpc05hTihtYXJnaW5Ub3ApKSAgbWFyZ2luVG9wICA9IDBcbiAgICBpZiAoaXNOYU4obWFyZ2luTGVmdCkpIG1hcmdpbkxlZnQgPSAwXG5cbiAgICBvZmZzZXQudG9wICArPSBtYXJnaW5Ub3BcbiAgICBvZmZzZXQubGVmdCArPSBtYXJnaW5MZWZ0XG5cbiAgICAvLyAkLmZuLm9mZnNldCBkb2Vzbid0IHJvdW5kIHBpeGVsIHZhbHVlc1xuICAgIC8vIHNvIHdlIHVzZSBzZXRPZmZzZXQgZGlyZWN0bHkgd2l0aCBvdXIgb3duIGZ1bmN0aW9uIEItMFxuICAgICQub2Zmc2V0LnNldE9mZnNldCgkdGlwWzBdLCAkLmV4dGVuZCh7XG4gICAgICB1c2luZzogZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgICR0aXAuY3NzKHtcbiAgICAgICAgICB0b3A6IE1hdGgucm91bmQocHJvcHMudG9wKSxcbiAgICAgICAgICBsZWZ0OiBNYXRoLnJvdW5kKHByb3BzLmxlZnQpXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSwgb2Zmc2V0KSwgMClcblxuICAgICR0aXAuYWRkQ2xhc3MoJ2luJylcblxuICAgIC8vIGNoZWNrIHRvIHNlZSBpZiBwbGFjaW5nIHRpcCBpbiBuZXcgb2Zmc2V0IGNhdXNlZCB0aGUgdGlwIHRvIHJlc2l6ZSBpdHNlbGZcbiAgICB2YXIgYWN0dWFsV2lkdGggID0gJHRpcFswXS5vZmZzZXRXaWR0aFxuICAgIHZhciBhY3R1YWxIZWlnaHQgPSAkdGlwWzBdLm9mZnNldEhlaWdodFxuXG4gICAgaWYgKHBsYWNlbWVudCA9PSAndG9wJyAmJiBhY3R1YWxIZWlnaHQgIT0gaGVpZ2h0KSB7XG4gICAgICBvZmZzZXQudG9wID0gb2Zmc2V0LnRvcCArIGhlaWdodCAtIGFjdHVhbEhlaWdodFxuICAgIH1cblxuICAgIHZhciBkZWx0YSA9IHRoaXMuZ2V0Vmlld3BvcnRBZGp1c3RlZERlbHRhKHBsYWNlbWVudCwgb2Zmc2V0LCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KVxuXG4gICAgaWYgKGRlbHRhLmxlZnQpIG9mZnNldC5sZWZ0ICs9IGRlbHRhLmxlZnRcbiAgICBlbHNlIG9mZnNldC50b3AgKz0gZGVsdGEudG9wXG5cbiAgICB2YXIgaXNWZXJ0aWNhbCAgICAgICAgICA9IC90b3B8Ym90dG9tLy50ZXN0KHBsYWNlbWVudClcbiAgICB2YXIgYXJyb3dEZWx0YSAgICAgICAgICA9IGlzVmVydGljYWwgPyBkZWx0YS5sZWZ0ICogMiAtIHdpZHRoICsgYWN0dWFsV2lkdGggOiBkZWx0YS50b3AgKiAyIC0gaGVpZ2h0ICsgYWN0dWFsSGVpZ2h0XG4gICAgdmFyIGFycm93T2Zmc2V0UG9zaXRpb24gPSBpc1ZlcnRpY2FsID8gJ29mZnNldFdpZHRoJyA6ICdvZmZzZXRIZWlnaHQnXG5cbiAgICAkdGlwLm9mZnNldChvZmZzZXQpXG4gICAgdGhpcy5yZXBsYWNlQXJyb3coYXJyb3dEZWx0YSwgJHRpcFswXVthcnJvd09mZnNldFBvc2l0aW9uXSwgaXNWZXJ0aWNhbClcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnJlcGxhY2VBcnJvdyA9IGZ1bmN0aW9uIChkZWx0YSwgZGltZW5zaW9uLCBpc1ZlcnRpY2FsKSB7XG4gICAgdGhpcy5hcnJvdygpXG4gICAgICAuY3NzKGlzVmVydGljYWwgPyAnbGVmdCcgOiAndG9wJywgNTAgKiAoMSAtIGRlbHRhIC8gZGltZW5zaW9uKSArICclJylcbiAgICAgIC5jc3MoaXNWZXJ0aWNhbCA/ICd0b3AnIDogJ2xlZnQnLCAnJylcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnNldENvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICR0aXAgID0gdGhpcy50aXAoKVxuICAgIHZhciB0aXRsZSA9IHRoaXMuZ2V0VGl0bGUoKVxuXG4gICAgJHRpcC5maW5kKCcudG9vbHRpcC1pbm5lcicpW3RoaXMub3B0aW9ucy5odG1sID8gJ2h0bWwnIDogJ3RleHQnXSh0aXRsZSlcbiAgICAkdGlwLnJlbW92ZUNsYXNzKCdmYWRlIGluIHRvcCBib3R0b20gbGVmdCByaWdodCcpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgdmFyIHRoYXQgPSB0aGlzXG4gICAgdmFyICR0aXAgPSAkKHRoaXMuJHRpcClcbiAgICB2YXIgZSAgICA9ICQuRXZlbnQoJ2hpZGUuYnMuJyArIHRoaXMudHlwZSlcblxuICAgIGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgaWYgKHRoYXQuaG92ZXJTdGF0ZSAhPSAnaW4nKSAkdGlwLmRldGFjaCgpXG4gICAgICBpZiAodGhhdC4kZWxlbWVudCkgeyAvLyBUT0RPOiBDaGVjayB3aGV0aGVyIGd1YXJkaW5nIHRoaXMgY29kZSB3aXRoIHRoaXMgYGlmYCBpcyByZWFsbHkgbmVjZXNzYXJ5LlxuICAgICAgICB0aGF0LiRlbGVtZW50XG4gICAgICAgICAgLnJlbW92ZUF0dHIoJ2FyaWEtZGVzY3JpYmVkYnknKVxuICAgICAgICAgIC50cmlnZ2VyKCdoaWRkZW4uYnMuJyArIHRoYXQudHlwZSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKClcbiAgICB9XG5cbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSByZXR1cm5cblxuICAgICR0aXAucmVtb3ZlQ2xhc3MoJ2luJylcblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmICR0aXAuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAkdGlwXG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGNvbXBsZXRlKVxuICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoVG9vbHRpcC5UUkFOU0lUSU9OX0RVUkFUSU9OKSA6XG4gICAgICBjb21wbGV0ZSgpXG5cbiAgICB0aGlzLmhvdmVyU3RhdGUgPSBudWxsXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZml4VGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIGlmICgkZS5hdHRyKCd0aXRsZScpIHx8IHR5cGVvZiAkZS5hdHRyKCdkYXRhLW9yaWdpbmFsLXRpdGxlJykgIT0gJ3N0cmluZycpIHtcbiAgICAgICRlLmF0dHIoJ2RhdGEtb3JpZ2luYWwtdGl0bGUnLCAkZS5hdHRyKCd0aXRsZScpIHx8ICcnKS5hdHRyKCd0aXRsZScsICcnKVxuICAgIH1cbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmhhc0NvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VGl0bGUoKVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0UG9zaXRpb24gPSBmdW5jdGlvbiAoJGVsZW1lbnQpIHtcbiAgICAkZWxlbWVudCAgID0gJGVsZW1lbnQgfHwgdGhpcy4kZWxlbWVudFxuXG4gICAgdmFyIGVsICAgICA9ICRlbGVtZW50WzBdXG4gICAgdmFyIGlzQm9keSA9IGVsLnRhZ05hbWUgPT0gJ0JPRFknXG5cbiAgICB2YXIgZWxSZWN0ICAgID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAoZWxSZWN0LndpZHRoID09IG51bGwpIHtcbiAgICAgIC8vIHdpZHRoIGFuZCBoZWlnaHQgYXJlIG1pc3NpbmcgaW4gSUU4LCBzbyBjb21wdXRlIHRoZW0gbWFudWFsbHk7IHNlZSBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzE0MDkzXG4gICAgICBlbFJlY3QgPSAkLmV4dGVuZCh7fSwgZWxSZWN0LCB7IHdpZHRoOiBlbFJlY3QucmlnaHQgLSBlbFJlY3QubGVmdCwgaGVpZ2h0OiBlbFJlY3QuYm90dG9tIC0gZWxSZWN0LnRvcCB9KVxuICAgIH1cbiAgICB2YXIgaXNTdmcgPSB3aW5kb3cuU1ZHRWxlbWVudCAmJiBlbCBpbnN0YW5jZW9mIHdpbmRvdy5TVkdFbGVtZW50XG4gICAgLy8gQXZvaWQgdXNpbmcgJC5vZmZzZXQoKSBvbiBTVkdzIHNpbmNlIGl0IGdpdmVzIGluY29ycmVjdCByZXN1bHRzIGluIGpRdWVyeSAzLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzIwMjgwXG4gICAgdmFyIGVsT2Zmc2V0ICA9IGlzQm9keSA/IHsgdG9wOiAwLCBsZWZ0OiAwIH0gOiAoaXNTdmcgPyBudWxsIDogJGVsZW1lbnQub2Zmc2V0KCkpXG4gICAgdmFyIHNjcm9sbCAgICA9IHsgc2Nyb2xsOiBpc0JvZHkgPyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIDogJGVsZW1lbnQuc2Nyb2xsVG9wKCkgfVxuICAgIHZhciBvdXRlckRpbXMgPSBpc0JvZHkgPyB7IHdpZHRoOiAkKHdpbmRvdykud2lkdGgoKSwgaGVpZ2h0OiAkKHdpbmRvdykuaGVpZ2h0KCkgfSA6IG51bGxcblxuICAgIHJldHVybiAkLmV4dGVuZCh7fSwgZWxSZWN0LCBzY3JvbGwsIG91dGVyRGltcywgZWxPZmZzZXQpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRDYWxjdWxhdGVkT2Zmc2V0ID0gZnVuY3Rpb24gKHBsYWNlbWVudCwgcG9zLCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KSB7XG4gICAgcmV0dXJuIHBsYWNlbWVudCA9PSAnYm90dG9tJyA/IHsgdG9wOiBwb3MudG9wICsgcG9zLmhlaWdodCwgICBsZWZ0OiBwb3MubGVmdCArIHBvcy53aWR0aCAvIDIgLSBhY3R1YWxXaWR0aCAvIDIgfSA6XG4gICAgICAgICAgIHBsYWNlbWVudCA9PSAndG9wJyAgICA/IHsgdG9wOiBwb3MudG9wIC0gYWN0dWFsSGVpZ2h0LCBsZWZ0OiBwb3MubGVmdCArIHBvcy53aWR0aCAvIDIgLSBhY3R1YWxXaWR0aCAvIDIgfSA6XG4gICAgICAgICAgIHBsYWNlbWVudCA9PSAnbGVmdCcgICA/IHsgdG9wOiBwb3MudG9wICsgcG9zLmhlaWdodCAvIDIgLSBhY3R1YWxIZWlnaHQgLyAyLCBsZWZ0OiBwb3MubGVmdCAtIGFjdHVhbFdpZHRoIH0gOlxuICAgICAgICAvKiBwbGFjZW1lbnQgPT0gJ3JpZ2h0JyAqLyB7IHRvcDogcG9zLnRvcCArIHBvcy5oZWlnaHQgLyAyIC0gYWN0dWFsSGVpZ2h0IC8gMiwgbGVmdDogcG9zLmxlZnQgKyBwb3Mud2lkdGggfVxuXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRWaWV3cG9ydEFkanVzdGVkRGVsdGEgPSBmdW5jdGlvbiAocGxhY2VtZW50LCBwb3MsIGFjdHVhbFdpZHRoLCBhY3R1YWxIZWlnaHQpIHtcbiAgICB2YXIgZGVsdGEgPSB7IHRvcDogMCwgbGVmdDogMCB9XG4gICAgaWYgKCF0aGlzLiR2aWV3cG9ydCkgcmV0dXJuIGRlbHRhXG5cbiAgICB2YXIgdmlld3BvcnRQYWRkaW5nID0gdGhpcy5vcHRpb25zLnZpZXdwb3J0ICYmIHRoaXMub3B0aW9ucy52aWV3cG9ydC5wYWRkaW5nIHx8IDBcbiAgICB2YXIgdmlld3BvcnREaW1lbnNpb25zID0gdGhpcy5nZXRQb3NpdGlvbih0aGlzLiR2aWV3cG9ydClcblxuICAgIGlmICgvcmlnaHR8bGVmdC8udGVzdChwbGFjZW1lbnQpKSB7XG4gICAgICB2YXIgdG9wRWRnZU9mZnNldCAgICA9IHBvcy50b3AgLSB2aWV3cG9ydFBhZGRpbmcgLSB2aWV3cG9ydERpbWVuc2lvbnMuc2Nyb2xsXG4gICAgICB2YXIgYm90dG9tRWRnZU9mZnNldCA9IHBvcy50b3AgKyB2aWV3cG9ydFBhZGRpbmcgLSB2aWV3cG9ydERpbWVuc2lvbnMuc2Nyb2xsICsgYWN0dWFsSGVpZ2h0XG4gICAgICBpZiAodG9wRWRnZU9mZnNldCA8IHZpZXdwb3J0RGltZW5zaW9ucy50b3ApIHsgLy8gdG9wIG92ZXJmbG93XG4gICAgICAgIGRlbHRhLnRvcCA9IHZpZXdwb3J0RGltZW5zaW9ucy50b3AgLSB0b3BFZGdlT2Zmc2V0XG4gICAgICB9IGVsc2UgaWYgKGJvdHRvbUVkZ2VPZmZzZXQgPiB2aWV3cG9ydERpbWVuc2lvbnMudG9wICsgdmlld3BvcnREaW1lbnNpb25zLmhlaWdodCkgeyAvLyBib3R0b20gb3ZlcmZsb3dcbiAgICAgICAgZGVsdGEudG9wID0gdmlld3BvcnREaW1lbnNpb25zLnRvcCArIHZpZXdwb3J0RGltZW5zaW9ucy5oZWlnaHQgLSBib3R0b21FZGdlT2Zmc2V0XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBsZWZ0RWRnZU9mZnNldCAgPSBwb3MubGVmdCAtIHZpZXdwb3J0UGFkZGluZ1xuICAgICAgdmFyIHJpZ2h0RWRnZU9mZnNldCA9IHBvcy5sZWZ0ICsgdmlld3BvcnRQYWRkaW5nICsgYWN0dWFsV2lkdGhcbiAgICAgIGlmIChsZWZ0RWRnZU9mZnNldCA8IHZpZXdwb3J0RGltZW5zaW9ucy5sZWZ0KSB7IC8vIGxlZnQgb3ZlcmZsb3dcbiAgICAgICAgZGVsdGEubGVmdCA9IHZpZXdwb3J0RGltZW5zaW9ucy5sZWZ0IC0gbGVmdEVkZ2VPZmZzZXRcbiAgICAgIH0gZWxzZSBpZiAocmlnaHRFZGdlT2Zmc2V0ID4gdmlld3BvcnREaW1lbnNpb25zLnJpZ2h0KSB7IC8vIHJpZ2h0IG92ZXJmbG93XG4gICAgICAgIGRlbHRhLmxlZnQgPSB2aWV3cG9ydERpbWVuc2lvbnMubGVmdCArIHZpZXdwb3J0RGltZW5zaW9ucy53aWR0aCAtIHJpZ2h0RWRnZU9mZnNldFxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkZWx0YVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0VGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRpdGxlXG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIHZhciBvICA9IHRoaXMub3B0aW9uc1xuXG4gICAgdGl0bGUgPSAkZS5hdHRyKCdkYXRhLW9yaWdpbmFsLXRpdGxlJylcbiAgICAgIHx8ICh0eXBlb2Ygby50aXRsZSA9PSAnZnVuY3Rpb24nID8gby50aXRsZS5jYWxsKCRlWzBdKSA6ICBvLnRpdGxlKVxuXG4gICAgcmV0dXJuIHRpdGxlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRVSUQgPSBmdW5jdGlvbiAocHJlZml4KSB7XG4gICAgZG8gcHJlZml4ICs9IH5+KE1hdGgucmFuZG9tKCkgKiAxMDAwMDAwKVxuICAgIHdoaWxlIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwcmVmaXgpKVxuICAgIHJldHVybiBwcmVmaXhcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuJHRpcCkge1xuICAgICAgdGhpcy4kdGlwID0gJCh0aGlzLm9wdGlvbnMudGVtcGxhdGUpXG4gICAgICBpZiAodGhpcy4kdGlwLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnR5cGUgKyAnIGB0ZW1wbGF0ZWAgb3B0aW9uIG11c3QgY29uc2lzdCBvZiBleGFjdGx5IDEgdG9wLWxldmVsIGVsZW1lbnQhJylcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuJHRpcFxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuYXJyb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICh0aGlzLiRhcnJvdyA9IHRoaXMuJGFycm93IHx8IHRoaXMudGlwKCkuZmluZCgnLnRvb2x0aXAtYXJyb3cnKSlcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSB0cnVlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS50b2dnbGVFbmFibGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZW5hYmxlZCA9ICF0aGlzLmVuYWJsZWRcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzXG4gICAgaWYgKGUpIHtcbiAgICAgIHNlbGYgPSAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYnMuJyArIHRoaXMudHlwZSlcbiAgICAgIGlmICghc2VsZikge1xuICAgICAgICBzZWxmID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZS5jdXJyZW50VGFyZ2V0LCB0aGlzLmdldERlbGVnYXRlT3B0aW9ucygpKVxuICAgICAgICAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYnMuJyArIHRoaXMudHlwZSwgc2VsZilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZSkge1xuICAgICAgc2VsZi5pblN0YXRlLmNsaWNrID0gIXNlbGYuaW5TdGF0ZS5jbGlja1xuICAgICAgaWYgKHNlbGYuaXNJblN0YXRlVHJ1ZSgpKSBzZWxmLmVudGVyKHNlbGYpXG4gICAgICBlbHNlIHNlbGYubGVhdmUoc2VsZilcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi50aXAoKS5oYXNDbGFzcygnaW4nKSA/IHNlbGYubGVhdmUoc2VsZikgOiBzZWxmLmVudGVyKHNlbGYpXG4gICAgfVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdGhhdCA9IHRoaXNcbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0KVxuICAgIHRoaXMuaGlkZShmdW5jdGlvbiAoKSB7XG4gICAgICB0aGF0LiRlbGVtZW50Lm9mZignLicgKyB0aGF0LnR5cGUpLnJlbW92ZURhdGEoJ2JzLicgKyB0aGF0LnR5cGUpXG4gICAgICBpZiAodGhhdC4kdGlwKSB7XG4gICAgICAgIHRoYXQuJHRpcC5kZXRhY2goKVxuICAgICAgfVxuICAgICAgdGhhdC4kdGlwID0gbnVsbFxuICAgICAgdGhhdC4kYXJyb3cgPSBudWxsXG4gICAgICB0aGF0LiR2aWV3cG9ydCA9IG51bGxcbiAgICAgIHRoYXQuJGVsZW1lbnQgPSBudWxsXG4gICAgfSlcbiAgfVxuXG5cbiAgLy8gVE9PTFRJUCBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnRvb2x0aXAnKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEgJiYgL2Rlc3Ryb3l8aGlkZS8udGVzdChvcHRpb24pKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMudG9vbHRpcCcsIChkYXRhID0gbmV3IFRvb2x0aXAodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLnRvb2x0aXBcblxuICAkLmZuLnRvb2x0aXAgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yID0gVG9vbHRpcFxuXG5cbiAgLy8gVE9PTFRJUCBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi50b29sdGlwLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi50b29sdGlwID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvdG9vbHRpcC5qc1xuLy8gbW9kdWxlIGlkID0gMTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHBvcG92ZXIuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNwb3BvdmVyc1xuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFBPUE9WRVIgUFVCTElDIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBQb3BvdmVyID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmluaXQoJ3BvcG92ZXInLCBlbGVtZW50LCBvcHRpb25zKVxuICB9XG5cbiAgaWYgKCEkLmZuLnRvb2x0aXApIHRocm93IG5ldyBFcnJvcignUG9wb3ZlciByZXF1aXJlcyB0b29sdGlwLmpzJylcblxuICBQb3BvdmVyLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFBvcG92ZXIuREVGQVVMVFMgPSAkLmV4dGVuZCh7fSwgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yLkRFRkFVTFRTLCB7XG4gICAgcGxhY2VtZW50OiAncmlnaHQnLFxuICAgIHRyaWdnZXI6ICdjbGljaycsXG4gICAgY29udGVudDogJycsXG4gICAgdGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwicG9wb3ZlclwiIHJvbGU9XCJ0b29sdGlwXCI+PGRpdiBjbGFzcz1cImFycm93XCI+PC9kaXY+PGgzIGNsYXNzPVwicG9wb3Zlci10aXRsZVwiPjwvaDM+PGRpdiBjbGFzcz1cInBvcG92ZXItY29udGVudFwiPjwvZGl2PjwvZGl2PidcbiAgfSlcblxuXG4gIC8vIE5PVEU6IFBPUE9WRVIgRVhURU5EUyB0b29sdGlwLmpzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgUG9wb3Zlci5wcm90b3R5cGUgPSAkLmV4dGVuZCh7fSwgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yLnByb3RvdHlwZSlcblxuICBQb3BvdmVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFBvcG92ZXJcblxuICBQb3BvdmVyLnByb3RvdHlwZS5nZXREZWZhdWx0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gUG9wb3Zlci5ERUZBVUxUU1xuICB9XG5cbiAgUG9wb3Zlci5wcm90b3R5cGUuc2V0Q29udGVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHRpcCAgICA9IHRoaXMudGlwKClcbiAgICB2YXIgdGl0bGUgICA9IHRoaXMuZ2V0VGl0bGUoKVxuICAgIHZhciBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KClcblxuICAgICR0aXAuZmluZCgnLnBvcG92ZXItdGl0bGUnKVt0aGlzLm9wdGlvbnMuaHRtbCA/ICdodG1sJyA6ICd0ZXh0J10odGl0bGUpXG4gICAgJHRpcC5maW5kKCcucG9wb3Zlci1jb250ZW50JykuY2hpbGRyZW4oKS5kZXRhY2goKS5lbmQoKVsgLy8gd2UgdXNlIGFwcGVuZCBmb3IgaHRtbCBvYmplY3RzIHRvIG1haW50YWluIGpzIGV2ZW50c1xuICAgICAgdGhpcy5vcHRpb25zLmh0bWwgPyAodHlwZW9mIGNvbnRlbnQgPT0gJ3N0cmluZycgPyAnaHRtbCcgOiAnYXBwZW5kJykgOiAndGV4dCdcbiAgICBdKGNvbnRlbnQpXG5cbiAgICAkdGlwLnJlbW92ZUNsYXNzKCdmYWRlIHRvcCBib3R0b20gbGVmdCByaWdodCBpbicpXG5cbiAgICAvLyBJRTggZG9lc24ndCBhY2NlcHQgaGlkaW5nIHZpYSB0aGUgYDplbXB0eWAgcHNldWRvIHNlbGVjdG9yLCB3ZSBoYXZlIHRvIGRvXG4gICAgLy8gdGhpcyBtYW51YWxseSBieSBjaGVja2luZyB0aGUgY29udGVudHMuXG4gICAgaWYgKCEkdGlwLmZpbmQoJy5wb3BvdmVyLXRpdGxlJykuaHRtbCgpKSAkdGlwLmZpbmQoJy5wb3BvdmVyLXRpdGxlJykuaGlkZSgpXG4gIH1cblxuICBQb3BvdmVyLnByb3RvdHlwZS5oYXNDb250ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmdldFRpdGxlKCkgfHwgdGhpcy5nZXRDb250ZW50KClcbiAgfVxuXG4gIFBvcG92ZXIucHJvdG90eXBlLmdldENvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIHZhciBvICA9IHRoaXMub3B0aW9uc1xuXG4gICAgcmV0dXJuICRlLmF0dHIoJ2RhdGEtY29udGVudCcpXG4gICAgICB8fCAodHlwZW9mIG8uY29udGVudCA9PSAnZnVuY3Rpb24nID9cbiAgICAgICAgICAgIG8uY29udGVudC5jYWxsKCRlWzBdKSA6XG4gICAgICAgICAgICBvLmNvbnRlbnQpXG4gIH1cblxuICBQb3BvdmVyLnByb3RvdHlwZS5hcnJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKHRoaXMuJGFycm93ID0gdGhpcy4kYXJyb3cgfHwgdGhpcy50aXAoKS5maW5kKCcuYXJyb3cnKSlcbiAgfVxuXG5cbiAgLy8gUE9QT1ZFUiBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnBvcG92ZXInKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEgJiYgL2Rlc3Ryb3l8aGlkZS8udGVzdChvcHRpb24pKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMucG9wb3ZlcicsIChkYXRhID0gbmV3IFBvcG92ZXIodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLnBvcG92ZXJcblxuICAkLmZuLnBvcG92ZXIgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5wb3BvdmVyLkNvbnN0cnVjdG9yID0gUG9wb3ZlclxuXG5cbiAgLy8gUE9QT1ZFUiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5wb3BvdmVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5wb3BvdmVyID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvcG9wb3Zlci5qc1xuLy8gbW9kdWxlIGlkID0gMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHNjcm9sbHNweS5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI3Njcm9sbHNweVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFNDUk9MTFNQWSBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gU2Nyb2xsU3B5KGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLiRib2R5ICAgICAgICAgID0gJChkb2N1bWVudC5ib2R5KVxuICAgIHRoaXMuJHNjcm9sbEVsZW1lbnQgPSAkKGVsZW1lbnQpLmlzKGRvY3VtZW50LmJvZHkpID8gJCh3aW5kb3cpIDogJChlbGVtZW50KVxuICAgIHRoaXMub3B0aW9ucyAgICAgICAgPSAkLmV4dGVuZCh7fSwgU2Nyb2xsU3B5LkRFRkFVTFRTLCBvcHRpb25zKVxuICAgIHRoaXMuc2VsZWN0b3IgICAgICAgPSAodGhpcy5vcHRpb25zLnRhcmdldCB8fCAnJykgKyAnIC5uYXYgbGkgPiBhJ1xuICAgIHRoaXMub2Zmc2V0cyAgICAgICAgPSBbXVxuICAgIHRoaXMudGFyZ2V0cyAgICAgICAgPSBbXVxuICAgIHRoaXMuYWN0aXZlVGFyZ2V0ICAgPSBudWxsXG4gICAgdGhpcy5zY3JvbGxIZWlnaHQgICA9IDBcblxuICAgIHRoaXMuJHNjcm9sbEVsZW1lbnQub24oJ3Njcm9sbC5icy5zY3JvbGxzcHknLCAkLnByb3h5KHRoaXMucHJvY2VzcywgdGhpcykpXG4gICAgdGhpcy5yZWZyZXNoKClcbiAgICB0aGlzLnByb2Nlc3MoKVxuICB9XG5cbiAgU2Nyb2xsU3B5LlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFNjcm9sbFNweS5ERUZBVUxUUyA9IHtcbiAgICBvZmZzZXQ6IDEwXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy4kc2Nyb2xsRWxlbWVudFswXS5zY3JvbGxIZWlnaHQgfHwgTWF0aC5tYXgodGhpcy4kYm9keVswXS5zY3JvbGxIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQpXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRoYXQgICAgICAgICAgPSB0aGlzXG4gICAgdmFyIG9mZnNldE1ldGhvZCAgPSAnb2Zmc2V0J1xuICAgIHZhciBvZmZzZXRCYXNlICAgID0gMFxuXG4gICAgdGhpcy5vZmZzZXRzICAgICAgPSBbXVxuICAgIHRoaXMudGFyZ2V0cyAgICAgID0gW11cbiAgICB0aGlzLnNjcm9sbEhlaWdodCA9IHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KClcblxuICAgIGlmICghJC5pc1dpbmRvdyh0aGlzLiRzY3JvbGxFbGVtZW50WzBdKSkge1xuICAgICAgb2Zmc2V0TWV0aG9kID0gJ3Bvc2l0aW9uJ1xuICAgICAgb2Zmc2V0QmFzZSAgID0gdGhpcy4kc2Nyb2xsRWxlbWVudC5zY3JvbGxUb3AoKVxuICAgIH1cblxuICAgIHRoaXMuJGJvZHlcbiAgICAgIC5maW5kKHRoaXMuc2VsZWN0b3IpXG4gICAgICAubWFwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRlbCAgID0gJCh0aGlzKVxuICAgICAgICB2YXIgaHJlZiAgPSAkZWwuZGF0YSgndGFyZ2V0JykgfHwgJGVsLmF0dHIoJ2hyZWYnKVxuICAgICAgICB2YXIgJGhyZWYgPSAvXiMuLy50ZXN0KGhyZWYpICYmICQoaHJlZilcblxuICAgICAgICByZXR1cm4gKCRocmVmXG4gICAgICAgICAgJiYgJGhyZWYubGVuZ3RoXG4gICAgICAgICAgJiYgJGhyZWYuaXMoJzp2aXNpYmxlJylcbiAgICAgICAgICAmJiBbWyRocmVmW29mZnNldE1ldGhvZF0oKS50b3AgKyBvZmZzZXRCYXNlLCBocmVmXV0pIHx8IG51bGxcbiAgICAgIH0pXG4gICAgICAuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYVswXSAtIGJbMF0gfSlcbiAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5vZmZzZXRzLnB1c2godGhpc1swXSlcbiAgICAgICAgdGhhdC50YXJnZXRzLnB1c2godGhpc1sxXSlcbiAgICAgIH0pXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLnByb2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNjcm9sbFRvcCAgICA9IHRoaXMuJHNjcm9sbEVsZW1lbnQuc2Nyb2xsVG9wKCkgKyB0aGlzLm9wdGlvbnMub2Zmc2V0XG4gICAgdmFyIHNjcm9sbEhlaWdodCA9IHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KClcbiAgICB2YXIgbWF4U2Nyb2xsICAgID0gdGhpcy5vcHRpb25zLm9mZnNldCArIHNjcm9sbEhlaWdodCAtIHRoaXMuJHNjcm9sbEVsZW1lbnQuaGVpZ2h0KClcbiAgICB2YXIgb2Zmc2V0cyAgICAgID0gdGhpcy5vZmZzZXRzXG4gICAgdmFyIHRhcmdldHMgICAgICA9IHRoaXMudGFyZ2V0c1xuICAgIHZhciBhY3RpdmVUYXJnZXQgPSB0aGlzLmFjdGl2ZVRhcmdldFxuICAgIHZhciBpXG5cbiAgICBpZiAodGhpcy5zY3JvbGxIZWlnaHQgIT0gc2Nyb2xsSGVpZ2h0KSB7XG4gICAgICB0aGlzLnJlZnJlc2goKVxuICAgIH1cblxuICAgIGlmIChzY3JvbGxUb3AgPj0gbWF4U2Nyb2xsKSB7XG4gICAgICByZXR1cm4gYWN0aXZlVGFyZ2V0ICE9IChpID0gdGFyZ2V0c1t0YXJnZXRzLmxlbmd0aCAtIDFdKSAmJiB0aGlzLmFjdGl2YXRlKGkpXG4gICAgfVxuXG4gICAgaWYgKGFjdGl2ZVRhcmdldCAmJiBzY3JvbGxUb3AgPCBvZmZzZXRzWzBdKSB7XG4gICAgICB0aGlzLmFjdGl2ZVRhcmdldCA9IG51bGxcbiAgICAgIHJldHVybiB0aGlzLmNsZWFyKClcbiAgICB9XG5cbiAgICBmb3IgKGkgPSBvZmZzZXRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgYWN0aXZlVGFyZ2V0ICE9IHRhcmdldHNbaV1cbiAgICAgICAgJiYgc2Nyb2xsVG9wID49IG9mZnNldHNbaV1cbiAgICAgICAgJiYgKG9mZnNldHNbaSArIDFdID09PSB1bmRlZmluZWQgfHwgc2Nyb2xsVG9wIDwgb2Zmc2V0c1tpICsgMV0pXG4gICAgICAgICYmIHRoaXMuYWN0aXZhdGUodGFyZ2V0c1tpXSlcbiAgICB9XG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLmFjdGl2YXRlID0gZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIHRoaXMuYWN0aXZlVGFyZ2V0ID0gdGFyZ2V0XG5cbiAgICB0aGlzLmNsZWFyKClcblxuICAgIHZhciBzZWxlY3RvciA9IHRoaXMuc2VsZWN0b3IgK1xuICAgICAgJ1tkYXRhLXRhcmdldD1cIicgKyB0YXJnZXQgKyAnXCJdLCcgK1xuICAgICAgdGhpcy5zZWxlY3RvciArICdbaHJlZj1cIicgKyB0YXJnZXQgKyAnXCJdJ1xuXG4gICAgdmFyIGFjdGl2ZSA9ICQoc2VsZWN0b3IpXG4gICAgICAucGFyZW50cygnbGknKVxuICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuXG4gICAgaWYgKGFjdGl2ZS5wYXJlbnQoJy5kcm9wZG93bi1tZW51JykubGVuZ3RoKSB7XG4gICAgICBhY3RpdmUgPSBhY3RpdmVcbiAgICAgICAgLmNsb3Nlc3QoJ2xpLmRyb3Bkb3duJylcbiAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgIH1cblxuICAgIGFjdGl2ZS50cmlnZ2VyKCdhY3RpdmF0ZS5icy5zY3JvbGxzcHknKVxuICB9XG5cbiAgU2Nyb2xsU3B5LnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKHRoaXMuc2VsZWN0b3IpXG4gICAgICAucGFyZW50c1VudGlsKHRoaXMub3B0aW9ucy50YXJnZXQsICcuYWN0aXZlJylcbiAgICAgIC5yZW1vdmVDbGFzcygnYWN0aXZlJylcbiAgfVxuXG5cbiAgLy8gU0NST0xMU1BZIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIFBsdWdpbihvcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyAgID0gJCh0aGlzKVxuICAgICAgdmFyIGRhdGEgICAgPSAkdGhpcy5kYXRhKCdicy5zY3JvbGxzcHknKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLnNjcm9sbHNweScsIChkYXRhID0gbmV3IFNjcm9sbFNweSh0aGlzLCBvcHRpb25zKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uc2Nyb2xsc3B5XG5cbiAgJC5mbi5zY3JvbGxzcHkgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5zY3JvbGxzcHkuQ29uc3RydWN0b3IgPSBTY3JvbGxTcHlcblxuXG4gIC8vIFNDUk9MTFNQWSBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLnNjcm9sbHNweS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uc2Nyb2xsc3B5ID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gU0NST0xMU1BZIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PT09PVxuXG4gICQod2luZG93KS5vbignbG9hZC5icy5zY3JvbGxzcHkuZGF0YS1hcGknLCBmdW5jdGlvbiAoKSB7XG4gICAgJCgnW2RhdGEtc3B5PVwic2Nyb2xsXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHNweSA9ICQodGhpcylcbiAgICAgIFBsdWdpbi5jYWxsKCRzcHksICRzcHkuZGF0YSgpKVxuICAgIH0pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9zY3JvbGxzcHkuanNcbi8vIG1vZHVsZSBpZCA9IDEyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiB0YWIuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyN0YWJzXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVEFCIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgVGFiID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAvLyBqc2NzOmRpc2FibGUgcmVxdWlyZURvbGxhckJlZm9yZWpRdWVyeUFzc2lnbm1lbnRcbiAgICB0aGlzLmVsZW1lbnQgPSAkKGVsZW1lbnQpXG4gICAgLy8ganNjczplbmFibGUgcmVxdWlyZURvbGxhckJlZm9yZWpRdWVyeUFzc2lnbm1lbnRcbiAgfVxuXG4gIFRhYi5WRVJTSU9OID0gJzMuMy43J1xuXG4gIFRhYi5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwXG5cbiAgVGFiLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkdGhpcyAgICA9IHRoaXMuZWxlbWVudFxuICAgIHZhciAkdWwgICAgICA9ICR0aGlzLmNsb3Nlc3QoJ3VsOm5vdCguZHJvcGRvd24tbWVudSknKVxuICAgIHZhciBzZWxlY3RvciA9ICR0aGlzLmRhdGEoJ3RhcmdldCcpXG5cbiAgICBpZiAoIXNlbGVjdG9yKSB7XG4gICAgICBzZWxlY3RvciA9ICR0aGlzLmF0dHIoJ2hyZWYnKVxuICAgICAgc2VsZWN0b3IgPSBzZWxlY3RvciAmJiBzZWxlY3Rvci5yZXBsYWNlKC8uKig/PSNbXlxcc10qJCkvLCAnJykgLy8gc3RyaXAgZm9yIGllN1xuICAgIH1cblxuICAgIGlmICgkdGhpcy5wYXJlbnQoJ2xpJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSByZXR1cm5cblxuICAgIHZhciAkcHJldmlvdXMgPSAkdWwuZmluZCgnLmFjdGl2ZTpsYXN0IGEnKVxuICAgIHZhciBoaWRlRXZlbnQgPSAkLkV2ZW50KCdoaWRlLmJzLnRhYicsIHtcbiAgICAgIHJlbGF0ZWRUYXJnZXQ6ICR0aGlzWzBdXG4gICAgfSlcbiAgICB2YXIgc2hvd0V2ZW50ID0gJC5FdmVudCgnc2hvdy5icy50YWInLCB7XG4gICAgICByZWxhdGVkVGFyZ2V0OiAkcHJldmlvdXNbMF1cbiAgICB9KVxuXG4gICAgJHByZXZpb3VzLnRyaWdnZXIoaGlkZUV2ZW50KVxuICAgICR0aGlzLnRyaWdnZXIoc2hvd0V2ZW50KVxuXG4gICAgaWYgKHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSB8fCBoaWRlRXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgdmFyICR0YXJnZXQgPSAkKHNlbGVjdG9yKVxuXG4gICAgdGhpcy5hY3RpdmF0ZSgkdGhpcy5jbG9zZXN0KCdsaScpLCAkdWwpXG4gICAgdGhpcy5hY3RpdmF0ZSgkdGFyZ2V0LCAkdGFyZ2V0LnBhcmVudCgpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAkcHJldmlvdXMudHJpZ2dlcih7XG4gICAgICAgIHR5cGU6ICdoaWRkZW4uYnMudGFiJyxcbiAgICAgICAgcmVsYXRlZFRhcmdldDogJHRoaXNbMF1cbiAgICAgIH0pXG4gICAgICAkdGhpcy50cmlnZ2VyKHtcbiAgICAgICAgdHlwZTogJ3Nob3duLmJzLnRhYicsXG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6ICRwcmV2aW91c1swXVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgVGFiLnByb3RvdHlwZS5hY3RpdmF0ZSA9IGZ1bmN0aW9uIChlbGVtZW50LCBjb250YWluZXIsIGNhbGxiYWNrKSB7XG4gICAgdmFyICRhY3RpdmUgICAgPSBjb250YWluZXIuZmluZCgnPiAuYWN0aXZlJylcbiAgICB2YXIgdHJhbnNpdGlvbiA9IGNhbGxiYWNrXG4gICAgICAmJiAkLnN1cHBvcnQudHJhbnNpdGlvblxuICAgICAgJiYgKCRhY3RpdmUubGVuZ3RoICYmICRhY3RpdmUuaGFzQ2xhc3MoJ2ZhZGUnKSB8fCAhIWNvbnRhaW5lci5maW5kKCc+IC5mYWRlJykubGVuZ3RoKVxuXG4gICAgZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgICRhY3RpdmVcbiAgICAgICAgLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuICAgICAgICAuZmluZCgnPiAuZHJvcGRvd24tbWVudSA+IC5hY3RpdmUnKVxuICAgICAgICAgIC5yZW1vdmVDbGFzcygnYWN0aXZlJylcbiAgICAgICAgLmVuZCgpXG4gICAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKVxuICAgICAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgZmFsc2UpXG5cbiAgICAgIGVsZW1lbnRcbiAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAuZmluZCgnW2RhdGEtdG9nZ2xlPVwidGFiXCJdJylcbiAgICAgICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsIHRydWUpXG5cbiAgICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICAgIGVsZW1lbnRbMF0ub2Zmc2V0V2lkdGggLy8gcmVmbG93IGZvciB0cmFuc2l0aW9uXG4gICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoJ2luJylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZhZGUnKVxuICAgICAgfVxuXG4gICAgICBpZiAoZWxlbWVudC5wYXJlbnQoJy5kcm9wZG93bi1tZW51JykubGVuZ3RoKSB7XG4gICAgICAgIGVsZW1lbnRcbiAgICAgICAgICAuY2xvc2VzdCgnbGkuZHJvcGRvd24nKVxuICAgICAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAgIC5lbmQoKVxuICAgICAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKVxuICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKVxuICAgICAgfVxuXG4gICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpXG4gICAgfVxuXG4gICAgJGFjdGl2ZS5sZW5ndGggJiYgdHJhbnNpdGlvbiA/XG4gICAgICAkYWN0aXZlXG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIG5leHQpXG4gICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChUYWIuVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgbmV4dCgpXG5cbiAgICAkYWN0aXZlLnJlbW92ZUNsYXNzKCdpbicpXG4gIH1cblxuXG4gIC8vIFRBQiBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgPSAkdGhpcy5kYXRhKCdicy50YWInKVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLnRhYicsIChkYXRhID0gbmV3IFRhYih0aGlzKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4udGFiXG5cbiAgJC5mbi50YWIgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi50YWIuQ29uc3RydWN0b3IgPSBUYWJcblxuXG4gIC8vIFRBQiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT1cblxuICAkLmZuLnRhYi5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4udGFiID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gVEFCIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PVxuXG4gIHZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKVxuICAgIFBsdWdpbi5jYWxsKCQodGhpcyksICdzaG93JylcbiAgfVxuXG4gICQoZG9jdW1lbnQpXG4gICAgLm9uKCdjbGljay5icy50YWIuZGF0YS1hcGknLCAnW2RhdGEtdG9nZ2xlPVwidGFiXCJdJywgY2xpY2tIYW5kbGVyKVxuICAgIC5vbignY2xpY2suYnMudGFiLmRhdGEtYXBpJywgJ1tkYXRhLXRvZ2dsZT1cInBpbGxcIl0nLCBjbGlja0hhbmRsZXIpXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90YWIuanNcbi8vIG1vZHVsZSBpZCA9IDEzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBhZmZpeC5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI2FmZml4XG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQUZGSVggQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIEFmZml4ID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgQWZmaXguREVGQVVMVFMsIG9wdGlvbnMpXG5cbiAgICB0aGlzLiR0YXJnZXQgPSAkKHRoaXMub3B0aW9ucy50YXJnZXQpXG4gICAgICAub24oJ3Njcm9sbC5icy5hZmZpeC5kYXRhLWFwaScsICQucHJveHkodGhpcy5jaGVja1Bvc2l0aW9uLCB0aGlzKSlcbiAgICAgIC5vbignY2xpY2suYnMuYWZmaXguZGF0YS1hcGknLCAgJC5wcm94eSh0aGlzLmNoZWNrUG9zaXRpb25XaXRoRXZlbnRMb29wLCB0aGlzKSlcblxuICAgIHRoaXMuJGVsZW1lbnQgICAgID0gJChlbGVtZW50KVxuICAgIHRoaXMuYWZmaXhlZCAgICAgID0gbnVsbFxuICAgIHRoaXMudW5waW4gICAgICAgID0gbnVsbFxuICAgIHRoaXMucGlubmVkT2Zmc2V0ID0gbnVsbFxuXG4gICAgdGhpcy5jaGVja1Bvc2l0aW9uKClcbiAgfVxuXG4gIEFmZml4LlZFUlNJT04gID0gJzMuMy43J1xuXG4gIEFmZml4LlJFU0VUICAgID0gJ2FmZml4IGFmZml4LXRvcCBhZmZpeC1ib3R0b20nXG5cbiAgQWZmaXguREVGQVVMVFMgPSB7XG4gICAgb2Zmc2V0OiAwLFxuICAgIHRhcmdldDogd2luZG93XG4gIH1cblxuICBBZmZpeC5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoc2Nyb2xsSGVpZ2h0LCBoZWlnaHQsIG9mZnNldFRvcCwgb2Zmc2V0Qm90dG9tKSB7XG4gICAgdmFyIHNjcm9sbFRvcCAgICA9IHRoaXMuJHRhcmdldC5zY3JvbGxUb3AoKVxuICAgIHZhciBwb3NpdGlvbiAgICAgPSB0aGlzLiRlbGVtZW50Lm9mZnNldCgpXG4gICAgdmFyIHRhcmdldEhlaWdodCA9IHRoaXMuJHRhcmdldC5oZWlnaHQoKVxuXG4gICAgaWYgKG9mZnNldFRvcCAhPSBudWxsICYmIHRoaXMuYWZmaXhlZCA9PSAndG9wJykgcmV0dXJuIHNjcm9sbFRvcCA8IG9mZnNldFRvcCA/ICd0b3AnIDogZmFsc2VcblxuICAgIGlmICh0aGlzLmFmZml4ZWQgPT0gJ2JvdHRvbScpIHtcbiAgICAgIGlmIChvZmZzZXRUb3AgIT0gbnVsbCkgcmV0dXJuIChzY3JvbGxUb3AgKyB0aGlzLnVucGluIDw9IHBvc2l0aW9uLnRvcCkgPyBmYWxzZSA6ICdib3R0b20nXG4gICAgICByZXR1cm4gKHNjcm9sbFRvcCArIHRhcmdldEhlaWdodCA8PSBzY3JvbGxIZWlnaHQgLSBvZmZzZXRCb3R0b20pID8gZmFsc2UgOiAnYm90dG9tJ1xuICAgIH1cblxuICAgIHZhciBpbml0aWFsaXppbmcgICA9IHRoaXMuYWZmaXhlZCA9PSBudWxsXG4gICAgdmFyIGNvbGxpZGVyVG9wICAgID0gaW5pdGlhbGl6aW5nID8gc2Nyb2xsVG9wIDogcG9zaXRpb24udG9wXG4gICAgdmFyIGNvbGxpZGVySGVpZ2h0ID0gaW5pdGlhbGl6aW5nID8gdGFyZ2V0SGVpZ2h0IDogaGVpZ2h0XG5cbiAgICBpZiAob2Zmc2V0VG9wICE9IG51bGwgJiYgc2Nyb2xsVG9wIDw9IG9mZnNldFRvcCkgcmV0dXJuICd0b3AnXG4gICAgaWYgKG9mZnNldEJvdHRvbSAhPSBudWxsICYmIChjb2xsaWRlclRvcCArIGNvbGxpZGVySGVpZ2h0ID49IHNjcm9sbEhlaWdodCAtIG9mZnNldEJvdHRvbSkpIHJldHVybiAnYm90dG9tJ1xuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBBZmZpeC5wcm90b3R5cGUuZ2V0UGlubmVkT2Zmc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnBpbm5lZE9mZnNldCkgcmV0dXJuIHRoaXMucGlubmVkT2Zmc2V0XG4gICAgdGhpcy4kZWxlbWVudC5yZW1vdmVDbGFzcyhBZmZpeC5SRVNFVCkuYWRkQ2xhc3MoJ2FmZml4JylcbiAgICB2YXIgc2Nyb2xsVG9wID0gdGhpcy4kdGFyZ2V0LnNjcm9sbFRvcCgpXG4gICAgdmFyIHBvc2l0aW9uICA9IHRoaXMuJGVsZW1lbnQub2Zmc2V0KClcbiAgICByZXR1cm4gKHRoaXMucGlubmVkT2Zmc2V0ID0gcG9zaXRpb24udG9wIC0gc2Nyb2xsVG9wKVxuICB9XG5cbiAgQWZmaXgucHJvdG90eXBlLmNoZWNrUG9zaXRpb25XaXRoRXZlbnRMb29wID0gZnVuY3Rpb24gKCkge1xuICAgIHNldFRpbWVvdXQoJC5wcm94eSh0aGlzLmNoZWNrUG9zaXRpb24sIHRoaXMpLCAxKVxuICB9XG5cbiAgQWZmaXgucHJvdG90eXBlLmNoZWNrUG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLiRlbGVtZW50LmlzKCc6dmlzaWJsZScpKSByZXR1cm5cblxuICAgIHZhciBoZWlnaHQgICAgICAgPSB0aGlzLiRlbGVtZW50LmhlaWdodCgpXG4gICAgdmFyIG9mZnNldCAgICAgICA9IHRoaXMub3B0aW9ucy5vZmZzZXRcbiAgICB2YXIgb2Zmc2V0VG9wICAgID0gb2Zmc2V0LnRvcFxuICAgIHZhciBvZmZzZXRCb3R0b20gPSBvZmZzZXQuYm90dG9tXG4gICAgdmFyIHNjcm9sbEhlaWdodCA9IE1hdGgubWF4KCQoZG9jdW1lbnQpLmhlaWdodCgpLCAkKGRvY3VtZW50LmJvZHkpLmhlaWdodCgpKVxuXG4gICAgaWYgKHR5cGVvZiBvZmZzZXQgIT0gJ29iamVjdCcpICAgICAgICAgb2Zmc2V0Qm90dG9tID0gb2Zmc2V0VG9wID0gb2Zmc2V0XG4gICAgaWYgKHR5cGVvZiBvZmZzZXRUb3AgPT0gJ2Z1bmN0aW9uJykgICAgb2Zmc2V0VG9wICAgID0gb2Zmc2V0LnRvcCh0aGlzLiRlbGVtZW50KVxuICAgIGlmICh0eXBlb2Ygb2Zmc2V0Qm90dG9tID09ICdmdW5jdGlvbicpIG9mZnNldEJvdHRvbSA9IG9mZnNldC5ib3R0b20odGhpcy4kZWxlbWVudClcblxuICAgIHZhciBhZmZpeCA9IHRoaXMuZ2V0U3RhdGUoc2Nyb2xsSGVpZ2h0LCBoZWlnaHQsIG9mZnNldFRvcCwgb2Zmc2V0Qm90dG9tKVxuXG4gICAgaWYgKHRoaXMuYWZmaXhlZCAhPSBhZmZpeCkge1xuICAgICAgaWYgKHRoaXMudW5waW4gIT0gbnVsbCkgdGhpcy4kZWxlbWVudC5jc3MoJ3RvcCcsICcnKVxuXG4gICAgICB2YXIgYWZmaXhUeXBlID0gJ2FmZml4JyArIChhZmZpeCA/ICctJyArIGFmZml4IDogJycpXG4gICAgICB2YXIgZSAgICAgICAgID0gJC5FdmVudChhZmZpeFR5cGUgKyAnLmJzLmFmZml4JylcblxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKGUpXG5cbiAgICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSByZXR1cm5cblxuICAgICAgdGhpcy5hZmZpeGVkID0gYWZmaXhcbiAgICAgIHRoaXMudW5waW4gPSBhZmZpeCA9PSAnYm90dG9tJyA/IHRoaXMuZ2V0UGlubmVkT2Zmc2V0KCkgOiBudWxsXG5cbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLnJlbW92ZUNsYXNzKEFmZml4LlJFU0VUKVxuICAgICAgICAuYWRkQ2xhc3MoYWZmaXhUeXBlKVxuICAgICAgICAudHJpZ2dlcihhZmZpeFR5cGUucmVwbGFjZSgnYWZmaXgnLCAnYWZmaXhlZCcpICsgJy5icy5hZmZpeCcpXG4gICAgfVxuXG4gICAgaWYgKGFmZml4ID09ICdib3R0b20nKSB7XG4gICAgICB0aGlzLiRlbGVtZW50Lm9mZnNldCh7XG4gICAgICAgIHRvcDogc2Nyb2xsSGVpZ2h0IC0gaGVpZ2h0IC0gb2Zmc2V0Qm90dG9tXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG5cbiAgLy8gQUZGSVggUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICAgIHZhciBkYXRhICAgID0gJHRoaXMuZGF0YSgnYnMuYWZmaXgnKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmFmZml4JywgKGRhdGEgPSBuZXcgQWZmaXgodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmFmZml4XG5cbiAgJC5mbi5hZmZpeCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmFmZml4LkNvbnN0cnVjdG9yID0gQWZmaXhcblxuXG4gIC8vIEFGRklYIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5hZmZpeC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYWZmaXggPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBBRkZJWCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQod2luZG93KS5vbignbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAkKCdbZGF0YS1zcHk9XCJhZmZpeFwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICRzcHkgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSA9ICRzcHkuZGF0YSgpXG5cbiAgICAgIGRhdGEub2Zmc2V0ID0gZGF0YS5vZmZzZXQgfHwge31cblxuICAgICAgaWYgKGRhdGEub2Zmc2V0Qm90dG9tICE9IG51bGwpIGRhdGEub2Zmc2V0LmJvdHRvbSA9IGRhdGEub2Zmc2V0Qm90dG9tXG4gICAgICBpZiAoZGF0YS5vZmZzZXRUb3AgICAgIT0gbnVsbCkgZGF0YS5vZmZzZXQudG9wICAgID0gZGF0YS5vZmZzZXRUb3BcblxuICAgICAgUGx1Z2luLmNhbGwoJHNweSwgZGF0YSlcbiAgICB9KVxuICB9KVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvYWZmaXguanNcbi8vIG1vZHVsZSBpZCA9IDE0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxyXG4gKiBCb290c3RyYXAtc2VsZWN0IHYxLjEyLjQgKGh0dHA6Ly9zaWx2aW9tb3JldG8uZ2l0aHViLmlvL2Jvb3RzdHJhcC1zZWxlY3QpXHJcbiAqXHJcbiAqIENvcHlyaWdodCAyMDEzLTIwMTcgYm9vdHN0cmFwLXNlbGVjdFxyXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS9zaWx2aW9tb3JldG8vYm9vdHN0cmFwLXNlbGVjdC9ibG9iL21hc3Rlci9MSUNFTlNFKVxyXG4gKi9cclxuXHJcbihmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHVubGVzcyBhbWRNb2R1bGVJZCBpcyBzZXRcbiAgICBkZWZpbmUoW1wianF1ZXJ5XCJdLCBmdW5jdGlvbiAoYTApIHtcbiAgICAgIHJldHVybiAoZmFjdG9yeShhMCkpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgLy8gTm9kZS4gRG9lcyBub3Qgd29yayB3aXRoIHN0cmljdCBDb21tb25KUywgYnV0XG4gICAgLy8gb25seSBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB0aGF0IHN1cHBvcnQgbW9kdWxlLmV4cG9ydHMsXG4gICAgLy8gbGlrZSBOb2RlLlxuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwianF1ZXJ5XCIpKTtcbiAgfSBlbHNlIHtcbiAgICBmYWN0b3J5KHJvb3RbXCJqUXVlcnlcIl0pO1xuICB9XG59KHRoaXMsIGZ1bmN0aW9uIChqUXVlcnkpIHtcblxuKGZ1bmN0aW9uICgkKSB7XHJcbiAgJ3VzZSBzdHJpY3QnO1xyXG5cclxuICAvLzxlZGl0b3ItZm9sZCBkZXNjPVwiU2hpbXNcIj5cclxuICBpZiAoIVN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMpIHtcclxuICAgIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICd1c2Ugc3RyaWN0JzsgLy8gbmVlZGVkIHRvIHN1cHBvcnQgYGFwcGx5YC9gY2FsbGAgd2l0aCBgdW5kZWZpbmVkYC9gbnVsbGBcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIGluZGV4T2YgPSAnJy5pbmRleE9mO1xyXG4gICAgICB2YXIgaW5jbHVkZXMgPSBmdW5jdGlvbiAoc2VhcmNoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHRoaXMpO1xyXG4gICAgICAgIGlmIChzZWFyY2ggJiYgdG9TdHJpbmcuY2FsbChzZWFyY2gpID09ICdbb2JqZWN0IFJlZ0V4cF0nKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xyXG4gICAgICAgIHZhciBzZWFyY2hTdHJpbmcgPSBTdHJpbmcoc2VhcmNoKTtcclxuICAgICAgICB2YXIgc2VhcmNoTGVuZ3RoID0gc2VhcmNoU3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgcG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBgVG9JbnRlZ2VyYFxyXG4gICAgICAgIHZhciBwb3MgPSBwb3NpdGlvbiA/IE51bWJlcihwb3NpdGlvbikgOiAwO1xyXG4gICAgICAgIGlmIChwb3MgIT0gcG9zKSB7IC8vIGJldHRlciBgaXNOYU5gXHJcbiAgICAgICAgICBwb3MgPSAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBNYXRoLm1pbihNYXRoLm1heChwb3MsIDApLCBzdHJpbmdMZW5ndGgpO1xyXG4gICAgICAgIC8vIEF2b2lkIHRoZSBgaW5kZXhPZmAgY2FsbCBpZiBubyBtYXRjaCBpcyBwb3NzaWJsZVxyXG4gICAgICAgIGlmIChzZWFyY2hMZW5ndGggKyBzdGFydCA+IHN0cmluZ0xlbmd0aCkge1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaW5kZXhPZi5jYWxsKHN0cmluZywgc2VhcmNoU3RyaW5nLCBwb3MpICE9IC0xO1xyXG4gICAgICB9O1xyXG4gICAgICBpZiAoZGVmaW5lUHJvcGVydHkpIHtcclxuICAgICAgICBkZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAnaW5jbHVkZXMnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBpbmNsdWRlcyxcclxuICAgICAgICAgICdjb25maWd1cmFibGUnOiB0cnVlLFxyXG4gICAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIFN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMgPSBpbmNsdWRlcztcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoKSB7XHJcbiAgICAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAndXNlIHN0cmljdCc7IC8vIG5lZWRlZCB0byBzdXBwb3J0IGBhcHBseWAvYGNhbGxgIHdpdGggYHVuZGVmaW5lZGAvYG51bGxgXHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBzdGFydHNXaXRoID0gZnVuY3Rpb24gKHNlYXJjaCkge1xyXG4gICAgICAgIGlmICh0aGlzID09IG51bGwpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0cmluZyA9IFN0cmluZyh0aGlzKTtcclxuICAgICAgICBpZiAoc2VhcmNoICYmIHRvU3RyaW5nLmNhbGwoc2VhcmNoKSA9PSAnW29iamVjdCBSZWdFeHBdJykge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgc2VhcmNoU3RyaW5nID0gU3RyaW5nKHNlYXJjaCk7XHJcbiAgICAgICAgdmFyIHNlYXJjaExlbmd0aCA9IHNlYXJjaFN0cmluZy5sZW5ndGg7XHJcbiAgICAgICAgdmFyIHBvc2l0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgLy8gYFRvSW50ZWdlcmBcclxuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPyBOdW1iZXIocG9zaXRpb24pIDogMDtcclxuICAgICAgICBpZiAocG9zICE9IHBvcykgeyAvLyBiZXR0ZXIgYGlzTmFOYFxyXG4gICAgICAgICAgcG9zID0gMDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5taW4oTWF0aC5tYXgocG9zLCAwKSwgc3RyaW5nTGVuZ3RoKTtcclxuICAgICAgICAvLyBBdm9pZCB0aGUgYGluZGV4T2ZgIGNhbGwgaWYgbm8gbWF0Y2ggaXMgcG9zc2libGVcclxuICAgICAgICBpZiAoc2VhcmNoTGVuZ3RoICsgc3RhcnQgPiBzdHJpbmdMZW5ndGgpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGluZGV4ID0gLTE7XHJcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzZWFyY2hMZW5ndGgpIHtcclxuICAgICAgICAgIGlmIChzdHJpbmcuY2hhckNvZGVBdChzdGFydCArIGluZGV4KSAhPSBzZWFyY2hTdHJpbmcuY2hhckNvZGVBdChpbmRleCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfTtcclxuICAgICAgaWYgKGRlZmluZVByb3BlcnR5KSB7XHJcbiAgICAgICAgZGVmaW5lUHJvcGVydHkoU3RyaW5nLnByb3RvdHlwZSwgJ3N0YXJ0c1dpdGgnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBzdGFydHNXaXRoLFxyXG4gICAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXHJcbiAgICAgICAgICAnd3JpdGFibGUnOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghT2JqZWN0LmtleXMpIHtcclxuICAgIE9iamVjdC5rZXlzID0gZnVuY3Rpb24gKFxyXG4gICAgICBvLCAvLyBvYmplY3RcclxuICAgICAgaywgLy8ga2V5XHJcbiAgICAgIHIgIC8vIHJlc3VsdCBhcnJheVxyXG4gICAgICApe1xyXG4gICAgICAvLyBpbml0aWFsaXplIG9iamVjdCBhbmQgcmVzdWx0XHJcbiAgICAgIHI9W107XHJcbiAgICAgIC8vIGl0ZXJhdGUgb3ZlciBvYmplY3Qga2V5c1xyXG4gICAgICBmb3IgKGsgaW4gbylcclxuICAgICAgICAgIC8vIGZpbGwgcmVzdWx0IGFycmF5IHdpdGggbm9uLXByb3RvdHlwaWNhbCBrZXlzXHJcbiAgICAgICAgci5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspICYmIHIucHVzaChrKTtcclxuICAgICAgLy8gcmV0dXJuIHJlc3VsdFxyXG4gICAgICByZXR1cm4gcjtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBzZXQgZGF0YS1zZWxlY3RlZCBvbiBzZWxlY3QgZWxlbWVudCBpZiB0aGUgdmFsdWUgaGFzIGJlZW4gcHJvZ3JhbW1hdGljYWxseSBzZWxlY3RlZFxyXG4gIC8vIHByaW9yIHRvIGluaXRpYWxpemF0aW9uIG9mIGJvb3RzdHJhcC1zZWxlY3RcclxuICAvLyAqIGNvbnNpZGVyIHJlbW92aW5nIG9yIHJlcGxhY2luZyBhbiBhbHRlcm5hdGl2ZSBtZXRob2QgKlxyXG4gIHZhciB2YWxIb29rcyA9IHtcclxuICAgIHVzZURlZmF1bHQ6IGZhbHNlLFxyXG4gICAgX3NldDogJC52YWxIb29rcy5zZWxlY3Quc2V0XHJcbiAgfTtcclxuXHJcbiAgJC52YWxIb29rcy5zZWxlY3Quc2V0ID0gZnVuY3Rpb24oZWxlbSwgdmFsdWUpIHtcclxuICAgIGlmICh2YWx1ZSAmJiAhdmFsSG9va3MudXNlRGVmYXVsdCkgJChlbGVtKS5kYXRhKCdzZWxlY3RlZCcsIHRydWUpO1xyXG5cclxuICAgIHJldHVybiB2YWxIb29rcy5fc2V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgfTtcclxuXHJcbiAgdmFyIGNoYW5nZWRfYXJndW1lbnRzID0gbnVsbDtcclxuXHJcbiAgdmFyIEV2ZW50SXNTdXBwb3J0ZWQgPSAoZnVuY3Rpb24oKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBuZXcgRXZlbnQoJ2NoYW5nZScpO1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH0pKCk7XHJcblxyXG4gICQuZm4udHJpZ2dlck5hdGl2ZSA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgIHZhciBlbCA9IHRoaXNbMF0sXHJcbiAgICAgICAgZXZlbnQ7XHJcblxyXG4gICAgaWYgKGVsLmRpc3BhdGNoRXZlbnQpIHsgLy8gZm9yIG1vZGVybiBicm93c2VycyAmIElFOStcclxuICAgICAgaWYgKEV2ZW50SXNTdXBwb3J0ZWQpIHtcclxuICAgICAgICAvLyBGb3IgbW9kZXJuIGJyb3dzZXJzXHJcbiAgICAgICAgZXZlbnQgPSBuZXcgRXZlbnQoZXZlbnROYW1lLCB7XHJcbiAgICAgICAgICBidWJibGVzOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gRm9yIElFIHNpbmNlIGl0IGRvZXNuJ3Qgc3VwcG9ydCBFdmVudCBjb25zdHJ1Y3RvclxyXG4gICAgICAgIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XHJcbiAgICAgICAgZXZlbnQuaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgZmFsc2UpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBlbC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcclxuICAgIH0gZWxzZSBpZiAoZWwuZmlyZUV2ZW50KSB7IC8vIGZvciBJRThcclxuICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudE9iamVjdCgpO1xyXG4gICAgICBldmVudC5ldmVudFR5cGUgPSBldmVudE5hbWU7XHJcbiAgICAgIGVsLmZpcmVFdmVudCgnb24nICsgZXZlbnROYW1lLCBldmVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBmYWxsIGJhY2sgdG8galF1ZXJ5LnRyaWdnZXJcclxuICAgICAgdGhpcy50cmlnZ2VyKGV2ZW50TmFtZSk7XHJcbiAgICB9XHJcbiAgfTtcclxuICAvLzwvZWRpdG9yLWZvbGQ+XHJcblxyXG4gIC8vIENhc2UgaW5zZW5zaXRpdmUgY29udGFpbnMgc2VhcmNoXHJcbiAgJC5leHByLnBzZXVkb3MuaWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suaW5jbHVkZXMobWV0YVszXS50b1VwcGVyQ2FzZSgpKTtcclxuICB9O1xyXG5cclxuICAvLyBDYXNlIGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5pYmVnaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suc3RhcnRzV2l0aChtZXRhWzNdLnRvVXBwZXJDYXNlKCkpO1xyXG4gIH07XHJcblxyXG4gIC8vIENhc2UgYW5kIGFjY2VudCBpbnNlbnNpdGl2ZSBjb250YWlucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmouZGF0YSgnbm9ybWFsaXplZFRleHQnKSB8fCAkb2JqLnRleHQoKSkudG9TdHJpbmcoKS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgcmV0dXJuIGhheXN0YWNrLmluY2x1ZGVzKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ2FzZSBhbmQgYWNjZW50IGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWJlZ2lucyA9IGZ1bmN0aW9uIChvYmosIGluZGV4LCBtZXRhKSB7XHJcbiAgICB2YXIgJG9iaiA9ICQob2JqKS5maW5kKCdhJyk7XHJcbiAgICB2YXIgaGF5c3RhY2sgPSAoJG9iai5kYXRhKCd0b2tlbnMnKSB8fCAkb2JqLmRhdGEoJ25vcm1hbGl6ZWRUZXh0JykgfHwgJG9iai50ZXh0KCkpLnRvU3RyaW5nKCkudG9VcHBlckNhc2UoKTtcclxuICAgIHJldHVybiBoYXlzdGFjay5zdGFydHNXaXRoKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFsbCBkaWF0cmljcyBmcm9tIHRoZSBnaXZlbiB0ZXh0LlxyXG4gICAqIEBhY2Nlc3MgcHJpdmF0ZVxyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0XHJcbiAgICogQHJldHVybnMge1N0cmluZ31cclxuICAgKi9cclxuICBmdW5jdGlvbiBub3JtYWxpemVUb0Jhc2UodGV4dCkge1xyXG4gICAgdmFyIHJFeHBzID0gW1xyXG4gICAgICB7cmU6IC9bXFx4QzAtXFx4QzZdL2csIGNoOiBcIkFcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhFMC1cXHhFNl0vZywgY2g6IFwiYVwifSxcclxuICAgICAge3JlOiAvW1xceEM4LVxceENCXS9nLCBjaDogXCJFXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RTgtXFx4RUJdL2csIGNoOiBcImVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDQy1cXHhDRl0vZywgY2g6IFwiSVwifSxcclxuICAgICAge3JlOiAvW1xceEVDLVxceEVGXS9nLCBjaDogXCJpXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RDItXFx4RDZdL2csIGNoOiBcIk9cIn0sXHJcbiAgICAgIHtyZTogL1tcXHhGMi1cXHhGNl0vZywgY2g6IFwib1wifSxcclxuICAgICAge3JlOiAvW1xceEQ5LVxceERDXS9nLCBjaDogXCJVXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjktXFx4RkNdL2csIGNoOiBcInVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDNy1cXHhFN10vZywgY2g6IFwiY1wifSxcclxuICAgICAge3JlOiAvW1xceEQxXS9nLCBjaDogXCJOXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjFdL2csIGNoOiBcIm5cIn1cclxuICAgIF07XHJcbiAgICAkLmVhY2gockV4cHMsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGV4dCA9IHRleHQgPyB0ZXh0LnJlcGxhY2UodGhpcy5yZSwgdGhpcy5jaCkgOiAnJztcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHRleHQ7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gTGlzdCBvZiBIVE1MIGVudGl0aWVzIGZvciBlc2NhcGluZy5cclxuICB2YXIgZXNjYXBlTWFwID0ge1xyXG4gICAgJyYnOiAnJmFtcDsnLFxyXG4gICAgJzwnOiAnJmx0OycsXHJcbiAgICAnPic6ICcmZ3Q7JyxcclxuICAgICdcIic6ICcmcXVvdDsnLFxyXG4gICAgXCInXCI6ICcmI3gyNzsnLFxyXG4gICAgJ2AnOiAnJiN4NjA7J1xyXG4gIH07XHJcbiAgXHJcbiAgdmFyIHVuZXNjYXBlTWFwID0ge1xyXG4gICAgJyZhbXA7JzogJyYnLFxyXG4gICAgJyZsdDsnOiAnPCcsXHJcbiAgICAnJmd0Oyc6ICc+JyxcclxuICAgICcmcXVvdDsnOiAnXCInLFxyXG4gICAgJyYjeDI3Oyc6IFwiJ1wiLFxyXG4gICAgJyYjeDYwOyc6ICdgJ1xyXG4gIH07XHJcblxyXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cclxuICB2YXIgY3JlYXRlRXNjYXBlciA9IGZ1bmN0aW9uKG1hcCkge1xyXG4gICAgdmFyIGVzY2FwZXIgPSBmdW5jdGlvbihtYXRjaCkge1xyXG4gICAgICByZXR1cm4gbWFwW21hdGNoXTtcclxuICAgIH07XHJcbiAgICAvLyBSZWdleGVzIGZvciBpZGVudGlmeWluZyBhIGtleSB0aGF0IG5lZWRzIHRvIGJlIGVzY2FwZWQuXHJcbiAgICB2YXIgc291cmNlID0gJyg/OicgKyBPYmplY3Qua2V5cyhtYXApLmpvaW4oJ3wnKSArICcpJztcclxuICAgIHZhciB0ZXN0UmVnZXhwID0gUmVnRXhwKHNvdXJjZSk7XHJcbiAgICB2YXIgcmVwbGFjZVJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UsICdnJyk7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XHJcbiAgICAgIHN0cmluZyA9IHN0cmluZyA9PSBudWxsID8gJycgOiAnJyArIHN0cmluZztcclxuICAgICAgcmV0dXJuIHRlc3RSZWdleHAudGVzdChzdHJpbmcpID8gc3RyaW5nLnJlcGxhY2UocmVwbGFjZVJlZ2V4cCwgZXNjYXBlcikgOiBzdHJpbmc7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIHZhciBodG1sRXNjYXBlID0gY3JlYXRlRXNjYXBlcihlc2NhcGVNYXApO1xyXG4gIHZhciBodG1sVW5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKHVuZXNjYXBlTWFwKTtcclxuXHJcbiAgdmFyIFNlbGVjdHBpY2tlciA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XHJcbiAgICAvLyBib290c3RyYXAtc2VsZWN0IGhhcyBiZWVuIGluaXRpYWxpemVkIC0gcmV2ZXJ0IHZhbEhvb2tzLnNlbGVjdC5zZXQgYmFjayB0byBpdHMgb3JpZ2luYWwgZnVuY3Rpb25cclxuICAgIGlmICghdmFsSG9va3MudXNlRGVmYXVsdCkge1xyXG4gICAgICAkLnZhbEhvb2tzLnNlbGVjdC5zZXQgPSB2YWxIb29rcy5fc2V0O1xyXG4gICAgICB2YWxIb29rcy51c2VEZWZhdWx0ID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLiRlbGVtZW50ID0gJChlbGVtZW50KTtcclxuICAgIHRoaXMuJG5ld0VsZW1lbnQgPSBudWxsO1xyXG4gICAgdGhpcy4kYnV0dG9uID0gbnVsbDtcclxuICAgIHRoaXMuJG1lbnUgPSBudWxsO1xyXG4gICAgdGhpcy4kbGlzID0gbnVsbDtcclxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XHJcblxyXG4gICAgLy8gSWYgd2UgaGF2ZSBubyB0aXRsZSB5ZXQsIHRyeSB0byBwdWxsIGl0IGZyb20gdGhlIGh0bWwgdGl0bGUgYXR0cmlidXRlIChqUXVlcnkgZG9lc250JyBwaWNrIGl0IHVwIGFzIGl0J3Mgbm90IGFcclxuICAgIC8vIGRhdGEtYXR0cmlidXRlKVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PT0gbnVsbCkge1xyXG4gICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9ybWF0IHdpbmRvdyBwYWRkaW5nXHJcbiAgICB2YXIgd2luUGFkID0gdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmc7XHJcbiAgICBpZiAodHlwZW9mIHdpblBhZCA9PT0gJ251bWJlcicpIHtcclxuICAgICAgdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmcgPSBbd2luUGFkLCB3aW5QYWQsIHdpblBhZCwgd2luUGFkXTtcclxuICAgIH1cclxuXHJcbiAgICAvL0V4cG9zZSBwdWJsaWMgbWV0aG9kc1xyXG4gICAgdGhpcy52YWwgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnZhbDtcclxuICAgIHRoaXMucmVuZGVyID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW5kZXI7XHJcbiAgICB0aGlzLnJlZnJlc2ggPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnJlZnJlc2g7XHJcbiAgICB0aGlzLnNldFN0eWxlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZXRTdHlsZTtcclxuICAgIHRoaXMuc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZWxlY3RBbGw7XHJcbiAgICB0aGlzLmRlc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5kZXNlbGVjdEFsbDtcclxuICAgIHRoaXMuZGVzdHJveSA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUuZGVzdHJveTtcclxuICAgIHRoaXMucmVtb3ZlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW1vdmU7XHJcbiAgICB0aGlzLnNob3cgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnNob3c7XHJcbiAgICB0aGlzLmhpZGUgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLmhpZGU7XHJcblxyXG4gICAgdGhpcy5pbml0KCk7XHJcbiAgfTtcclxuXHJcbiAgU2VsZWN0cGlja2VyLlZFUlNJT04gPSAnMS4xMi40JztcclxuXHJcbiAgLy8gcGFydCBvZiB0aGlzIGlzIGR1cGxpY2F0ZWQgaW4gaTE4bi9kZWZhdWx0cy1lbl9VUy5qcy4gTWFrZSBzdXJlIHRvIHVwZGF0ZSBib3RoLlxyXG4gIFNlbGVjdHBpY2tlci5ERUZBVUxUUyA9IHtcclxuICAgIG5vbmVTZWxlY3RlZFRleHQ6ICdOb3RoaW5nIHNlbGVjdGVkJyxcclxuICAgIG5vbmVSZXN1bHRzVGV4dDogJ05vIHJlc3VsdHMgbWF0Y2hlZCB7MH0nLFxyXG4gICAgY291bnRTZWxlY3RlZFRleHQ6IGZ1bmN0aW9uIChudW1TZWxlY3RlZCwgbnVtVG90YWwpIHtcclxuICAgICAgcmV0dXJuIChudW1TZWxlY3RlZCA9PSAxKSA/IFwiezB9IGl0ZW0gc2VsZWN0ZWRcIiA6IFwiezB9IGl0ZW1zIHNlbGVjdGVkXCI7XHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uc1RleHQ6IGZ1bmN0aW9uIChudW1BbGwsIG51bUdyb3VwKSB7XHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgKG51bUFsbCA9PSAxKSA/ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbSBtYXgpJyA6ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbXMgbWF4KScsXHJcbiAgICAgICAgKG51bUdyb3VwID09IDEpID8gJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtIG1heCknIDogJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtcyBtYXgpJ1xyXG4gICAgICBdO1xyXG4gICAgfSxcclxuICAgIHNlbGVjdEFsbFRleHQ6ICdTZWxlY3QgQWxsJyxcclxuICAgIGRlc2VsZWN0QWxsVGV4dDogJ0Rlc2VsZWN0IEFsbCcsXHJcbiAgICBkb25lQnV0dG9uOiBmYWxzZSxcclxuICAgIGRvbmVCdXR0b25UZXh0OiAnQ2xvc2UnLFxyXG4gICAgbXVsdGlwbGVTZXBhcmF0b3I6ICcsICcsXHJcbiAgICBzdHlsZUJhc2U6ICdidG4nLFxyXG4gICAgc3R5bGU6ICdidG4tZGVmYXVsdCcsXHJcbiAgICBzaXplOiAnYXV0bycsXHJcbiAgICB0aXRsZTogbnVsbCxcclxuICAgIHNlbGVjdGVkVGV4dEZvcm1hdDogJ3ZhbHVlcycsXHJcbiAgICB3aWR0aDogZmFsc2UsXHJcbiAgICBjb250YWluZXI6IGZhbHNlLFxyXG4gICAgaGlkZURpc2FibGVkOiBmYWxzZSxcclxuICAgIHNob3dTdWJ0ZXh0OiBmYWxzZSxcclxuICAgIHNob3dJY29uOiB0cnVlLFxyXG4gICAgc2hvd0NvbnRlbnQ6IHRydWUsXHJcbiAgICBkcm9wdXBBdXRvOiB0cnVlLFxyXG4gICAgaGVhZGVyOiBmYWxzZSxcclxuICAgIGxpdmVTZWFyY2g6IGZhbHNlLFxyXG4gICAgbGl2ZVNlYXJjaFBsYWNlaG9sZGVyOiBudWxsLFxyXG4gICAgbGl2ZVNlYXJjaE5vcm1hbGl6ZTogZmFsc2UsXHJcbiAgICBsaXZlU2VhcmNoU3R5bGU6ICdjb250YWlucycsXHJcbiAgICBhY3Rpb25zQm94OiBmYWxzZSxcclxuICAgIGljb25CYXNlOiAnZ2x5cGhpY29uJyxcclxuICAgIHRpY2tJY29uOiAnZ2x5cGhpY29uLW9rJyxcclxuICAgIHNob3dUaWNrOiBmYWxzZSxcclxuICAgIHRlbXBsYXRlOiB7XHJcbiAgICAgIGNhcmV0OiAnPHNwYW4gY2xhc3M9XCJjYXJldFwiPjwvc3Bhbj4nXHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uczogZmFsc2UsXHJcbiAgICBtb2JpbGU6IGZhbHNlLFxyXG4gICAgc2VsZWN0T25UYWI6IGZhbHNlLFxyXG4gICAgZHJvcGRvd25BbGlnblJpZ2h0OiBmYWxzZSxcclxuICAgIHdpbmRvd1BhZGRpbmc6IDBcclxuICB9O1xyXG5cclxuICBTZWxlY3RwaWNrZXIucHJvdG90eXBlID0ge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yOiBTZWxlY3RwaWNrZXIsXHJcblxyXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICBpZCA9IHRoaXMuJGVsZW1lbnQuYXR0cignaWQnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4nKTtcclxuXHJcbiAgICAgIC8vIHN0b3JlIG9yaWdpbmFsSW5kZXggKGtleSkgYW5kIG5ld0luZGV4ICh2YWx1ZSkgaW4gdGhpcy5saU9iaiBmb3IgZmFzdCBhY2Nlc3NpYmlsaXR5XHJcbiAgICAgIC8vIGFsbG93cyB1cyB0byBkbyB0aGlzLiRsaXMuZXEodGhhdC5saU9ialtpbmRleF0pIGluc3RlYWQgb2YgdGhpcy4kbGlzLmZpbHRlcignW2RhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCJdJylcclxuICAgICAgdGhpcy5saU9iaiA9IHt9O1xyXG4gICAgICB0aGlzLm11bHRpcGxlID0gdGhpcy4kZWxlbWVudC5wcm9wKCdtdWx0aXBsZScpO1xyXG4gICAgICB0aGlzLmF1dG9mb2N1cyA9IHRoaXMuJGVsZW1lbnQucHJvcCgnYXV0b2ZvY3VzJyk7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpZXcoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudFxyXG4gICAgICAgIC5hZnRlcih0aGlzLiRuZXdFbGVtZW50KVxyXG4gICAgICAgIC5hcHBlbmRUbyh0aGlzLiRuZXdFbGVtZW50KTtcclxuICAgICAgdGhpcy4kYnV0dG9uID0gdGhpcy4kbmV3RWxlbWVudC5jaGlsZHJlbignYnV0dG9uJyk7XHJcbiAgICAgIHRoaXMuJG1lbnUgPSB0aGlzLiRuZXdFbGVtZW50LmNoaWxkcmVuKCcuZHJvcGRvd24tbWVudScpO1xyXG4gICAgICB0aGlzLiRtZW51SW5uZXIgPSB0aGlzLiRtZW51LmNoaWxkcmVuKCcuaW5uZXInKTtcclxuICAgICAgdGhpcy4kc2VhcmNoYm94ID0gdGhpcy4kbWVudS5maW5kKCdpbnB1dCcpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmVDbGFzcygnYnMtc2VsZWN0LWhpZGRlbicpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09IHRydWUpIHRoaXMuJG1lbnUuYWRkQ2xhc3MoJ2Ryb3Bkb3duLW1lbnUtcmlnaHQnKTtcclxuXHJcbiAgICAgIGlmICh0eXBlb2YgaWQgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ2RhdGEtaWQnLCBpZCk7XHJcbiAgICAgICAgJCgnbGFiZWxbZm9yPVwiJyArIGlkICsgJ1wiXScpLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMuY2xpY2tMaXN0ZW5lcigpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmxpdmVTZWFyY2gpIHRoaXMubGl2ZVNlYXJjaExpc3RlbmVyKCk7XHJcbiAgICAgIHRoaXMucmVuZGVyKCk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmNvbnRhaW5lcikgdGhpcy5zZWxlY3RQb3NpdGlvbigpO1xyXG4gICAgICB0aGlzLiRtZW51LmRhdGEoJ3RoaXMnLCB0aGlzKTtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5kYXRhKCd0aGlzJywgdGhpcyk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMubW9iaWxlKSB0aGlzLm1vYmlsZSgpO1xyXG5cclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5vbih7XHJcbiAgICAgICAgJ2hpZGUuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2hpZGUuYnMuc2VsZWN0JywgZSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAnaGlkZGVuLmJzLmRyb3Bkb3duJzogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignaGlkZGVuLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgJ3Nob3cuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKTtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignc2hvdy5icy5zZWxlY3QnLCBlKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgICdzaG93bi5icy5kcm9wZG93bic6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ3Nob3duLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAodGhhdC4kZWxlbWVudFswXS5oYXNBdHRyaWJ1dGUoJ3JlcXVpcmVkJykpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50Lm9uKCdpbnZhbGlkJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLmFkZENsYXNzKCdicy1pbnZhbGlkJyk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kZWxlbWVudC5vbih7XHJcbiAgICAgICAgICAgICdmb2N1cy5icy5zZWxlY3QnOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC5vZmYoJ2ZvY3VzLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAnc2hvd24uYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnRcclxuICAgICAgICAgICAgICAgIC52YWwodGhhdC4kZWxlbWVudC52YWwoKSkgLy8gc2V0IHRoZSB2YWx1ZSB0byBoaWRlIHRoZSB2YWxpZGF0aW9uIG1lc3NhZ2UgaW4gQ2hyb21lIHdoZW4gbWVudSBpcyBvcGVuZWRcclxuICAgICAgICAgICAgICAgIC5vZmYoJ3Nob3duLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAncmVuZGVyZWQuYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIC8vIGlmIHNlbGVjdCBpcyBubyBsb25nZXIgaW52YWxpZCwgcmVtb3ZlIHRoZSBicy1pbnZhbGlkIGNsYXNzXHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMudmFsaWRpdHkudmFsaWQpIHRoYXQuJGJ1dHRvbi5yZW1vdmVDbGFzcygnYnMtaW52YWxpZCcpO1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQub2ZmKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLm9uKCdibHVyLmJzLnNlbGVjdCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB0aGF0LiRlbGVtZW50LmZvY3VzKCkuYmx1cigpO1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24ub2ZmKCdibHVyLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbG9hZGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlRHJvcGRvd246IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gT3B0aW9uc1xyXG4gICAgICAvLyBJZiB3ZSBhcmUgbXVsdGlwbGUgb3Igc2hvd1RpY2sgb3B0aW9uIGlzIHNldCwgdGhlbiBhZGQgdGhlIHNob3ctdGljayBjbGFzc1xyXG4gICAgICB2YXIgc2hvd1RpY2sgPSAodGhpcy5tdWx0aXBsZSB8fCB0aGlzLm9wdGlvbnMuc2hvd1RpY2spID8gJyBzaG93LXRpY2snIDogJycsXHJcbiAgICAgICAgICBpbnB1dEdyb3VwID0gdGhpcy4kZWxlbWVudC5wYXJlbnQoKS5oYXNDbGFzcygnaW5wdXQtZ3JvdXAnKSA/ICcgaW5wdXQtZ3JvdXAtYnRuJyA6ICcnLFxyXG4gICAgICAgICAgYXV0b2ZvY3VzID0gdGhpcy5hdXRvZm9jdXMgPyAnIGF1dG9mb2N1cycgOiAnJztcclxuICAgICAgLy8gRWxlbWVudHNcclxuICAgICAgdmFyIGhlYWRlciA9IHRoaXMub3B0aW9ucy5oZWFkZXIgPyAnPGRpdiBjbGFzcz1cInBvcG92ZXItdGl0bGVcIj48YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNsb3NlXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvYnV0dG9uPicgKyB0aGlzLm9wdGlvbnMuaGVhZGVyICsgJzwvZGl2PicgOiAnJztcclxuICAgICAgdmFyIHNlYXJjaGJveCA9IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoID9cclxuICAgICAgJzxkaXYgY2xhc3M9XCJicy1zZWFyY2hib3hcIj4nICtcclxuICAgICAgJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCInICtcclxuICAgICAgKG51bGwgPT09IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoUGxhY2Vob2xkZXIgPyAnJyA6ICcgcGxhY2Vob2xkZXI9XCInICsgaHRtbEVzY2FwZSh0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaFBsYWNlaG9sZGVyKSArICdcIicpICsgJyByb2xlPVwidGV4dGJveFwiIGFyaWEtbGFiZWw9XCJTZWFyY2hcIj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBhY3Rpb25zYm94ID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuYWN0aW9uc0JveCA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtYWN0aW9uc2JveFwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tZ3JvdXAtc20gYnRuLWJsb2NrXCI+JyArXHJcbiAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImFjdGlvbnMtYnRuIGJzLXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5zZWxlY3RBbGxUZXh0ICtcclxuICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJhY3Rpb25zLWJ0biBicy1kZXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5kZXNlbGVjdEFsbFRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkb25lYnV0dG9uID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvbiA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtZG9uZWJ1dHRvblwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tYmxvY2tcIj4nICtcclxuICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tZGVmYXVsdFwiPicgK1xyXG4gICAgICB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvblRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkcm9wID1cclxuICAgICAgICAgICc8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIGJvb3RzdHJhcC1zZWxlY3QnICsgc2hvd1RpY2sgKyBpbnB1dEdyb3VwICsgJ1wiPicgK1xyXG4gICAgICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiJyArIHRoaXMub3B0aW9ucy5zdHlsZUJhc2UgKyAnIGRyb3Bkb3duLXRvZ2dsZVwiIGRhdGEtdG9nZ2xlPVwiZHJvcGRvd25cIicgKyBhdXRvZm9jdXMgKyAnIHJvbGU9XCJidXR0b25cIj4nICtcclxuICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZpbHRlci1vcHRpb24gcHVsbC1sZWZ0XCI+PC9zcGFuPiZuYnNwOycgK1xyXG4gICAgICAgICAgJzxzcGFuIGNsYXNzPVwiYnMtY2FyZXRcIj4nICtcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy50ZW1wbGF0ZS5jYXJldCArXHJcbiAgICAgICAgICAnPC9zcGFuPicgK1xyXG4gICAgICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAgICAgJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51IG9wZW5cIiByb2xlPVwiY29tYm9ib3hcIj4nICtcclxuICAgICAgICAgIGhlYWRlciArXHJcbiAgICAgICAgICBzZWFyY2hib3ggK1xyXG4gICAgICAgICAgYWN0aW9uc2JveCArXHJcbiAgICAgICAgICAnPHVsIGNsYXNzPVwiZHJvcGRvd24tbWVudSBpbm5lclwiIHJvbGU9XCJsaXN0Ym94XCIgYXJpYS1leHBhbmRlZD1cImZhbHNlXCI+JyArXHJcbiAgICAgICAgICAnPC91bD4nICtcclxuICAgICAgICAgIGRvbmVidXR0b24gK1xyXG4gICAgICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAgICAgJzwvZGl2Pic7XHJcblxyXG4gICAgICByZXR1cm4gJChkcm9wKTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlVmlldzogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgJGRyb3AgPSB0aGlzLmNyZWF0ZURyb3Bkb3duKCksXHJcbiAgICAgICAgICBsaSA9IHRoaXMuY3JlYXRlTGkoKTtcclxuXHJcbiAgICAgICRkcm9wLmZpbmQoJ3VsJylbMF0uaW5uZXJIVE1MID0gbGk7XHJcbiAgICAgIHJldHVybiAkZHJvcDtcclxuICAgIH0sXHJcblxyXG4gICAgcmVsb2FkTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gcmVidWlsZFxyXG4gICAgICB2YXIgbGkgPSB0aGlzLmNyZWF0ZUxpKCk7XHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lclswXS5pbm5lckhUTUwgPSBsaTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgX2xpID0gW10sXHJcbiAgICAgICAgICBvcHRJRCA9IDAsXHJcbiAgICAgICAgICB0aXRsZU9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgbGlJbmRleCA9IC0xOyAvLyBpbmNyZW1lbnQgbGlJbmRleCB3aGVuZXZlciBhIG5ldyA8bGk+IGVsZW1lbnQgaXMgY3JlYXRlZCB0byBlbnN1cmUgbGlPYmogaXMgY29ycmVjdFxyXG5cclxuICAgICAgLy8gSGVscGVyIGZ1bmN0aW9uc1xyXG4gICAgICAvKipcclxuICAgICAgICogQHBhcmFtIGNvbnRlbnRcclxuICAgICAgICogQHBhcmFtIFtpbmRleF1cclxuICAgICAgICogQHBhcmFtIFtjbGFzc2VzXVxyXG4gICAgICAgKiBAcGFyYW0gW29wdGdyb3VwXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlTEkgPSBmdW5jdGlvbiAoY29udGVudCwgaW5kZXgsIGNsYXNzZXMsIG9wdGdyb3VwKSB7XHJcbiAgICAgICAgcmV0dXJuICc8bGknICtcclxuICAgICAgICAgICAgKCh0eXBlb2YgY2xhc3NlcyAhPT0gJ3VuZGVmaW5lZCcgJiYgJycgIT09IGNsYXNzZXMpID8gJyBjbGFzcz1cIicgKyBjbGFzc2VzICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICgodHlwZW9mIGluZGV4ICE9PSAndW5kZWZpbmVkJyAmJiBudWxsICE9PSBpbmRleCkgPyAnIGRhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKCh0eXBlb2Ygb3B0Z3JvdXAgIT09ICd1bmRlZmluZWQnICYmIG51bGwgIT09IG9wdGdyb3VwKSA/ICdkYXRhLW9wdGdyb3VwPVwiJyArIG9wdGdyb3VwICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICc+JyArIGNvbnRlbnQgKyAnPC9saT4nO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgLyoqXHJcbiAgICAgICAqIEBwYXJhbSB0ZXh0XHJcbiAgICAgICAqIEBwYXJhbSBbY2xhc3Nlc11cclxuICAgICAgICogQHBhcmFtIFtpbmxpbmVdXHJcbiAgICAgICAqIEBwYXJhbSBbdG9rZW5zXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlQSA9IGZ1bmN0aW9uICh0ZXh0LCBjbGFzc2VzLCBpbmxpbmUsIHRva2Vucykge1xyXG4gICAgICAgIHJldHVybiAnPGEgdGFiaW5kZXg9XCIwXCInICtcclxuICAgICAgICAgICAgKHR5cGVvZiBjbGFzc2VzICE9PSAndW5kZWZpbmVkJyA/ICcgY2xhc3M9XCInICsgY2xhc3NlcyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAoaW5saW5lID8gJyBzdHlsZT1cIicgKyBpbmxpbmUgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplID8gJyBkYXRhLW5vcm1hbGl6ZWQtdGV4dD1cIicgKyBub3JtYWxpemVUb0Jhc2UoaHRtbEVzY2FwZSgkKHRleHQpLmh0bWwoKSkpICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICh0eXBlb2YgdG9rZW5zICE9PSAndW5kZWZpbmVkJyB8fCB0b2tlbnMgIT09IG51bGwgPyAnIGRhdGEtdG9rZW5zPVwiJyArIHRva2VucyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAnIHJvbGU9XCJvcHRpb25cIj4nICsgdGV4dCArXHJcbiAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyB0aGF0Lm9wdGlvbnMudGlja0ljb24gKyAnIGNoZWNrLW1hcmtcIj48L3NwYW4+JyArXHJcbiAgICAgICAgICAgICc8L2E+JztcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMudGl0bGUgJiYgIXRoaXMubXVsdGlwbGUpIHtcclxuICAgICAgICAvLyB0aGlzIG9wdGlvbiBkb2Vzbid0IGNyZWF0ZSBhIG5ldyA8bGk+IGVsZW1lbnQsIGJ1dCBkb2VzIGFkZCBhIG5ldyBvcHRpb24sIHNvIGxpSW5kZXggaXMgZGVjcmVhc2VkXHJcbiAgICAgICAgLy8gc2luY2UgbGlPYmogaXMgcmVjYWxjdWxhdGVkIG9uIGV2ZXJ5IHJlZnJlc2gsIGxpSW5kZXggbmVlZHMgdG8gYmUgZGVjcmVhc2VkIGV2ZW4gaWYgdGhlIHRpdGxlT3B0aW9uIGlzIGFscmVhZHkgYXBwZW5kZWRcclxuICAgICAgICBsaUluZGV4LS07XHJcblxyXG4gICAgICAgIGlmICghdGhpcy4kZWxlbWVudC5maW5kKCcuYnMtdGl0bGUtb3B0aW9uJykubGVuZ3RoKSB7XHJcbiAgICAgICAgICAvLyBVc2UgbmF0aXZlIEpTIHRvIHByZXBlbmQgb3B0aW9uIChmYXN0ZXIpXHJcbiAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuJGVsZW1lbnRbMF07XHJcbiAgICAgICAgICB0aXRsZU9wdGlvbi5jbGFzc05hbWUgPSAnYnMtdGl0bGUtb3B0aW9uJztcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLmlubmVySFRNTCA9IHRoaXMub3B0aW9ucy50aXRsZTtcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLnZhbHVlID0gJyc7XHJcbiAgICAgICAgICBlbGVtZW50Lmluc2VydEJlZm9yZSh0aXRsZU9wdGlvbiwgZWxlbWVudC5maXJzdENoaWxkKTtcclxuICAgICAgICAgIC8vIENoZWNrIGlmIHNlbGVjdGVkIG9yIGRhdGEtc2VsZWN0ZWQgYXR0cmlidXRlIGlzIGFscmVhZHkgc2V0IG9uIGFuIG9wdGlvbi4gSWYgbm90LCBzZWxlY3QgdGhlIHRpdGxlT3B0aW9uIG9wdGlvbi5cclxuICAgICAgICAgIC8vIHRoZSBzZWxlY3RlZCBpdGVtIG1heSBoYXZlIGJlZW4gY2hhbmdlZCBieSB1c2VyIG9yIHByb2dyYW1tYXRpY2FsbHkgYmVmb3JlIHRoZSBib290c3RyYXAgc2VsZWN0IHBsdWdpbiBydW5zLFxyXG4gICAgICAgICAgLy8gaWYgc28sIHRoZSBzZWxlY3Qgd2lsbCBoYXZlIHRoZSBkYXRhLXNlbGVjdGVkIGF0dHJpYnV0ZVxyXG4gICAgICAgICAgdmFyICRvcHQgPSAkKGVsZW1lbnQub3B0aW9uc1tlbGVtZW50LnNlbGVjdGVkSW5kZXhdKTtcclxuICAgICAgICAgIGlmICgkb3B0LmF0dHIoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCAmJiB0aGlzLiRlbGVtZW50LmRhdGEoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aXRsZU9wdGlvbi5zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgJHNlbGVjdE9wdGlvbnMuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBsaUluZGV4Kys7XHJcblxyXG4gICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygnYnMtdGl0bGUtb3B0aW9uJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gR2V0IHRoZSBjbGFzcyBhbmQgdGV4dCBmb3IgdGhlIG9wdGlvblxyXG4gICAgICAgIHZhciBvcHRpb25DbGFzcyA9IHRoaXMuY2xhc3NOYW1lIHx8ICcnLFxyXG4gICAgICAgICAgICBpbmxpbmUgPSBodG1sRXNjYXBlKHRoaXMuc3R5bGUuY3NzVGV4dCksXHJcbiAgICAgICAgICAgIHRleHQgPSAkdGhpcy5kYXRhKCdjb250ZW50JykgPyAkdGhpcy5kYXRhKCdjb250ZW50JykgOiAkdGhpcy5odG1sKCksXHJcbiAgICAgICAgICAgIHRva2VucyA9ICR0aGlzLmRhdGEoJ3Rva2VucycpID8gJHRoaXMuZGF0YSgndG9rZW5zJykgOiBudWxsLFxyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gdHlwZW9mICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkdGhpcy5kYXRhKCdzdWJ0ZXh0JykgKyAnPC9zbWFsbD4nIDogJycsXHJcbiAgICAgICAgICAgIGljb24gPSB0eXBlb2YgJHRoaXMuZGF0YSgnaWNvbicpICE9PSAndW5kZWZpbmVkJyA/ICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9zcGFuPiAnIDogJycsXHJcbiAgICAgICAgICAgICRwYXJlbnQgPSAkdGhpcy5wYXJlbnQoKSxcclxuICAgICAgICAgICAgaXNPcHRncm91cCA9ICRwYXJlbnRbMF0udGFnTmFtZSA9PT0gJ09QVEdST1VQJyxcclxuICAgICAgICAgICAgaXNPcHRncm91cERpc2FibGVkID0gaXNPcHRncm91cCAmJiAkcGFyZW50WzBdLmRpc2FibGVkLFxyXG4gICAgICAgICAgICBpc0Rpc2FibGVkID0gdGhpcy5kaXNhYmxlZCB8fCBpc09wdGdyb3VwRGlzYWJsZWQsXHJcbiAgICAgICAgICAgIHByZXZIaWRkZW5JbmRleDtcclxuXHJcbiAgICAgICAgaWYgKGljb24gIT09ICcnICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgIGljb24gPSAnPHNwYW4+JyArIGljb24gKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAoaXNEaXNhYmxlZCAmJiAhaXNPcHRncm91cCB8fCBpc09wdGdyb3VwRGlzYWJsZWQpKSB7XHJcbiAgICAgICAgICAvLyBzZXQgcHJldkhpZGRlbkluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBoaWRkZW4gb3B0aW9uIGluIGEgZ3JvdXAgb2YgaGlkZGVuIG9wdGlvbnNcclxuICAgICAgICAgIC8vIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IGEgZGl2aWRlciBzaG91bGQgYmUgcGxhY2VkIGFmdGVyIGFuIG9wdGdyb3VwIGlmIHRoZXJlIGFyZVxyXG4gICAgICAgICAgLy8gaGlkZGVuIG9wdGlvbnMgYmV0d2VlbiB0aGUgb3B0Z3JvdXAgYW5kIHRoZSBmaXJzdCB2aXNpYmxlIG9wdGlvblxyXG4gICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcbiAgICAgICAgICAkdGhpcy5uZXh0KCkuZGF0YSgncHJldkhpZGRlbkluZGV4JywgKHByZXZIaWRkZW5JbmRleCAhPT0gdW5kZWZpbmVkID8gcHJldkhpZGRlbkluZGV4IDogaW5kZXgpKTtcclxuXHJcbiAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoISR0aGlzLmRhdGEoJ2NvbnRlbnQnKSkge1xyXG4gICAgICAgICAgLy8gUHJlcGVuZCBhbnkgaWNvbiBhbmQgYXBwZW5kIGFueSBzdWJ0ZXh0IHRvIHRoZSBtYWluIHRleHQuXHJcbiAgICAgICAgICB0ZXh0ID0gaWNvbiArICc8c3BhbiBjbGFzcz1cInRleHRcIj4nICsgdGV4dCArIHN1YnRleHQgKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaXNPcHRncm91cCAmJiAkdGhpcy5kYXRhKCdkaXZpZGVyJykgIT09IHRydWUpIHtcclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuaGlkZURpc2FibGVkICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgaWYgKCRwYXJlbnQuZGF0YSgnYWxsT3B0aW9uc0Rpc2FibGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIHZhciAkb3B0aW9ucyA9ICRwYXJlbnQuY2hpbGRyZW4oKTtcclxuICAgICAgICAgICAgICAkcGFyZW50LmRhdGEoJ2FsbE9wdGlvbnNEaXNhYmxlZCcsICRvcHRpb25zLmZpbHRlcignOmRpc2FibGVkJykubGVuZ3RoID09PSAkb3B0aW9ucy5sZW5ndGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5kYXRhKCdhbGxPcHRpb25zRGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgICAgIGxpSW5kZXgtLTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB2YXIgb3B0R3JvdXBDbGFzcyA9ICcgJyArICRwYXJlbnRbMF0uY2xhc3NOYW1lIHx8ICcnO1xyXG5cclxuICAgICAgICAgIGlmICgkdGhpcy5pbmRleCgpID09PSAwKSB7IC8vIElzIGl0IHRoZSBmaXJzdCBvcHRpb24gb2YgdGhlIG9wdGdyb3VwP1xyXG4gICAgICAgICAgICBvcHRJRCArPSAxO1xyXG5cclxuICAgICAgICAgICAgLy8gR2V0IHRoZSBvcHQgZ3JvdXAgbGFiZWxcclxuICAgICAgICAgICAgdmFyIGxhYmVsID0gJHBhcmVudFswXS5sYWJlbCxcclxuICAgICAgICAgICAgICAgIGxhYmVsU3VidGV4dCA9IHR5cGVvZiAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPicgOiAnJyxcclxuICAgICAgICAgICAgICAgIGxhYmVsSWNvbiA9ICRwYXJlbnQuZGF0YSgnaWNvbicpID8gJzxzcGFuIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArICRwYXJlbnQuZGF0YSgnaWNvbicpICsgJ1wiPjwvc3Bhbj4gJyA6ICcnO1xyXG5cclxuICAgICAgICAgICAgbGFiZWwgPSBsYWJlbEljb24gKyAnPHNwYW4gY2xhc3M9XCJ0ZXh0XCI+JyArIGh0bWxFc2NhcGUobGFiZWwpICsgbGFiZWxTdWJ0ZXh0ICsgJzwvc3Bhbj4nO1xyXG5cclxuICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAwICYmIF9saS5sZW5ndGggPiAwKSB7IC8vIElzIGl0IE5PVCB0aGUgZmlyc3Qgb3B0aW9uIG9mIHRoZSBzZWxlY3QgJiYgYXJlIHRoZXJlIGVsZW1lbnRzIGluIHRoZSBkcm9wZG93bj9cclxuICAgICAgICAgICAgICBsaUluZGV4Kys7XHJcbiAgICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGlJbmRleCsrO1xyXG4gICAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGxhYmVsLCBudWxsLCAnZHJvcGRvd24taGVhZGVyJyArIG9wdEdyb3VwQ2xhc3MsIG9wdElEKSk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCAnb3B0ICcgKyBvcHRpb25DbGFzcyArIG9wdEdyb3VwQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICcnLCBvcHRJRCkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuZGF0YSgnZGl2aWRlcicpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKCcnLCBpbmRleCwgJ2RpdmlkZXInKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdoaWRkZW4nKSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgLy8gc2V0IHByZXZIaWRkZW5JbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgaGlkZGVuIG9wdGlvbiBpbiBhIGdyb3VwIG9mIGhpZGRlbiBvcHRpb25zXHJcbiAgICAgICAgICAvLyB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCBhIGRpdmlkZXIgc2hvdWxkIGJlIHBsYWNlZCBhZnRlciBhbiBvcHRncm91cCBpZiB0aGVyZSBhcmVcclxuICAgICAgICAgIC8vIGhpZGRlbiBvcHRpb25zIGJldHdlZW4gdGhlIG9wdGdyb3VwIGFuZCB0aGUgZmlyc3QgdmlzaWJsZSBvcHRpb25cclxuICAgICAgICAgIHByZXZIaWRkZW5JbmRleCA9ICR0aGlzLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcpO1xyXG4gICAgICAgICAgJHRoaXMubmV4dCgpLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcsIChwcmV2SGlkZGVuSW5kZXggIT09IHVuZGVmaW5lZCA/IHByZXZIaWRkZW5JbmRleCA6IGluZGV4KSk7XHJcblxyXG4gICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSShnZW5lcmF0ZUEodGV4dCwgb3B0aW9uQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICdoaWRkZW4gaXMtaGlkZGVuJykpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB2YXIgc2hvd0RpdmlkZXIgPSB0aGlzLnByZXZpb3VzRWxlbWVudFNpYmxpbmcgJiYgdGhpcy5wcmV2aW91c0VsZW1lbnRTaWJsaW5nLnRhZ05hbWUgPT09ICdPUFRHUk9VUCc7XHJcblxyXG4gICAgICAgICAgLy8gaWYgcHJldmlvdXMgZWxlbWVudCBpcyBub3QgYW4gb3B0Z3JvdXAgYW5kIGhpZGVEaXNhYmxlZCBpcyB0cnVlXHJcbiAgICAgICAgICBpZiAoIXNob3dEaXZpZGVyICYmIHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcblxyXG4gICAgICAgICAgICBpZiAocHJldkhpZGRlbkluZGV4ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAvLyBzZWxlY3QgdGhlIGVsZW1lbnQgKipiZWZvcmUqKiB0aGUgZmlyc3QgaGlkZGVuIGVsZW1lbnQgaW4gdGhlIGdyb3VwXHJcbiAgICAgICAgICAgICAgdmFyIHByZXZIaWRkZW4gPSAkc2VsZWN0T3B0aW9ucy5lcShwcmV2SGlkZGVuSW5kZXgpWzBdLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XHJcbiAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgaWYgKHByZXZIaWRkZW4gJiYgcHJldkhpZGRlbi50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmICFwcmV2SGlkZGVuLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICBzaG93RGl2aWRlciA9IHRydWU7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHNob3dEaXZpZGVyKSB7XHJcbiAgICAgICAgICAgIGxpSW5kZXgrKztcclxuICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCBvcHRpb25DbGFzcywgaW5saW5lLCB0b2tlbnMpLCBpbmRleCkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC5saU9ialtpbmRleF0gPSBsaUluZGV4O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vSWYgd2UgYXJlIG5vdCBtdWx0aXBsZSwgd2UgZG9uJ3QgaGF2ZSBhIHNlbGVjdGVkIGl0ZW0sIGFuZCB3ZSBkb24ndCBoYXZlIGEgdGl0bGUsIHNlbGVjdCB0aGUgZmlyc3QgZWxlbWVudCBzbyBzb21ldGhpbmcgaXMgc2V0IGluIHRoZSBidXR0b25cclxuICAgICAgaWYgKCF0aGlzLm11bHRpcGxlICYmIHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykubGVuZ3RoID09PSAwICYmICF0aGlzLm9wdGlvbnMudGl0bGUpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLmVxKDApLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSkuYXR0cignc2VsZWN0ZWQnLCAnc2VsZWN0ZWQnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIF9saS5qb2luKCcnKTtcclxuICAgIH0sXHJcblxyXG4gICAgZmluZExpczogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kbGlzID09IG51bGwpIHRoaXMuJGxpcyA9IHRoaXMuJG1lbnUuZmluZCgnbGknKTtcclxuICAgICAgcmV0dXJuIHRoaXMuJGxpcztcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3VwZGF0ZUxpXSBkZWZhdWx0cyB0byB0cnVlXHJcbiAgICAgKi9cclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKHVwZGF0ZUxpKSB7XHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgIG5vdERpc2FibGVkLFxyXG4gICAgICAgICAgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgLy9VcGRhdGUgdGhlIExJIHRvIG1hdGNoIHRoZSBTRUxFQ1RcclxuICAgICAgaWYgKHVwZGF0ZUxpICE9PSBmYWxzZSkge1xyXG4gICAgICAgICRzZWxlY3RPcHRpb25zLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XHJcbiAgICAgICAgICB2YXIgJGxpcyA9IHRoYXQuZmluZExpcygpLmVxKHRoYXQubGlPYmpbaW5kZXhdKTtcclxuXHJcbiAgICAgICAgICB0aGF0LnNldERpc2FibGVkKGluZGV4LCB0aGlzLmRpc2FibGVkIHx8IHRoaXMucGFyZW50Tm9kZS50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmIHRoaXMucGFyZW50Tm9kZS5kaXNhYmxlZCwgJGxpcyk7XHJcbiAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGluZGV4LCB0aGlzLnNlbGVjdGVkLCAkbGlzKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy50b2dnbGVQbGFjZWhvbGRlcigpO1xyXG5cclxuICAgICAgdGhpcy50YWJJbmRleCgpO1xyXG5cclxuICAgICAgdmFyIHNlbGVjdGVkSXRlbXMgPSAkc2VsZWN0T3B0aW9ucy5tYXAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkKSB7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLnBhcmVudE5vZGUudGFnTmFtZSA9PT0gJ09QVEdST1VQJyAmJiB0aGlzLnBhcmVudE5vZGUuZGlzYWJsZWQpKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICAgICBpY29uID0gJHRoaXMuZGF0YSgnaWNvbicpICYmIHRoYXQub3B0aW9ucy5zaG93SWNvbiA/ICc8aSBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9pPiAnIDogJycsXHJcbiAgICAgICAgICAgICAgc3VidGV4dDtcclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLnNob3dTdWJ0ZXh0ICYmICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAmJiAhdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JyArICR0aGlzLmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPic7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyc7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAodHlwZW9mICR0aGlzLmF0dHIoJ3RpdGxlJykgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5hdHRyKCd0aXRsZScpO1xyXG4gICAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdjb250ZW50JykgJiYgdGhhdC5vcHRpb25zLnNob3dDb250ZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5kYXRhKCdjb250ZW50JykudG9TdHJpbmcoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpY29uICsgJHRoaXMuaHRtbCgpICsgc3VidGV4dDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pLnRvQXJyYXkoKTtcclxuXHJcbiAgICAgIC8vRml4ZXMgaXNzdWUgaW4gSUUxMCBvY2N1cnJpbmcgd2hlbiBubyBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZCBhbmQgYXQgbGVhc3Qgb25lIG9wdGlvbiBpcyBkaXNhYmxlZFxyXG4gICAgICAvL0NvbnZlcnQgYWxsIHRoZSB2YWx1ZXMgaW50byBhIGNvbW1hIGRlbGltaXRlZCBzdHJpbmdcclxuICAgICAgdmFyIHRpdGxlID0gIXRoaXMubXVsdGlwbGUgPyBzZWxlY3RlZEl0ZW1zWzBdIDogc2VsZWN0ZWRJdGVtcy5qb2luKHRoaXMub3B0aW9ucy5tdWx0aXBsZVNlcGFyYXRvcik7XHJcblxyXG4gICAgICAvL0lmIHRoaXMgaXMgbXVsdGkgc2VsZWN0LCBhbmQgdGhlIHNlbGVjdFRleHQgdHlwZSBpcyBjb3VudCwgdGhlIHNob3cgMSBvZiAyIHNlbGVjdGVkIGV0Yy4uXHJcbiAgICAgIGlmICh0aGlzLm11bHRpcGxlICYmIHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuaW5kZXhPZignY291bnQnKSA+IC0xKSB7XHJcbiAgICAgICAgdmFyIG1heCA9IHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuc3BsaXQoJz4nKTtcclxuICAgICAgICBpZiAoKG1heC5sZW5ndGggPiAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID4gbWF4WzFdKSB8fCAobWF4Lmxlbmd0aCA9PSAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID49IDIpKSB7XHJcbiAgICAgICAgICBub3REaXNhYmxlZCA9IHRoaXMub3B0aW9ucy5oaWRlRGlzYWJsZWQgPyAnLCBbZGlzYWJsZWRdJyA6ICcnO1xyXG4gICAgICAgICAgdmFyIHRvdGFsQ291bnQgPSAkc2VsZWN0T3B0aW9ucy5ub3QoJ1tkYXRhLWRpdmlkZXI9XCJ0cnVlXCJdLCBbZGF0YS1oaWRkZW49XCJ0cnVlXCJdJyArIG5vdERpc2FibGVkKS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgdHI4blRleHQgPSAodHlwZW9mIHRoaXMub3B0aW9ucy5jb3VudFNlbGVjdGVkVGV4dCA9PT0gJ2Z1bmN0aW9uJykgPyB0aGlzLm9wdGlvbnMuY291bnRTZWxlY3RlZFRleHQoc2VsZWN0ZWRJdGVtcy5sZW5ndGgsIHRvdGFsQ291bnQpIDogdGhpcy5vcHRpb25zLmNvdW50U2VsZWN0ZWRUZXh0O1xyXG4gICAgICAgICAgdGl0bGUgPSB0cjhuVGV4dC5yZXBsYWNlKCd7MH0nLCBzZWxlY3RlZEl0ZW1zLmxlbmd0aC50b1N0cmluZygpKS5yZXBsYWNlKCd7MX0nLCB0b3RhbENvdW50LnRvU3RyaW5nKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2VsZWN0ZWRUZXh0Rm9ybWF0ID09ICdzdGF0aWMnKSB7XHJcbiAgICAgICAgdGl0bGUgPSB0aGlzLm9wdGlvbnMudGl0bGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vSWYgd2UgZG9udCBoYXZlIGEgdGl0bGUsIHRoZW4gdXNlIHRoZSBkZWZhdWx0LCBvciBpZiBub3RoaW5nIGlzIHNldCBhdCBhbGwsIHVzZSB0aGUgbm90IHNlbGVjdGVkIHRleHRcclxuICAgICAgaWYgKCF0aXRsZSkge1xyXG4gICAgICAgIHRpdGxlID0gdHlwZW9mIHRoaXMub3B0aW9ucy50aXRsZSAhPT0gJ3VuZGVmaW5lZCcgPyB0aGlzLm9wdGlvbnMudGl0bGUgOiB0aGlzLm9wdGlvbnMubm9uZVNlbGVjdGVkVGV4dDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy9zdHJpcCBhbGwgSFRNTCB0YWdzIGFuZCB0cmltIHRoZSByZXN1bHQsIHRoZW4gdW5lc2NhcGUgYW55IGVzY2FwZWQgdGFnc1xyXG4gICAgICB0aGlzLiRidXR0b24uYXR0cigndGl0bGUnLCBodG1sVW5lc2NhcGUoJC50cmltKHRpdGxlLnJlcGxhY2UoLzxbXj5dKj4/L2csICcnKSkpKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLmNoaWxkcmVuKCcuZmlsdGVyLW9wdGlvbicpLmh0bWwodGl0bGUpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3N0eWxlXVxyXG4gICAgICogQHBhcmFtIFtzdGF0dXNdXHJcbiAgICAgKi9cclxuICAgIHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUsIHN0YXR1cykge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5hdHRyKCdjbGFzcycpKSB7XHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5hZGRDbGFzcyh0aGlzLiRlbGVtZW50LmF0dHIoJ2NsYXNzJykucmVwbGFjZSgvc2VsZWN0cGlja2VyfG1vYmlsZS1kZXZpY2V8YnMtc2VsZWN0LWhpZGRlbnx2YWxpZGF0ZVxcWy4qXFxdL2dpLCAnJykpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgYnV0dG9uQ2xhc3MgPSBzdHlsZSA/IHN0eWxlIDogdGhpcy5vcHRpb25zLnN0eWxlO1xyXG5cclxuICAgICAgaWYgKHN0YXR1cyA9PSAnYWRkJykge1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcyhidXR0b25DbGFzcyk7XHJcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID09ICdyZW1vdmUnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLnJlbW92ZUNsYXNzKGJ1dHRvbkNsYXNzKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLiRidXR0b24ucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLnN0eWxlKTtcclxuICAgICAgICB0aGlzLiRidXR0b24uYWRkQ2xhc3MoYnV0dG9uQ2xhc3MpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGxpSGVpZ2h0OiBmdW5jdGlvbiAocmVmcmVzaCkge1xyXG4gICAgICBpZiAoIXJlZnJlc2ggJiYgKHRoaXMub3B0aW9ucy5zaXplID09PSBmYWxzZSB8fCB0aGlzLnNpemVJbmZvKSkgcmV0dXJuO1xyXG5cclxuICAgICAgdmFyIG5ld0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnVJbm5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3VsJyksXHJcbiAgICAgICAgICBkaXZpZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGxpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyksXHJcbiAgICAgICAgICB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLFxyXG4gICAgICAgICAgaGVhZGVyID0gdGhpcy5vcHRpb25zLmhlYWRlciAmJiB0aGlzLiRtZW51LmZpbmQoJy5wb3BvdmVyLXRpdGxlJykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLnBvcG92ZXItdGl0bGUnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgc2VhcmNoID0gdGhpcy5vcHRpb25zLmxpdmVTZWFyY2ggPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSA6IG51bGwsXHJcbiAgICAgICAgICBhY3Rpb25zID0gdGhpcy5vcHRpb25zLmFjdGlvbnNCb3ggJiYgdGhpcy5tdWx0aXBsZSAmJiB0aGlzLiRtZW51LmZpbmQoJy5icy1hY3Rpb25zYm94JykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLmJzLWFjdGlvbnNib3gnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbiA9IHRoaXMub3B0aW9ucy5kb25lQnV0dG9uICYmIHRoaXMubXVsdGlwbGUgJiYgdGhpcy4kbWVudS5maW5kKCcuYnMtZG9uZWJ1dHRvbicpLmxlbmd0aCA+IDAgPyB0aGlzLiRtZW51LmZpbmQoJy5icy1kb25lYnV0dG9uJylbMF0uY2xvbmVOb2RlKHRydWUpIDogbnVsbDtcclxuXHJcbiAgICAgIHRleHQuY2xhc3NOYW1lID0gJ3RleHQnO1xyXG4gICAgICBuZXdFbGVtZW50LmNsYXNzTmFtZSA9IHRoaXMuJG1lbnVbMF0ucGFyZW50Tm9kZS5jbGFzc05hbWUgKyAnIG9wZW4nO1xyXG4gICAgICBtZW51LmNsYXNzTmFtZSA9ICdkcm9wZG93bi1tZW51IG9wZW4nO1xyXG4gICAgICBtZW51SW5uZXIuY2xhc3NOYW1lID0gJ2Ryb3Bkb3duLW1lbnUgaW5uZXInO1xyXG4gICAgICBkaXZpZGVyLmNsYXNzTmFtZSA9ICdkaXZpZGVyJztcclxuXHJcbiAgICAgIHRleHQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJ0lubmVyIHRleHQnKSk7XHJcbiAgICAgIGEuYXBwZW5kQ2hpbGQodGV4dCk7XHJcbiAgICAgIGxpLmFwcGVuZENoaWxkKGEpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQobGkpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQoZGl2aWRlcik7XHJcbiAgICAgIGlmIChoZWFkZXIpIG1lbnUuYXBwZW5kQ2hpbGQoaGVhZGVyKTtcclxuICAgICAgaWYgKHNlYXJjaCkge1xyXG4gICAgICAgIHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcbiAgICAgICAgc2VhcmNoLmNsYXNzTmFtZSA9ICdicy1zZWFyY2hib3gnO1xyXG4gICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICdmb3JtLWNvbnRyb2wnO1xyXG4gICAgICAgIHNlYXJjaC5hcHBlbmRDaGlsZChpbnB1dCk7XHJcbiAgICAgICAgbWVudS5hcHBlbmRDaGlsZChzZWFyY2gpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChhY3Rpb25zKSBtZW51LmFwcGVuZENoaWxkKGFjdGlvbnMpO1xyXG4gICAgICBtZW51LmFwcGVuZENoaWxkKG1lbnVJbm5lcik7XHJcbiAgICAgIGlmIChkb25lQnV0dG9uKSBtZW51LmFwcGVuZENoaWxkKGRvbmVCdXR0b24pO1xyXG4gICAgICBuZXdFbGVtZW50LmFwcGVuZENoaWxkKG1lbnUpO1xyXG5cclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgIHZhciBsaUhlaWdodCA9IGEub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gaGVhZGVyID8gaGVhZGVyLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSBzZWFyY2ggPyBzZWFyY2gub2Zmc2V0SGVpZ2h0IDogMCxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSBhY3Rpb25zID8gYWN0aW9ucy5vZmZzZXRIZWlnaHQgOiAwLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbkhlaWdodCA9IGRvbmVCdXR0b24gPyBkb25lQnV0dG9uLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBkaXZpZGVySGVpZ2h0ID0gJChkaXZpZGVyKS5vdXRlckhlaWdodCh0cnVlKSxcclxuICAgICAgICAgIC8vIGZhbGwgYmFjayB0byBqUXVlcnkgaWYgZ2V0Q29tcHV0ZWRTdHlsZSBpcyBub3Qgc3VwcG9ydGVkXHJcbiAgICAgICAgICBtZW51U3R5bGUgPSB0eXBlb2YgZ2V0Q29tcHV0ZWRTdHlsZSA9PT0gJ2Z1bmN0aW9uJyA/IGdldENvbXB1dGVkU3R5bGUobWVudSkgOiBmYWxzZSxcclxuICAgICAgICAgICRtZW51ID0gbWVudVN0eWxlID8gbnVsbCA6ICQobWVudSksXHJcbiAgICAgICAgICBtZW51UGFkZGluZyA9IHtcclxuICAgICAgICAgICAgdmVydDogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdUb3AgOiAkbWVudS5jc3MoJ3BhZGRpbmdUb3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUucGFkZGluZ0JvdHRvbSA6ICRtZW51LmNzcygncGFkZGluZ0JvdHRvbScpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJUb3BXaWR0aCA6ICRtZW51LmNzcygnYm9yZGVyVG9wV2lkdGgnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUuYm9yZGVyQm90dG9tV2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckJvdHRvbVdpZHRoJykpLFxyXG4gICAgICAgICAgICBob3JpejogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdMZWZ0IDogJG1lbnUuY3NzKCdwYWRkaW5nTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5wYWRkaW5nUmlnaHQgOiAkbWVudS5jc3MoJ3BhZGRpbmdSaWdodCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJMZWZ0V2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJSaWdodFdpZHRoIDogJG1lbnUuY3NzKCdib3JkZXJSaWdodFdpZHRoJykpXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9ICB7XHJcbiAgICAgICAgICAgIHZlcnQ6IG1lbnVQYWRkaW5nLnZlcnQgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luVG9wIDogJG1lbnUuY3NzKCdtYXJnaW5Ub3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luQm90dG9tIDogJG1lbnUuY3NzKCdtYXJnaW5Cb3R0b20nKSkgKyAyLFxyXG4gICAgICAgICAgICBob3JpejogbWVudVBhZGRpbmcuaG9yaXogK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luTGVmdCA6ICRtZW51LmNzcygnbWFyZ2luTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5SaWdodCA6ICRtZW51LmNzcygnbWFyZ2luUmlnaHQnKSkgKyAyXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgdGhpcy5zaXplSW5mbyA9IHtcclxuICAgICAgICBsaUhlaWdodDogbGlIZWlnaHQsXHJcbiAgICAgICAgaGVhZGVySGVpZ2h0OiBoZWFkZXJIZWlnaHQsXHJcbiAgICAgICAgc2VhcmNoSGVpZ2h0OiBzZWFyY2hIZWlnaHQsXHJcbiAgICAgICAgYWN0aW9uc0hlaWdodDogYWN0aW9uc0hlaWdodCxcclxuICAgICAgICBkb25lQnV0dG9uSGVpZ2h0OiBkb25lQnV0dG9uSGVpZ2h0LFxyXG4gICAgICAgIGRpdmlkZXJIZWlnaHQ6IGRpdmlkZXJIZWlnaHQsXHJcbiAgICAgICAgbWVudVBhZGRpbmc6IG1lbnVQYWRkaW5nLFxyXG4gICAgICAgIG1lbnVFeHRyYXM6IG1lbnVFeHRyYXNcclxuICAgICAgfTtcclxuICAgIH0sXHJcblxyXG4gICAgc2V0U2l6ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLmZpbmRMaXMoKTtcclxuICAgICAgdGhpcy5saUhlaWdodCgpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5oZWFkZXIpIHRoaXMuJG1lbnUuY3NzKCdwYWRkaW5nLXRvcCcsIDApO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnNpemUgPT09IGZhbHNlKSByZXR1cm47XHJcblxyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkbWVudSA9IHRoaXMuJG1lbnUsXHJcbiAgICAgICAgICAkbWVudUlubmVyID0gdGhpcy4kbWVudUlubmVyLFxyXG4gICAgICAgICAgJHdpbmRvdyA9ICQod2luZG93KSxcclxuICAgICAgICAgIHNlbGVjdEhlaWdodCA9IHRoaXMuJG5ld0VsZW1lbnRbMF0ub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgc2VsZWN0V2lkdGggPSB0aGlzLiRuZXdFbGVtZW50WzBdLm9mZnNldFdpZHRoLFxyXG4gICAgICAgICAgbGlIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydsaUhlaWdodCddLFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snaGVhZGVySGVpZ2h0J10sXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydzZWFyY2hIZWlnaHQnXSxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydhY3Rpb25zSGVpZ2h0J10sXHJcbiAgICAgICAgICBkb25lQnV0dG9uSGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZG9uZUJ1dHRvbkhlaWdodCddLFxyXG4gICAgICAgICAgZGl2SGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZGl2aWRlckhlaWdodCddLFxyXG4gICAgICAgICAgbWVudVBhZGRpbmcgPSB0aGlzLnNpemVJbmZvWydtZW51UGFkZGluZyddLFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9IHRoaXMuc2l6ZUluZm9bJ21lbnVFeHRyYXMnXSxcclxuICAgICAgICAgIG5vdERpc2FibGVkID0gdGhpcy5vcHRpb25zLmhpZGVEaXNhYmxlZCA/ICcuZGlzYWJsZWQnIDogJycsXHJcbiAgICAgICAgICBtZW51SGVpZ2h0LFxyXG4gICAgICAgICAgbWVudVdpZHRoLFxyXG4gICAgICAgICAgZ2V0SGVpZ2h0LFxyXG4gICAgICAgICAgZ2V0V2lkdGgsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRCb3QsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0LFxyXG4gICAgICAgICAgc2VsZWN0T2Zmc2V0UmlnaHQsXHJcbiAgICAgICAgICBnZXRQb3MgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgdmFyIHBvcyA9IHRoYXQuJG5ld0VsZW1lbnQub2Zmc2V0KCksXHJcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyID0gJCh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSxcclxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclBvcztcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyICYmICEkY29udGFpbmVyLmlzKCdib2R5JykpIHtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MgPSAkY29udGFpbmVyLm9mZnNldCgpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy50b3AgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlclRvcFdpZHRoJykpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy5sZWZ0ICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJMZWZ0V2lkdGgnKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdmFyIHdpblBhZCA9IHRoYXQub3B0aW9ucy53aW5kb3dQYWRkaW5nO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgPSBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCAtICR3aW5kb3cuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldEJvdCA9ICR3aW5kb3cuaGVpZ2h0KCkgLSBzZWxlY3RPZmZzZXRUb3AgLSBzZWxlY3RIZWlnaHQgLSBjb250YWluZXJQb3MudG9wIC0gd2luUGFkWzJdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0ID0gcG9zLmxlZnQgLSBjb250YWluZXJQb3MubGVmdCAtICR3aW5kb3cuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRSaWdodCA9ICR3aW5kb3cud2lkdGgoKSAtIHNlbGVjdE9mZnNldExlZnQgLSBzZWxlY3RXaWR0aCAtIGNvbnRhaW5lclBvcy5sZWZ0IC0gd2luUGFkWzFdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgLT0gd2luUGFkWzBdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0IC09IHdpblBhZFszXTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICBnZXRQb3MoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSA9PT0gJ2F1dG8nKSB7XHJcbiAgICAgICAgdmFyIGdldFNpemUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB2YXIgbWluSGVpZ2h0LFxyXG4gICAgICAgICAgICAgIGhhc0NsYXNzID0gZnVuY3Rpb24gKGNsYXNzTmFtZSwgaW5jbHVkZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluY2x1ZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChlbGVtZW50LmNsYXNzTGlzdCA/IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSkgOiAkKGVsZW1lbnQpLmhhc0NsYXNzKGNsYXNzTmFtZSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhKGVsZW1lbnQuY2xhc3NMaXN0ID8gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSA6ICQoZWxlbWVudCkuaGFzQ2xhc3MoY2xhc3NOYW1lKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgIGxpcyA9IHRoYXQuJG1lbnVJbm5lclswXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbGknKSxcclxuICAgICAgICAgICAgICBsaXNWaXNpYmxlID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXMsIGhhc0NsYXNzKCdoaWRkZW4nLCBmYWxzZSkpIDogdGhhdC4kbGlzLm5vdCgnLmhpZGRlbicpLFxyXG4gICAgICAgICAgICAgIG9wdEdyb3VwID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXNWaXNpYmxlLCBoYXNDbGFzcygnZHJvcGRvd24taGVhZGVyJywgdHJ1ZSkpIDogbGlzVmlzaWJsZS5maWx0ZXIoJy5kcm9wZG93bi1oZWFkZXInKTtcclxuXHJcbiAgICAgICAgICBnZXRQb3MoKTtcclxuICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRCb3QgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICBtZW51V2lkdGggPSBzZWxlY3RPZmZzZXRSaWdodCAtIG1lbnVFeHRyYXMuaG9yaXo7XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgICBnZXRIZWlnaHQgPSAkbWVudS5kYXRhKCdoZWlnaHQnKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJG1lbnUuZGF0YSgnd2lkdGgnKSkgJG1lbnUuZGF0YSgnd2lkdGgnLCAkbWVudS53aWR0aCgpKTtcclxuICAgICAgICAgICAgZ2V0V2lkdGggPSAkbWVudS5kYXRhKCd3aWR0aCcpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuaGVpZ2h0KCk7XHJcbiAgICAgICAgICAgIGdldFdpZHRoID0gJG1lbnUud2lkdGgoKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmRyb3B1cEF1dG8pIHtcclxuICAgICAgICAgICAgdGhhdC4kbmV3RWxlbWVudC50b2dnbGVDbGFzcygnZHJvcHVwJywgc2VsZWN0T2Zmc2V0VG9wID4gc2VsZWN0T2Zmc2V0Qm90ICYmIChtZW51SGVpZ2h0IC0gbWVudUV4dHJhcy52ZXJ0KSA8IGdldEhlaWdodCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2Ryb3B1cCcpKSB7XHJcbiAgICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRUb3AgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09ICdhdXRvJykge1xyXG4gICAgICAgICAgICAkbWVudS50b2dnbGVDbGFzcygnZHJvcGRvd24tbWVudS1yaWdodCcsIHNlbGVjdE9mZnNldExlZnQgPiBzZWxlY3RPZmZzZXRSaWdodCAmJiAobWVudVdpZHRoIC0gbWVudUV4dHJhcy5ob3JpeikgPCAoZ2V0V2lkdGggLSBzZWxlY3RXaWR0aCkpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICgobGlzVmlzaWJsZS5sZW5ndGggKyBvcHRHcm91cC5sZW5ndGgpID4gMykge1xyXG4gICAgICAgICAgICBtaW5IZWlnaHQgPSBsaUhlaWdodCAqIDMgKyBtZW51RXh0cmFzLnZlcnQgLSAyO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbWluSGVpZ2h0ID0gMDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cnOiAnaGlkZGVuJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBtaW5IZWlnaHQgKyBoZWFkZXJIZWlnaHQgKyBzZWFyY2hIZWlnaHQgKyBhY3Rpb25zSGVpZ2h0ICsgZG9uZUJ1dHRvbkhlaWdodCArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgLSBoZWFkZXJIZWlnaHQgLSBzZWFyY2hIZWlnaHQgLSBhY3Rpb25zSGVpZ2h0IC0gZG9uZUJ1dHRvbkhlaWdodCAtIG1lbnVQYWRkaW5nLnZlcnQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBNYXRoLm1heChtaW5IZWlnaHQgLSBtZW51UGFkZGluZy52ZXJ0LCAwKSArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgZ2V0U2l6ZSgpO1xyXG4gICAgICAgIHRoaXMuJHNlYXJjaGJveC5vZmYoJ2lucHV0LmdldFNpemUgcHJvcGVydHljaGFuZ2UuZ2V0U2l6ZScpLm9uKCdpbnB1dC5nZXRTaXplIHByb3BlcnR5Y2hhbmdlLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgICAkd2luZG93Lm9mZigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnKS5vbigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSAmJiB0aGlzLm9wdGlvbnMuc2l6ZSAhPSAnYXV0bycgJiYgdGhpcy4kbGlzLm5vdChub3REaXNhYmxlZCkubGVuZ3RoID4gdGhpcy5vcHRpb25zLnNpemUpIHtcclxuICAgICAgICB2YXIgb3B0SW5kZXggPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlcicpLm5vdChub3REaXNhYmxlZCkuY2hpbGRyZW4oKS5zbGljZSgwLCB0aGlzLm9wdGlvbnMuc2l6ZSkubGFzdCgpLnBhcmVudCgpLmluZGV4KCksXHJcbiAgICAgICAgICAgIGRpdkxlbmd0aCA9IHRoaXMuJGxpcy5zbGljZSgwLCBvcHRJbmRleCArIDEpLmZpbHRlcignLmRpdmlkZXInKS5sZW5ndGg7XHJcbiAgICAgICAgbWVudUhlaWdodCA9IGxpSGVpZ2h0ICogdGhpcy5vcHRpb25zLnNpemUgKyBkaXZMZW5ndGggKiBkaXZIZWlnaHQgKyBtZW51UGFkZGluZy52ZXJ0O1xyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmNvbnRhaW5lcikge1xyXG4gICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuZGF0YSgnaGVpZ2h0Jyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGdldEhlaWdodCA9ICRtZW51LmhlaWdodCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wdXBBdXRvKSB7XHJcbiAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1VudXNlZEFzc2lnbm1lbnRcclxuICAgICAgICAgIHRoaXMuJG5ld0VsZW1lbnQudG9nZ2xlQ2xhc3MoJ2Ryb3B1cCcsIHNlbGVjdE9mZnNldFRvcCA+IHNlbGVjdE9mZnNldEJvdCAmJiAobWVudUhlaWdodCAtIG1lbnVFeHRyYXMudmVydCkgPCBnZXRIZWlnaHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0ICsgaGVhZGVySGVpZ2h0ICsgc2VhcmNoSGVpZ2h0ICsgYWN0aW9uc0hlaWdodCArIGRvbmVCdXR0b25IZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgJ292ZXJmbG93JzogJ2hpZGRlbicsXHJcbiAgICAgICAgICAnbWluLWhlaWdodCc6ICcnXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0IC0gbWVudVBhZGRpbmcudmVydCArICdweCcsXHJcbiAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICdtaW4taGVpZ2h0JzogJydcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZXRXaWR0aDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnYXV0bycpIHtcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJzAnKTtcclxuXHJcbiAgICAgICAgLy8gR2V0IGNvcnJlY3Qgd2lkdGggaWYgZWxlbWVudCBpcyBoaWRkZW5cclxuICAgICAgICB2YXIgJHNlbGVjdENsb25lID0gdGhpcy4kbWVudS5wYXJlbnQoKS5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JyksXHJcbiAgICAgICAgICAgICRzZWxlY3RDbG9uZTIgPSB0aGlzLm9wdGlvbnMuY29udGFpbmVyID8gdGhpcy4kbmV3RWxlbWVudC5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JykgOiAkc2VsZWN0Q2xvbmUsXHJcbiAgICAgICAgICAgIHVsV2lkdGggPSAkc2VsZWN0Q2xvbmUuY2hpbGRyZW4oJy5kcm9wZG93bi1tZW51Jykub3V0ZXJXaWR0aCgpLFxyXG4gICAgICAgICAgICBidG5XaWR0aCA9ICRzZWxlY3RDbG9uZTIuY3NzKCd3aWR0aCcsICdhdXRvJykuY2hpbGRyZW4oJ2J1dHRvbicpLm91dGVyV2lkdGgoKTtcclxuXHJcbiAgICAgICAgJHNlbGVjdENsb25lLnJlbW92ZSgpO1xyXG4gICAgICAgICRzZWxlY3RDbG9uZTIucmVtb3ZlKCk7XHJcblxyXG4gICAgICAgIC8vIFNldCB3aWR0aCB0byB3aGF0ZXZlcidzIGxhcmdlciwgYnV0dG9uIHRpdGxlIG9yIGxvbmdlc3Qgb3B0aW9uXHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5jc3MoJ3dpZHRoJywgTWF0aC5tYXgodWxXaWR0aCwgYnRuV2lkdGgpICsgJ3B4Jyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnZml0Jykge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJykuYWRkQ2xhc3MoJ2ZpdC13aWR0aCcpO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy53aWR0aCkge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCB0aGlzLm9wdGlvbnMud2lkdGgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoL3dpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJyk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gUmVtb3ZlIGZpdC13aWR0aCBjbGFzcyBpZiB3aWR0aCBpcyBjaGFuZ2VkIHByb2dyYW1tYXRpY2FsbHlcclxuICAgICAgaWYgKHRoaXMuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2ZpdC13aWR0aCcpICYmIHRoaXMub3B0aW9ucy53aWR0aCAhPT0gJ2ZpdCcpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdmaXQtd2lkdGgnKTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRic0NvbnRhaW5lciA9ICQoJzxkaXYgY2xhc3M9XCJicy1jb250YWluZXJcIiAvPicpO1xyXG5cclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGNvbnRhaW5lciA9ICQodGhpcy5vcHRpb25zLmNvbnRhaW5lciksXHJcbiAgICAgICAgICBwb3MsXHJcbiAgICAgICAgICBjb250YWluZXJQb3MsXHJcbiAgICAgICAgICBhY3R1YWxIZWlnaHQsXHJcbiAgICAgICAgICBnZXRQbGFjZW1lbnQgPSBmdW5jdGlvbiAoJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgdGhhdC4kYnNDb250YWluZXIuYWRkQ2xhc3MoJGVsZW1lbnQuYXR0cignY2xhc3MnKS5yZXBsYWNlKC9mb3JtLWNvbnRyb2x8Zml0LXdpZHRoL2dpLCAnJykpLnRvZ2dsZUNsYXNzKCdkcm9wdXAnLCAkZWxlbWVudC5oYXNDbGFzcygnZHJvcHVwJykpO1xyXG4gICAgICAgICAgICBwb3MgPSAkZWxlbWVudC5vZmZzZXQoKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJGNvbnRhaW5lci5pcygnYm9keScpKSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0gJGNvbnRhaW5lci5vZmZzZXQoKTtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MudG9wICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJUb3BXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zLmxlZnQgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcyA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGFjdHVhbEhlaWdodCA9ICRlbGVtZW50Lmhhc0NsYXNzKCdkcm9wdXAnKSA/IDAgOiAkZWxlbWVudFswXS5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICd0b3AnOiBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCArIGFjdHVhbEhlaWdodCxcclxuICAgICAgICAgICAgICAnbGVmdCc6IHBvcy5sZWZ0IC0gY29udGFpbmVyUG9zLmxlZnQsXHJcbiAgICAgICAgICAgICAgJ3dpZHRoJzogJGVsZW1lbnRbMF0ub2Zmc2V0V2lkdGhcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9O1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBpZiAodGhhdC5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGdldFBsYWNlbWVudCh0aGF0LiRuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgICAgdGhhdC4kYnNDb250YWluZXJcclxuICAgICAgICAgIC5hcHBlbmRUbyh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKVxyXG4gICAgICAgICAgLnRvZ2dsZUNsYXNzKCdvcGVuJywgISR0aGlzLmhhc0NsYXNzKCdvcGVuJykpXHJcbiAgICAgICAgICAuYXBwZW5kKHRoYXQuJG1lbnUpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgICQod2luZG93KS5vbigncmVzaXplIHNjcm9sbCcsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBnZXRQbGFjZW1lbnQodGhhdC4kbmV3RWxlbWVudCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignaGlkZS5icy5zZWxlY3QnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5kYXRhKCdoZWlnaHQnLCB0aGF0LiRtZW51LmhlaWdodCgpKTtcclxuICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5kZXRhY2goKTtcclxuICAgICAgfSk7XHJcbiAgICB9LFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBvcHRpb24gdGhhdCBpcyBiZWluZyBjaGFuZ2VkXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNlbGVjdGVkIC0gdHJ1ZSBpZiB0aGUgb3B0aW9uIGlzIGJlaW5nIHNlbGVjdGVkLCBmYWxzZSBpZiBiZWluZyBkZXNlbGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge0pRdWVyeX0gJGxpcyAtIHRoZSAnbGknIGVsZW1lbnQgdGhhdCBpcyBiZWluZyBtb2RpZmllZFxyXG4gICAgICovXHJcbiAgICBzZXRTZWxlY3RlZDogZnVuY3Rpb24gKGluZGV4LCBzZWxlY3RlZCwgJGxpcykge1xyXG4gICAgICBpZiAoISRsaXMpIHtcclxuICAgICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7IC8vIGNoZWNrIGlmIHNldFNlbGVjdGVkIGlzIGJlaW5nIGNhbGxlZCBieSBjaGFuZ2luZyB0aGUgdmFsdWUgb2YgdGhlIHNlbGVjdFxyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICRsaXMudG9nZ2xlQ2xhc3MoJ3NlbGVjdGVkJywgc2VsZWN0ZWQpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgc2VsZWN0ZWQpO1xyXG4gICAgfSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgb3B0aW9uIHRoYXQgaXMgYmVpbmcgZGlzYWJsZWRcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlzYWJsZWQgLSB0cnVlIGlmIHRoZSBvcHRpb24gaXMgYmVpbmcgZGlzYWJsZWQsIGZhbHNlIGlmIGJlaW5nIGVuYWJsZWRcclxuICAgICAqIEBwYXJhbSB7SlF1ZXJ5fSAkbGlzIC0gdGhlICdsaScgZWxlbWVudCB0aGF0IGlzIGJlaW5nIG1vZGlmaWVkXHJcbiAgICAgKi9cclxuICAgIHNldERpc2FibGVkOiBmdW5jdGlvbiAoaW5kZXgsIGRpc2FibGVkLCAkbGlzKSB7XHJcbiAgICAgIGlmICghJGxpcykge1xyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChkaXNhYmxlZCkge1xyXG4gICAgICAgICRsaXMuYWRkQ2xhc3MoJ2Rpc2FibGVkJykuY2hpbGRyZW4oJ2EnKS5hdHRyKCdocmVmJywgJyMnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgJGxpcy5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5jaGlsZHJlbignYScpLnJlbW92ZUF0dHIoJ2hyZWYnKS5hdHRyKCd0YWJpbmRleCcsIDApLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCBmYWxzZSk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgaXNEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy4kZWxlbWVudFswXS5kaXNhYmxlZDtcclxuICAgIH0sXHJcblxyXG4gICAgY2hlY2tEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcblxyXG4gICAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgZmFsc2UpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5hdHRyKCd0YWJpbmRleCcpID09IC0xICYmICF0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JykpIHtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVBdHRyKCd0YWJpbmRleCcpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gIXRoYXQuaXNEaXNhYmxlZCgpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgdG9nZ2xlUGxhY2Vob2xkZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHZhbHVlID0gdGhpcy4kZWxlbWVudC52YWwoKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLnRvZ2dsZUNsYXNzKCdicy1wbGFjZWhvbGRlcicsIHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnJyB8fCAodmFsdWUuY29uc3RydWN0b3IgPT09IEFycmF5ICYmIHZhbHVlLmxlbmd0aCA9PT0gMCkpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0YWJJbmRleDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpICE9PSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RhYmluZGV4JykgJiYgXHJcbiAgICAgICAgKHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gLTk4ICYmIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gJy05OCcpKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcsIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSk7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ3RhYmluZGV4JywgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcsIC05OCk7XHJcbiAgICB9LFxyXG5cclxuICAgIGNsaWNrTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGRvY3VtZW50ID0gJChkb2N1bWVudCk7XHJcblxyXG4gICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24ub24oJ2tleXVwJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAoLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgJiYgJGRvY3VtZW50LmRhdGEoJ3NwYWNlU2VsZWN0JykpIHtcclxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC5zZXRTaXplKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignc2hvd24uYnMuc2VsZWN0JywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmxpdmVTZWFyY2ggJiYgIXRoYXQubXVsdGlwbGUpIHtcclxuICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQgYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmICghdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgdmFyIHNlbGVjdGVkSW5kZXggPSB0aGF0LmxpT2JqW3RoYXQuJGVsZW1lbnRbMF0uc2VsZWN0ZWRJbmRleF07XHJcblxyXG4gICAgICAgICAgaWYgKHR5cGVvZiBzZWxlY3RlZEluZGV4ICE9PSAnbnVtYmVyJyB8fCB0aGF0Lm9wdGlvbnMuc2l6ZSA9PT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAvLyBzY3JvbGwgdG8gc2VsZWN0ZWQgb3B0aW9uXHJcbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gdGhhdC4kbGlzLmVxKHNlbGVjdGVkSW5kZXgpWzBdLm9mZnNldFRvcCAtIHRoYXQuJG1lbnVJbm5lclswXS5vZmZzZXRUb3A7XHJcbiAgICAgICAgICBvZmZzZXQgPSBvZmZzZXQgLSB0aGF0LiRtZW51SW5uZXJbMF0ub2Zmc2V0SGVpZ2h0LzIgKyB0aGF0LnNpemVJbmZvLmxpSGVpZ2h0LzI7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXJbMF0uc2Nyb2xsVG9wID0gb2Zmc2V0O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJ2xpIGEnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAgIGNsaWNrZWRJbmRleCA9ICR0aGlzLnBhcmVudCgpLmRhdGEoJ29yaWdpbmFsSW5kZXgnKSxcclxuICAgICAgICAgICAgcHJldlZhbHVlID0gdGhhdC4kZWxlbWVudC52YWwoKSxcclxuICAgICAgICAgICAgcHJldkluZGV4ID0gdGhhdC4kZWxlbWVudC5wcm9wKCdzZWxlY3RlZEluZGV4JyksXHJcbiAgICAgICAgICAgIHRyaWdnZXJDaGFuZ2UgPSB0cnVlO1xyXG5cclxuICAgICAgICAvLyBEb24ndCBjbG9zZSBvbiBtdWx0aSBjaG9pY2UgbWVudVxyXG4gICAgICAgIGlmICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zICE9PSAxKSB7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgICAgICAvL0Rvbid0IHJ1biBpZiB3ZSBoYXZlIGJlZW4gZGlzYWJsZWRcclxuICAgICAgICBpZiAoIXRoYXQuaXNEaXNhYmxlZCgpICYmICEkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdmFyICRvcHRpb25zID0gdGhhdC4kZWxlbWVudC5maW5kKCdvcHRpb24nKSxcclxuICAgICAgICAgICAgICAkb3B0aW9uID0gJG9wdGlvbnMuZXEoY2xpY2tlZEluZGV4KSxcclxuICAgICAgICAgICAgICBzdGF0ZSA9ICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSxcclxuICAgICAgICAgICAgICAkb3B0Z3JvdXAgPSAkb3B0aW9uLnBhcmVudCgnb3B0Z3JvdXAnKSxcclxuICAgICAgICAgICAgICBtYXhPcHRpb25zID0gdGhhdC5vcHRpb25zLm1heE9wdGlvbnMsXHJcbiAgICAgICAgICAgICAgbWF4T3B0aW9uc0dycCA9ICRvcHRncm91cC5kYXRhKCdtYXhPcHRpb25zJykgfHwgZmFsc2U7XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlKSB7IC8vIERlc2VsZWN0IGFsbCBvdGhlcnMgaWYgbm90IG11bHRpIHNlbGVjdCBib3hcclxuICAgICAgICAgICAgJG9wdGlvbnMucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCcpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgdHJ1ZSk7XHJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBUb2dnbGUgdGhlIG9uZSB3ZSBoYXZlIGNob3NlbiBpZiB3ZSBhcmUgbXVsdGkgc2VsZWN0LlxyXG4gICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgIXN0YXRlKTtcclxuICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsICFzdGF0ZSk7XHJcbiAgICAgICAgICAgICR0aGlzLmJsdXIoKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChtYXhPcHRpb25zICE9PSBmYWxzZSB8fCBtYXhPcHRpb25zR3JwICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgIHZhciBtYXhSZWFjaGVkID0gbWF4T3B0aW9ucyA8ICRvcHRpb25zLmZpbHRlcignOnNlbGVjdGVkJykubGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICBtYXhSZWFjaGVkR3JwID0gbWF4T3B0aW9uc0dycCA8ICRvcHRncm91cC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5sZW5ndGg7XHJcblxyXG4gICAgICAgICAgICAgIGlmICgobWF4T3B0aW9ucyAmJiBtYXhSZWFjaGVkKSB8fCAobWF4T3B0aW9uc0dycCAmJiBtYXhSZWFjaGVkR3JwKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4T3B0aW9ucyA9PSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb25zLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXhPcHRpb25zR3JwICYmIG1heE9wdGlvbnNHcnAgPT0gMSkge1xyXG4gICAgICAgICAgICAgICAgICAkb3B0Z3JvdXAuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgdmFyIG9wdGdyb3VwSUQgPSAkdGhpcy5wYXJlbnQoKS5kYXRhKCdvcHRncm91cCcpO1xyXG4gICAgICAgICAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnW2RhdGEtb3B0Z3JvdXA9XCInICsgb3B0Z3JvdXBJRCArICdcIl0nKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgdmFyIG1heE9wdGlvbnNUZXh0ID0gdHlwZW9mIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zVGV4dCA9PT0gJ3N0cmluZycgPyBbdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LCB0aGF0Lm9wdGlvbnMubWF4T3B0aW9uc1RleHRdIDogdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4T3B0aW9uc0FyciA9IHR5cGVvZiBtYXhPcHRpb25zVGV4dCA9PT0gJ2Z1bmN0aW9uJyA/IG1heE9wdGlvbnNUZXh0KG1heE9wdGlvbnMsIG1heE9wdGlvbnNHcnApIDogbWF4T3B0aW9uc1RleHQsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhPcHRpb25zQXJyWzBdLnJlcGxhY2UoJ3tufScsIG1heE9wdGlvbnMpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4VHh0R3JwID0gbWF4T3B0aW9uc0FyclsxXS5yZXBsYWNlKCd7bn0nLCBtYXhPcHRpb25zR3JwKSxcclxuICAgICAgICAgICAgICAgICAgICAgICRub3RpZnkgPSAkKCc8ZGl2IGNsYXNzPVwibm90aWZ5XCI+PC9kaXY+Jyk7XHJcbiAgICAgICAgICAgICAgICAgIC8vIElmIHt2YXJ9IGlzIHNldCBpbiBhcnJheSwgcmVwbGFjZSBpdFxyXG4gICAgICAgICAgICAgICAgICAvKiogQGRlcHJlY2F0ZWQgKi9cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNBcnJbMl0pIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhUeHQucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnMgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHRHcnAgPSBtYXhUeHRHcnAucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnNHcnAgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnUuYXBwZW5kKCRub3RpZnkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4UmVhY2hlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNHcnAgJiYgbWF4UmVhY2hlZEdycCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dEdycCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZEdycC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgfSwgMTApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgJG5vdGlmeS5kZWxheSg3NTApLmZhZGVPdXQoMzAwLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5yZW1vdmUoKTtcclxuICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlIHx8ICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zID09PSAxKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gVHJpZ2dlciBzZWxlY3QgJ2NoYW5nZSdcclxuICAgICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlKSB7XHJcbiAgICAgICAgICAgIGlmICgocHJldlZhbHVlICE9IHRoYXQuJGVsZW1lbnQudmFsKCkgJiYgdGhhdC5tdWx0aXBsZSkgfHwgKHByZXZJbmRleCAhPSB0aGF0LiRlbGVtZW50LnByb3AoJ3NlbGVjdGVkSW5kZXgnKSAmJiAhdGhhdC5tdWx0aXBsZSkpIHtcclxuICAgICAgICAgICAgICAvLyAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJykgaXMgY3VycmVudCBvcHRpb24gc3RhdGUgKHNlbGVjdGVkL3Vuc2VsZWN0ZWQpLiBzdGF0ZSBpcyBwcmV2aW91cyBvcHRpb24gc3RhdGUuXHJcbiAgICAgICAgICAgICAgY2hhbmdlZF9hcmd1bWVudHMgPSBbY2xpY2tlZEluZGV4LCAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJyksIHN0YXRlXTtcclxuICAgICAgICAgICAgICB0aGF0LiRlbGVtZW50XHJcbiAgICAgICAgICAgICAgICAudHJpZ2dlck5hdGl2ZSgnY2hhbmdlJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnbGkuZGlzYWJsZWQgYSwgLnBvcG92ZXItdGl0bGUsIC5wb3BvdmVyLXRpdGxlIDpub3QoLmNsb3NlKScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgaWYgKGUuY3VycmVudFRhcmdldCA9PSB0aGlzKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoICYmICEkKGUudGFyZ2V0KS5oYXNDbGFzcygnY2xvc2UnKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJy5kaXZpZGVyLCAuZHJvcGRvd24taGVhZGVyJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLnBvcG92ZXItdGl0bGUgLmNsb3NlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGJ1dHRvbi5jbGljaygpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJHNlYXJjaGJveC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLmFjdGlvbnMtYnRuJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcygnYnMtc2VsZWN0LWFsbCcpKSB7XHJcbiAgICAgICAgICB0aGF0LnNlbGVjdEFsbCgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LmRlc2VsZWN0QWxsKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuY2hhbmdlKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LnJlbmRlcihmYWxzZSk7XHJcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdjaGFuZ2VkLmJzLnNlbGVjdCcsIGNoYW5nZWRfYXJndW1lbnRzKTtcclxuICAgICAgICBjaGFuZ2VkX2FyZ3VtZW50cyA9IG51bGw7XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBsaXZlU2VhcmNoTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJG5vX3Jlc3VsdHMgPSAkKCc8bGkgY2xhc3M9XCJuby1yZXN1bHRzXCI+PC9saT4nKTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2suZHJvcGRvd24uZGF0YS1hcGknLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgaWYgKCEhdGhhdC4kc2VhcmNoYm94LnZhbCgpKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3gudmFsKCcnKTtcclxuICAgICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICBpZiAoISEkbm9fcmVzdWx0cy5wYXJlbnQoKS5sZW5ndGgpICRub19yZXN1bHRzLnJlbW92ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIXRoYXQubXVsdGlwbGUpIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5hZGRDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICB9LCAxMCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kc2VhcmNoYm94Lm9uKCdjbGljay5kcm9wZG93bi5kYXRhLWFwaSBmb2N1cy5kcm9wZG93bi5kYXRhLWFwaSB0b3VjaGVuZC5kcm9wZG93bi5kYXRhLWFwaScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRzZWFyY2hib3gub24oJ2lucHV0IHByb3BlcnR5Y2hhbmdlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgdGhhdC4kbGlzLmZpbHRlcignLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAkbm9fcmVzdWx0cy5yZW1vdmUoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoYXQuJHNlYXJjaGJveC52YWwoKSkge1xyXG4gICAgICAgICAgdmFyICRzZWFyY2hCYXNlID0gdGhhdC4kbGlzLm5vdCgnLmlzLWhpZGRlbiwgLmRpdmlkZXIsIC5kcm9wZG93bi1oZWFkZXInKSxcclxuICAgICAgICAgICAgICAkaGlkZUl0ZW1zO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplKSB7XHJcbiAgICAgICAgICAgICRoaWRlSXRlbXMgPSAkc2VhcmNoQmFzZS5ub3QoJzphJyArIHRoYXQuX3NlYXJjaFN0eWxlKCkgKyAnKFwiJyArIG5vcm1hbGl6ZVRvQmFzZSh0aGF0LiRzZWFyY2hib3gudmFsKCkpICsgJ1wiKScpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcyA9ICRzZWFyY2hCYXNlLm5vdCgnOicgKyB0aGF0Ll9zZWFyY2hTdHlsZSgpICsgJyhcIicgKyB0aGF0LiRzZWFyY2hib3gudmFsKCkgKyAnXCIpJyk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCRoaWRlSXRlbXMubGVuZ3RoID09PSAkc2VhcmNoQmFzZS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgJG5vX3Jlc3VsdHMuaHRtbCh0aGF0Lm9wdGlvbnMubm9uZVJlc3VsdHNUZXh0LnJlcGxhY2UoJ3swfScsICdcIicgKyBodG1sRXNjYXBlKHRoYXQuJHNlYXJjaGJveC52YWwoKSkgKyAnXCInKSk7XHJcbiAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5hcHBlbmQoJG5vX3Jlc3VsdHMpO1xyXG4gICAgICAgICAgICB0aGF0LiRsaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcy5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICB2YXIgJGxpc1Zpc2libGUgPSB0aGF0LiRsaXMubm90KCcuaGlkZGVuJyksXHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXY7XHJcblxyXG4gICAgICAgICAgICAvLyBoaWRlIGRpdmlkZXIgaWYgZmlyc3Qgb3IgbGFzdCB2aXNpYmxlLCBvciBpZiBmb2xsb3dlZCBieSBhbm90aGVyIGRpdmlkZXJcclxuICAgICAgICAgICAgJGxpc1Zpc2libGUuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICAgICAgICBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2RpdmlkZXInKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZERpdiA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICR0aGlzLmFkZENsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICAgICAgICAgICRmb3VuZERpdiA9ICR0aGlzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLWhlYWRlcicpICYmICRsaXNWaXNpYmxlLmVxKGluZGV4ICsgMSkuZGF0YSgnb3B0Z3JvdXAnKSAhPT0gJHRoaXMuZGF0YSgnb3B0Z3JvdXAnKSkge1xyXG4gICAgICAgICAgICAgICAgJHRoaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXYgPSBudWxsO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICAkc2VhcmNoQmFzZS5ub3QoJy5oaWRkZW4nKS5maXJzdCgpLmFkZENsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLnNjcm9sbFRvcCgwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBfc2VhcmNoU3R5bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHN0eWxlcyA9IHtcclxuICAgICAgICBiZWdpbnM6ICdpYmVnaW5zJyxcclxuICAgICAgICBzdGFydHNXaXRoOiAnaWJlZ2lucydcclxuICAgICAgfTtcclxuXHJcbiAgICAgIHJldHVybiBzdHlsZXNbdGhpcy5vcHRpb25zLmxpdmVTZWFyY2hTdHlsZV0gfHwgJ2ljb250YWlucyc7XHJcbiAgICB9LFxyXG5cclxuICAgIHZhbDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC52YWwodmFsdWUpO1xyXG4gICAgICAgIHRoaXMucmVuZGVyKCk7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50LnZhbCgpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGNoYW5nZUFsbDogZnVuY3Rpb24gKHN0YXR1cykge1xyXG4gICAgICBpZiAoIXRoaXMubXVsdGlwbGUpIHJldHVybjtcclxuICAgICAgaWYgKHR5cGVvZiBzdGF0dXMgPT09ICd1bmRlZmluZWQnKSBzdGF0dXMgPSB0cnVlO1xyXG5cclxuICAgICAgdGhpcy5maW5kTGlzKCk7XHJcblxyXG4gICAgICB2YXIgJG9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgJGxpc1Zpc2libGUgPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlciwgLmRyb3Bkb3duLWhlYWRlciwgLmRpc2FibGVkLCAuaGlkZGVuJyksXHJcbiAgICAgICAgICBsaXNWaXNMZW4gPSAkbGlzVmlzaWJsZS5sZW5ndGgsXHJcbiAgICAgICAgICBzZWxlY3RlZE9wdGlvbnMgPSBbXTtcclxuICAgICAgICAgIFxyXG4gICAgICBpZiAoc3RhdHVzKSB7XHJcbiAgICAgICAgaWYgKCRsaXNWaXNpYmxlLmZpbHRlcignLnNlbGVjdGVkJykubGVuZ3RoID09PSAkbGlzVmlzaWJsZS5sZW5ndGgpIHJldHVybjtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAoJGxpc1Zpc2libGUuZmlsdGVyKCcuc2VsZWN0ZWQnKS5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICAgICAgXHJcbiAgICAgICRsaXNWaXNpYmxlLnRvZ2dsZUNsYXNzKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc1Zpc0xlbjsgaSsrKSB7XHJcbiAgICAgICAgdmFyIG9yaWdJbmRleCA9ICRsaXNWaXNpYmxlW2ldLmdldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC1pbmRleCcpO1xyXG4gICAgICAgIHNlbGVjdGVkT3B0aW9uc1tzZWxlY3RlZE9wdGlvbnMubGVuZ3RoXSA9ICRvcHRpb25zLmVxKG9yaWdJbmRleClbMF07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICQoc2VsZWN0ZWRPcHRpb25zKS5wcm9wKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICB0aGlzLnJlbmRlcihmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50XHJcbiAgICAgICAgLnRyaWdnZXJOYXRpdmUoJ2NoYW5nZScpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RBbGw6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY2hhbmdlQWxsKHRydWUpO1xyXG4gICAgfSxcclxuXHJcbiAgICBkZXNlbGVjdEFsbDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5jaGFuZ2VBbGwoZmFsc2UpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0b2dnbGU6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcclxuXHJcbiAgICAgIGlmIChlKSBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLnRyaWdnZXIoJ2NsaWNrJyk7XHJcbiAgICB9LFxyXG5cclxuICAgIGtleWRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuaXMoJ2lucHV0JykgPyAkdGhpcy5wYXJlbnQoKS5wYXJlbnQoKSA6ICR0aGlzLnBhcmVudCgpLFxyXG4gICAgICAgICAgJGl0ZW1zLFxyXG4gICAgICAgICAgdGhhdCA9ICRwYXJlbnQuZGF0YSgndGhpcycpLFxyXG4gICAgICAgICAgaW5kZXgsXHJcbiAgICAgICAgICBwcmV2SW5kZXgsXHJcbiAgICAgICAgICBpc0FjdGl2ZSxcclxuICAgICAgICAgIHNlbGVjdG9yID0gJzpub3QoLmRpc2FibGVkLCAuaGlkZGVuLCAuZHJvcGRvd24taGVhZGVyLCAuZGl2aWRlciknLFxyXG4gICAgICAgICAga2V5Q29kZU1hcCA9IHtcclxuICAgICAgICAgICAgMzI6ICcgJyxcclxuICAgICAgICAgICAgNDg6ICcwJyxcclxuICAgICAgICAgICAgNDk6ICcxJyxcclxuICAgICAgICAgICAgNTA6ICcyJyxcclxuICAgICAgICAgICAgNTE6ICczJyxcclxuICAgICAgICAgICAgNTI6ICc0JyxcclxuICAgICAgICAgICAgNTM6ICc1JyxcclxuICAgICAgICAgICAgNTQ6ICc2JyxcclxuICAgICAgICAgICAgNTU6ICc3JyxcclxuICAgICAgICAgICAgNTY6ICc4JyxcclxuICAgICAgICAgICAgNTc6ICc5JyxcclxuICAgICAgICAgICAgNTk6ICc7JyxcclxuICAgICAgICAgICAgNjU6ICdhJyxcclxuICAgICAgICAgICAgNjY6ICdiJyxcclxuICAgICAgICAgICAgNjc6ICdjJyxcclxuICAgICAgICAgICAgNjg6ICdkJyxcclxuICAgICAgICAgICAgNjk6ICdlJyxcclxuICAgICAgICAgICAgNzA6ICdmJyxcclxuICAgICAgICAgICAgNzE6ICdnJyxcclxuICAgICAgICAgICAgNzI6ICdoJyxcclxuICAgICAgICAgICAgNzM6ICdpJyxcclxuICAgICAgICAgICAgNzQ6ICdqJyxcclxuICAgICAgICAgICAgNzU6ICdrJyxcclxuICAgICAgICAgICAgNzY6ICdsJyxcclxuICAgICAgICAgICAgNzc6ICdtJyxcclxuICAgICAgICAgICAgNzg6ICduJyxcclxuICAgICAgICAgICAgNzk6ICdvJyxcclxuICAgICAgICAgICAgODA6ICdwJyxcclxuICAgICAgICAgICAgODE6ICdxJyxcclxuICAgICAgICAgICAgODI6ICdyJyxcclxuICAgICAgICAgICAgODM6ICdzJyxcclxuICAgICAgICAgICAgODQ6ICd0JyxcclxuICAgICAgICAgICAgODU6ICd1JyxcclxuICAgICAgICAgICAgODY6ICd2JyxcclxuICAgICAgICAgICAgODc6ICd3JyxcclxuICAgICAgICAgICAgODg6ICd4JyxcclxuICAgICAgICAgICAgODk6ICd5JyxcclxuICAgICAgICAgICAgOTA6ICd6JyxcclxuICAgICAgICAgICAgOTY6ICcwJyxcclxuICAgICAgICAgICAgOTc6ICcxJyxcclxuICAgICAgICAgICAgOTg6ICcyJyxcclxuICAgICAgICAgICAgOTk6ICczJyxcclxuICAgICAgICAgICAgMTAwOiAnNCcsXHJcbiAgICAgICAgICAgIDEwMTogJzUnLFxyXG4gICAgICAgICAgICAxMDI6ICc2JyxcclxuICAgICAgICAgICAgMTAzOiAnNycsXHJcbiAgICAgICAgICAgIDEwNDogJzgnLFxyXG4gICAgICAgICAgICAxMDU6ICc5J1xyXG4gICAgICAgICAgfTtcclxuXHJcblxyXG4gICAgICBpc0FjdGl2ZSA9IHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ29wZW4nKTtcclxuXHJcbiAgICAgIGlmICghaXNBY3RpdmUgJiYgKGUua2V5Q29kZSA+PSA0OCAmJiBlLmtleUNvZGUgPD0gNTcgfHwgZS5rZXlDb2RlID49IDk2ICYmIGUua2V5Q29kZSA8PSAxMDUgfHwgZS5rZXlDb2RlID49IDY1ICYmIGUua2V5Q29kZSA8PSA5MCkpIHtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgIHRoYXQuc2V0U2l6ZSgpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5hZGRDbGFzcygnb3BlbicpO1xyXG4gICAgICAgICAgaXNBY3RpdmUgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24udHJpZ2dlcignY2xpY2snKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICBpZiAoLyheOSR8MjcpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmIGlzQWN0aXZlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmNsaWNrKCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICgvKDM4fDQwKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgIGlmICghJGl0ZW1zLmxlbmd0aCkgcmV0dXJuO1xyXG5cclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICBpbmRleCA9ICRpdGVtcy5pbmRleCgkaXRlbXMuZmluZCgnYScpLmZpbHRlcignOmZvY3VzJykucGFyZW50KCkpO1xyXG5cdCAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaW5kZXggPSAkaXRlbXMuaW5kZXgoJGl0ZW1zLmZpbHRlcignLmFjdGl2ZScpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHByZXZJbmRleCA9IHRoYXQuJG1lbnVJbm5lci5kYXRhKCdwcmV2SW5kZXgnKTtcclxuXHJcbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAzOCkge1xyXG4gICAgICAgICAgaWYgKCh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCB8fCBpbmRleCA9PSBwcmV2SW5kZXgpICYmIGluZGV4ICE9IC0xKSBpbmRleC0tO1xyXG4gICAgICAgICAgaWYgKGluZGV4IDwgMCkgaW5kZXggKz0gJGl0ZW1zLmxlbmd0aDtcclxuICAgICAgICB9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSA0MCkge1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoIHx8IGluZGV4ID09IHByZXZJbmRleCkgaW5kZXgrKztcclxuICAgICAgICAgIGluZGV4ID0gaW5kZXggJSAkaXRlbXMubGVuZ3RoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmRhdGEoJ3ByZXZJbmRleCcsIGluZGV4KTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgJGl0ZW1zLmVxKGluZGV4KS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIGlmICghJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLXRvZ2dsZScpKSB7XHJcbiAgICAgICAgICAgICRpdGVtcy5yZW1vdmVDbGFzcygnYWN0aXZlJykuZXEoaW5kZXgpLmFkZENsYXNzKCdhY3RpdmUnKS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICR0aGlzLmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfSBlbHNlIGlmICghJHRoaXMuaXMoJ2lucHV0JykpIHtcclxuICAgICAgICB2YXIga2V5SW5kZXggPSBbXSxcclxuICAgICAgICAgICAgY291bnQsXHJcbiAgICAgICAgICAgIHByZXZLZXk7XHJcblxyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgICRpdGVtcy5lYWNoKGZ1bmN0aW9uIChpKSB7XHJcbiAgICAgICAgICBpZiAoJC50cmltKCQodGhpcykuY2hpbGRyZW4oJ2EnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpID09IGtleUNvZGVNYXBbZS5rZXlDb2RlXSkge1xyXG4gICAgICAgICAgICBrZXlJbmRleC5wdXNoKGkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBjb3VudCA9ICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50Jyk7XHJcbiAgICAgICAgY291bnQrKztcclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIGNvdW50KTtcclxuXHJcbiAgICAgICAgcHJldktleSA9ICQudHJpbSgkKCc6Zm9jdXMnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpO1xyXG5cclxuICAgICAgICBpZiAocHJldktleSAhPSBrZXlDb2RlTWFwW2Uua2V5Q29kZV0pIHtcclxuICAgICAgICAgIGNvdW50ID0gMTtcclxuICAgICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgY291bnQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoY291bnQgPj0ga2V5SW5kZXgubGVuZ3RoKSB7XHJcbiAgICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICAgICAgaWYgKGNvdW50ID4ga2V5SW5kZXgubGVuZ3RoKSBjb3VudCA9IDE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAkaXRlbXMuZXEoa2V5SW5kZXhbY291bnQgLSAxXSkuY2hpbGRyZW4oJ2EnKS5mb2N1cygpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZWxlY3QgZm9jdXNlZCBvcHRpb24gaWYgXCJFbnRlclwiLCBcIlNwYWNlYmFyXCIgb3IgXCJUYWJcIiAod2hlbiBzZWxlY3RPblRhYiBpcyB0cnVlKSBhcmUgcHJlc3NlZCBpbnNpZGUgdGhlIG1lbnUuXHJcbiAgICAgIGlmICgoLygxM3wzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgfHwgKC8oXjkkKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiB0aGF0Lm9wdGlvbnMuc2VsZWN0T25UYWIpKSAmJiBpc0FjdGl2ZSkge1xyXG4gICAgICAgIGlmICghLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkpIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICB2YXIgZWxlbSA9ICQoJzpmb2N1cycpO1xyXG4gICAgICAgICAgZWxlbS5jbGljaygpO1xyXG4gICAgICAgICAgLy8gQnJpbmcgYmFjayBmb2N1cyBmb3IgbXVsdGlzZWxlY3RzXHJcbiAgICAgICAgICBlbGVtLmZvY3VzKCk7XHJcbiAgICAgICAgICAvLyBQcmV2ZW50IHNjcmVlbiBmcm9tIHNjcm9sbGluZyBpZiB0aGUgdXNlciBoaXQgdGhlIHNwYWNlYmFyXHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAvLyBGaXhlcyBzcGFjZWJhciBzZWxlY3Rpb24gb2YgZHJvcGRvd24gaXRlbXMgaW4gRkYgJiBJRVxyXG4gICAgICAgICAgJChkb2N1bWVudCkuZGF0YSgnc3BhY2VTZWxlY3QnLCB0cnVlKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCEvKDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUgYScpLmNsaWNrKCk7XHJcbiAgICAgICAgICAkdGhpcy5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoKC8oXjkkfDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiBpc0FjdGl2ZSAmJiAodGhhdC5tdWx0aXBsZSB8fCB0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkpIHx8ICgvKDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiAhaXNBY3RpdmUpKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5yZW1vdmVDbGFzcygnb3BlbicpO1xyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSB0aGF0LiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdvcGVuJyk7XHJcbiAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgbW9iaWxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ21vYmlsZS1kZXZpY2UnKTtcclxuICAgIH0sXHJcblxyXG4gICAgcmVmcmVzaDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRsaXMgPSBudWxsO1xyXG4gICAgICB0aGlzLmxpT2JqID0ge307XHJcbiAgICAgIHRoaXMucmVsb2FkTGkoKTtcclxuICAgICAgdGhpcy5yZW5kZXIoKTtcclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMubGlIZWlnaHQodHJ1ZSk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy4kbGlzKSB0aGlzLiRzZWFyY2hib3gudHJpZ2dlcigncHJvcGVydHljaGFuZ2UnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcigncmVmcmVzaGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgfSxcclxuXHJcbiAgICBoaWRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuaGlkZSgpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzaG93OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuc2hvdygpO1xyXG4gICAgfSxcclxuXHJcbiAgICByZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmUoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmUoKTtcclxuICAgIH0sXHJcblxyXG4gICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50LmJlZm9yZSh0aGlzLiRlbGVtZW50KS5yZW1vdmUoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLiRic0NvbnRhaW5lcikge1xyXG4gICAgICAgIHRoaXMuJGJzQ29udGFpbmVyLnJlbW92ZSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuJG1lbnUucmVtb3ZlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnRcclxuICAgICAgICAub2ZmKCcuYnMuc2VsZWN0JylcclxuICAgICAgICAucmVtb3ZlRGF0YSgnc2VsZWN0cGlja2VyJylcclxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4gc2VsZWN0cGlja2VyJyk7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIFBMVUdJTiBERUZJTklUSU9OXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xyXG4gICAgLy8gZ2V0IHRoZSBhcmdzIG9mIHRoZSBvdXRlciBmdW5jdGlvbi4uXHJcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcclxuICAgIC8vIFRoZSBhcmd1bWVudHMgb2YgdGhlIGZ1bmN0aW9uIGFyZSBleHBsaWNpdGx5IHJlLWRlZmluZWQgZnJvbSB0aGUgYXJndW1lbnQgbGlzdCwgYmVjYXVzZSB0aGUgc2hpZnQgY2F1c2VzIHRoZW1cclxuICAgIC8vIHRvIGdldCBsb3N0L2NvcnJ1cHRlZCBpbiBhbmRyb2lkIDIuMyBhbmQgSUU5ICM3MTUgIzc3NVxyXG4gICAgdmFyIF9vcHRpb24gPSBvcHRpb247XHJcblxyXG4gICAgW10uc2hpZnQuYXBwbHkoYXJncyk7XHJcblxyXG4gICAgdmFyIHZhbHVlO1xyXG4gICAgdmFyIGNoYWluID0gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcclxuICAgICAgaWYgKCR0aGlzLmlzKCdzZWxlY3QnKSkge1xyXG4gICAgICAgIHZhciBkYXRhID0gJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJyksXHJcbiAgICAgICAgICAgIG9wdGlvbnMgPSB0eXBlb2YgX29wdGlvbiA9PSAnb2JqZWN0JyAmJiBfb3B0aW9uO1xyXG5cclxuICAgICAgICBpZiAoIWRhdGEpIHtcclxuICAgICAgICAgIHZhciBjb25maWcgPSAkLmV4dGVuZCh7fSwgU2VsZWN0cGlja2VyLkRFRkFVTFRTLCAkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyB8fCB7fSwgJHRoaXMuZGF0YSgpLCBvcHRpb25zKTtcclxuICAgICAgICAgIGNvbmZpZy50ZW1wbGF0ZSA9ICQuZXh0ZW5kKHt9LCBTZWxlY3RwaWNrZXIuREVGQVVMVFMudGVtcGxhdGUsICgkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyA/ICQuZm4uc2VsZWN0cGlja2VyLmRlZmF1bHRzLnRlbXBsYXRlIDoge30pLCAkdGhpcy5kYXRhKCkudGVtcGxhdGUsIG9wdGlvbnMudGVtcGxhdGUpO1xyXG4gICAgICAgICAgJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJywgKGRhdGEgPSBuZXcgU2VsZWN0cGlja2VyKHRoaXMsIGNvbmZpZykpKTtcclxuICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMpIHtcclxuICAgICAgICAgIGZvciAodmFyIGkgaW4gb3B0aW9ucykge1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG4gICAgICAgICAgICAgIGRhdGEub3B0aW9uc1tpXSA9IG9wdGlvbnNbaV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YgX29wdGlvbiA9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgaWYgKGRhdGFbX29wdGlvbl0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGFbX29wdGlvbl0uYXBwbHkoZGF0YSwgYXJncyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGEub3B0aW9uc1tfb3B0aW9uXTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkQXNzaWdubWVudFxyXG4gICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gY2hhaW47XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgb2xkID0gJC5mbi5zZWxlY3RwaWNrZXI7XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIgPSBQbHVnaW47XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIuQ29uc3RydWN0b3IgPSBTZWxlY3RwaWNrZXI7XHJcblxyXG4gIC8vIFNFTEVDVFBJQ0tFUiBOTyBDT05GTElDVFxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gICQuZm4uc2VsZWN0cGlja2VyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAkLmZuLnNlbGVjdHBpY2tlciA9IG9sZDtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH07XHJcblxyXG4gICQoZG9jdW1lbnQpXHJcbiAgICAgIC5kYXRhKCdrZXljb3VudCcsIDApXHJcbiAgICAgIC5vbigna2V5ZG93bi5icy5zZWxlY3QnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgU2VsZWN0cGlja2VyLnByb3RvdHlwZS5rZXlkb3duKVxyXG4gICAgICAub24oJ2ZvY3VzaW4ubW9kYWwnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIERBVEEtQVBJXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XHJcbiAgJCh3aW5kb3cpLm9uKCdsb2FkLmJzLnNlbGVjdC5kYXRhLWFwaScsIGZ1bmN0aW9uICgpIHtcclxuICAgICQoJy5zZWxlY3RwaWNrZXInKS5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICRzZWxlY3RwaWNrZXIgPSAkKHRoaXMpO1xyXG4gICAgICBQbHVnaW4uY2FsbCgkc2VsZWN0cGlja2VyLCAkc2VsZWN0cGlja2VyLmRhdGEoKSk7XHJcbiAgICB9KVxyXG4gIH0pO1xyXG59KShqUXVlcnkpO1xyXG5cblxufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2pzL2Jvb3RzdHJhcC1zZWxlY3QuanNcbi8vIG1vZHVsZSBpZCA9IDE1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwIChwbHVnaW4pOiB2YWxpZGF0b3IuanMgdjAuMTEuOVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYgQ2luYSBTYWZmYXJ5LlxuICogTWFkZSBieSBAMTAwMGh6IGluIHRoZSBzdHlsZSBvZiBCb290c3RyYXAgMyBlcmEgQGZhdFxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAqIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAqIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuICogYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4gKiBUSEUgU09GVFdBUkUuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFZBTElEQVRPUiBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gZ2V0VmFsdWUoJGVsKSB7XG4gICAgcmV0dXJuICRlbC5pcygnW3R5cGU9XCJjaGVja2JveFwiXScpID8gJGVsLnByb3AoJ2NoZWNrZWQnKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6XG4gICAgICAgICAgICRlbC5pcygnW3R5cGU9XCJyYWRpb1wiXScpICAgID8gISEkKCdbbmFtZT1cIicgKyAkZWwuYXR0cignbmFtZScpICsgJ1wiXTpjaGVja2VkJykubGVuZ3RoIDpcbiAgICAgICAgICAgJGVsLmlzKCdzZWxlY3RbbXVsdGlwbGVdJykgID8gKCRlbC52YWwoKSB8fCBbXSkubGVuZ3RoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbC52YWwoKVxuICB9XG5cbiAgdmFyIFZhbGlkYXRvciA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zICAgID0gb3B0aW9uc1xuICAgIHRoaXMudmFsaWRhdG9ycyA9ICQuZXh0ZW5kKHt9LCBWYWxpZGF0b3IuVkFMSURBVE9SUywgb3B0aW9ucy5jdXN0b20pXG4gICAgdGhpcy4kZWxlbWVudCAgID0gJChlbGVtZW50KVxuICAgIHRoaXMuJGJ0biAgICAgICA9ICQoJ2J1dHRvblt0eXBlPVwic3VibWl0XCJdLCBpbnB1dFt0eXBlPVwic3VibWl0XCJdJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoJ1tmb3JtPVwiJyArIHRoaXMuJGVsZW1lbnQuYXR0cignaWQnKSArICdcIl0nKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFkZCh0aGlzLiRlbGVtZW50LmZpbmQoJ2lucHV0W3R5cGU9XCJzdWJtaXRcIl0sIGJ1dHRvblt0eXBlPVwic3VibWl0XCJdJykpXG5cbiAgICB0aGlzLnVwZGF0ZSgpXG5cbiAgICB0aGlzLiRlbGVtZW50Lm9uKCdpbnB1dC5icy52YWxpZGF0b3IgY2hhbmdlLmJzLnZhbGlkYXRvciBmb2N1c291dC5icy52YWxpZGF0b3InLCAkLnByb3h5KHRoaXMub25JbnB1dCwgdGhpcykpXG4gICAgdGhpcy4kZWxlbWVudC5vbignc3VibWl0LmJzLnZhbGlkYXRvcicsICQucHJveHkodGhpcy5vblN1Ym1pdCwgdGhpcykpXG4gICAgdGhpcy4kZWxlbWVudC5vbigncmVzZXQuYnMudmFsaWRhdG9yJywgJC5wcm94eSh0aGlzLnJlc2V0LCB0aGlzKSlcblxuICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtbWF0Y2hdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgID0gJCh0aGlzKVxuICAgICAgdmFyIHRhcmdldCA9ICR0aGlzLmF0dHIoJ2RhdGEtbWF0Y2gnKVxuXG4gICAgICAkKHRhcmdldCkub24oJ2lucHV0LmJzLnZhbGlkYXRvcicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGdldFZhbHVlKCR0aGlzKSAmJiAkdGhpcy50cmlnZ2VyKCdpbnB1dC5icy52YWxpZGF0b3InKVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgLy8gcnVuIHZhbGlkYXRvcnMgZm9yIGZpZWxkcyB3aXRoIHZhbHVlcywgYnV0IGRvbid0IGNsb2JiZXIgc2VydmVyLXNpZGUgZXJyb3JzXG4gICAgdGhpcy4kaW5wdXRzLmZpbHRlcihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZ2V0VmFsdWUoJCh0aGlzKSkgJiYgISQodGhpcykuY2xvc2VzdCgnLmhhcy1lcnJvcicpLmxlbmd0aFxuICAgIH0pLnRyaWdnZXIoJ2ZvY3Vzb3V0JylcblxuICAgIHRoaXMuJGVsZW1lbnQuYXR0cignbm92YWxpZGF0ZScsIHRydWUpIC8vIGRpc2FibGUgYXV0b21hdGljIG5hdGl2ZSB2YWxpZGF0aW9uXG4gIH1cblxuICBWYWxpZGF0b3IuVkVSU0lPTiA9ICcwLjExLjknXG5cbiAgVmFsaWRhdG9yLklOUFVUX1NFTEVDVE9SID0gJzppbnB1dDpub3QoW3R5cGU9XCJoaWRkZW5cIl0sIFt0eXBlPVwic3VibWl0XCJdLCBbdHlwZT1cInJlc2V0XCJdLCBidXR0b24pJ1xuXG4gIFZhbGlkYXRvci5GT0NVU19PRkZTRVQgPSAyMFxuXG4gIFZhbGlkYXRvci5ERUZBVUxUUyA9IHtcbiAgICBkZWxheTogNTAwLFxuICAgIGh0bWw6IGZhbHNlLFxuICAgIGRpc2FibGU6IHRydWUsXG4gICAgZm9jdXM6IHRydWUsXG4gICAgY3VzdG9tOiB7fSxcbiAgICBlcnJvcnM6IHtcbiAgICAgIG1hdGNoOiAnRG9lcyBub3QgbWF0Y2gnLFxuICAgICAgbWlubGVuZ3RoOiAnTm90IGxvbmcgZW5vdWdoJ1xuICAgIH0sXG4gICAgZmVlZGJhY2s6IHtcbiAgICAgIHN1Y2Nlc3M6ICdnbHlwaGljb24tb2snLFxuICAgICAgZXJyb3I6ICdnbHlwaGljb24tcmVtb3ZlJ1xuICAgIH1cbiAgfVxuXG4gIFZhbGlkYXRvci5WQUxJREFUT1JTID0ge1xuICAgICduYXRpdmUnOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICB2YXIgZWwgPSAkZWxbMF1cbiAgICAgIGlmIChlbC5jaGVja1ZhbGlkaXR5KSB7XG4gICAgICAgIHJldHVybiAhZWwuY2hlY2tWYWxpZGl0eSgpICYmICFlbC52YWxpZGl0eS52YWxpZCAmJiAoZWwudmFsaWRhdGlvbk1lc3NhZ2UgfHwgXCJlcnJvciFcIilcbiAgICAgIH1cbiAgICB9LFxuICAgICdtYXRjaCc6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgIHZhciB0YXJnZXQgPSAkZWwuYXR0cignZGF0YS1tYXRjaCcpXG4gICAgICByZXR1cm4gJGVsLnZhbCgpICE9PSAkKHRhcmdldCkudmFsKCkgJiYgVmFsaWRhdG9yLkRFRkFVTFRTLmVycm9ycy5tYXRjaFxuICAgIH0sXG4gICAgJ21pbmxlbmd0aCc6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgIHZhciBtaW5sZW5ndGggPSAkZWwuYXR0cignZGF0YS1taW5sZW5ndGgnKVxuICAgICAgcmV0dXJuICRlbC52YWwoKS5sZW5ndGggPCBtaW5sZW5ndGggJiYgVmFsaWRhdG9yLkRFRkFVTFRTLmVycm9ycy5taW5sZW5ndGhcbiAgICB9XG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXNcblxuICAgIHRoaXMuJGlucHV0cyA9IHRoaXMuJGVsZW1lbnQuZmluZChWYWxpZGF0b3IuSU5QVVRfU0VMRUNUT1IpXG4gICAgICAuYWRkKHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtdmFsaWRhdGU9XCJ0cnVlXCJdJykpXG4gICAgICAubm90KHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtdmFsaWRhdGU9XCJmYWxzZVwiXScpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHsgc2VsZi5jbGVhckVycm9ycygkKHRoaXMpKSB9KVxuICAgICAgKVxuXG4gICAgdGhpcy50b2dnbGVTdWJtaXQoKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUub25JbnB1dCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIHNlbGYgICAgICAgID0gdGhpc1xuICAgIHZhciAkZWwgICAgICAgICA9ICQoZS50YXJnZXQpXG4gICAgdmFyIGRlZmVyRXJyb3JzID0gZS50eXBlICE9PSAnZm9jdXNvdXQnXG5cbiAgICBpZiAoIXRoaXMuJGlucHV0cy5pcygkZWwpKSByZXR1cm5cblxuICAgIHRoaXMudmFsaWRhdGVJbnB1dCgkZWwsIGRlZmVyRXJyb3JzKS5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYudG9nZ2xlU3VibWl0KClcbiAgICB9KVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS52YWxpZGF0ZUlucHV0ID0gZnVuY3Rpb24gKCRlbCwgZGVmZXJFcnJvcnMpIHtcbiAgICB2YXIgdmFsdWUgICAgICA9IGdldFZhbHVlKCRlbClcbiAgICB2YXIgcHJldkVycm9ycyA9ICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJylcblxuICAgIGlmICgkZWwuaXMoJ1t0eXBlPVwicmFkaW9cIl0nKSkgJGVsID0gdGhpcy4kZWxlbWVudC5maW5kKCdpbnB1dFtuYW1lPVwiJyArICRlbC5hdHRyKCduYW1lJykgKyAnXCJdJylcblxuICAgIHZhciBlID0gJC5FdmVudCgndmFsaWRhdGUuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXX0pXG4gICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKGUpXG4gICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgICByZXR1cm4gdGhpcy5ydW5WYWxpZGF0b3JzKCRlbCkuZG9uZShmdW5jdGlvbiAoZXJyb3JzKSB7XG4gICAgICAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycsIGVycm9ycylcblxuICAgICAgZXJyb3JzLmxlbmd0aFxuICAgICAgICA/IGRlZmVyRXJyb3JzID8gc2VsZi5kZWZlcigkZWwsIHNlbGYuc2hvd0Vycm9ycykgOiBzZWxmLnNob3dFcnJvcnMoJGVsKVxuICAgICAgICA6IHNlbGYuY2xlYXJFcnJvcnMoJGVsKVxuXG4gICAgICBpZiAoIXByZXZFcnJvcnMgfHwgZXJyb3JzLnRvU3RyaW5nKCkgIT09IHByZXZFcnJvcnMudG9TdHJpbmcoKSkge1xuICAgICAgICBlID0gZXJyb3JzLmxlbmd0aFxuICAgICAgICAgID8gJC5FdmVudCgnaW52YWxpZC5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdLCBkZXRhaWw6IGVycm9yc30pXG4gICAgICAgICAgOiAkLkV2ZW50KCd2YWxpZC5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdLCBkZXRhaWw6IHByZXZFcnJvcnN9KVxuXG4gICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcihlKVxuICAgICAgfVxuXG4gICAgICBzZWxmLnRvZ2dsZVN1Ym1pdCgpXG5cbiAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcigkLkV2ZW50KCd2YWxpZGF0ZWQuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXX0pKVxuICAgIH0pXG4gIH1cblxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUucnVuVmFsaWRhdG9ycyA9IGZ1bmN0aW9uICgkZWwpIHtcbiAgICB2YXIgZXJyb3JzICAgPSBbXVxuICAgIHZhciBkZWZlcnJlZCA9ICQuRGVmZXJyZWQoKVxuXG4gICAgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCcpICYmICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZGVmZXJyZWQnKS5yZWplY3QoKVxuICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZGVmZXJyZWQnLCBkZWZlcnJlZClcblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkYXRvclNwZWNpZmljRXJyb3Ioa2V5KSB7XG4gICAgICByZXR1cm4gJGVsLmF0dHIoJ2RhdGEtJyArIGtleSArICctZXJyb3InKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkaXR5U3RhdGVFcnJvcigpIHtcbiAgICAgIHZhciB2YWxpZGl0eSA9ICRlbFswXS52YWxpZGl0eVxuICAgICAgcmV0dXJuIHZhbGlkaXR5LnR5cGVNaXNtYXRjaCAgICA/ICRlbC5hdHRyKCdkYXRhLXR5cGUtZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnBhdHRlcm5NaXNtYXRjaCA/ICRlbC5hdHRyKCdkYXRhLXBhdHRlcm4tZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnN0ZXBNaXNtYXRjaCAgICA/ICRlbC5hdHRyKCdkYXRhLXN0ZXAtZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnJhbmdlT3ZlcmZsb3cgICA/ICRlbC5hdHRyKCdkYXRhLW1heC1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkucmFuZ2VVbmRlcmZsb3cgID8gJGVsLmF0dHIoJ2RhdGEtbWluLWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS52YWx1ZU1pc3NpbmcgICAgPyAkZWwuYXR0cignZGF0YS1yZXF1aXJlZC1lcnJvcicpXG4gICAgICAgICAgIDogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVsbFxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEdlbmVyaWNFcnJvcigpIHtcbiAgICAgIHJldHVybiAkZWwuYXR0cignZGF0YS1lcnJvcicpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGtleSkge1xuICAgICAgcmV0dXJuIGdldFZhbGlkYXRvclNwZWNpZmljRXJyb3Ioa2V5KVxuICAgICAgICAgIHx8IGdldFZhbGlkaXR5U3RhdGVFcnJvcigpXG4gICAgICAgICAgfHwgZ2V0R2VuZXJpY0Vycm9yKClcbiAgICB9XG5cbiAgICAkLmVhY2godGhpcy52YWxpZGF0b3JzLCAkLnByb3h5KGZ1bmN0aW9uIChrZXksIHZhbGlkYXRvcikge1xuICAgICAgdmFyIGVycm9yID0gbnVsbFxuICAgICAgaWYgKChnZXRWYWx1ZSgkZWwpIHx8ICRlbC5hdHRyKCdyZXF1aXJlZCcpKSAmJlxuICAgICAgICAgICgkZWwuYXR0cignZGF0YS0nICsga2V5KSAhPT0gdW5kZWZpbmVkIHx8IGtleSA9PSAnbmF0aXZlJykgJiZcbiAgICAgICAgICAoZXJyb3IgPSB2YWxpZGF0b3IuY2FsbCh0aGlzLCAkZWwpKSkge1xuICAgICAgICAgZXJyb3IgPSBnZXRFcnJvck1lc3NhZ2Uoa2V5KSB8fCBlcnJvclxuICAgICAgICAhfmVycm9ycy5pbmRleE9mKGVycm9yKSAmJiBlcnJvcnMucHVzaChlcnJvcilcbiAgICAgIH1cbiAgICB9LCB0aGlzKSlcblxuICAgIGlmICghZXJyb3JzLmxlbmd0aCAmJiBnZXRWYWx1ZSgkZWwpICYmICRlbC5hdHRyKCdkYXRhLXJlbW90ZScpKSB7XG4gICAgICB0aGlzLmRlZmVyKCRlbCwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGF0YSA9IHt9XG4gICAgICAgIGRhdGFbJGVsLmF0dHIoJ25hbWUnKV0gPSBnZXRWYWx1ZSgkZWwpXG4gICAgICAgICQuZ2V0KCRlbC5hdHRyKCdkYXRhLXJlbW90ZScpLCBkYXRhKVxuICAgICAgICAgIC5mYWlsKGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3IpIHsgZXJyb3JzLnB1c2goZ2V0RXJyb3JNZXNzYWdlKCdyZW1vdGUnKSB8fCBlcnJvcikgfSlcbiAgICAgICAgICAuYWx3YXlzKGZ1bmN0aW9uICgpIHsgZGVmZXJyZWQucmVzb2x2ZShlcnJvcnMpfSlcbiAgICAgIH0pXG4gICAgfSBlbHNlIGRlZmVycmVkLnJlc29sdmUoZXJyb3JzKVxuXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2UoKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS52YWxpZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXNcblxuICAgICQud2hlbih0aGlzLiRpbnB1dHMubWFwKGZ1bmN0aW9uIChlbCkge1xuICAgICAgcmV0dXJuIHNlbGYudmFsaWRhdGVJbnB1dCgkKHRoaXMpLCBmYWxzZSlcbiAgICB9KSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLnRvZ2dsZVN1Ym1pdCgpXG4gICAgICBzZWxmLmZvY3VzRXJyb3IoKVxuICAgIH0pXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5mb2N1c0Vycm9yID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmZvY3VzKSByZXR1cm5cblxuICAgIHZhciAkaW5wdXQgPSB0aGlzLiRlbGVtZW50LmZpbmQoXCIuaGFzLWVycm9yOmZpcnN0IDppbnB1dFwiKVxuICAgIGlmICgkaW5wdXQubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHtzY3JvbGxUb3A6ICRpbnB1dC5vZmZzZXQoKS50b3AgLSBWYWxpZGF0b3IuRk9DVVNfT0ZGU0VUfSwgMjUwKVxuICAgICRpbnB1dC5mb2N1cygpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnNob3dFcnJvcnMgPSBmdW5jdGlvbiAoJGVsKSB7XG4gICAgdmFyIG1ldGhvZCA9IHRoaXMub3B0aW9ucy5odG1sID8gJ2h0bWwnIDogJ3RleHQnXG4gICAgdmFyIGVycm9ycyA9ICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJylcbiAgICB2YXIgJGdyb3VwID0gJGVsLmNsb3Nlc3QoJy5mb3JtLWdyb3VwJylcbiAgICB2YXIgJGJsb2NrID0gJGdyb3VwLmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICB2YXIgJGZlZWRiYWNrID0gJGdyb3VwLmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuXG4gICAgaWYgKCFlcnJvcnMubGVuZ3RoKSByZXR1cm5cblxuICAgIGVycm9ycyA9ICQoJzx1bC8+JylcbiAgICAgIC5hZGRDbGFzcygnbGlzdC11bnN0eWxlZCcpXG4gICAgICAuYXBwZW5kKCQubWFwKGVycm9ycywgZnVuY3Rpb24gKGVycm9yKSB7IHJldHVybiAkKCc8bGkvPicpW21ldGhvZF0oZXJyb3IpIH0pKVxuXG4gICAgJGJsb2NrLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKSA9PT0gdW5kZWZpbmVkICYmICRibG9jay5kYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JywgJGJsb2NrLmh0bWwoKSlcbiAgICAkYmxvY2suZW1wdHkoKS5hcHBlbmQoZXJyb3JzKVxuICAgICRncm91cC5hZGRDbGFzcygnaGFzLWVycm9yIGhhcy1kYW5nZXInKVxuXG4gICAgJGdyb3VwLmhhc0NsYXNzKCdoYXMtZmVlZGJhY2snKVxuICAgICAgJiYgJGZlZWRiYWNrLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5zdWNjZXNzKVxuICAgICAgJiYgJGZlZWRiYWNrLmFkZENsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5lcnJvcilcbiAgICAgICYmICRncm91cC5yZW1vdmVDbGFzcygnaGFzLXN1Y2Nlc3MnKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5jbGVhckVycm9ycyA9IGZ1bmN0aW9uICgkZWwpIHtcbiAgICB2YXIgJGdyb3VwID0gJGVsLmNsb3Nlc3QoJy5mb3JtLWdyb3VwJylcbiAgICB2YXIgJGJsb2NrID0gJGdyb3VwLmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICB2YXIgJGZlZWRiYWNrID0gJGdyb3VwLmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuXG4gICAgJGJsb2NrLmh0bWwoJGJsb2NrLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKSlcbiAgICAkZ3JvdXAucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvciBoYXMtZGFuZ2VyIGhhcy1zdWNjZXNzJylcblxuICAgICRncm91cC5oYXNDbGFzcygnaGFzLWZlZWRiYWNrJylcbiAgICAgICYmICRmZWVkYmFjay5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suZXJyb3IpXG4gICAgICAmJiAkZmVlZGJhY2sucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG4gICAgICAmJiBnZXRWYWx1ZSgkZWwpXG4gICAgICAmJiAkZmVlZGJhY2suYWRkQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG4gICAgICAmJiAkZ3JvdXAuYWRkQ2xhc3MoJ2hhcy1zdWNjZXNzJylcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuaGFzRXJyb3JzID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIGZpZWxkRXJyb3JzKCkge1xuICAgICAgcmV0dXJuICEhKCQodGhpcykuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycpIHx8IFtdKS5sZW5ndGhcbiAgICB9XG5cbiAgICByZXR1cm4gISF0aGlzLiRpbnB1dHMuZmlsdGVyKGZpZWxkRXJyb3JzKS5sZW5ndGhcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuaXNJbmNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIGZpZWxkSW5jb21wbGV0ZSgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGdldFZhbHVlKCQodGhpcykpXG4gICAgICByZXR1cm4gISh0eXBlb2YgdmFsdWUgPT0gXCJzdHJpbmdcIiA/ICQudHJpbSh2YWx1ZSkgOiB2YWx1ZSlcbiAgICB9XG5cbiAgICByZXR1cm4gISF0aGlzLiRpbnB1dHMuZmlsdGVyKCdbcmVxdWlyZWRdJykuZmlsdGVyKGZpZWxkSW5jb21wbGV0ZSkubGVuZ3RoXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLm9uU3VibWl0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICB0aGlzLnZhbGlkYXRlKClcbiAgICBpZiAodGhpcy5pc0luY29tcGxldGUoKSB8fCB0aGlzLmhhc0Vycm9ycygpKSBlLnByZXZlbnREZWZhdWx0KClcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUudG9nZ2xlU3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmRpc2FibGUpIHJldHVyblxuICAgIHRoaXMuJGJ0bi50b2dnbGVDbGFzcygnZGlzYWJsZWQnLCB0aGlzLmlzSW5jb21wbGV0ZSgpIHx8IHRoaXMuaGFzRXJyb3JzKCkpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmRlZmVyID0gZnVuY3Rpb24gKCRlbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9ICQucHJveHkoY2FsbGJhY2ssIHRoaXMsICRlbClcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5kZWxheSkgcmV0dXJuIGNhbGxiYWNrKClcbiAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KCRlbC5kYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcpKVxuICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcsIHdpbmRvdy5zZXRUaW1lb3V0KGNhbGxiYWNrLCB0aGlzLm9wdGlvbnMuZGVsYXkpKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuICAgICAgLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5lcnJvcilcbiAgICAgIC5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suc3VjY2VzcylcblxuICAgIHRoaXMuJGlucHV0c1xuICAgICAgLnJlbW92ZURhdGEoWydicy52YWxpZGF0b3IuZXJyb3JzJywgJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCddKVxuICAgICAgLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICAgIHZhciB0aW1lb3V0ID0gJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yLnRpbWVvdXQnKVxuICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRpbWVvdXQpICYmICR0aGlzLnJlbW92ZURhdGEoJ2JzLnZhbGlkYXRvci50aW1lb3V0JylcbiAgICAgIH0pXG5cbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgICB2YXIgb3JpZ2luYWxDb250ZW50ID0gJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpXG5cbiAgICAgICAgJHRoaXNcbiAgICAgICAgICAucmVtb3ZlRGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpXG4gICAgICAgICAgLmh0bWwob3JpZ2luYWxDb250ZW50KVxuICAgICAgfSlcblxuICAgIHRoaXMuJGJ0bi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKVxuXG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCcuaGFzLWVycm9yLCAuaGFzLWRhbmdlciwgLmhhcy1zdWNjZXNzJykucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvciBoYXMtZGFuZ2VyIGhhcy1zdWNjZXNzJylcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5yZXNldCgpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQXR0cignbm92YWxpZGF0ZScpXG4gICAgICAucmVtb3ZlRGF0YSgnYnMudmFsaWRhdG9yJylcbiAgICAgIC5vZmYoJy5icy52YWxpZGF0b3InKVxuXG4gICAgdGhpcy4kaW5wdXRzXG4gICAgICAub2ZmKCcuYnMudmFsaWRhdG9yJylcblxuICAgIHRoaXMub3B0aW9ucyAgICA9IG51bGxcbiAgICB0aGlzLnZhbGlkYXRvcnMgPSBudWxsXG4gICAgdGhpcy4kZWxlbWVudCAgID0gbnVsbFxuICAgIHRoaXMuJGJ0biAgICAgICA9IG51bGxcbiAgICB0aGlzLiRpbnB1dHMgICAgPSBudWxsXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gVkFMSURBVE9SIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgb3B0aW9ucyA9ICQuZXh0ZW5kKHt9LCBWYWxpZGF0b3IuREVGQVVMVFMsICR0aGlzLmRhdGEoKSwgdHlwZW9mIG9wdGlvbiA9PSAnb2JqZWN0JyAmJiBvcHRpb24pXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnZhbGlkYXRvcicpXG5cbiAgICAgIGlmICghZGF0YSAmJiBvcHRpb24gPT0gJ2Rlc3Ryb3knKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yJywgKGRhdGEgPSBuZXcgVmFsaWRhdG9yKHRoaXMsIG9wdGlvbnMpKSlcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09ICdzdHJpbmcnKSBkYXRhW29wdGlvbl0oKVxuICAgIH0pXG4gIH1cblxuICB2YXIgb2xkID0gJC5mbi52YWxpZGF0b3JcblxuICAkLmZuLnZhbGlkYXRvciAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLnZhbGlkYXRvci5Db25zdHJ1Y3RvciA9IFZhbGlkYXRvclxuXG5cbiAgLy8gVkFMSURBVE9SIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09PT09PVxuXG4gICQuZm4udmFsaWRhdG9yLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi52YWxpZGF0b3IgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBWQUxJREFUT1IgREFUQS1BUElcbiAgLy8gPT09PT09PT09PT09PT09PT09XG5cbiAgJCh3aW5kb3cpLm9uKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICQoJ2Zvcm1bZGF0YS10b2dnbGU9XCJ2YWxpZGF0b3JcIl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkZm9ybSA9ICQodGhpcylcbiAgICAgIFBsdWdpbi5jYWxsKCRmb3JtLCAkZm9ybS5kYXRhKCkpXG4gICAgfSlcbiAgfSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXZhbGlkYXRvci9qcy92YWxpZGF0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDE2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxuICogYm9vdHN0cmFwLWZpbGVpbnB1dCB2NC40LjJcbiAqIGh0dHA6Ly9wbHVnaW5zLmtyYWplZS5jb20vZmlsZS1pbnB1dFxuICpcbiAqIEF1dGhvcjogS2FydGlrIFZpc3dlc3dhcmFuXG4gKiBDb3B5cmlnaHQ6IDIwMTQgLSAyMDE3LCBLYXJ0aWsgVmlzd2Vzd2FyYW4sIEtyYWplZS5jb21cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQlNEIDMtQ2xhdXNlXG4gKiBodHRwczovL2dpdGh1Yi5jb20va2FydGlrLXYvYm9vdHN0cmFwLWZpbGVpbnB1dC9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4gKi9cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuICAgICAgICBkZWZpbmUoWydqcXVlcnknXSwgZmFjdG9yeSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgIH0gZWxzZSB7IC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgICAgICAvLyBOb2RlL0NvbW1vbkpTXG4gICAgICAgICAgICAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCdqcXVlcnknKSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgICAgICAgICBmYWN0b3J5KHdpbmRvdy5qUXVlcnkpO1xuICAgICAgICB9XG4gICAgfVxufShmdW5jdGlvbiAoJCkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgJC5mbi5maWxlaW5wdXRMb2NhbGVzID0ge307XG4gICAgJC5mbi5maWxlaW5wdXRUaGVtZXMgPSB7fTtcblxuICAgIFN0cmluZy5wcm90b3R5cGUuc2V0VG9rZW5zID0gZnVuY3Rpb24gKHJlcGxhY2VQYWlycykge1xuICAgICAgICB2YXIgc3RyID0gdGhpcy50b1N0cmluZygpLCBrZXksIHJlO1xuICAgICAgICBmb3IgKGtleSBpbiByZXBsYWNlUGFpcnMpIHtcbiAgICAgICAgICAgIGlmIChyZXBsYWNlUGFpcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIHJlID0gbmV3IFJlZ0V4cChcIlxce1wiICsga2V5ICsgXCJcXH1cIiwgXCJnXCIpO1xuICAgICAgICAgICAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKHJlLCByZXBsYWNlUGFpcnNba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgdmFyICRoLCBGaWxlSW5wdXQ7XG5cbiAgICAvLyBmaWxlaW5wdXQgaGVscGVyIG9iamVjdCBmb3IgYWxsIGdsb2JhbCB2YXJpYWJsZXMgYW5kIGludGVybmFsIGhlbHBlciBtZXRob2RzXG4gICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAkaCA9IHtcbiAgICAgICAgRlJBTUVTOiAnLmt2LXByZXZpZXctdGh1bWInLFxuICAgICAgICBTT1JUX0NTUzogJ2ZpbGUtc29ydGFibGUnLFxuICAgICAgICBTVFlMRV9TRVRUSU5HOiAnc3R5bGU9XCJ3aWR0aDp7d2lkdGh9O2hlaWdodDp7aGVpZ2h0fTtcIicsXG4gICAgICAgIE9CSkVDVF9QQVJBTVM6ICc8cGFyYW0gbmFtZT1cImNvbnRyb2xsZXJcIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd0Z1bGxTY3JlZW5cIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd1NjcmlwdEFjY2Vzc1wiIHZhbHVlPVwiYWx3YXlzXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1BsYXlcIiB2YWx1ZT1cImZhbHNlXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1N0YXJ0XCIgdmFsdWU9XCJmYWxzZVwiIC8+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+KG9yIGNsaWNrIHRvIHNlbGVjdCB7ZmlsZXN9KScsXG4gICAgICAgIHByZXZpZXdab29tQnV0dG9uVGl0bGVzOiB7XG4gICAgICAgICAgICBwcmV2OiAnVmlldyBwcmV2aW91cyBmaWxlJyxcbiAgICAgICAgICAgIG5leHQ6ICdWaWV3IG5leHQgZmlsZScsXG4gICAgICAgICAgICB0b2dnbGVoZWFkZXI6ICdUb2dnbGUgaGVhZGVyJyxcbiAgICAgICAgICAgIGZ1bGxzY3JlZW46ICdUb2dnbGUgZnVsbCBzY3JlZW4nLFxuICAgICAgICAgICAgYm9yZGVybGVzczogJ1RvZ2dsZSBib3JkZXJsZXNzIG1vZGUnLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSBkZXRhaWxlZCBwcmV2aWV3J1xuICAgICAgICB9XG4gICAgfTtcblxuICAgICQuZm4uZmlsZWlucHV0LkNvbnN0cnVjdG9yID0gRmlsZUlucHV0O1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydCBhdXRvbWF0aWNhbGx5IGZpbGUgaW5wdXRzIHdpdGggY2xhc3MgJ2ZpbGUnIGludG8gYSBib290c3RyYXAgZmlsZWlucHV0IGNvbnRyb2wuXG4gICAgICovXG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGlucHV0ID0gJCgnaW5wdXQuZmlsZVt0eXBlPWZpbGVdJyk7XG4gICAgICAgIGlmICgkaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAkaW5wdXQuZmlsZWlucHV0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn0pKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2pzL2ZpbGVpbnB1dC5qc1xuLy8gbW9kdWxlIGlkID0gMTdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9jc3MvYm9vdHN0cmFwLmNzc1xuLy8gbW9kdWxlIGlkID0gMThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtc2VsZWN0L2Rpc3QvY3NzL2Jvb3RzdHJhcC1zZWxlY3QuY3NzXG4vLyBtb2R1bGUgaWQgPSAxOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3Ncbi8vIG1vZHVsZSBpZCA9IDIwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvc3R5bGUuY3NzXG4vLyBtb2R1bGUgaWQgPSAyMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwic291cmNlUm9vdCI6IiJ9