navmesh.bjs 1.3 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659
  1. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Navigation = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2. "use strict";
  3. var extractAnnotations = require("./annotation.js");
  4. var _disableConstructor = false;
  5. // Inherit from a class without calling its constructor.
  6. function inherit(SuperClass) {
  7. _disableConstructor = true;
  8. var __class__ = new SuperClass();
  9. _disableConstructor = false;
  10. return __class__;
  11. }
  12. // Checks if the given function uses abitbol special properties ($super, $name,...)
  13. function usesSpecialProperty(fn) {
  14. return Boolean(fn.toString().match(/.*(\$super|\$name|\$computedPropertyName).*/));
  15. }
  16. var Class = function () {};
  17. Object.defineProperty(Class, "$class", {
  18. enumerable: false,
  19. value: Class
  20. });
  21. Object.defineProperty(Class, "$map", {
  22. enumerable: false,
  23. value: {
  24. attributes: {},
  25. methods: {},
  26. computedProperties: {}
  27. }
  28. });
  29. Object.defineProperty(Class, "$extend", {
  30. enumerable: false,
  31. value: function (properties) {
  32. var _superClass = this;
  33. var _classMap = JSON.parse(JSON.stringify(_superClass.$map)); // not pretty :s
  34. // New class
  35. var __class__ = function () {
  36. if (_disableConstructor) {
  37. return;
  38. }
  39. // Abitbol special properties
  40. Object.defineProperty(this, "$class", {
  41. enumerable: false,
  42. value: __class__
  43. });
  44. Object.defineProperty(this, "$map", {
  45. enumerable: false,
  46. value: _classMap
  47. });
  48. Object.defineProperty(this, "$data", {
  49. enumerable: false,
  50. value: {}
  51. });
  52. // Computed properties
  53. for (var property in _classMap.computedProperties) {
  54. Object.defineProperty(this, property, {
  55. enumerable: true,
  56. configurable: false,
  57. get: (_classMap.computedProperties[property].get !== undefined) ? (function (accessorName) {
  58. return function () {
  59. return this[accessorName].apply(this, arguments);
  60. };
  61. })(_classMap.computedProperties[property].get) : undefined, // jshint ignore:line
  62. set: (_classMap.computedProperties[property].set !== undefined) ? (function (mutatorName) {
  63. return function () {
  64. return this[mutatorName].apply(this, arguments);
  65. };
  66. })(_classMap.computedProperties[property].set) : undefined // jshint ignore:line
  67. });
  68. }
  69. // Bind this
  70. for (var method in _classMap.methods) {
  71. this[method] = this[method].bind(this);
  72. }
  73. // Call the constructor if any
  74. if (this.__init__) {
  75. this.__init__.apply(this, arguments);
  76. }
  77. return this;
  78. };
  79. // Inheritance
  80. __class__.prototype = inherit(this.$class);
  81. properties = properties || {};
  82. var property;
  83. var computedPropertyName;
  84. var annotations;
  85. var i;
  86. // Copy properties from mixins
  87. if (properties.__include__) {
  88. for (i = properties.__include__.length - 1 ; i >= 0 ; i--) {
  89. for (property in properties.__include__[i]) {
  90. if (properties[property] === undefined) {
  91. properties[property] = properties.__include__[i][property];
  92. }
  93. }
  94. }
  95. }
  96. // Add properties
  97. for (property in properties || {}) {
  98. if (property == "__include__" || property == "__classvars__") {
  99. continue;
  100. }
  101. if (typeof properties[property] == "function") {
  102. computedPropertyName = undefined;
  103. _classMap.methods[property] = {annotations: {}};
  104. // Accessors / Mutators
  105. if (property.indexOf("get") === 0) {
  106. computedPropertyName = property.slice(3, 4).toLowerCase() + property.slice(4, property.length);
  107. if (!_classMap.computedProperties[computedPropertyName]) {
  108. _classMap.computedProperties[computedPropertyName] = {annotations: {}};
  109. }
  110. _classMap.computedProperties[computedPropertyName].get = property;
  111. } else if (property.indexOf("set") === 0) {
  112. computedPropertyName = property.slice(3, 4).toLowerCase() + property.slice(4, property.length);
  113. if (!_classMap.computedProperties[computedPropertyName]) {
  114. _classMap.computedProperties[computedPropertyName] = {annotations: {}};
  115. }
  116. _classMap.computedProperties[computedPropertyName].set = property;
  117. } else if (property.indexOf("has") === 0) {
  118. computedPropertyName = property.slice(3, 4).toLowerCase() + property.slice(4, property.length);
  119. if (!_classMap.computedProperties[computedPropertyName]) {
  120. _classMap.computedProperties[computedPropertyName] = {annotations: {}};
  121. }
  122. _classMap.computedProperties[computedPropertyName].get = property;
  123. } else if (property.indexOf("is") === 0) {
  124. computedPropertyName = property.slice(2, 3).toLowerCase() + property.slice(3, property.length);
  125. if (!_classMap.computedProperties[computedPropertyName]) {
  126. _classMap.computedProperties[computedPropertyName] = {annotations: {}};
  127. }
  128. _classMap.computedProperties[computedPropertyName].get = property;
  129. }
  130. // Annotations
  131. annotations = extractAnnotations(properties[property]);
  132. for (var annotation in annotations) {
  133. _classMap.methods[property].annotations[annotation] = annotations[annotation];
  134. if (computedPropertyName) {
  135. _classMap.computedProperties[computedPropertyName]
  136. .annotations[annotation] = annotations[annotation];
  137. }
  138. }
  139. // Wrapped method
  140. if (usesSpecialProperty(properties[property])) {
  141. __class__.prototype[property] = (function (method, propertyName, computedPropertyName) {
  142. return function () {
  143. var _oldSuper = this.$super;
  144. var _oldName = this.$name;
  145. var _oldComputedPropertyName = this.$computedPropertyName;
  146. this.$super = _superClass.prototype[propertyName];
  147. this.$name = propertyName;
  148. this.$computedPropertyName = computedPropertyName;
  149. try {
  150. return method.apply(this, arguments);
  151. } finally {
  152. if (_oldSuper) {
  153. this.$super = _oldSuper;
  154. } else {
  155. delete this.$super;
  156. }
  157. if (_oldName) {
  158. this.$name = _oldName;
  159. } else {
  160. delete this.$name;
  161. }
  162. if (_oldComputedPropertyName) {
  163. this.$computedPropertyName = _oldComputedPropertyName;
  164. } else {
  165. delete this.$computedPropertyName;
  166. }
  167. }
  168. };
  169. })(properties[property], property, computedPropertyName); // jshint ignore:line
  170. // Simple methods
  171. } else {
  172. __class__.prototype[property] = properties[property];
  173. }
  174. } else {
  175. _classMap.attributes[property] = true;
  176. __class__.prototype[property] = properties[property];
  177. }
  178. }
  179. // Copy super class static properties
  180. var scStaticProps = Object.getOwnPropertyNames(_superClass);
  181. // Removes caller, callee and arguments from the list (strict mode)
  182. // Removes non enumerable Abitbol properties too
  183. scStaticProps = scStaticProps.filter(function (value) {
  184. return (["caller", "callee", "arguments", "$class", "$extend", "$map"].indexOf(value) == -1);
  185. });
  186. for (i = 0 ; i < scStaticProps.length ; i++) {
  187. if (__class__[scStaticProps[i]] === undefined) {
  188. __class__[scStaticProps[i]] = _superClass[scStaticProps[i]];
  189. }
  190. }
  191. // Add static properties
  192. if (properties.__classvars__) {
  193. for (property in properties.__classvars__) {
  194. __class__[property] = properties.__classvars__[property];
  195. }
  196. }
  197. // Add abitbol static properties
  198. Object.defineProperty(__class__, "$class", {
  199. enumerable: false,
  200. value: __class__
  201. });
  202. Object.defineProperty(__class__, "$extend", {
  203. enumerable: false,
  204. value: Class.$extend
  205. });
  206. Object.defineProperty(__class__, "$map", {
  207. enumerable: false,
  208. value: _classMap
  209. });
  210. return __class__;
  211. }
  212. });
  213. module.exports = Class;
  214. },{"./annotation.js":2}],2:[function(require,module,exports){
  215. "use strict";
  216. function cleanJs(js) {
  217. // remove function fn(param) {
  218. js = js.replace(/^function\s*[^(]*\s*\([^)]*\)\s*\{/, "");
  219. // remove comments (not super safe but should work in most cases)
  220. js = js.replace(/\/\*(.|\r|\n)*?\*\//g, "");
  221. js = js.replace(/\/\/.*?\r?\n/g, "\n");
  222. // remove indentation and CR/LF
  223. js = js.replace(/\s*\r?\n\s*/g, "");
  224. return js;
  225. }
  226. function extractStrings(js) {
  227. var strings = [];
  228. var instr = false;
  229. var inesc = false;
  230. var quote;
  231. var buff;
  232. var c;
  233. for (var i = 0 ; i < js.length ; i++) {
  234. c = js[i];
  235. if (!instr) {
  236. // New string
  237. if (c == "\"" || c == "'") {
  238. instr = true;
  239. inesc = false;
  240. quote = c;
  241. buff = "";
  242. // Char we don't care about
  243. } else if ([" ", " ", "\n", "\r", ";"].indexOf(c) > -1) { // jshint ignore:line
  244. continue;
  245. // Other expression -> job finished!
  246. } else {
  247. break;
  248. }
  249. } else {
  250. if (!inesc) {
  251. // Escaped char
  252. if (c == "\\") {
  253. inesc = true;
  254. // End of string
  255. } else if (c == quote) {
  256. strings.push(buff);
  257. instr = false;
  258. // Any char
  259. } else {
  260. buff += c;
  261. }
  262. } else {
  263. if (c == "\\") {
  264. buff += "\\";
  265. } else if (c == "n") {
  266. buff += "\n";
  267. } else if (c == "r") {
  268. buff += "\r";
  269. } else if (c == "t") {
  270. buff += "\t";
  271. } else if (c == quote) {
  272. buff += quote;
  273. // We don't care...
  274. } else {
  275. buff += "\\" + c;
  276. }
  277. inesc = false;
  278. }
  279. }
  280. }
  281. return strings;
  282. }
  283. function autoCast(value) {
  284. if (value == "true") {
  285. return true;
  286. } else if (value == "false") {
  287. return false;
  288. } else if (value == "null") {
  289. return null;
  290. } else if (value == "undefined") {
  291. return undefined;
  292. } else if (value.match(/^([0-9]+\.?|[0-9]*\.[0-9]+)$/)) {
  293. return parseFloat(value);
  294. } else {
  295. return value;
  296. }
  297. }
  298. function extractAnnotations(func) {
  299. var js = cleanJs(func.toString());
  300. var strings = extractStrings(js);
  301. var annotations = {};
  302. var string;
  303. var key;
  304. var value;
  305. for (var i = 0 ; i < strings.length ; i++) {
  306. string = strings[i].trim();
  307. if (string.indexOf("@") !== 0) {
  308. continue;
  309. }
  310. key = string.slice(1, (string.indexOf(" ") > -1) ? string.indexOf(" ") : string.length);
  311. value = true;
  312. if (string.indexOf(" ") > -1) {
  313. value = string.slice(string.indexOf(" ") + 1, string.length);
  314. value = value.trim();
  315. value = autoCast(value);
  316. }
  317. annotations[key] = value;
  318. }
  319. return annotations;
  320. }
  321. module.exports = extractAnnotations;
  322. },{}],3:[function(require,module,exports){
  323. (function (global){
  324. /**
  325. * @license
  326. * lodash 4.5.1 (Custom Build) <https://lodash.com/>
  327. * Build: `lodash -d -o ./foo/lodash.js`
  328. * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
  329. * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
  330. * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
  331. * Available under MIT license <https://lodash.com/license>
  332. */
  333. ;(function() {
  334. /** Used as a safe reference for `undefined` in pre-ES5 environments. */
  335. var undefined;
  336. /** Used as the semantic version number. */
  337. var VERSION = '4.5.1';
  338. /** Used to compose bitmasks for wrapper metadata. */
  339. var BIND_FLAG = 1,
  340. BIND_KEY_FLAG = 2,
  341. CURRY_BOUND_FLAG = 4,
  342. CURRY_FLAG = 8,
  343. CURRY_RIGHT_FLAG = 16,
  344. PARTIAL_FLAG = 32,
  345. PARTIAL_RIGHT_FLAG = 64,
  346. ARY_FLAG = 128,
  347. REARG_FLAG = 256,
  348. FLIP_FLAG = 512;
  349. /** Used to compose bitmasks for comparison styles. */
  350. var UNORDERED_COMPARE_FLAG = 1,
  351. PARTIAL_COMPARE_FLAG = 2;
  352. /** Used as default options for `_.truncate`. */
  353. var DEFAULT_TRUNC_LENGTH = 30,
  354. DEFAULT_TRUNC_OMISSION = '...';
  355. /** Used to detect hot functions by number of calls within a span of milliseconds. */
  356. var HOT_COUNT = 150,
  357. HOT_SPAN = 16;
  358. /** Used as the size to enable large array optimizations. */
  359. var LARGE_ARRAY_SIZE = 200;
  360. /** Used to indicate the type of lazy iteratees. */
  361. var LAZY_FILTER_FLAG = 1,
  362. LAZY_MAP_FLAG = 2,
  363. LAZY_WHILE_FLAG = 3;
  364. /** Used as the `TypeError` message for "Functions" methods. */
  365. var FUNC_ERROR_TEXT = 'Expected a function';
  366. /** Used to stand-in for `undefined` hash values. */
  367. var HASH_UNDEFINED = '__lodash_hash_undefined__';
  368. /** Used as references for various `Number` constants. */
  369. var INFINITY = 1 / 0,
  370. MAX_SAFE_INTEGER = 9007199254740991,
  371. MAX_INTEGER = 1.7976931348623157e+308,
  372. NAN = 0 / 0;
  373. /** Used as references for the maximum length and index of an array. */
  374. var MAX_ARRAY_LENGTH = 4294967295,
  375. MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
  376. HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
  377. /** Used as the internal argument placeholder. */
  378. var PLACEHOLDER = '__lodash_placeholder__';
  379. /** `Object#toString` result references. */
  380. var argsTag = '[object Arguments]',
  381. arrayTag = '[object Array]',
  382. boolTag = '[object Boolean]',
  383. dateTag = '[object Date]',
  384. errorTag = '[object Error]',
  385. funcTag = '[object Function]',
  386. genTag = '[object GeneratorFunction]',
  387. mapTag = '[object Map]',
  388. numberTag = '[object Number]',
  389. objectTag = '[object Object]',
  390. regexpTag = '[object RegExp]',
  391. setTag = '[object Set]',
  392. stringTag = '[object String]',
  393. symbolTag = '[object Symbol]',
  394. weakMapTag = '[object WeakMap]',
  395. weakSetTag = '[object WeakSet]';
  396. var arrayBufferTag = '[object ArrayBuffer]',
  397. float32Tag = '[object Float32Array]',
  398. float64Tag = '[object Float64Array]',
  399. int8Tag = '[object Int8Array]',
  400. int16Tag = '[object Int16Array]',
  401. int32Tag = '[object Int32Array]',
  402. uint8Tag = '[object Uint8Array]',
  403. uint8ClampedTag = '[object Uint8ClampedArray]',
  404. uint16Tag = '[object Uint16Array]',
  405. uint32Tag = '[object Uint32Array]';
  406. /** Used to match empty string literals in compiled template source. */
  407. var reEmptyStringLeading = /\b__p \+= '';/g,
  408. reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
  409. reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  410. /** Used to match HTML entities and HTML characters. */
  411. var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
  412. reUnescapedHtml = /[&<>"'`]/g,
  413. reHasEscapedHtml = RegExp(reEscapedHtml.source),
  414. reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
  415. /** Used to match template delimiters. */
  416. var reEscape = /<%-([\s\S]+?)%>/g,
  417. reEvaluate = /<%([\s\S]+?)%>/g,
  418. reInterpolate = /<%=([\s\S]+?)%>/g;
  419. /** Used to match property names within property paths. */
  420. var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
  421. reIsPlainProp = /^\w*$/,
  422. rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;
  423. /** Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */
  424. var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
  425. reHasRegExpChar = RegExp(reRegExpChar.source);
  426. /** Used to match leading and trailing whitespace. */
  427. var reTrim = /^\s+|\s+$/g,
  428. reTrimStart = /^\s+/,
  429. reTrimEnd = /\s+$/;
  430. /** Used to match backslashes in property paths. */
  431. var reEscapeChar = /\\(\\)?/g;
  432. /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
  433. var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
  434. /** Used to match `RegExp` flags from their coerced string values. */
  435. var reFlags = /\w*$/;
  436. /** Used to detect hexadecimal string values. */
  437. var reHasHexPrefix = /^0x/i;
  438. /** Used to detect bad signed hexadecimal string values. */
  439. var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
  440. /** Used to detect binary string values. */
  441. var reIsBinary = /^0b[01]+$/i;
  442. /** Used to detect host constructors (Safari > 5). */
  443. var reIsHostCtor = /^\[object .+?Constructor\]$/;
  444. /** Used to detect octal string values. */
  445. var reIsOctal = /^0o[0-7]+$/i;
  446. /** Used to detect unsigned integer values. */
  447. var reIsUint = /^(?:0|[1-9]\d*)$/;
  448. /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
  449. var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
  450. /** Used to ensure capturing order of template delimiters. */
  451. var reNoMatch = /($^)/;
  452. /** Used to match unescaped characters in compiled string literals. */
  453. var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
  454. /** Used to compose unicode character classes. */
  455. var rsAstralRange = '\\ud800-\\udfff',
  456. rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
  457. rsComboSymbolsRange = '\\u20d0-\\u20f0',
  458. rsDingbatRange = '\\u2700-\\u27bf',
  459. rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
  460. rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
  461. rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
  462. rsQuoteRange = '\\u2018\\u2019\\u201c\\u201d',
  463. rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
  464. rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
  465. rsVarRange = '\\ufe0e\\ufe0f',
  466. rsBreakRange = rsMathOpRange + rsNonCharRange + rsQuoteRange + rsSpaceRange;
  467. /** Used to compose unicode capture groups. */
  468. var rsAstral = '[' + rsAstralRange + ']',
  469. rsBreak = '[' + rsBreakRange + ']',
  470. rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
  471. rsDigits = '\\d+',
  472. rsDingbat = '[' + rsDingbatRange + ']',
  473. rsLower = '[' + rsLowerRange + ']',
  474. rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
  475. rsFitz = '\\ud83c[\\udffb-\\udfff]',
  476. rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
  477. rsNonAstral = '[^' + rsAstralRange + ']',
  478. rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
  479. rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
  480. rsUpper = '[' + rsUpperRange + ']',
  481. rsZWJ = '\\u200d';
  482. /** Used to compose unicode regexes. */
  483. var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')',
  484. rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')',
  485. reOptMod = rsModifier + '?',
  486. rsOptVar = '[' + rsVarRange + ']?',
  487. rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
  488. rsSeq = rsOptVar + reOptMod + rsOptJoin,
  489. rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
  490. rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
  491. /**
  492. * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
  493. * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
  494. */
  495. var reComboMark = RegExp(rsCombo, 'g');
  496. /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
  497. var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
  498. /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
  499. var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']');
  500. /** Used to match non-compound words composed of alphanumeric characters. */
  501. var reBasicWord = /[a-zA-Z0-9]+/g;
  502. /** Used to match complex or compound words. */
  503. var reComplexWord = RegExp([
  504. rsUpper + '?' + rsLower + '+(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
  505. rsUpperMisc + '+(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')',
  506. rsUpper + '?' + rsLowerMisc + '+',
  507. rsUpper + '+',
  508. rsDigits,
  509. rsEmoji
  510. ].join('|'), 'g');
  511. /** Used to detect strings that need a more robust regexp to match words. */
  512. var reHasComplexWord = /[a-z][A-Z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
  513. /** Used to assign default `context` object properties. */
  514. var contextProps = [
  515. 'Array', 'Buffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
  516. 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
  517. 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
  518. 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_',
  519. 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
  520. ];
  521. /** Used to make template sourceURLs easier to identify. */
  522. var templateCounter = -1;
  523. /** Used to identify `toStringTag` values of typed arrays. */
  524. var typedArrayTags = {};
  525. typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
  526. typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
  527. typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
  528. typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
  529. typedArrayTags[uint32Tag] = true;
  530. typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
  531. typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
  532. typedArrayTags[dateTag] = typedArrayTags[errorTag] =
  533. typedArrayTags[funcTag] = typedArrayTags[mapTag] =
  534. typedArrayTags[numberTag] = typedArrayTags[objectTag] =
  535. typedArrayTags[regexpTag] = typedArrayTags[setTag] =
  536. typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
  537. /** Used to identify `toStringTag` values supported by `_.clone`. */
  538. var cloneableTags = {};
  539. cloneableTags[argsTag] = cloneableTags[arrayTag] =
  540. cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
  541. cloneableTags[dateTag] = cloneableTags[float32Tag] =
  542. cloneableTags[float64Tag] = cloneableTags[int8Tag] =
  543. cloneableTags[int16Tag] = cloneableTags[int32Tag] =
  544. cloneableTags[mapTag] = cloneableTags[numberTag] =
  545. cloneableTags[objectTag] = cloneableTags[regexpTag] =
  546. cloneableTags[setTag] = cloneableTags[stringTag] =
  547. cloneableTags[symbolTag] = cloneableTags[uint8Tag] =
  548. cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] =
  549. cloneableTags[uint32Tag] = true;
  550. cloneableTags[errorTag] = cloneableTags[funcTag] =
  551. cloneableTags[weakMapTag] = false;
  552. /** Used to map latin-1 supplementary letters to basic latin letters. */
  553. var deburredLetters = {
  554. '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
  555. '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
  556. '\xc7': 'C', '\xe7': 'c',
  557. '\xd0': 'D', '\xf0': 'd',
  558. '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
  559. '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
  560. '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
  561. '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
  562. '\xd1': 'N', '\xf1': 'n',
  563. '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
  564. '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
  565. '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
  566. '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
  567. '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
  568. '\xc6': 'Ae', '\xe6': 'ae',
  569. '\xde': 'Th', '\xfe': 'th',
  570. '\xdf': 'ss'
  571. };
  572. /** Used to map characters to HTML entities. */
  573. var htmlEscapes = {
  574. '&': '&amp;',
  575. '<': '&lt;',
  576. '>': '&gt;',
  577. '"': '&quot;',
  578. "'": '&#39;',
  579. '`': '&#96;'
  580. };
  581. /** Used to map HTML entities to characters. */
  582. var htmlUnescapes = {
  583. '&amp;': '&',
  584. '&lt;': '<',
  585. '&gt;': '>',
  586. '&quot;': '"',
  587. '&#39;': "'",
  588. '&#96;': '`'
  589. };
  590. /** Used to determine if values are of the language type `Object`. */
  591. var objectTypes = {
  592. 'function': true,
  593. 'object': true
  594. };
  595. /** Used to escape characters for inclusion in compiled string literals. */
  596. var stringEscapes = {
  597. '\\': '\\',
  598. "'": "'",
  599. '\n': 'n',
  600. '\r': 'r',
  601. '\u2028': 'u2028',
  602. '\u2029': 'u2029'
  603. };
  604. /** Built-in method references without a dependency on `root`. */
  605. var freeParseFloat = parseFloat,
  606. freeParseInt = parseInt;
  607. /** Detect free variable `exports`. */
  608. var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType)
  609. ? exports
  610. : undefined;
  611. /** Detect free variable `module`. */
  612. var freeModule = (objectTypes[typeof module] && module && !module.nodeType)
  613. ? module
  614. : undefined;
  615. /** Detect the popular CommonJS extension `module.exports`. */
  616. var moduleExports = (freeModule && freeModule.exports === freeExports)
  617. ? freeExports
  618. : undefined;
  619. /** Detect free variable `global` from Node.js. */
  620. var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
  621. /** Detect free variable `self`. */
  622. var freeSelf = checkGlobal(objectTypes[typeof self] && self);
  623. /** Detect free variable `window`. */
  624. var freeWindow = checkGlobal(objectTypes[typeof window] && window);
  625. /** Detect `this` as the global object. */
  626. var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
  627. /**
  628. * Used as a reference to the global object.
  629. *
  630. * The `this` value is used if it's the global object to avoid Greasemonkey's
  631. * restricted `window` object, otherwise the `window` object is used.
  632. */
  633. var root = freeGlobal ||
  634. ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) ||
  635. freeSelf || thisGlobal || Function('return this')();
  636. /*--------------------------------------------------------------------------*/
  637. /**
  638. * Adds the key-value `pair` to `map`.
  639. *
  640. * @private
  641. * @param {Object} map The map to modify.
  642. * @param {Array} pair The key-value pair to add.
  643. * @returns {Object} Returns `map`.
  644. */
  645. function addMapEntry(map, pair) {
  646. map.set(pair[0], pair[1]);
  647. return map;
  648. }
  649. /**
  650. * Adds `value` to `set`.
  651. *
  652. * @private
  653. * @param {Object} set The set to modify.
  654. * @param {*} value The value to add.
  655. * @returns {Object} Returns `set`.
  656. */
  657. function addSetEntry(set, value) {
  658. set.add(value);
  659. return set;
  660. }
  661. /**
  662. * A faster alternative to `Function#apply`, this function invokes `func`
  663. * with the `this` binding of `thisArg` and the arguments of `args`.
  664. *
  665. * @private
  666. * @param {Function} func The function to invoke.
  667. * @param {*} thisArg The `this` binding of `func`.
  668. * @param {...*} args The arguments to invoke `func` with.
  669. * @returns {*} Returns the result of `func`.
  670. */
  671. function apply(func, thisArg, args) {
  672. var length = args.length;
  673. switch (length) {
  674. case 0: return func.call(thisArg);
  675. case 1: return func.call(thisArg, args[0]);
  676. case 2: return func.call(thisArg, args[0], args[1]);
  677. case 3: return func.call(thisArg, args[0], args[1], args[2]);
  678. }
  679. return func.apply(thisArg, args);
  680. }
  681. /**
  682. * A specialized version of `baseAggregator` for arrays.
  683. *
  684. * @private
  685. * @param {Array} array The array to iterate over.
  686. * @param {Function} setter The function to set `accumulator` values.
  687. * @param {Function} iteratee The iteratee to transform keys.
  688. * @param {Object} accumulator The initial aggregated object.
  689. * @returns {Function} Returns `accumulator`.
  690. */
  691. function arrayAggregator(array, setter, iteratee, accumulator) {
  692. var index = -1,
  693. length = array.length;
  694. while (++index < length) {
  695. var value = array[index];
  696. setter(accumulator, value, iteratee(value), array);
  697. }
  698. return accumulator;
  699. }
  700. /**
  701. * Creates a new array concatenating `array` with `other`.
  702. *
  703. * @private
  704. * @param {Array} array The first array to concatenate.
  705. * @param {Array} other The second array to concatenate.
  706. * @returns {Array} Returns the new concatenated array.
  707. */
  708. function arrayConcat(array, other) {
  709. var index = -1,
  710. length = array.length,
  711. othIndex = -1,
  712. othLength = other.length,
  713. result = Array(length + othLength);
  714. while (++index < length) {
  715. result[index] = array[index];
  716. }
  717. while (++othIndex < othLength) {
  718. result[index++] = other[othIndex];
  719. }
  720. return result;
  721. }
  722. /**
  723. * A specialized version of `_.forEach` for arrays without support for
  724. * iteratee shorthands.
  725. *
  726. * @private
  727. * @param {Array} array The array to iterate over.
  728. * @param {Function} iteratee The function invoked per iteration.
  729. * @returns {Array} Returns `array`.
  730. */
  731. function arrayEach(array, iteratee) {
  732. var index = -1,
  733. length = array.length;
  734. while (++index < length) {
  735. if (iteratee(array[index], index, array) === false) {
  736. break;
  737. }
  738. }
  739. return array;
  740. }
  741. /**
  742. * A specialized version of `_.forEachRight` for arrays without support for
  743. * iteratee shorthands.
  744. *
  745. * @private
  746. * @param {Array} array The array to iterate over.
  747. * @param {Function} iteratee The function invoked per iteration.
  748. * @returns {Array} Returns `array`.
  749. */
  750. function arrayEachRight(array, iteratee) {
  751. var length = array.length;
  752. while (length--) {
  753. if (iteratee(array[length], length, array) === false) {
  754. break;
  755. }
  756. }
  757. return array;
  758. }
  759. /**
  760. * A specialized version of `_.every` for arrays without support for
  761. * iteratee shorthands.
  762. *
  763. * @private
  764. * @param {Array} array The array to iterate over.
  765. * @param {Function} predicate The function invoked per iteration.
  766. * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`.
  767. */
  768. function arrayEvery(array, predicate) {
  769. var index = -1,
  770. length = array.length;
  771. while (++index < length) {
  772. if (!predicate(array[index], index, array)) {
  773. return false;
  774. }
  775. }
  776. return true;
  777. }
  778. /**
  779. * A specialized version of `_.filter` for arrays without support for
  780. * iteratee shorthands.
  781. *
  782. * @private
  783. * @param {Array} array The array to iterate over.
  784. * @param {Function} predicate The function invoked per iteration.
  785. * @returns {Array} Returns the new filtered array.
  786. */
  787. function arrayFilter(array, predicate) {
  788. var index = -1,
  789. length = array.length,
  790. resIndex = -1,
  791. result = [];
  792. while (++index < length) {
  793. var value = array[index];
  794. if (predicate(value, index, array)) {
  795. result[++resIndex] = value;
  796. }
  797. }
  798. return result;
  799. }
  800. /**
  801. * A specialized version of `_.includes` for arrays without support for
  802. * specifying an index to search from.
  803. *
  804. * @private
  805. * @param {Array} array The array to search.
  806. * @param {*} target The value to search for.
  807. * @returns {boolean} Returns `true` if `target` is found, else `false`.
  808. */
  809. function arrayIncludes(array, value) {
  810. return !!array.length && baseIndexOf(array, value, 0) > -1;
  811. }
  812. /**
  813. * A specialized version of `_.includesWith` for arrays without support for
  814. * specifying an index to search from.
  815. *
  816. * @private
  817. * @param {Array} array The array to search.
  818. * @param {*} target The value to search for.
  819. * @param {Function} comparator The comparator invoked per element.
  820. * @returns {boolean} Returns `true` if `target` is found, else `false`.
  821. */
  822. function arrayIncludesWith(array, value, comparator) {
  823. var index = -1,
  824. length = array.length;
  825. while (++index < length) {
  826. if (comparator(value, array[index])) {
  827. return true;
  828. }
  829. }
  830. return false;
  831. }
  832. /**
  833. * A specialized version of `_.map` for arrays without support for iteratee
  834. * shorthands.
  835. *
  836. * @private
  837. * @param {Array} array The array to iterate over.
  838. * @param {Function} iteratee The function invoked per iteration.
  839. * @returns {Array} Returns the new mapped array.
  840. */
  841. function arrayMap(array, iteratee) {
  842. var index = -1,
  843. length = array.length,
  844. result = Array(length);
  845. while (++index < length) {
  846. result[index] = iteratee(array[index], index, array);
  847. }
  848. return result;
  849. }
  850. /**
  851. * Appends the elements of `values` to `array`.
  852. *
  853. * @private
  854. * @param {Array} array The array to modify.
  855. * @param {Array} values The values to append.
  856. * @returns {Array} Returns `array`.
  857. */
  858. function arrayPush(array, values) {
  859. var index = -1,
  860. length = values.length,
  861. offset = array.length;
  862. while (++index < length) {
  863. array[offset + index] = values[index];
  864. }
  865. return array;
  866. }
  867. /**
  868. * A specialized version of `_.reduce` for arrays without support for
  869. * iteratee shorthands.
  870. *
  871. * @private
  872. * @param {Array} array The array to iterate over.
  873. * @param {Function} iteratee The function invoked per iteration.
  874. * @param {*} [accumulator] The initial value.
  875. * @param {boolean} [initAccum] Specify using the first element of `array` as the initial value.
  876. * @returns {*} Returns the accumulated value.
  877. */
  878. function arrayReduce(array, iteratee, accumulator, initAccum) {
  879. var index = -1,
  880. length = array.length;
  881. if (initAccum && length) {
  882. accumulator = array[++index];
  883. }
  884. while (++index < length) {
  885. accumulator = iteratee(accumulator, array[index], index, array);
  886. }
  887. return accumulator;
  888. }
  889. /**
  890. * A specialized version of `_.reduceRight` for arrays without support for
  891. * iteratee shorthands.
  892. *
  893. * @private
  894. * @param {Array} array The array to iterate over.
  895. * @param {Function} iteratee The function invoked per iteration.
  896. * @param {*} [accumulator] The initial value.
  897. * @param {boolean} [initAccum] Specify using the last element of `array` as the initial value.
  898. * @returns {*} Returns the accumulated value.
  899. */
  900. function arrayReduceRight(array, iteratee, accumulator, initAccum) {
  901. var length = array.length;
  902. if (initAccum && length) {
  903. accumulator = array[--length];
  904. }
  905. while (length--) {
  906. accumulator = iteratee(accumulator, array[length], length, array);
  907. }
  908. return accumulator;
  909. }
  910. /**
  911. * A specialized version of `_.some` for arrays without support for iteratee
  912. * shorthands.
  913. *
  914. * @private
  915. * @param {Array} array The array to iterate over.
  916. * @param {Function} predicate The function invoked per iteration.
  917. * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
  918. */
  919. function arraySome(array, predicate) {
  920. var index = -1,
  921. length = array.length;
  922. while (++index < length) {
  923. if (predicate(array[index], index, array)) {
  924. return true;
  925. }
  926. }
  927. return false;
  928. }
  929. /**
  930. * The base implementation of methods like `_.max` and `_.min` which accepts a
  931. * `comparator` to determine the extremum value.
  932. *
  933. * @private
  934. * @param {Array} array The array to iterate over.
  935. * @param {Function} iteratee The iteratee invoked per iteration.
  936. * @param {Function} comparator The comparator used to compare values.
  937. * @returns {*} Returns the extremum value.
  938. */
  939. function baseExtremum(array, iteratee, comparator) {
  940. var index = -1,
  941. length = array.length;
  942. while (++index < length) {
  943. var value = array[index],
  944. current = iteratee(value);
  945. if (current != null && (computed === undefined
  946. ? current === current
  947. : comparator(current, computed)
  948. )) {
  949. var computed = current,
  950. result = value;
  951. }
  952. }
  953. return result;
  954. }
  955. /**
  956. * The base implementation of methods like `_.find` and `_.findKey`, without
  957. * support for iteratee shorthands, which iterates over `collection` using
  958. * `eachFunc`.
  959. *
  960. * @private
  961. * @param {Array|Object} collection The collection to search.
  962. * @param {Function} predicate The function invoked per iteration.
  963. * @param {Function} eachFunc The function to iterate over `collection`.
  964. * @param {boolean} [retKey] Specify returning the key of the found element instead of the element itself.
  965. * @returns {*} Returns the found element or its key, else `undefined`.
  966. */
  967. function baseFind(collection, predicate, eachFunc, retKey) {
  968. var result;
  969. eachFunc(collection, function(value, key, collection) {
  970. if (predicate(value, key, collection)) {
  971. result = retKey ? key : value;
  972. return false;
  973. }
  974. });
  975. return result;
  976. }
  977. /**
  978. * The base implementation of `_.findIndex` and `_.findLastIndex` without
  979. * support for iteratee shorthands.
  980. *
  981. * @private
  982. * @param {Array} array The array to search.
  983. * @param {Function} predicate The function invoked per iteration.
  984. * @param {boolean} [fromRight] Specify iterating from right to left.
  985. * @returns {number} Returns the index of the matched value, else `-1`.
  986. */
  987. function baseFindIndex(array, predicate, fromRight) {
  988. var length = array.length,
  989. index = fromRight ? length : -1;
  990. while ((fromRight ? index-- : ++index < length)) {
  991. if (predicate(array[index], index, array)) {
  992. return index;
  993. }
  994. }
  995. return -1;
  996. }
  997. /**
  998. * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
  999. *
  1000. * @private
  1001. * @param {Array} array The array to search.
  1002. * @param {*} value The value to search for.
  1003. * @param {number} fromIndex The index to search from.
  1004. * @returns {number} Returns the index of the matched value, else `-1`.
  1005. */
  1006. function baseIndexOf(array, value, fromIndex) {
  1007. if (value !== value) {
  1008. return indexOfNaN(array, fromIndex);
  1009. }
  1010. var index = fromIndex - 1,
  1011. length = array.length;
  1012. while (++index < length) {
  1013. if (array[index] === value) {
  1014. return index;
  1015. }
  1016. }
  1017. return -1;
  1018. }
  1019. /**
  1020. * The base implementation of `_.reduce` and `_.reduceRight`, without support
  1021. * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
  1022. *
  1023. * @private
  1024. * @param {Array|Object} collection The collection to iterate over.
  1025. * @param {Function} iteratee The function invoked per iteration.
  1026. * @param {*} accumulator The initial value.
  1027. * @param {boolean} initAccum Specify using the first or last element of `collection` as the initial value.
  1028. * @param {Function} eachFunc The function to iterate over `collection`.
  1029. * @returns {*} Returns the accumulated value.
  1030. */
  1031. function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
  1032. eachFunc(collection, function(value, index, collection) {
  1033. accumulator = initAccum
  1034. ? (initAccum = false, value)
  1035. : iteratee(accumulator, value, index, collection);
  1036. });
  1037. return accumulator;
  1038. }
  1039. /**
  1040. * The base implementation of `_.sortBy` which uses `comparer` to define
  1041. * the sort order of `array` and replaces criteria objects with their
  1042. * corresponding values.
  1043. *
  1044. * @private
  1045. * @param {Array} array The array to sort.
  1046. * @param {Function} comparer The function to define sort order.
  1047. * @returns {Array} Returns `array`.
  1048. */
  1049. function baseSortBy(array, comparer) {
  1050. var length = array.length;
  1051. array.sort(comparer);
  1052. while (length--) {
  1053. array[length] = array[length].value;
  1054. }
  1055. return array;
  1056. }
  1057. /**
  1058. * The base implementation of `_.sum` without support for iteratee shorthands.
  1059. *
  1060. * @private
  1061. * @param {Array} array The array to iterate over.
  1062. * @param {Function} iteratee The function invoked per iteration.
  1063. * @returns {number} Returns the sum.
  1064. */
  1065. function baseSum(array, iteratee) {
  1066. var result,
  1067. index = -1,
  1068. length = array.length;
  1069. while (++index < length) {
  1070. var current = iteratee(array[index]);
  1071. if (current !== undefined) {
  1072. result = result === undefined ? current : (result + current);
  1073. }
  1074. }
  1075. return result;
  1076. }
  1077. /**
  1078. * The base implementation of `_.times` without support for iteratee shorthands
  1079. * or max array length checks.
  1080. *
  1081. * @private
  1082. * @param {number} n The number of times to invoke `iteratee`.
  1083. * @param {Function} iteratee The function invoked per iteration.
  1084. * @returns {Array} Returns the array of results.
  1085. */
  1086. function baseTimes(n, iteratee) {
  1087. var index = -1,
  1088. result = Array(n);
  1089. while (++index < n) {
  1090. result[index] = iteratee(index);
  1091. }
  1092. return result;
  1093. }
  1094. /**
  1095. * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
  1096. * of key-value pairs for `object` corresponding to the property names of `props`.
  1097. *
  1098. * @private
  1099. * @param {Object} object The object to query.
  1100. * @param {Array} props The property names to get values for.
  1101. * @returns {Object} Returns the new array of key-value pairs.
  1102. */
  1103. function baseToPairs(object, props) {
  1104. return arrayMap(props, function(key) {
  1105. return [key, object[key]];
  1106. });
  1107. }
  1108. /**
  1109. * The base implementation of `_.unary` without support for storing wrapper metadata.
  1110. *
  1111. * @private
  1112. * @param {Function} func The function to cap arguments for.
  1113. * @returns {Function} Returns the new function.
  1114. */
  1115. function baseUnary(func) {
  1116. return function(value) {
  1117. return func(value);
  1118. };
  1119. }
  1120. /**
  1121. * The base implementation of `_.values` and `_.valuesIn` which creates an
  1122. * array of `object` property values corresponding to the property names
  1123. * of `props`.
  1124. *
  1125. * @private
  1126. * @param {Object} object The object to query.
  1127. * @param {Array} props The property names to get values for.
  1128. * @returns {Object} Returns the array of property values.
  1129. */
  1130. function baseValues(object, props) {
  1131. return arrayMap(props, function(key) {
  1132. return object[key];
  1133. });
  1134. }
  1135. /**
  1136. * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
  1137. * that is not found in the character symbols.
  1138. *
  1139. * @private
  1140. * @param {Array} strSymbols The string symbols to inspect.
  1141. * @param {Array} chrSymbols The character symbols to find.
  1142. * @returns {number} Returns the index of the first unmatched string symbol.
  1143. */
  1144. function charsStartIndex(strSymbols, chrSymbols) {
  1145. var index = -1,
  1146. length = strSymbols.length;
  1147. while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
  1148. return index;
  1149. }
  1150. /**
  1151. * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
  1152. * that is not found in the character symbols.
  1153. *
  1154. * @private
  1155. * @param {Array} strSymbols The string symbols to inspect.
  1156. * @param {Array} chrSymbols The character symbols to find.
  1157. * @returns {number} Returns the index of the last unmatched string symbol.
  1158. */
  1159. function charsEndIndex(strSymbols, chrSymbols) {
  1160. var index = strSymbols.length;
  1161. while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
  1162. return index;
  1163. }
  1164. /**
  1165. * Checks if `value` is a global object.
  1166. *
  1167. * @private
  1168. * @param {*} value The value to check.
  1169. * @returns {null|Object} Returns `value` if it's a global object, else `null`.
  1170. */
  1171. function checkGlobal(value) {
  1172. return (value && value.Object === Object) ? value : null;
  1173. }
  1174. /**
  1175. * Compares values to sort them in ascending order.
  1176. *
  1177. * @private
  1178. * @param {*} value The value to compare.
  1179. * @param {*} other The other value to compare.
  1180. * @returns {number} Returns the sort order indicator for `value`.
  1181. */
  1182. function compareAscending(value, other) {
  1183. if (value !== other) {
  1184. var valIsNull = value === null,
  1185. valIsUndef = value === undefined,
  1186. valIsReflexive = value === value;
  1187. var othIsNull = other === null,
  1188. othIsUndef = other === undefined,
  1189. othIsReflexive = other === other;
  1190. if ((value > other && !othIsNull) || !valIsReflexive ||
  1191. (valIsNull && !othIsUndef && othIsReflexive) ||
  1192. (valIsUndef && othIsReflexive)) {
  1193. return 1;
  1194. }
  1195. if ((value < other && !valIsNull) || !othIsReflexive ||
  1196. (othIsNull && !valIsUndef && valIsReflexive) ||
  1197. (othIsUndef && valIsReflexive)) {
  1198. return -1;
  1199. }
  1200. }
  1201. return 0;
  1202. }
  1203. /**
  1204. * Used by `_.orderBy` to compare multiple properties of a value to another
  1205. * and stable sort them.
  1206. *
  1207. * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
  1208. * specify an order of "desc" for descending or "asc" for ascending sort order
  1209. * of corresponding values.
  1210. *
  1211. * @private
  1212. * @param {Object} object The object to compare.
  1213. * @param {Object} other The other object to compare.
  1214. * @param {boolean[]|string[]} orders The order to sort by for each property.
  1215. * @returns {number} Returns the sort order indicator for `object`.
  1216. */
  1217. function compareMultiple(object, other, orders) {
  1218. var index = -1,
  1219. objCriteria = object.criteria,
  1220. othCriteria = other.criteria,
  1221. length = objCriteria.length,
  1222. ordersLength = orders.length;
  1223. while (++index < length) {
  1224. var result = compareAscending(objCriteria[index], othCriteria[index]);
  1225. if (result) {
  1226. if (index >= ordersLength) {
  1227. return result;
  1228. }
  1229. var order = orders[index];
  1230. return result * (order == 'desc' ? -1 : 1);
  1231. }
  1232. }
  1233. // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
  1234. // that causes it, under certain circumstances, to provide the same value for
  1235. // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
  1236. // for more details.
  1237. //
  1238. // This also ensures a stable sort in V8 and other engines.
  1239. // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
  1240. return object.index - other.index;
  1241. }
  1242. /**
  1243. * Gets the number of `placeholder` occurrences in `array`.
  1244. *
  1245. * @private
  1246. * @param {Array} array The array to inspect.
  1247. * @param {*} placeholder The placeholder to search for.
  1248. * @returns {number} Returns the placeholder count.
  1249. */
  1250. function countHolders(array, placeholder) {
  1251. var length = array.length,
  1252. result = 0;
  1253. while (length--) {
  1254. if (array[length] === placeholder) {
  1255. result++;
  1256. }
  1257. }
  1258. return result;
  1259. }
  1260. /**
  1261. * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
  1262. *
  1263. * @private
  1264. * @param {string} letter The matched letter to deburr.
  1265. * @returns {string} Returns the deburred letter.
  1266. */
  1267. function deburrLetter(letter) {
  1268. return deburredLetters[letter];
  1269. }
  1270. /**
  1271. * Used by `_.escape` to convert characters to HTML entities.
  1272. *
  1273. * @private
  1274. * @param {string} chr The matched character to escape.
  1275. * @returns {string} Returns the escaped character.
  1276. */
  1277. function escapeHtmlChar(chr) {
  1278. return htmlEscapes[chr];
  1279. }
  1280. /**
  1281. * Used by `_.template` to escape characters for inclusion in compiled string literals.
  1282. *
  1283. * @private
  1284. * @param {string} chr The matched character to escape.
  1285. * @returns {string} Returns the escaped character.
  1286. */
  1287. function escapeStringChar(chr) {
  1288. return '\\' + stringEscapes[chr];
  1289. }
  1290. /**
  1291. * Gets the index at which the first occurrence of `NaN` is found in `array`.
  1292. *
  1293. * @private
  1294. * @param {Array} array The array to search.
  1295. * @param {number} fromIndex The index to search from.
  1296. * @param {boolean} [fromRight] Specify iterating from right to left.
  1297. * @returns {number} Returns the index of the matched `NaN`, else `-1`.
  1298. */
  1299. function indexOfNaN(array, fromIndex, fromRight) {
  1300. var length = array.length,
  1301. index = fromIndex + (fromRight ? 0 : -1);
  1302. while ((fromRight ? index-- : ++index < length)) {
  1303. var other = array[index];
  1304. if (other !== other) {
  1305. return index;
  1306. }
  1307. }
  1308. return -1;
  1309. }
  1310. /**
  1311. * Checks if `value` is a host object in IE < 9.
  1312. *
  1313. * @private
  1314. * @param {*} value The value to check.
  1315. * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
  1316. */
  1317. function isHostObject(value) {
  1318. // Many host objects are `Object` objects that can coerce to strings
  1319. // despite having improperly defined `toString` methods.
  1320. var result = false;
  1321. if (value != null && typeof value.toString != 'function') {
  1322. try {
  1323. result = !!(value + '');
  1324. } catch (e) {}
  1325. }
  1326. return result;
  1327. }
  1328. /**
  1329. * Checks if `value` is a valid array-like index.
  1330. *
  1331. * @private
  1332. * @param {*} value The value to check.
  1333. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
  1334. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
  1335. */
  1336. function isIndex(value, length) {
  1337. value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
  1338. length = length == null ? MAX_SAFE_INTEGER : length;
  1339. return value > -1 && value % 1 == 0 && value < length;
  1340. }
  1341. /**
  1342. * Converts `iterator` to an array.
  1343. *
  1344. * @private
  1345. * @param {Object} iterator The iterator to convert.
  1346. * @returns {Array} Returns the converted array.
  1347. */
  1348. function iteratorToArray(iterator) {
  1349. var data,
  1350. result = [];
  1351. while (!(data = iterator.next()).done) {
  1352. result.push(data.value);
  1353. }
  1354. return result;
  1355. }
  1356. /**
  1357. * Converts `map` to an array.
  1358. *
  1359. * @private
  1360. * @param {Object} map The map to convert.
  1361. * @returns {Array} Returns the converted array.
  1362. */
  1363. function mapToArray(map) {
  1364. var index = -1,
  1365. result = Array(map.size);
  1366. map.forEach(function(value, key) {
  1367. result[++index] = [key, value];
  1368. });
  1369. return result;
  1370. }
  1371. /**
  1372. * Replaces all `placeholder` elements in `array` with an internal placeholder
  1373. * and returns an array of their indexes.
  1374. *
  1375. * @private
  1376. * @param {Array} array The array to modify.
  1377. * @param {*} placeholder The placeholder to replace.
  1378. * @returns {Array} Returns the new array of placeholder indexes.
  1379. */
  1380. function replaceHolders(array, placeholder) {
  1381. var index = -1,
  1382. length = array.length,
  1383. resIndex = -1,
  1384. result = [];
  1385. while (++index < length) {
  1386. var value = array[index];
  1387. if (value === placeholder || value === PLACEHOLDER) {
  1388. array[index] = PLACEHOLDER;
  1389. result[++resIndex] = index;
  1390. }
  1391. }
  1392. return result;
  1393. }
  1394. /**
  1395. * Converts `set` to an array.
  1396. *
  1397. * @private
  1398. * @param {Object} set The set to convert.
  1399. * @returns {Array} Returns the converted array.
  1400. */
  1401. function setToArray(set) {
  1402. var index = -1,
  1403. result = Array(set.size);
  1404. set.forEach(function(value) {
  1405. result[++index] = value;
  1406. });
  1407. return result;
  1408. }
  1409. /**
  1410. * Gets the number of symbols in `string`.
  1411. *
  1412. * @private
  1413. * @param {string} string The string to inspect.
  1414. * @returns {number} Returns the string size.
  1415. */
  1416. function stringSize(string) {
  1417. if (!(string && reHasComplexSymbol.test(string))) {
  1418. return string.length;
  1419. }
  1420. var result = reComplexSymbol.lastIndex = 0;
  1421. while (reComplexSymbol.test(string)) {
  1422. result++;
  1423. }
  1424. return result;
  1425. }
  1426. /**
  1427. * Converts `string` to an array.
  1428. *
  1429. * @private
  1430. * @param {string} string The string to convert.
  1431. * @returns {Array} Returns the converted array.
  1432. */
  1433. function stringToArray(string) {
  1434. return string.match(reComplexSymbol);
  1435. }
  1436. /**
  1437. * Used by `_.unescape` to convert HTML entities to characters.
  1438. *
  1439. * @private
  1440. * @param {string} chr The matched character to unescape.
  1441. * @returns {string} Returns the unescaped character.
  1442. */
  1443. function unescapeHtmlChar(chr) {
  1444. return htmlUnescapes[chr];
  1445. }
  1446. /*--------------------------------------------------------------------------*/
  1447. /**
  1448. * Create a new pristine `lodash` function using the `context` object.
  1449. *
  1450. * @static
  1451. * @memberOf _
  1452. * @category Util
  1453. * @param {Object} [context=root] The context object.
  1454. * @returns {Function} Returns a new `lodash` function.
  1455. * @example
  1456. *
  1457. * _.mixin({ 'foo': _.constant('foo') });
  1458. *
  1459. * var lodash = _.runInContext();
  1460. * lodash.mixin({ 'bar': lodash.constant('bar') });
  1461. *
  1462. * _.isFunction(_.foo);
  1463. * // => true
  1464. * _.isFunction(_.bar);
  1465. * // => false
  1466. *
  1467. * lodash.isFunction(lodash.foo);
  1468. * // => false
  1469. * lodash.isFunction(lodash.bar);
  1470. * // => true
  1471. *
  1472. * // Use `context` to mock `Date#getTime` use in `_.now`.
  1473. * var mock = _.runInContext({
  1474. * 'Date': function() {
  1475. * return { 'getTime': getTimeMock };
  1476. * }
  1477. * });
  1478. *
  1479. * // Create a suped-up `defer` in Node.js.
  1480. * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
  1481. */
  1482. function runInContext(context) {
  1483. context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root;
  1484. /** Built-in constructor references. */
  1485. var Date = context.Date,
  1486. Error = context.Error,
  1487. Math = context.Math,
  1488. RegExp = context.RegExp,
  1489. TypeError = context.TypeError;
  1490. /** Used for built-in method references. */
  1491. var arrayProto = context.Array.prototype,
  1492. objectProto = context.Object.prototype;
  1493. /** Used to resolve the decompiled source of functions. */
  1494. var funcToString = context.Function.prototype.toString;
  1495. /** Used to check objects for own properties. */
  1496. var hasOwnProperty = objectProto.hasOwnProperty;
  1497. /** Used to generate unique IDs. */
  1498. var idCounter = 0;
  1499. /** Used to infer the `Object` constructor. */
  1500. var objectCtorString = funcToString.call(Object);
  1501. /**
  1502. * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
  1503. * of values.
  1504. */
  1505. var objectToString = objectProto.toString;
  1506. /** Used to restore the original `_` reference in `_.noConflict`. */
  1507. var oldDash = root._;
  1508. /** Used to detect if a method is native. */
  1509. var reIsNative = RegExp('^' +
  1510. funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  1511. .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  1512. );
  1513. /** Built-in value references. */
  1514. var Buffer = moduleExports ? context.Buffer : undefined,
  1515. Reflect = context.Reflect,
  1516. Symbol = context.Symbol,
  1517. Uint8Array = context.Uint8Array,
  1518. clearTimeout = context.clearTimeout,
  1519. enumerate = Reflect ? Reflect.enumerate : undefined,
  1520. getPrototypeOf = Object.getPrototypeOf,
  1521. getOwnPropertySymbols = Object.getOwnPropertySymbols,
  1522. iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
  1523. objectCreate = Object.create,
  1524. propertyIsEnumerable = objectProto.propertyIsEnumerable,
  1525. setTimeout = context.setTimeout,
  1526. splice = arrayProto.splice;
  1527. /* Built-in method references for those with the same name as other `lodash` methods. */
  1528. var nativeCeil = Math.ceil,
  1529. nativeFloor = Math.floor,
  1530. nativeIsFinite = context.isFinite,
  1531. nativeJoin = arrayProto.join,
  1532. nativeKeys = Object.keys,
  1533. nativeMax = Math.max,
  1534. nativeMin = Math.min,
  1535. nativeParseInt = context.parseInt,
  1536. nativeRandom = Math.random,
  1537. nativeReverse = arrayProto.reverse;
  1538. /* Built-in method references that are verified to be native. */
  1539. var Map = getNative(context, 'Map'),
  1540. Set = getNative(context, 'Set'),
  1541. WeakMap = getNative(context, 'WeakMap'),
  1542. nativeCreate = getNative(Object, 'create');
  1543. /** Used to store function metadata. */
  1544. var metaMap = WeakMap && new WeakMap;
  1545. /** Used to detect maps, sets, and weakmaps. */
  1546. var mapCtorString = Map ? funcToString.call(Map) : '',
  1547. setCtorString = Set ? funcToString.call(Set) : '',
  1548. weakMapCtorString = WeakMap ? funcToString.call(WeakMap) : '';
  1549. /** Used to convert symbols to primitives and strings. */
  1550. var symbolProto = Symbol ? Symbol.prototype : undefined,
  1551. symbolValueOf = Symbol ? symbolProto.valueOf : undefined,
  1552. symbolToString = Symbol ? symbolProto.toString : undefined;
  1553. /** Used to lookup unminified function names. */
  1554. var realNames = {};
  1555. /*------------------------------------------------------------------------*/
  1556. /**
  1557. * Creates a `lodash` object which wraps `value` to enable implicit method
  1558. * chaining. Methods that operate on and return arrays, collections, and
  1559. * functions can be chained together. Methods that retrieve a single value or
  1560. * may return a primitive value will automatically end the chain sequence and
  1561. * return the unwrapped value. Otherwise, the value must be unwrapped with
  1562. * `_#value`.
  1563. *
  1564. * Explicit chaining, which must be unwrapped with `_#value` in all cases,
  1565. * may be enabled using `_.chain`.
  1566. *
  1567. * The execution of chained methods is lazy, that is, it's deferred until
  1568. * `_#value` is implicitly or explicitly called.
  1569. *
  1570. * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
  1571. * fusion is an optimization to merge iteratee calls; this avoids the creation
  1572. * of intermediate arrays and can greatly reduce the number of iteratee executions.
  1573. * Sections of a chain sequence qualify for shortcut fusion if the section is
  1574. * applied to an array of at least two hundred elements and any iteratees
  1575. * accept only one argument. The heuristic for whether a section qualifies
  1576. * for shortcut fusion is subject to change.
  1577. *
  1578. * Chaining is supported in custom builds as long as the `_#value` method is
  1579. * directly or indirectly included in the build.
  1580. *
  1581. * In addition to lodash methods, wrappers have `Array` and `String` methods.
  1582. *
  1583. * The wrapper `Array` methods are:
  1584. * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
  1585. *
  1586. * The wrapper `String` methods are:
  1587. * `replace` and `split`
  1588. *
  1589. * The wrapper methods that support shortcut fusion are:
  1590. * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
  1591. * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
  1592. * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
  1593. *
  1594. * The chainable wrapper methods are:
  1595. * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
  1596. * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
  1597. * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
  1598. * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, `difference`,
  1599. * `differenceBy`, `differenceWith`, `drop`, `dropRight`, `dropRightWhile`,
  1600. * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flattenDepth`,
  1601. * `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, `functionsIn`,
  1602. * `groupBy`, `initial`, `intersection`, `intersectionBy`, `intersectionWith`,
  1603. * `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, `keys`, `keysIn`,
  1604. * `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
  1605. * `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, `nthArg`,
  1606. * `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, `overEvery`,
  1607. * `overSome`, `partial`, `partialRight`, `partition`, `pick`, `pickBy`, `plant`,
  1608. * `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, `pullAt`, `push`,
  1609. * `range`, `rangeRight`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
  1610. * `sampleSize`, `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`,
  1611. * `splice`, `spread`, `tail`, `take`, `takeRight`, `takeRightWhile`,
  1612. * `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, `toPairs`, `toPairsIn`,
  1613. * `toPath`, `toPlainObject`, `transform`, `unary`, `union`, `unionBy`,
  1614. * `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, `unshift`, `unzip`,
  1615. * `unzipWith`, `values`, `valuesIn`, `without`, `wrap`, `xor`, `xorBy`,
  1616. * `xorWith`, `zip`, `zipObject`, `zipObjectDeep`, and `zipWith`
  1617. *
  1618. * The wrapper methods that are **not** chainable by default are:
  1619. * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
  1620. * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `endsWith`, `eq`,
  1621. * `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
  1622. * `findLastIndex`, `findLastKey`, `floor`, `forEach`, `forEachRight`, `forIn`,
  1623. * `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`,
  1624. * `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`,
  1625. * `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`,
  1626. * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
  1627. * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`,
  1628. * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
  1629. * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`,
  1630. * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
  1631. * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`,
  1632. * `lt`, `lte`, `max`, `maxBy`, `mean`, `min`, `minBy`, `noConflict`, `noop`,
  1633. * `now`, `pad`, `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`,
  1634. * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `sample`,
  1635. * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`,
  1636. * `sortedLastIndex`, `sortedLastIndexBy`, `startCase`, `startsWith`, `subtract`,
  1637. * `sum`, `sumBy`, `template`, `times`, `toLower`, `toInteger`, `toLength`,
  1638. * `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, `trimEnd`,
  1639. * `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, `upperFirst`,
  1640. * `value`, and `words`
  1641. *
  1642. * @name _
  1643. * @constructor
  1644. * @category Seq
  1645. * @param {*} value The value to wrap in a `lodash` instance.
  1646. * @returns {Object} Returns the new `lodash` wrapper instance.
  1647. * @example
  1648. *
  1649. * function square(n) {
  1650. * return n * n;
  1651. * }
  1652. *
  1653. * var wrapped = _([1, 2, 3]);
  1654. *
  1655. * // Returns an unwrapped value.
  1656. * wrapped.reduce(_.add);
  1657. * // => 6
  1658. *
  1659. * // Returns a wrapped value.
  1660. * var squares = wrapped.map(square);
  1661. *
  1662. * _.isArray(squares);
  1663. * // => false
  1664. *
  1665. * _.isArray(squares.value());
  1666. * // => true
  1667. */
  1668. function lodash(value) {
  1669. if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
  1670. if (value instanceof LodashWrapper) {
  1671. return value;
  1672. }
  1673. if (hasOwnProperty.call(value, '__wrapped__')) {
  1674. return wrapperClone(value);
  1675. }
  1676. }
  1677. return new LodashWrapper(value);
  1678. }
  1679. /**
  1680. * The function whose prototype all chaining wrappers inherit from.
  1681. *
  1682. * @private
  1683. */
  1684. function baseLodash() {
  1685. // No operation performed.
  1686. }
  1687. /**
  1688. * The base constructor for creating `lodash` wrapper objects.
  1689. *
  1690. * @private
  1691. * @param {*} value The value to wrap.
  1692. * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
  1693. */
  1694. function LodashWrapper(value, chainAll) {
  1695. this.__wrapped__ = value;
  1696. this.__actions__ = [];
  1697. this.__chain__ = !!chainAll;
  1698. this.__index__ = 0;
  1699. this.__values__ = undefined;
  1700. }
  1701. /**
  1702. * By default, the template delimiters used by lodash are like those in
  1703. * embedded Ruby (ERB). Change the following template settings to use
  1704. * alternative delimiters.
  1705. *
  1706. * @static
  1707. * @memberOf _
  1708. * @type {Object}
  1709. */
  1710. lodash.templateSettings = {
  1711. /**
  1712. * Used to detect `data` property values to be HTML-escaped.
  1713. *
  1714. * @memberOf _.templateSettings
  1715. * @type {RegExp}
  1716. */
  1717. 'escape': reEscape,
  1718. /**
  1719. * Used to detect code to be evaluated.
  1720. *
  1721. * @memberOf _.templateSettings
  1722. * @type {RegExp}
  1723. */
  1724. 'evaluate': reEvaluate,
  1725. /**
  1726. * Used to detect `data` property values to inject.
  1727. *
  1728. * @memberOf _.templateSettings
  1729. * @type {RegExp}
  1730. */
  1731. 'interpolate': reInterpolate,
  1732. /**
  1733. * Used to reference the data object in the template text.
  1734. *
  1735. * @memberOf _.templateSettings
  1736. * @type {string}
  1737. */
  1738. 'variable': '',
  1739. /**
  1740. * Used to import variables into the compiled template.
  1741. *
  1742. * @memberOf _.templateSettings
  1743. * @type {Object}
  1744. */
  1745. 'imports': {
  1746. /**
  1747. * A reference to the `lodash` function.
  1748. *
  1749. * @memberOf _.templateSettings.imports
  1750. * @type {Function}
  1751. */
  1752. '_': lodash
  1753. }
  1754. };
  1755. /*------------------------------------------------------------------------*/
  1756. /**
  1757. * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
  1758. *
  1759. * @private
  1760. * @constructor
  1761. * @param {*} value The value to wrap.
  1762. */
  1763. function LazyWrapper(value) {
  1764. this.__wrapped__ = value;
  1765. this.__actions__ = [];
  1766. this.__dir__ = 1;
  1767. this.__filtered__ = false;
  1768. this.__iteratees__ = [];
  1769. this.__takeCount__ = MAX_ARRAY_LENGTH;
  1770. this.__views__ = [];
  1771. }
  1772. /**
  1773. * Creates a clone of the lazy wrapper object.
  1774. *
  1775. * @private
  1776. * @name clone
  1777. * @memberOf LazyWrapper
  1778. * @returns {Object} Returns the cloned `LazyWrapper` object.
  1779. */
  1780. function lazyClone() {
  1781. var result = new LazyWrapper(this.__wrapped__);
  1782. result.__actions__ = copyArray(this.__actions__);
  1783. result.__dir__ = this.__dir__;
  1784. result.__filtered__ = this.__filtered__;
  1785. result.__iteratees__ = copyArray(this.__iteratees__);
  1786. result.__takeCount__ = this.__takeCount__;
  1787. result.__views__ = copyArray(this.__views__);
  1788. return result;
  1789. }
  1790. /**
  1791. * Reverses the direction of lazy iteration.
  1792. *
  1793. * @private
  1794. * @name reverse
  1795. * @memberOf LazyWrapper
  1796. * @returns {Object} Returns the new reversed `LazyWrapper` object.
  1797. */
  1798. function lazyReverse() {
  1799. if (this.__filtered__) {
  1800. var result = new LazyWrapper(this);
  1801. result.__dir__ = -1;
  1802. result.__filtered__ = true;
  1803. } else {
  1804. result = this.clone();
  1805. result.__dir__ *= -1;
  1806. }
  1807. return result;
  1808. }
  1809. /**
  1810. * Extracts the unwrapped value from its lazy wrapper.
  1811. *
  1812. * @private
  1813. * @name value
  1814. * @memberOf LazyWrapper
  1815. * @returns {*} Returns the unwrapped value.
  1816. */
  1817. function lazyValue() {
  1818. var array = this.__wrapped__.value(),
  1819. dir = this.__dir__,
  1820. isArr = isArray(array),
  1821. isRight = dir < 0,
  1822. arrLength = isArr ? array.length : 0,
  1823. view = getView(0, arrLength, this.__views__),
  1824. start = view.start,
  1825. end = view.end,
  1826. length = end - start,
  1827. index = isRight ? end : (start - 1),
  1828. iteratees = this.__iteratees__,
  1829. iterLength = iteratees.length,
  1830. resIndex = 0,
  1831. takeCount = nativeMin(length, this.__takeCount__);
  1832. if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
  1833. (arrLength == length && takeCount == length)) {
  1834. return baseWrapperValue(array, this.__actions__);
  1835. }
  1836. var result = [];
  1837. outer:
  1838. while (length-- && resIndex < takeCount) {
  1839. index += dir;
  1840. var iterIndex = -1,
  1841. value = array[index];
  1842. while (++iterIndex < iterLength) {
  1843. var data = iteratees[iterIndex],
  1844. iteratee = data.iteratee,
  1845. type = data.type,
  1846. computed = iteratee(value);
  1847. if (type == LAZY_MAP_FLAG) {
  1848. value = computed;
  1849. } else if (!computed) {
  1850. if (type == LAZY_FILTER_FLAG) {
  1851. continue outer;
  1852. } else {
  1853. break outer;
  1854. }
  1855. }
  1856. }
  1857. result[resIndex++] = value;
  1858. }
  1859. return result;
  1860. }
  1861. /*------------------------------------------------------------------------*/
  1862. /**
  1863. * Creates an hash object.
  1864. *
  1865. * @private
  1866. * @constructor
  1867. * @returns {Object} Returns the new hash object.
  1868. */
  1869. function Hash() {}
  1870. /**
  1871. * Removes `key` and its value from the hash.
  1872. *
  1873. * @private
  1874. * @param {Object} hash The hash to modify.
  1875. * @param {string} key The key of the value to remove.
  1876. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  1877. */
  1878. function hashDelete(hash, key) {
  1879. return hashHas(hash, key) && delete hash[key];
  1880. }
  1881. /**
  1882. * Gets the hash value for `key`.
  1883. *
  1884. * @private
  1885. * @param {Object} hash The hash to query.
  1886. * @param {string} key The key of the value to get.
  1887. * @returns {*} Returns the entry value.
  1888. */
  1889. function hashGet(hash, key) {
  1890. if (nativeCreate) {
  1891. var result = hash[key];
  1892. return result === HASH_UNDEFINED ? undefined : result;
  1893. }
  1894. return hasOwnProperty.call(hash, key) ? hash[key] : undefined;
  1895. }
  1896. /**
  1897. * Checks if a hash value for `key` exists.
  1898. *
  1899. * @private
  1900. * @param {Object} hash The hash to query.
  1901. * @param {string} key The key of the entry to check.
  1902. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  1903. */
  1904. function hashHas(hash, key) {
  1905. return nativeCreate ? hash[key] !== undefined : hasOwnProperty.call(hash, key);
  1906. }
  1907. /**
  1908. * Sets the hash `key` to `value`.
  1909. *
  1910. * @private
  1911. * @param {Object} hash The hash to modify.
  1912. * @param {string} key The key of the value to set.
  1913. * @param {*} value The value to set.
  1914. */
  1915. function hashSet(hash, key, value) {
  1916. hash[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  1917. }
  1918. /*------------------------------------------------------------------------*/
  1919. /**
  1920. * Creates a map cache object to store key-value pairs.
  1921. *
  1922. * @private
  1923. * @constructor
  1924. * @param {Array} [values] The values to cache.
  1925. */
  1926. function MapCache(values) {
  1927. var index = -1,
  1928. length = values ? values.length : 0;
  1929. this.clear();
  1930. while (++index < length) {
  1931. var entry = values[index];
  1932. this.set(entry[0], entry[1]);
  1933. }
  1934. }
  1935. /**
  1936. * Removes all key-value entries from the map.
  1937. *
  1938. * @private
  1939. * @name clear
  1940. * @memberOf MapCache
  1941. */
  1942. function mapClear() {
  1943. this.__data__ = {
  1944. 'hash': new Hash,
  1945. 'map': Map ? new Map : [],
  1946. 'string': new Hash
  1947. };
  1948. }
  1949. /**
  1950. * Removes `key` and its value from the map.
  1951. *
  1952. * @private
  1953. * @name delete
  1954. * @memberOf MapCache
  1955. * @param {string} key The key of the value to remove.
  1956. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  1957. */
  1958. function mapDelete(key) {
  1959. var data = this.__data__;
  1960. if (isKeyable(key)) {
  1961. return hashDelete(typeof key == 'string' ? data.string : data.hash, key);
  1962. }
  1963. return Map ? data.map['delete'](key) : assocDelete(data.map, key);
  1964. }
  1965. /**
  1966. * Gets the map value for `key`.
  1967. *
  1968. * @private
  1969. * @name get
  1970. * @memberOf MapCache
  1971. * @param {string} key The key of the value to get.
  1972. * @returns {*} Returns the entry value.
  1973. */
  1974. function mapGet(key) {
  1975. var data = this.__data__;
  1976. if (isKeyable(key)) {
  1977. return hashGet(typeof key == 'string' ? data.string : data.hash, key);
  1978. }
  1979. return Map ? data.map.get(key) : assocGet(data.map, key);
  1980. }
  1981. /**
  1982. * Checks if a map value for `key` exists.
  1983. *
  1984. * @private
  1985. * @name has
  1986. * @memberOf MapCache
  1987. * @param {string} key The key of the entry to check.
  1988. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  1989. */
  1990. function mapHas(key) {
  1991. var data = this.__data__;
  1992. if (isKeyable(key)) {
  1993. return hashHas(typeof key == 'string' ? data.string : data.hash, key);
  1994. }
  1995. return Map ? data.map.has(key) : assocHas(data.map, key);
  1996. }
  1997. /**
  1998. * Sets the map `key` to `value`.
  1999. *
  2000. * @private
  2001. * @name set
  2002. * @memberOf MapCache
  2003. * @param {string} key The key of the value to set.
  2004. * @param {*} value The value to set.
  2005. * @returns {Object} Returns the map cache object.
  2006. */
  2007. function mapSet(key, value) {
  2008. var data = this.__data__;
  2009. if (isKeyable(key)) {
  2010. hashSet(typeof key == 'string' ? data.string : data.hash, key, value);
  2011. } else if (Map) {
  2012. data.map.set(key, value);
  2013. } else {
  2014. assocSet(data.map, key, value);
  2015. }
  2016. return this;
  2017. }
  2018. /*------------------------------------------------------------------------*/
  2019. /**
  2020. *
  2021. * Creates a set cache object to store unique values.
  2022. *
  2023. * @private
  2024. * @constructor
  2025. * @param {Array} [values] The values to cache.
  2026. */
  2027. function SetCache(values) {
  2028. var index = -1,
  2029. length = values ? values.length : 0;
  2030. this.__data__ = new MapCache;
  2031. while (++index < length) {
  2032. this.push(values[index]);
  2033. }
  2034. }
  2035. /**
  2036. * Checks if `value` is in `cache`.
  2037. *
  2038. * @private
  2039. * @param {Object} cache The set cache to search.
  2040. * @param {*} value The value to search for.
  2041. * @returns {number} Returns `true` if `value` is found, else `false`.
  2042. */
  2043. function cacheHas(cache, value) {
  2044. var map = cache.__data__;
  2045. if (isKeyable(value)) {
  2046. var data = map.__data__,
  2047. hash = typeof value == 'string' ? data.string : data.hash;
  2048. return hash[value] === HASH_UNDEFINED;
  2049. }
  2050. return map.has(value);
  2051. }
  2052. /**
  2053. * Adds `value` to the set cache.
  2054. *
  2055. * @private
  2056. * @name push
  2057. * @memberOf SetCache
  2058. * @param {*} value The value to cache.
  2059. */
  2060. function cachePush(value) {
  2061. var map = this.__data__;
  2062. if (isKeyable(value)) {
  2063. var data = map.__data__,
  2064. hash = typeof value == 'string' ? data.string : data.hash;
  2065. hash[value] = HASH_UNDEFINED;
  2066. }
  2067. else {
  2068. map.set(value, HASH_UNDEFINED);
  2069. }
  2070. }
  2071. /*------------------------------------------------------------------------*/
  2072. /**
  2073. * Creates a stack cache object to store key-value pairs.
  2074. *
  2075. * @private
  2076. * @constructor
  2077. * @param {Array} [values] The values to cache.
  2078. */
  2079. function Stack(values) {
  2080. var index = -1,
  2081. length = values ? values.length : 0;
  2082. this.clear();
  2083. while (++index < length) {
  2084. var entry = values[index];
  2085. this.set(entry[0], entry[1]);
  2086. }
  2087. }
  2088. /**
  2089. * Removes all key-value entries from the stack.
  2090. *
  2091. * @private
  2092. * @name clear
  2093. * @memberOf Stack
  2094. */
  2095. function stackClear() {
  2096. this.__data__ = { 'array': [], 'map': null };
  2097. }
  2098. /**
  2099. * Removes `key` and its value from the stack.
  2100. *
  2101. * @private
  2102. * @name delete
  2103. * @memberOf Stack
  2104. * @param {string} key The key of the value to remove.
  2105. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  2106. */
  2107. function stackDelete(key) {
  2108. var data = this.__data__,
  2109. array = data.array;
  2110. return array ? assocDelete(array, key) : data.map['delete'](key);
  2111. }
  2112. /**
  2113. * Gets the stack value for `key`.
  2114. *
  2115. * @private
  2116. * @name get
  2117. * @memberOf Stack
  2118. * @param {string} key The key of the value to get.
  2119. * @returns {*} Returns the entry value.
  2120. */
  2121. function stackGet(key) {
  2122. var data = this.__data__,
  2123. array = data.array;
  2124. return array ? assocGet(array, key) : data.map.get(key);
  2125. }
  2126. /**
  2127. * Checks if a stack value for `key` exists.
  2128. *
  2129. * @private
  2130. * @name has
  2131. * @memberOf Stack
  2132. * @param {string} key The key of the entry to check.
  2133. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  2134. */
  2135. function stackHas(key) {
  2136. var data = this.__data__,
  2137. array = data.array;
  2138. return array ? assocHas(array, key) : data.map.has(key);
  2139. }
  2140. /**
  2141. * Sets the stack `key` to `value`.
  2142. *
  2143. * @private
  2144. * @name set
  2145. * @memberOf Stack
  2146. * @param {string} key The key of the value to set.
  2147. * @param {*} value The value to set.
  2148. * @returns {Object} Returns the stack cache object.
  2149. */
  2150. function stackSet(key, value) {
  2151. var data = this.__data__,
  2152. array = data.array;
  2153. if (array) {
  2154. if (array.length < (LARGE_ARRAY_SIZE - 1)) {
  2155. assocSet(array, key, value);
  2156. } else {
  2157. data.array = null;
  2158. data.map = new MapCache(array);
  2159. }
  2160. }
  2161. var map = data.map;
  2162. if (map) {
  2163. map.set(key, value);
  2164. }
  2165. return this;
  2166. }
  2167. /*------------------------------------------------------------------------*/
  2168. /**
  2169. * Removes `key` and its value from the associative array.
  2170. *
  2171. * @private
  2172. * @param {Array} array The array to query.
  2173. * @param {string} key The key of the value to remove.
  2174. * @returns {boolean} Returns `true` if the entry was removed, else `false`.
  2175. */
  2176. function assocDelete(array, key) {
  2177. var index = assocIndexOf(array, key);
  2178. if (index < 0) {
  2179. return false;
  2180. }
  2181. var lastIndex = array.length - 1;
  2182. if (index == lastIndex) {
  2183. array.pop();
  2184. } else {
  2185. splice.call(array, index, 1);
  2186. }
  2187. return true;
  2188. }
  2189. /**
  2190. * Gets the associative array value for `key`.
  2191. *
  2192. * @private
  2193. * @param {Array} array The array to query.
  2194. * @param {string} key The key of the value to get.
  2195. * @returns {*} Returns the entry value.
  2196. */
  2197. function assocGet(array, key) {
  2198. var index = assocIndexOf(array, key);
  2199. return index < 0 ? undefined : array[index][1];
  2200. }
  2201. /**
  2202. * Checks if an associative array value for `key` exists.
  2203. *
  2204. * @private
  2205. * @param {Array} array The array to query.
  2206. * @param {string} key The key of the entry to check.
  2207. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  2208. */
  2209. function assocHas(array, key) {
  2210. return assocIndexOf(array, key) > -1;
  2211. }
  2212. /**
  2213. * Gets the index at which the first occurrence of `key` is found in `array`
  2214. * of key-value pairs.
  2215. *
  2216. * @private
  2217. * @param {Array} array The array to search.
  2218. * @param {*} key The key to search for.
  2219. * @returns {number} Returns the index of the matched value, else `-1`.
  2220. */
  2221. function assocIndexOf(array, key) {
  2222. var length = array.length;
  2223. while (length--) {
  2224. if (eq(array[length][0], key)) {
  2225. return length;
  2226. }
  2227. }
  2228. return -1;
  2229. }
  2230. /**
  2231. * Sets the associative array `key` to `value`.
  2232. *
  2233. * @private
  2234. * @param {Array} array The array to modify.
  2235. * @param {string} key The key of the value to set.
  2236. * @param {*} value The value to set.
  2237. */
  2238. function assocSet(array, key, value) {
  2239. var index = assocIndexOf(array, key);
  2240. if (index < 0) {
  2241. array.push([key, value]);
  2242. } else {
  2243. array[index][1] = value;
  2244. }
  2245. }
  2246. /*------------------------------------------------------------------------*/
  2247. /**
  2248. * Used by `_.defaults` to customize its `_.assignIn` use.
  2249. *
  2250. * @private
  2251. * @param {*} objValue The destination value.
  2252. * @param {*} srcValue The source value.
  2253. * @param {string} key The key of the property to assign.
  2254. * @param {Object} object The parent object of `objValue`.
  2255. * @returns {*} Returns the value to assign.
  2256. */
  2257. function assignInDefaults(objValue, srcValue, key, object) {
  2258. if (objValue === undefined ||
  2259. (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
  2260. return srcValue;
  2261. }
  2262. return objValue;
  2263. }
  2264. /**
  2265. * This function is like `assignValue` except that it doesn't assign `undefined` values.
  2266. *
  2267. * @private
  2268. * @param {Object} object The object to modify.
  2269. * @param {string} key The key of the property to assign.
  2270. * @param {*} value The value to assign.
  2271. */
  2272. function assignMergeValue(object, key, value) {
  2273. if ((value !== undefined && !eq(object[key], value)) ||
  2274. (typeof key == 'number' && value === undefined && !(key in object))) {
  2275. object[key] = value;
  2276. }
  2277. }
  2278. /**
  2279. * Assigns `value` to `key` of `object` if the existing value is not equivalent
  2280. * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  2281. * for equality comparisons.
  2282. *
  2283. * @private
  2284. * @param {Object} object The object to modify.
  2285. * @param {string} key The key of the property to assign.
  2286. * @param {*} value The value to assign.
  2287. */
  2288. function assignValue(object, key, value) {
  2289. var objValue = object[key];
  2290. if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
  2291. (value === undefined && !(key in object))) {
  2292. object[key] = value;
  2293. }
  2294. }
  2295. /**
  2296. * Aggregates elements of `collection` on `accumulator` with keys transformed
  2297. * by `iteratee` and values set by `setter`.
  2298. *
  2299. * @private
  2300. * @param {Array|Object} collection The collection to iterate over.
  2301. * @param {Function} setter The function to set `accumulator` values.
  2302. * @param {Function} iteratee The iteratee to transform keys.
  2303. * @param {Object} accumulator The initial aggregated object.
  2304. * @returns {Function} Returns `accumulator`.
  2305. */
  2306. function baseAggregator(collection, setter, iteratee, accumulator) {
  2307. baseEach(collection, function(value, key, collection) {
  2308. setter(accumulator, value, iteratee(value), collection);
  2309. });
  2310. return accumulator;
  2311. }
  2312. /**
  2313. * The base implementation of `_.assign` without support for multiple sources
  2314. * or `customizer` functions.
  2315. *
  2316. * @private
  2317. * @param {Object} object The destination object.
  2318. * @param {Object} source The source object.
  2319. * @returns {Object} Returns `object`.
  2320. */
  2321. function baseAssign(object, source) {
  2322. return object && copyObject(source, keys(source), object);
  2323. }
  2324. /**
  2325. * The base implementation of `_.at` without support for individual paths.
  2326. *
  2327. * @private
  2328. * @param {Object} object The object to iterate over.
  2329. * @param {string[]} paths The property paths of elements to pick.
  2330. * @returns {Array} Returns the new array of picked elements.
  2331. */
  2332. function baseAt(object, paths) {
  2333. var index = -1,
  2334. isNil = object == null,
  2335. length = paths.length,
  2336. result = Array(length);
  2337. while (++index < length) {
  2338. result[index] = isNil ? undefined : get(object, paths[index]);
  2339. }
  2340. return result;
  2341. }
  2342. /**
  2343. * Casts `value` to an empty array if it's not an array like object.
  2344. *
  2345. * @private
  2346. * @param {*} value The value to inspect.
  2347. * @returns {Array} Returns the array-like object.
  2348. */
  2349. function baseCastArrayLikeObject(value) {
  2350. return isArrayLikeObject(value) ? value : [];
  2351. }
  2352. /**
  2353. * Casts `value` to `identity` if it's not a function.
  2354. *
  2355. * @private
  2356. * @param {*} value The value to inspect.
  2357. * @returns {Array} Returns the array-like object.
  2358. */
  2359. function baseCastFunction(value) {
  2360. return typeof value == 'function' ? value : identity;
  2361. }
  2362. /**
  2363. * Casts `value` to a path array if it's not one.
  2364. *
  2365. * @private
  2366. * @param {*} value The value to inspect.
  2367. * @returns {Array} Returns the cast property path array.
  2368. */
  2369. function baseCastPath(value) {
  2370. return isArray(value) ? value : stringToPath(value);
  2371. }
  2372. /**
  2373. * The base implementation of `_.clamp` which doesn't coerce arguments to numbers.
  2374. *
  2375. * @private
  2376. * @param {number} number The number to clamp.
  2377. * @param {number} [lower] The lower bound.
  2378. * @param {number} upper The upper bound.
  2379. * @returns {number} Returns the clamped number.
  2380. */
  2381. function baseClamp(number, lower, upper) {
  2382. if (number === number) {
  2383. if (upper !== undefined) {
  2384. number = number <= upper ? number : upper;
  2385. }
  2386. if (lower !== undefined) {
  2387. number = number >= lower ? number : lower;
  2388. }
  2389. }
  2390. return number;
  2391. }
  2392. /**
  2393. * The base implementation of `_.clone` and `_.cloneDeep` which tracks
  2394. * traversed objects.
  2395. *
  2396. * @private
  2397. * @param {*} value The value to clone.
  2398. * @param {boolean} [isDeep] Specify a deep clone.
  2399. * @param {Function} [customizer] The function to customize cloning.
  2400. * @param {string} [key] The key of `value`.
  2401. * @param {Object} [object] The parent object of `value`.
  2402. * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
  2403. * @returns {*} Returns the cloned value.
  2404. */
  2405. function baseClone(value, isDeep, customizer, key, object, stack) {
  2406. var result;
  2407. if (customizer) {
  2408. result = object ? customizer(value, key, object, stack) : customizer(value);
  2409. }
  2410. if (result !== undefined) {
  2411. return result;
  2412. }
  2413. if (!isObject(value)) {
  2414. return value;
  2415. }
  2416. var isArr = isArray(value);
  2417. if (isArr) {
  2418. result = initCloneArray(value);
  2419. if (!isDeep) {
  2420. return copyArray(value, result);
  2421. }
  2422. } else {
  2423. var tag = getTag(value),
  2424. isFunc = tag == funcTag || tag == genTag;
  2425. if (isBuffer(value)) {
  2426. return cloneBuffer(value, isDeep);
  2427. }
  2428. if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
  2429. if (isHostObject(value)) {
  2430. return object ? value : {};
  2431. }
  2432. result = initCloneObject(isFunc ? {} : value);
  2433. if (!isDeep) {
  2434. return copySymbols(value, baseAssign(result, value));
  2435. }
  2436. } else {
  2437. if (!cloneableTags[tag]) {
  2438. return object ? value : {};
  2439. }
  2440. result = initCloneByTag(value, tag, isDeep);
  2441. }
  2442. }
  2443. // Check for circular references and return its corresponding clone.
  2444. stack || (stack = new Stack);
  2445. var stacked = stack.get(value);
  2446. if (stacked) {
  2447. return stacked;
  2448. }
  2449. stack.set(value, result);
  2450. // Recursively populate clone (susceptible to call stack limits).
  2451. (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
  2452. assignValue(result, key, baseClone(subValue, isDeep, customizer, key, value, stack));
  2453. });
  2454. return isArr ? result : copySymbols(value, result);
  2455. }
  2456. /**
  2457. * The base implementation of `_.conforms` which doesn't clone `source`.
  2458. *
  2459. * @private
  2460. * @param {Object} source The object of property predicates to conform to.
  2461. * @returns {Function} Returns the new function.
  2462. */
  2463. function baseConforms(source) {
  2464. var props = keys(source),
  2465. length = props.length;
  2466. return function(object) {
  2467. if (object == null) {
  2468. return !length;
  2469. }
  2470. var index = length;
  2471. while (index--) {
  2472. var key = props[index],
  2473. predicate = source[key],
  2474. value = object[key];
  2475. if ((value === undefined && !(key in Object(object))) || !predicate(value)) {
  2476. return false;
  2477. }
  2478. }
  2479. return true;
  2480. };
  2481. }
  2482. /**
  2483. * The base implementation of `_.create` without support for assigning
  2484. * properties to the created object.
  2485. *
  2486. * @private
  2487. * @param {Object} prototype The object to inherit from.
  2488. * @returns {Object} Returns the new object.
  2489. */
  2490. function baseCreate(proto) {
  2491. return isObject(proto) ? objectCreate(proto) : {};
  2492. }
  2493. /**
  2494. * The base implementation of `_.delay` and `_.defer` which accepts an array
  2495. * of `func` arguments.
  2496. *
  2497. * @private
  2498. * @param {Function} func The function to delay.
  2499. * @param {number} wait The number of milliseconds to delay invocation.
  2500. * @param {Object} args The arguments to provide to `func`.
  2501. * @returns {number} Returns the timer id.
  2502. */
  2503. function baseDelay(func, wait, args) {
  2504. if (typeof func != 'function') {
  2505. throw new TypeError(FUNC_ERROR_TEXT);
  2506. }
  2507. return setTimeout(function() { func.apply(undefined, args); }, wait);
  2508. }
  2509. /**
  2510. * The base implementation of methods like `_.difference` without support for
  2511. * excluding multiple arrays or iteratee shorthands.
  2512. *
  2513. * @private
  2514. * @param {Array} array The array to inspect.
  2515. * @param {Array} values The values to exclude.
  2516. * @param {Function} [iteratee] The iteratee invoked per element.
  2517. * @param {Function} [comparator] The comparator invoked per element.
  2518. * @returns {Array} Returns the new array of filtered values.
  2519. */
  2520. function baseDifference(array, values, iteratee, comparator) {
  2521. var index = -1,
  2522. includes = arrayIncludes,
  2523. isCommon = true,
  2524. length = array.length,
  2525. result = [],
  2526. valuesLength = values.length;
  2527. if (!length) {
  2528. return result;
  2529. }
  2530. if (iteratee) {
  2531. values = arrayMap(values, baseUnary(iteratee));
  2532. }
  2533. if (comparator) {
  2534. includes = arrayIncludesWith;
  2535. isCommon = false;
  2536. }
  2537. else if (values.length >= LARGE_ARRAY_SIZE) {
  2538. includes = cacheHas;
  2539. isCommon = false;
  2540. values = new SetCache(values);
  2541. }
  2542. outer:
  2543. while (++index < length) {
  2544. var value = array[index],
  2545. computed = iteratee ? iteratee(value) : value;
  2546. if (isCommon && computed === computed) {
  2547. var valuesIndex = valuesLength;
  2548. while (valuesIndex--) {
  2549. if (values[valuesIndex] === computed) {
  2550. continue outer;
  2551. }
  2552. }
  2553. result.push(value);
  2554. }
  2555. else if (!includes(values, computed, comparator)) {
  2556. result.push(value);
  2557. }
  2558. }
  2559. return result;
  2560. }
  2561. /**
  2562. * The base implementation of `_.forEach` without support for iteratee shorthands.
  2563. *
  2564. * @private
  2565. * @param {Array|Object} collection The collection to iterate over.
  2566. * @param {Function} iteratee The function invoked per iteration.
  2567. * @returns {Array|Object} Returns `collection`.
  2568. */
  2569. var baseEach = createBaseEach(baseForOwn);
  2570. /**
  2571. * The base implementation of `_.forEachRight` without support for iteratee shorthands.
  2572. *
  2573. * @private
  2574. * @param {Array|Object} collection The collection to iterate over.
  2575. * @param {Function} iteratee The function invoked per iteration.
  2576. * @returns {Array|Object} Returns `collection`.
  2577. */
  2578. var baseEachRight = createBaseEach(baseForOwnRight, true);
  2579. /**
  2580. * The base implementation of `_.every` without support for iteratee shorthands.
  2581. *
  2582. * @private
  2583. * @param {Array|Object} collection The collection to iterate over.
  2584. * @param {Function} predicate The function invoked per iteration.
  2585. * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`
  2586. */
  2587. function baseEvery(collection, predicate) {
  2588. var result = true;
  2589. baseEach(collection, function(value, index, collection) {
  2590. result = !!predicate(value, index, collection);
  2591. return result;
  2592. });
  2593. return result;
  2594. }
  2595. /**
  2596. * The base implementation of `_.fill` without an iteratee call guard.
  2597. *
  2598. * @private
  2599. * @param {Array} array The array to fill.
  2600. * @param {*} value The value to fill `array` with.
  2601. * @param {number} [start=0] The start position.
  2602. * @param {number} [end=array.length] The end position.
  2603. * @returns {Array} Returns `array`.
  2604. */
  2605. function baseFill(array, value, start, end) {
  2606. var length = array.length;
  2607. start = toInteger(start);
  2608. if (start < 0) {
  2609. start = -start > length ? 0 : (length + start);
  2610. }
  2611. end = (end === undefined || end > length) ? length : toInteger(end);
  2612. if (end < 0) {
  2613. end += length;
  2614. }
  2615. end = start > end ? 0 : toLength(end);
  2616. while (start < end) {
  2617. array[start++] = value;
  2618. }
  2619. return array;
  2620. }
  2621. /**
  2622. * The base implementation of `_.filter` without support for iteratee shorthands.
  2623. *
  2624. * @private
  2625. * @param {Array|Object} collection The collection to iterate over.
  2626. * @param {Function} predicate The function invoked per iteration.
  2627. * @returns {Array} Returns the new filtered array.
  2628. */
  2629. function baseFilter(collection, predicate) {
  2630. var result = [];
  2631. baseEach(collection, function(value, index, collection) {
  2632. if (predicate(value, index, collection)) {
  2633. result.push(value);
  2634. }
  2635. });
  2636. return result;
  2637. }
  2638. /**
  2639. * The base implementation of `_.flatten` with support for restricting flattening.
  2640. *
  2641. * @private
  2642. * @param {Array} array The array to flatten.
  2643. * @param {number} depth The maximum recursion depth.
  2644. * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
  2645. * @param {Array} [result=[]] The initial result value.
  2646. * @returns {Array} Returns the new flattened array.
  2647. */
  2648. function baseFlatten(array, depth, isStrict, result) {
  2649. result || (result = []);
  2650. var index = -1,
  2651. length = array.length;
  2652. while (++index < length) {
  2653. var value = array[index];
  2654. if (depth > 0 && isArrayLikeObject(value) &&
  2655. (isStrict || isArray(value) || isArguments(value))) {
  2656. if (depth > 1) {
  2657. // Recursively flatten arrays (susceptible to call stack limits).
  2658. baseFlatten(value, depth - 1, isStrict, result);
  2659. } else {
  2660. arrayPush(result, value);
  2661. }
  2662. } else if (!isStrict) {
  2663. result[result.length] = value;
  2664. }
  2665. }
  2666. return result;
  2667. }
  2668. /**
  2669. * The base implementation of `baseForIn` and `baseForOwn` which iterates
  2670. * over `object` properties returned by `keysFunc` invoking `iteratee` for
  2671. * each property. Iteratee functions may exit iteration early by explicitly
  2672. * returning `false`.
  2673. *
  2674. * @private
  2675. * @param {Object} object The object to iterate over.
  2676. * @param {Function} iteratee The function invoked per iteration.
  2677. * @param {Function} keysFunc The function to get the keys of `object`.
  2678. * @returns {Object} Returns `object`.
  2679. */
  2680. var baseFor = createBaseFor();
  2681. /**
  2682. * This function is like `baseFor` except that it iterates over properties
  2683. * in the opposite order.
  2684. *
  2685. * @private
  2686. * @param {Object} object The object to iterate over.
  2687. * @param {Function} iteratee The function invoked per iteration.
  2688. * @param {Function} keysFunc The function to get the keys of `object`.
  2689. * @returns {Object} Returns `object`.
  2690. */
  2691. var baseForRight = createBaseFor(true);
  2692. /**
  2693. * The base implementation of `_.forIn` without support for iteratee shorthands.
  2694. *
  2695. * @private
  2696. * @param {Object} object The object to iterate over.
  2697. * @param {Function} iteratee The function invoked per iteration.
  2698. * @returns {Object} Returns `object`.
  2699. */
  2700. function baseForIn(object, iteratee) {
  2701. return object == null ? object : baseFor(object, iteratee, keysIn);
  2702. }
  2703. /**
  2704. * The base implementation of `_.forOwn` without support for iteratee shorthands.
  2705. *
  2706. * @private
  2707. * @param {Object} object The object to iterate over.
  2708. * @param {Function} iteratee The function invoked per iteration.
  2709. * @returns {Object} Returns `object`.
  2710. */
  2711. function baseForOwn(object, iteratee) {
  2712. return object && baseFor(object, iteratee, keys);
  2713. }
  2714. /**
  2715. * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
  2716. *
  2717. * @private
  2718. * @param {Object} object The object to iterate over.
  2719. * @param {Function} iteratee The function invoked per iteration.
  2720. * @returns {Object} Returns `object`.
  2721. */
  2722. function baseForOwnRight(object, iteratee) {
  2723. return object && baseForRight(object, iteratee, keys);
  2724. }
  2725. /**
  2726. * The base implementation of `_.functions` which creates an array of
  2727. * `object` function property names filtered from `props`.
  2728. *
  2729. * @private
  2730. * @param {Object} object The object to inspect.
  2731. * @param {Array} props The property names to filter.
  2732. * @returns {Array} Returns the new array of filtered property names.
  2733. */
  2734. function baseFunctions(object, props) {
  2735. return arrayFilter(props, function(key) {
  2736. return isFunction(object[key]);
  2737. });
  2738. }
  2739. /**
  2740. * The base implementation of `_.get` without support for default values.
  2741. *
  2742. * @private
  2743. * @param {Object} object The object to query.
  2744. * @param {Array|string} path The path of the property to get.
  2745. * @returns {*} Returns the resolved value.
  2746. */
  2747. function baseGet(object, path) {
  2748. path = isKey(path, object) ? [path + ''] : baseCastPath(path);
  2749. var index = 0,
  2750. length = path.length;
  2751. while (object != null && index < length) {
  2752. object = object[path[index++]];
  2753. }
  2754. return (index && index == length) ? object : undefined;
  2755. }
  2756. /**
  2757. * The base implementation of `_.has` without support for deep paths.
  2758. *
  2759. * @private
  2760. * @param {Object} object The object to query.
  2761. * @param {Array|string} key The key to check.
  2762. * @returns {boolean} Returns `true` if `key` exists, else `false`.
  2763. */
  2764. function baseHas(object, key) {
  2765. // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`,
  2766. // that are composed entirely of index properties, return `false` for
  2767. // `hasOwnProperty` checks of them.
  2768. return hasOwnProperty.call(object, key) ||
  2769. (typeof object == 'object' && key in object && getPrototypeOf(object) === null);
  2770. }
  2771. /**
  2772. * The base implementation of `_.hasIn` without support for deep paths.
  2773. *
  2774. * @private
  2775. * @param {Object} object The object to query.
  2776. * @param {Array|string} key The key to check.
  2777. * @returns {boolean} Returns `true` if `key` exists, else `false`.
  2778. */
  2779. function baseHasIn(object, key) {
  2780. return key in Object(object);
  2781. }
  2782. /**
  2783. * The base implementation of `_.inRange` which doesn't coerce arguments to numbers.
  2784. *
  2785. * @private
  2786. * @param {number} number The number to check.
  2787. * @param {number} start The start of the range.
  2788. * @param {number} end The end of the range.
  2789. * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
  2790. */
  2791. function baseInRange(number, start, end) {
  2792. return number >= nativeMin(start, end) && number < nativeMax(start, end);
  2793. }
  2794. /**
  2795. * The base implementation of methods like `_.intersection`, without support
  2796. * for iteratee shorthands, that accepts an array of arrays to inspect.
  2797. *
  2798. * @private
  2799. * @param {Array} arrays The arrays to inspect.
  2800. * @param {Function} [iteratee] The iteratee invoked per element.
  2801. * @param {Function} [comparator] The comparator invoked per element.
  2802. * @returns {Array} Returns the new array of shared values.
  2803. */
  2804. function baseIntersection(arrays, iteratee, comparator) {
  2805. var includes = comparator ? arrayIncludesWith : arrayIncludes,
  2806. othLength = arrays.length,
  2807. othIndex = othLength,
  2808. caches = Array(othLength),
  2809. result = [];
  2810. while (othIndex--) {
  2811. var array = arrays[othIndex];
  2812. if (othIndex && iteratee) {
  2813. array = arrayMap(array, baseUnary(iteratee));
  2814. }
  2815. caches[othIndex] = !comparator && (iteratee || array.length >= 120)
  2816. ? new SetCache(othIndex && array)
  2817. : undefined;
  2818. }
  2819. array = arrays[0];
  2820. var index = -1,
  2821. length = array.length,
  2822. seen = caches[0];
  2823. outer:
  2824. while (++index < length) {
  2825. var value = array[index],
  2826. computed = iteratee ? iteratee(value) : value;
  2827. if (!(seen
  2828. ? cacheHas(seen, computed)
  2829. : includes(result, computed, comparator)
  2830. )) {
  2831. var othIndex = othLength;
  2832. while (--othIndex) {
  2833. var cache = caches[othIndex];
  2834. if (!(cache
  2835. ? cacheHas(cache, computed)
  2836. : includes(arrays[othIndex], computed, comparator))
  2837. ) {
  2838. continue outer;
  2839. }
  2840. }
  2841. if (seen) {
  2842. seen.push(computed);
  2843. }
  2844. result.push(value);
  2845. }
  2846. }
  2847. return result;
  2848. }
  2849. /**
  2850. * The base implementation of `_.invert` and `_.invertBy` which inverts
  2851. * `object` with values transformed by `iteratee` and set by `setter`.
  2852. *
  2853. * @private
  2854. * @param {Object} object The object to iterate over.
  2855. * @param {Function} setter The function to set `accumulator` values.
  2856. * @param {Function} iteratee The iteratee to transform values.
  2857. * @param {Object} accumulator The initial inverted object.
  2858. * @returns {Function} Returns `accumulator`.
  2859. */
  2860. function baseInverter(object, setter, iteratee, accumulator) {
  2861. baseForOwn(object, function(value, key, object) {
  2862. setter(accumulator, iteratee(value), key, object);
  2863. });
  2864. return accumulator;
  2865. }
  2866. /**
  2867. * The base implementation of `_.invoke` without support for individual
  2868. * method arguments.
  2869. *
  2870. * @private
  2871. * @param {Object} object The object to query.
  2872. * @param {Array|string} path The path of the method to invoke.
  2873. * @param {Array} args The arguments to invoke the method with.
  2874. * @returns {*} Returns the result of the invoked method.
  2875. */
  2876. function baseInvoke(object, path, args) {
  2877. if (!isKey(path, object)) {
  2878. path = baseCastPath(path);
  2879. object = parent(object, path);
  2880. path = last(path);
  2881. }
  2882. var func = object == null ? object : object[path];
  2883. return func == null ? undefined : apply(func, object, args);
  2884. }
  2885. /**
  2886. * The base implementation of `_.isEqual` which supports partial comparisons
  2887. * and tracks traversed objects.
  2888. *
  2889. * @private
  2890. * @param {*} value The value to compare.
  2891. * @param {*} other The other value to compare.
  2892. * @param {Function} [customizer] The function to customize comparisons.
  2893. * @param {boolean} [bitmask] The bitmask of comparison flags.
  2894. * The bitmask may be composed of the following flags:
  2895. * 1 - Unordered comparison
  2896. * 2 - Partial comparison
  2897. * @param {Object} [stack] Tracks traversed `value` and `other` objects.
  2898. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
  2899. */
  2900. function baseIsEqual(value, other, customizer, bitmask, stack) {
  2901. if (value === other) {
  2902. return true;
  2903. }
  2904. if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
  2905. return value !== value && other !== other;
  2906. }
  2907. return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
  2908. }
  2909. /**
  2910. * A specialized version of `baseIsEqual` for arrays and objects which performs
  2911. * deep comparisons and tracks traversed objects enabling objects with circular
  2912. * references to be compared.
  2913. *
  2914. * @private
  2915. * @param {Object} object The object to compare.
  2916. * @param {Object} other The other object to compare.
  2917. * @param {Function} equalFunc The function to determine equivalents of values.
  2918. * @param {Function} [customizer] The function to customize comparisons.
  2919. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
  2920. * @param {Object} [stack] Tracks traversed `object` and `other` objects.
  2921. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
  2922. */
  2923. function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
  2924. var objIsArr = isArray(object),
  2925. othIsArr = isArray(other),
  2926. objTag = arrayTag,
  2927. othTag = arrayTag;
  2928. if (!objIsArr) {
  2929. objTag = getTag(object);
  2930. if (objTag == argsTag) {
  2931. objTag = objectTag;
  2932. } else if (objTag != objectTag) {
  2933. objIsArr = isTypedArray(object);
  2934. }
  2935. }
  2936. if (!othIsArr) {
  2937. othTag = getTag(other);
  2938. if (othTag == argsTag) {
  2939. othTag = objectTag;
  2940. } else if (othTag != objectTag) {
  2941. othIsArr = isTypedArray(other);
  2942. }
  2943. }
  2944. var objIsObj = objTag == objectTag && !isHostObject(object),
  2945. othIsObj = othTag == objectTag && !isHostObject(other),
  2946. isSameTag = objTag == othTag;
  2947. if (isSameTag && !(objIsArr || objIsObj)) {
  2948. return equalByTag(object, other, objTag, equalFunc, customizer, bitmask);
  2949. }
  2950. var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
  2951. if (!isPartial) {
  2952. var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
  2953. othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
  2954. if (objIsWrapped || othIsWrapped) {
  2955. return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, bitmask, stack);
  2956. }
  2957. }
  2958. if (!isSameTag) {
  2959. return false;
  2960. }
  2961. stack || (stack = new Stack);
  2962. return (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, bitmask, stack);
  2963. }
  2964. /**
  2965. * The base implementation of `_.isMatch` without support for iteratee shorthands.
  2966. *
  2967. * @private
  2968. * @param {Object} object The object to inspect.
  2969. * @param {Object} source The object of property values to match.
  2970. * @param {Array} matchData The property names, values, and compare flags to match.
  2971. * @param {Function} [customizer] The function to customize comparisons.
  2972. * @returns {boolean} Returns `true` if `object` is a match, else `false`.
  2973. */
  2974. function baseIsMatch(object, source, matchData, customizer) {
  2975. var index = matchData.length,
  2976. length = index,
  2977. noCustomizer = !customizer;
  2978. if (object == null) {
  2979. return !length;
  2980. }
  2981. object = Object(object);
  2982. while (index--) {
  2983. var data = matchData[index];
  2984. if ((noCustomizer && data[2])
  2985. ? data[1] !== object[data[0]]
  2986. : !(data[0] in object)
  2987. ) {
  2988. return false;
  2989. }
  2990. }
  2991. while (++index < length) {
  2992. data = matchData[index];
  2993. var key = data[0],
  2994. objValue = object[key],
  2995. srcValue = data[1];
  2996. if (noCustomizer && data[2]) {
  2997. if (objValue === undefined && !(key in object)) {
  2998. return false;
  2999. }
  3000. } else {
  3001. var stack = new Stack,
  3002. result = customizer ? customizer(objValue, srcValue, key, object, source, stack) : undefined;
  3003. if (!(result === undefined
  3004. ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
  3005. : result
  3006. )) {
  3007. return false;
  3008. }
  3009. }
  3010. }
  3011. return true;
  3012. }
  3013. /**
  3014. * The base implementation of `_.iteratee`.
  3015. *
  3016. * @private
  3017. * @param {*} [value=_.identity] The value to convert to an iteratee.
  3018. * @returns {Function} Returns the iteratee.
  3019. */
  3020. function baseIteratee(value) {
  3021. var type = typeof value;
  3022. if (type == 'function') {
  3023. return value;
  3024. }
  3025. if (value == null) {
  3026. return identity;
  3027. }
  3028. if (type == 'object') {
  3029. return isArray(value)
  3030. ? baseMatchesProperty(value[0], value[1])
  3031. : baseMatches(value);
  3032. }
  3033. return property(value);
  3034. }
  3035. /**
  3036. * The base implementation of `_.keys` which doesn't skip the constructor
  3037. * property of prototypes or treat sparse arrays as dense.
  3038. *
  3039. * @private
  3040. * @param {Object} object The object to query.
  3041. * @returns {Array} Returns the array of property names.
  3042. */
  3043. function baseKeys(object) {
  3044. return nativeKeys(Object(object));
  3045. }
  3046. /**
  3047. * The base implementation of `_.keysIn` which doesn't skip the constructor
  3048. * property of prototypes or treat sparse arrays as dense.
  3049. *
  3050. * @private
  3051. * @param {Object} object The object to query.
  3052. * @returns {Array} Returns the array of property names.
  3053. */
  3054. function baseKeysIn(object) {
  3055. object = object == null ? object : Object(object);
  3056. var result = [];
  3057. for (var key in object) {
  3058. result.push(key);
  3059. }
  3060. return result;
  3061. }
  3062. // Fallback for IE < 9 with es6-shim.
  3063. if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) {
  3064. baseKeysIn = function(object) {
  3065. return iteratorToArray(enumerate(object));
  3066. };
  3067. }
  3068. /**
  3069. * The base implementation of `_.map` without support for iteratee shorthands.
  3070. *
  3071. * @private
  3072. * @param {Array|Object} collection The collection to iterate over.
  3073. * @param {Function} iteratee The function invoked per iteration.
  3074. * @returns {Array} Returns the new mapped array.
  3075. */
  3076. function baseMap(collection, iteratee) {
  3077. var index = -1,
  3078. result = isArrayLike(collection) ? Array(collection.length) : [];
  3079. baseEach(collection, function(value, key, collection) {
  3080. result[++index] = iteratee(value, key, collection);
  3081. });
  3082. return result;
  3083. }
  3084. /**
  3085. * The base implementation of `_.matches` which doesn't clone `source`.
  3086. *
  3087. * @private
  3088. * @param {Object} source The object of property values to match.
  3089. * @returns {Function} Returns the new function.
  3090. */
  3091. function baseMatches(source) {
  3092. var matchData = getMatchData(source);
  3093. if (matchData.length == 1 && matchData[0][2]) {
  3094. var key = matchData[0][0],
  3095. value = matchData[0][1];
  3096. return function(object) {
  3097. if (object == null) {
  3098. return false;
  3099. }
  3100. return object[key] === value &&
  3101. (value !== undefined || (key in Object(object)));
  3102. };
  3103. }
  3104. return function(object) {
  3105. return object === source || baseIsMatch(object, source, matchData);
  3106. };
  3107. }
  3108. /**
  3109. * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
  3110. *
  3111. * @private
  3112. * @param {string} path The path of the property to get.
  3113. * @param {*} srcValue The value to match.
  3114. * @returns {Function} Returns the new function.
  3115. */
  3116. function baseMatchesProperty(path, srcValue) {
  3117. return function(object) {
  3118. var objValue = get(object, path);
  3119. return (objValue === undefined && objValue === srcValue)
  3120. ? hasIn(object, path)
  3121. : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
  3122. };
  3123. }
  3124. /**
  3125. * The base implementation of `_.merge` without support for multiple sources.
  3126. *
  3127. * @private
  3128. * @param {Object} object The destination object.
  3129. * @param {Object} source The source object.
  3130. * @param {number} srcIndex The index of `source`.
  3131. * @param {Function} [customizer] The function to customize merged values.
  3132. * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
  3133. */
  3134. function baseMerge(object, source, srcIndex, customizer, stack) {
  3135. if (object === source) {
  3136. return;
  3137. }
  3138. var props = (isArray(source) || isTypedArray(source))
  3139. ? undefined
  3140. : keysIn(source);
  3141. arrayEach(props || source, function(srcValue, key) {
  3142. if (props) {
  3143. key = srcValue;
  3144. srcValue = source[key];
  3145. }
  3146. if (isObject(srcValue)) {
  3147. stack || (stack = new Stack);
  3148. baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
  3149. }
  3150. else {
  3151. var newValue = customizer
  3152. ? customizer(object[key], srcValue, (key + ''), object, source, stack)
  3153. : undefined;
  3154. if (newValue === undefined) {
  3155. newValue = srcValue;
  3156. }
  3157. assignMergeValue(object, key, newValue);
  3158. }
  3159. });
  3160. }
  3161. /**
  3162. * A specialized version of `baseMerge` for arrays and objects which performs
  3163. * deep merges and tracks traversed objects enabling objects with circular
  3164. * references to be merged.
  3165. *
  3166. * @private
  3167. * @param {Object} object The destination object.
  3168. * @param {Object} source The source object.
  3169. * @param {string} key The key of the value to merge.
  3170. * @param {number} srcIndex The index of `source`.
  3171. * @param {Function} mergeFunc The function to merge values.
  3172. * @param {Function} [customizer] The function to customize assigned values.
  3173. * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
  3174. */
  3175. function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
  3176. var objValue = object[key],
  3177. srcValue = source[key],
  3178. stacked = stack.get(srcValue);
  3179. if (stacked) {
  3180. assignMergeValue(object, key, stacked);
  3181. return;
  3182. }
  3183. var newValue = customizer
  3184. ? customizer(objValue, srcValue, (key + ''), object, source, stack)
  3185. : undefined;
  3186. var isCommon = newValue === undefined;
  3187. if (isCommon) {
  3188. newValue = srcValue;
  3189. if (isArray(srcValue) || isTypedArray(srcValue)) {
  3190. if (isArray(objValue)) {
  3191. newValue = objValue;
  3192. }
  3193. else if (isArrayLikeObject(objValue)) {
  3194. newValue = copyArray(objValue);
  3195. }
  3196. else {
  3197. isCommon = false;
  3198. newValue = baseClone(srcValue, true);
  3199. }
  3200. }
  3201. else if (isPlainObject(srcValue) || isArguments(srcValue)) {
  3202. if (isArguments(objValue)) {
  3203. newValue = toPlainObject(objValue);
  3204. }
  3205. else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
  3206. isCommon = false;
  3207. newValue = baseClone(srcValue, true);
  3208. }
  3209. else {
  3210. newValue = objValue;
  3211. }
  3212. }
  3213. else {
  3214. isCommon = false;
  3215. }
  3216. }
  3217. stack.set(srcValue, newValue);
  3218. if (isCommon) {
  3219. // Recursively merge objects and arrays (susceptible to call stack limits).
  3220. mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
  3221. }
  3222. assignMergeValue(object, key, newValue);
  3223. }
  3224. /**
  3225. * The base implementation of `_.orderBy` without param guards.
  3226. *
  3227. * @private
  3228. * @param {Array|Object} collection The collection to iterate over.
  3229. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
  3230. * @param {string[]} orders The sort orders of `iteratees`.
  3231. * @returns {Array} Returns the new sorted array.
  3232. */
  3233. function baseOrderBy(collection, iteratees, orders) {
  3234. var index = -1,
  3235. toIteratee = getIteratee();
  3236. iteratees = arrayMap(iteratees.length ? iteratees : Array(1), function(iteratee) {
  3237. return toIteratee(iteratee);
  3238. });
  3239. var result = baseMap(collection, function(value, key, collection) {
  3240. var criteria = arrayMap(iteratees, function(iteratee) {
  3241. return iteratee(value);
  3242. });
  3243. return { 'criteria': criteria, 'index': ++index, 'value': value };
  3244. });
  3245. return baseSortBy(result, function(object, other) {
  3246. return compareMultiple(object, other, orders);
  3247. });
  3248. }
  3249. /**
  3250. * The base implementation of `_.pick` without support for individual
  3251. * property names.
  3252. *
  3253. * @private
  3254. * @param {Object} object The source object.
  3255. * @param {string[]} props The property names to pick.
  3256. * @returns {Object} Returns the new object.
  3257. */
  3258. function basePick(object, props) {
  3259. object = Object(object);
  3260. return arrayReduce(props, function(result, key) {
  3261. if (key in object) {
  3262. result[key] = object[key];
  3263. }
  3264. return result;
  3265. }, {});
  3266. }
  3267. /**
  3268. * The base implementation of `_.pickBy` without support for iteratee shorthands.
  3269. *
  3270. * @private
  3271. * @param {Object} object The source object.
  3272. * @param {Function} predicate The function invoked per property.
  3273. * @returns {Object} Returns the new object.
  3274. */
  3275. function basePickBy(object, predicate) {
  3276. var result = {};
  3277. baseForIn(object, function(value, key) {
  3278. if (predicate(value, key)) {
  3279. result[key] = value;
  3280. }
  3281. });
  3282. return result;
  3283. }
  3284. /**
  3285. * The base implementation of `_.property` without support for deep paths.
  3286. *
  3287. * @private
  3288. * @param {string} key The key of the property to get.
  3289. * @returns {Function} Returns the new function.
  3290. */
  3291. function baseProperty(key) {
  3292. return function(object) {
  3293. return object == null ? undefined : object[key];
  3294. };
  3295. }
  3296. /**
  3297. * A specialized version of `baseProperty` which supports deep paths.
  3298. *
  3299. * @private
  3300. * @param {Array|string} path The path of the property to get.
  3301. * @returns {Function} Returns the new function.
  3302. */
  3303. function basePropertyDeep(path) {
  3304. return function(object) {
  3305. return baseGet(object, path);
  3306. };
  3307. }
  3308. /**
  3309. * The base implementation of `_.pullAll`.
  3310. *
  3311. * @private
  3312. * @param {Array} array The array to modify.
  3313. * @param {Array} values The values to remove.
  3314. * @returns {Array} Returns `array`.
  3315. */
  3316. function basePullAll(array, values) {
  3317. return basePullAllBy(array, values);
  3318. }
  3319. /**
  3320. * The base implementation of `_.pullAllBy` without support for iteratee
  3321. * shorthands.
  3322. *
  3323. * @private
  3324. * @param {Array} array The array to modify.
  3325. * @param {Array} values The values to remove.
  3326. * @param {Function} [iteratee] The iteratee invoked per element.
  3327. * @returns {Array} Returns `array`.
  3328. */
  3329. function basePullAllBy(array, values, iteratee) {
  3330. var index = -1,
  3331. length = values.length,
  3332. seen = array;
  3333. if (iteratee) {
  3334. seen = arrayMap(array, function(value) { return iteratee(value); });
  3335. }
  3336. while (++index < length) {
  3337. var fromIndex = 0,
  3338. value = values[index],
  3339. computed = iteratee ? iteratee(value) : value;
  3340. while ((fromIndex = baseIndexOf(seen, computed, fromIndex)) > -1) {
  3341. if (seen !== array) {
  3342. splice.call(seen, fromIndex, 1);
  3343. }
  3344. splice.call(array, fromIndex, 1);
  3345. }
  3346. }
  3347. return array;
  3348. }
  3349. /**
  3350. * The base implementation of `_.pullAt` without support for individual
  3351. * indexes or capturing the removed elements.
  3352. *
  3353. * @private
  3354. * @param {Array} array The array to modify.
  3355. * @param {number[]} indexes The indexes of elements to remove.
  3356. * @returns {Array} Returns `array`.
  3357. */
  3358. function basePullAt(array, indexes) {
  3359. var length = array ? indexes.length : 0,
  3360. lastIndex = length - 1;
  3361. while (length--) {
  3362. var index = indexes[length];
  3363. if (lastIndex == length || index != previous) {
  3364. var previous = index;
  3365. if (isIndex(index)) {
  3366. splice.call(array, index, 1);
  3367. }
  3368. else if (!isKey(index, array)) {
  3369. var path = baseCastPath(index),
  3370. object = parent(array, path);
  3371. if (object != null) {
  3372. delete object[last(path)];
  3373. }
  3374. }
  3375. else {
  3376. delete array[index];
  3377. }
  3378. }
  3379. }
  3380. return array;
  3381. }
  3382. /**
  3383. * The base implementation of `_.random` without support for returning
  3384. * floating-point numbers.
  3385. *
  3386. * @private
  3387. * @param {number} lower The lower bound.
  3388. * @param {number} upper The upper bound.
  3389. * @returns {number} Returns the random number.
  3390. */
  3391. function baseRandom(lower, upper) {
  3392. return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
  3393. }
  3394. /**
  3395. * The base implementation of `_.range` and `_.rangeRight` which doesn't
  3396. * coerce arguments to numbers.
  3397. *
  3398. * @private
  3399. * @param {number} start The start of the range.
  3400. * @param {number} end The end of the range.
  3401. * @param {number} step The value to increment or decrement by.
  3402. * @param {boolean} [fromRight] Specify iterating from right to left.
  3403. * @returns {Array} Returns the new array of numbers.
  3404. */
  3405. function baseRange(start, end, step, fromRight) {
  3406. var index = -1,
  3407. length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
  3408. result = Array(length);
  3409. while (length--) {
  3410. result[fromRight ? length : ++index] = start;
  3411. start += step;
  3412. }
  3413. return result;
  3414. }
  3415. /**
  3416. * The base implementation of `_.set`.
  3417. *
  3418. * @private
  3419. * @param {Object} object The object to query.
  3420. * @param {Array|string} path The path of the property to set.
  3421. * @param {*} value The value to set.
  3422. * @param {Function} [customizer] The function to customize path creation.
  3423. * @returns {Object} Returns `object`.
  3424. */
  3425. function baseSet(object, path, value, customizer) {
  3426. path = isKey(path, object) ? [path + ''] : baseCastPath(path);
  3427. var index = -1,
  3428. length = path.length,
  3429. lastIndex = length - 1,
  3430. nested = object;
  3431. while (nested != null && ++index < length) {
  3432. var key = path[index];
  3433. if (isObject(nested)) {
  3434. var newValue = value;
  3435. if (index != lastIndex) {
  3436. var objValue = nested[key];
  3437. newValue = customizer ? customizer(objValue, key, nested) : undefined;
  3438. if (newValue === undefined) {
  3439. newValue = objValue == null
  3440. ? (isIndex(path[index + 1]) ? [] : {})
  3441. : objValue;
  3442. }
  3443. }
  3444. assignValue(nested, key, newValue);
  3445. }
  3446. nested = nested[key];
  3447. }
  3448. return object;
  3449. }
  3450. /**
  3451. * The base implementation of `setData` without support for hot loop detection.
  3452. *
  3453. * @private
  3454. * @param {Function} func The function to associate metadata with.
  3455. * @param {*} data The metadata.
  3456. * @returns {Function} Returns `func`.
  3457. */
  3458. var baseSetData = !metaMap ? identity : function(func, data) {
  3459. metaMap.set(func, data);
  3460. return func;
  3461. };
  3462. /**
  3463. * The base implementation of `_.slice` without an iteratee call guard.
  3464. *
  3465. * @private
  3466. * @param {Array} array The array to slice.
  3467. * @param {number} [start=0] The start position.
  3468. * @param {number} [end=array.length] The end position.
  3469. * @returns {Array} Returns the slice of `array`.
  3470. */
  3471. function baseSlice(array, start, end) {
  3472. var index = -1,
  3473. length = array.length;
  3474. if (start < 0) {
  3475. start = -start > length ? 0 : (length + start);
  3476. }
  3477. end = end > length ? length : end;
  3478. if (end < 0) {
  3479. end += length;
  3480. }
  3481. length = start > end ? 0 : ((end - start) >>> 0);
  3482. start >>>= 0;
  3483. var result = Array(length);
  3484. while (++index < length) {
  3485. result[index] = array[index + start];
  3486. }
  3487. return result;
  3488. }
  3489. /**
  3490. * The base implementation of `_.some` without support for iteratee shorthands.
  3491. *
  3492. * @private
  3493. * @param {Array|Object} collection The collection to iterate over.
  3494. * @param {Function} predicate The function invoked per iteration.
  3495. * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
  3496. */
  3497. function baseSome(collection, predicate) {
  3498. var result;
  3499. baseEach(collection, function(value, index, collection) {
  3500. result = predicate(value, index, collection);
  3501. return !result;
  3502. });
  3503. return !!result;
  3504. }
  3505. /**
  3506. * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
  3507. * performs a binary search of `array` to determine the index at which `value`
  3508. * should be inserted into `array` in order to maintain its sort order.
  3509. *
  3510. * @private
  3511. * @param {Array} array The sorted array to inspect.
  3512. * @param {*} value The value to evaluate.
  3513. * @param {boolean} [retHighest] Specify returning the highest qualified index.
  3514. * @returns {number} Returns the index at which `value` should be inserted
  3515. * into `array`.
  3516. */
  3517. function baseSortedIndex(array, value, retHighest) {
  3518. var low = 0,
  3519. high = array ? array.length : low;
  3520. if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
  3521. while (low < high) {
  3522. var mid = (low + high) >>> 1,
  3523. computed = array[mid];
  3524. if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
  3525. low = mid + 1;
  3526. } else {
  3527. high = mid;
  3528. }
  3529. }
  3530. return high;
  3531. }
  3532. return baseSortedIndexBy(array, value, identity, retHighest);
  3533. }
  3534. /**
  3535. * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
  3536. * which invokes `iteratee` for `value` and each element of `array` to compute
  3537. * their sort ranking. The iteratee is invoked with one argument; (value).
  3538. *
  3539. * @private
  3540. * @param {Array} array The sorted array to inspect.
  3541. * @param {*} value The value to evaluate.
  3542. * @param {Function} iteratee The iteratee invoked per element.
  3543. * @param {boolean} [retHighest] Specify returning the highest qualified index.
  3544. * @returns {number} Returns the index at which `value` should be inserted into `array`.
  3545. */
  3546. function baseSortedIndexBy(array, value, iteratee, retHighest) {
  3547. value = iteratee(value);
  3548. var low = 0,
  3549. high = array ? array.length : 0,
  3550. valIsNaN = value !== value,
  3551. valIsNull = value === null,
  3552. valIsUndef = value === undefined;
  3553. while (low < high) {
  3554. var mid = nativeFloor((low + high) / 2),
  3555. computed = iteratee(array[mid]),
  3556. isDef = computed !== undefined,
  3557. isReflexive = computed === computed;
  3558. if (valIsNaN) {
  3559. var setLow = isReflexive || retHighest;
  3560. } else if (valIsNull) {
  3561. setLow = isReflexive && isDef && (retHighest || computed != null);
  3562. } else if (valIsUndef) {
  3563. setLow = isReflexive && (retHighest || isDef);
  3564. } else if (computed == null) {
  3565. setLow = false;
  3566. } else {
  3567. setLow = retHighest ? (computed <= value) : (computed < value);
  3568. }
  3569. if (setLow) {
  3570. low = mid + 1;
  3571. } else {
  3572. high = mid;
  3573. }
  3574. }
  3575. return nativeMin(high, MAX_ARRAY_INDEX);
  3576. }
  3577. /**
  3578. * The base implementation of `_.sortedUniq`.
  3579. *
  3580. * @private
  3581. * @param {Array} array The array to inspect.
  3582. * @returns {Array} Returns the new duplicate free array.
  3583. */
  3584. function baseSortedUniq(array) {
  3585. return baseSortedUniqBy(array);
  3586. }
  3587. /**
  3588. * The base implementation of `_.sortedUniqBy` without support for iteratee
  3589. * shorthands.
  3590. *
  3591. * @private
  3592. * @param {Array} array The array to inspect.
  3593. * @param {Function} [iteratee] The iteratee invoked per element.
  3594. * @returns {Array} Returns the new duplicate free array.
  3595. */
  3596. function baseSortedUniqBy(array, iteratee) {
  3597. var index = 0,
  3598. length = array.length,
  3599. value = array[0],
  3600. computed = iteratee ? iteratee(value) : value,
  3601. seen = computed,
  3602. resIndex = 0,
  3603. result = [value];
  3604. while (++index < length) {
  3605. value = array[index],
  3606. computed = iteratee ? iteratee(value) : value;
  3607. if (!eq(computed, seen)) {
  3608. seen = computed;
  3609. result[++resIndex] = value;
  3610. }
  3611. }
  3612. return result;
  3613. }
  3614. /**
  3615. * The base implementation of `_.uniqBy` without support for iteratee shorthands.
  3616. *
  3617. * @private
  3618. * @param {Array} array The array to inspect.
  3619. * @param {Function} [iteratee] The iteratee invoked per element.
  3620. * @param {Function} [comparator] The comparator invoked per element.
  3621. * @returns {Array} Returns the new duplicate free array.
  3622. */
  3623. function baseUniq(array, iteratee, comparator) {
  3624. var index = -1,
  3625. includes = arrayIncludes,
  3626. length = array.length,
  3627. isCommon = true,
  3628. result = [],
  3629. seen = result;
  3630. if (comparator) {
  3631. isCommon = false;
  3632. includes = arrayIncludesWith;
  3633. }
  3634. else if (length >= LARGE_ARRAY_SIZE) {
  3635. var set = iteratee ? null : createSet(array);
  3636. if (set) {
  3637. return setToArray(set);
  3638. }
  3639. isCommon = false;
  3640. includes = cacheHas;
  3641. seen = new SetCache;
  3642. }
  3643. else {
  3644. seen = iteratee ? [] : result;
  3645. }
  3646. outer:
  3647. while (++index < length) {
  3648. var value = array[index],
  3649. computed = iteratee ? iteratee(value) : value;
  3650. if (isCommon && computed === computed) {
  3651. var seenIndex = seen.length;
  3652. while (seenIndex--) {
  3653. if (seen[seenIndex] === computed) {
  3654. continue outer;
  3655. }
  3656. }
  3657. if (iteratee) {
  3658. seen.push(computed);
  3659. }
  3660. result.push(value);
  3661. }
  3662. else if (!includes(seen, computed, comparator)) {
  3663. if (seen !== result) {
  3664. seen.push(computed);
  3665. }
  3666. result.push(value);
  3667. }
  3668. }
  3669. return result;
  3670. }
  3671. /**
  3672. * The base implementation of `_.unset`.
  3673. *
  3674. * @private
  3675. * @param {Object} object The object to modify.
  3676. * @param {Array|string} path The path of the property to unset.
  3677. * @returns {boolean} Returns `true` if the property is deleted, else `false`.
  3678. */
  3679. function baseUnset(object, path) {
  3680. path = isKey(path, object) ? [path + ''] : baseCastPath(path);
  3681. object = parent(object, path);
  3682. var key = last(path);
  3683. return (object != null && has(object, key)) ? delete object[key] : true;
  3684. }
  3685. /**
  3686. * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
  3687. * without support for iteratee shorthands.
  3688. *
  3689. * @private
  3690. * @param {Array} array The array to query.
  3691. * @param {Function} predicate The function invoked per iteration.
  3692. * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
  3693. * @param {boolean} [fromRight] Specify iterating from right to left.
  3694. * @returns {Array} Returns the slice of `array`.
  3695. */
  3696. function baseWhile(array, predicate, isDrop, fromRight) {
  3697. var length = array.length,
  3698. index = fromRight ? length : -1;
  3699. while ((fromRight ? index-- : ++index < length) &&
  3700. predicate(array[index], index, array)) {}
  3701. return isDrop
  3702. ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
  3703. : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
  3704. }
  3705. /**
  3706. * The base implementation of `wrapperValue` which returns the result of
  3707. * performing a sequence of actions on the unwrapped `value`, where each
  3708. * successive action is supplied the return value of the previous.
  3709. *
  3710. * @private
  3711. * @param {*} value The unwrapped value.
  3712. * @param {Array} actions Actions to perform to resolve the unwrapped value.
  3713. * @returns {*} Returns the resolved value.
  3714. */
  3715. function baseWrapperValue(value, actions) {
  3716. var result = value;
  3717. if (result instanceof LazyWrapper) {
  3718. result = result.value();
  3719. }
  3720. return arrayReduce(actions, function(result, action) {
  3721. return action.func.apply(action.thisArg, arrayPush([result], action.args));
  3722. }, result);
  3723. }
  3724. /**
  3725. * The base implementation of methods like `_.xor`, without support for
  3726. * iteratee shorthands, that accepts an array of arrays to inspect.
  3727. *
  3728. * @private
  3729. * @param {Array} arrays The arrays to inspect.
  3730. * @param {Function} [iteratee] The iteratee invoked per element.
  3731. * @param {Function} [comparator] The comparator invoked per element.
  3732. * @returns {Array} Returns the new array of values.
  3733. */
  3734. function baseXor(arrays, iteratee, comparator) {
  3735. var index = -1,
  3736. length = arrays.length;
  3737. while (++index < length) {
  3738. var result = result
  3739. ? arrayPush(
  3740. baseDifference(result, arrays[index], iteratee, comparator),
  3741. baseDifference(arrays[index], result, iteratee, comparator)
  3742. )
  3743. : arrays[index];
  3744. }
  3745. return (result && result.length) ? baseUniq(result, iteratee, comparator) : [];
  3746. }
  3747. /**
  3748. * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
  3749. *
  3750. * @private
  3751. * @param {Array} props The property names.
  3752. * @param {Array} values The property values.
  3753. * @param {Function} assignFunc The function to assign values.
  3754. * @returns {Object} Returns the new object.
  3755. */
  3756. function baseZipObject(props, values, assignFunc) {
  3757. var index = -1,
  3758. length = props.length,
  3759. valsLength = values.length,
  3760. result = {};
  3761. while (++index < length) {
  3762. assignFunc(result, props[index], index < valsLength ? values[index] : undefined);
  3763. }
  3764. return result;
  3765. }
  3766. /**
  3767. * Creates a clone of `buffer`.
  3768. *
  3769. * @private
  3770. * @param {Buffer} buffer The buffer to clone.
  3771. * @param {boolean} [isDeep] Specify a deep clone.
  3772. * @returns {Buffer} Returns the cloned buffer.
  3773. */
  3774. function cloneBuffer(buffer, isDeep) {
  3775. if (isDeep) {
  3776. return buffer.slice();
  3777. }
  3778. var Ctor = buffer.constructor,
  3779. result = new Ctor(buffer.length);
  3780. buffer.copy(result);
  3781. return result;
  3782. }
  3783. /**
  3784. * Creates a clone of `arrayBuffer`.
  3785. *
  3786. * @private
  3787. * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
  3788. * @returns {ArrayBuffer} Returns the cloned array buffer.
  3789. */
  3790. function cloneArrayBuffer(arrayBuffer) {
  3791. var Ctor = arrayBuffer.constructor,
  3792. result = new Ctor(arrayBuffer.byteLength),
  3793. view = new Uint8Array(result);
  3794. view.set(new Uint8Array(arrayBuffer));
  3795. return result;
  3796. }
  3797. /**
  3798. * Creates a clone of `map`.
  3799. *
  3800. * @private
  3801. * @param {Object} map The map to clone.
  3802. * @returns {Object} Returns the cloned map.
  3803. */
  3804. function cloneMap(map) {
  3805. var Ctor = map.constructor;
  3806. return arrayReduce(mapToArray(map), addMapEntry, new Ctor);
  3807. }
  3808. /**
  3809. * Creates a clone of `regexp`.
  3810. *
  3811. * @private
  3812. * @param {Object} regexp The regexp to clone.
  3813. * @returns {Object} Returns the cloned regexp.
  3814. */
  3815. function cloneRegExp(regexp) {
  3816. var Ctor = regexp.constructor,
  3817. result = new Ctor(regexp.source, reFlags.exec(regexp));
  3818. result.lastIndex = regexp.lastIndex;
  3819. return result;
  3820. }
  3821. /**
  3822. * Creates a clone of `set`.
  3823. *
  3824. * @private
  3825. * @param {Object} set The set to clone.
  3826. * @returns {Object} Returns the cloned set.
  3827. */
  3828. function cloneSet(set) {
  3829. var Ctor = set.constructor;
  3830. return arrayReduce(setToArray(set), addSetEntry, new Ctor);
  3831. }
  3832. /**
  3833. * Creates a clone of the `symbol` object.
  3834. *
  3835. * @private
  3836. * @param {Object} symbol The symbol object to clone.
  3837. * @returns {Object} Returns the cloned symbol object.
  3838. */
  3839. function cloneSymbol(symbol) {
  3840. return Symbol ? Object(symbolValueOf.call(symbol)) : {};
  3841. }
  3842. /**
  3843. * Creates a clone of `typedArray`.
  3844. *
  3845. * @private
  3846. * @param {Object} typedArray The typed array to clone.
  3847. * @param {boolean} [isDeep] Specify a deep clone.
  3848. * @returns {Object} Returns the cloned typed array.
  3849. */
  3850. function cloneTypedArray(typedArray, isDeep) {
  3851. var arrayBuffer = typedArray.buffer,
  3852. buffer = isDeep ? cloneArrayBuffer(arrayBuffer) : arrayBuffer,
  3853. Ctor = typedArray.constructor;
  3854. return new Ctor(buffer, typedArray.byteOffset, typedArray.length);
  3855. }
  3856. /**
  3857. * Creates an array that is the composition of partially applied arguments,
  3858. * placeholders, and provided arguments into a single array of arguments.
  3859. *
  3860. * @private
  3861. * @param {Array|Object} args The provided arguments.
  3862. * @param {Array} partials The arguments to prepend to those provided.
  3863. * @param {Array} holders The `partials` placeholder indexes.
  3864. * @params {boolean} [isCurried] Specify composing for a curried function.
  3865. * @returns {Array} Returns the new array of composed arguments.
  3866. */
  3867. function composeArgs(args, partials, holders, isCurried) {
  3868. var argsIndex = -1,
  3869. argsLength = args.length,
  3870. holdersLength = holders.length,
  3871. leftIndex = -1,
  3872. leftLength = partials.length,
  3873. rangeLength = nativeMax(argsLength - holdersLength, 0),
  3874. result = Array(leftLength + rangeLength),
  3875. isUncurried = !isCurried;
  3876. while (++leftIndex < leftLength) {
  3877. result[leftIndex] = partials[leftIndex];
  3878. }
  3879. while (++argsIndex < holdersLength) {
  3880. if (isUncurried || argsIndex < argsLength) {
  3881. result[holders[argsIndex]] = args[argsIndex];
  3882. }
  3883. }
  3884. while (rangeLength--) {
  3885. result[leftIndex++] = args[argsIndex++];
  3886. }
  3887. return result;
  3888. }
  3889. /**
  3890. * This function is like `composeArgs` except that the arguments composition
  3891. * is tailored for `_.partialRight`.
  3892. *
  3893. * @private
  3894. * @param {Array|Object} args The provided arguments.
  3895. * @param {Array} partials The arguments to append to those provided.
  3896. * @param {Array} holders The `partials` placeholder indexes.
  3897. * @params {boolean} [isCurried] Specify composing for a curried function.
  3898. * @returns {Array} Returns the new array of composed arguments.
  3899. */
  3900. function composeArgsRight(args, partials, holders, isCurried) {
  3901. var argsIndex = -1,
  3902. argsLength = args.length,
  3903. holdersIndex = -1,
  3904. holdersLength = holders.length,
  3905. rightIndex = -1,
  3906. rightLength = partials.length,
  3907. rangeLength = nativeMax(argsLength - holdersLength, 0),
  3908. result = Array(rangeLength + rightLength),
  3909. isUncurried = !isCurried;
  3910. while (++argsIndex < rangeLength) {
  3911. result[argsIndex] = args[argsIndex];
  3912. }
  3913. var offset = argsIndex;
  3914. while (++rightIndex < rightLength) {
  3915. result[offset + rightIndex] = partials[rightIndex];
  3916. }
  3917. while (++holdersIndex < holdersLength) {
  3918. if (isUncurried || argsIndex < argsLength) {
  3919. result[offset + holders[holdersIndex]] = args[argsIndex++];
  3920. }
  3921. }
  3922. return result;
  3923. }
  3924. /**
  3925. * Copies the values of `source` to `array`.
  3926. *
  3927. * @private
  3928. * @param {Array} source The array to copy values from.
  3929. * @param {Array} [array=[]] The array to copy values to.
  3930. * @returns {Array} Returns `array`.
  3931. */
  3932. function copyArray(source, array) {
  3933. var index = -1,
  3934. length = source.length;
  3935. array || (array = Array(length));
  3936. while (++index < length) {
  3937. array[index] = source[index];
  3938. }
  3939. return array;
  3940. }
  3941. /**
  3942. * Copies properties of `source` to `object`.
  3943. *
  3944. * @private
  3945. * @param {Object} source The object to copy properties from.
  3946. * @param {Array} props The property names to copy.
  3947. * @param {Object} [object={}] The object to copy properties to.
  3948. * @returns {Object} Returns `object`.
  3949. */
  3950. function copyObject(source, props, object) {
  3951. return copyObjectWith(source, props, object);
  3952. }
  3953. /**
  3954. * This function is like `copyObject` except that it accepts a function to
  3955. * customize copied values.
  3956. *
  3957. * @private
  3958. * @param {Object} source The object to copy properties from.
  3959. * @param {Array} props The property names to copy.
  3960. * @param {Object} [object={}] The object to copy properties to.
  3961. * @param {Function} [customizer] The function to customize copied values.
  3962. * @returns {Object} Returns `object`.
  3963. */
  3964. function copyObjectWith(source, props, object, customizer) {
  3965. object || (object = {});
  3966. var index = -1,
  3967. length = props.length;
  3968. while (++index < length) {
  3969. var key = props[index];
  3970. var newValue = customizer
  3971. ? customizer(object[key], source[key], key, object, source)
  3972. : source[key];
  3973. assignValue(object, key, newValue);
  3974. }
  3975. return object;
  3976. }
  3977. /**
  3978. * Copies own symbol properties of `source` to `object`.
  3979. *
  3980. * @private
  3981. * @param {Object} source The object to copy symbols from.
  3982. * @param {Object} [object={}] The object to copy symbols to.
  3983. * @returns {Object} Returns `object`.
  3984. */
  3985. function copySymbols(source, object) {
  3986. return copyObject(source, getSymbols(source), object);
  3987. }
  3988. /**
  3989. * Creates a function like `_.groupBy`.
  3990. *
  3991. * @private
  3992. * @param {Function} setter The function to set accumulator values.
  3993. * @param {Function} [initializer] The accumulator object initializer.
  3994. * @returns {Function} Returns the new aggregator function.
  3995. */
  3996. function createAggregator(setter, initializer) {
  3997. return function(collection, iteratee) {
  3998. var func = isArray(collection) ? arrayAggregator : baseAggregator,
  3999. accumulator = initializer ? initializer() : {};
  4000. return func(collection, setter, getIteratee(iteratee), accumulator);
  4001. };
  4002. }
  4003. /**
  4004. * Creates a function like `_.assign`.
  4005. *
  4006. * @private
  4007. * @param {Function} assigner The function to assign values.
  4008. * @returns {Function} Returns the new assigner function.
  4009. */
  4010. function createAssigner(assigner) {
  4011. return rest(function(object, sources) {
  4012. var index = -1,
  4013. length = sources.length,
  4014. customizer = length > 1 ? sources[length - 1] : undefined,
  4015. guard = length > 2 ? sources[2] : undefined;
  4016. customizer = typeof customizer == 'function'
  4017. ? (length--, customizer)
  4018. : undefined;
  4019. if (guard && isIterateeCall(sources[0], sources[1], guard)) {
  4020. customizer = length < 3 ? undefined : customizer;
  4021. length = 1;
  4022. }
  4023. object = Object(object);
  4024. while (++index < length) {
  4025. var source = sources[index];
  4026. if (source) {
  4027. assigner(object, source, index, customizer);
  4028. }
  4029. }
  4030. return object;
  4031. });
  4032. }
  4033. /**
  4034. * Creates a `baseEach` or `baseEachRight` function.
  4035. *
  4036. * @private
  4037. * @param {Function} eachFunc The function to iterate over a collection.
  4038. * @param {boolean} [fromRight] Specify iterating from right to left.
  4039. * @returns {Function} Returns the new base function.
  4040. */
  4041. function createBaseEach(eachFunc, fromRight) {
  4042. return function(collection, iteratee) {
  4043. if (collection == null) {
  4044. return collection;
  4045. }
  4046. if (!isArrayLike(collection)) {
  4047. return eachFunc(collection, iteratee);
  4048. }
  4049. var length = collection.length,
  4050. index = fromRight ? length : -1,
  4051. iterable = Object(collection);
  4052. while ((fromRight ? index-- : ++index < length)) {
  4053. if (iteratee(iterable[index], index, iterable) === false) {
  4054. break;
  4055. }
  4056. }
  4057. return collection;
  4058. };
  4059. }
  4060. /**
  4061. * Creates a base function for methods like `_.forIn`.
  4062. *
  4063. * @private
  4064. * @param {boolean} [fromRight] Specify iterating from right to left.
  4065. * @returns {Function} Returns the new base function.
  4066. */
  4067. function createBaseFor(fromRight) {
  4068. return function(object, iteratee, keysFunc) {
  4069. var index = -1,
  4070. iterable = Object(object),
  4071. props = keysFunc(object),
  4072. length = props.length;
  4073. while (length--) {
  4074. var key = props[fromRight ? length : ++index];
  4075. if (iteratee(iterable[key], key, iterable) === false) {
  4076. break;
  4077. }
  4078. }
  4079. return object;
  4080. };
  4081. }
  4082. /**
  4083. * Creates a function that wraps `func` to invoke it with the optional `this`
  4084. * binding of `thisArg`.
  4085. *
  4086. * @private
  4087. * @param {Function} func The function to wrap.
  4088. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
  4089. * @param {*} [thisArg] The `this` binding of `func`.
  4090. * @returns {Function} Returns the new wrapped function.
  4091. */
  4092. function createBaseWrapper(func, bitmask, thisArg) {
  4093. var isBind = bitmask & BIND_FLAG,
  4094. Ctor = createCtorWrapper(func);
  4095. function wrapper() {
  4096. var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  4097. return fn.apply(isBind ? thisArg : this, arguments);
  4098. }
  4099. return wrapper;
  4100. }
  4101. /**
  4102. * Creates a function like `_.lowerFirst`.
  4103. *
  4104. * @private
  4105. * @param {string} methodName The name of the `String` case method to use.
  4106. * @returns {Function} Returns the new function.
  4107. */
  4108. function createCaseFirst(methodName) {
  4109. return function(string) {
  4110. string = toString(string);
  4111. var strSymbols = reHasComplexSymbol.test(string)
  4112. ? stringToArray(string)
  4113. : undefined;
  4114. var chr = strSymbols ? strSymbols[0] : string.charAt(0),
  4115. trailing = strSymbols ? strSymbols.slice(1).join('') : string.slice(1);
  4116. return chr[methodName]() + trailing;
  4117. };
  4118. }
  4119. /**
  4120. * Creates a function like `_.camelCase`.
  4121. *
  4122. * @private
  4123. * @param {Function} callback The function to combine each word.
  4124. * @returns {Function} Returns the new compounder function.
  4125. */
  4126. function createCompounder(callback) {
  4127. return function(string) {
  4128. return arrayReduce(words(deburr(string)), callback, '');
  4129. };
  4130. }
  4131. /**
  4132. * Creates a function that produces an instance of `Ctor` regardless of
  4133. * whether it was invoked as part of a `new` expression or by `call` or `apply`.
  4134. *
  4135. * @private
  4136. * @param {Function} Ctor The constructor to wrap.
  4137. * @returns {Function} Returns the new wrapped function.
  4138. */
  4139. function createCtorWrapper(Ctor) {
  4140. return function() {
  4141. // Use a `switch` statement to work with class constructors.
  4142. // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
  4143. // for more details.
  4144. var args = arguments;
  4145. switch (args.length) {
  4146. case 0: return new Ctor;
  4147. case 1: return new Ctor(args[0]);
  4148. case 2: return new Ctor(args[0], args[1]);
  4149. case 3: return new Ctor(args[0], args[1], args[2]);
  4150. case 4: return new Ctor(args[0], args[1], args[2], args[3]);
  4151. case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
  4152. case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
  4153. case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
  4154. }
  4155. var thisBinding = baseCreate(Ctor.prototype),
  4156. result = Ctor.apply(thisBinding, args);
  4157. // Mimic the constructor's `return` behavior.
  4158. // See https://es5.github.io/#x13.2.2 for more details.
  4159. return isObject(result) ? result : thisBinding;
  4160. };
  4161. }
  4162. /**
  4163. * Creates a function that wraps `func` to enable currying.
  4164. *
  4165. * @private
  4166. * @param {Function} func The function to wrap.
  4167. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
  4168. * @param {number} arity The arity of `func`.
  4169. * @returns {Function} Returns the new wrapped function.
  4170. */
  4171. function createCurryWrapper(func, bitmask, arity) {
  4172. var Ctor = createCtorWrapper(func);
  4173. function wrapper() {
  4174. var length = arguments.length,
  4175. args = Array(length),
  4176. index = length,
  4177. placeholder = getPlaceholder(wrapper);
  4178. while (index--) {
  4179. args[index] = arguments[index];
  4180. }
  4181. var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
  4182. ? []
  4183. : replaceHolders(args, placeholder);
  4184. length -= holders.length;
  4185. if (length < arity) {
  4186. return createRecurryWrapper(
  4187. func, bitmask, createHybridWrapper, wrapper.placeholder, undefined,
  4188. args, holders, undefined, undefined, arity - length);
  4189. }
  4190. var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  4191. return apply(fn, this, args);
  4192. }
  4193. return wrapper;
  4194. }
  4195. /**
  4196. * Creates a `_.flow` or `_.flowRight` function.
  4197. *
  4198. * @private
  4199. * @param {boolean} [fromRight] Specify iterating from right to left.
  4200. * @returns {Function} Returns the new flow function.
  4201. */
  4202. function createFlow(fromRight) {
  4203. return rest(function(funcs) {
  4204. funcs = baseFlatten(funcs, 1);
  4205. var length = funcs.length,
  4206. index = length,
  4207. prereq = LodashWrapper.prototype.thru;
  4208. if (fromRight) {
  4209. funcs.reverse();
  4210. }
  4211. while (index--) {
  4212. var func = funcs[index];
  4213. if (typeof func != 'function') {
  4214. throw new TypeError(FUNC_ERROR_TEXT);
  4215. }
  4216. if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
  4217. var wrapper = new LodashWrapper([], true);
  4218. }
  4219. }
  4220. index = wrapper ? index : length;
  4221. while (++index < length) {
  4222. func = funcs[index];
  4223. var funcName = getFuncName(func),
  4224. data = funcName == 'wrapper' ? getData(func) : undefined;
  4225. if (data && isLaziable(data[0]) &&
  4226. data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) &&
  4227. !data[4].length && data[9] == 1
  4228. ) {
  4229. wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
  4230. } else {
  4231. wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
  4232. }
  4233. }
  4234. return function() {
  4235. var args = arguments,
  4236. value = args[0];
  4237. if (wrapper && args.length == 1 &&
  4238. isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
  4239. return wrapper.plant(value).value();
  4240. }
  4241. var index = 0,
  4242. result = length ? funcs[index].apply(this, args) : value;
  4243. while (++index < length) {
  4244. result = funcs[index].call(this, result);
  4245. }
  4246. return result;
  4247. };
  4248. });
  4249. }
  4250. /**
  4251. * Creates a function that wraps `func` to invoke it with optional `this`
  4252. * binding of `thisArg`, partial application, and currying.
  4253. *
  4254. * @private
  4255. * @param {Function|string} func The function or method name to wrap.
  4256. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
  4257. * @param {*} [thisArg] The `this` binding of `func`.
  4258. * @param {Array} [partials] The arguments to prepend to those provided to the new function.
  4259. * @param {Array} [holders] The `partials` placeholder indexes.
  4260. * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
  4261. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
  4262. * @param {Array} [argPos] The argument positions of the new function.
  4263. * @param {number} [ary] The arity cap of `func`.
  4264. * @param {number} [arity] The arity of `func`.
  4265. * @returns {Function} Returns the new wrapped function.
  4266. */
  4267. function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
  4268. var isAry = bitmask & ARY_FLAG,
  4269. isBind = bitmask & BIND_FLAG,
  4270. isBindKey = bitmask & BIND_KEY_FLAG,
  4271. isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
  4272. isFlip = bitmask & FLIP_FLAG,
  4273. Ctor = isBindKey ? undefined : createCtorWrapper(func);
  4274. function wrapper() {
  4275. var length = arguments.length,
  4276. index = length,
  4277. args = Array(length);
  4278. while (index--) {
  4279. args[index] = arguments[index];
  4280. }
  4281. if (isCurried) {
  4282. var placeholder = getPlaceholder(wrapper),
  4283. holdersCount = countHolders(args, placeholder);
  4284. }
  4285. if (partials) {
  4286. args = composeArgs(args, partials, holders, isCurried);
  4287. }
  4288. if (partialsRight) {
  4289. args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
  4290. }
  4291. length -= holdersCount;
  4292. if (isCurried && length < arity) {
  4293. var newHolders = replaceHolders(args, placeholder);
  4294. return createRecurryWrapper(
  4295. func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
  4296. args, newHolders, argPos, ary, arity - length
  4297. );
  4298. }
  4299. var thisBinding = isBind ? thisArg : this,
  4300. fn = isBindKey ? thisBinding[func] : func;
  4301. length = args.length;
  4302. if (argPos) {
  4303. args = reorder(args, argPos);
  4304. } else if (isFlip && length > 1) {
  4305. args.reverse();
  4306. }
  4307. if (isAry && ary < length) {
  4308. args.length = ary;
  4309. }
  4310. if (this && this !== root && this instanceof wrapper) {
  4311. fn = Ctor || createCtorWrapper(fn);
  4312. }
  4313. return fn.apply(thisBinding, args);
  4314. }
  4315. return wrapper;
  4316. }
  4317. /**
  4318. * Creates a function like `_.invertBy`.
  4319. *
  4320. * @private
  4321. * @param {Function} setter The function to set accumulator values.
  4322. * @param {Function} toIteratee The function to resolve iteratees.
  4323. * @returns {Function} Returns the new inverter function.
  4324. */
  4325. function createInverter(setter, toIteratee) {
  4326. return function(object, iteratee) {
  4327. return baseInverter(object, setter, toIteratee(iteratee), {});
  4328. };
  4329. }
  4330. /**
  4331. * Creates a function like `_.over`.
  4332. *
  4333. * @private
  4334. * @param {Function} arrayFunc The function to iterate over iteratees.
  4335. * @returns {Function} Returns the new invoker function.
  4336. */
  4337. function createOver(arrayFunc) {
  4338. return rest(function(iteratees) {
  4339. iteratees = arrayMap(baseFlatten(iteratees, 1), getIteratee());
  4340. return rest(function(args) {
  4341. var thisArg = this;
  4342. return arrayFunc(iteratees, function(iteratee) {
  4343. return apply(iteratee, thisArg, args);
  4344. });
  4345. });
  4346. });
  4347. }
  4348. /**
  4349. * Creates the padding for `string` based on `length`. The `chars` string
  4350. * is truncated if the number of characters exceeds `length`.
  4351. *
  4352. * @private
  4353. * @param {string} string The string to create padding for.
  4354. * @param {number} [length=0] The padding length.
  4355. * @param {string} [chars=' '] The string used as padding.
  4356. * @returns {string} Returns the padding for `string`.
  4357. */
  4358. function createPadding(string, length, chars) {
  4359. length = toInteger(length);
  4360. var strLength = stringSize(string);
  4361. if (!length || strLength >= length) {
  4362. return '';
  4363. }
  4364. var padLength = length - strLength;
  4365. chars = chars === undefined ? ' ' : (chars + '');
  4366. var result = repeat(chars, nativeCeil(padLength / stringSize(chars)));
  4367. return reHasComplexSymbol.test(chars)
  4368. ? stringToArray(result).slice(0, padLength).join('')
  4369. : result.slice(0, padLength);
  4370. }
  4371. /**
  4372. * Creates a function that wraps `func` to invoke it with the optional `this`
  4373. * binding of `thisArg` and the `partials` prepended to those provided to
  4374. * the wrapper.
  4375. *
  4376. * @private
  4377. * @param {Function} func The function to wrap.
  4378. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
  4379. * @param {*} thisArg The `this` binding of `func`.
  4380. * @param {Array} partials The arguments to prepend to those provided to the new function.
  4381. * @returns {Function} Returns the new wrapped function.
  4382. */
  4383. function createPartialWrapper(func, bitmask, thisArg, partials) {
  4384. var isBind = bitmask & BIND_FLAG,
  4385. Ctor = createCtorWrapper(func);
  4386. function wrapper() {
  4387. var argsIndex = -1,
  4388. argsLength = arguments.length,
  4389. leftIndex = -1,
  4390. leftLength = partials.length,
  4391. args = Array(leftLength + argsLength),
  4392. fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  4393. while (++leftIndex < leftLength) {
  4394. args[leftIndex] = partials[leftIndex];
  4395. }
  4396. while (argsLength--) {
  4397. args[leftIndex++] = arguments[++argsIndex];
  4398. }
  4399. return apply(fn, isBind ? thisArg : this, args);
  4400. }
  4401. return wrapper;
  4402. }
  4403. /**
  4404. * Creates a `_.range` or `_.rangeRight` function.
  4405. *
  4406. * @private
  4407. * @param {boolean} [fromRight] Specify iterating from right to left.
  4408. * @returns {Function} Returns the new range function.
  4409. */
  4410. function createRange(fromRight) {
  4411. return function(start, end, step) {
  4412. if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
  4413. end = step = undefined;
  4414. }
  4415. // Ensure the sign of `-0` is preserved.
  4416. start = toNumber(start);
  4417. start = start === start ? start : 0;
  4418. if (end === undefined) {
  4419. end = start;
  4420. start = 0;
  4421. } else {
  4422. end = toNumber(end) || 0;
  4423. }
  4424. step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0);
  4425. return baseRange(start, end, step, fromRight);
  4426. };
  4427. }
  4428. /**
  4429. * Creates a function that wraps `func` to continue currying.
  4430. *
  4431. * @private
  4432. * @param {Function} func The function to wrap.
  4433. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` for more details.
  4434. * @param {Function} wrapFunc The function to create the `func` wrapper.
  4435. * @param {*} placeholder The placeholder value.
  4436. * @param {*} [thisArg] The `this` binding of `func`.
  4437. * @param {Array} [partials] The arguments to prepend to those provided to the new function.
  4438. * @param {Array} [holders] The `partials` placeholder indexes.
  4439. * @param {Array} [argPos] The argument positions of the new function.
  4440. * @param {number} [ary] The arity cap of `func`.
  4441. * @param {number} [arity] The arity of `func`.
  4442. * @returns {Function} Returns the new wrapped function.
  4443. */
  4444. function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
  4445. var isCurry = bitmask & CURRY_FLAG,
  4446. newArgPos = argPos ? copyArray(argPos) : undefined,
  4447. newHolders = isCurry ? holders : undefined,
  4448. newHoldersRight = isCurry ? undefined : holders,
  4449. newPartials = isCurry ? partials : undefined,
  4450. newPartialsRight = isCurry ? undefined : partials;
  4451. bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
  4452. bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
  4453. if (!(bitmask & CURRY_BOUND_FLAG)) {
  4454. bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
  4455. }
  4456. var newData = [
  4457. func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
  4458. newHoldersRight, newArgPos, ary, arity
  4459. ];
  4460. var result = wrapFunc.apply(undefined, newData);
  4461. if (isLaziable(func)) {
  4462. setData(result, newData);
  4463. }
  4464. result.placeholder = placeholder;
  4465. return result;
  4466. }
  4467. /**
  4468. * Creates a function like `_.round`.
  4469. *
  4470. * @private
  4471. * @param {string} methodName The name of the `Math` method to use when rounding.
  4472. * @returns {Function} Returns the new round function.
  4473. */
  4474. function createRound(methodName) {
  4475. var func = Math[methodName];
  4476. return function(number, precision) {
  4477. number = toNumber(number);
  4478. precision = toInteger(precision);
  4479. if (precision) {
  4480. // Shift with exponential notation to avoid floating-point issues.
  4481. // See [MDN](https://mdn.io/round#Examples) for more details.
  4482. var pair = (toString(number) + 'e').split('e'),
  4483. value = func(pair[0] + 'e' + (+pair[1] + precision));
  4484. pair = (toString(value) + 'e').split('e');
  4485. return +(pair[0] + 'e' + (+pair[1] - precision));
  4486. }
  4487. return func(number);
  4488. };
  4489. }
  4490. /**
  4491. * Creates a set of `values`.
  4492. *
  4493. * @private
  4494. * @param {Array} values The values to add to the set.
  4495. * @returns {Object} Returns the new set.
  4496. */
  4497. var createSet = !(Set && new Set([1, 2]).size === 2) ? noop : function(values) {
  4498. return new Set(values);
  4499. };
  4500. /**
  4501. * Creates a function that either curries or invokes `func` with optional
  4502. * `this` binding and partially applied arguments.
  4503. *
  4504. * @private
  4505. * @param {Function|string} func The function or method name to wrap.
  4506. * @param {number} bitmask The bitmask of wrapper flags.
  4507. * The bitmask may be composed of the following flags:
  4508. * 1 - `_.bind`
  4509. * 2 - `_.bindKey`
  4510. * 4 - `_.curry` or `_.curryRight` of a bound function
  4511. * 8 - `_.curry`
  4512. * 16 - `_.curryRight`
  4513. * 32 - `_.partial`
  4514. * 64 - `_.partialRight`
  4515. * 128 - `_.rearg`
  4516. * 256 - `_.ary`
  4517. * @param {*} [thisArg] The `this` binding of `func`.
  4518. * @param {Array} [partials] The arguments to be partially applied.
  4519. * @param {Array} [holders] The `partials` placeholder indexes.
  4520. * @param {Array} [argPos] The argument positions of the new function.
  4521. * @param {number} [ary] The arity cap of `func`.
  4522. * @param {number} [arity] The arity of `func`.
  4523. * @returns {Function} Returns the new wrapped function.
  4524. */
  4525. function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
  4526. var isBindKey = bitmask & BIND_KEY_FLAG;
  4527. if (!isBindKey && typeof func != 'function') {
  4528. throw new TypeError(FUNC_ERROR_TEXT);
  4529. }
  4530. var length = partials ? partials.length : 0;
  4531. if (!length) {
  4532. bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
  4533. partials = holders = undefined;
  4534. }
  4535. ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
  4536. arity = arity === undefined ? arity : toInteger(arity);
  4537. length -= holders ? holders.length : 0;
  4538. if (bitmask & PARTIAL_RIGHT_FLAG) {
  4539. var partialsRight = partials,
  4540. holdersRight = holders;
  4541. partials = holders = undefined;
  4542. }
  4543. var data = isBindKey ? undefined : getData(func);
  4544. var newData = [
  4545. func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
  4546. argPos, ary, arity
  4547. ];
  4548. if (data) {
  4549. mergeData(newData, data);
  4550. }
  4551. func = newData[0];
  4552. bitmask = newData[1];
  4553. thisArg = newData[2];
  4554. partials = newData[3];
  4555. holders = newData[4];
  4556. arity = newData[9] = newData[9] == null
  4557. ? (isBindKey ? 0 : func.length)
  4558. : nativeMax(newData[9] - length, 0);
  4559. if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) {
  4560. bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG);
  4561. }
  4562. if (!bitmask || bitmask == BIND_FLAG) {
  4563. var result = createBaseWrapper(func, bitmask, thisArg);
  4564. } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
  4565. result = createCurryWrapper(func, bitmask, arity);
  4566. } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
  4567. result = createPartialWrapper(func, bitmask, thisArg, partials);
  4568. } else {
  4569. result = createHybridWrapper.apply(undefined, newData);
  4570. }
  4571. var setter = data ? baseSetData : setData;
  4572. return setter(result, newData);
  4573. }
  4574. /**
  4575. * A specialized version of `baseIsEqualDeep` for arrays with support for
  4576. * partial deep comparisons.
  4577. *
  4578. * @private
  4579. * @param {Array} array The array to compare.
  4580. * @param {Array} other The other array to compare.
  4581. * @param {Function} equalFunc The function to determine equivalents of values.
  4582. * @param {Function} [customizer] The function to customize comparisons.
  4583. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
  4584. * @param {Object} [stack] Tracks traversed `array` and `other` objects.
  4585. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
  4586. */
  4587. function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
  4588. var index = -1,
  4589. isPartial = bitmask & PARTIAL_COMPARE_FLAG,
  4590. isUnordered = bitmask & UNORDERED_COMPARE_FLAG,
  4591. arrLength = array.length,
  4592. othLength = other.length;
  4593. if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
  4594. return false;
  4595. }
  4596. // Assume cyclic values are equal.
  4597. var stacked = stack.get(array);
  4598. if (stacked) {
  4599. return stacked == other;
  4600. }
  4601. var result = true;
  4602. stack.set(array, other);
  4603. // Ignore non-index properties.
  4604. while (++index < arrLength) {
  4605. var arrValue = array[index],
  4606. othValue = other[index];
  4607. if (customizer) {
  4608. var compared = isPartial
  4609. ? customizer(othValue, arrValue, index, other, array, stack)
  4610. : customizer(arrValue, othValue, index, array, other, stack);
  4611. }
  4612. if (compared !== undefined) {
  4613. if (compared) {
  4614. continue;
  4615. }
  4616. result = false;
  4617. break;
  4618. }
  4619. // Recursively compare arrays (susceptible to call stack limits).
  4620. if (isUnordered) {
  4621. if (!arraySome(other, function(othValue) {
  4622. return arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack);
  4623. })) {
  4624. result = false;
  4625. break;
  4626. }
  4627. } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
  4628. result = false;
  4629. break;
  4630. }
  4631. }
  4632. stack['delete'](array);
  4633. return result;
  4634. }
  4635. /**
  4636. * A specialized version of `baseIsEqualDeep` for comparing objects of
  4637. * the same `toStringTag`.
  4638. *
  4639. * **Note:** This function only supports comparing values with tags of
  4640. * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
  4641. *
  4642. * @private
  4643. * @param {Object} object The object to compare.
  4644. * @param {Object} other The other object to compare.
  4645. * @param {string} tag The `toStringTag` of the objects to compare.
  4646. * @param {Function} equalFunc The function to determine equivalents of values.
  4647. * @param {Function} [customizer] The function to customize comparisons.
  4648. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
  4649. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
  4650. */
  4651. function equalByTag(object, other, tag, equalFunc, customizer, bitmask) {
  4652. switch (tag) {
  4653. case arrayBufferTag:
  4654. if ((object.byteLength != other.byteLength) ||
  4655. !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
  4656. return false;
  4657. }
  4658. return true;
  4659. case boolTag:
  4660. case dateTag:
  4661. // Coerce dates and booleans to numbers, dates to milliseconds and booleans
  4662. // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
  4663. return +object == +other;
  4664. case errorTag:
  4665. return object.name == other.name && object.message == other.message;
  4666. case numberTag:
  4667. // Treat `NaN` vs. `NaN` as equal.
  4668. return (object != +object) ? other != +other : object == +other;
  4669. case regexpTag:
  4670. case stringTag:
  4671. // Coerce regexes to strings and treat strings primitives and string
  4672. // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
  4673. return object == (other + '');
  4674. case mapTag:
  4675. var convert = mapToArray;
  4676. case setTag:
  4677. var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
  4678. convert || (convert = setToArray);
  4679. // Recursively compare objects (susceptible to call stack limits).
  4680. return (isPartial || object.size == other.size) &&
  4681. equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
  4682. case symbolTag:
  4683. return !!Symbol && (symbolValueOf.call(object) == symbolValueOf.call(other));
  4684. }
  4685. return false;
  4686. }
  4687. /**
  4688. * A specialized version of `baseIsEqualDeep` for objects with support for
  4689. * partial deep comparisons.
  4690. *
  4691. * @private
  4692. * @param {Object} object The object to compare.
  4693. * @param {Object} other The other object to compare.
  4694. * @param {Function} equalFunc The function to determine equivalents of values.
  4695. * @param {Function} [customizer] The function to customize comparisons.
  4696. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` for more details.
  4697. * @param {Object} [stack] Tracks traversed `object` and `other` objects.
  4698. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
  4699. */
  4700. function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
  4701. var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
  4702. objProps = keys(object),
  4703. objLength = objProps.length,
  4704. othProps = keys(other),
  4705. othLength = othProps.length;
  4706. if (objLength != othLength && !isPartial) {
  4707. return false;
  4708. }
  4709. var index = objLength;
  4710. while (index--) {
  4711. var key = objProps[index];
  4712. if (!(isPartial ? key in other : baseHas(other, key))) {
  4713. return false;
  4714. }
  4715. }
  4716. // Assume cyclic values are equal.
  4717. var stacked = stack.get(object);
  4718. if (stacked) {
  4719. return stacked == other;
  4720. }
  4721. var result = true;
  4722. stack.set(object, other);
  4723. var skipCtor = isPartial;
  4724. while (++index < objLength) {
  4725. key = objProps[index];
  4726. var objValue = object[key],
  4727. othValue = other[key];
  4728. if (customizer) {
  4729. var compared = isPartial
  4730. ? customizer(othValue, objValue, key, other, object, stack)
  4731. : customizer(objValue, othValue, key, object, other, stack);
  4732. }
  4733. // Recursively compare objects (susceptible to call stack limits).
  4734. if (!(compared === undefined
  4735. ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
  4736. : compared
  4737. )) {
  4738. result = false;
  4739. break;
  4740. }
  4741. skipCtor || (skipCtor = key == 'constructor');
  4742. }
  4743. if (result && !skipCtor) {
  4744. var objCtor = object.constructor,
  4745. othCtor = other.constructor;
  4746. // Non `Object` object instances with different constructors are not equal.
  4747. if (objCtor != othCtor &&
  4748. ('constructor' in object && 'constructor' in other) &&
  4749. !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
  4750. typeof othCtor == 'function' && othCtor instanceof othCtor)) {
  4751. result = false;
  4752. }
  4753. }
  4754. stack['delete'](object);
  4755. return result;
  4756. }
  4757. /**
  4758. * Gets metadata for `func`.
  4759. *
  4760. * @private
  4761. * @param {Function} func The function to query.
  4762. * @returns {*} Returns the metadata for `func`.
  4763. */
  4764. var getData = !metaMap ? noop : function(func) {
  4765. return metaMap.get(func);
  4766. };
  4767. /**
  4768. * Gets the name of `func`.
  4769. *
  4770. * @private
  4771. * @param {Function} func The function to query.
  4772. * @returns {string} Returns the function name.
  4773. */
  4774. function getFuncName(func) {
  4775. var result = (func.name + ''),
  4776. array = realNames[result],
  4777. length = hasOwnProperty.call(realNames, result) ? array.length : 0;
  4778. while (length--) {
  4779. var data = array[length],
  4780. otherFunc = data.func;
  4781. if (otherFunc == null || otherFunc == func) {
  4782. return data.name;
  4783. }
  4784. }
  4785. return result;
  4786. }
  4787. /**
  4788. * Gets the appropriate "iteratee" function. If the `_.iteratee` method is
  4789. * customized this function returns the custom method, otherwise it returns
  4790. * `baseIteratee`. If arguments are provided the chosen function is invoked
  4791. * with them and its result is returned.
  4792. *
  4793. * @private
  4794. * @param {*} [value] The value to convert to an iteratee.
  4795. * @param {number} [arity] The arity of the created iteratee.
  4796. * @returns {Function} Returns the chosen function or its result.
  4797. */
  4798. function getIteratee() {
  4799. var result = lodash.iteratee || iteratee;
  4800. result = result === iteratee ? baseIteratee : result;
  4801. return arguments.length ? result(arguments[0], arguments[1]) : result;
  4802. }
  4803. /**
  4804. * Gets the "length" property value of `object`.
  4805. *
  4806. * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
  4807. * that affects Safari on at least iOS 8.1-8.3 ARM64.
  4808. *
  4809. * @private
  4810. * @param {Object} object The object to query.
  4811. * @returns {*} Returns the "length" value.
  4812. */
  4813. var getLength = baseProperty('length');
  4814. /**
  4815. * Gets the property names, values, and compare flags of `object`.
  4816. *
  4817. * @private
  4818. * @param {Object} object The object to query.
  4819. * @returns {Array} Returns the match data of `object`.
  4820. */
  4821. function getMatchData(object) {
  4822. var result = toPairs(object),
  4823. length = result.length;
  4824. while (length--) {
  4825. result[length][2] = isStrictComparable(result[length][1]);
  4826. }
  4827. return result;
  4828. }
  4829. /**
  4830. * Gets the native function at `key` of `object`.
  4831. *
  4832. * @private
  4833. * @param {Object} object The object to query.
  4834. * @param {string} key The key of the method to get.
  4835. * @returns {*} Returns the function if it's native, else `undefined`.
  4836. */
  4837. function getNative(object, key) {
  4838. var value = object == null ? undefined : object[key];
  4839. return isNative(value) ? value : undefined;
  4840. }
  4841. /**
  4842. * Gets the argument placeholder value for `func`.
  4843. *
  4844. * @private
  4845. * @param {Function} func The function to inspect.
  4846. * @returns {*} Returns the placeholder value.
  4847. */
  4848. function getPlaceholder(func) {
  4849. var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
  4850. return object.placeholder;
  4851. }
  4852. /**
  4853. * Creates an array of the own symbol properties of `object`.
  4854. *
  4855. * @private
  4856. * @param {Object} object The object to query.
  4857. * @returns {Array} Returns the array of symbols.
  4858. */
  4859. var getSymbols = getOwnPropertySymbols || function() {
  4860. return [];
  4861. };
  4862. /**
  4863. * Gets the `toStringTag` of `value`.
  4864. *
  4865. * @private
  4866. * @param {*} value The value to query.
  4867. * @returns {string} Returns the `toStringTag`.
  4868. */
  4869. function getTag(value) {
  4870. return objectToString.call(value);
  4871. }
  4872. // Fallback for IE 11 providing `toStringTag` values for maps, sets, and weakmaps.
  4873. if ((Map && getTag(new Map) != mapTag) ||
  4874. (Set && getTag(new Set) != setTag) ||
  4875. (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  4876. getTag = function(value) {
  4877. var result = objectToString.call(value),
  4878. Ctor = result == objectTag ? value.constructor : null,
  4879. ctorString = typeof Ctor == 'function' ? funcToString.call(Ctor) : '';
  4880. if (ctorString) {
  4881. switch (ctorString) {
  4882. case mapCtorString: return mapTag;
  4883. case setCtorString: return setTag;
  4884. case weakMapCtorString: return weakMapTag;
  4885. }
  4886. }
  4887. return result;
  4888. };
  4889. }
  4890. /**
  4891. * Gets the view, applying any `transforms` to the `start` and `end` positions.
  4892. *
  4893. * @private
  4894. * @param {number} start The start of the view.
  4895. * @param {number} end The end of the view.
  4896. * @param {Array} transforms The transformations to apply to the view.
  4897. * @returns {Object} Returns an object containing the `start` and `end`
  4898. * positions of the view.
  4899. */
  4900. function getView(start, end, transforms) {
  4901. var index = -1,
  4902. length = transforms.length;
  4903. while (++index < length) {
  4904. var data = transforms[index],
  4905. size = data.size;
  4906. switch (data.type) {
  4907. case 'drop': start += size; break;
  4908. case 'dropRight': end -= size; break;
  4909. case 'take': end = nativeMin(end, start + size); break;
  4910. case 'takeRight': start = nativeMax(start, end - size); break;
  4911. }
  4912. }
  4913. return { 'start': start, 'end': end };
  4914. }
  4915. /**
  4916. * Checks if `path` exists on `object`.
  4917. *
  4918. * @private
  4919. * @param {Object} object The object to query.
  4920. * @param {Array|string} path The path to check.
  4921. * @param {Function} hasFunc The function to check properties.
  4922. * @returns {boolean} Returns `true` if `path` exists, else `false`.
  4923. */
  4924. function hasPath(object, path, hasFunc) {
  4925. if (object == null) {
  4926. return false;
  4927. }
  4928. var result = hasFunc(object, path);
  4929. if (!result && !isKey(path)) {
  4930. path = baseCastPath(path);
  4931. object = parent(object, path);
  4932. if (object != null) {
  4933. path = last(path);
  4934. result = hasFunc(object, path);
  4935. }
  4936. }
  4937. var length = object ? object.length : undefined;
  4938. return result || (
  4939. !!length && isLength(length) && isIndex(path, length) &&
  4940. (isArray(object) || isString(object) || isArguments(object))
  4941. );
  4942. }
  4943. /**
  4944. * Initializes an array clone.
  4945. *
  4946. * @private
  4947. * @param {Array} array The array to clone.
  4948. * @returns {Array} Returns the initialized clone.
  4949. */
  4950. function initCloneArray(array) {
  4951. var length = array.length,
  4952. result = array.constructor(length);
  4953. // Add properties assigned by `RegExp#exec`.
  4954. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
  4955. result.index = array.index;
  4956. result.input = array.input;
  4957. }
  4958. return result;
  4959. }
  4960. /**
  4961. * Initializes an object clone.
  4962. *
  4963. * @private
  4964. * @param {Object} object The object to clone.
  4965. * @returns {Object} Returns the initialized clone.
  4966. */
  4967. function initCloneObject(object) {
  4968. return (isFunction(object.constructor) && !isPrototype(object))
  4969. ? baseCreate(getPrototypeOf(object))
  4970. : {};
  4971. }
  4972. /**
  4973. * Initializes an object clone based on its `toStringTag`.
  4974. *
  4975. * **Note:** This function only supports cloning values with tags of
  4976. * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
  4977. *
  4978. * @private
  4979. * @param {Object} object The object to clone.
  4980. * @param {string} tag The `toStringTag` of the object to clone.
  4981. * @param {boolean} [isDeep] Specify a deep clone.
  4982. * @returns {Object} Returns the initialized clone.
  4983. */
  4984. function initCloneByTag(object, tag, isDeep) {
  4985. var Ctor = object.constructor;
  4986. switch (tag) {
  4987. case arrayBufferTag:
  4988. return cloneArrayBuffer(object);
  4989. case boolTag:
  4990. case dateTag:
  4991. return new Ctor(+object);
  4992. case float32Tag: case float64Tag:
  4993. case int8Tag: case int16Tag: case int32Tag:
  4994. case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
  4995. return cloneTypedArray(object, isDeep);
  4996. case mapTag:
  4997. return cloneMap(object);
  4998. case numberTag:
  4999. case stringTag:
  5000. return new Ctor(object);
  5001. case regexpTag:
  5002. return cloneRegExp(object);
  5003. case setTag:
  5004. return cloneSet(object);
  5005. case symbolTag:
  5006. return cloneSymbol(object);
  5007. }
  5008. }
  5009. /**
  5010. * Creates an array of index keys for `object` values of arrays,
  5011. * `arguments` objects, and strings, otherwise `null` is returned.
  5012. *
  5013. * @private
  5014. * @param {Object} object The object to query.
  5015. * @returns {Array|null} Returns index keys, else `null`.
  5016. */
  5017. function indexKeys(object) {
  5018. var length = object ? object.length : undefined;
  5019. if (isLength(length) &&
  5020. (isArray(object) || isString(object) || isArguments(object))) {
  5021. return baseTimes(length, String);
  5022. }
  5023. return null;
  5024. }
  5025. /**
  5026. * Checks if the given arguments are from an iteratee call.
  5027. *
  5028. * @private
  5029. * @param {*} value The potential iteratee value argument.
  5030. * @param {*} index The potential iteratee index or key argument.
  5031. * @param {*} object The potential iteratee object argument.
  5032. * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
  5033. */
  5034. function isIterateeCall(value, index, object) {
  5035. if (!isObject(object)) {
  5036. return false;
  5037. }
  5038. var type = typeof index;
  5039. if (type == 'number'
  5040. ? (isArrayLike(object) && isIndex(index, object.length))
  5041. : (type == 'string' && index in object)) {
  5042. return eq(object[index], value);
  5043. }
  5044. return false;
  5045. }
  5046. /**
  5047. * Checks if `value` is a property name and not a property path.
  5048. *
  5049. * @private
  5050. * @param {*} value The value to check.
  5051. * @param {Object} [object] The object to query keys on.
  5052. * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
  5053. */
  5054. function isKey(value, object) {
  5055. if (typeof value == 'number') {
  5056. return true;
  5057. }
  5058. return !isArray(value) &&
  5059. (reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
  5060. (object != null && value in Object(object)));
  5061. }
  5062. /**
  5063. * Checks if `value` is suitable for use as unique object key.
  5064. *
  5065. * @private
  5066. * @param {*} value The value to check.
  5067. * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
  5068. */
  5069. function isKeyable(value) {
  5070. var type = typeof value;
  5071. return type == 'number' || type == 'boolean' ||
  5072. (type == 'string' && value != '__proto__') || value == null;
  5073. }
  5074. /**
  5075. * Checks if `func` has a lazy counterpart.
  5076. *
  5077. * @private
  5078. * @param {Function} func The function to check.
  5079. * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
  5080. */
  5081. function isLaziable(func) {
  5082. var funcName = getFuncName(func),
  5083. other = lodash[funcName];
  5084. if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
  5085. return false;
  5086. }
  5087. if (func === other) {
  5088. return true;
  5089. }
  5090. var data = getData(other);
  5091. return !!data && func === data[0];
  5092. }
  5093. /**
  5094. * Checks if `value` is likely a prototype object.
  5095. *
  5096. * @private
  5097. * @param {*} value The value to check.
  5098. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
  5099. */
  5100. function isPrototype(value) {
  5101. var Ctor = value && value.constructor,
  5102. proto = (isFunction(Ctor) && Ctor.prototype) || objectProto;
  5103. return value === proto;
  5104. }
  5105. /**
  5106. * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
  5107. *
  5108. * @private
  5109. * @param {*} value The value to check.
  5110. * @returns {boolean} Returns `true` if `value` if suitable for strict
  5111. * equality comparisons, else `false`.
  5112. */
  5113. function isStrictComparable(value) {
  5114. return value === value && !isObject(value);
  5115. }
  5116. /**
  5117. * Merges the function metadata of `source` into `data`.
  5118. *
  5119. * Merging metadata reduces the number of wrappers used to invoke a function.
  5120. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
  5121. * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
  5122. * modify function arguments, making the order in which they are executed important,
  5123. * preventing the merging of metadata. However, we make an exception for a safe
  5124. * combined case where curried functions have `_.ary` and or `_.rearg` applied.
  5125. *
  5126. * @private
  5127. * @param {Array} data The destination metadata.
  5128. * @param {Array} source The source metadata.
  5129. * @returns {Array} Returns `data`.
  5130. */
  5131. function mergeData(data, source) {
  5132. var bitmask = data[1],
  5133. srcBitmask = source[1],
  5134. newBitmask = bitmask | srcBitmask,
  5135. isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG);
  5136. var isCombo =
  5137. ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) ||
  5138. ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
  5139. ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));
  5140. // Exit early if metadata can't be merged.
  5141. if (!(isCommon || isCombo)) {
  5142. return data;
  5143. }
  5144. // Use source `thisArg` if available.
  5145. if (srcBitmask & BIND_FLAG) {
  5146. data[2] = source[2];
  5147. // Set when currying a bound function.
  5148. newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG;
  5149. }
  5150. // Compose partial arguments.
  5151. var value = source[3];
  5152. if (value) {
  5153. var partials = data[3];
  5154. data[3] = partials ? composeArgs(partials, value, source[4]) : copyArray(value);
  5155. data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : copyArray(source[4]);
  5156. }
  5157. // Compose partial right arguments.
  5158. value = source[5];
  5159. if (value) {
  5160. partials = data[5];
  5161. data[5] = partials ? composeArgsRight(partials, value, source[6]) : copyArray(value);
  5162. data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : copyArray(source[6]);
  5163. }
  5164. // Use source `argPos` if available.
  5165. value = source[7];
  5166. if (value) {
  5167. data[7] = copyArray(value);
  5168. }
  5169. // Use source `ary` if it's smaller.
  5170. if (srcBitmask & ARY_FLAG) {
  5171. data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
  5172. }
  5173. // Use source `arity` if one is not provided.
  5174. if (data[9] == null) {
  5175. data[9] = source[9];
  5176. }
  5177. // Use source `func` and merge bitmasks.
  5178. data[0] = source[0];
  5179. data[1] = newBitmask;
  5180. return data;
  5181. }
  5182. /**
  5183. * Used by `_.defaultsDeep` to customize its `_.merge` use.
  5184. *
  5185. * @private
  5186. * @param {*} objValue The destination value.
  5187. * @param {*} srcValue The source value.
  5188. * @param {string} key The key of the property to merge.
  5189. * @param {Object} object The parent object of `objValue`.
  5190. * @param {Object} source The parent object of `srcValue`.
  5191. * @param {Object} [stack] Tracks traversed source values and their merged counterparts.
  5192. * @returns {*} Returns the value to assign.
  5193. */
  5194. function mergeDefaults(objValue, srcValue, key, object, source, stack) {
  5195. if (isObject(objValue) && isObject(srcValue)) {
  5196. stack.set(srcValue, objValue);
  5197. baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
  5198. }
  5199. return objValue;
  5200. }
  5201. /**
  5202. * Gets the parent value at `path` of `object`.
  5203. *
  5204. * @private
  5205. * @param {Object} object The object to query.
  5206. * @param {Array} path The path to get the parent value of.
  5207. * @returns {*} Returns the parent value.
  5208. */
  5209. function parent(object, path) {
  5210. return path.length == 1 ? object : get(object, baseSlice(path, 0, -1));
  5211. }
  5212. /**
  5213. * Reorder `array` according to the specified indexes where the element at
  5214. * the first index is assigned as the first element, the element at
  5215. * the second index is assigned as the second element, and so on.
  5216. *
  5217. * @private
  5218. * @param {Array} array The array to reorder.
  5219. * @param {Array} indexes The arranged array indexes.
  5220. * @returns {Array} Returns `array`.
  5221. */
  5222. function reorder(array, indexes) {
  5223. var arrLength = array.length,
  5224. length = nativeMin(indexes.length, arrLength),
  5225. oldArray = copyArray(array);
  5226. while (length--) {
  5227. var index = indexes[length];
  5228. array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
  5229. }
  5230. return array;
  5231. }
  5232. /**
  5233. * Sets metadata for `func`.
  5234. *
  5235. * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
  5236. * period of time, it will trip its breaker and transition to an identity function
  5237. * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
  5238. * for more details.
  5239. *
  5240. * @private
  5241. * @param {Function} func The function to associate metadata with.
  5242. * @param {*} data The metadata.
  5243. * @returns {Function} Returns `func`.
  5244. */
  5245. var setData = (function() {
  5246. var count = 0,
  5247. lastCalled = 0;
  5248. return function(key, value) {
  5249. var stamp = now(),
  5250. remaining = HOT_SPAN - (stamp - lastCalled);
  5251. lastCalled = stamp;
  5252. if (remaining > 0) {
  5253. if (++count >= HOT_COUNT) {
  5254. return key;
  5255. }
  5256. } else {
  5257. count = 0;
  5258. }
  5259. return baseSetData(key, value);
  5260. };
  5261. }());
  5262. /**
  5263. * Converts `string` to a property path array.
  5264. *
  5265. * @private
  5266. * @param {string} string The string to convert.
  5267. * @returns {Array} Returns the property path array.
  5268. */
  5269. function stringToPath(string) {
  5270. var result = [];
  5271. toString(string).replace(rePropName, function(match, number, quote, string) {
  5272. result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
  5273. });
  5274. return result;
  5275. }
  5276. /**
  5277. * Creates a clone of `wrapper`.
  5278. *
  5279. * @private
  5280. * @param {Object} wrapper The wrapper to clone.
  5281. * @returns {Object} Returns the cloned wrapper.
  5282. */
  5283. function wrapperClone(wrapper) {
  5284. if (wrapper instanceof LazyWrapper) {
  5285. return wrapper.clone();
  5286. }
  5287. var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
  5288. result.__actions__ = copyArray(wrapper.__actions__);
  5289. result.__index__ = wrapper.__index__;
  5290. result.__values__ = wrapper.__values__;
  5291. return result;
  5292. }
  5293. /*------------------------------------------------------------------------*/
  5294. /**
  5295. * Creates an array of elements split into groups the length of `size`.
  5296. * If `array` can't be split evenly, the final chunk will be the remaining
  5297. * elements.
  5298. *
  5299. * @static
  5300. * @memberOf _
  5301. * @category Array
  5302. * @param {Array} array The array to process.
  5303. * @param {number} [size=0] The length of each chunk.
  5304. * @returns {Array} Returns the new array containing chunks.
  5305. * @example
  5306. *
  5307. * _.chunk(['a', 'b', 'c', 'd'], 2);
  5308. * // => [['a', 'b'], ['c', 'd']]
  5309. *
  5310. * _.chunk(['a', 'b', 'c', 'd'], 3);
  5311. * // => [['a', 'b', 'c'], ['d']]
  5312. */
  5313. function chunk(array, size) {
  5314. size = nativeMax(toInteger(size), 0);
  5315. var length = array ? array.length : 0;
  5316. if (!length || size < 1) {
  5317. return [];
  5318. }
  5319. var index = 0,
  5320. resIndex = -1,
  5321. result = Array(nativeCeil(length / size));
  5322. while (index < length) {
  5323. result[++resIndex] = baseSlice(array, index, (index += size));
  5324. }
  5325. return result;
  5326. }
  5327. /**
  5328. * Creates an array with all falsey values removed. The values `false`, `null`,
  5329. * `0`, `""`, `undefined`, and `NaN` are falsey.
  5330. *
  5331. * @static
  5332. * @memberOf _
  5333. * @category Array
  5334. * @param {Array} array The array to compact.
  5335. * @returns {Array} Returns the new array of filtered values.
  5336. * @example
  5337. *
  5338. * _.compact([0, 1, false, 2, '', 3]);
  5339. * // => [1, 2, 3]
  5340. */
  5341. function compact(array) {
  5342. var index = -1,
  5343. length = array ? array.length : 0,
  5344. resIndex = -1,
  5345. result = [];
  5346. while (++index < length) {
  5347. var value = array[index];
  5348. if (value) {
  5349. result[++resIndex] = value;
  5350. }
  5351. }
  5352. return result;
  5353. }
  5354. /**
  5355. * Creates a new array concatenating `array` with any additional arrays
  5356. * and/or values.
  5357. *
  5358. * @static
  5359. * @memberOf _
  5360. * @category Array
  5361. * @param {Array} array The array to concatenate.
  5362. * @param {...*} [values] The values to concatenate.
  5363. * @returns {Array} Returns the new concatenated array.
  5364. * @example
  5365. *
  5366. * var array = [1];
  5367. * var other = _.concat(array, 2, [3], [[4]]);
  5368. *
  5369. * console.log(other);
  5370. * // => [1, 2, 3, [4]]
  5371. *
  5372. * console.log(array);
  5373. * // => [1]
  5374. */
  5375. var concat = rest(function(array, values) {
  5376. if (!isArray(array)) {
  5377. array = array == null ? [] : [Object(array)];
  5378. }
  5379. values = baseFlatten(values, 1);
  5380. return arrayConcat(array, values);
  5381. });
  5382. /**
  5383. * Creates an array of unique `array` values not included in the other
  5384. * given arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  5385. * for equality comparisons.
  5386. *
  5387. * @static
  5388. * @memberOf _
  5389. * @category Array
  5390. * @param {Array} array The array to inspect.
  5391. * @param {...Array} [values] The values to exclude.
  5392. * @returns {Array} Returns the new array of filtered values.
  5393. * @example
  5394. *
  5395. * _.difference([3, 2, 1], [4, 2]);
  5396. * // => [3, 1]
  5397. */
  5398. var difference = rest(function(array, values) {
  5399. return isArrayLikeObject(array)
  5400. ? baseDifference(array, baseFlatten(values, 1, true))
  5401. : [];
  5402. });
  5403. /**
  5404. * This method is like `_.difference` except that it accepts `iteratee` which
  5405. * is invoked for each element of `array` and `values` to generate the criterion
  5406. * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
  5407. *
  5408. * @static
  5409. * @memberOf _
  5410. * @category Array
  5411. * @param {Array} array The array to inspect.
  5412. * @param {...Array} [values] The values to exclude.
  5413. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  5414. * @returns {Array} Returns the new array of filtered values.
  5415. * @example
  5416. *
  5417. * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);
  5418. * // => [3.1, 1.3]
  5419. *
  5420. * // The `_.property` iteratee shorthand.
  5421. * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
  5422. * // => [{ 'x': 2 }]
  5423. */
  5424. var differenceBy = rest(function(array, values) {
  5425. var iteratee = last(values);
  5426. if (isArrayLikeObject(iteratee)) {
  5427. iteratee = undefined;
  5428. }
  5429. return isArrayLikeObject(array)
  5430. ? baseDifference(array, baseFlatten(values, 1, true), getIteratee(iteratee))
  5431. : [];
  5432. });
  5433. /**
  5434. * This method is like `_.difference` except that it accepts `comparator`
  5435. * which is invoked to compare elements of `array` to `values`. The comparator
  5436. * is invoked with two arguments: (arrVal, othVal).
  5437. *
  5438. * @static
  5439. * @memberOf _
  5440. * @category Array
  5441. * @param {Array} array The array to inspect.
  5442. * @param {...Array} [values] The values to exclude.
  5443. * @param {Function} [comparator] The comparator invoked per element.
  5444. * @returns {Array} Returns the new array of filtered values.
  5445. * @example
  5446. *
  5447. * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
  5448. *
  5449. * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
  5450. * // => [{ 'x': 2, 'y': 1 }]
  5451. */
  5452. var differenceWith = rest(function(array, values) {
  5453. var comparator = last(values);
  5454. if (isArrayLikeObject(comparator)) {
  5455. comparator = undefined;
  5456. }
  5457. return isArrayLikeObject(array)
  5458. ? baseDifference(array, baseFlatten(values, 1, true), undefined, comparator)
  5459. : [];
  5460. });
  5461. /**
  5462. * Creates a slice of `array` with `n` elements dropped from the beginning.
  5463. *
  5464. * @static
  5465. * @memberOf _
  5466. * @category Array
  5467. * @param {Array} array The array to query.
  5468. * @param {number} [n=1] The number of elements to drop.
  5469. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  5470. * @returns {Array} Returns the slice of `array`.
  5471. * @example
  5472. *
  5473. * _.drop([1, 2, 3]);
  5474. * // => [2, 3]
  5475. *
  5476. * _.drop([1, 2, 3], 2);
  5477. * // => [3]
  5478. *
  5479. * _.drop([1, 2, 3], 5);
  5480. * // => []
  5481. *
  5482. * _.drop([1, 2, 3], 0);
  5483. * // => [1, 2, 3]
  5484. */
  5485. function drop(array, n, guard) {
  5486. var length = array ? array.length : 0;
  5487. if (!length) {
  5488. return [];
  5489. }
  5490. n = (guard || n === undefined) ? 1 : toInteger(n);
  5491. return baseSlice(array, n < 0 ? 0 : n, length);
  5492. }
  5493. /**
  5494. * Creates a slice of `array` with `n` elements dropped from the end.
  5495. *
  5496. * @static
  5497. * @memberOf _
  5498. * @category Array
  5499. * @param {Array} array The array to query.
  5500. * @param {number} [n=1] The number of elements to drop.
  5501. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  5502. * @returns {Array} Returns the slice of `array`.
  5503. * @example
  5504. *
  5505. * _.dropRight([1, 2, 3]);
  5506. * // => [1, 2]
  5507. *
  5508. * _.dropRight([1, 2, 3], 2);
  5509. * // => [1]
  5510. *
  5511. * _.dropRight([1, 2, 3], 5);
  5512. * // => []
  5513. *
  5514. * _.dropRight([1, 2, 3], 0);
  5515. * // => [1, 2, 3]
  5516. */
  5517. function dropRight(array, n, guard) {
  5518. var length = array ? array.length : 0;
  5519. if (!length) {
  5520. return [];
  5521. }
  5522. n = (guard || n === undefined) ? 1 : toInteger(n);
  5523. n = length - n;
  5524. return baseSlice(array, 0, n < 0 ? 0 : n);
  5525. }
  5526. /**
  5527. * Creates a slice of `array` excluding elements dropped from the end.
  5528. * Elements are dropped until `predicate` returns falsey. The predicate is
  5529. * invoked with three arguments: (value, index, array).
  5530. *
  5531. * @static
  5532. * @memberOf _
  5533. * @category Array
  5534. * @param {Array} array The array to query.
  5535. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  5536. * @returns {Array} Returns the slice of `array`.
  5537. * @example
  5538. *
  5539. * var users = [
  5540. * { 'user': 'barney', 'active': true },
  5541. * { 'user': 'fred', 'active': false },
  5542. * { 'user': 'pebbles', 'active': false }
  5543. * ];
  5544. *
  5545. * _.dropRightWhile(users, function(o) { return !o.active; });
  5546. * // => objects for ['barney']
  5547. *
  5548. * // The `_.matches` iteratee shorthand.
  5549. * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
  5550. * // => objects for ['barney', 'fred']
  5551. *
  5552. * // The `_.matchesProperty` iteratee shorthand.
  5553. * _.dropRightWhile(users, ['active', false]);
  5554. * // => objects for ['barney']
  5555. *
  5556. * // The `_.property` iteratee shorthand.
  5557. * _.dropRightWhile(users, 'active');
  5558. * // => objects for ['barney', 'fred', 'pebbles']
  5559. */
  5560. function dropRightWhile(array, predicate) {
  5561. return (array && array.length)
  5562. ? baseWhile(array, getIteratee(predicate, 3), true, true)
  5563. : [];
  5564. }
  5565. /**
  5566. * Creates a slice of `array` excluding elements dropped from the beginning.
  5567. * Elements are dropped until `predicate` returns falsey. The predicate is
  5568. * invoked with three arguments: (value, index, array).
  5569. *
  5570. * @static
  5571. * @memberOf _
  5572. * @category Array
  5573. * @param {Array} array The array to query.
  5574. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  5575. * @returns {Array} Returns the slice of `array`.
  5576. * @example
  5577. *
  5578. * var users = [
  5579. * { 'user': 'barney', 'active': false },
  5580. * { 'user': 'fred', 'active': false },
  5581. * { 'user': 'pebbles', 'active': true }
  5582. * ];
  5583. *
  5584. * _.dropWhile(users, function(o) { return !o.active; });
  5585. * // => objects for ['pebbles']
  5586. *
  5587. * // The `_.matches` iteratee shorthand.
  5588. * _.dropWhile(users, { 'user': 'barney', 'active': false });
  5589. * // => objects for ['fred', 'pebbles']
  5590. *
  5591. * // The `_.matchesProperty` iteratee shorthand.
  5592. * _.dropWhile(users, ['active', false]);
  5593. * // => objects for ['pebbles']
  5594. *
  5595. * // The `_.property` iteratee shorthand.
  5596. * _.dropWhile(users, 'active');
  5597. * // => objects for ['barney', 'fred', 'pebbles']
  5598. */
  5599. function dropWhile(array, predicate) {
  5600. return (array && array.length)
  5601. ? baseWhile(array, getIteratee(predicate, 3), true)
  5602. : [];
  5603. }
  5604. /**
  5605. * Fills elements of `array` with `value` from `start` up to, but not
  5606. * including, `end`.
  5607. *
  5608. * **Note:** This method mutates `array`.
  5609. *
  5610. * @static
  5611. * @memberOf _
  5612. * @category Array
  5613. * @param {Array} array The array to fill.
  5614. * @param {*} value The value to fill `array` with.
  5615. * @param {number} [start=0] The start position.
  5616. * @param {number} [end=array.length] The end position.
  5617. * @returns {Array} Returns `array`.
  5618. * @example
  5619. *
  5620. * var array = [1, 2, 3];
  5621. *
  5622. * _.fill(array, 'a');
  5623. * console.log(array);
  5624. * // => ['a', 'a', 'a']
  5625. *
  5626. * _.fill(Array(3), 2);
  5627. * // => [2, 2, 2]
  5628. *
  5629. * _.fill([4, 6, 8, 10], '*', 1, 3);
  5630. * // => [4, '*', '*', 10]
  5631. */
  5632. function fill(array, value, start, end) {
  5633. var length = array ? array.length : 0;
  5634. if (!length) {
  5635. return [];
  5636. }
  5637. if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
  5638. start = 0;
  5639. end = length;
  5640. }
  5641. return baseFill(array, value, start, end);
  5642. }
  5643. /**
  5644. * This method is like `_.find` except that it returns the index of the first
  5645. * element `predicate` returns truthy for instead of the element itself.
  5646. *
  5647. * @static
  5648. * @memberOf _
  5649. * @category Array
  5650. * @param {Array} array The array to search.
  5651. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  5652. * @returns {number} Returns the index of the found element, else `-1`.
  5653. * @example
  5654. *
  5655. * var users = [
  5656. * { 'user': 'barney', 'active': false },
  5657. * { 'user': 'fred', 'active': false },
  5658. * { 'user': 'pebbles', 'active': true }
  5659. * ];
  5660. *
  5661. * _.findIndex(users, function(o) { return o.user == 'barney'; });
  5662. * // => 0
  5663. *
  5664. * // The `_.matches` iteratee shorthand.
  5665. * _.findIndex(users, { 'user': 'fred', 'active': false });
  5666. * // => 1
  5667. *
  5668. * // The `_.matchesProperty` iteratee shorthand.
  5669. * _.findIndex(users, ['active', false]);
  5670. * // => 0
  5671. *
  5672. * // The `_.property` iteratee shorthand.
  5673. * _.findIndex(users, 'active');
  5674. * // => 2
  5675. */
  5676. function findIndex(array, predicate) {
  5677. return (array && array.length)
  5678. ? baseFindIndex(array, getIteratee(predicate, 3))
  5679. : -1;
  5680. }
  5681. /**
  5682. * This method is like `_.findIndex` except that it iterates over elements
  5683. * of `collection` from right to left.
  5684. *
  5685. * @static
  5686. * @memberOf _
  5687. * @category Array
  5688. * @param {Array} array The array to search.
  5689. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  5690. * @returns {number} Returns the index of the found element, else `-1`.
  5691. * @example
  5692. *
  5693. * var users = [
  5694. * { 'user': 'barney', 'active': true },
  5695. * { 'user': 'fred', 'active': false },
  5696. * { 'user': 'pebbles', 'active': false }
  5697. * ];
  5698. *
  5699. * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
  5700. * // => 2
  5701. *
  5702. * // The `_.matches` iteratee shorthand.
  5703. * _.findLastIndex(users, { 'user': 'barney', 'active': true });
  5704. * // => 0
  5705. *
  5706. * // The `_.matchesProperty` iteratee shorthand.
  5707. * _.findLastIndex(users, ['active', false]);
  5708. * // => 2
  5709. *
  5710. * // The `_.property` iteratee shorthand.
  5711. * _.findLastIndex(users, 'active');
  5712. * // => 0
  5713. */
  5714. function findLastIndex(array, predicate) {
  5715. return (array && array.length)
  5716. ? baseFindIndex(array, getIteratee(predicate, 3), true)
  5717. : -1;
  5718. }
  5719. /**
  5720. * Flattens `array` a single level deep.
  5721. *
  5722. * @static
  5723. * @memberOf _
  5724. * @category Array
  5725. * @param {Array} array The array to flatten.
  5726. * @returns {Array} Returns the new flattened array.
  5727. * @example
  5728. *
  5729. * _.flatten([1, [2, [3, [4]], 5]]);
  5730. * // => [1, 2, [3, [4]], 5]
  5731. */
  5732. function flatten(array) {
  5733. var length = array ? array.length : 0;
  5734. return length ? baseFlatten(array, 1) : [];
  5735. }
  5736. /**
  5737. * Recursively flattens `array`.
  5738. *
  5739. * @static
  5740. * @memberOf _
  5741. * @category Array
  5742. * @param {Array} array The array to flatten.
  5743. * @returns {Array} Returns the new flattened array.
  5744. * @example
  5745. *
  5746. * _.flattenDeep([1, [2, [3, [4]], 5]]);
  5747. * // => [1, 2, 3, 4, 5]
  5748. */
  5749. function flattenDeep(array) {
  5750. var length = array ? array.length : 0;
  5751. return length ? baseFlatten(array, INFINITY) : [];
  5752. }
  5753. /**
  5754. * Recursively flatten `array` up to `depth` times.
  5755. *
  5756. * @static
  5757. * @memberOf _
  5758. * @category Array
  5759. * @param {Array} array The array to flatten.
  5760. * @param {number} [depth=1] The maximum recursion depth.
  5761. * @returns {Array} Returns the new flattened array.
  5762. * @example
  5763. *
  5764. * var array = [1, [2, [3, [4]], 5]];
  5765. *
  5766. * _.flattenDepth(array, 1);
  5767. * // => [1, 2, [3, [4]], 5]
  5768. *
  5769. * _.flattenDepth(array, 2);
  5770. * // => [1, 2, 3, [4], 5]
  5771. */
  5772. function flattenDepth(array, depth) {
  5773. var length = array ? array.length : 0;
  5774. if (!length) {
  5775. return [];
  5776. }
  5777. depth = depth === undefined ? 1 : toInteger(depth);
  5778. return baseFlatten(array, depth);
  5779. }
  5780. /**
  5781. * The inverse of `_.toPairs`; this method returns an object composed
  5782. * from key-value `pairs`.
  5783. *
  5784. * @static
  5785. * @memberOf _
  5786. * @category Array
  5787. * @param {Array} pairs The key-value pairs.
  5788. * @returns {Object} Returns the new object.
  5789. * @example
  5790. *
  5791. * _.fromPairs([['fred', 30], ['barney', 40]]);
  5792. * // => { 'fred': 30, 'barney': 40 }
  5793. */
  5794. function fromPairs(pairs) {
  5795. var index = -1,
  5796. length = pairs ? pairs.length : 0,
  5797. result = {};
  5798. while (++index < length) {
  5799. var pair = pairs[index];
  5800. result[pair[0]] = pair[1];
  5801. }
  5802. return result;
  5803. }
  5804. /**
  5805. * Gets the first element of `array`.
  5806. *
  5807. * @static
  5808. * @memberOf _
  5809. * @alias first
  5810. * @category Array
  5811. * @param {Array} array The array to query.
  5812. * @returns {*} Returns the first element of `array`.
  5813. * @example
  5814. *
  5815. * _.head([1, 2, 3]);
  5816. * // => 1
  5817. *
  5818. * _.head([]);
  5819. * // => undefined
  5820. */
  5821. function head(array) {
  5822. return array ? array[0] : undefined;
  5823. }
  5824. /**
  5825. * Gets the index at which the first occurrence of `value` is found in `array`
  5826. * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  5827. * for equality comparisons. If `fromIndex` is negative, it's used as the offset
  5828. * from the end of `array`.
  5829. *
  5830. * @static
  5831. * @memberOf _
  5832. * @category Array
  5833. * @param {Array} array The array to search.
  5834. * @param {*} value The value to search for.
  5835. * @param {number} [fromIndex=0] The index to search from.
  5836. * @returns {number} Returns the index of the matched value, else `-1`.
  5837. * @example
  5838. *
  5839. * _.indexOf([1, 2, 1, 2], 2);
  5840. * // => 1
  5841. *
  5842. * // Search from the `fromIndex`.
  5843. * _.indexOf([1, 2, 1, 2], 2, 2);
  5844. * // => 3
  5845. */
  5846. function indexOf(array, value, fromIndex) {
  5847. var length = array ? array.length : 0;
  5848. if (!length) {
  5849. return -1;
  5850. }
  5851. fromIndex = toInteger(fromIndex);
  5852. if (fromIndex < 0) {
  5853. fromIndex = nativeMax(length + fromIndex, 0);
  5854. }
  5855. return baseIndexOf(array, value, fromIndex);
  5856. }
  5857. /**
  5858. * Gets all but the last element of `array`.
  5859. *
  5860. * @static
  5861. * @memberOf _
  5862. * @category Array
  5863. * @param {Array} array The array to query.
  5864. * @returns {Array} Returns the slice of `array`.
  5865. * @example
  5866. *
  5867. * _.initial([1, 2, 3]);
  5868. * // => [1, 2]
  5869. */
  5870. function initial(array) {
  5871. return dropRight(array, 1);
  5872. }
  5873. /**
  5874. * Creates an array of unique values that are included in all given arrays
  5875. * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  5876. * for equality comparisons.
  5877. *
  5878. * @static
  5879. * @memberOf _
  5880. * @category Array
  5881. * @param {...Array} [arrays] The arrays to inspect.
  5882. * @returns {Array} Returns the new array of shared values.
  5883. * @example
  5884. *
  5885. * _.intersection([2, 1], [4, 2], [1, 2]);
  5886. * // => [2]
  5887. */
  5888. var intersection = rest(function(arrays) {
  5889. var mapped = arrayMap(arrays, baseCastArrayLikeObject);
  5890. return (mapped.length && mapped[0] === arrays[0])
  5891. ? baseIntersection(mapped)
  5892. : [];
  5893. });
  5894. /**
  5895. * This method is like `_.intersection` except that it accepts `iteratee`
  5896. * which is invoked for each element of each `arrays` to generate the criterion
  5897. * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
  5898. *
  5899. * @static
  5900. * @memberOf _
  5901. * @category Array
  5902. * @param {...Array} [arrays] The arrays to inspect.
  5903. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  5904. * @returns {Array} Returns the new array of shared values.
  5905. * @example
  5906. *
  5907. * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
  5908. * // => [2.1]
  5909. *
  5910. * // The `_.property` iteratee shorthand.
  5911. * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
  5912. * // => [{ 'x': 1 }]
  5913. */
  5914. var intersectionBy = rest(function(arrays) {
  5915. var iteratee = last(arrays),
  5916. mapped = arrayMap(arrays, baseCastArrayLikeObject);
  5917. if (iteratee === last(mapped)) {
  5918. iteratee = undefined;
  5919. } else {
  5920. mapped.pop();
  5921. }
  5922. return (mapped.length && mapped[0] === arrays[0])
  5923. ? baseIntersection(mapped, getIteratee(iteratee))
  5924. : [];
  5925. });
  5926. /**
  5927. * This method is like `_.intersection` except that it accepts `comparator`
  5928. * which is invoked to compare elements of `arrays`. The comparator is invoked
  5929. * with two arguments: (arrVal, othVal).
  5930. *
  5931. * @static
  5932. * @memberOf _
  5933. * @category Array
  5934. * @param {...Array} [arrays] The arrays to inspect.
  5935. * @param {Function} [comparator] The comparator invoked per element.
  5936. * @returns {Array} Returns the new array of shared values.
  5937. * @example
  5938. *
  5939. * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
  5940. * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
  5941. *
  5942. * _.intersectionWith(objects, others, _.isEqual);
  5943. * // => [{ 'x': 1, 'y': 2 }]
  5944. */
  5945. var intersectionWith = rest(function(arrays) {
  5946. var comparator = last(arrays),
  5947. mapped = arrayMap(arrays, baseCastArrayLikeObject);
  5948. if (comparator === last(mapped)) {
  5949. comparator = undefined;
  5950. } else {
  5951. mapped.pop();
  5952. }
  5953. return (mapped.length && mapped[0] === arrays[0])
  5954. ? baseIntersection(mapped, undefined, comparator)
  5955. : [];
  5956. });
  5957. /**
  5958. * Converts all elements in `array` into a string separated by `separator`.
  5959. *
  5960. * @static
  5961. * @memberOf _
  5962. * @category Array
  5963. * @param {Array} array The array to convert.
  5964. * @param {string} [separator=','] The element separator.
  5965. * @returns {string} Returns the joined string.
  5966. * @example
  5967. *
  5968. * _.join(['a', 'b', 'c'], '~');
  5969. * // => 'a~b~c'
  5970. */
  5971. function join(array, separator) {
  5972. return array ? nativeJoin.call(array, separator) : '';
  5973. }
  5974. /**
  5975. * Gets the last element of `array`.
  5976. *
  5977. * @static
  5978. * @memberOf _
  5979. * @category Array
  5980. * @param {Array} array The array to query.
  5981. * @returns {*} Returns the last element of `array`.
  5982. * @example
  5983. *
  5984. * _.last([1, 2, 3]);
  5985. * // => 3
  5986. */
  5987. function last(array) {
  5988. var length = array ? array.length : 0;
  5989. return length ? array[length - 1] : undefined;
  5990. }
  5991. /**
  5992. * This method is like `_.indexOf` except that it iterates over elements of
  5993. * `array` from right to left.
  5994. *
  5995. * @static
  5996. * @memberOf _
  5997. * @category Array
  5998. * @param {Array} array The array to search.
  5999. * @param {*} value The value to search for.
  6000. * @param {number} [fromIndex=array.length-1] The index to search from.
  6001. * @returns {number} Returns the index of the matched value, else `-1`.
  6002. * @example
  6003. *
  6004. * _.lastIndexOf([1, 2, 1, 2], 2);
  6005. * // => 3
  6006. *
  6007. * // Search from the `fromIndex`.
  6008. * _.lastIndexOf([1, 2, 1, 2], 2, 2);
  6009. * // => 1
  6010. */
  6011. function lastIndexOf(array, value, fromIndex) {
  6012. var length = array ? array.length : 0;
  6013. if (!length) {
  6014. return -1;
  6015. }
  6016. var index = length;
  6017. if (fromIndex !== undefined) {
  6018. index = toInteger(fromIndex);
  6019. index = (index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1)) + 1;
  6020. }
  6021. if (value !== value) {
  6022. return indexOfNaN(array, index, true);
  6023. }
  6024. while (index--) {
  6025. if (array[index] === value) {
  6026. return index;
  6027. }
  6028. }
  6029. return -1;
  6030. }
  6031. /**
  6032. * Removes all given values from `array` using
  6033. * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  6034. * for equality comparisons.
  6035. *
  6036. * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
  6037. * to remove elements from an array by predicate.
  6038. *
  6039. * @static
  6040. * @memberOf _
  6041. * @category Array
  6042. * @param {Array} array The array to modify.
  6043. * @param {...*} [values] The values to remove.
  6044. * @returns {Array} Returns `array`.
  6045. * @example
  6046. *
  6047. * var array = [1, 2, 3, 1, 2, 3];
  6048. *
  6049. * _.pull(array, 2, 3);
  6050. * console.log(array);
  6051. * // => [1, 1]
  6052. */
  6053. var pull = rest(pullAll);
  6054. /**
  6055. * This method is like `_.pull` except that it accepts an array of values to remove.
  6056. *
  6057. * **Note:** Unlike `_.difference`, this method mutates `array`.
  6058. *
  6059. * @static
  6060. * @memberOf _
  6061. * @category Array
  6062. * @param {Array} array The array to modify.
  6063. * @param {Array} values The values to remove.
  6064. * @returns {Array} Returns `array`.
  6065. * @example
  6066. *
  6067. * var array = [1, 2, 3, 1, 2, 3];
  6068. *
  6069. * _.pullAll(array, [2, 3]);
  6070. * console.log(array);
  6071. * // => [1, 1]
  6072. */
  6073. function pullAll(array, values) {
  6074. return (array && array.length && values && values.length)
  6075. ? basePullAll(array, values)
  6076. : array;
  6077. }
  6078. /**
  6079. * This method is like `_.pullAll` except that it accepts `iteratee` which is
  6080. * invoked for each element of `array` and `values` to generate the criterion
  6081. * by which uniqueness is computed. The iteratee is invoked with one argument: (value).
  6082. *
  6083. * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
  6084. *
  6085. * @static
  6086. * @memberOf _
  6087. * @category Array
  6088. * @param {Array} array The array to modify.
  6089. * @param {Array} values The values to remove.
  6090. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6091. * @returns {Array} Returns `array`.
  6092. * @example
  6093. *
  6094. * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
  6095. *
  6096. * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
  6097. * console.log(array);
  6098. * // => [{ 'x': 2 }]
  6099. */
  6100. function pullAllBy(array, values, iteratee) {
  6101. return (array && array.length && values && values.length)
  6102. ? basePullAllBy(array, values, getIteratee(iteratee))
  6103. : array;
  6104. }
  6105. /**
  6106. * Removes elements from `array` corresponding to `indexes` and returns an
  6107. * array of removed elements.
  6108. *
  6109. * **Note:** Unlike `_.at`, this method mutates `array`.
  6110. *
  6111. * @static
  6112. * @memberOf _
  6113. * @category Array
  6114. * @param {Array} array The array to modify.
  6115. * @param {...(number|number[])} [indexes] The indexes of elements to remove,
  6116. * specified individually or in arrays.
  6117. * @returns {Array} Returns the new array of removed elements.
  6118. * @example
  6119. *
  6120. * var array = [5, 10, 15, 20];
  6121. * var evens = _.pullAt(array, 1, 3);
  6122. *
  6123. * console.log(array);
  6124. * // => [5, 15]
  6125. *
  6126. * console.log(evens);
  6127. * // => [10, 20]
  6128. */
  6129. var pullAt = rest(function(array, indexes) {
  6130. indexes = arrayMap(baseFlatten(indexes, 1), String);
  6131. var result = baseAt(array, indexes);
  6132. basePullAt(array, indexes.sort(compareAscending));
  6133. return result;
  6134. });
  6135. /**
  6136. * Removes all elements from `array` that `predicate` returns truthy for
  6137. * and returns an array of the removed elements. The predicate is invoked
  6138. * with three arguments: (value, index, array).
  6139. *
  6140. * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
  6141. * to pull elements from an array by value.
  6142. *
  6143. * @static
  6144. * @memberOf _
  6145. * @category Array
  6146. * @param {Array} array The array to modify.
  6147. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  6148. * @returns {Array} Returns the new array of removed elements.
  6149. * @example
  6150. *
  6151. * var array = [1, 2, 3, 4];
  6152. * var evens = _.remove(array, function(n) {
  6153. * return n % 2 == 0;
  6154. * });
  6155. *
  6156. * console.log(array);
  6157. * // => [1, 3]
  6158. *
  6159. * console.log(evens);
  6160. * // => [2, 4]
  6161. */
  6162. function remove(array, predicate) {
  6163. var result = [];
  6164. if (!(array && array.length)) {
  6165. return result;
  6166. }
  6167. var index = -1,
  6168. indexes = [],
  6169. length = array.length;
  6170. predicate = getIteratee(predicate, 3);
  6171. while (++index < length) {
  6172. var value = array[index];
  6173. if (predicate(value, index, array)) {
  6174. result.push(value);
  6175. indexes.push(index);
  6176. }
  6177. }
  6178. basePullAt(array, indexes);
  6179. return result;
  6180. }
  6181. /**
  6182. * Reverses `array` so that the first element becomes the last, the second
  6183. * element becomes the second to last, and so on.
  6184. *
  6185. * **Note:** This method mutates `array` and is based on
  6186. * [`Array#reverse`](https://mdn.io/Array/reverse).
  6187. *
  6188. * @static
  6189. * @memberOf _
  6190. * @category Array
  6191. * @returns {Array} Returns `array`.
  6192. * @example
  6193. *
  6194. * var array = [1, 2, 3];
  6195. *
  6196. * _.reverse(array);
  6197. * // => [3, 2, 1]
  6198. *
  6199. * console.log(array);
  6200. * // => [3, 2, 1]
  6201. */
  6202. function reverse(array) {
  6203. return array ? nativeReverse.call(array) : array;
  6204. }
  6205. /**
  6206. * Creates a slice of `array` from `start` up to, but not including, `end`.
  6207. *
  6208. * **Note:** This method is used instead of [`Array#slice`](https://mdn.io/Array/slice)
  6209. * to ensure dense arrays are returned.
  6210. *
  6211. * @static
  6212. * @memberOf _
  6213. * @category Array
  6214. * @param {Array} array The array to slice.
  6215. * @param {number} [start=0] The start position.
  6216. * @param {number} [end=array.length] The end position.
  6217. * @returns {Array} Returns the slice of `array`.
  6218. */
  6219. function slice(array, start, end) {
  6220. var length = array ? array.length : 0;
  6221. if (!length) {
  6222. return [];
  6223. }
  6224. if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
  6225. start = 0;
  6226. end = length;
  6227. }
  6228. else {
  6229. start = start == null ? 0 : toInteger(start);
  6230. end = end === undefined ? length : toInteger(end);
  6231. }
  6232. return baseSlice(array, start, end);
  6233. }
  6234. /**
  6235. * Uses a binary search to determine the lowest index at which `value` should
  6236. * be inserted into `array` in order to maintain its sort order.
  6237. *
  6238. * @static
  6239. * @memberOf _
  6240. * @category Array
  6241. * @param {Array} array The sorted array to inspect.
  6242. * @param {*} value The value to evaluate.
  6243. * @returns {number} Returns the index at which `value` should be inserted into `array`.
  6244. * @example
  6245. *
  6246. * _.sortedIndex([30, 50], 40);
  6247. * // => 1
  6248. *
  6249. * _.sortedIndex([4, 5], 4);
  6250. * // => 0
  6251. */
  6252. function sortedIndex(array, value) {
  6253. return baseSortedIndex(array, value);
  6254. }
  6255. /**
  6256. * This method is like `_.sortedIndex` except that it accepts `iteratee`
  6257. * which is invoked for `value` and each element of `array` to compute their
  6258. * sort ranking. The iteratee is invoked with one argument: (value).
  6259. *
  6260. * @static
  6261. * @memberOf _
  6262. * @category Array
  6263. * @param {Array} array The sorted array to inspect.
  6264. * @param {*} value The value to evaluate.
  6265. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6266. * @returns {number} Returns the index at which `value` should be inserted into `array`.
  6267. * @example
  6268. *
  6269. * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 };
  6270. *
  6271. * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict));
  6272. * // => 1
  6273. *
  6274. * // The `_.property` iteratee shorthand.
  6275. * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
  6276. * // => 0
  6277. */
  6278. function sortedIndexBy(array, value, iteratee) {
  6279. return baseSortedIndexBy(array, value, getIteratee(iteratee));
  6280. }
  6281. /**
  6282. * This method is like `_.indexOf` except that it performs a binary
  6283. * search on a sorted `array`.
  6284. *
  6285. * @static
  6286. * @memberOf _
  6287. * @category Array
  6288. * @param {Array} array The array to search.
  6289. * @param {*} value The value to search for.
  6290. * @returns {number} Returns the index of the matched value, else `-1`.
  6291. * @example
  6292. *
  6293. * _.sortedIndexOf([1, 1, 2, 2], 2);
  6294. * // => 2
  6295. */
  6296. function sortedIndexOf(array, value) {
  6297. var length = array ? array.length : 0;
  6298. if (length) {
  6299. var index = baseSortedIndex(array, value);
  6300. if (index < length && eq(array[index], value)) {
  6301. return index;
  6302. }
  6303. }
  6304. return -1;
  6305. }
  6306. /**
  6307. * This method is like `_.sortedIndex` except that it returns the highest
  6308. * index at which `value` should be inserted into `array` in order to
  6309. * maintain its sort order.
  6310. *
  6311. * @static
  6312. * @memberOf _
  6313. * @category Array
  6314. * @param {Array} array The sorted array to inspect.
  6315. * @param {*} value The value to evaluate.
  6316. * @returns {number} Returns the index at which `value` should be inserted into `array`.
  6317. * @example
  6318. *
  6319. * _.sortedLastIndex([4, 5], 4);
  6320. * // => 1
  6321. */
  6322. function sortedLastIndex(array, value) {
  6323. return baseSortedIndex(array, value, true);
  6324. }
  6325. /**
  6326. * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
  6327. * which is invoked for `value` and each element of `array` to compute their
  6328. * sort ranking. The iteratee is invoked with one argument: (value).
  6329. *
  6330. * @static
  6331. * @memberOf _
  6332. * @category Array
  6333. * @param {Array} array The sorted array to inspect.
  6334. * @param {*} value The value to evaluate.
  6335. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6336. * @returns {number} Returns the index at which `value` should be inserted into `array`.
  6337. * @example
  6338. *
  6339. * // The `_.property` iteratee shorthand.
  6340. * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x');
  6341. * // => 1
  6342. */
  6343. function sortedLastIndexBy(array, value, iteratee) {
  6344. return baseSortedIndexBy(array, value, getIteratee(iteratee), true);
  6345. }
  6346. /**
  6347. * This method is like `_.lastIndexOf` except that it performs a binary
  6348. * search on a sorted `array`.
  6349. *
  6350. * @static
  6351. * @memberOf _
  6352. * @category Array
  6353. * @param {Array} array The array to search.
  6354. * @param {*} value The value to search for.
  6355. * @returns {number} Returns the index of the matched value, else `-1`.
  6356. * @example
  6357. *
  6358. * _.sortedLastIndexOf([1, 1, 2, 2], 2);
  6359. * // => 3
  6360. */
  6361. function sortedLastIndexOf(array, value) {
  6362. var length = array ? array.length : 0;
  6363. if (length) {
  6364. var index = baseSortedIndex(array, value, true) - 1;
  6365. if (eq(array[index], value)) {
  6366. return index;
  6367. }
  6368. }
  6369. return -1;
  6370. }
  6371. /**
  6372. * This method is like `_.uniq` except that it's designed and optimized
  6373. * for sorted arrays.
  6374. *
  6375. * @static
  6376. * @memberOf _
  6377. * @category Array
  6378. * @param {Array} array The array to inspect.
  6379. * @returns {Array} Returns the new duplicate free array.
  6380. * @example
  6381. *
  6382. * _.sortedUniq([1, 1, 2]);
  6383. * // => [1, 2]
  6384. */
  6385. function sortedUniq(array) {
  6386. return (array && array.length)
  6387. ? baseSortedUniq(array)
  6388. : [];
  6389. }
  6390. /**
  6391. * This method is like `_.uniqBy` except that it's designed and optimized
  6392. * for sorted arrays.
  6393. *
  6394. * @static
  6395. * @memberOf _
  6396. * @category Array
  6397. * @param {Array} array The array to inspect.
  6398. * @param {Function} [iteratee] The iteratee invoked per element.
  6399. * @returns {Array} Returns the new duplicate free array.
  6400. * @example
  6401. *
  6402. * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
  6403. * // => [1.1, 2.3]
  6404. */
  6405. function sortedUniqBy(array, iteratee) {
  6406. return (array && array.length)
  6407. ? baseSortedUniqBy(array, getIteratee(iteratee))
  6408. : [];
  6409. }
  6410. /**
  6411. * Gets all but the first element of `array`.
  6412. *
  6413. * @static
  6414. * @memberOf _
  6415. * @category Array
  6416. * @param {Array} array The array to query.
  6417. * @returns {Array} Returns the slice of `array`.
  6418. * @example
  6419. *
  6420. * _.tail([1, 2, 3]);
  6421. * // => [2, 3]
  6422. */
  6423. function tail(array) {
  6424. return drop(array, 1);
  6425. }
  6426. /**
  6427. * Creates a slice of `array` with `n` elements taken from the beginning.
  6428. *
  6429. * @static
  6430. * @memberOf _
  6431. * @category Array
  6432. * @param {Array} array The array to query.
  6433. * @param {number} [n=1] The number of elements to take.
  6434. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  6435. * @returns {Array} Returns the slice of `array`.
  6436. * @example
  6437. *
  6438. * _.take([1, 2, 3]);
  6439. * // => [1]
  6440. *
  6441. * _.take([1, 2, 3], 2);
  6442. * // => [1, 2]
  6443. *
  6444. * _.take([1, 2, 3], 5);
  6445. * // => [1, 2, 3]
  6446. *
  6447. * _.take([1, 2, 3], 0);
  6448. * // => []
  6449. */
  6450. function take(array, n, guard) {
  6451. if (!(array && array.length)) {
  6452. return [];
  6453. }
  6454. n = (guard || n === undefined) ? 1 : toInteger(n);
  6455. return baseSlice(array, 0, n < 0 ? 0 : n);
  6456. }
  6457. /**
  6458. * Creates a slice of `array` with `n` elements taken from the end.
  6459. *
  6460. * @static
  6461. * @memberOf _
  6462. * @category Array
  6463. * @param {Array} array The array to query.
  6464. * @param {number} [n=1] The number of elements to take.
  6465. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  6466. * @returns {Array} Returns the slice of `array`.
  6467. * @example
  6468. *
  6469. * _.takeRight([1, 2, 3]);
  6470. * // => [3]
  6471. *
  6472. * _.takeRight([1, 2, 3], 2);
  6473. * // => [2, 3]
  6474. *
  6475. * _.takeRight([1, 2, 3], 5);
  6476. * // => [1, 2, 3]
  6477. *
  6478. * _.takeRight([1, 2, 3], 0);
  6479. * // => []
  6480. */
  6481. function takeRight(array, n, guard) {
  6482. var length = array ? array.length : 0;
  6483. if (!length) {
  6484. return [];
  6485. }
  6486. n = (guard || n === undefined) ? 1 : toInteger(n);
  6487. n = length - n;
  6488. return baseSlice(array, n < 0 ? 0 : n, length);
  6489. }
  6490. /**
  6491. * Creates a slice of `array` with elements taken from the end. Elements are
  6492. * taken until `predicate` returns falsey. The predicate is invoked with three
  6493. * arguments: (value, index, array).
  6494. *
  6495. * @static
  6496. * @memberOf _
  6497. * @category Array
  6498. * @param {Array} array The array to query.
  6499. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  6500. * @returns {Array} Returns the slice of `array`.
  6501. * @example
  6502. *
  6503. * var users = [
  6504. * { 'user': 'barney', 'active': true },
  6505. * { 'user': 'fred', 'active': false },
  6506. * { 'user': 'pebbles', 'active': false }
  6507. * ];
  6508. *
  6509. * _.takeRightWhile(users, function(o) { return !o.active; });
  6510. * // => objects for ['fred', 'pebbles']
  6511. *
  6512. * // The `_.matches` iteratee shorthand.
  6513. * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
  6514. * // => objects for ['pebbles']
  6515. *
  6516. * // The `_.matchesProperty` iteratee shorthand.
  6517. * _.takeRightWhile(users, ['active', false]);
  6518. * // => objects for ['fred', 'pebbles']
  6519. *
  6520. * // The `_.property` iteratee shorthand.
  6521. * _.takeRightWhile(users, 'active');
  6522. * // => []
  6523. */
  6524. function takeRightWhile(array, predicate) {
  6525. return (array && array.length)
  6526. ? baseWhile(array, getIteratee(predicate, 3), false, true)
  6527. : [];
  6528. }
  6529. /**
  6530. * Creates a slice of `array` with elements taken from the beginning. Elements
  6531. * are taken until `predicate` returns falsey. The predicate is invoked with
  6532. * three arguments: (value, index, array).
  6533. *
  6534. * @static
  6535. * @memberOf _
  6536. * @category Array
  6537. * @param {Array} array The array to query.
  6538. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  6539. * @returns {Array} Returns the slice of `array`.
  6540. * @example
  6541. *
  6542. * var users = [
  6543. * { 'user': 'barney', 'active': false },
  6544. * { 'user': 'fred', 'active': false},
  6545. * { 'user': 'pebbles', 'active': true }
  6546. * ];
  6547. *
  6548. * _.takeWhile(users, function(o) { return !o.active; });
  6549. * // => objects for ['barney', 'fred']
  6550. *
  6551. * // The `_.matches` iteratee shorthand.
  6552. * _.takeWhile(users, { 'user': 'barney', 'active': false });
  6553. * // => objects for ['barney']
  6554. *
  6555. * // The `_.matchesProperty` iteratee shorthand.
  6556. * _.takeWhile(users, ['active', false]);
  6557. * // => objects for ['barney', 'fred']
  6558. *
  6559. * // The `_.property` iteratee shorthand.
  6560. * _.takeWhile(users, 'active');
  6561. * // => []
  6562. */
  6563. function takeWhile(array, predicate) {
  6564. return (array && array.length)
  6565. ? baseWhile(array, getIteratee(predicate, 3))
  6566. : [];
  6567. }
  6568. /**
  6569. * Creates an array of unique values, in order, from all given arrays using
  6570. * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  6571. * for equality comparisons.
  6572. *
  6573. * @static
  6574. * @memberOf _
  6575. * @category Array
  6576. * @param {...Array} [arrays] The arrays to inspect.
  6577. * @returns {Array} Returns the new array of combined values.
  6578. * @example
  6579. *
  6580. * _.union([2, 1], [4, 2], [1, 2]);
  6581. * // => [2, 1, 4]
  6582. */
  6583. var union = rest(function(arrays) {
  6584. return baseUniq(baseFlatten(arrays, 1, true));
  6585. });
  6586. /**
  6587. * This method is like `_.union` except that it accepts `iteratee` which is
  6588. * invoked for each element of each `arrays` to generate the criterion by which
  6589. * uniqueness is computed. The iteratee is invoked with one argument: (value).
  6590. *
  6591. * @static
  6592. * @memberOf _
  6593. * @category Array
  6594. * @param {...Array} [arrays] The arrays to inspect.
  6595. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6596. * @returns {Array} Returns the new array of combined values.
  6597. * @example
  6598. *
  6599. * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor);
  6600. * // => [2.1, 1.2, 4.3]
  6601. *
  6602. * // The `_.property` iteratee shorthand.
  6603. * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
  6604. * // => [{ 'x': 1 }, { 'x': 2 }]
  6605. */
  6606. var unionBy = rest(function(arrays) {
  6607. var iteratee = last(arrays);
  6608. if (isArrayLikeObject(iteratee)) {
  6609. iteratee = undefined;
  6610. }
  6611. return baseUniq(baseFlatten(arrays, 1, true), getIteratee(iteratee));
  6612. });
  6613. /**
  6614. * This method is like `_.union` except that it accepts `comparator` which
  6615. * is invoked to compare elements of `arrays`. The comparator is invoked
  6616. * with two arguments: (arrVal, othVal).
  6617. *
  6618. * @static
  6619. * @memberOf _
  6620. * @category Array
  6621. * @param {...Array} [arrays] The arrays to inspect.
  6622. * @param {Function} [comparator] The comparator invoked per element.
  6623. * @returns {Array} Returns the new array of combined values.
  6624. * @example
  6625. *
  6626. * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
  6627. * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
  6628. *
  6629. * _.unionWith(objects, others, _.isEqual);
  6630. * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
  6631. */
  6632. var unionWith = rest(function(arrays) {
  6633. var comparator = last(arrays);
  6634. if (isArrayLikeObject(comparator)) {
  6635. comparator = undefined;
  6636. }
  6637. return baseUniq(baseFlatten(arrays, 1, true), undefined, comparator);
  6638. });
  6639. /**
  6640. * Creates a duplicate-free version of an array, using
  6641. * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  6642. * for equality comparisons, in which only the first occurrence of each element
  6643. * is kept.
  6644. *
  6645. * @static
  6646. * @memberOf _
  6647. * @category Array
  6648. * @param {Array} array The array to inspect.
  6649. * @returns {Array} Returns the new duplicate free array.
  6650. * @example
  6651. *
  6652. * _.uniq([2, 1, 2]);
  6653. * // => [2, 1]
  6654. */
  6655. function uniq(array) {
  6656. return (array && array.length)
  6657. ? baseUniq(array)
  6658. : [];
  6659. }
  6660. /**
  6661. * This method is like `_.uniq` except that it accepts `iteratee` which is
  6662. * invoked for each element in `array` to generate the criterion by which
  6663. * uniqueness is computed. The iteratee is invoked with one argument: (value).
  6664. *
  6665. * @static
  6666. * @memberOf _
  6667. * @category Array
  6668. * @param {Array} array The array to inspect.
  6669. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6670. * @returns {Array} Returns the new duplicate free array.
  6671. * @example
  6672. *
  6673. * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
  6674. * // => [2.1, 1.2]
  6675. *
  6676. * // The `_.property` iteratee shorthand.
  6677. * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
  6678. * // => [{ 'x': 1 }, { 'x': 2 }]
  6679. */
  6680. function uniqBy(array, iteratee) {
  6681. return (array && array.length)
  6682. ? baseUniq(array, getIteratee(iteratee))
  6683. : [];
  6684. }
  6685. /**
  6686. * This method is like `_.uniq` except that it accepts `comparator` which
  6687. * is invoked to compare elements of `array`. The comparator is invoked with
  6688. * two arguments: (arrVal, othVal).
  6689. *
  6690. * @static
  6691. * @memberOf _
  6692. * @category Array
  6693. * @param {Array} array The array to inspect.
  6694. * @param {Function} [comparator] The comparator invoked per element.
  6695. * @returns {Array} Returns the new duplicate free array.
  6696. * @example
  6697. *
  6698. * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
  6699. *
  6700. * _.uniqWith(objects, _.isEqual);
  6701. * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
  6702. */
  6703. function uniqWith(array, comparator) {
  6704. return (array && array.length)
  6705. ? baseUniq(array, undefined, comparator)
  6706. : [];
  6707. }
  6708. /**
  6709. * This method is like `_.zip` except that it accepts an array of grouped
  6710. * elements and creates an array regrouping the elements to their pre-zip
  6711. * configuration.
  6712. *
  6713. * @static
  6714. * @memberOf _
  6715. * @category Array
  6716. * @param {Array} array The array of grouped elements to process.
  6717. * @returns {Array} Returns the new array of regrouped elements.
  6718. * @example
  6719. *
  6720. * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
  6721. * // => [['fred', 30, true], ['barney', 40, false]]
  6722. *
  6723. * _.unzip(zipped);
  6724. * // => [['fred', 'barney'], [30, 40], [true, false]]
  6725. */
  6726. function unzip(array) {
  6727. if (!(array && array.length)) {
  6728. return [];
  6729. }
  6730. var length = 0;
  6731. array = arrayFilter(array, function(group) {
  6732. if (isArrayLikeObject(group)) {
  6733. length = nativeMax(group.length, length);
  6734. return true;
  6735. }
  6736. });
  6737. return baseTimes(length, function(index) {
  6738. return arrayMap(array, baseProperty(index));
  6739. });
  6740. }
  6741. /**
  6742. * This method is like `_.unzip` except that it accepts `iteratee` to specify
  6743. * how regrouped values should be combined. The iteratee is invoked with the
  6744. * elements of each group: (...group).
  6745. *
  6746. * @static
  6747. * @memberOf _
  6748. * @category Array
  6749. * @param {Array} array The array of grouped elements to process.
  6750. * @param {Function} [iteratee=_.identity] The function to combine regrouped values.
  6751. * @returns {Array} Returns the new array of regrouped elements.
  6752. * @example
  6753. *
  6754. * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
  6755. * // => [[1, 10, 100], [2, 20, 200]]
  6756. *
  6757. * _.unzipWith(zipped, _.add);
  6758. * // => [3, 30, 300]
  6759. */
  6760. function unzipWith(array, iteratee) {
  6761. if (!(array && array.length)) {
  6762. return [];
  6763. }
  6764. var result = unzip(array);
  6765. if (iteratee == null) {
  6766. return result;
  6767. }
  6768. return arrayMap(result, function(group) {
  6769. return apply(iteratee, undefined, group);
  6770. });
  6771. }
  6772. /**
  6773. * Creates an array excluding all given values using
  6774. * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  6775. * for equality comparisons.
  6776. *
  6777. * @static
  6778. * @memberOf _
  6779. * @category Array
  6780. * @param {Array} array The array to filter.
  6781. * @param {...*} [values] The values to exclude.
  6782. * @returns {Array} Returns the new array of filtered values.
  6783. * @example
  6784. *
  6785. * _.without([1, 2, 1, 3], 1, 2);
  6786. * // => [3]
  6787. */
  6788. var without = rest(function(array, values) {
  6789. return isArrayLikeObject(array)
  6790. ? baseDifference(array, values)
  6791. : [];
  6792. });
  6793. /**
  6794. * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
  6795. * of the given arrays.
  6796. *
  6797. * @static
  6798. * @memberOf _
  6799. * @category Array
  6800. * @param {...Array} [arrays] The arrays to inspect.
  6801. * @returns {Array} Returns the new array of values.
  6802. * @example
  6803. *
  6804. * _.xor([2, 1], [4, 2]);
  6805. * // => [1, 4]
  6806. */
  6807. var xor = rest(function(arrays) {
  6808. return baseXor(arrayFilter(arrays, isArrayLikeObject));
  6809. });
  6810. /**
  6811. * This method is like `_.xor` except that it accepts `iteratee` which is
  6812. * invoked for each element of each `arrays` to generate the criterion by which
  6813. * uniqueness is computed. The iteratee is invoked with one argument: (value).
  6814. *
  6815. * @static
  6816. * @memberOf _
  6817. * @category Array
  6818. * @param {...Array} [arrays] The arrays to inspect.
  6819. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  6820. * @returns {Array} Returns the new array of values.
  6821. * @example
  6822. *
  6823. * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor);
  6824. * // => [1.2, 4.3]
  6825. *
  6826. * // The `_.property` iteratee shorthand.
  6827. * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
  6828. * // => [{ 'x': 2 }]
  6829. */
  6830. var xorBy = rest(function(arrays) {
  6831. var iteratee = last(arrays);
  6832. if (isArrayLikeObject(iteratee)) {
  6833. iteratee = undefined;
  6834. }
  6835. return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee));
  6836. });
  6837. /**
  6838. * This method is like `_.xor` except that it accepts `comparator` which is
  6839. * invoked to compare elements of `arrays`. The comparator is invoked with
  6840. * two arguments: (arrVal, othVal).
  6841. *
  6842. * @static
  6843. * @memberOf _
  6844. * @category Array
  6845. * @param {...Array} [arrays] The arrays to inspect.
  6846. * @param {Function} [comparator] The comparator invoked per element.
  6847. * @returns {Array} Returns the new array of values.
  6848. * @example
  6849. *
  6850. * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
  6851. * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
  6852. *
  6853. * _.xorWith(objects, others, _.isEqual);
  6854. * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
  6855. */
  6856. var xorWith = rest(function(arrays) {
  6857. var comparator = last(arrays);
  6858. if (isArrayLikeObject(comparator)) {
  6859. comparator = undefined;
  6860. }
  6861. return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
  6862. });
  6863. /**
  6864. * Creates an array of grouped elements, the first of which contains the first
  6865. * elements of the given arrays, the second of which contains the second elements
  6866. * of the given arrays, and so on.
  6867. *
  6868. * @static
  6869. * @memberOf _
  6870. * @category Array
  6871. * @param {...Array} [arrays] The arrays to process.
  6872. * @returns {Array} Returns the new array of grouped elements.
  6873. * @example
  6874. *
  6875. * _.zip(['fred', 'barney'], [30, 40], [true, false]);
  6876. * // => [['fred', 30, true], ['barney', 40, false]]
  6877. */
  6878. var zip = rest(unzip);
  6879. /**
  6880. * This method is like `_.fromPairs` except that it accepts two arrays,
  6881. * one of property names and one of corresponding values.
  6882. *
  6883. * @static
  6884. * @memberOf _
  6885. * @category Array
  6886. * @param {Array} [props=[]] The property names.
  6887. * @param {Array} [values=[]] The property values.
  6888. * @returns {Object} Returns the new object.
  6889. * @example
  6890. *
  6891. * _.zipObject(['a', 'b'], [1, 2]);
  6892. * // => { 'a': 1, 'b': 2 }
  6893. */
  6894. function zipObject(props, values) {
  6895. return baseZipObject(props || [], values || [], assignValue);
  6896. }
  6897. /**
  6898. * This method is like `_.zipObject` except that it supports property paths.
  6899. *
  6900. * @static
  6901. * @memberOf _
  6902. * @category Array
  6903. * @param {Array} [props=[]] The property names.
  6904. * @param {Array} [values=[]] The property values.
  6905. * @returns {Object} Returns the new object.
  6906. * @example
  6907. *
  6908. * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
  6909. * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
  6910. */
  6911. function zipObjectDeep(props, values) {
  6912. return baseZipObject(props || [], values || [], baseSet);
  6913. }
  6914. /**
  6915. * This method is like `_.zip` except that it accepts `iteratee` to specify
  6916. * how grouped values should be combined. The iteratee is invoked with the
  6917. * elements of each group: (...group).
  6918. *
  6919. * @static
  6920. * @memberOf _
  6921. * @category Array
  6922. * @param {...Array} [arrays] The arrays to process.
  6923. * @param {Function} [iteratee=_.identity] The function to combine grouped values.
  6924. * @returns {Array} Returns the new array of grouped elements.
  6925. * @example
  6926. *
  6927. * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
  6928. * return a + b + c;
  6929. * });
  6930. * // => [111, 222]
  6931. */
  6932. var zipWith = rest(function(arrays) {
  6933. var length = arrays.length,
  6934. iteratee = length > 1 ? arrays[length - 1] : undefined;
  6935. iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
  6936. return unzipWith(arrays, iteratee);
  6937. });
  6938. /*------------------------------------------------------------------------*/
  6939. /**
  6940. * Creates a `lodash` object that wraps `value` with explicit method chaining enabled.
  6941. * The result of such method chaining must be unwrapped with `_#value`.
  6942. *
  6943. * @static
  6944. * @memberOf _
  6945. * @category Seq
  6946. * @param {*} value The value to wrap.
  6947. * @returns {Object} Returns the new `lodash` wrapper instance.
  6948. * @example
  6949. *
  6950. * var users = [
  6951. * { 'user': 'barney', 'age': 36 },
  6952. * { 'user': 'fred', 'age': 40 },
  6953. * { 'user': 'pebbles', 'age': 1 }
  6954. * ];
  6955. *
  6956. * var youngest = _
  6957. * .chain(users)
  6958. * .sortBy('age')
  6959. * .map(function(o) {
  6960. * return o.user + ' is ' + o.age;
  6961. * })
  6962. * .head()
  6963. * .value();
  6964. * // => 'pebbles is 1'
  6965. */
  6966. function chain(value) {
  6967. var result = lodash(value);
  6968. result.__chain__ = true;
  6969. return result;
  6970. }
  6971. /**
  6972. * This method invokes `interceptor` and returns `value`. The interceptor
  6973. * is invoked with one argument; (value). The purpose of this method is to
  6974. * "tap into" a method chain in order to modify intermediate results.
  6975. *
  6976. * @static
  6977. * @memberOf _
  6978. * @category Seq
  6979. * @param {*} value The value to provide to `interceptor`.
  6980. * @param {Function} interceptor The function to invoke.
  6981. * @returns {*} Returns `value`.
  6982. * @example
  6983. *
  6984. * _([1, 2, 3])
  6985. * .tap(function(array) {
  6986. * // Mutate input array.
  6987. * array.pop();
  6988. * })
  6989. * .reverse()
  6990. * .value();
  6991. * // => [2, 1]
  6992. */
  6993. function tap(value, interceptor) {
  6994. interceptor(value);
  6995. return value;
  6996. }
  6997. /**
  6998. * This method is like `_.tap` except that it returns the result of `interceptor`.
  6999. * The purpose of this method is to "pass thru" values replacing intermediate
  7000. * results in a method chain.
  7001. *
  7002. * @static
  7003. * @memberOf _
  7004. * @category Seq
  7005. * @param {*} value The value to provide to `interceptor`.
  7006. * @param {Function} interceptor The function to invoke.
  7007. * @returns {*} Returns the result of `interceptor`.
  7008. * @example
  7009. *
  7010. * _(' abc ')
  7011. * .chain()
  7012. * .trim()
  7013. * .thru(function(value) {
  7014. * return [value];
  7015. * })
  7016. * .value();
  7017. * // => ['abc']
  7018. */
  7019. function thru(value, interceptor) {
  7020. return interceptor(value);
  7021. }
  7022. /**
  7023. * This method is the wrapper version of `_.at`.
  7024. *
  7025. * @name at
  7026. * @memberOf _
  7027. * @category Seq
  7028. * @param {...(string|string[])} [paths] The property paths of elements to pick,
  7029. * specified individually or in arrays.
  7030. * @returns {Object} Returns the new `lodash` wrapper instance.
  7031. * @example
  7032. *
  7033. * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
  7034. *
  7035. * _(object).at(['a[0].b.c', 'a[1]']).value();
  7036. * // => [3, 4]
  7037. *
  7038. * _(['a', 'b', 'c']).at(0, 2).value();
  7039. * // => ['a', 'c']
  7040. */
  7041. var wrapperAt = rest(function(paths) {
  7042. paths = baseFlatten(paths, 1);
  7043. var length = paths.length,
  7044. start = length ? paths[0] : 0,
  7045. value = this.__wrapped__,
  7046. interceptor = function(object) { return baseAt(object, paths); };
  7047. if (length > 1 || this.__actions__.length ||
  7048. !(value instanceof LazyWrapper) || !isIndex(start)) {
  7049. return this.thru(interceptor);
  7050. }
  7051. value = value.slice(start, +start + (length ? 1 : 0));
  7052. value.__actions__.push({
  7053. 'func': thru,
  7054. 'args': [interceptor],
  7055. 'thisArg': undefined
  7056. });
  7057. return new LodashWrapper(value, this.__chain__).thru(function(array) {
  7058. if (length && !array.length) {
  7059. array.push(undefined);
  7060. }
  7061. return array;
  7062. });
  7063. });
  7064. /**
  7065. * Enables explicit method chaining on the wrapper object.
  7066. *
  7067. * @name chain
  7068. * @memberOf _
  7069. * @category Seq
  7070. * @returns {Object} Returns the new `lodash` wrapper instance.
  7071. * @example
  7072. *
  7073. * var users = [
  7074. * { 'user': 'barney', 'age': 36 },
  7075. * { 'user': 'fred', 'age': 40 }
  7076. * ];
  7077. *
  7078. * // A sequence without explicit chaining.
  7079. * _(users).head();
  7080. * // => { 'user': 'barney', 'age': 36 }
  7081. *
  7082. * // A sequence with explicit chaining.
  7083. * _(users)
  7084. * .chain()
  7085. * .head()
  7086. * .pick('user')
  7087. * .value();
  7088. * // => { 'user': 'barney' }
  7089. */
  7090. function wrapperChain() {
  7091. return chain(this);
  7092. }
  7093. /**
  7094. * Executes the chained sequence and returns the wrapped result.
  7095. *
  7096. * @name commit
  7097. * @memberOf _
  7098. * @category Seq
  7099. * @returns {Object} Returns the new `lodash` wrapper instance.
  7100. * @example
  7101. *
  7102. * var array = [1, 2];
  7103. * var wrapped = _(array).push(3);
  7104. *
  7105. * console.log(array);
  7106. * // => [1, 2]
  7107. *
  7108. * wrapped = wrapped.commit();
  7109. * console.log(array);
  7110. * // => [1, 2, 3]
  7111. *
  7112. * wrapped.last();
  7113. * // => 3
  7114. *
  7115. * console.log(array);
  7116. * // => [1, 2, 3]
  7117. */
  7118. function wrapperCommit() {
  7119. return new LodashWrapper(this.value(), this.__chain__);
  7120. }
  7121. /**
  7122. * This method is the wrapper version of `_.flatMap`.
  7123. *
  7124. * @name flatMap
  7125. * @memberOf _
  7126. * @category Seq
  7127. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
  7128. * @returns {Object} Returns the new `lodash` wrapper instance.
  7129. * @example
  7130. *
  7131. * function duplicate(n) {
  7132. * return [n, n];
  7133. * }
  7134. *
  7135. * _([1, 2]).flatMap(duplicate).value();
  7136. * // => [1, 1, 2, 2]
  7137. */
  7138. function wrapperFlatMap(iteratee) {
  7139. return this.map(iteratee).flatten();
  7140. }
  7141. /**
  7142. * Gets the next value on a wrapped object following the
  7143. * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
  7144. *
  7145. * @name next
  7146. * @memberOf _
  7147. * @category Seq
  7148. * @returns {Object} Returns the next iterator value.
  7149. * @example
  7150. *
  7151. * var wrapped = _([1, 2]);
  7152. *
  7153. * wrapped.next();
  7154. * // => { 'done': false, 'value': 1 }
  7155. *
  7156. * wrapped.next();
  7157. * // => { 'done': false, 'value': 2 }
  7158. *
  7159. * wrapped.next();
  7160. * // => { 'done': true, 'value': undefined }
  7161. */
  7162. function wrapperNext() {
  7163. if (this.__values__ === undefined) {
  7164. this.__values__ = toArray(this.value());
  7165. }
  7166. var done = this.__index__ >= this.__values__.length,
  7167. value = done ? undefined : this.__values__[this.__index__++];
  7168. return { 'done': done, 'value': value };
  7169. }
  7170. /**
  7171. * Enables the wrapper to be iterable.
  7172. *
  7173. * @name Symbol.iterator
  7174. * @memberOf _
  7175. * @category Seq
  7176. * @returns {Object} Returns the wrapper object.
  7177. * @example
  7178. *
  7179. * var wrapped = _([1, 2]);
  7180. *
  7181. * wrapped[Symbol.iterator]() === wrapped;
  7182. * // => true
  7183. *
  7184. * Array.from(wrapped);
  7185. * // => [1, 2]
  7186. */
  7187. function wrapperToIterator() {
  7188. return this;
  7189. }
  7190. /**
  7191. * Creates a clone of the chained sequence planting `value` as the wrapped value.
  7192. *
  7193. * @name plant
  7194. * @memberOf _
  7195. * @category Seq
  7196. * @param {*} value The value to plant.
  7197. * @returns {Object} Returns the new `lodash` wrapper instance.
  7198. * @example
  7199. *
  7200. * function square(n) {
  7201. * return n * n;
  7202. * }
  7203. *
  7204. * var wrapped = _([1, 2]).map(square);
  7205. * var other = wrapped.plant([3, 4]);
  7206. *
  7207. * other.value();
  7208. * // => [9, 16]
  7209. *
  7210. * wrapped.value();
  7211. * // => [1, 4]
  7212. */
  7213. function wrapperPlant(value) {
  7214. var result,
  7215. parent = this;
  7216. while (parent instanceof baseLodash) {
  7217. var clone = wrapperClone(parent);
  7218. clone.__index__ = 0;
  7219. clone.__values__ = undefined;
  7220. if (result) {
  7221. previous.__wrapped__ = clone;
  7222. } else {
  7223. result = clone;
  7224. }
  7225. var previous = clone;
  7226. parent = parent.__wrapped__;
  7227. }
  7228. previous.__wrapped__ = value;
  7229. return result;
  7230. }
  7231. /**
  7232. * This method is the wrapper version of `_.reverse`.
  7233. *
  7234. * **Note:** This method mutates the wrapped array.
  7235. *
  7236. * @name reverse
  7237. * @memberOf _
  7238. * @category Seq
  7239. * @returns {Object} Returns the new `lodash` wrapper instance.
  7240. * @example
  7241. *
  7242. * var array = [1, 2, 3];
  7243. *
  7244. * _(array).reverse().value()
  7245. * // => [3, 2, 1]
  7246. *
  7247. * console.log(array);
  7248. * // => [3, 2, 1]
  7249. */
  7250. function wrapperReverse() {
  7251. var value = this.__wrapped__;
  7252. if (value instanceof LazyWrapper) {
  7253. var wrapped = value;
  7254. if (this.__actions__.length) {
  7255. wrapped = new LazyWrapper(this);
  7256. }
  7257. wrapped = wrapped.reverse();
  7258. wrapped.__actions__.push({
  7259. 'func': thru,
  7260. 'args': [reverse],
  7261. 'thisArg': undefined
  7262. });
  7263. return new LodashWrapper(wrapped, this.__chain__);
  7264. }
  7265. return this.thru(reverse);
  7266. }
  7267. /**
  7268. * Executes the chained sequence to extract the unwrapped value.
  7269. *
  7270. * @name value
  7271. * @memberOf _
  7272. * @alias toJSON, valueOf
  7273. * @category Seq
  7274. * @returns {*} Returns the resolved unwrapped value.
  7275. * @example
  7276. *
  7277. * _([1, 2, 3]).value();
  7278. * // => [1, 2, 3]
  7279. */
  7280. function wrapperValue() {
  7281. return baseWrapperValue(this.__wrapped__, this.__actions__);
  7282. }
  7283. /*------------------------------------------------------------------------*/
  7284. /**
  7285. * Creates an object composed of keys generated from the results of running
  7286. * each element of `collection` through `iteratee`. The corresponding value
  7287. * of each key is the number of times the key was returned by `iteratee`.
  7288. * The iteratee is invoked with one argument: (value).
  7289. *
  7290. * @static
  7291. * @memberOf _
  7292. * @category Collection
  7293. * @param {Array|Object} collection The collection to iterate over.
  7294. * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
  7295. * @returns {Object} Returns the composed aggregate object.
  7296. * @example
  7297. *
  7298. * _.countBy([6.1, 4.2, 6.3], Math.floor);
  7299. * // => { '4': 1, '6': 2 }
  7300. *
  7301. * _.countBy(['one', 'two', 'three'], 'length');
  7302. * // => { '3': 2, '5': 1 }
  7303. */
  7304. var countBy = createAggregator(function(result, value, key) {
  7305. hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
  7306. });
  7307. /**
  7308. * Checks if `predicate` returns truthy for **all** elements of `collection`.
  7309. * Iteration is stopped once `predicate` returns falsey. The predicate is
  7310. * invoked with three arguments: (value, index|key, collection).
  7311. *
  7312. * @static
  7313. * @memberOf _
  7314. * @category Collection
  7315. * @param {Array|Object} collection The collection to iterate over.
  7316. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7317. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  7318. * @returns {boolean} Returns `true` if all elements pass the predicate check, else `false`.
  7319. * @example
  7320. *
  7321. * _.every([true, 1, null, 'yes'], Boolean);
  7322. * // => false
  7323. *
  7324. * var users = [
  7325. * { 'user': 'barney', 'active': false },
  7326. * { 'user': 'fred', 'active': false }
  7327. * ];
  7328. *
  7329. * // The `_.matches` iteratee shorthand.
  7330. * _.every(users, { 'user': 'barney', 'active': false });
  7331. * // => false
  7332. *
  7333. * // The `_.matchesProperty` iteratee shorthand.
  7334. * _.every(users, ['active', false]);
  7335. * // => true
  7336. *
  7337. * // The `_.property` iteratee shorthand.
  7338. * _.every(users, 'active');
  7339. * // => false
  7340. */
  7341. function every(collection, predicate, guard) {
  7342. var func = isArray(collection) ? arrayEvery : baseEvery;
  7343. if (guard && isIterateeCall(collection, predicate, guard)) {
  7344. predicate = undefined;
  7345. }
  7346. return func(collection, getIteratee(predicate, 3));
  7347. }
  7348. /**
  7349. * Iterates over elements of `collection`, returning an array of all elements
  7350. * `predicate` returns truthy for. The predicate is invoked with three arguments:
  7351. * (value, index|key, collection).
  7352. *
  7353. * @static
  7354. * @memberOf _
  7355. * @category Collection
  7356. * @param {Array|Object} collection The collection to iterate over.
  7357. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7358. * @returns {Array} Returns the new filtered array.
  7359. * @example
  7360. *
  7361. * var users = [
  7362. * { 'user': 'barney', 'age': 36, 'active': true },
  7363. * { 'user': 'fred', 'age': 40, 'active': false }
  7364. * ];
  7365. *
  7366. * _.filter(users, function(o) { return !o.active; });
  7367. * // => objects for ['fred']
  7368. *
  7369. * // The `_.matches` iteratee shorthand.
  7370. * _.filter(users, { 'age': 36, 'active': true });
  7371. * // => objects for ['barney']
  7372. *
  7373. * // The `_.matchesProperty` iteratee shorthand.
  7374. * _.filter(users, ['active', false]);
  7375. * // => objects for ['fred']
  7376. *
  7377. * // The `_.property` iteratee shorthand.
  7378. * _.filter(users, 'active');
  7379. * // => objects for ['barney']
  7380. */
  7381. function filter(collection, predicate) {
  7382. var func = isArray(collection) ? arrayFilter : baseFilter;
  7383. return func(collection, getIteratee(predicate, 3));
  7384. }
  7385. /**
  7386. * Iterates over elements of `collection`, returning the first element
  7387. * `predicate` returns truthy for. The predicate is invoked with three arguments:
  7388. * (value, index|key, collection).
  7389. *
  7390. * @static
  7391. * @memberOf _
  7392. * @category Collection
  7393. * @param {Array|Object} collection The collection to search.
  7394. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7395. * @returns {*} Returns the matched element, else `undefined`.
  7396. * @example
  7397. *
  7398. * var users = [
  7399. * { 'user': 'barney', 'age': 36, 'active': true },
  7400. * { 'user': 'fred', 'age': 40, 'active': false },
  7401. * { 'user': 'pebbles', 'age': 1, 'active': true }
  7402. * ];
  7403. *
  7404. * _.find(users, function(o) { return o.age < 40; });
  7405. * // => object for 'barney'
  7406. *
  7407. * // The `_.matches` iteratee shorthand.
  7408. * _.find(users, { 'age': 1, 'active': true });
  7409. * // => object for 'pebbles'
  7410. *
  7411. * // The `_.matchesProperty` iteratee shorthand.
  7412. * _.find(users, ['active', false]);
  7413. * // => object for 'fred'
  7414. *
  7415. * // The `_.property` iteratee shorthand.
  7416. * _.find(users, 'active');
  7417. * // => object for 'barney'
  7418. */
  7419. function find(collection, predicate) {
  7420. predicate = getIteratee(predicate, 3);
  7421. if (isArray(collection)) {
  7422. var index = baseFindIndex(collection, predicate);
  7423. return index > -1 ? collection[index] : undefined;
  7424. }
  7425. return baseFind(collection, predicate, baseEach);
  7426. }
  7427. /**
  7428. * This method is like `_.find` except that it iterates over elements of
  7429. * `collection` from right to left.
  7430. *
  7431. * @static
  7432. * @memberOf _
  7433. * @category Collection
  7434. * @param {Array|Object} collection The collection to search.
  7435. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7436. * @returns {*} Returns the matched element, else `undefined`.
  7437. * @example
  7438. *
  7439. * _.findLast([1, 2, 3, 4], function(n) {
  7440. * return n % 2 == 1;
  7441. * });
  7442. * // => 3
  7443. */
  7444. function findLast(collection, predicate) {
  7445. predicate = getIteratee(predicate, 3);
  7446. if (isArray(collection)) {
  7447. var index = baseFindIndex(collection, predicate, true);
  7448. return index > -1 ? collection[index] : undefined;
  7449. }
  7450. return baseFind(collection, predicate, baseEachRight);
  7451. }
  7452. /**
  7453. * Creates an array of flattened values by running each element in `collection`
  7454. * through `iteratee` and concating its result to the other mapped values.
  7455. * The iteratee is invoked with three arguments: (value, index|key, collection).
  7456. *
  7457. * @static
  7458. * @memberOf _
  7459. * @category Collection
  7460. * @param {Array|Object} collection The collection to iterate over.
  7461. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
  7462. * @returns {Array} Returns the new flattened array.
  7463. * @example
  7464. *
  7465. * function duplicate(n) {
  7466. * return [n, n];
  7467. * }
  7468. *
  7469. * _.flatMap([1, 2], duplicate);
  7470. * // => [1, 1, 2, 2]
  7471. */
  7472. function flatMap(collection, iteratee) {
  7473. return baseFlatten(map(collection, iteratee), 1);
  7474. }
  7475. /**
  7476. * Iterates over elements of `collection` invoking `iteratee` for each element.
  7477. * The iteratee is invoked with three arguments: (value, index|key, collection).
  7478. * Iteratee functions may exit iteration early by explicitly returning `false`.
  7479. *
  7480. * **Note:** As with other "Collections" methods, objects with a "length" property
  7481. * are iterated like arrays. To avoid this behavior use `_.forIn` or `_.forOwn`
  7482. * for object iteration.
  7483. *
  7484. * @static
  7485. * @memberOf _
  7486. * @alias each
  7487. * @category Collection
  7488. * @param {Array|Object} collection The collection to iterate over.
  7489. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  7490. * @returns {Array|Object} Returns `collection`.
  7491. * @example
  7492. *
  7493. * _([1, 2]).forEach(function(value) {
  7494. * console.log(value);
  7495. * });
  7496. * // => logs `1` then `2`
  7497. *
  7498. * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
  7499. * console.log(key);
  7500. * });
  7501. * // => logs 'a' then 'b' (iteration order is not guaranteed)
  7502. */
  7503. function forEach(collection, iteratee) {
  7504. return (typeof iteratee == 'function' && isArray(collection))
  7505. ? arrayEach(collection, iteratee)
  7506. : baseEach(collection, baseCastFunction(iteratee));
  7507. }
  7508. /**
  7509. * This method is like `_.forEach` except that it iterates over elements of
  7510. * `collection` from right to left.
  7511. *
  7512. * @static
  7513. * @memberOf _
  7514. * @alias eachRight
  7515. * @category Collection
  7516. * @param {Array|Object} collection The collection to iterate over.
  7517. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  7518. * @returns {Array|Object} Returns `collection`.
  7519. * @example
  7520. *
  7521. * _.forEachRight([1, 2], function(value) {
  7522. * console.log(value);
  7523. * });
  7524. * // => logs `2` then `1`
  7525. */
  7526. function forEachRight(collection, iteratee) {
  7527. return (typeof iteratee == 'function' && isArray(collection))
  7528. ? arrayEachRight(collection, iteratee)
  7529. : baseEachRight(collection, baseCastFunction(iteratee));
  7530. }
  7531. /**
  7532. * Creates an object composed of keys generated from the results of running
  7533. * each element of `collection` through `iteratee`. The corresponding value
  7534. * of each key is an array of elements responsible for generating the key.
  7535. * The iteratee is invoked with one argument: (value).
  7536. *
  7537. * @static
  7538. * @memberOf _
  7539. * @category Collection
  7540. * @param {Array|Object} collection The collection to iterate over.
  7541. * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
  7542. * @returns {Object} Returns the composed aggregate object.
  7543. * @example
  7544. *
  7545. * _.groupBy([6.1, 4.2, 6.3], Math.floor);
  7546. * // => { '4': [4.2], '6': [6.1, 6.3] }
  7547. *
  7548. * // The `_.property` iteratee shorthand.
  7549. * _.groupBy(['one', 'two', 'three'], 'length');
  7550. * // => { '3': ['one', 'two'], '5': ['three'] }
  7551. */
  7552. var groupBy = createAggregator(function(result, value, key) {
  7553. if (hasOwnProperty.call(result, key)) {
  7554. result[key].push(value);
  7555. } else {
  7556. result[key] = [value];
  7557. }
  7558. });
  7559. /**
  7560. * Checks if `value` is in `collection`. If `collection` is a string it's checked
  7561. * for a substring of `value`, otherwise [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  7562. * is used for equality comparisons. If `fromIndex` is negative, it's used as
  7563. * the offset from the end of `collection`.
  7564. *
  7565. * @static
  7566. * @memberOf _
  7567. * @category Collection
  7568. * @param {Array|Object|string} collection The collection to search.
  7569. * @param {*} value The value to search for.
  7570. * @param {number} [fromIndex=0] The index to search from.
  7571. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`.
  7572. * @returns {boolean} Returns `true` if `value` is found, else `false`.
  7573. * @example
  7574. *
  7575. * _.includes([1, 2, 3], 1);
  7576. * // => true
  7577. *
  7578. * _.includes([1, 2, 3], 1, 2);
  7579. * // => false
  7580. *
  7581. * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
  7582. * // => true
  7583. *
  7584. * _.includes('pebbles', 'eb');
  7585. * // => true
  7586. */
  7587. function includes(collection, value, fromIndex, guard) {
  7588. collection = isArrayLike(collection) ? collection : values(collection);
  7589. fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
  7590. var length = collection.length;
  7591. if (fromIndex < 0) {
  7592. fromIndex = nativeMax(length + fromIndex, 0);
  7593. }
  7594. return isString(collection)
  7595. ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
  7596. : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
  7597. }
  7598. /**
  7599. * Invokes the method at `path` of each element in `collection`, returning
  7600. * an array of the results of each invoked method. Any additional arguments
  7601. * are provided to each invoked method. If `methodName` is a function it's
  7602. * invoked for, and `this` bound to, each element in `collection`.
  7603. *
  7604. * @static
  7605. * @memberOf _
  7606. * @category Collection
  7607. * @param {Array|Object} collection The collection to iterate over.
  7608. * @param {Array|Function|string} path The path of the method to invoke or
  7609. * the function invoked per iteration.
  7610. * @param {...*} [args] The arguments to invoke each method with.
  7611. * @returns {Array} Returns the array of results.
  7612. * @example
  7613. *
  7614. * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
  7615. * // => [[1, 5, 7], [1, 2, 3]]
  7616. *
  7617. * _.invokeMap([123, 456], String.prototype.split, '');
  7618. * // => [['1', '2', '3'], ['4', '5', '6']]
  7619. */
  7620. var invokeMap = rest(function(collection, path, args) {
  7621. var index = -1,
  7622. isFunc = typeof path == 'function',
  7623. isProp = isKey(path),
  7624. result = isArrayLike(collection) ? Array(collection.length) : [];
  7625. baseEach(collection, function(value) {
  7626. var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
  7627. result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args);
  7628. });
  7629. return result;
  7630. });
  7631. /**
  7632. * Creates an object composed of keys generated from the results of running
  7633. * each element of `collection` through `iteratee`. The corresponding value
  7634. * of each key is the last element responsible for generating the key. The
  7635. * iteratee is invoked with one argument: (value).
  7636. *
  7637. * @static
  7638. * @memberOf _
  7639. * @category Collection
  7640. * @param {Array|Object} collection The collection to iterate over.
  7641. * @param {Function|Object|string} [iteratee=_.identity] The iteratee to transform keys.
  7642. * @returns {Object} Returns the composed aggregate object.
  7643. * @example
  7644. *
  7645. * var array = [
  7646. * { 'dir': 'left', 'code': 97 },
  7647. * { 'dir': 'right', 'code': 100 }
  7648. * ];
  7649. *
  7650. * _.keyBy(array, function(o) {
  7651. * return String.fromCharCode(o.code);
  7652. * });
  7653. * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
  7654. *
  7655. * _.keyBy(array, 'dir');
  7656. * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
  7657. */
  7658. var keyBy = createAggregator(function(result, value, key) {
  7659. result[key] = value;
  7660. });
  7661. /**
  7662. * Creates an array of values by running each element in `collection` through
  7663. * `iteratee`. The iteratee is invoked with three arguments:
  7664. * (value, index|key, collection).
  7665. *
  7666. * Many lodash methods are guarded to work as iteratees for methods like
  7667. * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
  7668. *
  7669. * The guarded methods are:
  7670. * `ary`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, `fill`,
  7671. * `invert`, `parseInt`, `random`, `range`, `rangeRight`, `slice`, `some`,
  7672. * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimEnd`, `trimStart`,
  7673. * and `words`
  7674. *
  7675. * @static
  7676. * @memberOf _
  7677. * @category Collection
  7678. * @param {Array|Object} collection The collection to iterate over.
  7679. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
  7680. * @returns {Array} Returns the new mapped array.
  7681. * @example
  7682. *
  7683. * function square(n) {
  7684. * return n * n;
  7685. * }
  7686. *
  7687. * _.map([4, 8], square);
  7688. * // => [16, 64]
  7689. *
  7690. * _.map({ 'a': 4, 'b': 8 }, square);
  7691. * // => [16, 64] (iteration order is not guaranteed)
  7692. *
  7693. * var users = [
  7694. * { 'user': 'barney' },
  7695. * { 'user': 'fred' }
  7696. * ];
  7697. *
  7698. * // The `_.property` iteratee shorthand.
  7699. * _.map(users, 'user');
  7700. * // => ['barney', 'fred']
  7701. */
  7702. function map(collection, iteratee) {
  7703. var func = isArray(collection) ? arrayMap : baseMap;
  7704. return func(collection, getIteratee(iteratee, 3));
  7705. }
  7706. /**
  7707. * This method is like `_.sortBy` except that it allows specifying the sort
  7708. * orders of the iteratees to sort by. If `orders` is unspecified, all values
  7709. * are sorted in ascending order. Otherwise, specify an order of "desc" for
  7710. * descending or "asc" for ascending sort order of corresponding values.
  7711. *
  7712. * @static
  7713. * @memberOf _
  7714. * @category Collection
  7715. * @param {Array|Object} collection The collection to iterate over.
  7716. * @param {Function[]|Object[]|string[]} [iteratees=[_.identity]] The iteratees to sort by.
  7717. * @param {string[]} [orders] The sort orders of `iteratees`.
  7718. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.reduce`.
  7719. * @returns {Array} Returns the new sorted array.
  7720. * @example
  7721. *
  7722. * var users = [
  7723. * { 'user': 'fred', 'age': 48 },
  7724. * { 'user': 'barney', 'age': 34 },
  7725. * { 'user': 'fred', 'age': 42 },
  7726. * { 'user': 'barney', 'age': 36 }
  7727. * ];
  7728. *
  7729. * // Sort by `user` in ascending order and by `age` in descending order.
  7730. * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
  7731. * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
  7732. */
  7733. function orderBy(collection, iteratees, orders, guard) {
  7734. if (collection == null) {
  7735. return [];
  7736. }
  7737. if (!isArray(iteratees)) {
  7738. iteratees = iteratees == null ? [] : [iteratees];
  7739. }
  7740. orders = guard ? undefined : orders;
  7741. if (!isArray(orders)) {
  7742. orders = orders == null ? [] : [orders];
  7743. }
  7744. return baseOrderBy(collection, iteratees, orders);
  7745. }
  7746. /**
  7747. * Creates an array of elements split into two groups, the first of which
  7748. * contains elements `predicate` returns truthy for, the second of which
  7749. * contains elements `predicate` returns falsey for. The predicate is
  7750. * invoked with one argument: (value).
  7751. *
  7752. * @static
  7753. * @memberOf _
  7754. * @category Collection
  7755. * @param {Array|Object} collection The collection to iterate over.
  7756. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7757. * @returns {Array} Returns the array of grouped elements.
  7758. * @example
  7759. *
  7760. * var users = [
  7761. * { 'user': 'barney', 'age': 36, 'active': false },
  7762. * { 'user': 'fred', 'age': 40, 'active': true },
  7763. * { 'user': 'pebbles', 'age': 1, 'active': false }
  7764. * ];
  7765. *
  7766. * _.partition(users, function(o) { return o.active; });
  7767. * // => objects for [['fred'], ['barney', 'pebbles']]
  7768. *
  7769. * // The `_.matches` iteratee shorthand.
  7770. * _.partition(users, { 'age': 1, 'active': false });
  7771. * // => objects for [['pebbles'], ['barney', 'fred']]
  7772. *
  7773. * // The `_.matchesProperty` iteratee shorthand.
  7774. * _.partition(users, ['active', false]);
  7775. * // => objects for [['barney', 'pebbles'], ['fred']]
  7776. *
  7777. * // The `_.property` iteratee shorthand.
  7778. * _.partition(users, 'active');
  7779. * // => objects for [['fred'], ['barney', 'pebbles']]
  7780. */
  7781. var partition = createAggregator(function(result, value, key) {
  7782. result[key ? 0 : 1].push(value);
  7783. }, function() { return [[], []]; });
  7784. /**
  7785. * Reduces `collection` to a value which is the accumulated result of running
  7786. * each element in `collection` through `iteratee`, where each successive
  7787. * invocation is supplied the return value of the previous. If `accumulator`
  7788. * is not given the first element of `collection` is used as the initial
  7789. * value. The iteratee is invoked with four arguments:
  7790. * (accumulator, value, index|key, collection).
  7791. *
  7792. * Many lodash methods are guarded to work as iteratees for methods like
  7793. * `_.reduce`, `_.reduceRight`, and `_.transform`.
  7794. *
  7795. * The guarded methods are:
  7796. * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
  7797. * and `sortBy`
  7798. *
  7799. * @static
  7800. * @memberOf _
  7801. * @category Collection
  7802. * @param {Array|Object} collection The collection to iterate over.
  7803. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  7804. * @param {*} [accumulator] The initial value.
  7805. * @returns {*} Returns the accumulated value.
  7806. * @example
  7807. *
  7808. * _.reduce([1, 2], function(sum, n) {
  7809. * return sum + n;
  7810. * }, 0);
  7811. * // => 3
  7812. *
  7813. * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
  7814. * (result[value] || (result[value] = [])).push(key);
  7815. * return result;
  7816. * }, {});
  7817. * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
  7818. */
  7819. function reduce(collection, iteratee, accumulator) {
  7820. var func = isArray(collection) ? arrayReduce : baseReduce,
  7821. initAccum = arguments.length < 3;
  7822. return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
  7823. }
  7824. /**
  7825. * This method is like `_.reduce` except that it iterates over elements of
  7826. * `collection` from right to left.
  7827. *
  7828. * @static
  7829. * @memberOf _
  7830. * @category Collection
  7831. * @param {Array|Object} collection The collection to iterate over.
  7832. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  7833. * @param {*} [accumulator] The initial value.
  7834. * @returns {*} Returns the accumulated value.
  7835. * @example
  7836. *
  7837. * var array = [[0, 1], [2, 3], [4, 5]];
  7838. *
  7839. * _.reduceRight(array, function(flattened, other) {
  7840. * return flattened.concat(other);
  7841. * }, []);
  7842. * // => [4, 5, 2, 3, 0, 1]
  7843. */
  7844. function reduceRight(collection, iteratee, accumulator) {
  7845. var func = isArray(collection) ? arrayReduceRight : baseReduce,
  7846. initAccum = arguments.length < 3;
  7847. return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
  7848. }
  7849. /**
  7850. * The opposite of `_.filter`; this method returns the elements of `collection`
  7851. * that `predicate` does **not** return truthy for.
  7852. *
  7853. * @static
  7854. * @memberOf _
  7855. * @category Collection
  7856. * @param {Array|Object} collection The collection to iterate over.
  7857. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7858. * @returns {Array} Returns the new filtered array.
  7859. * @example
  7860. *
  7861. * var users = [
  7862. * { 'user': 'barney', 'age': 36, 'active': false },
  7863. * { 'user': 'fred', 'age': 40, 'active': true }
  7864. * ];
  7865. *
  7866. * _.reject(users, function(o) { return !o.active; });
  7867. * // => objects for ['fred']
  7868. *
  7869. * // The `_.matches` iteratee shorthand.
  7870. * _.reject(users, { 'age': 40, 'active': true });
  7871. * // => objects for ['barney']
  7872. *
  7873. * // The `_.matchesProperty` iteratee shorthand.
  7874. * _.reject(users, ['active', false]);
  7875. * // => objects for ['fred']
  7876. *
  7877. * // The `_.property` iteratee shorthand.
  7878. * _.reject(users, 'active');
  7879. * // => objects for ['barney']
  7880. */
  7881. function reject(collection, predicate) {
  7882. var func = isArray(collection) ? arrayFilter : baseFilter;
  7883. predicate = getIteratee(predicate, 3);
  7884. return func(collection, function(value, index, collection) {
  7885. return !predicate(value, index, collection);
  7886. });
  7887. }
  7888. /**
  7889. * Gets a random element from `collection`.
  7890. *
  7891. * @static
  7892. * @memberOf _
  7893. * @category Collection
  7894. * @param {Array|Object} collection The collection to sample.
  7895. * @returns {*} Returns the random element.
  7896. * @example
  7897. *
  7898. * _.sample([1, 2, 3, 4]);
  7899. * // => 2
  7900. */
  7901. function sample(collection) {
  7902. var array = isArrayLike(collection) ? collection : values(collection),
  7903. length = array.length;
  7904. return length > 0 ? array[baseRandom(0, length - 1)] : undefined;
  7905. }
  7906. /**
  7907. * Gets `n` random elements at unique keys from `collection` up to the
  7908. * size of `collection`.
  7909. *
  7910. * @static
  7911. * @memberOf _
  7912. * @category Collection
  7913. * @param {Array|Object} collection The collection to sample.
  7914. * @param {number} [n=0] The number of elements to sample.
  7915. * @returns {Array} Returns the random elements.
  7916. * @example
  7917. *
  7918. * _.sampleSize([1, 2, 3], 2);
  7919. * // => [3, 1]
  7920. *
  7921. * _.sampleSize([1, 2, 3], 4);
  7922. * // => [2, 3, 1]
  7923. */
  7924. function sampleSize(collection, n) {
  7925. var index = -1,
  7926. result = toArray(collection),
  7927. length = result.length,
  7928. lastIndex = length - 1;
  7929. n = baseClamp(toInteger(n), 0, length);
  7930. while (++index < n) {
  7931. var rand = baseRandom(index, lastIndex),
  7932. value = result[rand];
  7933. result[rand] = result[index];
  7934. result[index] = value;
  7935. }
  7936. result.length = n;
  7937. return result;
  7938. }
  7939. /**
  7940. * Creates an array of shuffled values, using a version of the
  7941. * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
  7942. *
  7943. * @static
  7944. * @memberOf _
  7945. * @category Collection
  7946. * @param {Array|Object} collection The collection to shuffle.
  7947. * @returns {Array} Returns the new shuffled array.
  7948. * @example
  7949. *
  7950. * _.shuffle([1, 2, 3, 4]);
  7951. * // => [4, 1, 3, 2]
  7952. */
  7953. function shuffle(collection) {
  7954. return sampleSize(collection, MAX_ARRAY_LENGTH);
  7955. }
  7956. /**
  7957. * Gets the size of `collection` by returning its length for array-like
  7958. * values or the number of own enumerable properties for objects.
  7959. *
  7960. * @static
  7961. * @memberOf _
  7962. * @category Collection
  7963. * @param {Array|Object} collection The collection to inspect.
  7964. * @returns {number} Returns the collection size.
  7965. * @example
  7966. *
  7967. * _.size([1, 2, 3]);
  7968. * // => 3
  7969. *
  7970. * _.size({ 'a': 1, 'b': 2 });
  7971. * // => 2
  7972. *
  7973. * _.size('pebbles');
  7974. * // => 7
  7975. */
  7976. function size(collection) {
  7977. if (collection == null) {
  7978. return 0;
  7979. }
  7980. if (isArrayLike(collection)) {
  7981. var result = collection.length;
  7982. return (result && isString(collection)) ? stringSize(collection) : result;
  7983. }
  7984. return keys(collection).length;
  7985. }
  7986. /**
  7987. * Checks if `predicate` returns truthy for **any** element of `collection`.
  7988. * Iteration is stopped once `predicate` returns truthy. The predicate is
  7989. * invoked with three arguments: (value, index|key, collection).
  7990. *
  7991. * @static
  7992. * @memberOf _
  7993. * @category Collection
  7994. * @param {Array|Object} collection The collection to iterate over.
  7995. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  7996. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  7997. * @returns {boolean} Returns `true` if any element passes the predicate check, else `false`.
  7998. * @example
  7999. *
  8000. * _.some([null, 0, 'yes', false], Boolean);
  8001. * // => true
  8002. *
  8003. * var users = [
  8004. * { 'user': 'barney', 'active': true },
  8005. * { 'user': 'fred', 'active': false }
  8006. * ];
  8007. *
  8008. * // The `_.matches` iteratee shorthand.
  8009. * _.some(users, { 'user': 'barney', 'active': false });
  8010. * // => false
  8011. *
  8012. * // The `_.matchesProperty` iteratee shorthand.
  8013. * _.some(users, ['active', false]);
  8014. * // => true
  8015. *
  8016. * // The `_.property` iteratee shorthand.
  8017. * _.some(users, 'active');
  8018. * // => true
  8019. */
  8020. function some(collection, predicate, guard) {
  8021. var func = isArray(collection) ? arraySome : baseSome;
  8022. if (guard && isIterateeCall(collection, predicate, guard)) {
  8023. predicate = undefined;
  8024. }
  8025. return func(collection, getIteratee(predicate, 3));
  8026. }
  8027. /**
  8028. * Creates an array of elements, sorted in ascending order by the results of
  8029. * running each element in a collection through each iteratee. This method
  8030. * performs a stable sort, that is, it preserves the original sort order of
  8031. * equal elements. The iteratees are invoked with one argument: (value).
  8032. *
  8033. * @static
  8034. * @memberOf _
  8035. * @category Collection
  8036. * @param {Array|Object} collection The collection to iterate over.
  8037. * @param {...(Function|Function[]|Object|Object[]|string|string[])} [iteratees=[_.identity]]
  8038. * The iteratees to sort by, specified individually or in arrays.
  8039. * @returns {Array} Returns the new sorted array.
  8040. * @example
  8041. *
  8042. * var users = [
  8043. * { 'user': 'fred', 'age': 48 },
  8044. * { 'user': 'barney', 'age': 36 },
  8045. * { 'user': 'fred', 'age': 42 },
  8046. * { 'user': 'barney', 'age': 34 }
  8047. * ];
  8048. *
  8049. * _.sortBy(users, function(o) { return o.user; });
  8050. * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
  8051. *
  8052. * _.sortBy(users, ['user', 'age']);
  8053. * // => objects for [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
  8054. *
  8055. * _.sortBy(users, 'user', function(o) {
  8056. * return Math.floor(o.age / 10);
  8057. * });
  8058. * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
  8059. */
  8060. var sortBy = rest(function(collection, iteratees) {
  8061. if (collection == null) {
  8062. return [];
  8063. }
  8064. var length = iteratees.length;
  8065. if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
  8066. iteratees = [];
  8067. } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
  8068. iteratees.length = 1;
  8069. }
  8070. return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
  8071. });
  8072. /*------------------------------------------------------------------------*/
  8073. /**
  8074. * Gets the timestamp of the number of milliseconds that have elapsed since
  8075. * the Unix epoch (1 January 1970 00:00:00 UTC).
  8076. *
  8077. * @static
  8078. * @memberOf _
  8079. * @type {Function}
  8080. * @category Date
  8081. * @returns {number} Returns the timestamp.
  8082. * @example
  8083. *
  8084. * _.defer(function(stamp) {
  8085. * console.log(_.now() - stamp);
  8086. * }, _.now());
  8087. * // => logs the number of milliseconds it took for the deferred function to be invoked
  8088. */
  8089. var now = Date.now;
  8090. /*------------------------------------------------------------------------*/
  8091. /**
  8092. * The opposite of `_.before`; this method creates a function that invokes
  8093. * `func` once it's called `n` or more times.
  8094. *
  8095. * @static
  8096. * @memberOf _
  8097. * @category Function
  8098. * @param {number} n The number of calls before `func` is invoked.
  8099. * @param {Function} func The function to restrict.
  8100. * @returns {Function} Returns the new restricted function.
  8101. * @example
  8102. *
  8103. * var saves = ['profile', 'settings'];
  8104. *
  8105. * var done = _.after(saves.length, function() {
  8106. * console.log('done saving!');
  8107. * });
  8108. *
  8109. * _.forEach(saves, function(type) {
  8110. * asyncSave({ 'type': type, 'complete': done });
  8111. * });
  8112. * // => logs 'done saving!' after the two async saves have completed
  8113. */
  8114. function after(n, func) {
  8115. if (typeof func != 'function') {
  8116. throw new TypeError(FUNC_ERROR_TEXT);
  8117. }
  8118. n = toInteger(n);
  8119. return function() {
  8120. if (--n < 1) {
  8121. return func.apply(this, arguments);
  8122. }
  8123. };
  8124. }
  8125. /**
  8126. * Creates a function that accepts up to `n` arguments, ignoring any
  8127. * additional arguments.
  8128. *
  8129. * @static
  8130. * @memberOf _
  8131. * @category Function
  8132. * @param {Function} func The function to cap arguments for.
  8133. * @param {number} [n=func.length] The arity cap.
  8134. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  8135. * @returns {Function} Returns the new function.
  8136. * @example
  8137. *
  8138. * _.map(['6', '8', '10'], _.ary(parseInt, 1));
  8139. * // => [6, 8, 10]
  8140. */
  8141. function ary(func, n, guard) {
  8142. n = guard ? undefined : n;
  8143. n = (func && n == null) ? func.length : n;
  8144. return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
  8145. }
  8146. /**
  8147. * Creates a function that invokes `func`, with the `this` binding and arguments
  8148. * of the created function, while it's called less than `n` times. Subsequent
  8149. * calls to the created function return the result of the last `func` invocation.
  8150. *
  8151. * @static
  8152. * @memberOf _
  8153. * @category Function
  8154. * @param {number} n The number of calls at which `func` is no longer invoked.
  8155. * @param {Function} func The function to restrict.
  8156. * @returns {Function} Returns the new restricted function.
  8157. * @example
  8158. *
  8159. * jQuery(element).on('click', _.before(5, addContactToList));
  8160. * // => allows adding up to 4 contacts to the list
  8161. */
  8162. function before(n, func) {
  8163. var result;
  8164. if (typeof func != 'function') {
  8165. throw new TypeError(FUNC_ERROR_TEXT);
  8166. }
  8167. n = toInteger(n);
  8168. return function() {
  8169. if (--n > 0) {
  8170. result = func.apply(this, arguments);
  8171. }
  8172. if (n <= 1) {
  8173. func = undefined;
  8174. }
  8175. return result;
  8176. };
  8177. }
  8178. /**
  8179. * Creates a function that invokes `func` with the `this` binding of `thisArg`
  8180. * and prepends any additional `_.bind` arguments to those provided to the
  8181. * bound function.
  8182. *
  8183. * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
  8184. * may be used as a placeholder for partially applied arguments.
  8185. *
  8186. * **Note:** Unlike native `Function#bind` this method doesn't set the "length"
  8187. * property of bound functions.
  8188. *
  8189. * @static
  8190. * @memberOf _
  8191. * @category Function
  8192. * @param {Function} func The function to bind.
  8193. * @param {*} thisArg The `this` binding of `func`.
  8194. * @param {...*} [partials] The arguments to be partially applied.
  8195. * @returns {Function} Returns the new bound function.
  8196. * @example
  8197. *
  8198. * var greet = function(greeting, punctuation) {
  8199. * return greeting + ' ' + this.user + punctuation;
  8200. * };
  8201. *
  8202. * var object = { 'user': 'fred' };
  8203. *
  8204. * var bound = _.bind(greet, object, 'hi');
  8205. * bound('!');
  8206. * // => 'hi fred!'
  8207. *
  8208. * // Bound with placeholders.
  8209. * var bound = _.bind(greet, object, _, '!');
  8210. * bound('hi');
  8211. * // => 'hi fred!'
  8212. */
  8213. var bind = rest(function(func, thisArg, partials) {
  8214. var bitmask = BIND_FLAG;
  8215. if (partials.length) {
  8216. var holders = replaceHolders(partials, getPlaceholder(bind));
  8217. bitmask |= PARTIAL_FLAG;
  8218. }
  8219. return createWrapper(func, bitmask, thisArg, partials, holders);
  8220. });
  8221. /**
  8222. * Creates a function that invokes the method at `object[key]` and prepends
  8223. * any additional `_.bindKey` arguments to those provided to the bound function.
  8224. *
  8225. * This method differs from `_.bind` by allowing bound functions to reference
  8226. * methods that may be redefined or don't yet exist.
  8227. * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
  8228. * for more details.
  8229. *
  8230. * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
  8231. * builds, may be used as a placeholder for partially applied arguments.
  8232. *
  8233. * @static
  8234. * @memberOf _
  8235. * @category Function
  8236. * @param {Object} object The object to invoke the method on.
  8237. * @param {string} key The key of the method.
  8238. * @param {...*} [partials] The arguments to be partially applied.
  8239. * @returns {Function} Returns the new bound function.
  8240. * @example
  8241. *
  8242. * var object = {
  8243. * 'user': 'fred',
  8244. * 'greet': function(greeting, punctuation) {
  8245. * return greeting + ' ' + this.user + punctuation;
  8246. * }
  8247. * };
  8248. *
  8249. * var bound = _.bindKey(object, 'greet', 'hi');
  8250. * bound('!');
  8251. * // => 'hi fred!'
  8252. *
  8253. * object.greet = function(greeting, punctuation) {
  8254. * return greeting + 'ya ' + this.user + punctuation;
  8255. * };
  8256. *
  8257. * bound('!');
  8258. * // => 'hiya fred!'
  8259. *
  8260. * // Bound with placeholders.
  8261. * var bound = _.bindKey(object, 'greet', _, '!');
  8262. * bound('hi');
  8263. * // => 'hiya fred!'
  8264. */
  8265. var bindKey = rest(function(object, key, partials) {
  8266. var bitmask = BIND_FLAG | BIND_KEY_FLAG;
  8267. if (partials.length) {
  8268. var holders = replaceHolders(partials, getPlaceholder(bindKey));
  8269. bitmask |= PARTIAL_FLAG;
  8270. }
  8271. return createWrapper(key, bitmask, object, partials, holders);
  8272. });
  8273. /**
  8274. * Creates a function that accepts arguments of `func` and either invokes
  8275. * `func` returning its result, if at least `arity` number of arguments have
  8276. * been provided, or returns a function that accepts the remaining `func`
  8277. * arguments, and so on. The arity of `func` may be specified if `func.length`
  8278. * is not sufficient.
  8279. *
  8280. * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
  8281. * may be used as a placeholder for provided arguments.
  8282. *
  8283. * **Note:** This method doesn't set the "length" property of curried functions.
  8284. *
  8285. * @static
  8286. * @memberOf _
  8287. * @category Function
  8288. * @param {Function} func The function to curry.
  8289. * @param {number} [arity=func.length] The arity of `func`.
  8290. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  8291. * @returns {Function} Returns the new curried function.
  8292. * @example
  8293. *
  8294. * var abc = function(a, b, c) {
  8295. * return [a, b, c];
  8296. * };
  8297. *
  8298. * var curried = _.curry(abc);
  8299. *
  8300. * curried(1)(2)(3);
  8301. * // => [1, 2, 3]
  8302. *
  8303. * curried(1, 2)(3);
  8304. * // => [1, 2, 3]
  8305. *
  8306. * curried(1, 2, 3);
  8307. * // => [1, 2, 3]
  8308. *
  8309. * // Curried with placeholders.
  8310. * curried(1)(_, 3)(2);
  8311. * // => [1, 2, 3]
  8312. */
  8313. function curry(func, arity, guard) {
  8314. arity = guard ? undefined : arity;
  8315. var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
  8316. result.placeholder = curry.placeholder;
  8317. return result;
  8318. }
  8319. /**
  8320. * This method is like `_.curry` except that arguments are applied to `func`
  8321. * in the manner of `_.partialRight` instead of `_.partial`.
  8322. *
  8323. * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
  8324. * builds, may be used as a placeholder for provided arguments.
  8325. *
  8326. * **Note:** This method doesn't set the "length" property of curried functions.
  8327. *
  8328. * @static
  8329. * @memberOf _
  8330. * @category Function
  8331. * @param {Function} func The function to curry.
  8332. * @param {number} [arity=func.length] The arity of `func`.
  8333. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  8334. * @returns {Function} Returns the new curried function.
  8335. * @example
  8336. *
  8337. * var abc = function(a, b, c) {
  8338. * return [a, b, c];
  8339. * };
  8340. *
  8341. * var curried = _.curryRight(abc);
  8342. *
  8343. * curried(3)(2)(1);
  8344. * // => [1, 2, 3]
  8345. *
  8346. * curried(2, 3)(1);
  8347. * // => [1, 2, 3]
  8348. *
  8349. * curried(1, 2, 3);
  8350. * // => [1, 2, 3]
  8351. *
  8352. * // Curried with placeholders.
  8353. * curried(3)(1, _)(2);
  8354. * // => [1, 2, 3]
  8355. */
  8356. function curryRight(func, arity, guard) {
  8357. arity = guard ? undefined : arity;
  8358. var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
  8359. result.placeholder = curryRight.placeholder;
  8360. return result;
  8361. }
  8362. /**
  8363. * Creates a debounced function that delays invoking `func` until after `wait`
  8364. * milliseconds have elapsed since the last time the debounced function was
  8365. * invoked. The debounced function comes with a `cancel` method to cancel
  8366. * delayed `func` invocations and a `flush` method to immediately invoke them.
  8367. * Provide an options object to indicate whether `func` should be invoked on
  8368. * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked
  8369. * with the last arguments provided to the debounced function. Subsequent calls
  8370. * to the debounced function return the result of the last `func` invocation.
  8371. *
  8372. * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
  8373. * on the trailing edge of the timeout only if the debounced function is
  8374. * invoked more than once during the `wait` timeout.
  8375. *
  8376. * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
  8377. * for details over the differences between `_.debounce` and `_.throttle`.
  8378. *
  8379. * @static
  8380. * @memberOf _
  8381. * @category Function
  8382. * @param {Function} func The function to debounce.
  8383. * @param {number} [wait=0] The number of milliseconds to delay.
  8384. * @param {Object} [options] The options object.
  8385. * @param {boolean} [options.leading=false] Specify invoking on the leading
  8386. * edge of the timeout.
  8387. * @param {number} [options.maxWait] The maximum time `func` is allowed to be
  8388. * delayed before it's invoked.
  8389. * @param {boolean} [options.trailing=true] Specify invoking on the trailing
  8390. * edge of the timeout.
  8391. * @returns {Function} Returns the new debounced function.
  8392. * @example
  8393. *
  8394. * // Avoid costly calculations while the window size is in flux.
  8395. * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
  8396. *
  8397. * // Invoke `sendMail` when clicked, debouncing subsequent calls.
  8398. * jQuery(element).on('click', _.debounce(sendMail, 300, {
  8399. * 'leading': true,
  8400. * 'trailing': false
  8401. * }));
  8402. *
  8403. * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
  8404. * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
  8405. * var source = new EventSource('/stream');
  8406. * jQuery(source).on('message', debounced);
  8407. *
  8408. * // Cancel the trailing debounced invocation.
  8409. * jQuery(window).on('popstate', debounced.cancel);
  8410. */
  8411. function debounce(func, wait, options) {
  8412. var args,
  8413. maxTimeoutId,
  8414. result,
  8415. stamp,
  8416. thisArg,
  8417. timeoutId,
  8418. trailingCall,
  8419. lastCalled = 0,
  8420. leading = false,
  8421. maxWait = false,
  8422. trailing = true;
  8423. if (typeof func != 'function') {
  8424. throw new TypeError(FUNC_ERROR_TEXT);
  8425. }
  8426. wait = toNumber(wait) || 0;
  8427. if (isObject(options)) {
  8428. leading = !!options.leading;
  8429. maxWait = 'maxWait' in options && nativeMax(toNumber(options.maxWait) || 0, wait);
  8430. trailing = 'trailing' in options ? !!options.trailing : trailing;
  8431. }
  8432. function cancel() {
  8433. if (timeoutId) {
  8434. clearTimeout(timeoutId);
  8435. }
  8436. if (maxTimeoutId) {
  8437. clearTimeout(maxTimeoutId);
  8438. }
  8439. lastCalled = 0;
  8440. args = maxTimeoutId = thisArg = timeoutId = trailingCall = undefined;
  8441. }
  8442. function complete(isCalled, id) {
  8443. if (id) {
  8444. clearTimeout(id);
  8445. }
  8446. maxTimeoutId = timeoutId = trailingCall = undefined;
  8447. if (isCalled) {
  8448. lastCalled = now();
  8449. result = func.apply(thisArg, args);
  8450. if (!timeoutId && !maxTimeoutId) {
  8451. args = thisArg = undefined;
  8452. }
  8453. }
  8454. }
  8455. function delayed() {
  8456. var remaining = wait - (now() - stamp);
  8457. if (remaining <= 0 || remaining > wait) {
  8458. complete(trailingCall, maxTimeoutId);
  8459. } else {
  8460. timeoutId = setTimeout(delayed, remaining);
  8461. }
  8462. }
  8463. function flush() {
  8464. if ((timeoutId && trailingCall) || (maxTimeoutId && trailing)) {
  8465. result = func.apply(thisArg, args);
  8466. }
  8467. cancel();
  8468. return result;
  8469. }
  8470. function maxDelayed() {
  8471. complete(trailing, timeoutId);
  8472. }
  8473. function debounced() {
  8474. args = arguments;
  8475. stamp = now();
  8476. thisArg = this;
  8477. trailingCall = trailing && (timeoutId || !leading);
  8478. if (maxWait === false) {
  8479. var leadingCall = leading && !timeoutId;
  8480. } else {
  8481. if (!lastCalled && !maxTimeoutId && !leading) {
  8482. lastCalled = stamp;
  8483. }
  8484. var remaining = maxWait - (stamp - lastCalled);
  8485. var isCalled = (remaining <= 0 || remaining > maxWait) &&
  8486. (leading || maxTimeoutId);
  8487. if (isCalled) {
  8488. if (maxTimeoutId) {
  8489. maxTimeoutId = clearTimeout(maxTimeoutId);
  8490. }
  8491. lastCalled = stamp;
  8492. result = func.apply(thisArg, args);
  8493. }
  8494. else if (!maxTimeoutId) {
  8495. maxTimeoutId = setTimeout(maxDelayed, remaining);
  8496. }
  8497. }
  8498. if (isCalled && timeoutId) {
  8499. timeoutId = clearTimeout(timeoutId);
  8500. }
  8501. else if (!timeoutId && wait !== maxWait) {
  8502. timeoutId = setTimeout(delayed, wait);
  8503. }
  8504. if (leadingCall) {
  8505. isCalled = true;
  8506. result = func.apply(thisArg, args);
  8507. }
  8508. if (isCalled && !timeoutId && !maxTimeoutId) {
  8509. args = thisArg = undefined;
  8510. }
  8511. return result;
  8512. }
  8513. debounced.cancel = cancel;
  8514. debounced.flush = flush;
  8515. return debounced;
  8516. }
  8517. /**
  8518. * Defers invoking the `func` until the current call stack has cleared. Any
  8519. * additional arguments are provided to `func` when it's invoked.
  8520. *
  8521. * @static
  8522. * @memberOf _
  8523. * @category Function
  8524. * @param {Function} func The function to defer.
  8525. * @param {...*} [args] The arguments to invoke `func` with.
  8526. * @returns {number} Returns the timer id.
  8527. * @example
  8528. *
  8529. * _.defer(function(text) {
  8530. * console.log(text);
  8531. * }, 'deferred');
  8532. * // => logs 'deferred' after one or more milliseconds
  8533. */
  8534. var defer = rest(function(func, args) {
  8535. return baseDelay(func, 1, args);
  8536. });
  8537. /**
  8538. * Invokes `func` after `wait` milliseconds. Any additional arguments are
  8539. * provided to `func` when it's invoked.
  8540. *
  8541. * @static
  8542. * @memberOf _
  8543. * @category Function
  8544. * @param {Function} func The function to delay.
  8545. * @param {number} wait The number of milliseconds to delay invocation.
  8546. * @param {...*} [args] The arguments to invoke `func` with.
  8547. * @returns {number} Returns the timer id.
  8548. * @example
  8549. *
  8550. * _.delay(function(text) {
  8551. * console.log(text);
  8552. * }, 1000, 'later');
  8553. * // => logs 'later' after one second
  8554. */
  8555. var delay = rest(function(func, wait, args) {
  8556. return baseDelay(func, toNumber(wait) || 0, args);
  8557. });
  8558. /**
  8559. * Creates a function that invokes `func` with arguments reversed.
  8560. *
  8561. * @static
  8562. * @memberOf _
  8563. * @category Function
  8564. * @param {Function} func The function to flip arguments for.
  8565. * @returns {Function} Returns the new function.
  8566. * @example
  8567. *
  8568. * var flipped = _.flip(function() {
  8569. * return _.toArray(arguments);
  8570. * });
  8571. *
  8572. * flipped('a', 'b', 'c', 'd');
  8573. * // => ['d', 'c', 'b', 'a']
  8574. */
  8575. function flip(func) {
  8576. return createWrapper(func, FLIP_FLAG);
  8577. }
  8578. /**
  8579. * Creates a function that memoizes the result of `func`. If `resolver` is
  8580. * provided it determines the cache key for storing the result based on the
  8581. * arguments provided to the memoized function. By default, the first argument
  8582. * provided to the memoized function is used as the map cache key. The `func`
  8583. * is invoked with the `this` binding of the memoized function.
  8584. *
  8585. * **Note:** The cache is exposed as the `cache` property on the memoized
  8586. * function. Its creation may be customized by replacing the `_.memoize.Cache`
  8587. * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
  8588. * method interface of `delete`, `get`, `has`, and `set`.
  8589. *
  8590. * @static
  8591. * @memberOf _
  8592. * @category Function
  8593. * @param {Function} func The function to have its output memoized.
  8594. * @param {Function} [resolver] The function to resolve the cache key.
  8595. * @returns {Function} Returns the new memoizing function.
  8596. * @example
  8597. *
  8598. * var object = { 'a': 1, 'b': 2 };
  8599. * var other = { 'c': 3, 'd': 4 };
  8600. *
  8601. * var values = _.memoize(_.values);
  8602. * values(object);
  8603. * // => [1, 2]
  8604. *
  8605. * values(other);
  8606. * // => [3, 4]
  8607. *
  8608. * object.a = 2;
  8609. * values(object);
  8610. * // => [1, 2]
  8611. *
  8612. * // Modify the result cache.
  8613. * values.cache.set(object, ['a', 'b']);
  8614. * values(object);
  8615. * // => ['a', 'b']
  8616. *
  8617. * // Replace `_.memoize.Cache`.
  8618. * _.memoize.Cache = WeakMap;
  8619. */
  8620. function memoize(func, resolver) {
  8621. if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
  8622. throw new TypeError(FUNC_ERROR_TEXT);
  8623. }
  8624. var memoized = function() {
  8625. var args = arguments,
  8626. key = resolver ? resolver.apply(this, args) : args[0],
  8627. cache = memoized.cache;
  8628. if (cache.has(key)) {
  8629. return cache.get(key);
  8630. }
  8631. var result = func.apply(this, args);
  8632. memoized.cache = cache.set(key, result);
  8633. return result;
  8634. };
  8635. memoized.cache = new memoize.Cache;
  8636. return memoized;
  8637. }
  8638. /**
  8639. * Creates a function that negates the result of the predicate `func`. The
  8640. * `func` predicate is invoked with the `this` binding and arguments of the
  8641. * created function.
  8642. *
  8643. * @static
  8644. * @memberOf _
  8645. * @category Function
  8646. * @param {Function} predicate The predicate to negate.
  8647. * @returns {Function} Returns the new function.
  8648. * @example
  8649. *
  8650. * function isEven(n) {
  8651. * return n % 2 == 0;
  8652. * }
  8653. *
  8654. * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
  8655. * // => [1, 3, 5]
  8656. */
  8657. function negate(predicate) {
  8658. if (typeof predicate != 'function') {
  8659. throw new TypeError(FUNC_ERROR_TEXT);
  8660. }
  8661. return function() {
  8662. return !predicate.apply(this, arguments);
  8663. };
  8664. }
  8665. /**
  8666. * Creates a function that is restricted to invoking `func` once. Repeat calls
  8667. * to the function return the value of the first invocation. The `func` is
  8668. * invoked with the `this` binding and arguments of the created function.
  8669. *
  8670. * @static
  8671. * @memberOf _
  8672. * @category Function
  8673. * @param {Function} func The function to restrict.
  8674. * @returns {Function} Returns the new restricted function.
  8675. * @example
  8676. *
  8677. * var initialize = _.once(createApplication);
  8678. * initialize();
  8679. * initialize();
  8680. * // `initialize` invokes `createApplication` once
  8681. */
  8682. function once(func) {
  8683. return before(2, func);
  8684. }
  8685. /**
  8686. * Creates a function that invokes `func` with arguments transformed by
  8687. * corresponding `transforms`.
  8688. *
  8689. * @static
  8690. * @memberOf _
  8691. * @category Function
  8692. * @param {Function} func The function to wrap.
  8693. * @param {...(Function|Function[])} [transforms] The functions to transform
  8694. * arguments, specified individually or in arrays.
  8695. * @returns {Function} Returns the new function.
  8696. * @example
  8697. *
  8698. * function doubled(n) {
  8699. * return n * 2;
  8700. * }
  8701. *
  8702. * function square(n) {
  8703. * return n * n;
  8704. * }
  8705. *
  8706. * var func = _.overArgs(function(x, y) {
  8707. * return [x, y];
  8708. * }, square, doubled);
  8709. *
  8710. * func(9, 3);
  8711. * // => [81, 6]
  8712. *
  8713. * func(10, 5);
  8714. * // => [100, 10]
  8715. */
  8716. var overArgs = rest(function(func, transforms) {
  8717. transforms = arrayMap(baseFlatten(transforms, 1), getIteratee());
  8718. var funcsLength = transforms.length;
  8719. return rest(function(args) {
  8720. var index = -1,
  8721. length = nativeMin(args.length, funcsLength);
  8722. while (++index < length) {
  8723. args[index] = transforms[index].call(this, args[index]);
  8724. }
  8725. return apply(func, this, args);
  8726. });
  8727. });
  8728. /**
  8729. * Creates a function that invokes `func` with `partial` arguments prepended
  8730. * to those provided to the new function. This method is like `_.bind` except
  8731. * it does **not** alter the `this` binding.
  8732. *
  8733. * The `_.partial.placeholder` value, which defaults to `_` in monolithic
  8734. * builds, may be used as a placeholder for partially applied arguments.
  8735. *
  8736. * **Note:** This method doesn't set the "length" property of partially
  8737. * applied functions.
  8738. *
  8739. * @static
  8740. * @memberOf _
  8741. * @category Function
  8742. * @param {Function} func The function to partially apply arguments to.
  8743. * @param {...*} [partials] The arguments to be partially applied.
  8744. * @returns {Function} Returns the new partially applied function.
  8745. * @example
  8746. *
  8747. * var greet = function(greeting, name) {
  8748. * return greeting + ' ' + name;
  8749. * };
  8750. *
  8751. * var sayHelloTo = _.partial(greet, 'hello');
  8752. * sayHelloTo('fred');
  8753. * // => 'hello fred'
  8754. *
  8755. * // Partially applied with placeholders.
  8756. * var greetFred = _.partial(greet, _, 'fred');
  8757. * greetFred('hi');
  8758. * // => 'hi fred'
  8759. */
  8760. var partial = rest(function(func, partials) {
  8761. var holders = replaceHolders(partials, getPlaceholder(partial));
  8762. return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders);
  8763. });
  8764. /**
  8765. * This method is like `_.partial` except that partially applied arguments
  8766. * are appended to those provided to the new function.
  8767. *
  8768. * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
  8769. * builds, may be used as a placeholder for partially applied arguments.
  8770. *
  8771. * **Note:** This method doesn't set the "length" property of partially
  8772. * applied functions.
  8773. *
  8774. * @static
  8775. * @memberOf _
  8776. * @category Function
  8777. * @param {Function} func The function to partially apply arguments to.
  8778. * @param {...*} [partials] The arguments to be partially applied.
  8779. * @returns {Function} Returns the new partially applied function.
  8780. * @example
  8781. *
  8782. * var greet = function(greeting, name) {
  8783. * return greeting + ' ' + name;
  8784. * };
  8785. *
  8786. * var greetFred = _.partialRight(greet, 'fred');
  8787. * greetFred('hi');
  8788. * // => 'hi fred'
  8789. *
  8790. * // Partially applied with placeholders.
  8791. * var sayHelloTo = _.partialRight(greet, 'hello', _);
  8792. * sayHelloTo('fred');
  8793. * // => 'hello fred'
  8794. */
  8795. var partialRight = rest(function(func, partials) {
  8796. var holders = replaceHolders(partials, getPlaceholder(partialRight));
  8797. return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders);
  8798. });
  8799. /**
  8800. * Creates a function that invokes `func` with arguments arranged according
  8801. * to the specified indexes where the argument value at the first index is
  8802. * provided as the first argument, the argument value at the second index is
  8803. * provided as the second argument, and so on.
  8804. *
  8805. * @static
  8806. * @memberOf _
  8807. * @category Function
  8808. * @param {Function} func The function to rearrange arguments for.
  8809. * @param {...(number|number[])} indexes The arranged argument indexes,
  8810. * specified individually or in arrays.
  8811. * @returns {Function} Returns the new function.
  8812. * @example
  8813. *
  8814. * var rearged = _.rearg(function(a, b, c) {
  8815. * return [a, b, c];
  8816. * }, 2, 0, 1);
  8817. *
  8818. * rearged('b', 'c', 'a')
  8819. * // => ['a', 'b', 'c']
  8820. */
  8821. var rearg = rest(function(func, indexes) {
  8822. return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1));
  8823. });
  8824. /**
  8825. * Creates a function that invokes `func` with the `this` binding of the
  8826. * created function and arguments from `start` and beyond provided as an array.
  8827. *
  8828. * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters).
  8829. *
  8830. * @static
  8831. * @memberOf _
  8832. * @category Function
  8833. * @param {Function} func The function to apply a rest parameter to.
  8834. * @param {number} [start=func.length-1] The start position of the rest parameter.
  8835. * @returns {Function} Returns the new function.
  8836. * @example
  8837. *
  8838. * var say = _.rest(function(what, names) {
  8839. * return what + ' ' + _.initial(names).join(', ') +
  8840. * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
  8841. * });
  8842. *
  8843. * say('hello', 'fred', 'barney', 'pebbles');
  8844. * // => 'hello fred, barney, & pebbles'
  8845. */
  8846. function rest(func, start) {
  8847. if (typeof func != 'function') {
  8848. throw new TypeError(FUNC_ERROR_TEXT);
  8849. }
  8850. start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0);
  8851. return function() {
  8852. var args = arguments,
  8853. index = -1,
  8854. length = nativeMax(args.length - start, 0),
  8855. array = Array(length);
  8856. while (++index < length) {
  8857. array[index] = args[start + index];
  8858. }
  8859. switch (start) {
  8860. case 0: return func.call(this, array);
  8861. case 1: return func.call(this, args[0], array);
  8862. case 2: return func.call(this, args[0], args[1], array);
  8863. }
  8864. var otherArgs = Array(start + 1);
  8865. index = -1;
  8866. while (++index < start) {
  8867. otherArgs[index] = args[index];
  8868. }
  8869. otherArgs[start] = array;
  8870. return apply(func, this, otherArgs);
  8871. };
  8872. }
  8873. /**
  8874. * Creates a function that invokes `func` with the `this` binding of the created
  8875. * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
  8876. *
  8877. * **Note:** This method is based on the [spread operator](https://mdn.io/spread_operator).
  8878. *
  8879. * @static
  8880. * @memberOf _
  8881. * @category Function
  8882. * @param {Function} func The function to spread arguments over.
  8883. * @param {number} [start=0] The start position of the spread.
  8884. * @returns {Function} Returns the new function.
  8885. * @example
  8886. *
  8887. * var say = _.spread(function(who, what) {
  8888. * return who + ' says ' + what;
  8889. * });
  8890. *
  8891. * say(['fred', 'hello']);
  8892. * // => 'fred says hello'
  8893. *
  8894. * var numbers = Promise.all([
  8895. * Promise.resolve(40),
  8896. * Promise.resolve(36)
  8897. * ]);
  8898. *
  8899. * numbers.then(_.spread(function(x, y) {
  8900. * return x + y;
  8901. * }));
  8902. * // => a Promise of 76
  8903. */
  8904. function spread(func, start) {
  8905. if (typeof func != 'function') {
  8906. throw new TypeError(FUNC_ERROR_TEXT);
  8907. }
  8908. start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
  8909. return rest(function(args) {
  8910. var array = args[start],
  8911. otherArgs = args.slice(0, start);
  8912. if (array) {
  8913. arrayPush(otherArgs, array);
  8914. }
  8915. return apply(func, this, otherArgs);
  8916. });
  8917. }
  8918. /**
  8919. * Creates a throttled function that only invokes `func` at most once per
  8920. * every `wait` milliseconds. The throttled function comes with a `cancel`
  8921. * method to cancel delayed `func` invocations and a `flush` method to
  8922. * immediately invoke them. Provide an options object to indicate whether
  8923. * `func` should be invoked on the leading and/or trailing edge of the `wait`
  8924. * timeout. The `func` is invoked with the last arguments provided to the
  8925. * throttled function. Subsequent calls to the throttled function return the
  8926. * result of the last `func` invocation.
  8927. *
  8928. * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
  8929. * on the trailing edge of the timeout only if the throttled function is
  8930. * invoked more than once during the `wait` timeout.
  8931. *
  8932. * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
  8933. * for details over the differences between `_.throttle` and `_.debounce`.
  8934. *
  8935. * @static
  8936. * @memberOf _
  8937. * @category Function
  8938. * @param {Function} func The function to throttle.
  8939. * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
  8940. * @param {Object} [options] The options object.
  8941. * @param {boolean} [options.leading=true] Specify invoking on the leading
  8942. * edge of the timeout.
  8943. * @param {boolean} [options.trailing=true] Specify invoking on the trailing
  8944. * edge of the timeout.
  8945. * @returns {Function} Returns the new throttled function.
  8946. * @example
  8947. *
  8948. * // Avoid excessively updating the position while scrolling.
  8949. * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
  8950. *
  8951. * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
  8952. * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
  8953. * jQuery(element).on('click', throttled);
  8954. *
  8955. * // Cancel the trailing throttled invocation.
  8956. * jQuery(window).on('popstate', throttled.cancel);
  8957. */
  8958. function throttle(func, wait, options) {
  8959. var leading = true,
  8960. trailing = true;
  8961. if (typeof func != 'function') {
  8962. throw new TypeError(FUNC_ERROR_TEXT);
  8963. }
  8964. if (isObject(options)) {
  8965. leading = 'leading' in options ? !!options.leading : leading;
  8966. trailing = 'trailing' in options ? !!options.trailing : trailing;
  8967. }
  8968. return debounce(func, wait, {
  8969. 'leading': leading,
  8970. 'maxWait': wait,
  8971. 'trailing': trailing
  8972. });
  8973. }
  8974. /**
  8975. * Creates a function that accepts up to one argument, ignoring any
  8976. * additional arguments.
  8977. *
  8978. * @static
  8979. * @memberOf _
  8980. * @category Function
  8981. * @param {Function} func The function to cap arguments for.
  8982. * @returns {Function} Returns the new function.
  8983. * @example
  8984. *
  8985. * _.map(['6', '8', '10'], _.unary(parseInt));
  8986. * // => [6, 8, 10]
  8987. */
  8988. function unary(func) {
  8989. return ary(func, 1);
  8990. }
  8991. /**
  8992. * Creates a function that provides `value` to the wrapper function as its
  8993. * first argument. Any additional arguments provided to the function are
  8994. * appended to those provided to the wrapper function. The wrapper is invoked
  8995. * with the `this` binding of the created function.
  8996. *
  8997. * @static
  8998. * @memberOf _
  8999. * @category Function
  9000. * @param {*} value The value to wrap.
  9001. * @param {Function} [wrapper=identity] The wrapper function.
  9002. * @returns {Function} Returns the new function.
  9003. * @example
  9004. *
  9005. * var p = _.wrap(_.escape, function(func, text) {
  9006. * return '<p>' + func(text) + '</p>';
  9007. * });
  9008. *
  9009. * p('fred, barney, & pebbles');
  9010. * // => '<p>fred, barney, &amp; pebbles</p>'
  9011. */
  9012. function wrap(value, wrapper) {
  9013. wrapper = wrapper == null ? identity : wrapper;
  9014. return partial(wrapper, value);
  9015. }
  9016. /*------------------------------------------------------------------------*/
  9017. /**
  9018. * Casts `value` as an array if it's not one.
  9019. *
  9020. * @static
  9021. * @memberOf _
  9022. * @category Lang
  9023. * @param {*} value The value to inspect.
  9024. * @returns {Array} Returns the cast array.
  9025. * @example
  9026. *
  9027. * _.castArray(1);
  9028. * // => [1]
  9029. *
  9030. * _.castArray({ 'a': 1 });
  9031. * // => [{ 'a': 1 }]
  9032. *
  9033. * _.castArray('abc');
  9034. * // => ['abc']
  9035. *
  9036. * _.castArray(null);
  9037. * // => [null]
  9038. *
  9039. * _.castArray(undefined);
  9040. * // => [undefined]
  9041. *
  9042. * _.castArray();
  9043. * // => []
  9044. *
  9045. * var array = [1, 2, 3];
  9046. * console.log(_.castArray(array) === array);
  9047. * // => true
  9048. */
  9049. function castArray() {
  9050. if (!arguments.length) {
  9051. return [];
  9052. }
  9053. var value = arguments[0];
  9054. return isArray(value) ? value : [value];
  9055. }
  9056. /**
  9057. * Creates a shallow clone of `value`.
  9058. *
  9059. * **Note:** This method is loosely based on the
  9060. * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
  9061. * and supports cloning arrays, array buffers, booleans, date objects, maps,
  9062. * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
  9063. * arrays. The own enumerable properties of `arguments` objects are cloned
  9064. * as plain objects. An empty object is returned for uncloneable values such
  9065. * as error objects, functions, DOM nodes, and WeakMaps.
  9066. *
  9067. * @static
  9068. * @memberOf _
  9069. * @category Lang
  9070. * @param {*} value The value to clone.
  9071. * @returns {*} Returns the cloned value.
  9072. * @example
  9073. *
  9074. * var objects = [{ 'a': 1 }, { 'b': 2 }];
  9075. *
  9076. * var shallow = _.clone(objects);
  9077. * console.log(shallow[0] === objects[0]);
  9078. * // => true
  9079. */
  9080. function clone(value) {
  9081. return baseClone(value);
  9082. }
  9083. /**
  9084. * This method is like `_.clone` except that it accepts `customizer` which
  9085. * is invoked to produce the cloned value. If `customizer` returns `undefined`
  9086. * cloning is handled by the method instead. The `customizer` is invoked with
  9087. * up to four arguments; (value [, index|key, object, stack]).
  9088. *
  9089. * @static
  9090. * @memberOf _
  9091. * @category Lang
  9092. * @param {*} value The value to clone.
  9093. * @param {Function} [customizer] The function to customize cloning.
  9094. * @returns {*} Returns the cloned value.
  9095. * @example
  9096. *
  9097. * function customizer(value) {
  9098. * if (_.isElement(value)) {
  9099. * return value.cloneNode(false);
  9100. * }
  9101. * }
  9102. *
  9103. * var el = _.cloneWith(document.body, customizer);
  9104. *
  9105. * console.log(el === document.body);
  9106. * // => false
  9107. * console.log(el.nodeName);
  9108. * // => 'BODY'
  9109. * console.log(el.childNodes.length);
  9110. * // => 0
  9111. */
  9112. function cloneWith(value, customizer) {
  9113. return baseClone(value, false, customizer);
  9114. }
  9115. /**
  9116. * This method is like `_.clone` except that it recursively clones `value`.
  9117. *
  9118. * @static
  9119. * @memberOf _
  9120. * @category Lang
  9121. * @param {*} value The value to recursively clone.
  9122. * @returns {*} Returns the deep cloned value.
  9123. * @example
  9124. *
  9125. * var objects = [{ 'a': 1 }, { 'b': 2 }];
  9126. *
  9127. * var deep = _.cloneDeep(objects);
  9128. * console.log(deep[0] === objects[0]);
  9129. * // => false
  9130. */
  9131. function cloneDeep(value) {
  9132. return baseClone(value, true);
  9133. }
  9134. /**
  9135. * This method is like `_.cloneWith` except that it recursively clones `value`.
  9136. *
  9137. * @static
  9138. * @memberOf _
  9139. * @category Lang
  9140. * @param {*} value The value to recursively clone.
  9141. * @param {Function} [customizer] The function to customize cloning.
  9142. * @returns {*} Returns the deep cloned value.
  9143. * @example
  9144. *
  9145. * function customizer(value) {
  9146. * if (_.isElement(value)) {
  9147. * return value.cloneNode(true);
  9148. * }
  9149. * }
  9150. *
  9151. * var el = _.cloneDeepWith(document.body, customizer);
  9152. *
  9153. * console.log(el === document.body);
  9154. * // => false
  9155. * console.log(el.nodeName);
  9156. * // => 'BODY'
  9157. * console.log(el.childNodes.length);
  9158. * // => 20
  9159. */
  9160. function cloneDeepWith(value, customizer) {
  9161. return baseClone(value, true, customizer);
  9162. }
  9163. /**
  9164. * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
  9165. * comparison between two values to determine if they are equivalent.
  9166. *
  9167. * @static
  9168. * @memberOf _
  9169. * @category Lang
  9170. * @param {*} value The value to compare.
  9171. * @param {*} other The other value to compare.
  9172. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
  9173. * @example
  9174. *
  9175. * var object = { 'user': 'fred' };
  9176. * var other = { 'user': 'fred' };
  9177. *
  9178. * _.eq(object, object);
  9179. * // => true
  9180. *
  9181. * _.eq(object, other);
  9182. * // => false
  9183. *
  9184. * _.eq('a', 'a');
  9185. * // => true
  9186. *
  9187. * _.eq('a', Object('a'));
  9188. * // => false
  9189. *
  9190. * _.eq(NaN, NaN);
  9191. * // => true
  9192. */
  9193. function eq(value, other) {
  9194. return value === other || (value !== value && other !== other);
  9195. }
  9196. /**
  9197. * Checks if `value` is greater than `other`.
  9198. *
  9199. * @static
  9200. * @memberOf _
  9201. * @category Lang
  9202. * @param {*} value The value to compare.
  9203. * @param {*} other The other value to compare.
  9204. * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.
  9205. * @example
  9206. *
  9207. * _.gt(3, 1);
  9208. * // => true
  9209. *
  9210. * _.gt(3, 3);
  9211. * // => false
  9212. *
  9213. * _.gt(1, 3);
  9214. * // => false
  9215. */
  9216. function gt(value, other) {
  9217. return value > other;
  9218. }
  9219. /**
  9220. * Checks if `value` is greater than or equal to `other`.
  9221. *
  9222. * @static
  9223. * @memberOf _
  9224. * @category Lang
  9225. * @param {*} value The value to compare.
  9226. * @param {*} other The other value to compare.
  9227. * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`.
  9228. * @example
  9229. *
  9230. * _.gte(3, 1);
  9231. * // => true
  9232. *
  9233. * _.gte(3, 3);
  9234. * // => true
  9235. *
  9236. * _.gte(1, 3);
  9237. * // => false
  9238. */
  9239. function gte(value, other) {
  9240. return value >= other;
  9241. }
  9242. /**
  9243. * Checks if `value` is likely an `arguments` object.
  9244. *
  9245. * @static
  9246. * @memberOf _
  9247. * @category Lang
  9248. * @param {*} value The value to check.
  9249. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9250. * @example
  9251. *
  9252. * _.isArguments(function() { return arguments; }());
  9253. * // => true
  9254. *
  9255. * _.isArguments([1, 2, 3]);
  9256. * // => false
  9257. */
  9258. function isArguments(value) {
  9259. // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
  9260. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
  9261. (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
  9262. }
  9263. /**
  9264. * Checks if `value` is classified as an `Array` object.
  9265. *
  9266. * @static
  9267. * @memberOf _
  9268. * @type {Function}
  9269. * @category Lang
  9270. * @param {*} value The value to check.
  9271. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9272. * @example
  9273. *
  9274. * _.isArray([1, 2, 3]);
  9275. * // => true
  9276. *
  9277. * _.isArray(document.body.children);
  9278. * // => false
  9279. *
  9280. * _.isArray('abc');
  9281. * // => false
  9282. *
  9283. * _.isArray(_.noop);
  9284. * // => false
  9285. */
  9286. var isArray = Array.isArray;
  9287. /**
  9288. * Checks if `value` is classified as an `ArrayBuffer` object.
  9289. *
  9290. * @static
  9291. * @memberOf _
  9292. * @category Lang
  9293. * @param {*} value The value to check.
  9294. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9295. * @example
  9296. *
  9297. * _.isArrayBuffer(new ArrayBuffer(2));
  9298. * // => true
  9299. *
  9300. * _.isArrayBuffer(new Array(2));
  9301. * // => false
  9302. */
  9303. function isArrayBuffer(value) {
  9304. return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
  9305. }
  9306. /**
  9307. * Checks if `value` is array-like. A value is considered array-like if it's
  9308. * not a function and has a `value.length` that's an integer greater than or
  9309. * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
  9310. *
  9311. * @static
  9312. * @memberOf _
  9313. * @category Lang
  9314. * @param {*} value The value to check.
  9315. * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
  9316. * @example
  9317. *
  9318. * _.isArrayLike([1, 2, 3]);
  9319. * // => true
  9320. *
  9321. * _.isArrayLike(document.body.children);
  9322. * // => true
  9323. *
  9324. * _.isArrayLike('abc');
  9325. * // => true
  9326. *
  9327. * _.isArrayLike(_.noop);
  9328. * // => false
  9329. */
  9330. function isArrayLike(value) {
  9331. return value != null &&
  9332. !(typeof value == 'function' && isFunction(value)) && isLength(getLength(value));
  9333. }
  9334. /**
  9335. * This method is like `_.isArrayLike` except that it also checks if `value`
  9336. * is an object.
  9337. *
  9338. * @static
  9339. * @memberOf _
  9340. * @category Lang
  9341. * @param {*} value The value to check.
  9342. * @returns {boolean} Returns `true` if `value` is an array-like object, else `false`.
  9343. * @example
  9344. *
  9345. * _.isArrayLikeObject([1, 2, 3]);
  9346. * // => true
  9347. *
  9348. * _.isArrayLikeObject(document.body.children);
  9349. * // => true
  9350. *
  9351. * _.isArrayLikeObject('abc');
  9352. * // => false
  9353. *
  9354. * _.isArrayLikeObject(_.noop);
  9355. * // => false
  9356. */
  9357. function isArrayLikeObject(value) {
  9358. return isObjectLike(value) && isArrayLike(value);
  9359. }
  9360. /**
  9361. * Checks if `value` is classified as a boolean primitive or object.
  9362. *
  9363. * @static
  9364. * @memberOf _
  9365. * @category Lang
  9366. * @param {*} value The value to check.
  9367. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9368. * @example
  9369. *
  9370. * _.isBoolean(false);
  9371. * // => true
  9372. *
  9373. * _.isBoolean(null);
  9374. * // => false
  9375. */
  9376. function isBoolean(value) {
  9377. return value === true || value === false ||
  9378. (isObjectLike(value) && objectToString.call(value) == boolTag);
  9379. }
  9380. /**
  9381. * Checks if `value` is a buffer.
  9382. *
  9383. * @static
  9384. * @memberOf _
  9385. * @category Lang
  9386. * @param {*} value The value to check.
  9387. * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
  9388. * @example
  9389. *
  9390. * _.isBuffer(new Buffer(2));
  9391. * // => true
  9392. *
  9393. * _.isBuffer(new Uint8Array(2));
  9394. * // => false
  9395. */
  9396. var isBuffer = !Buffer ? constant(false) : function(value) {
  9397. return value instanceof Buffer;
  9398. };
  9399. /**
  9400. * Checks if `value` is classified as a `Date` object.
  9401. *
  9402. * @static
  9403. * @memberOf _
  9404. * @category Lang
  9405. * @param {*} value The value to check.
  9406. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9407. * @example
  9408. *
  9409. * _.isDate(new Date);
  9410. * // => true
  9411. *
  9412. * _.isDate('Mon April 23 2012');
  9413. * // => false
  9414. */
  9415. function isDate(value) {
  9416. return isObjectLike(value) && objectToString.call(value) == dateTag;
  9417. }
  9418. /**
  9419. * Checks if `value` is likely a DOM element.
  9420. *
  9421. * @static
  9422. * @memberOf _
  9423. * @category Lang
  9424. * @param {*} value The value to check.
  9425. * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
  9426. * @example
  9427. *
  9428. * _.isElement(document.body);
  9429. * // => true
  9430. *
  9431. * _.isElement('<body>');
  9432. * // => false
  9433. */
  9434. function isElement(value) {
  9435. return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
  9436. }
  9437. /**
  9438. * Checks if `value` is empty. A value is considered empty unless it's an
  9439. * `arguments` object, array, string, or jQuery-like collection with a length
  9440. * greater than `0` or an object with own enumerable properties.
  9441. *
  9442. * @static
  9443. * @memberOf _
  9444. * @category Lang
  9445. * @param {Array|Object|string} value The value to inspect.
  9446. * @returns {boolean} Returns `true` if `value` is empty, else `false`.
  9447. * @example
  9448. *
  9449. * _.isEmpty(null);
  9450. * // => true
  9451. *
  9452. * _.isEmpty(true);
  9453. * // => true
  9454. *
  9455. * _.isEmpty(1);
  9456. * // => true
  9457. *
  9458. * _.isEmpty([1, 2, 3]);
  9459. * // => false
  9460. *
  9461. * _.isEmpty({ 'a': 1 });
  9462. * // => false
  9463. */
  9464. function isEmpty(value) {
  9465. if (isArrayLike(value) &&
  9466. (isArray(value) || isString(value) ||
  9467. isFunction(value.splice) || isArguments(value))) {
  9468. return !value.length;
  9469. }
  9470. for (var key in value) {
  9471. if (hasOwnProperty.call(value, key)) {
  9472. return false;
  9473. }
  9474. }
  9475. return true;
  9476. }
  9477. /**
  9478. * Performs a deep comparison between two values to determine if they are
  9479. * equivalent.
  9480. *
  9481. * **Note:** This method supports comparing arrays, array buffers, booleans,
  9482. * date objects, error objects, maps, numbers, `Object` objects, regexes,
  9483. * sets, strings, symbols, and typed arrays. `Object` objects are compared
  9484. * by their own, not inherited, enumerable properties. Functions and DOM
  9485. * nodes are **not** supported.
  9486. *
  9487. * @static
  9488. * @memberOf _
  9489. * @category Lang
  9490. * @param {*} value The value to compare.
  9491. * @param {*} other The other value to compare.
  9492. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
  9493. * @example
  9494. *
  9495. * var object = { 'user': 'fred' };
  9496. * var other = { 'user': 'fred' };
  9497. *
  9498. * _.isEqual(object, other);
  9499. * // => true
  9500. *
  9501. * object === other;
  9502. * // => false
  9503. */
  9504. function isEqual(value, other) {
  9505. return baseIsEqual(value, other);
  9506. }
  9507. /**
  9508. * This method is like `_.isEqual` except that it accepts `customizer` which
  9509. * is invoked to compare values. If `customizer` returns `undefined` comparisons
  9510. * are handled by the method instead. The `customizer` is invoked with up to
  9511. * six arguments: (objValue, othValue [, index|key, object, other, stack]).
  9512. *
  9513. * @static
  9514. * @memberOf _
  9515. * @category Lang
  9516. * @param {*} value The value to compare.
  9517. * @param {*} other The other value to compare.
  9518. * @param {Function} [customizer] The function to customize comparisons.
  9519. * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
  9520. * @example
  9521. *
  9522. * function isGreeting(value) {
  9523. * return /^h(?:i|ello)$/.test(value);
  9524. * }
  9525. *
  9526. * function customizer(objValue, othValue) {
  9527. * if (isGreeting(objValue) && isGreeting(othValue)) {
  9528. * return true;
  9529. * }
  9530. * }
  9531. *
  9532. * var array = ['hello', 'goodbye'];
  9533. * var other = ['hi', 'goodbye'];
  9534. *
  9535. * _.isEqualWith(array, other, customizer);
  9536. * // => true
  9537. */
  9538. function isEqualWith(value, other, customizer) {
  9539. customizer = typeof customizer == 'function' ? customizer : undefined;
  9540. var result = customizer ? customizer(value, other) : undefined;
  9541. return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
  9542. }
  9543. /**
  9544. * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
  9545. * `SyntaxError`, `TypeError`, or `URIError` object.
  9546. *
  9547. * @static
  9548. * @memberOf _
  9549. * @category Lang
  9550. * @param {*} value The value to check.
  9551. * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
  9552. * @example
  9553. *
  9554. * _.isError(new Error);
  9555. * // => true
  9556. *
  9557. * _.isError(Error);
  9558. * // => false
  9559. */
  9560. function isError(value) {
  9561. if (!isObjectLike(value)) {
  9562. return false;
  9563. }
  9564. return (objectToString.call(value) == errorTag) ||
  9565. (typeof value.message == 'string' && typeof value.name == 'string');
  9566. }
  9567. /**
  9568. * Checks if `value` is a finite primitive number.
  9569. *
  9570. * **Note:** This method is based on [`Number.isFinite`](https://mdn.io/Number/isFinite).
  9571. *
  9572. * @static
  9573. * @memberOf _
  9574. * @category Lang
  9575. * @param {*} value The value to check.
  9576. * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
  9577. * @example
  9578. *
  9579. * _.isFinite(3);
  9580. * // => true
  9581. *
  9582. * _.isFinite(Number.MAX_VALUE);
  9583. * // => true
  9584. *
  9585. * _.isFinite(3.14);
  9586. * // => true
  9587. *
  9588. * _.isFinite(Infinity);
  9589. * // => false
  9590. */
  9591. function isFinite(value) {
  9592. return typeof value == 'number' && nativeIsFinite(value);
  9593. }
  9594. /**
  9595. * Checks if `value` is classified as a `Function` object.
  9596. *
  9597. * @static
  9598. * @memberOf _
  9599. * @category Lang
  9600. * @param {*} value The value to check.
  9601. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9602. * @example
  9603. *
  9604. * _.isFunction(_);
  9605. * // => true
  9606. *
  9607. * _.isFunction(/abc/);
  9608. * // => false
  9609. */
  9610. function isFunction(value) {
  9611. // The use of `Object#toString` avoids issues with the `typeof` operator
  9612. // in Safari 8 which returns 'object' for typed array constructors, and
  9613. // PhantomJS 1.9 which returns 'function' for `NodeList` instances.
  9614. var tag = isObject(value) ? objectToString.call(value) : '';
  9615. return tag == funcTag || tag == genTag;
  9616. }
  9617. /**
  9618. * Checks if `value` is an integer.
  9619. *
  9620. * **Note:** This method is based on [`Number.isInteger`](https://mdn.io/Number/isInteger).
  9621. *
  9622. * @static
  9623. * @memberOf _
  9624. * @category Lang
  9625. * @param {*} value The value to check.
  9626. * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
  9627. * @example
  9628. *
  9629. * _.isInteger(3);
  9630. * // => true
  9631. *
  9632. * _.isInteger(Number.MIN_VALUE);
  9633. * // => false
  9634. *
  9635. * _.isInteger(Infinity);
  9636. * // => false
  9637. *
  9638. * _.isInteger('3');
  9639. * // => false
  9640. */
  9641. function isInteger(value) {
  9642. return typeof value == 'number' && value == toInteger(value);
  9643. }
  9644. /**
  9645. * Checks if `value` is a valid array-like length.
  9646. *
  9647. * **Note:** This function is loosely based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
  9648. *
  9649. * @static
  9650. * @memberOf _
  9651. * @category Lang
  9652. * @param {*} value The value to check.
  9653. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
  9654. * @example
  9655. *
  9656. * _.isLength(3);
  9657. * // => true
  9658. *
  9659. * _.isLength(Number.MIN_VALUE);
  9660. * // => false
  9661. *
  9662. * _.isLength(Infinity);
  9663. * // => false
  9664. *
  9665. * _.isLength('3');
  9666. * // => false
  9667. */
  9668. function isLength(value) {
  9669. return typeof value == 'number' &&
  9670. value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  9671. }
  9672. /**
  9673. * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
  9674. * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
  9675. *
  9676. * @static
  9677. * @memberOf _
  9678. * @category Lang
  9679. * @param {*} value The value to check.
  9680. * @returns {boolean} Returns `true` if `value` is an object, else `false`.
  9681. * @example
  9682. *
  9683. * _.isObject({});
  9684. * // => true
  9685. *
  9686. * _.isObject([1, 2, 3]);
  9687. * // => true
  9688. *
  9689. * _.isObject(_.noop);
  9690. * // => true
  9691. *
  9692. * _.isObject(null);
  9693. * // => false
  9694. */
  9695. function isObject(value) {
  9696. var type = typeof value;
  9697. return !!value && (type == 'object' || type == 'function');
  9698. }
  9699. /**
  9700. * Checks if `value` is object-like. A value is object-like if it's not `null`
  9701. * and has a `typeof` result of "object".
  9702. *
  9703. * @static
  9704. * @memberOf _
  9705. * @category Lang
  9706. * @param {*} value The value to check.
  9707. * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
  9708. * @example
  9709. *
  9710. * _.isObjectLike({});
  9711. * // => true
  9712. *
  9713. * _.isObjectLike([1, 2, 3]);
  9714. * // => true
  9715. *
  9716. * _.isObjectLike(_.noop);
  9717. * // => false
  9718. *
  9719. * _.isObjectLike(null);
  9720. * // => false
  9721. */
  9722. function isObjectLike(value) {
  9723. return !!value && typeof value == 'object';
  9724. }
  9725. /**
  9726. * Checks if `value` is classified as a `Map` object.
  9727. *
  9728. * @static
  9729. * @memberOf _
  9730. * @category Lang
  9731. * @param {*} value The value to check.
  9732. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9733. * @example
  9734. *
  9735. * _.isMap(new Map);
  9736. * // => true
  9737. *
  9738. * _.isMap(new WeakMap);
  9739. * // => false
  9740. */
  9741. function isMap(value) {
  9742. return isObjectLike(value) && getTag(value) == mapTag;
  9743. }
  9744. /**
  9745. * Performs a partial deep comparison between `object` and `source` to
  9746. * determine if `object` contains equivalent property values. This method is
  9747. * equivalent to a `_.matches` function when `source` is partially applied.
  9748. *
  9749. * **Note:** This method supports comparing the same values as `_.isEqual`.
  9750. *
  9751. * @static
  9752. * @memberOf _
  9753. * @category Lang
  9754. * @param {Object} object The object to inspect.
  9755. * @param {Object} source The object of property values to match.
  9756. * @returns {boolean} Returns `true` if `object` is a match, else `false`.
  9757. * @example
  9758. *
  9759. * var object = { 'user': 'fred', 'age': 40 };
  9760. *
  9761. * _.isMatch(object, { 'age': 40 });
  9762. * // => true
  9763. *
  9764. * _.isMatch(object, { 'age': 36 });
  9765. * // => false
  9766. */
  9767. function isMatch(object, source) {
  9768. return object === source || baseIsMatch(object, source, getMatchData(source));
  9769. }
  9770. /**
  9771. * This method is like `_.isMatch` except that it accepts `customizer` which
  9772. * is invoked to compare values. If `customizer` returns `undefined` comparisons
  9773. * are handled by the method instead. The `customizer` is invoked with five
  9774. * arguments: (objValue, srcValue, index|key, object, source).
  9775. *
  9776. * @static
  9777. * @memberOf _
  9778. * @category Lang
  9779. * @param {Object} object The object to inspect.
  9780. * @param {Object} source The object of property values to match.
  9781. * @param {Function} [customizer] The function to customize comparisons.
  9782. * @returns {boolean} Returns `true` if `object` is a match, else `false`.
  9783. * @example
  9784. *
  9785. * function isGreeting(value) {
  9786. * return /^h(?:i|ello)$/.test(value);
  9787. * }
  9788. *
  9789. * function customizer(objValue, srcValue) {
  9790. * if (isGreeting(objValue) && isGreeting(srcValue)) {
  9791. * return true;
  9792. * }
  9793. * }
  9794. *
  9795. * var object = { 'greeting': 'hello' };
  9796. * var source = { 'greeting': 'hi' };
  9797. *
  9798. * _.isMatchWith(object, source, customizer);
  9799. * // => true
  9800. */
  9801. function isMatchWith(object, source, customizer) {
  9802. customizer = typeof customizer == 'function' ? customizer : undefined;
  9803. return baseIsMatch(object, source, getMatchData(source), customizer);
  9804. }
  9805. /**
  9806. * Checks if `value` is `NaN`.
  9807. *
  9808. * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
  9809. * which returns `true` for `undefined` and other non-numeric values.
  9810. *
  9811. * @static
  9812. * @memberOf _
  9813. * @category Lang
  9814. * @param {*} value The value to check.
  9815. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
  9816. * @example
  9817. *
  9818. * _.isNaN(NaN);
  9819. * // => true
  9820. *
  9821. * _.isNaN(new Number(NaN));
  9822. * // => true
  9823. *
  9824. * isNaN(undefined);
  9825. * // => true
  9826. *
  9827. * _.isNaN(undefined);
  9828. * // => false
  9829. */
  9830. function isNaN(value) {
  9831. // An `NaN` primitive is the only value that is not equal to itself.
  9832. // Perform the `toStringTag` check first to avoid errors with some ActiveX objects in IE.
  9833. return isNumber(value) && value != +value;
  9834. }
  9835. /**
  9836. * Checks if `value` is a native function.
  9837. *
  9838. * @static
  9839. * @memberOf _
  9840. * @category Lang
  9841. * @param {*} value The value to check.
  9842. * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
  9843. * @example
  9844. *
  9845. * _.isNative(Array.prototype.push);
  9846. * // => true
  9847. *
  9848. * _.isNative(_);
  9849. * // => false
  9850. */
  9851. function isNative(value) {
  9852. if (value == null) {
  9853. return false;
  9854. }
  9855. if (isFunction(value)) {
  9856. return reIsNative.test(funcToString.call(value));
  9857. }
  9858. return isObjectLike(value) &&
  9859. (isHostObject(value) ? reIsNative : reIsHostCtor).test(value);
  9860. }
  9861. /**
  9862. * Checks if `value` is `null`.
  9863. *
  9864. * @static
  9865. * @memberOf _
  9866. * @category Lang
  9867. * @param {*} value The value to check.
  9868. * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
  9869. * @example
  9870. *
  9871. * _.isNull(null);
  9872. * // => true
  9873. *
  9874. * _.isNull(void 0);
  9875. * // => false
  9876. */
  9877. function isNull(value) {
  9878. return value === null;
  9879. }
  9880. /**
  9881. * Checks if `value` is `null` or `undefined`.
  9882. *
  9883. * @static
  9884. * @memberOf _
  9885. * @category Lang
  9886. * @param {*} value The value to check.
  9887. * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
  9888. * @example
  9889. *
  9890. * _.isNil(null);
  9891. * // => true
  9892. *
  9893. * _.isNil(void 0);
  9894. * // => true
  9895. *
  9896. * _.isNil(NaN);
  9897. * // => false
  9898. */
  9899. function isNil(value) {
  9900. return value == null;
  9901. }
  9902. /**
  9903. * Checks if `value` is classified as a `Number` primitive or object.
  9904. *
  9905. * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
  9906. * as numbers, use the `_.isFinite` method.
  9907. *
  9908. * @static
  9909. * @memberOf _
  9910. * @category Lang
  9911. * @param {*} value The value to check.
  9912. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9913. * @example
  9914. *
  9915. * _.isNumber(3);
  9916. * // => true
  9917. *
  9918. * _.isNumber(Number.MIN_VALUE);
  9919. * // => true
  9920. *
  9921. * _.isNumber(Infinity);
  9922. * // => true
  9923. *
  9924. * _.isNumber('3');
  9925. * // => false
  9926. */
  9927. function isNumber(value) {
  9928. return typeof value == 'number' ||
  9929. (isObjectLike(value) && objectToString.call(value) == numberTag);
  9930. }
  9931. /**
  9932. * Checks if `value` is a plain object, that is, an object created by the
  9933. * `Object` constructor or one with a `[[Prototype]]` of `null`.
  9934. *
  9935. * @static
  9936. * @memberOf _
  9937. * @category Lang
  9938. * @param {*} value The value to check.
  9939. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
  9940. * @example
  9941. *
  9942. * function Foo() {
  9943. * this.a = 1;
  9944. * }
  9945. *
  9946. * _.isPlainObject(new Foo);
  9947. * // => false
  9948. *
  9949. * _.isPlainObject([1, 2, 3]);
  9950. * // => false
  9951. *
  9952. * _.isPlainObject({ 'x': 0, 'y': 0 });
  9953. * // => true
  9954. *
  9955. * _.isPlainObject(Object.create(null));
  9956. * // => true
  9957. */
  9958. function isPlainObject(value) {
  9959. if (!isObjectLike(value) ||
  9960. objectToString.call(value) != objectTag || isHostObject(value)) {
  9961. return false;
  9962. }
  9963. var proto = getPrototypeOf(value);
  9964. if (proto === null) {
  9965. return true;
  9966. }
  9967. var Ctor = proto.constructor;
  9968. return (typeof Ctor == 'function' &&
  9969. Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
  9970. }
  9971. /**
  9972. * Checks if `value` is classified as a `RegExp` object.
  9973. *
  9974. * @static
  9975. * @memberOf _
  9976. * @category Lang
  9977. * @param {*} value The value to check.
  9978. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  9979. * @example
  9980. *
  9981. * _.isRegExp(/abc/);
  9982. * // => true
  9983. *
  9984. * _.isRegExp('/abc/');
  9985. * // => false
  9986. */
  9987. function isRegExp(value) {
  9988. return isObject(value) && objectToString.call(value) == regexpTag;
  9989. }
  9990. /**
  9991. * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
  9992. * double precision number which isn't the result of a rounded unsafe integer.
  9993. *
  9994. * **Note:** This method is based on [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
  9995. *
  9996. * @static
  9997. * @memberOf _
  9998. * @category Lang
  9999. * @param {*} value The value to check.
  10000. * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
  10001. * @example
  10002. *
  10003. * _.isSafeInteger(3);
  10004. * // => true
  10005. *
  10006. * _.isSafeInteger(Number.MIN_VALUE);
  10007. * // => false
  10008. *
  10009. * _.isSafeInteger(Infinity);
  10010. * // => false
  10011. *
  10012. * _.isSafeInteger('3');
  10013. * // => false
  10014. */
  10015. function isSafeInteger(value) {
  10016. return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
  10017. }
  10018. /**
  10019. * Checks if `value` is classified as a `Set` object.
  10020. *
  10021. * @static
  10022. * @memberOf _
  10023. * @category Lang
  10024. * @param {*} value The value to check.
  10025. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10026. * @example
  10027. *
  10028. * _.isSet(new Set);
  10029. * // => true
  10030. *
  10031. * _.isSet(new WeakSet);
  10032. * // => false
  10033. */
  10034. function isSet(value) {
  10035. return isObjectLike(value) && getTag(value) == setTag;
  10036. }
  10037. /**
  10038. * Checks if `value` is classified as a `String` primitive or object.
  10039. *
  10040. * @static
  10041. * @memberOf _
  10042. * @category Lang
  10043. * @param {*} value The value to check.
  10044. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10045. * @example
  10046. *
  10047. * _.isString('abc');
  10048. * // => true
  10049. *
  10050. * _.isString(1);
  10051. * // => false
  10052. */
  10053. function isString(value) {
  10054. return typeof value == 'string' ||
  10055. (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
  10056. }
  10057. /**
  10058. * Checks if `value` is classified as a `Symbol` primitive or object.
  10059. *
  10060. * @static
  10061. * @memberOf _
  10062. * @category Lang
  10063. * @param {*} value The value to check.
  10064. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10065. * @example
  10066. *
  10067. * _.isSymbol(Symbol.iterator);
  10068. * // => true
  10069. *
  10070. * _.isSymbol('abc');
  10071. * // => false
  10072. */
  10073. function isSymbol(value) {
  10074. return typeof value == 'symbol' ||
  10075. (isObjectLike(value) && objectToString.call(value) == symbolTag);
  10076. }
  10077. /**
  10078. * Checks if `value` is classified as a typed array.
  10079. *
  10080. * @static
  10081. * @memberOf _
  10082. * @category Lang
  10083. * @param {*} value The value to check.
  10084. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10085. * @example
  10086. *
  10087. * _.isTypedArray(new Uint8Array);
  10088. * // => true
  10089. *
  10090. * _.isTypedArray([]);
  10091. * // => false
  10092. */
  10093. function isTypedArray(value) {
  10094. return isObjectLike(value) &&
  10095. isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
  10096. }
  10097. /**
  10098. * Checks if `value` is `undefined`.
  10099. *
  10100. * @static
  10101. * @memberOf _
  10102. * @category Lang
  10103. * @param {*} value The value to check.
  10104. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
  10105. * @example
  10106. *
  10107. * _.isUndefined(void 0);
  10108. * // => true
  10109. *
  10110. * _.isUndefined(null);
  10111. * // => false
  10112. */
  10113. function isUndefined(value) {
  10114. return value === undefined;
  10115. }
  10116. /**
  10117. * Checks if `value` is classified as a `WeakMap` object.
  10118. *
  10119. * @static
  10120. * @memberOf _
  10121. * @category Lang
  10122. * @param {*} value The value to check.
  10123. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10124. * @example
  10125. *
  10126. * _.isWeakMap(new WeakMap);
  10127. * // => true
  10128. *
  10129. * _.isWeakMap(new Map);
  10130. * // => false
  10131. */
  10132. function isWeakMap(value) {
  10133. return isObjectLike(value) && getTag(value) == weakMapTag;
  10134. }
  10135. /**
  10136. * Checks if `value` is classified as a `WeakSet` object.
  10137. *
  10138. * @static
  10139. * @memberOf _
  10140. * @category Lang
  10141. * @param {*} value The value to check.
  10142. * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
  10143. * @example
  10144. *
  10145. * _.isWeakSet(new WeakSet);
  10146. * // => true
  10147. *
  10148. * _.isWeakSet(new Set);
  10149. * // => false
  10150. */
  10151. function isWeakSet(value) {
  10152. return isObjectLike(value) && objectToString.call(value) == weakSetTag;
  10153. }
  10154. /**
  10155. * Checks if `value` is less than `other`.
  10156. *
  10157. * @static
  10158. * @memberOf _
  10159. * @category Lang
  10160. * @param {*} value The value to compare.
  10161. * @param {*} other The other value to compare.
  10162. * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
  10163. * @example
  10164. *
  10165. * _.lt(1, 3);
  10166. * // => true
  10167. *
  10168. * _.lt(3, 3);
  10169. * // => false
  10170. *
  10171. * _.lt(3, 1);
  10172. * // => false
  10173. */
  10174. function lt(value, other) {
  10175. return value < other;
  10176. }
  10177. /**
  10178. * Checks if `value` is less than or equal to `other`.
  10179. *
  10180. * @static
  10181. * @memberOf _
  10182. * @category Lang
  10183. * @param {*} value The value to compare.
  10184. * @param {*} other The other value to compare.
  10185. * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`.
  10186. * @example
  10187. *
  10188. * _.lte(1, 3);
  10189. * // => true
  10190. *
  10191. * _.lte(3, 3);
  10192. * // => true
  10193. *
  10194. * _.lte(3, 1);
  10195. * // => false
  10196. */
  10197. function lte(value, other) {
  10198. return value <= other;
  10199. }
  10200. /**
  10201. * Converts `value` to an array.
  10202. *
  10203. * @static
  10204. * @memberOf _
  10205. * @category Lang
  10206. * @param {*} value The value to convert.
  10207. * @returns {Array} Returns the converted array.
  10208. * @example
  10209. *
  10210. * _.toArray({ 'a': 1, 'b': 2 });
  10211. * // => [1, 2]
  10212. *
  10213. * _.toArray('abc');
  10214. * // => ['a', 'b', 'c']
  10215. *
  10216. * _.toArray(1);
  10217. * // => []
  10218. *
  10219. * _.toArray(null);
  10220. * // => []
  10221. */
  10222. function toArray(value) {
  10223. if (!value) {
  10224. return [];
  10225. }
  10226. if (isArrayLike(value)) {
  10227. return isString(value) ? stringToArray(value) : copyArray(value);
  10228. }
  10229. if (iteratorSymbol && value[iteratorSymbol]) {
  10230. return iteratorToArray(value[iteratorSymbol]());
  10231. }
  10232. var tag = getTag(value),
  10233. func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
  10234. return func(value);
  10235. }
  10236. /**
  10237. * Converts `value` to an integer.
  10238. *
  10239. * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
  10240. *
  10241. * @static
  10242. * @memberOf _
  10243. * @category Lang
  10244. * @param {*} value The value to convert.
  10245. * @returns {number} Returns the converted integer.
  10246. * @example
  10247. *
  10248. * _.toInteger(3);
  10249. * // => 3
  10250. *
  10251. * _.toInteger(Number.MIN_VALUE);
  10252. * // => 0
  10253. *
  10254. * _.toInteger(Infinity);
  10255. * // => 1.7976931348623157e+308
  10256. *
  10257. * _.toInteger('3');
  10258. * // => 3
  10259. */
  10260. function toInteger(value) {
  10261. if (!value) {
  10262. return value === 0 ? value : 0;
  10263. }
  10264. value = toNumber(value);
  10265. if (value === INFINITY || value === -INFINITY) {
  10266. var sign = (value < 0 ? -1 : 1);
  10267. return sign * MAX_INTEGER;
  10268. }
  10269. var remainder = value % 1;
  10270. return value === value ? (remainder ? value - remainder : value) : 0;
  10271. }
  10272. /**
  10273. * Converts `value` to an integer suitable for use as the length of an
  10274. * array-like object.
  10275. *
  10276. * **Note:** This method is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
  10277. *
  10278. * @static
  10279. * @memberOf _
  10280. * @category Lang
  10281. * @param {*} value The value to convert.
  10282. * @returns {number} Returns the converted integer.
  10283. * @example
  10284. *
  10285. * _.toLength(3);
  10286. * // => 3
  10287. *
  10288. * _.toLength(Number.MIN_VALUE);
  10289. * // => 0
  10290. *
  10291. * _.toLength(Infinity);
  10292. * // => 4294967295
  10293. *
  10294. * _.toLength('3');
  10295. * // => 3
  10296. */
  10297. function toLength(value) {
  10298. return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
  10299. }
  10300. /**
  10301. * Converts `value` to a number.
  10302. *
  10303. * @static
  10304. * @memberOf _
  10305. * @category Lang
  10306. * @param {*} value The value to process.
  10307. * @returns {number} Returns the number.
  10308. * @example
  10309. *
  10310. * _.toNumber(3);
  10311. * // => 3
  10312. *
  10313. * _.toNumber(Number.MIN_VALUE);
  10314. * // => 5e-324
  10315. *
  10316. * _.toNumber(Infinity);
  10317. * // => Infinity
  10318. *
  10319. * _.toNumber('3');
  10320. * // => 3
  10321. */
  10322. function toNumber(value) {
  10323. if (isObject(value)) {
  10324. var other = isFunction(value.valueOf) ? value.valueOf() : value;
  10325. value = isObject(other) ? (other + '') : other;
  10326. }
  10327. if (typeof value != 'string') {
  10328. return value === 0 ? value : +value;
  10329. }
  10330. value = value.replace(reTrim, '');
  10331. var isBinary = reIsBinary.test(value);
  10332. return (isBinary || reIsOctal.test(value))
  10333. ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
  10334. : (reIsBadHex.test(value) ? NAN : +value);
  10335. }
  10336. /**
  10337. * Converts `value` to a plain object flattening inherited enumerable
  10338. * properties of `value` to own properties of the plain object.
  10339. *
  10340. * @static
  10341. * @memberOf _
  10342. * @category Lang
  10343. * @param {*} value The value to convert.
  10344. * @returns {Object} Returns the converted plain object.
  10345. * @example
  10346. *
  10347. * function Foo() {
  10348. * this.b = 2;
  10349. * }
  10350. *
  10351. * Foo.prototype.c = 3;
  10352. *
  10353. * _.assign({ 'a': 1 }, new Foo);
  10354. * // => { 'a': 1, 'b': 2 }
  10355. *
  10356. * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
  10357. * // => { 'a': 1, 'b': 2, 'c': 3 }
  10358. */
  10359. function toPlainObject(value) {
  10360. return copyObject(value, keysIn(value));
  10361. }
  10362. /**
  10363. * Converts `value` to a safe integer. A safe integer can be compared and
  10364. * represented correctly.
  10365. *
  10366. * @static
  10367. * @memberOf _
  10368. * @category Lang
  10369. * @param {*} value The value to convert.
  10370. * @returns {number} Returns the converted integer.
  10371. * @example
  10372. *
  10373. * _.toSafeInteger(3);
  10374. * // => 3
  10375. *
  10376. * _.toSafeInteger(Number.MIN_VALUE);
  10377. * // => 0
  10378. *
  10379. * _.toSafeInteger(Infinity);
  10380. * // => 9007199254740991
  10381. *
  10382. * _.toSafeInteger('3');
  10383. * // => 3
  10384. */
  10385. function toSafeInteger(value) {
  10386. return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
  10387. }
  10388. /**
  10389. * Converts `value` to a string if it's not one. An empty string is returned
  10390. * for `null` and `undefined` values. The sign of `-0` is preserved.
  10391. *
  10392. * @static
  10393. * @memberOf _
  10394. * @category Lang
  10395. * @param {*} value The value to process.
  10396. * @returns {string} Returns the string.
  10397. * @example
  10398. *
  10399. * _.toString(null);
  10400. * // => ''
  10401. *
  10402. * _.toString(-0);
  10403. * // => '-0'
  10404. *
  10405. * _.toString([1, 2, 3]);
  10406. * // => '1,2,3'
  10407. */
  10408. function toString(value) {
  10409. // Exit early for strings to avoid a performance hit in some environments.
  10410. if (typeof value == 'string') {
  10411. return value;
  10412. }
  10413. if (value == null) {
  10414. return '';
  10415. }
  10416. if (isSymbol(value)) {
  10417. return Symbol ? symbolToString.call(value) : '';
  10418. }
  10419. var result = (value + '');
  10420. return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  10421. }
  10422. /*------------------------------------------------------------------------*/
  10423. /**
  10424. * Assigns own enumerable properties of source objects to the destination
  10425. * object. Source objects are applied from left to right. Subsequent sources
  10426. * overwrite property assignments of previous sources.
  10427. *
  10428. * **Note:** This method mutates `object` and is loosely based on
  10429. * [`Object.assign`](https://mdn.io/Object/assign).
  10430. *
  10431. * @static
  10432. * @memberOf _
  10433. * @category Object
  10434. * @param {Object} object The destination object.
  10435. * @param {...Object} [sources] The source objects.
  10436. * @returns {Object} Returns `object`.
  10437. * @example
  10438. *
  10439. * function Foo() {
  10440. * this.c = 3;
  10441. * }
  10442. *
  10443. * function Bar() {
  10444. * this.e = 5;
  10445. * }
  10446. *
  10447. * Foo.prototype.d = 4;
  10448. * Bar.prototype.f = 6;
  10449. *
  10450. * _.assign({ 'a': 1 }, new Foo, new Bar);
  10451. * // => { 'a': 1, 'c': 3, 'e': 5 }
  10452. */
  10453. var assign = createAssigner(function(object, source) {
  10454. copyObject(source, keys(source), object);
  10455. });
  10456. /**
  10457. * This method is like `_.assign` except that it iterates over own and
  10458. * inherited source properties.
  10459. *
  10460. * **Note:** This method mutates `object`.
  10461. *
  10462. * @static
  10463. * @memberOf _
  10464. * @alias extend
  10465. * @category Object
  10466. * @param {Object} object The destination object.
  10467. * @param {...Object} [sources] The source objects.
  10468. * @returns {Object} Returns `object`.
  10469. * @example
  10470. *
  10471. * function Foo() {
  10472. * this.b = 2;
  10473. * }
  10474. *
  10475. * function Bar() {
  10476. * this.d = 4;
  10477. * }
  10478. *
  10479. * Foo.prototype.c = 3;
  10480. * Bar.prototype.e = 5;
  10481. *
  10482. * _.assignIn({ 'a': 1 }, new Foo, new Bar);
  10483. * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 }
  10484. */
  10485. var assignIn = createAssigner(function(object, source) {
  10486. copyObject(source, keysIn(source), object);
  10487. });
  10488. /**
  10489. * This method is like `_.assignIn` except that it accepts `customizer` which
  10490. * is invoked to produce the assigned values. If `customizer` returns `undefined`
  10491. * assignment is handled by the method instead. The `customizer` is invoked
  10492. * with five arguments: (objValue, srcValue, key, object, source).
  10493. *
  10494. * **Note:** This method mutates `object`.
  10495. *
  10496. * @static
  10497. * @memberOf _
  10498. * @alias extendWith
  10499. * @category Object
  10500. * @param {Object} object The destination object.
  10501. * @param {...Object} sources The source objects.
  10502. * @param {Function} [customizer] The function to customize assigned values.
  10503. * @returns {Object} Returns `object`.
  10504. * @example
  10505. *
  10506. * function customizer(objValue, srcValue) {
  10507. * return _.isUndefined(objValue) ? srcValue : objValue;
  10508. * }
  10509. *
  10510. * var defaults = _.partialRight(_.assignInWith, customizer);
  10511. *
  10512. * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
  10513. * // => { 'a': 1, 'b': 2 }
  10514. */
  10515. var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
  10516. copyObjectWith(source, keysIn(source), object, customizer);
  10517. });
  10518. /**
  10519. * This method is like `_.assign` except that it accepts `customizer` which
  10520. * is invoked to produce the assigned values. If `customizer` returns `undefined`
  10521. * assignment is handled by the method instead. The `customizer` is invoked
  10522. * with five arguments: (objValue, srcValue, key, object, source).
  10523. *
  10524. * **Note:** This method mutates `object`.
  10525. *
  10526. * @static
  10527. * @memberOf _
  10528. * @category Object
  10529. * @param {Object} object The destination object.
  10530. * @param {...Object} sources The source objects.
  10531. * @param {Function} [customizer] The function to customize assigned values.
  10532. * @returns {Object} Returns `object`.
  10533. * @example
  10534. *
  10535. * function customizer(objValue, srcValue) {
  10536. * return _.isUndefined(objValue) ? srcValue : objValue;
  10537. * }
  10538. *
  10539. * var defaults = _.partialRight(_.assignWith, customizer);
  10540. *
  10541. * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
  10542. * // => { 'a': 1, 'b': 2 }
  10543. */
  10544. var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
  10545. copyObjectWith(source, keys(source), object, customizer);
  10546. });
  10547. /**
  10548. * Creates an array of values corresponding to `paths` of `object`.
  10549. *
  10550. * @static
  10551. * @memberOf _
  10552. * @category Object
  10553. * @param {Object} object The object to iterate over.
  10554. * @param {...(string|string[])} [paths] The property paths of elements to pick,
  10555. * specified individually or in arrays.
  10556. * @returns {Array} Returns the new array of picked elements.
  10557. * @example
  10558. *
  10559. * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
  10560. *
  10561. * _.at(object, ['a[0].b.c', 'a[1]']);
  10562. * // => [3, 4]
  10563. *
  10564. * _.at(['a', 'b', 'c'], 0, 2);
  10565. * // => ['a', 'c']
  10566. */
  10567. var at = rest(function(object, paths) {
  10568. return baseAt(object, baseFlatten(paths, 1));
  10569. });
  10570. /**
  10571. * Creates an object that inherits from the `prototype` object. If a `properties`
  10572. * object is given its own enumerable properties are assigned to the created object.
  10573. *
  10574. * @static
  10575. * @memberOf _
  10576. * @category Object
  10577. * @param {Object} prototype The object to inherit from.
  10578. * @param {Object} [properties] The properties to assign to the object.
  10579. * @returns {Object} Returns the new object.
  10580. * @example
  10581. *
  10582. * function Shape() {
  10583. * this.x = 0;
  10584. * this.y = 0;
  10585. * }
  10586. *
  10587. * function Circle() {
  10588. * Shape.call(this);
  10589. * }
  10590. *
  10591. * Circle.prototype = _.create(Shape.prototype, {
  10592. * 'constructor': Circle
  10593. * });
  10594. *
  10595. * var circle = new Circle;
  10596. * circle instanceof Circle;
  10597. * // => true
  10598. *
  10599. * circle instanceof Shape;
  10600. * // => true
  10601. */
  10602. function create(prototype, properties) {
  10603. var result = baseCreate(prototype);
  10604. return properties ? baseAssign(result, properties) : result;
  10605. }
  10606. /**
  10607. * Assigns own and inherited enumerable properties of source objects to the
  10608. * destination object for all destination properties that resolve to `undefined`.
  10609. * Source objects are applied from left to right. Once a property is set,
  10610. * additional values of the same property are ignored.
  10611. *
  10612. * **Note:** This method mutates `object`.
  10613. *
  10614. * @static
  10615. * @memberOf _
  10616. * @category Object
  10617. * @param {Object} object The destination object.
  10618. * @param {...Object} [sources] The source objects.
  10619. * @returns {Object} Returns `object`.
  10620. * @example
  10621. *
  10622. * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
  10623. * // => { 'user': 'barney', 'age': 36 }
  10624. */
  10625. var defaults = rest(function(args) {
  10626. args.push(undefined, assignInDefaults);
  10627. return apply(assignInWith, undefined, args);
  10628. });
  10629. /**
  10630. * This method is like `_.defaults` except that it recursively assigns
  10631. * default properties.
  10632. *
  10633. * **Note:** This method mutates `object`.
  10634. *
  10635. * @static
  10636. * @memberOf _
  10637. * @category Object
  10638. * @param {Object} object The destination object.
  10639. * @param {...Object} [sources] The source objects.
  10640. * @returns {Object} Returns `object`.
  10641. * @example
  10642. *
  10643. * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
  10644. * // => { 'user': { 'name': 'barney', 'age': 36 } }
  10645. *
  10646. */
  10647. var defaultsDeep = rest(function(args) {
  10648. args.push(undefined, mergeDefaults);
  10649. return apply(mergeWith, undefined, args);
  10650. });
  10651. /**
  10652. * This method is like `_.find` except that it returns the key of the first
  10653. * element `predicate` returns truthy for instead of the element itself.
  10654. *
  10655. * @static
  10656. * @memberOf _
  10657. * @category Object
  10658. * @param {Object} object The object to search.
  10659. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  10660. * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
  10661. * @example
  10662. *
  10663. * var users = {
  10664. * 'barney': { 'age': 36, 'active': true },
  10665. * 'fred': { 'age': 40, 'active': false },
  10666. * 'pebbles': { 'age': 1, 'active': true }
  10667. * };
  10668. *
  10669. * _.findKey(users, function(o) { return o.age < 40; });
  10670. * // => 'barney' (iteration order is not guaranteed)
  10671. *
  10672. * // The `_.matches` iteratee shorthand.
  10673. * _.findKey(users, { 'age': 1, 'active': true });
  10674. * // => 'pebbles'
  10675. *
  10676. * // The `_.matchesProperty` iteratee shorthand.
  10677. * _.findKey(users, ['active', false]);
  10678. * // => 'fred'
  10679. *
  10680. * // The `_.property` iteratee shorthand.
  10681. * _.findKey(users, 'active');
  10682. * // => 'barney'
  10683. */
  10684. function findKey(object, predicate) {
  10685. return baseFind(object, getIteratee(predicate, 3), baseForOwn, true);
  10686. }
  10687. /**
  10688. * This method is like `_.findKey` except that it iterates over elements of
  10689. * a collection in the opposite order.
  10690. *
  10691. * @static
  10692. * @memberOf _
  10693. * @category Object
  10694. * @param {Object} object The object to search.
  10695. * @param {Function|Object|string} [predicate=_.identity] The function invoked per iteration.
  10696. * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
  10697. * @example
  10698. *
  10699. * var users = {
  10700. * 'barney': { 'age': 36, 'active': true },
  10701. * 'fred': { 'age': 40, 'active': false },
  10702. * 'pebbles': { 'age': 1, 'active': true }
  10703. * };
  10704. *
  10705. * _.findLastKey(users, function(o) { return o.age < 40; });
  10706. * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
  10707. *
  10708. * // The `_.matches` iteratee shorthand.
  10709. * _.findLastKey(users, { 'age': 36, 'active': true });
  10710. * // => 'barney'
  10711. *
  10712. * // The `_.matchesProperty` iteratee shorthand.
  10713. * _.findLastKey(users, ['active', false]);
  10714. * // => 'fred'
  10715. *
  10716. * // The `_.property` iteratee shorthand.
  10717. * _.findLastKey(users, 'active');
  10718. * // => 'pebbles'
  10719. */
  10720. function findLastKey(object, predicate) {
  10721. return baseFind(object, getIteratee(predicate, 3), baseForOwnRight, true);
  10722. }
  10723. /**
  10724. * Iterates over own and inherited enumerable properties of an object invoking
  10725. * `iteratee` for each property. The iteratee is invoked with three arguments:
  10726. * (value, key, object). Iteratee functions may exit iteration early by explicitly
  10727. * returning `false`.
  10728. *
  10729. * @static
  10730. * @memberOf _
  10731. * @category Object
  10732. * @param {Object} object The object to iterate over.
  10733. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  10734. * @returns {Object} Returns `object`.
  10735. * @example
  10736. *
  10737. * function Foo() {
  10738. * this.a = 1;
  10739. * this.b = 2;
  10740. * }
  10741. *
  10742. * Foo.prototype.c = 3;
  10743. *
  10744. * _.forIn(new Foo, function(value, key) {
  10745. * console.log(key);
  10746. * });
  10747. * // => logs 'a', 'b', then 'c' (iteration order is not guaranteed)
  10748. */
  10749. function forIn(object, iteratee) {
  10750. return object == null
  10751. ? object
  10752. : baseFor(object, baseCastFunction(iteratee), keysIn);
  10753. }
  10754. /**
  10755. * This method is like `_.forIn` except that it iterates over properties of
  10756. * `object` in the opposite order.
  10757. *
  10758. * @static
  10759. * @memberOf _
  10760. * @category Object
  10761. * @param {Object} object The object to iterate over.
  10762. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  10763. * @returns {Object} Returns `object`.
  10764. * @example
  10765. *
  10766. * function Foo() {
  10767. * this.a = 1;
  10768. * this.b = 2;
  10769. * }
  10770. *
  10771. * Foo.prototype.c = 3;
  10772. *
  10773. * _.forInRight(new Foo, function(value, key) {
  10774. * console.log(key);
  10775. * });
  10776. * // => logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'
  10777. */
  10778. function forInRight(object, iteratee) {
  10779. return object == null
  10780. ? object
  10781. : baseForRight(object, baseCastFunction(iteratee), keysIn);
  10782. }
  10783. /**
  10784. * Iterates over own enumerable properties of an object invoking `iteratee`
  10785. * for each property. The iteratee is invoked with three arguments:
  10786. * (value, key, object). Iteratee functions may exit iteration early by
  10787. * explicitly returning `false`.
  10788. *
  10789. * @static
  10790. * @memberOf _
  10791. * @category Object
  10792. * @param {Object} object The object to iterate over.
  10793. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  10794. * @returns {Object} Returns `object`.
  10795. * @example
  10796. *
  10797. * function Foo() {
  10798. * this.a = 1;
  10799. * this.b = 2;
  10800. * }
  10801. *
  10802. * Foo.prototype.c = 3;
  10803. *
  10804. * _.forOwn(new Foo, function(value, key) {
  10805. * console.log(key);
  10806. * });
  10807. * // => logs 'a' then 'b' (iteration order is not guaranteed)
  10808. */
  10809. function forOwn(object, iteratee) {
  10810. return object && baseForOwn(object, baseCastFunction(iteratee));
  10811. }
  10812. /**
  10813. * This method is like `_.forOwn` except that it iterates over properties of
  10814. * `object` in the opposite order.
  10815. *
  10816. * @static
  10817. * @memberOf _
  10818. * @category Object
  10819. * @param {Object} object The object to iterate over.
  10820. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  10821. * @returns {Object} Returns `object`.
  10822. * @example
  10823. *
  10824. * function Foo() {
  10825. * this.a = 1;
  10826. * this.b = 2;
  10827. * }
  10828. *
  10829. * Foo.prototype.c = 3;
  10830. *
  10831. * _.forOwnRight(new Foo, function(value, key) {
  10832. * console.log(key);
  10833. * });
  10834. * // => logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'
  10835. */
  10836. function forOwnRight(object, iteratee) {
  10837. return object && baseForOwnRight(object, baseCastFunction(iteratee));
  10838. }
  10839. /**
  10840. * Creates an array of function property names from own enumerable properties
  10841. * of `object`.
  10842. *
  10843. * @static
  10844. * @memberOf _
  10845. * @category Object
  10846. * @param {Object} object The object to inspect.
  10847. * @returns {Array} Returns the new array of property names.
  10848. * @example
  10849. *
  10850. * function Foo() {
  10851. * this.a = _.constant('a');
  10852. * this.b = _.constant('b');
  10853. * }
  10854. *
  10855. * Foo.prototype.c = _.constant('c');
  10856. *
  10857. * _.functions(new Foo);
  10858. * // => ['a', 'b']
  10859. */
  10860. function functions(object) {
  10861. return object == null ? [] : baseFunctions(object, keys(object));
  10862. }
  10863. /**
  10864. * Creates an array of function property names from own and inherited
  10865. * enumerable properties of `object`.
  10866. *
  10867. * @static
  10868. * @memberOf _
  10869. * @category Object
  10870. * @param {Object} object The object to inspect.
  10871. * @returns {Array} Returns the new array of property names.
  10872. * @example
  10873. *
  10874. * function Foo() {
  10875. * this.a = _.constant('a');
  10876. * this.b = _.constant('b');
  10877. * }
  10878. *
  10879. * Foo.prototype.c = _.constant('c');
  10880. *
  10881. * _.functionsIn(new Foo);
  10882. * // => ['a', 'b', 'c']
  10883. */
  10884. function functionsIn(object) {
  10885. return object == null ? [] : baseFunctions(object, keysIn(object));
  10886. }
  10887. /**
  10888. * Gets the value at `path` of `object`. If the resolved value is
  10889. * `undefined` the `defaultValue` is used in its place.
  10890. *
  10891. * @static
  10892. * @memberOf _
  10893. * @category Object
  10894. * @param {Object} object The object to query.
  10895. * @param {Array|string} path The path of the property to get.
  10896. * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
  10897. * @returns {*} Returns the resolved value.
  10898. * @example
  10899. *
  10900. * var object = { 'a': [{ 'b': { 'c': 3 } }] };
  10901. *
  10902. * _.get(object, 'a[0].b.c');
  10903. * // => 3
  10904. *
  10905. * _.get(object, ['a', '0', 'b', 'c']);
  10906. * // => 3
  10907. *
  10908. * _.get(object, 'a.b.c', 'default');
  10909. * // => 'default'
  10910. */
  10911. function get(object, path, defaultValue) {
  10912. var result = object == null ? undefined : baseGet(object, path);
  10913. return result === undefined ? defaultValue : result;
  10914. }
  10915. /**
  10916. * Checks if `path` is a direct property of `object`.
  10917. *
  10918. * @static
  10919. * @memberOf _
  10920. * @category Object
  10921. * @param {Object} object The object to query.
  10922. * @param {Array|string} path The path to check.
  10923. * @returns {boolean} Returns `true` if `path` exists, else `false`.
  10924. * @example
  10925. *
  10926. * var object = { 'a': { 'b': { 'c': 3 } } };
  10927. * var other = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) });
  10928. *
  10929. * _.has(object, 'a');
  10930. * // => true
  10931. *
  10932. * _.has(object, 'a.b.c');
  10933. * // => true
  10934. *
  10935. * _.has(object, ['a', 'b', 'c']);
  10936. * // => true
  10937. *
  10938. * _.has(other, 'a');
  10939. * // => false
  10940. */
  10941. function has(object, path) {
  10942. return hasPath(object, path, baseHas);
  10943. }
  10944. /**
  10945. * Checks if `path` is a direct or inherited property of `object`.
  10946. *
  10947. * @static
  10948. * @memberOf _
  10949. * @category Object
  10950. * @param {Object} object The object to query.
  10951. * @param {Array|string} path The path to check.
  10952. * @returns {boolean} Returns `true` if `path` exists, else `false`.
  10953. * @example
  10954. *
  10955. * var object = _.create({ 'a': _.create({ 'b': _.create({ 'c': 3 }) }) });
  10956. *
  10957. * _.hasIn(object, 'a');
  10958. * // => true
  10959. *
  10960. * _.hasIn(object, 'a.b.c');
  10961. * // => true
  10962. *
  10963. * _.hasIn(object, ['a', 'b', 'c']);
  10964. * // => true
  10965. *
  10966. * _.hasIn(object, 'b');
  10967. * // => false
  10968. */
  10969. function hasIn(object, path) {
  10970. return hasPath(object, path, baseHasIn);
  10971. }
  10972. /**
  10973. * Creates an object composed of the inverted keys and values of `object`.
  10974. * If `object` contains duplicate values, subsequent values overwrite property
  10975. * assignments of previous values.
  10976. *
  10977. * @static
  10978. * @memberOf _
  10979. * @category Object
  10980. * @param {Object} object The object to invert.
  10981. * @returns {Object} Returns the new inverted object.
  10982. * @example
  10983. *
  10984. * var object = { 'a': 1, 'b': 2, 'c': 1 };
  10985. *
  10986. * _.invert(object);
  10987. * // => { '1': 'c', '2': 'b' }
  10988. */
  10989. var invert = createInverter(function(result, value, key) {
  10990. result[value] = key;
  10991. }, constant(identity));
  10992. /**
  10993. * This method is like `_.invert` except that the inverted object is generated
  10994. * from the results of running each element of `object` through `iteratee`.
  10995. * The corresponding inverted value of each inverted key is an array of keys
  10996. * responsible for generating the inverted value. The iteratee is invoked
  10997. * with one argument: (value).
  10998. *
  10999. * @static
  11000. * @memberOf _
  11001. * @category Object
  11002. * @param {Object} object The object to invert.
  11003. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  11004. * @returns {Object} Returns the new inverted object.
  11005. * @example
  11006. *
  11007. * var object = { 'a': 1, 'b': 2, 'c': 1 };
  11008. *
  11009. * _.invertBy(object);
  11010. * // => { '1': ['a', 'c'], '2': ['b'] }
  11011. *
  11012. * _.invertBy(object, function(value) {
  11013. * return 'group' + value;
  11014. * });
  11015. * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
  11016. */
  11017. var invertBy = createInverter(function(result, value, key) {
  11018. if (hasOwnProperty.call(result, value)) {
  11019. result[value].push(key);
  11020. } else {
  11021. result[value] = [key];
  11022. }
  11023. }, getIteratee);
  11024. /**
  11025. * Invokes the method at `path` of `object`.
  11026. *
  11027. * @static
  11028. * @memberOf _
  11029. * @category Object
  11030. * @param {Object} object The object to query.
  11031. * @param {Array|string} path The path of the method to invoke.
  11032. * @param {...*} [args] The arguments to invoke the method with.
  11033. * @returns {*} Returns the result of the invoked method.
  11034. * @example
  11035. *
  11036. * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
  11037. *
  11038. * _.invoke(object, 'a[0].b.c.slice', 1, 3);
  11039. * // => [2, 3]
  11040. */
  11041. var invoke = rest(baseInvoke);
  11042. /**
  11043. * Creates an array of the own enumerable property names of `object`.
  11044. *
  11045. * **Note:** Non-object values are coerced to objects. See the
  11046. * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
  11047. * for more details.
  11048. *
  11049. * @static
  11050. * @memberOf _
  11051. * @category Object
  11052. * @param {Object} object The object to query.
  11053. * @returns {Array} Returns the array of property names.
  11054. * @example
  11055. *
  11056. * function Foo() {
  11057. * this.a = 1;
  11058. * this.b = 2;
  11059. * }
  11060. *
  11061. * Foo.prototype.c = 3;
  11062. *
  11063. * _.keys(new Foo);
  11064. * // => ['a', 'b'] (iteration order is not guaranteed)
  11065. *
  11066. * _.keys('hi');
  11067. * // => ['0', '1']
  11068. */
  11069. function keys(object) {
  11070. var isProto = isPrototype(object);
  11071. if (!(isProto || isArrayLike(object))) {
  11072. return baseKeys(object);
  11073. }
  11074. var indexes = indexKeys(object),
  11075. skipIndexes = !!indexes,
  11076. result = indexes || [],
  11077. length = result.length;
  11078. for (var key in object) {
  11079. if (baseHas(object, key) &&
  11080. !(skipIndexes && (key == 'length' || isIndex(key, length))) &&
  11081. !(isProto && key == 'constructor')) {
  11082. result.push(key);
  11083. }
  11084. }
  11085. return result;
  11086. }
  11087. /**
  11088. * Creates an array of the own and inherited enumerable property names of `object`.
  11089. *
  11090. * **Note:** Non-object values are coerced to objects.
  11091. *
  11092. * @static
  11093. * @memberOf _
  11094. * @category Object
  11095. * @param {Object} object The object to query.
  11096. * @returns {Array} Returns the array of property names.
  11097. * @example
  11098. *
  11099. * function Foo() {
  11100. * this.a = 1;
  11101. * this.b = 2;
  11102. * }
  11103. *
  11104. * Foo.prototype.c = 3;
  11105. *
  11106. * _.keysIn(new Foo);
  11107. * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
  11108. */
  11109. function keysIn(object) {
  11110. var index = -1,
  11111. isProto = isPrototype(object),
  11112. props = baseKeysIn(object),
  11113. propsLength = props.length,
  11114. indexes = indexKeys(object),
  11115. skipIndexes = !!indexes,
  11116. result = indexes || [],
  11117. length = result.length;
  11118. while (++index < propsLength) {
  11119. var key = props[index];
  11120. if (!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
  11121. !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
  11122. result.push(key);
  11123. }
  11124. }
  11125. return result;
  11126. }
  11127. /**
  11128. * The opposite of `_.mapValues`; this method creates an object with the
  11129. * same values as `object` and keys generated by running each own enumerable
  11130. * property of `object` through `iteratee`. The iteratee is invoked with
  11131. * three arguments: (value, key, object).
  11132. *
  11133. * @static
  11134. * @memberOf _
  11135. * @category Object
  11136. * @param {Object} object The object to iterate over.
  11137. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
  11138. * @returns {Object} Returns the new mapped object.
  11139. * @example
  11140. *
  11141. * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
  11142. * return key + value;
  11143. * });
  11144. * // => { 'a1': 1, 'b2': 2 }
  11145. */
  11146. function mapKeys(object, iteratee) {
  11147. var result = {};
  11148. iteratee = getIteratee(iteratee, 3);
  11149. baseForOwn(object, function(value, key, object) {
  11150. result[iteratee(value, key, object)] = value;
  11151. });
  11152. return result;
  11153. }
  11154. /**
  11155. * Creates an object with the same keys as `object` and values generated by
  11156. * running each own enumerable property of `object` through `iteratee`. The
  11157. * iteratee is invoked with three arguments: (value, key, object).
  11158. *
  11159. * @static
  11160. * @memberOf _
  11161. * @category Object
  11162. * @param {Object} object The object to iterate over.
  11163. * @param {Function|Object|string} [iteratee=_.identity] The function invoked per iteration.
  11164. * @returns {Object} Returns the new mapped object.
  11165. * @example
  11166. *
  11167. * var users = {
  11168. * 'fred': { 'user': 'fred', 'age': 40 },
  11169. * 'pebbles': { 'user': 'pebbles', 'age': 1 }
  11170. * };
  11171. *
  11172. * _.mapValues(users, function(o) { return o.age; });
  11173. * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
  11174. *
  11175. * // The `_.property` iteratee shorthand.
  11176. * _.mapValues(users, 'age');
  11177. * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
  11178. */
  11179. function mapValues(object, iteratee) {
  11180. var result = {};
  11181. iteratee = getIteratee(iteratee, 3);
  11182. baseForOwn(object, function(value, key, object) {
  11183. result[key] = iteratee(value, key, object);
  11184. });
  11185. return result;
  11186. }
  11187. /**
  11188. * Recursively merges own and inherited enumerable properties of source objects
  11189. * into the destination object. Source properties that resolve to `undefined`
  11190. * are skipped if a destination value exists. Array and plain object properties
  11191. * are merged recursively. Other objects and value types are overridden by
  11192. * assignment. Source objects are applied from left to right. Subsequent
  11193. * sources overwrite property assignments of previous sources.
  11194. *
  11195. * **Note:** This method mutates `object`.
  11196. *
  11197. * @static
  11198. * @memberOf _
  11199. * @category Object
  11200. * @param {Object} object The destination object.
  11201. * @param {...Object} [sources] The source objects.
  11202. * @returns {Object} Returns `object`.
  11203. * @example
  11204. *
  11205. * var users = {
  11206. * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
  11207. * };
  11208. *
  11209. * var ages = {
  11210. * 'data': [{ 'age': 36 }, { 'age': 40 }]
  11211. * };
  11212. *
  11213. * _.merge(users, ages);
  11214. * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
  11215. */
  11216. var merge = createAssigner(function(object, source, srcIndex) {
  11217. baseMerge(object, source, srcIndex);
  11218. });
  11219. /**
  11220. * This method is like `_.merge` except that it accepts `customizer` which
  11221. * is invoked to produce the merged values of the destination and source
  11222. * properties. If `customizer` returns `undefined` merging is handled by the
  11223. * method instead. The `customizer` is invoked with seven arguments:
  11224. * (objValue, srcValue, key, object, source, stack).
  11225. *
  11226. * **Note:** This method mutates `object`.
  11227. *
  11228. * @static
  11229. * @memberOf _
  11230. * @category Object
  11231. * @param {Object} object The destination object.
  11232. * @param {...Object} sources The source objects.
  11233. * @param {Function} customizer The function to customize assigned values.
  11234. * @returns {Object} Returns `object`.
  11235. * @example
  11236. *
  11237. * function customizer(objValue, srcValue) {
  11238. * if (_.isArray(objValue)) {
  11239. * return objValue.concat(srcValue);
  11240. * }
  11241. * }
  11242. *
  11243. * var object = {
  11244. * 'fruits': ['apple'],
  11245. * 'vegetables': ['beet']
  11246. * };
  11247. *
  11248. * var other = {
  11249. * 'fruits': ['banana'],
  11250. * 'vegetables': ['carrot']
  11251. * };
  11252. *
  11253. * _.mergeWith(object, other, customizer);
  11254. * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
  11255. */
  11256. var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
  11257. baseMerge(object, source, srcIndex, customizer);
  11258. });
  11259. /**
  11260. * The opposite of `_.pick`; this method creates an object composed of the
  11261. * own and inherited enumerable properties of `object` that are not omitted.
  11262. *
  11263. * @static
  11264. * @memberOf _
  11265. * @category Object
  11266. * @param {Object} object The source object.
  11267. * @param {...(string|string[])} [props] The property names to omit, specified
  11268. * individually or in arrays.
  11269. * @returns {Object} Returns the new object.
  11270. * @example
  11271. *
  11272. * var object = { 'a': 1, 'b': '2', 'c': 3 };
  11273. *
  11274. * _.omit(object, ['a', 'c']);
  11275. * // => { 'b': '2' }
  11276. */
  11277. var omit = rest(function(object, props) {
  11278. if (object == null) {
  11279. return {};
  11280. }
  11281. props = arrayMap(baseFlatten(props, 1), String);
  11282. return basePick(object, baseDifference(keysIn(object), props));
  11283. });
  11284. /**
  11285. * The opposite of `_.pickBy`; this method creates an object composed of
  11286. * the own and inherited enumerable properties of `object` that `predicate`
  11287. * doesn't return truthy for. The predicate is invoked with two arguments:
  11288. * (value, key).
  11289. *
  11290. * @static
  11291. * @memberOf _
  11292. * @category Object
  11293. * @param {Object} object The source object.
  11294. * @param {Function|Object|string} [predicate=_.identity] The function invoked per property.
  11295. * @returns {Object} Returns the new object.
  11296. * @example
  11297. *
  11298. * var object = { 'a': 1, 'b': '2', 'c': 3 };
  11299. *
  11300. * _.omitBy(object, _.isNumber);
  11301. * // => { 'b': '2' }
  11302. */
  11303. function omitBy(object, predicate) {
  11304. predicate = getIteratee(predicate);
  11305. return basePickBy(object, function(value, key) {
  11306. return !predicate(value, key);
  11307. });
  11308. }
  11309. /**
  11310. * Creates an object composed of the picked `object` properties.
  11311. *
  11312. * @static
  11313. * @memberOf _
  11314. * @category Object
  11315. * @param {Object} object The source object.
  11316. * @param {...(string|string[])} [props] The property names to pick, specified
  11317. * individually or in arrays.
  11318. * @returns {Object} Returns the new object.
  11319. * @example
  11320. *
  11321. * var object = { 'a': 1, 'b': '2', 'c': 3 };
  11322. *
  11323. * _.pick(object, ['a', 'c']);
  11324. * // => { 'a': 1, 'c': 3 }
  11325. */
  11326. var pick = rest(function(object, props) {
  11327. return object == null ? {} : basePick(object, baseFlatten(props, 1));
  11328. });
  11329. /**
  11330. * Creates an object composed of the `object` properties `predicate` returns
  11331. * truthy for. The predicate is invoked with two arguments: (value, key).
  11332. *
  11333. * @static
  11334. * @memberOf _
  11335. * @category Object
  11336. * @param {Object} object The source object.
  11337. * @param {Function|Object|string} [predicate=_.identity] The function invoked per property.
  11338. * @returns {Object} Returns the new object.
  11339. * @example
  11340. *
  11341. * var object = { 'a': 1, 'b': '2', 'c': 3 };
  11342. *
  11343. * _.pickBy(object, _.isNumber);
  11344. * // => { 'a': 1, 'c': 3 }
  11345. */
  11346. function pickBy(object, predicate) {
  11347. return object == null ? {} : basePickBy(object, getIteratee(predicate));
  11348. }
  11349. /**
  11350. * This method is like `_.get` except that if the resolved value is a function
  11351. * it's invoked with the `this` binding of its parent object and its result
  11352. * is returned.
  11353. *
  11354. * @static
  11355. * @memberOf _
  11356. * @category Object
  11357. * @param {Object} object The object to query.
  11358. * @param {Array|string} path The path of the property to resolve.
  11359. * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
  11360. * @returns {*} Returns the resolved value.
  11361. * @example
  11362. *
  11363. * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
  11364. *
  11365. * _.result(object, 'a[0].b.c1');
  11366. * // => 3
  11367. *
  11368. * _.result(object, 'a[0].b.c2');
  11369. * // => 4
  11370. *
  11371. * _.result(object, 'a[0].b.c3', 'default');
  11372. * // => 'default'
  11373. *
  11374. * _.result(object, 'a[0].b.c3', _.constant('default'));
  11375. * // => 'default'
  11376. */
  11377. function result(object, path, defaultValue) {
  11378. if (!isKey(path, object)) {
  11379. path = baseCastPath(path);
  11380. var result = get(object, path);
  11381. object = parent(object, path);
  11382. } else {
  11383. result = object == null ? undefined : object[path];
  11384. }
  11385. if (result === undefined) {
  11386. result = defaultValue;
  11387. }
  11388. return isFunction(result) ? result.call(object) : result;
  11389. }
  11390. /**
  11391. * Sets the value at `path` of `object`. If a portion of `path` doesn't exist
  11392. * it's created. Arrays are created for missing index properties while objects
  11393. * are created for all other missing properties. Use `_.setWith` to customize
  11394. * `path` creation.
  11395. *
  11396. * **Note:** This method mutates `object`.
  11397. *
  11398. * @static
  11399. * @memberOf _
  11400. * @category Object
  11401. * @param {Object} object The object to modify.
  11402. * @param {Array|string} path The path of the property to set.
  11403. * @param {*} value The value to set.
  11404. * @returns {Object} Returns `object`.
  11405. * @example
  11406. *
  11407. * var object = { 'a': [{ 'b': { 'c': 3 } }] };
  11408. *
  11409. * _.set(object, 'a[0].b.c', 4);
  11410. * console.log(object.a[0].b.c);
  11411. * // => 4
  11412. *
  11413. * _.set(object, 'x[0].y.z', 5);
  11414. * console.log(object.x[0].y.z);
  11415. * // => 5
  11416. */
  11417. function set(object, path, value) {
  11418. return object == null ? object : baseSet(object, path, value);
  11419. }
  11420. /**
  11421. * This method is like `_.set` except that it accepts `customizer` which is
  11422. * invoked to produce the objects of `path`. If `customizer` returns `undefined`
  11423. * path creation is handled by the method instead. The `customizer` is invoked
  11424. * with three arguments: (nsValue, key, nsObject).
  11425. *
  11426. * **Note:** This method mutates `object`.
  11427. *
  11428. * @static
  11429. * @memberOf _
  11430. * @category Object
  11431. * @param {Object} object The object to modify.
  11432. * @param {Array|string} path The path of the property to set.
  11433. * @param {*} value The value to set.
  11434. * @param {Function} [customizer] The function to customize assigned values.
  11435. * @returns {Object} Returns `object`.
  11436. * @example
  11437. *
  11438. * _.setWith({ '0': { 'length': 2 } }, '[0][1][2]', 3, Object);
  11439. * // => { '0': { '1': { '2': 3 }, 'length': 2 } }
  11440. */
  11441. function setWith(object, path, value, customizer) {
  11442. customizer = typeof customizer == 'function' ? customizer : undefined;
  11443. return object == null ? object : baseSet(object, path, value, customizer);
  11444. }
  11445. /**
  11446. * Creates an array of own enumerable key-value pairs for `object` which
  11447. * can be consumed by `_.fromPairs`.
  11448. *
  11449. * @static
  11450. * @memberOf _
  11451. * @category Object
  11452. * @param {Object} object The object to query.
  11453. * @returns {Array} Returns the new array of key-value pairs.
  11454. * @example
  11455. *
  11456. * function Foo() {
  11457. * this.a = 1;
  11458. * this.b = 2;
  11459. * }
  11460. *
  11461. * Foo.prototype.c = 3;
  11462. *
  11463. * _.toPairs(new Foo);
  11464. * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
  11465. */
  11466. function toPairs(object) {
  11467. return baseToPairs(object, keys(object));
  11468. }
  11469. /**
  11470. * Creates an array of own and inherited enumerable key-value pairs for
  11471. * `object` which can be consumed by `_.fromPairs`.
  11472. *
  11473. * @static
  11474. * @memberOf _
  11475. * @category Object
  11476. * @param {Object} object The object to query.
  11477. * @returns {Array} Returns the new array of key-value pairs.
  11478. * @example
  11479. *
  11480. * function Foo() {
  11481. * this.a = 1;
  11482. * this.b = 2;
  11483. * }
  11484. *
  11485. * Foo.prototype.c = 3;
  11486. *
  11487. * _.toPairsIn(new Foo);
  11488. * // => [['a', 1], ['b', 2], ['c', 1]] (iteration order is not guaranteed)
  11489. */
  11490. function toPairsIn(object) {
  11491. return baseToPairs(object, keysIn(object));
  11492. }
  11493. /**
  11494. * An alternative to `_.reduce`; this method transforms `object` to a new
  11495. * `accumulator` object which is the result of running each of its own enumerable
  11496. * properties through `iteratee`, with each invocation potentially mutating
  11497. * the `accumulator` object. The iteratee is invoked with four arguments:
  11498. * (accumulator, value, key, object). Iteratee functions may exit iteration
  11499. * early by explicitly returning `false`.
  11500. *
  11501. * @static
  11502. * @memberOf _
  11503. * @category Object
  11504. * @param {Array|Object} object The object to iterate over.
  11505. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  11506. * @param {*} [accumulator] The custom accumulator value.
  11507. * @returns {*} Returns the accumulated value.
  11508. * @example
  11509. *
  11510. * _.transform([2, 3, 4], function(result, n) {
  11511. * result.push(n *= n);
  11512. * return n % 2 == 0;
  11513. * }, []);
  11514. * // => [4, 9]
  11515. *
  11516. * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
  11517. * (result[value] || (result[value] = [])).push(key);
  11518. * }, {});
  11519. * // => { '1': ['a', 'c'], '2': ['b'] }
  11520. */
  11521. function transform(object, iteratee, accumulator) {
  11522. var isArr = isArray(object) || isTypedArray(object);
  11523. iteratee = getIteratee(iteratee, 4);
  11524. if (accumulator == null) {
  11525. if (isArr || isObject(object)) {
  11526. var Ctor = object.constructor;
  11527. if (isArr) {
  11528. accumulator = isArray(object) ? new Ctor : [];
  11529. } else {
  11530. accumulator = isFunction(Ctor) ? baseCreate(getPrototypeOf(object)) : {};
  11531. }
  11532. } else {
  11533. accumulator = {};
  11534. }
  11535. }
  11536. (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
  11537. return iteratee(accumulator, value, index, object);
  11538. });
  11539. return accumulator;
  11540. }
  11541. /**
  11542. * Removes the property at `path` of `object`.
  11543. *
  11544. * **Note:** This method mutates `object`.
  11545. *
  11546. * @static
  11547. * @memberOf _
  11548. * @category Object
  11549. * @param {Object} object The object to modify.
  11550. * @param {Array|string} path The path of the property to unset.
  11551. * @returns {boolean} Returns `true` if the property is deleted, else `false`.
  11552. * @example
  11553. *
  11554. * var object = { 'a': [{ 'b': { 'c': 7 } }] };
  11555. * _.unset(object, 'a[0].b.c');
  11556. * // => true
  11557. *
  11558. * console.log(object);
  11559. * // => { 'a': [{ 'b': {} }] };
  11560. *
  11561. * _.unset(object, 'a[0].b.c');
  11562. * // => true
  11563. *
  11564. * console.log(object);
  11565. * // => { 'a': [{ 'b': {} }] };
  11566. */
  11567. function unset(object, path) {
  11568. return object == null ? true : baseUnset(object, path);
  11569. }
  11570. /**
  11571. * Creates an array of the own enumerable property values of `object`.
  11572. *
  11573. * **Note:** Non-object values are coerced to objects.
  11574. *
  11575. * @static
  11576. * @memberOf _
  11577. * @category Object
  11578. * @param {Object} object The object to query.
  11579. * @returns {Array} Returns the array of property values.
  11580. * @example
  11581. *
  11582. * function Foo() {
  11583. * this.a = 1;
  11584. * this.b = 2;
  11585. * }
  11586. *
  11587. * Foo.prototype.c = 3;
  11588. *
  11589. * _.values(new Foo);
  11590. * // => [1, 2] (iteration order is not guaranteed)
  11591. *
  11592. * _.values('hi');
  11593. * // => ['h', 'i']
  11594. */
  11595. function values(object) {
  11596. return object ? baseValues(object, keys(object)) : [];
  11597. }
  11598. /**
  11599. * Creates an array of the own and inherited enumerable property values of `object`.
  11600. *
  11601. * **Note:** Non-object values are coerced to objects.
  11602. *
  11603. * @static
  11604. * @memberOf _
  11605. * @category Object
  11606. * @param {Object} object The object to query.
  11607. * @returns {Array} Returns the array of property values.
  11608. * @example
  11609. *
  11610. * function Foo() {
  11611. * this.a = 1;
  11612. * this.b = 2;
  11613. * }
  11614. *
  11615. * Foo.prototype.c = 3;
  11616. *
  11617. * _.valuesIn(new Foo);
  11618. * // => [1, 2, 3] (iteration order is not guaranteed)
  11619. */
  11620. function valuesIn(object) {
  11621. return object == null ? [] : baseValues(object, keysIn(object));
  11622. }
  11623. /*------------------------------------------------------------------------*/
  11624. /**
  11625. * Clamps `number` within the inclusive `lower` and `upper` bounds.
  11626. *
  11627. * @static
  11628. * @memberOf _
  11629. * @category Number
  11630. * @param {number} number The number to clamp.
  11631. * @param {number} [lower] The lower bound.
  11632. * @param {number} upper The upper bound.
  11633. * @returns {number} Returns the clamped number.
  11634. * @example
  11635. *
  11636. * _.clamp(-10, -5, 5);
  11637. * // => -5
  11638. *
  11639. * _.clamp(10, -5, 5);
  11640. * // => 5
  11641. */
  11642. function clamp(number, lower, upper) {
  11643. if (upper === undefined) {
  11644. upper = lower;
  11645. lower = undefined;
  11646. }
  11647. if (upper !== undefined) {
  11648. upper = toNumber(upper);
  11649. upper = upper === upper ? upper : 0;
  11650. }
  11651. if (lower !== undefined) {
  11652. lower = toNumber(lower);
  11653. lower = lower === lower ? lower : 0;
  11654. }
  11655. return baseClamp(toNumber(number), lower, upper);
  11656. }
  11657. /**
  11658. * Checks if `n` is between `start` and up to but not including, `end`. If
  11659. * `end` is not specified it's set to `start` with `start` then set to `0`.
  11660. * If `start` is greater than `end` the params are swapped to support
  11661. * negative ranges.
  11662. *
  11663. * @static
  11664. * @memberOf _
  11665. * @category Number
  11666. * @param {number} number The number to check.
  11667. * @param {number} [start=0] The start of the range.
  11668. * @param {number} end The end of the range.
  11669. * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
  11670. * @example
  11671. *
  11672. * _.inRange(3, 2, 4);
  11673. * // => true
  11674. *
  11675. * _.inRange(4, 8);
  11676. * // => true
  11677. *
  11678. * _.inRange(4, 2);
  11679. * // => false
  11680. *
  11681. * _.inRange(2, 2);
  11682. * // => false
  11683. *
  11684. * _.inRange(1.2, 2);
  11685. * // => true
  11686. *
  11687. * _.inRange(5.2, 4);
  11688. * // => false
  11689. *
  11690. * _.inRange(-3, -2, -6);
  11691. * // => true
  11692. */
  11693. function inRange(number, start, end) {
  11694. start = toNumber(start) || 0;
  11695. if (end === undefined) {
  11696. end = start;
  11697. start = 0;
  11698. } else {
  11699. end = toNumber(end) || 0;
  11700. }
  11701. number = toNumber(number);
  11702. return baseInRange(number, start, end);
  11703. }
  11704. /**
  11705. * Produces a random number between the inclusive `lower` and `upper` bounds.
  11706. * If only one argument is provided a number between `0` and the given number
  11707. * is returned. If `floating` is `true`, or either `lower` or `upper` are floats,
  11708. * a floating-point number is returned instead of an integer.
  11709. *
  11710. * **Note:** JavaScript follows the IEEE-754 standard for resolving
  11711. * floating-point values which can produce unexpected results.
  11712. *
  11713. * @static
  11714. * @memberOf _
  11715. * @category Number
  11716. * @param {number} [lower=0] The lower bound.
  11717. * @param {number} [upper=1] The upper bound.
  11718. * @param {boolean} [floating] Specify returning a floating-point number.
  11719. * @returns {number} Returns the random number.
  11720. * @example
  11721. *
  11722. * _.random(0, 5);
  11723. * // => an integer between 0 and 5
  11724. *
  11725. * _.random(5);
  11726. * // => also an integer between 0 and 5
  11727. *
  11728. * _.random(5, true);
  11729. * // => a floating-point number between 0 and 5
  11730. *
  11731. * _.random(1.2, 5.2);
  11732. * // => a floating-point number between 1.2 and 5.2
  11733. */
  11734. function random(lower, upper, floating) {
  11735. if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
  11736. upper = floating = undefined;
  11737. }
  11738. if (floating === undefined) {
  11739. if (typeof upper == 'boolean') {
  11740. floating = upper;
  11741. upper = undefined;
  11742. }
  11743. else if (typeof lower == 'boolean') {
  11744. floating = lower;
  11745. lower = undefined;
  11746. }
  11747. }
  11748. if (lower === undefined && upper === undefined) {
  11749. lower = 0;
  11750. upper = 1;
  11751. }
  11752. else {
  11753. lower = toNumber(lower) || 0;
  11754. if (upper === undefined) {
  11755. upper = lower;
  11756. lower = 0;
  11757. } else {
  11758. upper = toNumber(upper) || 0;
  11759. }
  11760. }
  11761. if (lower > upper) {
  11762. var temp = lower;
  11763. lower = upper;
  11764. upper = temp;
  11765. }
  11766. if (floating || lower % 1 || upper % 1) {
  11767. var rand = nativeRandom();
  11768. return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
  11769. }
  11770. return baseRandom(lower, upper);
  11771. }
  11772. /*------------------------------------------------------------------------*/
  11773. /**
  11774. * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
  11775. *
  11776. * @static
  11777. * @memberOf _
  11778. * @category String
  11779. * @param {string} [string=''] The string to convert.
  11780. * @returns {string} Returns the camel cased string.
  11781. * @example
  11782. *
  11783. * _.camelCase('Foo Bar');
  11784. * // => 'fooBar'
  11785. *
  11786. * _.camelCase('--foo-bar');
  11787. * // => 'fooBar'
  11788. *
  11789. * _.camelCase('__foo_bar__');
  11790. * // => 'fooBar'
  11791. */
  11792. var camelCase = createCompounder(function(result, word, index) {
  11793. word = word.toLowerCase();
  11794. return result + (index ? capitalize(word) : word);
  11795. });
  11796. /**
  11797. * Converts the first character of `string` to upper case and the remaining
  11798. * to lower case.
  11799. *
  11800. * @static
  11801. * @memberOf _
  11802. * @category String
  11803. * @param {string} [string=''] The string to capitalize.
  11804. * @returns {string} Returns the capitalized string.
  11805. * @example
  11806. *
  11807. * _.capitalize('FRED');
  11808. * // => 'Fred'
  11809. */
  11810. function capitalize(string) {
  11811. return upperFirst(toString(string).toLowerCase());
  11812. }
  11813. /**
  11814. * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
  11815. * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
  11816. *
  11817. * @static
  11818. * @memberOf _
  11819. * @category String
  11820. * @param {string} [string=''] The string to deburr.
  11821. * @returns {string} Returns the deburred string.
  11822. * @example
  11823. *
  11824. * _.deburr('déjà vu');
  11825. * // => 'deja vu'
  11826. */
  11827. function deburr(string) {
  11828. string = toString(string);
  11829. return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
  11830. }
  11831. /**
  11832. * Checks if `string` ends with the given target string.
  11833. *
  11834. * @static
  11835. * @memberOf _
  11836. * @category String
  11837. * @param {string} [string=''] The string to search.
  11838. * @param {string} [target] The string to search for.
  11839. * @param {number} [position=string.length] The position to search from.
  11840. * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.
  11841. * @example
  11842. *
  11843. * _.endsWith('abc', 'c');
  11844. * // => true
  11845. *
  11846. * _.endsWith('abc', 'b');
  11847. * // => false
  11848. *
  11849. * _.endsWith('abc', 'b', 2);
  11850. * // => true
  11851. */
  11852. function endsWith(string, target, position) {
  11853. string = toString(string);
  11854. target = typeof target == 'string' ? target : (target + '');
  11855. var length = string.length;
  11856. position = position === undefined
  11857. ? length
  11858. : baseClamp(toInteger(position), 0, length);
  11859. position -= target.length;
  11860. return position >= 0 && string.indexOf(target, position) == position;
  11861. }
  11862. /**
  11863. * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to
  11864. * their corresponding HTML entities.
  11865. *
  11866. * **Note:** No other characters are escaped. To escape additional
  11867. * characters use a third-party library like [_he_](https://mths.be/he).
  11868. *
  11869. * Though the ">" character is escaped for symmetry, characters like
  11870. * ">" and "/" don't need escaping in HTML and have no special meaning
  11871. * unless they're part of a tag or unquoted attribute value.
  11872. * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
  11873. * (under "semi-related fun fact") for more details.
  11874. *
  11875. * Backticks are escaped because in IE < 9, they can break out of
  11876. * attribute values or HTML comments. See [#59](https://html5sec.org/#59),
  11877. * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
  11878. * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
  11879. * for more details.
  11880. *
  11881. * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
  11882. * to reduce XSS vectors.
  11883. *
  11884. * @static
  11885. * @memberOf _
  11886. * @category String
  11887. * @param {string} [string=''] The string to escape.
  11888. * @returns {string} Returns the escaped string.
  11889. * @example
  11890. *
  11891. * _.escape('fred, barney, & pebbles');
  11892. * // => 'fred, barney, &amp; pebbles'
  11893. */
  11894. function escape(string) {
  11895. string = toString(string);
  11896. return (string && reHasUnescapedHtml.test(string))
  11897. ? string.replace(reUnescapedHtml, escapeHtmlChar)
  11898. : string;
  11899. }
  11900. /**
  11901. * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
  11902. * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
  11903. *
  11904. * @static
  11905. * @memberOf _
  11906. * @category String
  11907. * @param {string} [string=''] The string to escape.
  11908. * @returns {string} Returns the escaped string.
  11909. * @example
  11910. *
  11911. * _.escapeRegExp('[lodash](https://lodash.com/)');
  11912. * // => '\[lodash\]\(https://lodash\.com/\)'
  11913. */
  11914. function escapeRegExp(string) {
  11915. string = toString(string);
  11916. return (string && reHasRegExpChar.test(string))
  11917. ? string.replace(reRegExpChar, '\\$&')
  11918. : string;
  11919. }
  11920. /**
  11921. * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
  11922. *
  11923. * @static
  11924. * @memberOf _
  11925. * @category String
  11926. * @param {string} [string=''] The string to convert.
  11927. * @returns {string} Returns the kebab cased string.
  11928. * @example
  11929. *
  11930. * _.kebabCase('Foo Bar');
  11931. * // => 'foo-bar'
  11932. *
  11933. * _.kebabCase('fooBar');
  11934. * // => 'foo-bar'
  11935. *
  11936. * _.kebabCase('__foo_bar__');
  11937. * // => 'foo-bar'
  11938. */
  11939. var kebabCase = createCompounder(function(result, word, index) {
  11940. return result + (index ? '-' : '') + word.toLowerCase();
  11941. });
  11942. /**
  11943. * Converts `string`, as space separated words, to lower case.
  11944. *
  11945. * @static
  11946. * @memberOf _
  11947. * @category String
  11948. * @param {string} [string=''] The string to convert.
  11949. * @returns {string} Returns the lower cased string.
  11950. * @example
  11951. *
  11952. * _.lowerCase('--Foo-Bar');
  11953. * // => 'foo bar'
  11954. *
  11955. * _.lowerCase('fooBar');
  11956. * // => 'foo bar'
  11957. *
  11958. * _.lowerCase('__FOO_BAR__');
  11959. * // => 'foo bar'
  11960. */
  11961. var lowerCase = createCompounder(function(result, word, index) {
  11962. return result + (index ? ' ' : '') + word.toLowerCase();
  11963. });
  11964. /**
  11965. * Converts the first character of `string` to lower case.
  11966. *
  11967. * @static
  11968. * @memberOf _
  11969. * @category String
  11970. * @param {string} [string=''] The string to convert.
  11971. * @returns {string} Returns the converted string.
  11972. * @example
  11973. *
  11974. * _.lowerFirst('Fred');
  11975. * // => 'fred'
  11976. *
  11977. * _.lowerFirst('FRED');
  11978. * // => 'fRED'
  11979. */
  11980. var lowerFirst = createCaseFirst('toLowerCase');
  11981. /**
  11982. * Converts the first character of `string` to upper case.
  11983. *
  11984. * @static
  11985. * @memberOf _
  11986. * @category String
  11987. * @param {string} [string=''] The string to convert.
  11988. * @returns {string} Returns the converted string.
  11989. * @example
  11990. *
  11991. * _.upperFirst('fred');
  11992. * // => 'Fred'
  11993. *
  11994. * _.upperFirst('FRED');
  11995. * // => 'FRED'
  11996. */
  11997. var upperFirst = createCaseFirst('toUpperCase');
  11998. /**
  11999. * Pads `string` on the left and right sides if it's shorter than `length`.
  12000. * Padding characters are truncated if they can't be evenly divided by `length`.
  12001. *
  12002. * @static
  12003. * @memberOf _
  12004. * @category String
  12005. * @param {string} [string=''] The string to pad.
  12006. * @param {number} [length=0] The padding length.
  12007. * @param {string} [chars=' '] The string used as padding.
  12008. * @returns {string} Returns the padded string.
  12009. * @example
  12010. *
  12011. * _.pad('abc', 8);
  12012. * // => ' abc '
  12013. *
  12014. * _.pad('abc', 8, '_-');
  12015. * // => '_-abc_-_'
  12016. *
  12017. * _.pad('abc', 3);
  12018. * // => 'abc'
  12019. */
  12020. function pad(string, length, chars) {
  12021. string = toString(string);
  12022. length = toInteger(length);
  12023. var strLength = stringSize(string);
  12024. if (!length || strLength >= length) {
  12025. return string;
  12026. }
  12027. var mid = (length - strLength) / 2,
  12028. leftLength = nativeFloor(mid),
  12029. rightLength = nativeCeil(mid);
  12030. return createPadding('', leftLength, chars) + string + createPadding('', rightLength, chars);
  12031. }
  12032. /**
  12033. * Pads `string` on the right side if it's shorter than `length`. Padding
  12034. * characters are truncated if they exceed `length`.
  12035. *
  12036. * @static
  12037. * @memberOf _
  12038. * @category String
  12039. * @param {string} [string=''] The string to pad.
  12040. * @param {number} [length=0] The padding length.
  12041. * @param {string} [chars=' '] The string used as padding.
  12042. * @returns {string} Returns the padded string.
  12043. * @example
  12044. *
  12045. * _.padEnd('abc', 6);
  12046. * // => 'abc '
  12047. *
  12048. * _.padEnd('abc', 6, '_-');
  12049. * // => 'abc_-_'
  12050. *
  12051. * _.padEnd('abc', 3);
  12052. * // => 'abc'
  12053. */
  12054. function padEnd(string, length, chars) {
  12055. string = toString(string);
  12056. return string + createPadding(string, length, chars);
  12057. }
  12058. /**
  12059. * Pads `string` on the left side if it's shorter than `length`. Padding
  12060. * characters are truncated if they exceed `length`.
  12061. *
  12062. * @static
  12063. * @memberOf _
  12064. * @category String
  12065. * @param {string} [string=''] The string to pad.
  12066. * @param {number} [length=0] The padding length.
  12067. * @param {string} [chars=' '] The string used as padding.
  12068. * @returns {string} Returns the padded string.
  12069. * @example
  12070. *
  12071. * _.padStart('abc', 6);
  12072. * // => ' abc'
  12073. *
  12074. * _.padStart('abc', 6, '_-');
  12075. * // => '_-_abc'
  12076. *
  12077. * _.padStart('abc', 3);
  12078. * // => 'abc'
  12079. */
  12080. function padStart(string, length, chars) {
  12081. string = toString(string);
  12082. return createPadding(string, length, chars) + string;
  12083. }
  12084. /**
  12085. * Converts `string` to an integer of the specified radix. If `radix` is
  12086. * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
  12087. * in which case a `radix` of `16` is used.
  12088. *
  12089. * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#x15.1.2.2)
  12090. * of `parseInt`.
  12091. *
  12092. * @static
  12093. * @memberOf _
  12094. * @category String
  12095. * @param {string} string The string to convert.
  12096. * @param {number} [radix=10] The radix to interpret `value` by.
  12097. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12098. * @returns {number} Returns the converted integer.
  12099. * @example
  12100. *
  12101. * _.parseInt('08');
  12102. * // => 8
  12103. *
  12104. * _.map(['6', '08', '10'], _.parseInt);
  12105. * // => [6, 8, 10]
  12106. */
  12107. function parseInt(string, radix, guard) {
  12108. // Chrome fails to trim leading <BOM> whitespace characters.
  12109. // See https://code.google.com/p/v8/issues/detail?id=3109 for more details.
  12110. if (guard || radix == null) {
  12111. radix = 0;
  12112. } else if (radix) {
  12113. radix = +radix;
  12114. }
  12115. string = toString(string).replace(reTrim, '');
  12116. return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
  12117. }
  12118. /**
  12119. * Repeats the given string `n` times.
  12120. *
  12121. * @static
  12122. * @memberOf _
  12123. * @category String
  12124. * @param {string} [string=''] The string to repeat.
  12125. * @param {number} [n=0] The number of times to repeat the string.
  12126. * @returns {string} Returns the repeated string.
  12127. * @example
  12128. *
  12129. * _.repeat('*', 3);
  12130. * // => '***'
  12131. *
  12132. * _.repeat('abc', 2);
  12133. * // => 'abcabc'
  12134. *
  12135. * _.repeat('abc', 0);
  12136. * // => ''
  12137. */
  12138. function repeat(string, n) {
  12139. string = toString(string);
  12140. n = toInteger(n);
  12141. var result = '';
  12142. if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
  12143. return result;
  12144. }
  12145. // Leverage the exponentiation by squaring algorithm for a faster repeat.
  12146. // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
  12147. do {
  12148. if (n % 2) {
  12149. result += string;
  12150. }
  12151. n = nativeFloor(n / 2);
  12152. string += string;
  12153. } while (n);
  12154. return result;
  12155. }
  12156. /**
  12157. * Replaces matches for `pattern` in `string` with `replacement`.
  12158. *
  12159. * **Note:** This method is based on [`String#replace`](https://mdn.io/String/replace).
  12160. *
  12161. * @static
  12162. * @memberOf _
  12163. * @category String
  12164. * @param {string} [string=''] The string to modify.
  12165. * @param {RegExp|string} pattern The pattern to replace.
  12166. * @param {Function|string} replacement The match replacement.
  12167. * @returns {string} Returns the modified string.
  12168. * @example
  12169. *
  12170. * _.replace('Hi Fred', 'Fred', 'Barney');
  12171. * // => 'Hi Barney'
  12172. */
  12173. function replace() {
  12174. var args = arguments,
  12175. string = toString(args[0]);
  12176. return args.length < 3 ? string : string.replace(args[1], args[2]);
  12177. }
  12178. /**
  12179. * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).
  12180. *
  12181. * @static
  12182. * @memberOf _
  12183. * @category String
  12184. * @param {string} [string=''] The string to convert.
  12185. * @returns {string} Returns the snake cased string.
  12186. * @example
  12187. *
  12188. * _.snakeCase('Foo Bar');
  12189. * // => 'foo_bar'
  12190. *
  12191. * _.snakeCase('fooBar');
  12192. * // => 'foo_bar'
  12193. *
  12194. * _.snakeCase('--foo-bar');
  12195. * // => 'foo_bar'
  12196. */
  12197. var snakeCase = createCompounder(function(result, word, index) {
  12198. return result + (index ? '_' : '') + word.toLowerCase();
  12199. });
  12200. /**
  12201. * Splits `string` by `separator`.
  12202. *
  12203. * **Note:** This method is based on [`String#split`](https://mdn.io/String/split).
  12204. *
  12205. * @static
  12206. * @memberOf _
  12207. * @category String
  12208. * @param {string} [string=''] The string to split.
  12209. * @param {RegExp|string} separator The separator pattern to split by.
  12210. * @param {number} [limit] The length to truncate results to.
  12211. * @returns {Array} Returns the new array of string segments.
  12212. * @example
  12213. *
  12214. * _.split('a-b-c', '-', 2);
  12215. * // => ['a', 'b']
  12216. */
  12217. function split(string, separator, limit) {
  12218. return toString(string).split(separator, limit);
  12219. }
  12220. /**
  12221. * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
  12222. *
  12223. * @static
  12224. * @memberOf _
  12225. * @category String
  12226. * @param {string} [string=''] The string to convert.
  12227. * @returns {string} Returns the start cased string.
  12228. * @example
  12229. *
  12230. * _.startCase('--foo-bar');
  12231. * // => 'Foo Bar'
  12232. *
  12233. * _.startCase('fooBar');
  12234. * // => 'Foo Bar'
  12235. *
  12236. * _.startCase('__foo_bar__');
  12237. * // => 'Foo Bar'
  12238. */
  12239. var startCase = createCompounder(function(result, word, index) {
  12240. return result + (index ? ' ' : '') + capitalize(word);
  12241. });
  12242. /**
  12243. * Checks if `string` starts with the given target string.
  12244. *
  12245. * @static
  12246. * @memberOf _
  12247. * @category String
  12248. * @param {string} [string=''] The string to search.
  12249. * @param {string} [target] The string to search for.
  12250. * @param {number} [position=0] The position to search from.
  12251. * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.
  12252. * @example
  12253. *
  12254. * _.startsWith('abc', 'a');
  12255. * // => true
  12256. *
  12257. * _.startsWith('abc', 'b');
  12258. * // => false
  12259. *
  12260. * _.startsWith('abc', 'b', 1);
  12261. * // => true
  12262. */
  12263. function startsWith(string, target, position) {
  12264. string = toString(string);
  12265. position = baseClamp(toInteger(position), 0, string.length);
  12266. return string.lastIndexOf(target, position) == position;
  12267. }
  12268. /**
  12269. * Creates a compiled template function that can interpolate data properties
  12270. * in "interpolate" delimiters, HTML-escape interpolated data properties in
  12271. * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
  12272. * properties may be accessed as free variables in the template. If a setting
  12273. * object is given it takes precedence over `_.templateSettings` values.
  12274. *
  12275. * **Note:** In the development build `_.template` utilizes
  12276. * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
  12277. * for easier debugging.
  12278. *
  12279. * For more information on precompiling templates see
  12280. * [lodash's custom builds documentation](https://lodash.com/custom-builds).
  12281. *
  12282. * For more information on Chrome extension sandboxes see
  12283. * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
  12284. *
  12285. * @static
  12286. * @memberOf _
  12287. * @category String
  12288. * @param {string} [string=''] The template string.
  12289. * @param {Object} [options] The options object.
  12290. * @param {RegExp} [options.escape] The HTML "escape" delimiter.
  12291. * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
  12292. * @param {Object} [options.imports] An object to import into the template as free variables.
  12293. * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
  12294. * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
  12295. * @param {string} [options.variable] The data object variable name.
  12296. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12297. * @returns {Function} Returns the compiled template function.
  12298. * @example
  12299. *
  12300. * // Use the "interpolate" delimiter to create a compiled template.
  12301. * var compiled = _.template('hello <%= user %>!');
  12302. * compiled({ 'user': 'fred' });
  12303. * // => 'hello fred!'
  12304. *
  12305. * // Use the HTML "escape" delimiter to escape data property values.
  12306. * var compiled = _.template('<b><%- value %></b>');
  12307. * compiled({ 'value': '<script>' });
  12308. * // => '<b>&lt;script&gt;</b>'
  12309. *
  12310. * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
  12311. * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
  12312. * compiled({ 'users': ['fred', 'barney'] });
  12313. * // => '<li>fred</li><li>barney</li>'
  12314. *
  12315. * // Use the internal `print` function in "evaluate" delimiters.
  12316. * var compiled = _.template('<% print("hello " + user); %>!');
  12317. * compiled({ 'user': 'barney' });
  12318. * // => 'hello barney!'
  12319. *
  12320. * // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
  12321. * var compiled = _.template('hello ${ user }!');
  12322. * compiled({ 'user': 'pebbles' });
  12323. * // => 'hello pebbles!'
  12324. *
  12325. * // Use custom template delimiters.
  12326. * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
  12327. * var compiled = _.template('hello {{ user }}!');
  12328. * compiled({ 'user': 'mustache' });
  12329. * // => 'hello mustache!'
  12330. *
  12331. * // Use backslashes to treat delimiters as plain text.
  12332. * var compiled = _.template('<%= "\\<%- value %\\>" %>');
  12333. * compiled({ 'value': 'ignored' });
  12334. * // => '<%- value %>'
  12335. *
  12336. * // Use the `imports` option to import `jQuery` as `jq`.
  12337. * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
  12338. * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
  12339. * compiled({ 'users': ['fred', 'barney'] });
  12340. * // => '<li>fred</li><li>barney</li>'
  12341. *
  12342. * // Use the `sourceURL` option to specify a custom sourceURL for the template.
  12343. * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
  12344. * compiled(data);
  12345. * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
  12346. *
  12347. * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
  12348. * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
  12349. * compiled.source;
  12350. * // => function(data) {
  12351. * // var __t, __p = '';
  12352. * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
  12353. * // return __p;
  12354. * // }
  12355. *
  12356. * // Use the `source` property to inline compiled templates for meaningful
  12357. * // line numbers in error messages and stack traces.
  12358. * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
  12359. * var JST = {\
  12360. * "main": ' + _.template(mainText).source + '\
  12361. * };\
  12362. * ');
  12363. */
  12364. function template(string, options, guard) {
  12365. // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)
  12366. // and Laura Doktorova's doT.js (https://github.com/olado/doT).
  12367. var settings = lodash.templateSettings;
  12368. if (guard && isIterateeCall(string, options, guard)) {
  12369. options = undefined;
  12370. }
  12371. string = toString(string);
  12372. options = assignInWith({}, options, settings, assignInDefaults);
  12373. var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
  12374. importsKeys = keys(imports),
  12375. importsValues = baseValues(imports, importsKeys);
  12376. var isEscaping,
  12377. isEvaluating,
  12378. index = 0,
  12379. interpolate = options.interpolate || reNoMatch,
  12380. source = "__p += '";
  12381. // Compile the regexp to match each delimiter.
  12382. var reDelimiters = RegExp(
  12383. (options.escape || reNoMatch).source + '|' +
  12384. interpolate.source + '|' +
  12385. (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
  12386. (options.evaluate || reNoMatch).source + '|$'
  12387. , 'g');
  12388. // Use a sourceURL for easier debugging.
  12389. var sourceURL = '//# sourceURL=' +
  12390. ('sourceURL' in options
  12391. ? options.sourceURL
  12392. : ('lodash.templateSources[' + (++templateCounter) + ']')
  12393. ) + '\n';
  12394. string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
  12395. interpolateValue || (interpolateValue = esTemplateValue);
  12396. // Escape characters that can't be included in string literals.
  12397. source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
  12398. // Replace delimiters with snippets.
  12399. if (escapeValue) {
  12400. isEscaping = true;
  12401. source += "' +\n__e(" + escapeValue + ") +\n'";
  12402. }
  12403. if (evaluateValue) {
  12404. isEvaluating = true;
  12405. source += "';\n" + evaluateValue + ";\n__p += '";
  12406. }
  12407. if (interpolateValue) {
  12408. source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
  12409. }
  12410. index = offset + match.length;
  12411. // The JS engine embedded in Adobe products needs `match` returned in
  12412. // order to produce the correct `offset` value.
  12413. return match;
  12414. });
  12415. source += "';\n";
  12416. // If `variable` is not specified wrap a with-statement around the generated
  12417. // code to add the data object to the top of the scope chain.
  12418. var variable = options.variable;
  12419. if (!variable) {
  12420. source = 'with (obj) {\n' + source + '\n}\n';
  12421. }
  12422. // Cleanup code by stripping empty strings.
  12423. source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
  12424. .replace(reEmptyStringMiddle, '$1')
  12425. .replace(reEmptyStringTrailing, '$1;');
  12426. // Frame code as the function body.
  12427. source = 'function(' + (variable || 'obj') + ') {\n' +
  12428. (variable
  12429. ? ''
  12430. : 'obj || (obj = {});\n'
  12431. ) +
  12432. "var __t, __p = ''" +
  12433. (isEscaping
  12434. ? ', __e = _.escape'
  12435. : ''
  12436. ) +
  12437. (isEvaluating
  12438. ? ', __j = Array.prototype.join;\n' +
  12439. "function print() { __p += __j.call(arguments, '') }\n"
  12440. : ';\n'
  12441. ) +
  12442. source +
  12443. 'return __p\n}';
  12444. var result = attempt(function() {
  12445. return Function(importsKeys, sourceURL + 'return ' + source)
  12446. .apply(undefined, importsValues);
  12447. });
  12448. // Provide the compiled function's source by its `toString` method or
  12449. // the `source` property as a convenience for inlining compiled templates.
  12450. result.source = source;
  12451. if (isError(result)) {
  12452. throw result;
  12453. }
  12454. return result;
  12455. }
  12456. /**
  12457. * Converts `string`, as a whole, to lower case.
  12458. *
  12459. * @static
  12460. * @memberOf _
  12461. * @category String
  12462. * @param {string} [string=''] The string to convert.
  12463. * @returns {string} Returns the lower cased string.
  12464. * @example
  12465. *
  12466. * _.toLower('--Foo-Bar');
  12467. * // => '--foo-bar'
  12468. *
  12469. * _.toLower('fooBar');
  12470. * // => 'foobar'
  12471. *
  12472. * _.toLower('__FOO_BAR__');
  12473. * // => '__foo_bar__'
  12474. */
  12475. function toLower(value) {
  12476. return toString(value).toLowerCase();
  12477. }
  12478. /**
  12479. * Converts `string`, as a whole, to upper case.
  12480. *
  12481. * @static
  12482. * @memberOf _
  12483. * @category String
  12484. * @param {string} [string=''] The string to convert.
  12485. * @returns {string} Returns the upper cased string.
  12486. * @example
  12487. *
  12488. * _.toUpper('--foo-bar');
  12489. * // => '--FOO-BAR'
  12490. *
  12491. * _.toUpper('fooBar');
  12492. * // => 'FOOBAR'
  12493. *
  12494. * _.toUpper('__foo_bar__');
  12495. * // => '__FOO_BAR__'
  12496. */
  12497. function toUpper(value) {
  12498. return toString(value).toUpperCase();
  12499. }
  12500. /**
  12501. * Removes leading and trailing whitespace or specified characters from `string`.
  12502. *
  12503. * @static
  12504. * @memberOf _
  12505. * @category String
  12506. * @param {string} [string=''] The string to trim.
  12507. * @param {string} [chars=whitespace] The characters to trim.
  12508. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12509. * @returns {string} Returns the trimmed string.
  12510. * @example
  12511. *
  12512. * _.trim(' abc ');
  12513. * // => 'abc'
  12514. *
  12515. * _.trim('-_-abc-_-', '_-');
  12516. * // => 'abc'
  12517. *
  12518. * _.map([' foo ', ' bar '], _.trim);
  12519. * // => ['foo', 'bar']
  12520. */
  12521. function trim(string, chars, guard) {
  12522. string = toString(string);
  12523. if (!string) {
  12524. return string;
  12525. }
  12526. if (guard || chars === undefined) {
  12527. return string.replace(reTrim, '');
  12528. }
  12529. chars = (chars + '');
  12530. if (!chars) {
  12531. return string;
  12532. }
  12533. var strSymbols = stringToArray(string),
  12534. chrSymbols = stringToArray(chars);
  12535. return strSymbols
  12536. .slice(charsStartIndex(strSymbols, chrSymbols), charsEndIndex(strSymbols, chrSymbols) + 1)
  12537. .join('');
  12538. }
  12539. /**
  12540. * Removes trailing whitespace or specified characters from `string`.
  12541. *
  12542. * @static
  12543. * @memberOf _
  12544. * @category String
  12545. * @param {string} [string=''] The string to trim.
  12546. * @param {string} [chars=whitespace] The characters to trim.
  12547. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12548. * @returns {string} Returns the trimmed string.
  12549. * @example
  12550. *
  12551. * _.trimEnd(' abc ');
  12552. * // => ' abc'
  12553. *
  12554. * _.trimEnd('-_-abc-_-', '_-');
  12555. * // => '-_-abc'
  12556. */
  12557. function trimEnd(string, chars, guard) {
  12558. string = toString(string);
  12559. if (!string) {
  12560. return string;
  12561. }
  12562. if (guard || chars === undefined) {
  12563. return string.replace(reTrimEnd, '');
  12564. }
  12565. chars = (chars + '');
  12566. if (!chars) {
  12567. return string;
  12568. }
  12569. var strSymbols = stringToArray(string);
  12570. return strSymbols
  12571. .slice(0, charsEndIndex(strSymbols, stringToArray(chars)) + 1)
  12572. .join('');
  12573. }
  12574. /**
  12575. * Removes leading whitespace or specified characters from `string`.
  12576. *
  12577. * @static
  12578. * @memberOf _
  12579. * @category String
  12580. * @param {string} [string=''] The string to trim.
  12581. * @param {string} [chars=whitespace] The characters to trim.
  12582. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12583. * @returns {string} Returns the trimmed string.
  12584. * @example
  12585. *
  12586. * _.trimStart(' abc ');
  12587. * // => 'abc '
  12588. *
  12589. * _.trimStart('-_-abc-_-', '_-');
  12590. * // => 'abc-_-'
  12591. */
  12592. function trimStart(string, chars, guard) {
  12593. string = toString(string);
  12594. if (!string) {
  12595. return string;
  12596. }
  12597. if (guard || chars === undefined) {
  12598. return string.replace(reTrimStart, '');
  12599. }
  12600. chars = (chars + '');
  12601. if (!chars) {
  12602. return string;
  12603. }
  12604. var strSymbols = stringToArray(string);
  12605. return strSymbols
  12606. .slice(charsStartIndex(strSymbols, stringToArray(chars)))
  12607. .join('');
  12608. }
  12609. /**
  12610. * Truncates `string` if it's longer than the given maximum string length.
  12611. * The last characters of the truncated string are replaced with the omission
  12612. * string which defaults to "...".
  12613. *
  12614. * @static
  12615. * @memberOf _
  12616. * @category String
  12617. * @param {string} [string=''] The string to truncate.
  12618. * @param {Object} [options=({})] The options object.
  12619. * @param {number} [options.length=30] The maximum string length.
  12620. * @param {string} [options.omission='...'] The string to indicate text is omitted.
  12621. * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
  12622. * @returns {string} Returns the truncated string.
  12623. * @example
  12624. *
  12625. * _.truncate('hi-diddly-ho there, neighborino');
  12626. * // => 'hi-diddly-ho there, neighbo...'
  12627. *
  12628. * _.truncate('hi-diddly-ho there, neighborino', {
  12629. * 'length': 24,
  12630. * 'separator': ' '
  12631. * });
  12632. * // => 'hi-diddly-ho there,...'
  12633. *
  12634. * _.truncate('hi-diddly-ho there, neighborino', {
  12635. * 'length': 24,
  12636. * 'separator': /,? +/
  12637. * });
  12638. * // => 'hi-diddly-ho there...'
  12639. *
  12640. * _.truncate('hi-diddly-ho there, neighborino', {
  12641. * 'omission': ' [...]'
  12642. * });
  12643. * // => 'hi-diddly-ho there, neig [...]'
  12644. */
  12645. function truncate(string, options) {
  12646. var length = DEFAULT_TRUNC_LENGTH,
  12647. omission = DEFAULT_TRUNC_OMISSION;
  12648. if (isObject(options)) {
  12649. var separator = 'separator' in options ? options.separator : separator;
  12650. length = 'length' in options ? toInteger(options.length) : length;
  12651. omission = 'omission' in options ? toString(options.omission) : omission;
  12652. }
  12653. string = toString(string);
  12654. var strLength = string.length;
  12655. if (reHasComplexSymbol.test(string)) {
  12656. var strSymbols = stringToArray(string);
  12657. strLength = strSymbols.length;
  12658. }
  12659. if (length >= strLength) {
  12660. return string;
  12661. }
  12662. var end = length - stringSize(omission);
  12663. if (end < 1) {
  12664. return omission;
  12665. }
  12666. var result = strSymbols
  12667. ? strSymbols.slice(0, end).join('')
  12668. : string.slice(0, end);
  12669. if (separator === undefined) {
  12670. return result + omission;
  12671. }
  12672. if (strSymbols) {
  12673. end += (result.length - end);
  12674. }
  12675. if (isRegExp(separator)) {
  12676. if (string.slice(end).search(separator)) {
  12677. var match,
  12678. substring = result;
  12679. if (!separator.global) {
  12680. separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
  12681. }
  12682. separator.lastIndex = 0;
  12683. while ((match = separator.exec(substring))) {
  12684. var newEnd = match.index;
  12685. }
  12686. result = result.slice(0, newEnd === undefined ? end : newEnd);
  12687. }
  12688. } else if (string.indexOf(separator, end) != end) {
  12689. var index = result.lastIndexOf(separator);
  12690. if (index > -1) {
  12691. result = result.slice(0, index);
  12692. }
  12693. }
  12694. return result + omission;
  12695. }
  12696. /**
  12697. * The inverse of `_.escape`; this method converts the HTML entities
  12698. * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their
  12699. * corresponding characters.
  12700. *
  12701. * **Note:** No other HTML entities are unescaped. To unescape additional HTML
  12702. * entities use a third-party library like [_he_](https://mths.be/he).
  12703. *
  12704. * @static
  12705. * @memberOf _
  12706. * @category String
  12707. * @param {string} [string=''] The string to unescape.
  12708. * @returns {string} Returns the unescaped string.
  12709. * @example
  12710. *
  12711. * _.unescape('fred, barney, &amp; pebbles');
  12712. * // => 'fred, barney, & pebbles'
  12713. */
  12714. function unescape(string) {
  12715. string = toString(string);
  12716. return (string && reHasEscapedHtml.test(string))
  12717. ? string.replace(reEscapedHtml, unescapeHtmlChar)
  12718. : string;
  12719. }
  12720. /**
  12721. * Converts `string`, as space separated words, to upper case.
  12722. *
  12723. * @static
  12724. * @memberOf _
  12725. * @category String
  12726. * @param {string} [string=''] The string to convert.
  12727. * @returns {string} Returns the upper cased string.
  12728. * @example
  12729. *
  12730. * _.upperCase('--foo-bar');
  12731. * // => 'FOO BAR'
  12732. *
  12733. * _.upperCase('fooBar');
  12734. * // => 'FOO BAR'
  12735. *
  12736. * _.upperCase('__foo_bar__');
  12737. * // => 'FOO BAR'
  12738. */
  12739. var upperCase = createCompounder(function(result, word, index) {
  12740. return result + (index ? ' ' : '') + word.toUpperCase();
  12741. });
  12742. /**
  12743. * Splits `string` into an array of its words.
  12744. *
  12745. * @static
  12746. * @memberOf _
  12747. * @category String
  12748. * @param {string} [string=''] The string to inspect.
  12749. * @param {RegExp|string} [pattern] The pattern to match words.
  12750. * @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
  12751. * @returns {Array} Returns the words of `string`.
  12752. * @example
  12753. *
  12754. * _.words('fred, barney, & pebbles');
  12755. * // => ['fred', 'barney', 'pebbles']
  12756. *
  12757. * _.words('fred, barney, & pebbles', /[^, ]+/g);
  12758. * // => ['fred', 'barney', '&', 'pebbles']
  12759. */
  12760. function words(string, pattern, guard) {
  12761. string = toString(string);
  12762. pattern = guard ? undefined : pattern;
  12763. if (pattern === undefined) {
  12764. pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord;
  12765. }
  12766. return string.match(pattern) || [];
  12767. }
  12768. /*------------------------------------------------------------------------*/
  12769. /**
  12770. * Attempts to invoke `func`, returning either the result or the caught error
  12771. * object. Any additional arguments are provided to `func` when it's invoked.
  12772. *
  12773. * @static
  12774. * @memberOf _
  12775. * @category Util
  12776. * @param {Function} func The function to attempt.
  12777. * @returns {*} Returns the `func` result or error object.
  12778. * @example
  12779. *
  12780. * // Avoid throwing errors for invalid selectors.
  12781. * var elements = _.attempt(function(selector) {
  12782. * return document.querySelectorAll(selector);
  12783. * }, '>_>');
  12784. *
  12785. * if (_.isError(elements)) {
  12786. * elements = [];
  12787. * }
  12788. */
  12789. var attempt = rest(function(func, args) {
  12790. try {
  12791. return apply(func, undefined, args);
  12792. } catch (e) {
  12793. return isError(e) ? e : new Error(e);
  12794. }
  12795. });
  12796. /**
  12797. * Binds methods of an object to the object itself, overwriting the existing
  12798. * method.
  12799. *
  12800. * **Note:** This method doesn't set the "length" property of bound functions.
  12801. *
  12802. * @static
  12803. * @memberOf _
  12804. * @category Util
  12805. * @param {Object} object The object to bind and assign the bound methods to.
  12806. * @param {...(string|string[])} methodNames The object method names to bind,
  12807. * specified individually or in arrays.
  12808. * @returns {Object} Returns `object`.
  12809. * @example
  12810. *
  12811. * var view = {
  12812. * 'label': 'docs',
  12813. * 'onClick': function() {
  12814. * console.log('clicked ' + this.label);
  12815. * }
  12816. * };
  12817. *
  12818. * _.bindAll(view, 'onClick');
  12819. * jQuery(element).on('click', view.onClick);
  12820. * // => logs 'clicked docs' when clicked
  12821. */
  12822. var bindAll = rest(function(object, methodNames) {
  12823. arrayEach(baseFlatten(methodNames, 1), function(key) {
  12824. object[key] = bind(object[key], object);
  12825. });
  12826. return object;
  12827. });
  12828. /**
  12829. * Creates a function that iterates over `pairs` invoking the corresponding
  12830. * function of the first predicate to return truthy. The predicate-function
  12831. * pairs are invoked with the `this` binding and arguments of the created
  12832. * function.
  12833. *
  12834. * @static
  12835. * @memberOf _
  12836. * @category Util
  12837. * @param {Array} pairs The predicate-function pairs.
  12838. * @returns {Function} Returns the new function.
  12839. * @example
  12840. *
  12841. * var func = _.cond([
  12842. * [_.matches({ 'a': 1 }), _.constant('matches A')],
  12843. * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
  12844. * [_.constant(true), _.constant('no match')]
  12845. * ]);
  12846. *
  12847. * func({ 'a': 1, 'b': 2 });
  12848. * // => 'matches A'
  12849. *
  12850. * func({ 'a': 0, 'b': 1 });
  12851. * // => 'matches B'
  12852. *
  12853. * func({ 'a': '1', 'b': '2' });
  12854. * // => 'no match'
  12855. */
  12856. function cond(pairs) {
  12857. var length = pairs ? pairs.length : 0,
  12858. toIteratee = getIteratee();
  12859. pairs = !length ? [] : arrayMap(pairs, function(pair) {
  12860. if (typeof pair[1] != 'function') {
  12861. throw new TypeError(FUNC_ERROR_TEXT);
  12862. }
  12863. return [toIteratee(pair[0]), pair[1]];
  12864. });
  12865. return rest(function(args) {
  12866. var index = -1;
  12867. while (++index < length) {
  12868. var pair = pairs[index];
  12869. if (apply(pair[0], this, args)) {
  12870. return apply(pair[1], this, args);
  12871. }
  12872. }
  12873. });
  12874. }
  12875. /**
  12876. * Creates a function that invokes the predicate properties of `source` with
  12877. * the corresponding property values of a given object, returning `true` if
  12878. * all predicates return truthy, else `false`.
  12879. *
  12880. * @static
  12881. * @memberOf _
  12882. * @category Util
  12883. * @param {Object} source The object of property predicates to conform to.
  12884. * @returns {Function} Returns the new function.
  12885. * @example
  12886. *
  12887. * var users = [
  12888. * { 'user': 'barney', 'age': 36 },
  12889. * { 'user': 'fred', 'age': 40 }
  12890. * ];
  12891. *
  12892. * _.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) }));
  12893. * // => [{ 'user': 'fred', 'age': 40 }]
  12894. */
  12895. function conforms(source) {
  12896. return baseConforms(baseClone(source, true));
  12897. }
  12898. /**
  12899. * Creates a function that returns `value`.
  12900. *
  12901. * @static
  12902. * @memberOf _
  12903. * @category Util
  12904. * @param {*} value The value to return from the new function.
  12905. * @returns {Function} Returns the new function.
  12906. * @example
  12907. *
  12908. * var object = { 'user': 'fred' };
  12909. * var getter = _.constant(object);
  12910. *
  12911. * getter() === object;
  12912. * // => true
  12913. */
  12914. function constant(value) {
  12915. return function() {
  12916. return value;
  12917. };
  12918. }
  12919. /**
  12920. * Creates a function that returns the result of invoking the given functions
  12921. * with the `this` binding of the created function, where each successive
  12922. * invocation is supplied the return value of the previous.
  12923. *
  12924. * @static
  12925. * @memberOf _
  12926. * @category Util
  12927. * @param {...(Function|Function[])} [funcs] Functions to invoke.
  12928. * @returns {Function} Returns the new function.
  12929. * @example
  12930. *
  12931. * function square(n) {
  12932. * return n * n;
  12933. * }
  12934. *
  12935. * var addSquare = _.flow(_.add, square);
  12936. * addSquare(1, 2);
  12937. * // => 9
  12938. */
  12939. var flow = createFlow();
  12940. /**
  12941. * This method is like `_.flow` except that it creates a function that
  12942. * invokes the given functions from right to left.
  12943. *
  12944. * @static
  12945. * @memberOf _
  12946. * @category Util
  12947. * @param {...(Function|Function[])} [funcs] Functions to invoke.
  12948. * @returns {Function} Returns the new function.
  12949. * @example
  12950. *
  12951. * function square(n) {
  12952. * return n * n;
  12953. * }
  12954. *
  12955. * var addSquare = _.flowRight(square, _.add);
  12956. * addSquare(1, 2);
  12957. * // => 9
  12958. */
  12959. var flowRight = createFlow(true);
  12960. /**
  12961. * This method returns the first argument given to it.
  12962. *
  12963. * @static
  12964. * @memberOf _
  12965. * @category Util
  12966. * @param {*} value Any value.
  12967. * @returns {*} Returns `value`.
  12968. * @example
  12969. *
  12970. * var object = { 'user': 'fred' };
  12971. *
  12972. * _.identity(object) === object;
  12973. * // => true
  12974. */
  12975. function identity(value) {
  12976. return value;
  12977. }
  12978. /**
  12979. * Creates a function that invokes `func` with the arguments of the created
  12980. * function. If `func` is a property name the created callback returns the
  12981. * property value for a given element. If `func` is an object the created
  12982. * callback returns `true` for elements that contain the equivalent object
  12983. * properties, otherwise it returns `false`.
  12984. *
  12985. * @static
  12986. * @memberOf _
  12987. * @category Util
  12988. * @param {*} [func=_.identity] The value to convert to a callback.
  12989. * @returns {Function} Returns the callback.
  12990. * @example
  12991. *
  12992. * var users = [
  12993. * { 'user': 'barney', 'age': 36 },
  12994. * { 'user': 'fred', 'age': 40 }
  12995. * ];
  12996. *
  12997. * // Create custom iteratee shorthands.
  12998. * _.iteratee = _.wrap(_.iteratee, function(callback, func) {
  12999. * var p = /^(\S+)\s*([<>])\s*(\S+)$/.exec(func);
  13000. * return !p ? callback(func) : function(object) {
  13001. * return (p[2] == '>' ? object[p[1]] > p[3] : object[p[1]] < p[3]);
  13002. * };
  13003. * });
  13004. *
  13005. * _.filter(users, 'age > 36');
  13006. * // => [{ 'user': 'fred', 'age': 40 }]
  13007. */
  13008. function iteratee(func) {
  13009. return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
  13010. }
  13011. /**
  13012. * Creates a function that performs a partial deep comparison between a given
  13013. * object and `source`, returning `true` if the given object has equivalent
  13014. * property values, else `false`. The created function is equivalent to
  13015. * `_.isMatch` with a `source` partially applied.
  13016. *
  13017. * **Note:** This method supports comparing the same values as `_.isEqual`.
  13018. *
  13019. * @static
  13020. * @memberOf _
  13021. * @category Util
  13022. * @param {Object} source The object of property values to match.
  13023. * @returns {Function} Returns the new function.
  13024. * @example
  13025. *
  13026. * var users = [
  13027. * { 'user': 'barney', 'age': 36, 'active': true },
  13028. * { 'user': 'fred', 'age': 40, 'active': false }
  13029. * ];
  13030. *
  13031. * _.filter(users, _.matches({ 'age': 40, 'active': false }));
  13032. * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
  13033. */
  13034. function matches(source) {
  13035. return baseMatches(baseClone(source, true));
  13036. }
  13037. /**
  13038. * Creates a function that performs a partial deep comparison between the
  13039. * value at `path` of a given object to `srcValue`, returning `true` if the
  13040. * object value is equivalent, else `false`.
  13041. *
  13042. * **Note:** This method supports comparing the same values as `_.isEqual`.
  13043. *
  13044. * @static
  13045. * @memberOf _
  13046. * @category Util
  13047. * @param {Array|string} path The path of the property to get.
  13048. * @param {*} srcValue The value to match.
  13049. * @returns {Function} Returns the new function.
  13050. * @example
  13051. *
  13052. * var users = [
  13053. * { 'user': 'barney' },
  13054. * { 'user': 'fred' }
  13055. * ];
  13056. *
  13057. * _.find(users, _.matchesProperty('user', 'fred'));
  13058. * // => { 'user': 'fred' }
  13059. */
  13060. function matchesProperty(path, srcValue) {
  13061. return baseMatchesProperty(path, baseClone(srcValue, true));
  13062. }
  13063. /**
  13064. * Creates a function that invokes the method at `path` of a given object.
  13065. * Any additional arguments are provided to the invoked method.
  13066. *
  13067. * @static
  13068. * @memberOf _
  13069. * @category Util
  13070. * @param {Array|string} path The path of the method to invoke.
  13071. * @param {...*} [args] The arguments to invoke the method with.
  13072. * @returns {Function} Returns the new function.
  13073. * @example
  13074. *
  13075. * var objects = [
  13076. * { 'a': { 'b': { 'c': _.constant(2) } } },
  13077. * { 'a': { 'b': { 'c': _.constant(1) } } }
  13078. * ];
  13079. *
  13080. * _.map(objects, _.method('a.b.c'));
  13081. * // => [2, 1]
  13082. *
  13083. * _.invokeMap(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');
  13084. * // => [1, 2]
  13085. */
  13086. var method = rest(function(path, args) {
  13087. return function(object) {
  13088. return baseInvoke(object, path, args);
  13089. };
  13090. });
  13091. /**
  13092. * The opposite of `_.method`; this method creates a function that invokes
  13093. * the method at a given path of `object`. Any additional arguments are
  13094. * provided to the invoked method.
  13095. *
  13096. * @static
  13097. * @memberOf _
  13098. * @category Util
  13099. * @param {Object} object The object to query.
  13100. * @param {...*} [args] The arguments to invoke the method with.
  13101. * @returns {Function} Returns the new function.
  13102. * @example
  13103. *
  13104. * var array = _.times(3, _.constant),
  13105. * object = { 'a': array, 'b': array, 'c': array };
  13106. *
  13107. * _.map(['a[2]', 'c[0]'], _.methodOf(object));
  13108. * // => [2, 0]
  13109. *
  13110. * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
  13111. * // => [2, 0]
  13112. */
  13113. var methodOf = rest(function(object, args) {
  13114. return function(path) {
  13115. return baseInvoke(object, path, args);
  13116. };
  13117. });
  13118. /**
  13119. * Adds all own enumerable function properties of a source object to the
  13120. * destination object. If `object` is a function then methods are added to
  13121. * its prototype as well.
  13122. *
  13123. * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
  13124. * avoid conflicts caused by modifying the original.
  13125. *
  13126. * @static
  13127. * @memberOf _
  13128. * @category Util
  13129. * @param {Function|Object} [object=lodash] The destination object.
  13130. * @param {Object} source The object of functions to add.
  13131. * @param {Object} [options] The options object.
  13132. * @param {boolean} [options.chain=true] Specify whether the functions added
  13133. * are chainable.
  13134. * @returns {Function|Object} Returns `object`.
  13135. * @example
  13136. *
  13137. * function vowels(string) {
  13138. * return _.filter(string, function(v) {
  13139. * return /[aeiou]/i.test(v);
  13140. * });
  13141. * }
  13142. *
  13143. * _.mixin({ 'vowels': vowels });
  13144. * _.vowels('fred');
  13145. * // => ['e']
  13146. *
  13147. * _('fred').vowels().value();
  13148. * // => ['e']
  13149. *
  13150. * _.mixin({ 'vowels': vowels }, { 'chain': false });
  13151. * _('fred').vowels();
  13152. * // => ['e']
  13153. */
  13154. function mixin(object, source, options) {
  13155. var props = keys(source),
  13156. methodNames = baseFunctions(source, props);
  13157. if (options == null &&
  13158. !(isObject(source) && (methodNames.length || !props.length))) {
  13159. options = source;
  13160. source = object;
  13161. object = this;
  13162. methodNames = baseFunctions(source, keys(source));
  13163. }
  13164. var chain = (isObject(options) && 'chain' in options) ? options.chain : true,
  13165. isFunc = isFunction(object);
  13166. arrayEach(methodNames, function(methodName) {
  13167. var func = source[methodName];
  13168. object[methodName] = func;
  13169. if (isFunc) {
  13170. object.prototype[methodName] = function() {
  13171. var chainAll = this.__chain__;
  13172. if (chain || chainAll) {
  13173. var result = object(this.__wrapped__),
  13174. actions = result.__actions__ = copyArray(this.__actions__);
  13175. actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
  13176. result.__chain__ = chainAll;
  13177. return result;
  13178. }
  13179. return func.apply(object, arrayPush([this.value()], arguments));
  13180. };
  13181. }
  13182. });
  13183. return object;
  13184. }
  13185. /**
  13186. * Reverts the `_` variable to its previous value and returns a reference to
  13187. * the `lodash` function.
  13188. *
  13189. * @static
  13190. * @memberOf _
  13191. * @category Util
  13192. * @returns {Function} Returns the `lodash` function.
  13193. * @example
  13194. *
  13195. * var lodash = _.noConflict();
  13196. */
  13197. function noConflict() {
  13198. if (root._ === this) {
  13199. root._ = oldDash;
  13200. }
  13201. return this;
  13202. }
  13203. /**
  13204. * A no-operation function that returns `undefined` regardless of the
  13205. * arguments it receives.
  13206. *
  13207. * @static
  13208. * @memberOf _
  13209. * @category Util
  13210. * @example
  13211. *
  13212. * var object = { 'user': 'fred' };
  13213. *
  13214. * _.noop(object) === undefined;
  13215. * // => true
  13216. */
  13217. function noop() {
  13218. // No operation performed.
  13219. }
  13220. /**
  13221. * Creates a function that returns its nth argument.
  13222. *
  13223. * @static
  13224. * @memberOf _
  13225. * @category Util
  13226. * @param {number} [n=0] The index of the argument to return.
  13227. * @returns {Function} Returns the new function.
  13228. * @example
  13229. *
  13230. * var func = _.nthArg(1);
  13231. *
  13232. * func('a', 'b', 'c');
  13233. * // => 'b'
  13234. */
  13235. function nthArg(n) {
  13236. n = toInteger(n);
  13237. return function() {
  13238. return arguments[n];
  13239. };
  13240. }
  13241. /**
  13242. * Creates a function that invokes `iteratees` with the arguments provided
  13243. * to the created function and returns their results.
  13244. *
  13245. * @static
  13246. * @memberOf _
  13247. * @category Util
  13248. * @param {...(Function|Function[])} iteratees The iteratees to invoke.
  13249. * @returns {Function} Returns the new function.
  13250. * @example
  13251. *
  13252. * var func = _.over(Math.max, Math.min);
  13253. *
  13254. * func(1, 2, 3, 4);
  13255. * // => [4, 1]
  13256. */
  13257. var over = createOver(arrayMap);
  13258. /**
  13259. * Creates a function that checks if **all** of the `predicates` return
  13260. * truthy when invoked with the arguments provided to the created function.
  13261. *
  13262. * @static
  13263. * @memberOf _
  13264. * @category Util
  13265. * @param {...(Function|Function[])} predicates The predicates to check.
  13266. * @returns {Function} Returns the new function.
  13267. * @example
  13268. *
  13269. * var func = _.overEvery(Boolean, isFinite);
  13270. *
  13271. * func('1');
  13272. * // => true
  13273. *
  13274. * func(null);
  13275. * // => false
  13276. *
  13277. * func(NaN);
  13278. * // => false
  13279. */
  13280. var overEvery = createOver(arrayEvery);
  13281. /**
  13282. * Creates a function that checks if **any** of the `predicates` return
  13283. * truthy when invoked with the arguments provided to the created function.
  13284. *
  13285. * @static
  13286. * @memberOf _
  13287. * @category Util
  13288. * @param {...(Function|Function[])} predicates The predicates to check.
  13289. * @returns {Function} Returns the new function.
  13290. * @example
  13291. *
  13292. * var func = _.overSome(Boolean, isFinite);
  13293. *
  13294. * func('1');
  13295. * // => true
  13296. *
  13297. * func(null);
  13298. * // => true
  13299. *
  13300. * func(NaN);
  13301. * // => false
  13302. */
  13303. var overSome = createOver(arraySome);
  13304. /**
  13305. * Creates a function that returns the value at `path` of a given object.
  13306. *
  13307. * @static
  13308. * @memberOf _
  13309. * @category Util
  13310. * @param {Array|string} path The path of the property to get.
  13311. * @returns {Function} Returns the new function.
  13312. * @example
  13313. *
  13314. * var objects = [
  13315. * { 'a': { 'b': { 'c': 2 } } },
  13316. * { 'a': { 'b': { 'c': 1 } } }
  13317. * ];
  13318. *
  13319. * _.map(objects, _.property('a.b.c'));
  13320. * // => [2, 1]
  13321. *
  13322. * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
  13323. * // => [1, 2]
  13324. */
  13325. function property(path) {
  13326. return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
  13327. }
  13328. /**
  13329. * The opposite of `_.property`; this method creates a function that returns
  13330. * the value at a given path of `object`.
  13331. *
  13332. * @static
  13333. * @memberOf _
  13334. * @category Util
  13335. * @param {Object} object The object to query.
  13336. * @returns {Function} Returns the new function.
  13337. * @example
  13338. *
  13339. * var array = [0, 1, 2],
  13340. * object = { 'a': array, 'b': array, 'c': array };
  13341. *
  13342. * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
  13343. * // => [2, 0]
  13344. *
  13345. * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
  13346. * // => [2, 0]
  13347. */
  13348. function propertyOf(object) {
  13349. return function(path) {
  13350. return object == null ? undefined : baseGet(object, path);
  13351. };
  13352. }
  13353. /**
  13354. * Creates an array of numbers (positive and/or negative) progressing from
  13355. * `start` up to, but not including, `end`. A step of `-1` is used if a negative
  13356. * `start` is specified without an `end` or `step`. If `end` is not specified
  13357. * it's set to `start` with `start` then set to `0`.
  13358. *
  13359. * **Note:** JavaScript follows the IEEE-754 standard for resolving
  13360. * floating-point values which can produce unexpected results.
  13361. *
  13362. * @static
  13363. * @memberOf _
  13364. * @category Util
  13365. * @param {number} [start=0] The start of the range.
  13366. * @param {number} end The end of the range.
  13367. * @param {number} [step=1] The value to increment or decrement by.
  13368. * @returns {Array} Returns the new array of numbers.
  13369. * @example
  13370. *
  13371. * _.range(4);
  13372. * // => [0, 1, 2, 3]
  13373. *
  13374. * _.range(-4);
  13375. * // => [0, -1, -2, -3]
  13376. *
  13377. * _.range(1, 5);
  13378. * // => [1, 2, 3, 4]
  13379. *
  13380. * _.range(0, 20, 5);
  13381. * // => [0, 5, 10, 15]
  13382. *
  13383. * _.range(0, -4, -1);
  13384. * // => [0, -1, -2, -3]
  13385. *
  13386. * _.range(1, 4, 0);
  13387. * // => [1, 1, 1]
  13388. *
  13389. * _.range(0);
  13390. * // => []
  13391. */
  13392. var range = createRange();
  13393. /**
  13394. * This method is like `_.range` except that it populates values in
  13395. * descending order.
  13396. *
  13397. * @static
  13398. * @memberOf _
  13399. * @category Util
  13400. * @param {number} [start=0] The start of the range.
  13401. * @param {number} end The end of the range.
  13402. * @param {number} [step=1] The value to increment or decrement by.
  13403. * @returns {Array} Returns the new array of numbers.
  13404. * @example
  13405. *
  13406. * _.rangeRight(4);
  13407. * // => [3, 2, 1, 0]
  13408. *
  13409. * _.rangeRight(-4);
  13410. * // => [-3, -2, -1, 0]
  13411. *
  13412. * _.rangeRight(1, 5);
  13413. * // => [4, 3, 2, 1]
  13414. *
  13415. * _.rangeRight(0, 20, 5);
  13416. * // => [15, 10, 5, 0]
  13417. *
  13418. * _.rangeRight(0, -4, -1);
  13419. * // => [-3, -2, -1, 0]
  13420. *
  13421. * _.rangeRight(1, 4, 0);
  13422. * // => [1, 1, 1]
  13423. *
  13424. * _.rangeRight(0);
  13425. * // => []
  13426. */
  13427. var rangeRight = createRange(true);
  13428. /**
  13429. * Invokes the iteratee `n` times, returning an array of the results of
  13430. * each invocation. The iteratee is invoked with one argument; (index).
  13431. *
  13432. * @static
  13433. * @memberOf _
  13434. * @category Util
  13435. * @param {number} n The number of times to invoke `iteratee`.
  13436. * @param {Function} [iteratee=_.identity] The function invoked per iteration.
  13437. * @returns {Array} Returns the array of results.
  13438. * @example
  13439. *
  13440. * _.times(3, String);
  13441. * // => ['0', '1', '2']
  13442. *
  13443. * _.times(4, _.constant(true));
  13444. * // => [true, true, true, true]
  13445. */
  13446. function times(n, iteratee) {
  13447. n = toInteger(n);
  13448. if (n < 1 || n > MAX_SAFE_INTEGER) {
  13449. return [];
  13450. }
  13451. var index = MAX_ARRAY_LENGTH,
  13452. length = nativeMin(n, MAX_ARRAY_LENGTH);
  13453. iteratee = baseCastFunction(iteratee);
  13454. n -= MAX_ARRAY_LENGTH;
  13455. var result = baseTimes(length, iteratee);
  13456. while (++index < n) {
  13457. iteratee(index);
  13458. }
  13459. return result;
  13460. }
  13461. /**
  13462. * Converts `value` to a property path array.
  13463. *
  13464. * @static
  13465. * @memberOf _
  13466. * @category Util
  13467. * @param {*} value The value to convert.
  13468. * @returns {Array} Returns the new property path array.
  13469. * @example
  13470. *
  13471. * _.toPath('a.b.c');
  13472. * // => ['a', 'b', 'c']
  13473. *
  13474. * _.toPath('a[0].b.c');
  13475. * // => ['a', '0', 'b', 'c']
  13476. *
  13477. * var path = ['a', 'b', 'c'],
  13478. * newPath = _.toPath(path);
  13479. *
  13480. * console.log(newPath);
  13481. * // => ['a', 'b', 'c']
  13482. *
  13483. * console.log(path === newPath);
  13484. * // => false
  13485. */
  13486. function toPath(value) {
  13487. return isArray(value) ? arrayMap(value, String) : stringToPath(value);
  13488. }
  13489. /**
  13490. * Generates a unique ID. If `prefix` is given the ID is appended to it.
  13491. *
  13492. * @static
  13493. * @memberOf _
  13494. * @category Util
  13495. * @param {string} [prefix=''] The value to prefix the ID with.
  13496. * @returns {string} Returns the unique ID.
  13497. * @example
  13498. *
  13499. * _.uniqueId('contact_');
  13500. * // => 'contact_104'
  13501. *
  13502. * _.uniqueId();
  13503. * // => '105'
  13504. */
  13505. function uniqueId(prefix) {
  13506. var id = ++idCounter;
  13507. return toString(prefix) + id;
  13508. }
  13509. /*------------------------------------------------------------------------*/
  13510. /**
  13511. * Adds two numbers.
  13512. *
  13513. * @static
  13514. * @memberOf _
  13515. * @category Math
  13516. * @param {number} augend The first number in an addition.
  13517. * @param {number} addend The second number in an addition.
  13518. * @returns {number} Returns the total.
  13519. * @example
  13520. *
  13521. * _.add(6, 4);
  13522. * // => 10
  13523. */
  13524. function add(augend, addend) {
  13525. var result;
  13526. if (augend === undefined && addend === undefined) {
  13527. return 0;
  13528. }
  13529. if (augend !== undefined) {
  13530. result = augend;
  13531. }
  13532. if (addend !== undefined) {
  13533. result = result === undefined ? addend : (result + addend);
  13534. }
  13535. return result;
  13536. }
  13537. /**
  13538. * Computes `number` rounded up to `precision`.
  13539. *
  13540. * @static
  13541. * @memberOf _
  13542. * @category Math
  13543. * @param {number} number The number to round up.
  13544. * @param {number} [precision=0] The precision to round up to.
  13545. * @returns {number} Returns the rounded up number.
  13546. * @example
  13547. *
  13548. * _.ceil(4.006);
  13549. * // => 5
  13550. *
  13551. * _.ceil(6.004, 2);
  13552. * // => 6.01
  13553. *
  13554. * _.ceil(6040, -2);
  13555. * // => 6100
  13556. */
  13557. var ceil = createRound('ceil');
  13558. /**
  13559. * Computes `number` rounded down to `precision`.
  13560. *
  13561. * @static
  13562. * @memberOf _
  13563. * @category Math
  13564. * @param {number} number The number to round down.
  13565. * @param {number} [precision=0] The precision to round down to.
  13566. * @returns {number} Returns the rounded down number.
  13567. * @example
  13568. *
  13569. * _.floor(4.006);
  13570. * // => 4
  13571. *
  13572. * _.floor(0.046, 2);
  13573. * // => 0.04
  13574. *
  13575. * _.floor(4060, -2);
  13576. * // => 4000
  13577. */
  13578. var floor = createRound('floor');
  13579. /**
  13580. * Computes the maximum value of `array`. If `array` is empty or falsey
  13581. * `undefined` is returned.
  13582. *
  13583. * @static
  13584. * @memberOf _
  13585. * @category Math
  13586. * @param {Array} array The array to iterate over.
  13587. * @returns {*} Returns the maximum value.
  13588. * @example
  13589. *
  13590. * _.max([4, 2, 8, 6]);
  13591. * // => 8
  13592. *
  13593. * _.max([]);
  13594. * // => undefined
  13595. */
  13596. function max(array) {
  13597. return (array && array.length)
  13598. ? baseExtremum(array, identity, gt)
  13599. : undefined;
  13600. }
  13601. /**
  13602. * This method is like `_.max` except that it accepts `iteratee` which is
  13603. * invoked for each element in `array` to generate the criterion by which
  13604. * the value is ranked. The iteratee is invoked with one argument: (value).
  13605. *
  13606. * @static
  13607. * @memberOf _
  13608. * @category Math
  13609. * @param {Array} array The array to iterate over.
  13610. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  13611. * @returns {*} Returns the maximum value.
  13612. * @example
  13613. *
  13614. * var objects = [{ 'n': 1 }, { 'n': 2 }];
  13615. *
  13616. * _.maxBy(objects, function(o) { return o.n; });
  13617. * // => { 'n': 2 }
  13618. *
  13619. * // The `_.property` iteratee shorthand.
  13620. * _.maxBy(objects, 'n');
  13621. * // => { 'n': 2 }
  13622. */
  13623. function maxBy(array, iteratee) {
  13624. return (array && array.length)
  13625. ? baseExtremum(array, getIteratee(iteratee), gt)
  13626. : undefined;
  13627. }
  13628. /**
  13629. * Computes the mean of the values in `array`.
  13630. *
  13631. * @static
  13632. * @memberOf _
  13633. * @category Math
  13634. * @param {Array} array The array to iterate over.
  13635. * @returns {number} Returns the mean.
  13636. * @example
  13637. *
  13638. * _.mean([4, 2, 8, 6]);
  13639. * // => 5
  13640. */
  13641. function mean(array) {
  13642. return sum(array) / (array ? array.length : 0);
  13643. }
  13644. /**
  13645. * Computes the minimum value of `array`. If `array` is empty or falsey
  13646. * `undefined` is returned.
  13647. *
  13648. * @static
  13649. * @memberOf _
  13650. * @category Math
  13651. * @param {Array} array The array to iterate over.
  13652. * @returns {*} Returns the minimum value.
  13653. * @example
  13654. *
  13655. * _.min([4, 2, 8, 6]);
  13656. * // => 2
  13657. *
  13658. * _.min([]);
  13659. * // => undefined
  13660. */
  13661. function min(array) {
  13662. return (array && array.length)
  13663. ? baseExtremum(array, identity, lt)
  13664. : undefined;
  13665. }
  13666. /**
  13667. * This method is like `_.min` except that it accepts `iteratee` which is
  13668. * invoked for each element in `array` to generate the criterion by which
  13669. * the value is ranked. The iteratee is invoked with one argument: (value).
  13670. *
  13671. * @static
  13672. * @memberOf _
  13673. * @category Math
  13674. * @param {Array} array The array to iterate over.
  13675. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  13676. * @returns {*} Returns the minimum value.
  13677. * @example
  13678. *
  13679. * var objects = [{ 'n': 1 }, { 'n': 2 }];
  13680. *
  13681. * _.minBy(objects, function(o) { return o.n; });
  13682. * // => { 'n': 1 }
  13683. *
  13684. * // The `_.property` iteratee shorthand.
  13685. * _.minBy(objects, 'n');
  13686. * // => { 'n': 1 }
  13687. */
  13688. function minBy(array, iteratee) {
  13689. return (array && array.length)
  13690. ? baseExtremum(array, getIteratee(iteratee), lt)
  13691. : undefined;
  13692. }
  13693. /**
  13694. * Computes `number` rounded to `precision`.
  13695. *
  13696. * @static
  13697. * @memberOf _
  13698. * @category Math
  13699. * @param {number} number The number to round.
  13700. * @param {number} [precision=0] The precision to round to.
  13701. * @returns {number} Returns the rounded number.
  13702. * @example
  13703. *
  13704. * _.round(4.006);
  13705. * // => 4
  13706. *
  13707. * _.round(4.006, 2);
  13708. * // => 4.01
  13709. *
  13710. * _.round(4060, -2);
  13711. * // => 4100
  13712. */
  13713. var round = createRound('round');
  13714. /**
  13715. * Subtract two numbers.
  13716. *
  13717. * @static
  13718. * @memberOf _
  13719. * @category Math
  13720. * @param {number} minuend The first number in a subtraction.
  13721. * @param {number} subtrahend The second number in a subtraction.
  13722. * @returns {number} Returns the difference.
  13723. * @example
  13724. *
  13725. * _.subtract(6, 4);
  13726. * // => 2
  13727. */
  13728. function subtract(minuend, subtrahend) {
  13729. var result;
  13730. if (minuend === undefined && subtrahend === undefined) {
  13731. return 0;
  13732. }
  13733. if (minuend !== undefined) {
  13734. result = minuend;
  13735. }
  13736. if (subtrahend !== undefined) {
  13737. result = result === undefined ? subtrahend : (result - subtrahend);
  13738. }
  13739. return result;
  13740. }
  13741. /**
  13742. * Computes the sum of the values in `array`.
  13743. *
  13744. * @static
  13745. * @memberOf _
  13746. * @category Math
  13747. * @param {Array} array The array to iterate over.
  13748. * @returns {number} Returns the sum.
  13749. * @example
  13750. *
  13751. * _.sum([4, 2, 8, 6]);
  13752. * // => 20
  13753. */
  13754. function sum(array) {
  13755. return (array && array.length)
  13756. ? baseSum(array, identity)
  13757. : 0;
  13758. }
  13759. /**
  13760. * This method is like `_.sum` except that it accepts `iteratee` which is
  13761. * invoked for each element in `array` to generate the value to be summed.
  13762. * The iteratee is invoked with one argument: (value).
  13763. *
  13764. * @static
  13765. * @memberOf _
  13766. * @category Math
  13767. * @param {Array} array The array to iterate over.
  13768. * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
  13769. * @returns {number} Returns the sum.
  13770. * @example
  13771. *
  13772. * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
  13773. *
  13774. * _.sumBy(objects, function(o) { return o.n; });
  13775. * // => 20
  13776. *
  13777. * // The `_.property` iteratee shorthand.
  13778. * _.sumBy(objects, 'n');
  13779. * // => 20
  13780. */
  13781. function sumBy(array, iteratee) {
  13782. return (array && array.length)
  13783. ? baseSum(array, getIteratee(iteratee))
  13784. : 0;
  13785. }
  13786. /*------------------------------------------------------------------------*/
  13787. // Ensure wrappers are instances of `baseLodash`.
  13788. lodash.prototype = baseLodash.prototype;
  13789. LodashWrapper.prototype = baseCreate(baseLodash.prototype);
  13790. LodashWrapper.prototype.constructor = LodashWrapper;
  13791. LazyWrapper.prototype = baseCreate(baseLodash.prototype);
  13792. LazyWrapper.prototype.constructor = LazyWrapper;
  13793. // Avoid inheriting from `Object.prototype` when possible.
  13794. Hash.prototype = nativeCreate ? nativeCreate(null) : objectProto;
  13795. // Add functions to the `MapCache`.
  13796. MapCache.prototype.clear = mapClear;
  13797. MapCache.prototype['delete'] = mapDelete;
  13798. MapCache.prototype.get = mapGet;
  13799. MapCache.prototype.has = mapHas;
  13800. MapCache.prototype.set = mapSet;
  13801. // Add functions to the `SetCache`.
  13802. SetCache.prototype.push = cachePush;
  13803. // Add functions to the `Stack` cache.
  13804. Stack.prototype.clear = stackClear;
  13805. Stack.prototype['delete'] = stackDelete;
  13806. Stack.prototype.get = stackGet;
  13807. Stack.prototype.has = stackHas;
  13808. Stack.prototype.set = stackSet;
  13809. // Assign cache to `_.memoize`.
  13810. memoize.Cache = MapCache;
  13811. // Add functions that return wrapped values when chaining.
  13812. lodash.after = after;
  13813. lodash.ary = ary;
  13814. lodash.assign = assign;
  13815. lodash.assignIn = assignIn;
  13816. lodash.assignInWith = assignInWith;
  13817. lodash.assignWith = assignWith;
  13818. lodash.at = at;
  13819. lodash.before = before;
  13820. lodash.bind = bind;
  13821. lodash.bindAll = bindAll;
  13822. lodash.bindKey = bindKey;
  13823. lodash.castArray = castArray;
  13824. lodash.chain = chain;
  13825. lodash.chunk = chunk;
  13826. lodash.compact = compact;
  13827. lodash.concat = concat;
  13828. lodash.cond = cond;
  13829. lodash.conforms = conforms;
  13830. lodash.constant = constant;
  13831. lodash.countBy = countBy;
  13832. lodash.create = create;
  13833. lodash.curry = curry;
  13834. lodash.curryRight = curryRight;
  13835. lodash.debounce = debounce;
  13836. lodash.defaults = defaults;
  13837. lodash.defaultsDeep = defaultsDeep;
  13838. lodash.defer = defer;
  13839. lodash.delay = delay;
  13840. lodash.difference = difference;
  13841. lodash.differenceBy = differenceBy;
  13842. lodash.differenceWith = differenceWith;
  13843. lodash.drop = drop;
  13844. lodash.dropRight = dropRight;
  13845. lodash.dropRightWhile = dropRightWhile;
  13846. lodash.dropWhile = dropWhile;
  13847. lodash.fill = fill;
  13848. lodash.filter = filter;
  13849. lodash.flatMap = flatMap;
  13850. lodash.flatten = flatten;
  13851. lodash.flattenDeep = flattenDeep;
  13852. lodash.flattenDepth = flattenDepth;
  13853. lodash.flip = flip;
  13854. lodash.flow = flow;
  13855. lodash.flowRight = flowRight;
  13856. lodash.fromPairs = fromPairs;
  13857. lodash.functions = functions;
  13858. lodash.functionsIn = functionsIn;
  13859. lodash.groupBy = groupBy;
  13860. lodash.initial = initial;
  13861. lodash.intersection = intersection;
  13862. lodash.intersectionBy = intersectionBy;
  13863. lodash.intersectionWith = intersectionWith;
  13864. lodash.invert = invert;
  13865. lodash.invertBy = invertBy;
  13866. lodash.invokeMap = invokeMap;
  13867. lodash.iteratee = iteratee;
  13868. lodash.keyBy = keyBy;
  13869. lodash.keys = keys;
  13870. lodash.keysIn = keysIn;
  13871. lodash.map = map;
  13872. lodash.mapKeys = mapKeys;
  13873. lodash.mapValues = mapValues;
  13874. lodash.matches = matches;
  13875. lodash.matchesProperty = matchesProperty;
  13876. lodash.memoize = memoize;
  13877. lodash.merge = merge;
  13878. lodash.mergeWith = mergeWith;
  13879. lodash.method = method;
  13880. lodash.methodOf = methodOf;
  13881. lodash.mixin = mixin;
  13882. lodash.negate = negate;
  13883. lodash.nthArg = nthArg;
  13884. lodash.omit = omit;
  13885. lodash.omitBy = omitBy;
  13886. lodash.once = once;
  13887. lodash.orderBy = orderBy;
  13888. lodash.over = over;
  13889. lodash.overArgs = overArgs;
  13890. lodash.overEvery = overEvery;
  13891. lodash.overSome = overSome;
  13892. lodash.partial = partial;
  13893. lodash.partialRight = partialRight;
  13894. lodash.partition = partition;
  13895. lodash.pick = pick;
  13896. lodash.pickBy = pickBy;
  13897. lodash.property = property;
  13898. lodash.propertyOf = propertyOf;
  13899. lodash.pull = pull;
  13900. lodash.pullAll = pullAll;
  13901. lodash.pullAllBy = pullAllBy;
  13902. lodash.pullAt = pullAt;
  13903. lodash.range = range;
  13904. lodash.rangeRight = rangeRight;
  13905. lodash.rearg = rearg;
  13906. lodash.reject = reject;
  13907. lodash.remove = remove;
  13908. lodash.rest = rest;
  13909. lodash.reverse = reverse;
  13910. lodash.sampleSize = sampleSize;
  13911. lodash.set = set;
  13912. lodash.setWith = setWith;
  13913. lodash.shuffle = shuffle;
  13914. lodash.slice = slice;
  13915. lodash.sortBy = sortBy;
  13916. lodash.sortedUniq = sortedUniq;
  13917. lodash.sortedUniqBy = sortedUniqBy;
  13918. lodash.split = split;
  13919. lodash.spread = spread;
  13920. lodash.tail = tail;
  13921. lodash.take = take;
  13922. lodash.takeRight = takeRight;
  13923. lodash.takeRightWhile = takeRightWhile;
  13924. lodash.takeWhile = takeWhile;
  13925. lodash.tap = tap;
  13926. lodash.throttle = throttle;
  13927. lodash.thru = thru;
  13928. lodash.toArray = toArray;
  13929. lodash.toPairs = toPairs;
  13930. lodash.toPairsIn = toPairsIn;
  13931. lodash.toPath = toPath;
  13932. lodash.toPlainObject = toPlainObject;
  13933. lodash.transform = transform;
  13934. lodash.unary = unary;
  13935. lodash.union = union;
  13936. lodash.unionBy = unionBy;
  13937. lodash.unionWith = unionWith;
  13938. lodash.uniq = uniq;
  13939. lodash.uniqBy = uniqBy;
  13940. lodash.uniqWith = uniqWith;
  13941. lodash.unset = unset;
  13942. lodash.unzip = unzip;
  13943. lodash.unzipWith = unzipWith;
  13944. lodash.values = values;
  13945. lodash.valuesIn = valuesIn;
  13946. lodash.without = without;
  13947. lodash.words = words;
  13948. lodash.wrap = wrap;
  13949. lodash.xor = xor;
  13950. lodash.xorBy = xorBy;
  13951. lodash.xorWith = xorWith;
  13952. lodash.zip = zip;
  13953. lodash.zipObject = zipObject;
  13954. lodash.zipObjectDeep = zipObjectDeep;
  13955. lodash.zipWith = zipWith;
  13956. // Add aliases.
  13957. lodash.extend = assignIn;
  13958. lodash.extendWith = assignInWith;
  13959. // Add functions to `lodash.prototype`.
  13960. mixin(lodash, lodash);
  13961. /*------------------------------------------------------------------------*/
  13962. // Add functions that return unwrapped values when chaining.
  13963. lodash.add = add;
  13964. lodash.attempt = attempt;
  13965. lodash.camelCase = camelCase;
  13966. lodash.capitalize = capitalize;
  13967. lodash.ceil = ceil;
  13968. lodash.clamp = clamp;
  13969. lodash.clone = clone;
  13970. lodash.cloneDeep = cloneDeep;
  13971. lodash.cloneDeepWith = cloneDeepWith;
  13972. lodash.cloneWith = cloneWith;
  13973. lodash.deburr = deburr;
  13974. lodash.endsWith = endsWith;
  13975. lodash.eq = eq;
  13976. lodash.escape = escape;
  13977. lodash.escapeRegExp = escapeRegExp;
  13978. lodash.every = every;
  13979. lodash.find = find;
  13980. lodash.findIndex = findIndex;
  13981. lodash.findKey = findKey;
  13982. lodash.findLast = findLast;
  13983. lodash.findLastIndex = findLastIndex;
  13984. lodash.findLastKey = findLastKey;
  13985. lodash.floor = floor;
  13986. lodash.forEach = forEach;
  13987. lodash.forEachRight = forEachRight;
  13988. lodash.forIn = forIn;
  13989. lodash.forInRight = forInRight;
  13990. lodash.forOwn = forOwn;
  13991. lodash.forOwnRight = forOwnRight;
  13992. lodash.get = get;
  13993. lodash.gt = gt;
  13994. lodash.gte = gte;
  13995. lodash.has = has;
  13996. lodash.hasIn = hasIn;
  13997. lodash.head = head;
  13998. lodash.identity = identity;
  13999. lodash.includes = includes;
  14000. lodash.indexOf = indexOf;
  14001. lodash.inRange = inRange;
  14002. lodash.invoke = invoke;
  14003. lodash.isArguments = isArguments;
  14004. lodash.isArray = isArray;
  14005. lodash.isArrayBuffer = isArrayBuffer;
  14006. lodash.isArrayLike = isArrayLike;
  14007. lodash.isArrayLikeObject = isArrayLikeObject;
  14008. lodash.isBoolean = isBoolean;
  14009. lodash.isBuffer = isBuffer;
  14010. lodash.isDate = isDate;
  14011. lodash.isElement = isElement;
  14012. lodash.isEmpty = isEmpty;
  14013. lodash.isEqual = isEqual;
  14014. lodash.isEqualWith = isEqualWith;
  14015. lodash.isError = isError;
  14016. lodash.isFinite = isFinite;
  14017. lodash.isFunction = isFunction;
  14018. lodash.isInteger = isInteger;
  14019. lodash.isLength = isLength;
  14020. lodash.isMap = isMap;
  14021. lodash.isMatch = isMatch;
  14022. lodash.isMatchWith = isMatchWith;
  14023. lodash.isNaN = isNaN;
  14024. lodash.isNative = isNative;
  14025. lodash.isNil = isNil;
  14026. lodash.isNull = isNull;
  14027. lodash.isNumber = isNumber;
  14028. lodash.isObject = isObject;
  14029. lodash.isObjectLike = isObjectLike;
  14030. lodash.isPlainObject = isPlainObject;
  14031. lodash.isRegExp = isRegExp;
  14032. lodash.isSafeInteger = isSafeInteger;
  14033. lodash.isSet = isSet;
  14034. lodash.isString = isString;
  14035. lodash.isSymbol = isSymbol;
  14036. lodash.isTypedArray = isTypedArray;
  14037. lodash.isUndefined = isUndefined;
  14038. lodash.isWeakMap = isWeakMap;
  14039. lodash.isWeakSet = isWeakSet;
  14040. lodash.join = join;
  14041. lodash.kebabCase = kebabCase;
  14042. lodash.last = last;
  14043. lodash.lastIndexOf = lastIndexOf;
  14044. lodash.lowerCase = lowerCase;
  14045. lodash.lowerFirst = lowerFirst;
  14046. lodash.lt = lt;
  14047. lodash.lte = lte;
  14048. lodash.max = max;
  14049. lodash.maxBy = maxBy;
  14050. lodash.mean = mean;
  14051. lodash.min = min;
  14052. lodash.minBy = minBy;
  14053. lodash.noConflict = noConflict;
  14054. lodash.noop = noop;
  14055. lodash.now = now;
  14056. lodash.pad = pad;
  14057. lodash.padEnd = padEnd;
  14058. lodash.padStart = padStart;
  14059. lodash.parseInt = parseInt;
  14060. lodash.random = random;
  14061. lodash.reduce = reduce;
  14062. lodash.reduceRight = reduceRight;
  14063. lodash.repeat = repeat;
  14064. lodash.replace = replace;
  14065. lodash.result = result;
  14066. lodash.round = round;
  14067. lodash.runInContext = runInContext;
  14068. lodash.sample = sample;
  14069. lodash.size = size;
  14070. lodash.snakeCase = snakeCase;
  14071. lodash.some = some;
  14072. lodash.sortedIndex = sortedIndex;
  14073. lodash.sortedIndexBy = sortedIndexBy;
  14074. lodash.sortedIndexOf = sortedIndexOf;
  14075. lodash.sortedLastIndex = sortedLastIndex;
  14076. lodash.sortedLastIndexBy = sortedLastIndexBy;
  14077. lodash.sortedLastIndexOf = sortedLastIndexOf;
  14078. lodash.startCase = startCase;
  14079. lodash.startsWith = startsWith;
  14080. lodash.subtract = subtract;
  14081. lodash.sum = sum;
  14082. lodash.sumBy = sumBy;
  14083. lodash.template = template;
  14084. lodash.times = times;
  14085. lodash.toInteger = toInteger;
  14086. lodash.toLength = toLength;
  14087. lodash.toLower = toLower;
  14088. lodash.toNumber = toNumber;
  14089. lodash.toSafeInteger = toSafeInteger;
  14090. lodash.toString = toString;
  14091. lodash.toUpper = toUpper;
  14092. lodash.trim = trim;
  14093. lodash.trimEnd = trimEnd;
  14094. lodash.trimStart = trimStart;
  14095. lodash.truncate = truncate;
  14096. lodash.unescape = unescape;
  14097. lodash.uniqueId = uniqueId;
  14098. lodash.upperCase = upperCase;
  14099. lodash.upperFirst = upperFirst;
  14100. // Add aliases.
  14101. lodash.each = forEach;
  14102. lodash.eachRight = forEachRight;
  14103. lodash.first = head;
  14104. mixin(lodash, (function() {
  14105. var source = {};
  14106. baseForOwn(lodash, function(func, methodName) {
  14107. if (!hasOwnProperty.call(lodash.prototype, methodName)) {
  14108. source[methodName] = func;
  14109. }
  14110. });
  14111. return source;
  14112. }()), { 'chain': false });
  14113. /*------------------------------------------------------------------------*/
  14114. /**
  14115. * The semantic version number.
  14116. *
  14117. * @static
  14118. * @memberOf _
  14119. * @type {string}
  14120. */
  14121. lodash.VERSION = VERSION;
  14122. // Assign default placeholders.
  14123. arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
  14124. lodash[methodName].placeholder = lodash;
  14125. });
  14126. // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
  14127. arrayEach(['drop', 'take'], function(methodName, index) {
  14128. LazyWrapper.prototype[methodName] = function(n) {
  14129. var filtered = this.__filtered__;
  14130. if (filtered && !index) {
  14131. return new LazyWrapper(this);
  14132. }
  14133. n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
  14134. var result = this.clone();
  14135. if (filtered) {
  14136. result.__takeCount__ = nativeMin(n, result.__takeCount__);
  14137. } else {
  14138. result.__views__.push({
  14139. 'size': nativeMin(n, MAX_ARRAY_LENGTH),
  14140. 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
  14141. });
  14142. }
  14143. return result;
  14144. };
  14145. LazyWrapper.prototype[methodName + 'Right'] = function(n) {
  14146. return this.reverse()[methodName](n).reverse();
  14147. };
  14148. });
  14149. // Add `LazyWrapper` methods that accept an `iteratee` value.
  14150. arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
  14151. var type = index + 1,
  14152. isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
  14153. LazyWrapper.prototype[methodName] = function(iteratee) {
  14154. var result = this.clone();
  14155. result.__iteratees__.push({
  14156. 'iteratee': getIteratee(iteratee, 3),
  14157. 'type': type
  14158. });
  14159. result.__filtered__ = result.__filtered__ || isFilter;
  14160. return result;
  14161. };
  14162. });
  14163. // Add `LazyWrapper` methods for `_.head` and `_.last`.
  14164. arrayEach(['head', 'last'], function(methodName, index) {
  14165. var takeName = 'take' + (index ? 'Right' : '');
  14166. LazyWrapper.prototype[methodName] = function() {
  14167. return this[takeName](1).value()[0];
  14168. };
  14169. });
  14170. // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
  14171. arrayEach(['initial', 'tail'], function(methodName, index) {
  14172. var dropName = 'drop' + (index ? '' : 'Right');
  14173. LazyWrapper.prototype[methodName] = function() {
  14174. return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
  14175. };
  14176. });
  14177. LazyWrapper.prototype.compact = function() {
  14178. return this.filter(identity);
  14179. };
  14180. LazyWrapper.prototype.find = function(predicate) {
  14181. return this.filter(predicate).head();
  14182. };
  14183. LazyWrapper.prototype.findLast = function(predicate) {
  14184. return this.reverse().find(predicate);
  14185. };
  14186. LazyWrapper.prototype.invokeMap = rest(function(path, args) {
  14187. if (typeof path == 'function') {
  14188. return new LazyWrapper(this);
  14189. }
  14190. return this.map(function(value) {
  14191. return baseInvoke(value, path, args);
  14192. });
  14193. });
  14194. LazyWrapper.prototype.reject = function(predicate) {
  14195. predicate = getIteratee(predicate, 3);
  14196. return this.filter(function(value) {
  14197. return !predicate(value);
  14198. });
  14199. };
  14200. LazyWrapper.prototype.slice = function(start, end) {
  14201. start = toInteger(start);
  14202. var result = this;
  14203. if (result.__filtered__ && (start > 0 || end < 0)) {
  14204. return new LazyWrapper(result);
  14205. }
  14206. if (start < 0) {
  14207. result = result.takeRight(-start);
  14208. } else if (start) {
  14209. result = result.drop(start);
  14210. }
  14211. if (end !== undefined) {
  14212. end = toInteger(end);
  14213. result = end < 0 ? result.dropRight(-end) : result.take(end - start);
  14214. }
  14215. return result;
  14216. };
  14217. LazyWrapper.prototype.takeRightWhile = function(predicate) {
  14218. return this.reverse().takeWhile(predicate).reverse();
  14219. };
  14220. LazyWrapper.prototype.toArray = function() {
  14221. return this.take(MAX_ARRAY_LENGTH);
  14222. };
  14223. // Add `LazyWrapper` methods to `lodash.prototype`.
  14224. baseForOwn(LazyWrapper.prototype, function(func, methodName) {
  14225. var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
  14226. isTaker = /^(?:head|last)$/.test(methodName),
  14227. lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
  14228. retUnwrapped = isTaker || /^find/.test(methodName);
  14229. if (!lodashFunc) {
  14230. return;
  14231. }
  14232. lodash.prototype[methodName] = function() {
  14233. var value = this.__wrapped__,
  14234. args = isTaker ? [1] : arguments,
  14235. isLazy = value instanceof LazyWrapper,
  14236. iteratee = args[0],
  14237. useLazy = isLazy || isArray(value);
  14238. var interceptor = function(value) {
  14239. var result = lodashFunc.apply(lodash, arrayPush([value], args));
  14240. return (isTaker && chainAll) ? result[0] : result;
  14241. };
  14242. if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
  14243. // Avoid lazy use if the iteratee has a "length" value other than `1`.
  14244. isLazy = useLazy = false;
  14245. }
  14246. var chainAll = this.__chain__,
  14247. isHybrid = !!this.__actions__.length,
  14248. isUnwrapped = retUnwrapped && !chainAll,
  14249. onlyLazy = isLazy && !isHybrid;
  14250. if (!retUnwrapped && useLazy) {
  14251. value = onlyLazy ? value : new LazyWrapper(this);
  14252. var result = func.apply(value, args);
  14253. result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
  14254. return new LodashWrapper(result, chainAll);
  14255. }
  14256. if (isUnwrapped && onlyLazy) {
  14257. return func.apply(this, args);
  14258. }
  14259. result = this.thru(interceptor);
  14260. return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
  14261. };
  14262. });
  14263. // Add `Array` and `String` methods to `lodash.prototype`.
  14264. arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
  14265. var func = arrayProto[methodName],
  14266. chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
  14267. retUnwrapped = /^(?:pop|shift)$/.test(methodName);
  14268. lodash.prototype[methodName] = function() {
  14269. var args = arguments;
  14270. if (retUnwrapped && !this.__chain__) {
  14271. return func.apply(this.value(), args);
  14272. }
  14273. return this[chainName](function(value) {
  14274. return func.apply(value, args);
  14275. });
  14276. };
  14277. });
  14278. // Map minified function names to their real names.
  14279. baseForOwn(LazyWrapper.prototype, function(func, methodName) {
  14280. var lodashFunc = lodash[methodName];
  14281. if (lodashFunc) {
  14282. var key = (lodashFunc.name + ''),
  14283. names = realNames[key] || (realNames[key] = []);
  14284. names.push({ 'name': methodName, 'func': lodashFunc });
  14285. }
  14286. });
  14287. realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
  14288. 'name': 'wrapper',
  14289. 'func': undefined
  14290. }];
  14291. // Add functions to the lazy wrapper.
  14292. LazyWrapper.prototype.clone = lazyClone;
  14293. LazyWrapper.prototype.reverse = lazyReverse;
  14294. LazyWrapper.prototype.value = lazyValue;
  14295. // Add chaining functions to the `lodash` wrapper.
  14296. lodash.prototype.at = wrapperAt;
  14297. lodash.prototype.chain = wrapperChain;
  14298. lodash.prototype.commit = wrapperCommit;
  14299. lodash.prototype.flatMap = wrapperFlatMap;
  14300. lodash.prototype.next = wrapperNext;
  14301. lodash.prototype.plant = wrapperPlant;
  14302. lodash.prototype.reverse = wrapperReverse;
  14303. lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
  14304. if (iteratorSymbol) {
  14305. lodash.prototype[iteratorSymbol] = wrapperToIterator;
  14306. }
  14307. return lodash;
  14308. }
  14309. /*--------------------------------------------------------------------------*/
  14310. // Export lodash.
  14311. var _ = runInContext();
  14312. // Expose lodash on the free variable `window` or `self` when available. This
  14313. // prevents errors in cases where lodash is loaded by a script tag in the presence
  14314. // of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
  14315. (freeWindow || freeSelf || {})._ = _;
  14316. // Some AMD build optimizers like r.js check for condition patterns like the following:
  14317. if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
  14318. // Define as an anonymous module so, through path mapping, it can be
  14319. // referenced as the "underscore" module.
  14320. define(function() {
  14321. return _;
  14322. });
  14323. }
  14324. // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
  14325. else if (freeExports && freeModule) {
  14326. // Export for Node.js.
  14327. if (moduleExports) {
  14328. (freeModule.exports = _)._ = _;
  14329. }
  14330. // Export for CommonJS support.
  14331. freeExports._ = _;
  14332. }
  14333. else {
  14334. // Export to the global object.
  14335. root._ = _;
  14336. }
  14337. }.call(this));
  14338. }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  14339. },{}],4:[function(require,module,exports){
  14340. var Class = require("abitbol");
  14341. var BinaryHeap = require("./BinaryHeap.js");
  14342. var Astar = Class.$extend({
  14343. init: function (graph) {
  14344. for (var x = 0; x < graph.length; x++) {
  14345. //for(var x in graph) {
  14346. var node = graph[x];
  14347. node.f = 0;
  14348. node.g = 0;
  14349. node.h = 0;
  14350. node.cost = 1.0;
  14351. node.visited = false;
  14352. node.closed = false;
  14353. node.parent = null;
  14354. }
  14355. },
  14356. cleanUp: function (graph) {
  14357. for (var x = 0; x < graph.length; x++) {
  14358. var node = graph[x];
  14359. delete node.f;
  14360. delete node.g;
  14361. delete node.h;
  14362. delete node.cost;
  14363. delete node.visited;
  14364. delete node.closed;
  14365. delete node.parent;
  14366. }
  14367. },
  14368. heap: function () {
  14369. return new BinaryHeap(function (node) {
  14370. return node.f;
  14371. });
  14372. },
  14373. search: function (graph, start, end) {
  14374. this.init(graph);
  14375. //heuristic = heuristic || astar.manhattan;
  14376. var openHeap = this.heap();
  14377. openHeap.push(start);
  14378. while (openHeap.size() > 0) {
  14379. // Grab the lowest f(x) to process next. Heap keeps this sorted for us.
  14380. var currentNode = openHeap.pop();
  14381. // End case -- result has been found, return the traced path.
  14382. if (currentNode === end) {
  14383. var curr = currentNode;
  14384. var ret = [];
  14385. while (curr.parent) {
  14386. ret.push(curr);
  14387. curr = curr.parent;
  14388. }
  14389. this.cleanUp(ret);
  14390. return ret.reverse();
  14391. }
  14392. // Normal case -- move currentNode from open to closed, process each of its neighbours.
  14393. currentNode.closed = true;
  14394. // Find all neighbours for the current node. Optionally find diagonal neighbours as well (false by default).
  14395. var neighbours = this.neighbours(graph, currentNode);
  14396. for (var i = 0, il = neighbours.length; i < il; i++) {
  14397. var neighbour = neighbours[i];
  14398. if (neighbour.closed) {
  14399. // Not a valid node to process, skip to next neighbour.
  14400. continue;
  14401. }
  14402. // The g score is the shortest distance from start to current node.
  14403. // We need to check if the path we have arrived at this neighbour is the shortest one we have seen yet.
  14404. var gScore = currentNode.g + neighbour.cost;
  14405. var beenVisited = neighbour.visited;
  14406. if (!beenVisited || gScore < neighbour.g) {
  14407. // Found an optimal (so far) path to this node. Take score for node to see how good it is.
  14408. neighbour.visited = true;
  14409. neighbour.parent = currentNode;
  14410. if (!neighbour.centroid || !end.centroid) debugger;
  14411. neighbour.h = neighbour.h || this.heuristic(neighbour.centroid, end.centroid);
  14412. neighbour.g = gScore;
  14413. neighbour.f = neighbour.g + neighbour.h;
  14414. if (!beenVisited) {
  14415. // Pushing to heap will put it in proper place based on the 'f' value.
  14416. openHeap.push(neighbour);
  14417. } else {
  14418. // Already seen the node, but since it has been rescored we need to reorder it in the heap
  14419. openHeap.rescoreElement(neighbour);
  14420. }
  14421. }
  14422. }
  14423. }
  14424. // No result was found - empty array signifies failure to find path.
  14425. return [];
  14426. },
  14427. heuristic: function (pos1, pos2) {
  14428. return BABYLON.Vector3.DistanceSquared(pos1, pos2);
  14429. },
  14430. neighbours: function (graph, node) {
  14431. var ret = [];
  14432. for (var e = 0; e < node.neighbours.length; e++) {
  14433. ret.push(graph[node.neighbours[e]]);
  14434. }
  14435. return ret;
  14436. }
  14437. });
  14438. module.exports = Astar;
  14439. },{"./BinaryHeap.js":5,"abitbol":1}],5:[function(require,module,exports){
  14440. var Class = require("abitbol");
  14441. var BinaryHeap = Class.$extend({
  14442. __init__: function(scoreFunction) {
  14443. this.content = [];
  14444. this.scoreFunction = scoreFunction || new function () {};
  14445. },
  14446. push: function (element) {
  14447. // Add the new element to the end of the array.
  14448. this.content.push(element);
  14449. // Allow it to sink down.
  14450. this.sinkDown(this.content.length - 1);
  14451. },
  14452. pop: function () {
  14453. // Store the first element so we can return it later.
  14454. var result = this.content[0];
  14455. // Get the element at the end of the array.
  14456. var end = this.content.pop();
  14457. // If there are any elements left, put the end element at the
  14458. // start, and let it bubble up.
  14459. if (this.content.length > 0) {
  14460. this.content[0] = end;
  14461. this.bubbleUp(0);
  14462. }
  14463. return result;
  14464. },
  14465. remove: function (node) {
  14466. var i = this.content.indexOf(node);
  14467. // When it is found, the process seen in 'pop' is repeated
  14468. // to fill up the hole.
  14469. var end = this.content.pop();
  14470. if (i !== this.content.length - 1) {
  14471. this.content[i] = end;
  14472. if (this.scoreFunction(end) < this.scoreFunction(node)) {
  14473. this.sinkDown(i);
  14474. } else {
  14475. this.bubbleUp(i);
  14476. }
  14477. }
  14478. },
  14479. size: function () {
  14480. return this.content.length;
  14481. },
  14482. rescoreElement: function (node) {
  14483. this.sinkDown(this.content.indexOf(node));
  14484. },
  14485. sinkDown: function (n) {
  14486. // Fetch the element that has to be sunk.
  14487. var element = this.content[n];
  14488. // When at 0, an element can not sink any further.
  14489. while (n > 0) {
  14490. // Compute the parent element's index, and fetch it.
  14491. var parentN = ((n + 1) >> 1) - 1,
  14492. parent = this.content[parentN];
  14493. // Swap the elements if the parent is greater.
  14494. if (this.scoreFunction(element) < this.scoreFunction(parent)) {
  14495. this.content[parentN] = element;
  14496. this.content[n] = parent;
  14497. // Update 'n' to continue at the new position.
  14498. n = parentN;
  14499. }
  14500. // Found a parent that is less, no need to sink any further.
  14501. else {
  14502. break;
  14503. }
  14504. }
  14505. },
  14506. bubbleUp: function (n) {
  14507. // Look up the target element and its score.
  14508. var length = this.content.length,
  14509. element = this.content[n],
  14510. elemScore = this.scoreFunction(element);
  14511. while (true) {
  14512. // Compute the indices of the child elements.
  14513. var child2N = (n + 1) << 1,
  14514. child1N = child2N - 1;
  14515. // This is used to store the new position of the element,
  14516. // if any.
  14517. var swap = null;
  14518. // If the first child exists (is inside the array)...
  14519. if (child1N < length) {
  14520. // Look it up and compute its score.
  14521. var child1 = this.content[child1N],
  14522. child1Score = this.scoreFunction(child1);
  14523. // If the score is less than our element's, we need to swap.
  14524. if (child1Score < elemScore)
  14525. swap = child1N;
  14526. }
  14527. // Do the same checks for the other child.
  14528. if (child2N < length) {
  14529. var child2 = this.content[child2N],
  14530. child2Score = this.scoreFunction(child2);
  14531. if (child2Score < (swap === null ? elemScore : child1Score)) {
  14532. swap = child2N;
  14533. }
  14534. }
  14535. // If the element needs to be moved, swap it, and continue.
  14536. if (swap !== null) {
  14537. this.content[n] = this.content[swap];
  14538. this.content[swap] = element;
  14539. n = swap;
  14540. }
  14541. // Otherwise, we are done.
  14542. else {
  14543. break;
  14544. }
  14545. }
  14546. }
  14547. });
  14548. module.exports = BinaryHeap;
  14549. },{"abitbol":1}],6:[function(require,module,exports){
  14550. var Class = require("abitbol");
  14551. var Channel = Class.$extend({
  14552. __init__: function() {
  14553. this.portals = [];
  14554. },
  14555. push: function (p1, p2) {
  14556. if (p2 === undefined) p2 = p1;
  14557. this.portals.push({
  14558. left: p1,
  14559. right: p2
  14560. });
  14561. },
  14562. _vequal: function (a, b) {
  14563. return BABYLON.Vector3.DistanceSquared(a, b) < 0.00001;
  14564. },
  14565. _triarea2: function (a, b, c) {
  14566. var ax = b.x - a.x;
  14567. var az = b.z - a.z;
  14568. var bx = c.x - a.x;
  14569. var bz = c.z - a.z;
  14570. return bx * az - ax * bz;
  14571. },
  14572. stringPull: function () {
  14573. var portals = this.portals;
  14574. var pts = [];
  14575. // Init scan state
  14576. var portalApex, portalLeft, portalRight;
  14577. var apexIndex = 0,
  14578. leftIndex = 0,
  14579. rightIndex = 0;
  14580. portalApex = portals[0].left;
  14581. portalLeft = portals[0].left;
  14582. portalRight = portals[0].right;
  14583. // Add start point.
  14584. pts.push(portalApex);
  14585. for (var i = 1; i < portals.length; i++) {
  14586. var left = portals[i].left;
  14587. var right = portals[i].right;
  14588. // Update right vertex.
  14589. if (this._triarea2(portalApex, portalRight, right) >= 0.0) {
  14590. if (this._vequal(portalApex, portalRight) || this._triarea2(portalApex, portalLeft, right) < 0.0) {
  14591. // Tighten the funnel.
  14592. portalRight = right;
  14593. rightIndex = i;
  14594. } else {
  14595. // Right over left, insert left to path and restart scan from portal left point.
  14596. pts.push(portalLeft);
  14597. // Make current left the new apex.
  14598. portalApex = portalLeft;
  14599. apexIndex = leftIndex;
  14600. // Reset portal
  14601. portalLeft = portalApex;
  14602. portalRight = portalApex;
  14603. leftIndex = apexIndex;
  14604. rightIndex = apexIndex;
  14605. // Restart scan
  14606. i = apexIndex;
  14607. continue;
  14608. }
  14609. }
  14610. // Update left vertex.
  14611. if (this._triarea2(portalApex, portalLeft, left) <= 0.0) {
  14612. if (this._vequal(portalApex, portalLeft) || this._triarea2(portalApex, portalRight, left) > 0.0) {
  14613. // Tighten the funnel.
  14614. portalLeft = left;
  14615. leftIndex = i;
  14616. } else {
  14617. // Left over right, insert right to path and restart scan from portal right point.
  14618. pts.push(portalRight);
  14619. // Make current right the new apex.
  14620. portalApex = portalRight;
  14621. apexIndex = rightIndex;
  14622. // Reset portal
  14623. portalLeft = portalApex;
  14624. portalRight = portalApex;
  14625. leftIndex = apexIndex;
  14626. rightIndex = apexIndex;
  14627. // Restart scan
  14628. i = apexIndex;
  14629. continue;
  14630. }
  14631. }
  14632. }
  14633. if ((pts.length === 0) || (!this._vequal(pts[pts.length - 1], portals[portals.length - 1].left))) {
  14634. // Append last point to path.
  14635. pts.push(portals[portals.length - 1].left);
  14636. }
  14637. this.path = pts;
  14638. return pts;
  14639. }
  14640. });
  14641. module.exports = Channel;
  14642. },{"abitbol":1}],7:[function(require,module,exports){
  14643. var Class = require("abitbol");
  14644. var _ = require("lodash");
  14645. var Astar = require("./Astar.js");
  14646. var Channel = require("./Channel.js");
  14647. /**
  14648. * This component generates screenshots of 3D models, in order to preview them when they are rendered.
  14649. *
  14650. * @class Focus3D
  14651. * @constructor
  14652. */
  14653. var Navigation = Class.$extend({
  14654. __init__: function() {
  14655. this.zoneNodes = {};
  14656. this.astar = new Astar();
  14657. },
  14658. buildNodes: function (mesh) {
  14659. var navigationMesh = this._buildNavigationMesh(mesh.geometry);
  14660. var zoneNodes = this._groupNavMesh(navigationMesh);
  14661. return zoneNodes;
  14662. },
  14663. setZoneData: function (zone, data) {
  14664. this.zoneNodes[zone] = data;
  14665. },
  14666. getGroup: function (zone, position) {
  14667. if (!this.zoneNodes[zone]) return null;
  14668. var closestNodeGroup = null;
  14669. var distance = Infinity;
  14670. _.each(this.zoneNodes[zone].groups, function (group, index) {
  14671. _.each(group, function (node) {
  14672. var measuredDistance = BABYLON.Vector3.DistanceSquared(node.centroid, position);
  14673. if (measuredDistance < distance) {
  14674. closestNodeGroup = index;
  14675. distance = measuredDistance;
  14676. }
  14677. });
  14678. });
  14679. return closestNodeGroup;
  14680. },
  14681. getRandomNode: function (zone, group, nearPosition, nearRange) {
  14682. if (!this.zoneNodes[zone]) return new BABYLON.Vector3();
  14683. nearPosition = nearPosition || null;
  14684. nearRange = nearRange || 0;
  14685. var candidates = [];
  14686. var polygons = this.zoneNodes[zone].groups[group];
  14687. _.each(polygons, function (p) {
  14688. if (nearPosition && nearRange) {
  14689. if (BABYLON.Vector3.DistanceSquared(nearPosition, p.centroid) < nearRange * nearRange) {
  14690. candidates.push(p.centroid);
  14691. }
  14692. } else {
  14693. candidates.push(p.centroid);
  14694. }
  14695. });
  14696. return _.sample(candidates) || new BABYLON.Vector3();
  14697. },
  14698. projectOnNavmesh: function (position, zone, group) {
  14699. var allNodes = this.zoneNodes[zone].groups[group];
  14700. var vertices = this.zoneNodes[zone].vertices;
  14701. var closestNode = null;
  14702. var distance = Infinity;
  14703. var finalProj = null, proj = null;
  14704. for (var i = 0; i < allNodes.length; i++) {
  14705. var node = allNodes[i];
  14706. var proj = this._getProjectionOnNode(position, node, vertices);
  14707. var measuredDistance = BABYLON.Vector3.DistanceSquared(proj, position);
  14708. if (measuredDistance < distance) {
  14709. distance = measuredDistance;
  14710. //this.meshes[3].position.copyFrom(proj);
  14711. finalProj = proj;
  14712. closestNode = node;
  14713. }
  14714. }
  14715. return finalProj;
  14716. },
  14717. _getProjectionOnNode: function(position, node, vertices) {
  14718. var A = this.getVectorFrom(vertices, node.vertexIds[0]);
  14719. var B = this.getVectorFrom(vertices, node.vertexIds[1]);
  14720. var C = this.getVectorFrom(vertices, node.vertexIds[2]);
  14721. var u = B.subtract(A);
  14722. var v = C.subtract(A);
  14723. var n = BABYLON.Vector3.Cross(u, v).normalize();
  14724. var plane = {
  14725. normal: n,
  14726. d: -A.dot(n)
  14727. };
  14728. var p = position.projectOnPlane(plane);
  14729. // Compute barycentric coordinates (u, v, w) for
  14730. // point p with respect to triangle (a, b, c)
  14731. var barycentric = function(p, a, b, c) {
  14732. var ret = {};
  14733. var v0 = c.subtract(a),
  14734. v1 = b.subtract(a),
  14735. v2 = p.subtract(a);
  14736. var d00 = v0.dot(v0);
  14737. var d01 = v0.dot(v1);
  14738. var d02 = v0.dot(v2);
  14739. var d11 = v1.dot(v1);
  14740. var d12 = v1.dot(v2);
  14741. var denom = d00 * d11 - d01 * d01;
  14742. ret.u = (d11 * d02 - d01 * d12) / denom;
  14743. ret.v = (d00 * d12 - d01 * d02) / denom;
  14744. ret.w = 1 - ret.u - ret.v;
  14745. return ret;
  14746. }
  14747. var bary = barycentric(p, A, B, C);
  14748. bary.u = Math.min(Math.max(bary.u, 0), 1);
  14749. bary.v = Math.min(Math.max(bary.v, 0), 1);
  14750. if (bary.u + bary.v >= 1) {
  14751. var sum = bary.u + bary.v;
  14752. bary.u /= sum;
  14753. bary.v /= sum;
  14754. }
  14755. var proj = A.add(B.subtract(A).scale(bary.v).add(C.subtract(A).scale(bary.u)));
  14756. return proj;
  14757. },
  14758. findPath: function (startPosition, targetPosition, zone, group) {
  14759. var allNodes = this.zoneNodes[zone].groups[group];
  14760. var vertices = this.zoneNodes[zone].vertices;
  14761. var closestNode = null;
  14762. var distance = Infinity;
  14763. allNodes.forEach(function (node) {
  14764. var measuredDistance = BABYLON.Vector3.DistanceSquared(node.centroid, startPosition);
  14765. if (measuredDistance < distance) {
  14766. closestNode = node;
  14767. distance = measuredDistance;
  14768. }
  14769. });
  14770. var farthestNode = null;
  14771. distance = Infinity;
  14772. allNodes.forEach(function (node) {
  14773. var measuredDistance = BABYLON.Vector3.DistanceSquared(node.centroid, targetPosition);
  14774. if (measuredDistance < distance &&
  14775. this._isVectorInPolygon(targetPosition, node, vertices)) {
  14776. farthestNode = node;
  14777. distance = measuredDistance;
  14778. }
  14779. }.bind(this));
  14780. // If we can't find any node, just go straight to the target
  14781. if (!closestNode || !farthestNode) {
  14782. return null;
  14783. }
  14784. var paths = this.astar.search(allNodes, closestNode, farthestNode);
  14785. var getPortalFromTo = function (a, b) {
  14786. for (var i = 0; i < a.neighbours.length; i++) {
  14787. if (a.neighbours[i] === b.id) {
  14788. return a.portals[i];
  14789. }
  14790. }
  14791. };
  14792. // We got the corridor
  14793. // Now pull the rope
  14794. var channel = new Channel();
  14795. channel.push(startPosition);
  14796. for (var i = 0; i < paths.length; i++) {
  14797. var polygon = paths[i];
  14798. var nextPolygon = paths[i + 1];
  14799. if (nextPolygon) {
  14800. var portals = getPortalFromTo(polygon, nextPolygon);
  14801. channel.push(
  14802. this.getVectorFrom(vertices, portals[0]),
  14803. this.getVectorFrom(vertices, portals[1])
  14804. );
  14805. }
  14806. }
  14807. channel.push(targetPosition);
  14808. channel.stringPull();
  14809. var vectors = [];
  14810. channel.path.forEach(function (c) {
  14811. var vec = new BABYLON.Vector3(c.x, c.y, c.z);
  14812. // console.log(vec.clone().sub(startPosition).length());
  14813. // Ensure the intermediate steps aren't too close to the start position
  14814. // var dist = vec.clone().sub(startPosition).lengthSq();
  14815. // if (dist > 0.01 * 0.01) {
  14816. vectors.push(vec);
  14817. // }
  14818. });
  14819. // We don't need the first one, as we already know our start position
  14820. vectors.shift();
  14821. return vectors;
  14822. },
  14823. _isPointInPoly: function (poly, pt) {
  14824. for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
  14825. ((poly[i].z <= pt.z && pt.z < poly[j].z) || (poly[j].z <= pt.z && pt.z < poly[i].z)) && (pt.x < (poly[j].x - poly[i].x) * (pt.z - poly[i].z) / (poly[j].z - poly[i].z) + poly[i].x) && (c = !c);
  14826. return c;
  14827. },
  14828. _isVectorInPolygon: function (vector, polygon, vertices) {
  14829. // reference point will be the centroid of the polygon
  14830. // We need to rotate the vector as well as all the points which the polygon uses
  14831. var center = polygon.centroid;
  14832. var lowestPoint = 100000;
  14833. var highestPoint = -100000;
  14834. var polygonVertices = [];
  14835. _.each(polygon.vertexIds, function (vId) {
  14836. var point = this.getVectorFrom(vertices, vId);
  14837. lowestPoint = Math.min(point.y, lowestPoint);
  14838. highestPoint = Math.max(point.y, highestPoint);
  14839. polygonVertices.push(point);
  14840. }.bind(this));
  14841. if (vector.y < highestPoint + 0.5 && vector.y > lowestPoint - 0.5 &&
  14842. this._isPointInPoly(polygonVertices, vector)) {
  14843. return true;
  14844. }
  14845. return false;
  14846. },
  14847. _computeCentroids: function (geometry) {
  14848. var f, fl, face;
  14849. var centroids = [];
  14850. var indices = geometry.getIndices();
  14851. var vertices = geometry.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  14852. var c = new BABYLON.Vector3(0, 0, 0);
  14853. for ( f = 0, fl = indices.length; f < fl; f += 3 ) {
  14854. var p1 = this.getVectorFrom(vertices, indices[f]);
  14855. var p2 = this.getVectorFrom(vertices, indices[f+1]);
  14856. var p3 = this.getVectorFrom(vertices, indices[f+2]);
  14857. c.copyFromFloats( 0, 0, 0 );
  14858. c.addInPlace(p1);
  14859. c.addInPlace(p2);
  14860. c.addInPlace(p3);
  14861. c.scaleInPlace( 1/3 );
  14862. centroids.push(c.clone());
  14863. }
  14864. geometry.centroids = centroids;
  14865. },
  14866. _roundNumber: function (number, decimals) {
  14867. var newnumber = new Number(number + '').toFixed(parseInt(decimals));
  14868. return parseFloat(newnumber);
  14869. },
  14870. _mergeVertexIds: function (aList, bList) {
  14871. var sharedVertices = [];
  14872. aList.forEach(function (vId) {
  14873. if (_.includes(bList, vId)) {
  14874. sharedVertices.push(vId);
  14875. }
  14876. });
  14877. if (sharedVertices.length < 2) return [];
  14878. // console.log("TRYING aList:", aList, ", bList:", bList, ", sharedVertices:", sharedVertices);
  14879. if (_.includes(sharedVertices, aList[0]) && _.includes(sharedVertices, aList[aList.length - 1])) {
  14880. // Vertices on both edges are bad, so shift them once to the left
  14881. aList.push(aList.shift());
  14882. }
  14883. if (_.includes(sharedVertices, bList[0]) && _.includes(sharedVertices, bList[bList.length - 1])) {
  14884. // Vertices on both edges are bad, so shift them once to the left
  14885. bList.push(bList.shift());
  14886. }
  14887. // Again!
  14888. sharedVertices = [];
  14889. aList.forEach(function (vId) {
  14890. if (_.includes(bList, vId)) {
  14891. sharedVertices.push(vId);
  14892. }
  14893. });
  14894. var clockwiseMostSharedVertex = sharedVertices[1];
  14895. var counterClockwiseMostSharedVertex = sharedVertices[0];
  14896. var cList = _.clone(aList);
  14897. while (cList[0] !== clockwiseMostSharedVertex) {
  14898. cList.push(cList.shift());
  14899. }
  14900. var c = 0;
  14901. var temp = _.clone(bList);
  14902. while (temp[0] !== counterClockwiseMostSharedVertex) {
  14903. temp.push(temp.shift());
  14904. if (c++ > 10) debugger;
  14905. }
  14906. // Shave
  14907. temp.shift();
  14908. temp.pop();
  14909. cList = cList.concat(temp);
  14910. // console.log("aList:", aList, ", bList:", bList, ", cList:", cList, ", sharedVertices:", sharedVertices);
  14911. return cList;
  14912. },
  14913. _setPolygonCentroid: function (polygon, navigationMesh) {
  14914. var sum = new BABYLON.Vector3(0, 0, 0);
  14915. var vertices = navigationMesh.vertices;
  14916. _.each(polygon.vertexIds, function (vId) {
  14917. sum.x += vertices[vId*3];
  14918. sum.y += vertices[vId*3+1];
  14919. sum.z += vertices[vId*3+2];
  14920. });
  14921. sum.scaleInPlace(1/polygon.vertexIds.length);
  14922. polygon.centroid.copyFrom(sum);
  14923. },
  14924. getVectorFrom: function (vertices, id, _vector) {
  14925. if (_vector) {
  14926. _vector.copyFromFloats(vertices[id*3], vertices[id*3+1], vertices[id*3+2]);
  14927. return _vector;
  14928. }
  14929. return new BABYLON.Vector3(vertices[id*3], vertices[id*3+1], vertices[id*3+2]);
  14930. },
  14931. _cleanPolygon: function (polygon, navigationMesh) {
  14932. var newVertexIds = [];
  14933. var vertices = navigationMesh.vertices;
  14934. for (var i = 0; i < polygon.vertexIds.length; i++) {
  14935. var vertex = this.getVectorFrom(vertices, polygon.vertexIds[i]);
  14936. var nextVertexId, previousVertexId;
  14937. var nextVertex, previousVertex;
  14938. // console.log("nextVertex: ", nextVertex);
  14939. if (i === 0) {
  14940. nextVertexId = polygon.vertexIds[1];
  14941. previousVertexId = polygon.vertexIds[polygon.vertexIds.length - 1];
  14942. } else if (i === polygon.vertexIds.length - 1) {
  14943. nextVertexId = polygon.vertexIds[0];
  14944. previousVertexId = polygon.vertexIds[polygon.vertexIds.length - 2];
  14945. } else {
  14946. nextVertexId = polygon.vertexIds[i + 1];
  14947. previousVertexId = polygon.vertexIds[i - 1];
  14948. }
  14949. nextVertex = this.getVectorFrom(vertices, nextVertexId);
  14950. previousVertex = this.getVectorFrom(vertices, previousVertexId);
  14951. var a = nextVertex.clone().sub(vertex);
  14952. var b = previousVertex.clone().sub(vertex);
  14953. var angle = a.angleTo(b);
  14954. // console.log(angle);
  14955. if (angle > Math.PI - 0.01 && angle < Math.PI + 0.01) {
  14956. // Unneccesary vertex
  14957. // console.log("Unneccesary vertex: ", polygon.vertexIds[i]);
  14958. // console.log("Angle between "+previousVertexId+", "+polygon.vertexIds[i]+" "+nextVertexId+" was: ", angle);
  14959. // Remove the neighbours who had this vertex
  14960. var goodNeighbours = [];
  14961. polygon.neighbours.forEach(function (neighbour) {
  14962. if (!_.includes(neighbour.vertexIds, polygon.vertexIds[i])) {
  14963. goodNeighbours.push(neighbour);
  14964. }
  14965. });
  14966. polygon.neighbours = goodNeighbours;
  14967. // TODO cleanup the list of vertices and rebuild vertexIds for all polygons
  14968. } else {
  14969. newVertexIds.push(polygon.vertexIds[i]);
  14970. }
  14971. }
  14972. // console.log("New vertexIds: ", newVertexIds);
  14973. polygon.vertexIds = newVertexIds;
  14974. this._setPolygonCentroid(polygon, navigationMesh);
  14975. },
  14976. _isConvex: function (polygon, navigationMesh) {
  14977. var vertices = navigationMesh.vertices;
  14978. if (polygon.vertexIds.length < 3) return false;
  14979. var convex = true;
  14980. var total = 0;
  14981. var results = [];
  14982. for (var i = 0; i < polygon.vertexIds.length; i++) {
  14983. var vertex = this.getVectorFrom(vertices, polygon.vertexIds[i]);
  14984. var nextVertex, previousVertex;
  14985. // console.log("nextVertex: ", nextVertex);
  14986. if (i === 0) {
  14987. nextVertex = this.getVectorFrom(vertices, polygon.vertexIds[1]);
  14988. previousVertex = this.getVectorFrom(vertices, polygon.vertexIds[polygon.vertexIds.length - 1]);
  14989. } else if (i === polygon.vertexIds.length - 1) {
  14990. nextVertex = this.getVectorFrom(vertices, polygon.vertexIds[0]);
  14991. previousVertex = this.getVectorFrom(vertices, polygon.vertexIds[polygon.vertexIds.length - 2]);
  14992. } else {
  14993. nextVertex = this.getVectorFrom(vertices, polygon.vertexIds[i + 1]);
  14994. previousVertex = this.getVectorFrom(vertices, polygon.vertexIds[i - 1]);
  14995. }
  14996. var a = nextVertex.clone().sub(vertex);
  14997. var b = previousVertex.clone().sub(vertex);
  14998. var angle = a.angleTo(b);
  14999. total += angle;
  15000. // console.log(angle);
  15001. if (angle === Math.PI || angle === 0) return false;
  15002. var r = BABYLON.Vector3.Cross(a, b).y;
  15003. results.push(r);
  15004. // console.log("pushed: ", r);
  15005. }
  15006. // if ( total > (polygon.vertexIds.length-2)*Math.PI ) return false;
  15007. results.forEach(function (r) {
  15008. if (r === 0) convex = false;
  15009. });
  15010. if (results[0] > 0) {
  15011. results.forEach(function (r) {
  15012. if (r < 0) convex = false;
  15013. });
  15014. } else {
  15015. results.forEach(function (r) {
  15016. if (r > 0) convex = false;
  15017. });
  15018. }
  15019. // console.log("allowed: "+total+", max: "+(polygon.vertexIds.length-2)*Math.PI);
  15020. // if ( total > (polygon.vertexIds.length-2)*Math.PI ) convex = false;
  15021. // console.log("Convex: "+(convex ? "true": "false"));
  15022. return convex;
  15023. },
  15024. _buildPolygonGroups: function (navigationMesh) {
  15025. var polygons = navigationMesh.polygons;
  15026. var vertices = navigationMesh.vertices;
  15027. var polygonGroups = [];
  15028. var groupCount = 0;
  15029. var spreadGroupId = function (polygon) {
  15030. _.each(polygon.neighbours, function (neighbour) {
  15031. if (_.isUndefined(neighbour.group)) {
  15032. neighbour.group = polygon.group;
  15033. spreadGroupId(neighbour);
  15034. }
  15035. });
  15036. };
  15037. _.each(polygons, function (polygon, i) {
  15038. if (_.isUndefined(polygon.group)) {
  15039. polygon.group = groupCount++;
  15040. // Spread it
  15041. spreadGroupId(polygon);
  15042. }
  15043. if (!polygonGroups[polygon.group]) polygonGroups[polygon.group] = [];
  15044. polygonGroups[polygon.group].push(polygon);
  15045. });
  15046. console.log("Groups built: ", polygonGroups.length);
  15047. return polygonGroups;
  15048. },
  15049. _array_intersect: function() {
  15050. var i, all, shortest, nShortest, n, len, ret = [],
  15051. obj = {},
  15052. nOthers;
  15053. nOthers = arguments.length - 1;
  15054. nShortest = arguments[0].length;
  15055. shortest = 0;
  15056. for (i = 0; i <= nOthers; i++) {
  15057. n = arguments[i].length;
  15058. if (n < nShortest) {
  15059. shortest = i;
  15060. nShortest = n;
  15061. }
  15062. }
  15063. for (i = 0; i <= nOthers; i++) {
  15064. n = (i === shortest) ? 0 : (i || shortest); //Read the shortest array first. Read the first array instead of the shortest
  15065. len = arguments[n].length;
  15066. for (var j = 0; j < len; j++) {
  15067. var elem = arguments[n][j];
  15068. if (obj[elem] === i - 1) {
  15069. if (i === nOthers) {
  15070. ret.push(elem);
  15071. obj[elem] = 0;
  15072. } else {
  15073. obj[elem] = i;
  15074. }
  15075. } else if (i === 0) {
  15076. obj[elem] = 0;
  15077. }
  15078. }
  15079. }
  15080. return ret;
  15081. },
  15082. _buildPolygonNeighbours: function (polygon, navigationMesh) {
  15083. polygon.neighbours = [];
  15084. // All other nodes that contain at least two of our vertices are our neighbours
  15085. for (var i = 0, len = navigationMesh.polygons.length; i < len; i++) {
  15086. if (polygon === navigationMesh.polygons[i]) continue;
  15087. // Don't check polygons that are too far, since the intersection tests take a long time
  15088. if (BABYLON.Vector3.DistanceSquared(polygon.centroid, navigationMesh.polygons[i].centroid) > 100 * 100) continue;
  15089. var matches = this._array_intersect(polygon.vertexIds, navigationMesh.polygons[i].vertexIds);
  15090. // var matches = _.intersection(polygon.vertexIds, navigationMesh.polygons[i].vertexIds);
  15091. if (matches.length >= 2) {
  15092. polygon.neighbours.push(navigationMesh.polygons[i]);
  15093. }
  15094. }
  15095. },
  15096. _buildPolygonsFromGeometry: function (geometry) {
  15097. var polygons = [];
  15098. var vertices = geometry.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  15099. var indices = geometry.getIndices();
  15100. var polygonId = 1;
  15101. console.log("Vertices:", vertices.length/3, "polygons:", indices.length/3);
  15102. // Convert the faces into a custom format that supports more than 3 vertices
  15103. for (var i = 0; i < indices.length; i+=3) {
  15104. var a = this.getVectorFrom(vertices, indices[i]);
  15105. var b = this.getVectorFrom(vertices, indices[i+1]);
  15106. var c = this.getVectorFrom(vertices, indices[i+2]);
  15107. var normal = BABYLON.Vector3.Cross(b.subtract(a), b.subtract(c)).normalize();
  15108. polygons.push({
  15109. id: polygonId++,
  15110. vertexIds: [indices[i], indices[i+1], indices[i+2]],
  15111. centroid: geometry.centroids[i/3],
  15112. normal: normal,
  15113. neighbours: []
  15114. });
  15115. }
  15116. var navigationMesh = {
  15117. polygons: polygons,
  15118. vertices: vertices
  15119. };
  15120. // Build a list of adjacent polygons
  15121. _.each(polygons, function (polygon) {
  15122. this._buildPolygonNeighbours(polygon, navigationMesh);
  15123. }.bind(this));
  15124. return navigationMesh;
  15125. },
  15126. _cleanNavigationMesh: function (navigationMesh) {
  15127. var polygons = navigationMesh.polygons;
  15128. var vertices = navigationMesh.vertices;
  15129. // Remove steep triangles
  15130. var up = new BABYLON.Vector3(0, 1, 0);
  15131. polygons = _.filter(polygons, function (polygon) {
  15132. var angle = Math.acos(up.dot(polygon.normal));
  15133. return angle < (Math.PI / 4);
  15134. });
  15135. // Remove unnecessary edges using the Hertel-Mehlhorn algorithm
  15136. // 1. Find a pair of adjacent nodes (i.e., two nodes that share an edge between them)
  15137. // whose normals are nearly identical (i.e., their surfaces face the same direction).
  15138. var newPolygons = [];
  15139. _.each(polygons, function (polygon) {
  15140. if (polygon.toBeDeleted) return;
  15141. var keepLooking = true;
  15142. while (keepLooking) {
  15143. keepLooking = false;
  15144. _.each(polygon.neighbours, function (otherPolygon) {
  15145. if (polygon === otherPolygon) return;
  15146. if (Math.acos(polygon.normal.dot(otherPolygon.normal)) < 0.01) {
  15147. // That's pretty equal alright!
  15148. // Merge otherPolygon with polygon
  15149. var testVertexIdList = [];
  15150. var testPolygon = {
  15151. vertexIds: mergeVertexIds(polygon.vertexIds, otherPolygon.vertexIds),
  15152. neighbours: polygon.neighbours,
  15153. normal: polygon.normal.clone(),
  15154. centroid: polygon.centroid.clone()
  15155. };
  15156. this._cleanPolygon(testPolygon, navigationMesh);
  15157. if (isConvex(testPolygon, navigationMesh)) {
  15158. otherPolygon.toBeDeleted = true;
  15159. // Inherit the neighbours from the to be merged polygon, except ourself
  15160. _.each(otherPolygon.neighbours, function (otherPolygonNeighbour) {
  15161. // Set this poly to be merged to be no longer our neighbour
  15162. otherPolygonNeighbour.neighbours = _.without(otherPolygonNeighbour.neighbours, otherPolygon);
  15163. if (otherPolygonNeighbour !== polygon) {
  15164. // Tell the old Polygon's neighbours about the new neighbour who has merged
  15165. otherPolygonNeighbour.neighbours.push(polygon);
  15166. } else {
  15167. // For ourself, we don't need to know about ourselves
  15168. // But we inherit the old neighbours
  15169. polygon.neighbours = polygon.neighbours.concat(otherPolygon.neighbours);
  15170. polygon.neighbours = _.uniq(polygon.neighbours);
  15171. // Without ourselves in it!
  15172. polygon.neighbours = _.without(polygon.neighbours, polygon);
  15173. }
  15174. });
  15175. polygon.vertexIds = mergeVertexIds(polygon.vertexIds, otherPolygon.vertexIds);
  15176. // console.log(polygon.vertexIds);
  15177. // console.log("Merge!");
  15178. cleanPolygon(polygon, navigationMesh);
  15179. keepLooking = true;
  15180. }
  15181. }
  15182. }.bind(this));
  15183. }
  15184. if (!polygon.toBeDeleted) {
  15185. newPolygons.push(polygon);
  15186. }
  15187. });
  15188. var isUsed = function (vId) {
  15189. var contains = false;
  15190. _.each(newPolygons, function (p) {
  15191. if (!contains && _.includes(p.vertexIds, vId)) {
  15192. contains = true;
  15193. }
  15194. });
  15195. return contains;
  15196. };
  15197. // Clean vertices
  15198. var keepChecking = false;
  15199. for (var i = 0; i < vertices.length; i++) {
  15200. if (!isUsed(i)) {
  15201. // Decrement all vertices that are higher than i
  15202. _.each(newPolygons, function (p) {
  15203. for (var j = 0; j < p.vertexIds.length; j++) {
  15204. if (p.vertexIds[j] > i) {
  15205. p.vertexIds[j] --;
  15206. }
  15207. }
  15208. });
  15209. vertices.splice(i, 1);
  15210. i--;
  15211. }
  15212. };
  15213. navigationMesh.polygons = newPolygons;
  15214. navigationMesh.vertices = vertices;
  15215. },
  15216. _buildNavigationMesh: function (geometry) {
  15217. // Prepare geometry
  15218. this._computeCentroids(geometry);
  15219. this._mergeVertices(geometry);
  15220. // BABYLON.GeometryUtils.triangulateQuads(geometry);
  15221. // console.log("vertices:", geometry.vertices.length, "polygons:", geometry.faces.length);
  15222. var navigationMesh = this._buildPolygonsFromGeometry(geometry);
  15223. // cleanNavigationMesh(navigationMesh);
  15224. // console.log("Pre-clean:", navigationMesh.polygons.length, "polygons,", navigationMesh.vertices.length, "vertices.");
  15225. // console.log("")
  15226. // console.log("Vertices:", navigationMesh.vertices.length, "polygons,", navigationMesh.polygons.length, "vertices.");
  15227. return navigationMesh;
  15228. },
  15229. _mergeVertices: function (geometry) {
  15230. var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
  15231. var unique = [], changes = [];
  15232. var v, key;
  15233. var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
  15234. var precision = Math.pow( 10, precisionPoints );
  15235. var i, il, face;
  15236. var indices, j, jl;
  15237. var ind = geometry.getIndices(),
  15238. vert = geometry.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  15239. for ( i = 0, il = vert.length; i < il; i += 3 ) {
  15240. v = new BABYLON.Vector3(vert[ i ], vert[ i +1], vert[ i +2]);
  15241. key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
  15242. if ( verticesMap[ key ] === undefined ) {
  15243. verticesMap[ key ] = i/3;
  15244. unique.push( v.clone() );
  15245. changes[ i/3 ] = unique.length - 1;
  15246. } else {
  15247. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  15248. changes[ i/3 ] = changes[ verticesMap[ key ] ];
  15249. }
  15250. }
  15251. // if faces are completely degenerate after merging vertices, we
  15252. // have to remove them from the geometry.
  15253. var faceIndicesToRemove = [];
  15254. for ( i = 0, il = ind.length; i < il; i += 3 ) {
  15255. ind[i] = changes[ ind[i] ];
  15256. ind[i+1] = changes[ ind[i+1] ];
  15257. ind[i+2] = changes[ ind[i+2] ];
  15258. indices = [ ind[i], ind[i+1], ind[i+2] ];
  15259. var dupIndex = - 1;
  15260. // if any duplicate vertices are found in a Face3
  15261. // we have to remove the face as nothing can be saved
  15262. for ( var n = 0; n < 3; n ++ ) {
  15263. if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
  15264. dupIndex = n;
  15265. faceIndicesToRemove.push( i );
  15266. break;
  15267. }
  15268. }
  15269. }
  15270. for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
  15271. var idx = faceIndicesToRemove[ i ];
  15272. ind.splice( idx, 3 );
  15273. }
  15274. // Use unique set of vertices
  15275. var diff = vert.length/3 - unique.length;
  15276. vert = [];
  15277. for (var i = 0; i < unique.length; i++) {
  15278. vert.push(unique[i].x, unique[i].y, unique[i].z);
  15279. }
  15280. geometry.setIndices(ind);
  15281. geometry.setVerticesData(BABYLON.VertexBuffer.PositionKind, vert);
  15282. return diff;
  15283. },
  15284. _getSharedVerticesInOrder: function (a, b) {
  15285. var aList = a.vertexIds;
  15286. var bList = b.vertexIds;
  15287. var sharedVertices = [];
  15288. _.each(aList, function (vId) {
  15289. if (_.includes(bList, vId)) {
  15290. sharedVertices.push(vId);
  15291. }
  15292. });
  15293. if (sharedVertices.length < 2) return [];
  15294. // console.log("TRYING aList:", aList, ", bList:", bList, ", sharedVertices:", sharedVertices);
  15295. if (_.includes(sharedVertices, aList[0]) && _.includes(sharedVertices, aList[aList.length - 1])) {
  15296. // Vertices on both edges are bad, so shift them once to the left
  15297. aList.push(aList.shift());
  15298. }
  15299. if (_.includes(sharedVertices, bList[0]) && _.includes(sharedVertices, bList[bList.length - 1])) {
  15300. // Vertices on both edges are bad, so shift them once to the left
  15301. bList.push(bList.shift());
  15302. }
  15303. // Again!
  15304. sharedVertices = [];
  15305. _.each(aList, function (vId) {
  15306. if (_.includes(bList, vId)) {
  15307. sharedVertices.push(vId);
  15308. }
  15309. });
  15310. return sharedVertices;
  15311. },
  15312. _groupNavMesh: function (navigationMesh) {
  15313. var saveObj = {};
  15314. _.each(navigationMesh.vertices, function (v) {
  15315. v = this._roundNumber(v, 2);
  15316. }.bind(this));
  15317. saveObj.vertices = navigationMesh.vertices;
  15318. var groups = this._buildPolygonGroups(navigationMesh);
  15319. saveObj.groups = [];
  15320. var findPolygonIndex = function (group, p) {
  15321. for (var i = 0; i < group.length; i++) {
  15322. if (p === group[i]) return i;
  15323. }
  15324. };
  15325. _.each(groups, function (group) {
  15326. var newGroup = [];
  15327. _.each(group, function (p) {
  15328. var neighbours = [];
  15329. _.each(p.neighbours, function (n) {
  15330. neighbours.push(findPolygonIndex(group, n));
  15331. });
  15332. // Build a portal list to each neighbour
  15333. var portals = [];
  15334. _.each(p.neighbours, function (n) {
  15335. portals.push(this._getSharedVerticesInOrder(p, n));
  15336. }.bind(this));
  15337. p.centroid.x = this._roundNumber(p.centroid.x, 2);
  15338. p.centroid.y = this._roundNumber(p.centroid.y, 2);
  15339. p.centroid.z = this._roundNumber(p.centroid.z, 2);
  15340. newGroup.push({
  15341. id: findPolygonIndex(group, p),
  15342. neighbours: neighbours,
  15343. vertexIds: p.vertexIds,
  15344. centroid: p.centroid,
  15345. portals: portals
  15346. });
  15347. }.bind(this));
  15348. saveObj.groups.push(newGroup);
  15349. }.bind(this));
  15350. return saveObj;
  15351. },
  15352. });
  15353. module.exports = Navigation;
  15354. },{"./Astar.js":4,"./Channel.js":6,"abitbol":1,"lodash":3}]},{},[7])(7)
  15355. });
  15356. //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9ncnVudC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYWJpdGJvbC9zcmMvYWJpdGJvbC5qcyIsIm5vZGVfbW9kdWxlcy9hYml0Ym9sL3NyYy9hbm5vdGF0aW9uLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC9sb2Rhc2guanMiLCJzcmMvQXN0YXIuanMiLCJzcmMvQmluYXJ5SGVhcC5qcyIsInNyYy9DaGFubmVsLmpzIiwic3JjL05hdmlnYXRpb24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDek9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDN0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3JsZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGV4dHJhY3RBbm5vdGF0aW9ucyA9IHJlcXVpcmUoXCIuL2Fubm90YXRpb24uanNcIik7XG5cbnZhciBfZGlzYWJsZUNvbnN0cnVjdG9yID0gZmFsc2U7XG5cbi8vIEluaGVyaXQgZnJvbSBhIGNsYXNzIHdpdGhvdXQgY2FsbGluZyBpdHMgY29uc3RydWN0b3IuXG5mdW5jdGlvbiBpbmhlcml0KFN1cGVyQ2xhc3MpIHtcbiAgICBfZGlzYWJsZUNvbnN0cnVjdG9yID0gdHJ1ZTtcbiAgICB2YXIgX19jbGFzc19fID0gbmV3IFN1cGVyQ2xhc3MoKTtcbiAgICBfZGlzYWJsZUNvbnN0cnVjdG9yID0gZmFsc2U7XG4gICAgcmV0dXJuIF9fY2xhc3NfXztcbn1cblxuLy8gQ2hlY2tzIGlmIHRoZSBnaXZlbiBmdW5jdGlvbiB1c2VzIGFiaXRib2wgc3BlY2lhbCBwcm9wZXJ0aWVzICgkc3VwZXIsICRuYW1lLC4uLilcbmZ1bmN0aW9uIHVzZXNTcGVjaWFsUHJvcGVydHkoZm4pIHtcbiAgICByZXR1cm4gQm9vbGVhbihmbi50b1N0cmluZygpLm1hdGNoKC8uKihcXCRzdXBlcnxcXCRuYW1lfFxcJGNvbXB1dGVkUHJvcGVydHlOYW1lKS4qLykpO1xufVxuXG52YXIgQ2xhc3MgPSBmdW5jdGlvbiAoKSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KENsYXNzLCBcIiRjbGFzc1wiLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IENsYXNzXG59KTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KENsYXNzLCBcIiRtYXBcIiwge1xuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiB7XG4gICAgICAgIGF0dHJpYnV0ZXM6IHt9LFxuICAgICAgICBtZXRob2RzOiB7fSxcbiAgICAgICAgY29tcHV0ZWRQcm9wZXJ0aWVzOiB7fVxuICAgIH1cbn0pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQ2xhc3MsIFwiJGV4dGVuZFwiLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIChwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHZhciBfc3VwZXJDbGFzcyA9IHRoaXM7XG4gICAgICAgIHZhciBfY2xhc3NNYXAgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KF9zdXBlckNsYXNzLiRtYXApKTsgIC8vIG5vdCBwcmV0dHkgOnNcblxuICAgICAgICAvLyBOZXcgY2xhc3NcbiAgICAgICAgdmFyIF9fY2xhc3NfXyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfZGlzYWJsZUNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQWJpdGJvbCBzcGVjaWFsIHByb3BlcnRpZXNcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIiRjbGFzc1wiLCB7XG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgdmFsdWU6IF9fY2xhc3NfX1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCIkbWFwXCIsIHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogX2NsYXNzTWFwXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIiRkYXRhXCIsIHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB2YWx1ZToge31cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gQ29tcHV0ZWQgcHJvcGVydGllc1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcGVydHkgaW4gX2NsYXNzTWFwLmNvbXB1dGVkUHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBwcm9wZXJ0eSwge1xuICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBnZXQ6IChfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW3Byb3BlcnR5XS5nZXQgIT09IHVuZGVmaW5lZCkgPyAoZnVuY3Rpb24gKGFjY2Vzc29yTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1thY2Nlc3Nvck5hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9KShfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW3Byb3BlcnR5XS5nZXQpIDogdW5kZWZpbmVkLCAgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgICAgICAgICAgICAgIHNldDogKF9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbcHJvcGVydHldLnNldCAhPT0gdW5kZWZpbmVkKSA/IChmdW5jdGlvbiAobXV0YXRvck5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNbbXV0YXRvck5hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9KShfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW3Byb3BlcnR5XS5zZXQpIDogdW5kZWZpbmVkICAgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBCaW5kIHRoaXNcbiAgICAgICAgICAgIGZvciAodmFyIG1ldGhvZCBpbiBfY2xhc3NNYXAubWV0aG9kcykge1xuICAgICAgICAgICAgICAgIHRoaXNbbWV0aG9kXSA9IHRoaXNbbWV0aG9kXS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2FsbCB0aGUgY29uc3RydWN0b3IgaWYgYW55XG4gICAgICAgICAgICBpZiAodGhpcy5fX2luaXRfXykge1xuICAgICAgICAgICAgICAgIHRoaXMuX19pbml0X18uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEluaGVyaXRhbmNlXG4gICAgICAgIF9fY2xhc3NfXy5wcm90b3R5cGUgPSBpbmhlcml0KHRoaXMuJGNsYXNzKTtcblxuICAgICAgICBwcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgdmFyIHByb3BlcnR5O1xuICAgICAgICB2YXIgY29tcHV0ZWRQcm9wZXJ0eU5hbWU7XG4gICAgICAgIHZhciBhbm5vdGF0aW9ucztcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgLy8gQ29weSBwcm9wZXJ0aWVzIGZyb20gbWl4aW5zXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLl9faW5jbHVkZV9fKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSBwcm9wZXJ0aWVzLl9faW5jbHVkZV9fLmxlbmd0aCAtIDEgOyBpID49IDAgOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBmb3IgKHByb3BlcnR5IGluIHByb3BlcnRpZXMuX19pbmNsdWRlX19baV0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNbcHJvcGVydHldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXNbcHJvcGVydHldID0gcHJvcGVydGllcy5fX2luY2x1ZGVfX1tpXVtwcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgcHJvcGVydGllc1xuICAgICAgICBmb3IgKHByb3BlcnR5IGluIHByb3BlcnRpZXMgfHwge30pIHtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0eSA9PSBcIl9faW5jbHVkZV9fXCIgfHwgcHJvcGVydHkgPT0gXCJfX2NsYXNzdmFyc19fXCIpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcGVydGllc1twcm9wZXJ0eV0gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZWRQcm9wZXJ0eU5hbWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgX2NsYXNzTWFwLm1ldGhvZHNbcHJvcGVydHldID0ge2Fubm90YXRpb25zOiB7fX07XG4gICAgICAgICAgICAgICAgLy8gQWNjZXNzb3JzIC8gTXV0YXRvcnNcbiAgICAgICAgICAgICAgICBpZiAocHJvcGVydHkuaW5kZXhPZihcImdldFwiKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wdXRlZFByb3BlcnR5TmFtZSA9IHByb3BlcnR5LnNsaWNlKDMsIDQpLnRvTG93ZXJDYXNlKCkgKyBwcm9wZXJ0eS5zbGljZSg0LCBwcm9wZXJ0eS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW2NvbXB1dGVkUHJvcGVydHlOYW1lXSA9IHthbm5vdGF0aW9uczoge319O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdLmdldCA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcGVydHkuaW5kZXhPZihcInNldFwiKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wdXRlZFByb3BlcnR5TmFtZSA9IHByb3BlcnR5LnNsaWNlKDMsIDQpLnRvTG93ZXJDYXNlKCkgKyBwcm9wZXJ0eS5zbGljZSg0LCBwcm9wZXJ0eS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW2NvbXB1dGVkUHJvcGVydHlOYW1lXSA9IHthbm5vdGF0aW9uczoge319O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdLnNldCA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcGVydHkuaW5kZXhPZihcImhhc1wiKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wdXRlZFByb3BlcnR5TmFtZSA9IHByb3BlcnR5LnNsaWNlKDMsIDQpLnRvTG93ZXJDYXNlKCkgKyBwcm9wZXJ0eS5zbGljZSg0LCBwcm9wZXJ0eS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NNYXAuY29tcHV0ZWRQcm9wZXJ0aWVzW2NvbXB1dGVkUHJvcGVydHlOYW1lXSA9IHthbm5vdGF0aW9uczoge319O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdLmdldCA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcGVydHkuaW5kZXhPZihcImlzXCIpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXB1dGVkUHJvcGVydHlOYW1lID0gcHJvcGVydHkuc2xpY2UoMiwgMykudG9Mb3dlckNhc2UoKSArIHByb3BlcnR5LnNsaWNlKDMsIHByb3BlcnR5Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzTWFwLmNvbXB1dGVkUHJvcGVydGllc1tjb21wdXRlZFByb3BlcnR5TmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc01hcC5jb21wdXRlZFByb3BlcnRpZXNbY29tcHV0ZWRQcm9wZXJ0eU5hbWVdID0ge2Fubm90YXRpb25zOiB7fX07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX2NsYXNzTWFwLmNvbXB1dGVkUHJvcGVydGllc1tjb21wdXRlZFByb3BlcnR5TmFtZV0uZ2V0ID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIEFubm90YXRpb25zXG4gICAgICAgICAgICAgICAgYW5ub3RhdGlvbnMgPSBleHRyYWN0QW5ub3RhdGlvbnMocHJvcGVydGllc1twcm9wZXJ0eV0pO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGFubm90YXRpb24gaW4gYW5ub3RhdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgX2NsYXNzTWFwLm1ldGhvZHNbcHJvcGVydHldLmFubm90YXRpb25zW2Fubm90YXRpb25dID0gYW5ub3RhdGlvbnNbYW5ub3RhdGlvbl07XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb21wdXRlZFByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzTWFwLmNvbXB1dGVkUHJvcGVydGllc1tjb21wdXRlZFByb3BlcnR5TmFtZV1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hbm5vdGF0aW9uc1thbm5vdGF0aW9uXSA9IGFubm90YXRpb25zW2Fubm90YXRpb25dO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFdyYXBwZWQgbWV0aG9kXG4gICAgICAgICAgICAgICAgaWYgKHVzZXNTcGVjaWFsUHJvcGVydHkocHJvcGVydGllc1twcm9wZXJ0eV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NfXy5wcm90b3R5cGVbcHJvcGVydHldID0gKGZ1bmN0aW9uIChtZXRob2QsIHByb3BlcnR5TmFtZSwgY29tcHV0ZWRQcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9vbGRTdXBlciA9IHRoaXMuJHN1cGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfb2xkTmFtZSA9IHRoaXMuJG5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9vbGRDb21wdXRlZFByb3BlcnR5TmFtZSA9IHRoaXMuJGNvbXB1dGVkUHJvcGVydHlOYW1lO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kc3VwZXIgPSBfc3VwZXJDbGFzcy5wcm90b3R5cGVbcHJvcGVydHlOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiRuYW1lID0gcHJvcGVydHlOYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuJGNvbXB1dGVkUHJvcGVydHlOYW1lID0gY29tcHV0ZWRQcm9wZXJ0eU5hbWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9vbGRTdXBlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kc3VwZXIgPSBfb2xkU3VwZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy4kc3VwZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9vbGROYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiRuYW1lID0gX29sZE5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy4kbmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoX29sZENvbXB1dGVkUHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiRjb21wdXRlZFByb3BlcnR5TmFtZSA9IF9vbGRDb21wdXRlZFByb3BlcnR5TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLiRjb21wdXRlZFByb3BlcnR5TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0pKHByb3BlcnRpZXNbcHJvcGVydHldLCBwcm9wZXJ0eSwgY29tcHV0ZWRQcm9wZXJ0eU5hbWUpOyAgLy8ganNoaW50IGlnbm9yZTpsaW5lXG5cbiAgICAgICAgICAgICAgICAvLyBTaW1wbGUgbWV0aG9kc1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NfXy5wcm90b3R5cGVbcHJvcGVydHldID0gcHJvcGVydGllc1twcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfY2xhc3NNYXAuYXR0cmlidXRlc1twcm9wZXJ0eV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIF9fY2xhc3NfXy5wcm90b3R5cGVbcHJvcGVydHldID0gcHJvcGVydGllc1twcm9wZXJ0eV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb3B5IHN1cGVyIGNsYXNzIHN0YXRpYyBwcm9wZXJ0aWVzXG4gICAgICAgIHZhciBzY1N0YXRpY1Byb3BzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoX3N1cGVyQ2xhc3MpO1xuICAgICAgICAvLyBSZW1vdmVzIGNhbGxlciwgY2FsbGVlIGFuZCBhcmd1bWVudHMgZnJvbSB0aGUgbGlzdCAoc3RyaWN0IG1vZGUpXG4gICAgICAgIC8vIFJlbW92ZXMgbm9uIGVudW1lcmFibGUgQWJpdGJvbCBwcm9wZXJ0aWVzIHRvb1xuICAgICAgICBzY1N0YXRpY1Byb3BzID0gc2NTdGF0aWNQcm9wcy5maWx0ZXIoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gKFtcImNhbGxlclwiLCBcImNhbGxlZVwiLCBcImFyZ3VtZW50c1wiLCBcIiRjbGFzc1wiLCBcIiRleHRlbmRcIiwgXCIkbWFwXCJdLmluZGV4T2YodmFsdWUpID09IC0xKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZvciAoaSA9IDAgOyBpIDwgc2NTdGF0aWNQcm9wcy5sZW5ndGggOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChfX2NsYXNzX19bc2NTdGF0aWNQcm9wc1tpXV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIF9fY2xhc3NfX1tzY1N0YXRpY1Byb3BzW2ldXSA9IF9zdXBlckNsYXNzW3NjU3RhdGljUHJvcHNbaV1dO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHN0YXRpYyBwcm9wZXJ0aWVzXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLl9fY2xhc3N2YXJzX18pIHtcbiAgICAgICAgICAgIGZvciAocHJvcGVydHkgaW4gcHJvcGVydGllcy5fX2NsYXNzdmFyc19fKSB7XG4gICAgICAgICAgICAgICAgX19jbGFzc19fW3Byb3BlcnR5XSA9IHByb3BlcnRpZXMuX19jbGFzc3ZhcnNfX1twcm9wZXJ0eV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYWJpdGJvbCBzdGF0aWMgcHJvcGVydGllc1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX19jbGFzc19fLCBcIiRjbGFzc1wiLCB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbHVlOiBfX2NsYXNzX19cbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfX2NsYXNzX18sIFwiJGV4dGVuZFwiLCB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbHVlOiBDbGFzcy4kZXh0ZW5kXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoX19jbGFzc19fLCBcIiRtYXBcIiwge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICB2YWx1ZTogX2NsYXNzTWFwXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBfX2NsYXNzX187XG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gQ2xhc3M7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuZnVuY3Rpb24gY2xlYW5Kcyhqcykge1xuICAgIC8vIHJlbW92ZSBmdW5jdGlvbiBmbihwYXJhbSkge1xuICAgIGpzID0ganMucmVwbGFjZSgvXmZ1bmN0aW9uXFxzKlteKF0qXFxzKlxcKFteKV0qXFwpXFxzKlxcey8sIFwiXCIpO1xuXG4gICAgLy8gcmVtb3ZlIGNvbW1lbnRzIChub3Qgc3VwZXIgc2FmZSBidXQgc2hvdWxkIHdvcmsgaW4gbW9zdCBjYXNlcylcbiAgICBqcyA9IGpzLnJlcGxhY2UoL1xcL1xcKigufFxccnxcXG4pKj9cXCpcXC8vZywgXCJcIik7XG4gICAganMgPSBqcy5yZXBsYWNlKC9cXC9cXC8uKj9cXHI/XFxuL2csIFwiXFxuXCIpO1xuXG4gICAgLy8gcmVtb3ZlIGluZGVudGF0aW9uIGFuZCBDUi9MRlxuICAgIGpzID0ganMucmVwbGFjZSgvXFxzKlxccj9cXG5cXHMqL2csIFwiXCIpO1xuXG4gICAgcmV0dXJuIGpzO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0U3RyaW5ncyhqcykge1xuICAgIHZhciBzdHJpbmdzID0gW107XG5cbiAgICB2YXIgaW5zdHIgPSBmYWxzZTtcbiAgICB2YXIgaW5lc2MgPSBmYWxzZTtcbiAgICB2YXIgcXVvdGU7XG4gICAgdmFyIGJ1ZmY7XG4gICAgdmFyIGM7XG5cbiAgICBmb3IgKHZhciBpID0gMCA7IGkgPCBqcy5sZW5ndGggOyBpKyspIHtcbiAgICAgICAgYyA9IGpzW2ldO1xuXG4gICAgICAgIGlmICghaW5zdHIpIHtcbiAgICAgICAgICAgIC8vIE5ldyBzdHJpbmdcbiAgICAgICAgICAgIGlmIChjID09IFwiXFxcIlwiIHx8IGMgPT0gXCInXCIpIHtcbiAgICAgICAgICAgICAgICBpbnN0ciA9IHRydWU7XG4gICAgICAgICAgICAgICAgaW5lc2MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBxdW90ZSA9IGM7XG4gICAgICAgICAgICAgICAgYnVmZiA9IFwiXCI7XG4gICAgICAgICAgICAvLyBDaGFyIHdlIGRvbid0IGNhcmUgYWJvdXRcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoW1wiIFwiLCBcIsKgXCIsIFwiXFxuXCIsIFwiXFxyXCIsIFwiO1wiXS5pbmRleE9mKGMpID4gLTEpIHsgIC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgLy8gT3RoZXIgZXhwcmVzc2lvbiAtPiBqb2IgZmluaXNoZWQhXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFpbmVzYykge1xuICAgICAgICAgICAgICAgIC8vIEVzY2FwZWQgY2hhclxuICAgICAgICAgICAgICAgIGlmIChjID09IFwiXFxcXFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGluZXNjID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAvLyBFbmQgb2Ygc3RyaW5nXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09IHF1b3RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmluZ3MucHVzaChidWZmKTtcbiAgICAgICAgICAgICAgICAgICAgaW5zdHIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAvLyBBbnkgY2hhclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmYgKz0gYztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjID09IFwiXFxcXFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmYgKz0gXCJcXFxcXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09IFwiblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmYgKz0gXCJcXG5cIjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT0gXCJyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgYnVmZiArPSBcIlxcclwiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PSBcInRcIikge1xuICAgICAgICAgICAgICAgICAgICBidWZmICs9IFwiXFx0XCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09IHF1b3RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmYgKz0gcXVvdGU7XG4gICAgICAgICAgICAgICAgLy8gV2UgZG9uJ3QgY2FyZS4uLlxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1ZmYgKz0gXCJcXFxcXCIgKyBjO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpbmVzYyA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0cmluZ3M7XG59XG5cbmZ1bmN0aW9uIGF1dG9DYXN0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IFwidHJ1ZVwiKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgPT0gXCJmYWxzZVwiKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlID09IFwibnVsbFwiKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSBpZiAodmFsdWUubWF0Y2goL14oWzAtOV0rXFwuP3xbMC05XSpcXC5bMC05XSspJC8pKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBleHRyYWN0QW5ub3RhdGlvbnMoZnVuYykge1xuICAgIHZhciBqcyA9IGNsZWFuSnMoZnVuYy50b1N0cmluZygpKTtcbiAgICB2YXIgc3RyaW5ncyA9IGV4dHJhY3RTdHJpbmdzKGpzKTtcblxuICAgIHZhciBhbm5vdGF0aW9ucyA9IHt9O1xuICAgIHZhciBzdHJpbmc7XG4gICAgdmFyIGtleTtcbiAgICB2YXIgdmFsdWU7XG5cbiAgICBmb3IgKHZhciBpID0gMCA7IGkgPCBzdHJpbmdzLmxlbmd0aCA7IGkrKykge1xuICAgICAgICBzdHJpbmcgPSBzdHJpbmdzW2ldLnRyaW0oKTtcblxuICAgICAgICBpZiAoc3RyaW5nLmluZGV4T2YoXCJAXCIpICE9PSAwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGtleSA9IHN0cmluZy5zbGljZSgxLCAoc3RyaW5nLmluZGV4T2YoXCIgXCIpID4gLTEpID8gc3RyaW5nLmluZGV4T2YoXCIgXCIpIDogc3RyaW5nLmxlbmd0aCk7XG4gICAgICAgIHZhbHVlID0gdHJ1ZTtcbiAgICAgICAgaWYgKHN0cmluZy5pbmRleE9mKFwiIFwiKSA+IC0xKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHN0cmluZy5zbGljZShzdHJpbmcuaW5kZXhPZihcIiBcIikgKyAxLCBzdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUudHJpbSgpO1xuICAgICAgICAgICAgdmFsdWUgPSBhdXRvQ2FzdCh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBhbm5vdGF0aW9uc1trZXldID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFubm90YXRpb25zO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dHJhY3RBbm5vdGF0aW9ucztcbiIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIGxvZGFzaCA0LjUuMSAoQ3VzdG9tIEJ1aWxkKSA8aHR0cHM6Ly9sb2Rhc2guY29tLz5cbiAqIEJ1aWxkOiBgbG9kYXNoIC1kIC1vIC4vZm9vL2xvZGFzaC5qc2BcbiAqIENvcHlyaWdodCAyMDEyLTIwMTYgVGhlIERvam8gRm91bmRhdGlvbiA8aHR0cDovL2Rvam9mb3VuZGF0aW9uLm9yZy8+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuOC4zIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IDIwMDktMjAxNiBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqL1xuOyhmdW5jdGlvbigpIHtcblxuICAvKiogVXNlZCBhcyBhIHNhZmUgcmVmZXJlbmNlIGZvciBgdW5kZWZpbmVkYCBpbiBwcmUtRVM1IGVudmlyb25tZW50cy4gKi9cbiAgdmFyIHVuZGVmaW5lZDtcblxuICAvKiogVXNlZCBhcyB0aGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIuICovXG4gIHZhciBWRVJTSU9OID0gJzQuNS4xJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB3cmFwcGVyIG1ldGFkYXRhLiAqL1xuICB2YXIgQklORF9GTEFHID0gMSxcbiAgICAgIEJJTkRfS0VZX0ZMQUcgPSAyLFxuICAgICAgQ1VSUllfQk9VTkRfRkxBRyA9IDQsXG4gICAgICBDVVJSWV9GTEFHID0gOCxcbiAgICAgIENVUlJZX1JJR0hUX0ZMQUcgPSAxNixcbiAgICAgIFBBUlRJQUxfRkxBRyA9IDMyLFxuICAgICAgUEFSVElBTF9SSUdIVF9GTEFHID0gNjQsXG4gICAgICBBUllfRkxBRyA9IDEyOCxcbiAgICAgIFJFQVJHX0ZMQUcgPSAyNTYsXG4gICAgICBGTElQX0ZMQUcgPSA1MTI7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgY29tcGFyaXNvbiBzdHlsZXMuICovXG4gIHZhciBVTk9SREVSRURfQ09NUEFSRV9GTEFHID0gMSxcbiAgICAgIFBBUlRJQUxfQ09NUEFSRV9GTEFHID0gMjtcblxuICAvKiogVXNlZCBhcyBkZWZhdWx0IG9wdGlvbnMgZm9yIGBfLnRydW5jYXRlYC4gKi9cbiAgdmFyIERFRkFVTFRfVFJVTkNfTEVOR1RIID0gMzAsXG4gICAgICBERUZBVUxUX1RSVU5DX09NSVNTSU9OID0gJy4uLic7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGhvdCBmdW5jdGlvbnMgYnkgbnVtYmVyIG9mIGNhbGxzIHdpdGhpbiBhIHNwYW4gb2YgbWlsbGlzZWNvbmRzLiAqL1xuICB2YXIgSE9UX0NPVU5UID0gMTUwLFxuICAgICAgSE9UX1NQQU4gPSAxNjtcblxuICAvKiogVXNlZCBhcyB0aGUgc2l6ZSB0byBlbmFibGUgbGFyZ2UgYXJyYXkgb3B0aW1pemF0aW9ucy4gKi9cbiAgdmFyIExBUkdFX0FSUkFZX1NJWkUgPSAyMDA7XG5cbiAgLyoqIFVzZWQgdG8gaW5kaWNhdGUgdGhlIHR5cGUgb2YgbGF6eSBpdGVyYXRlZXMuICovXG4gIHZhciBMQVpZX0ZJTFRFUl9GTEFHID0gMSxcbiAgICAgIExBWllfTUFQX0ZMQUcgPSAyLFxuICAgICAgTEFaWV9XSElMRV9GTEFHID0gMztcblxuICAvKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xuICB2YXIgRlVOQ19FUlJPUl9URVhUID0gJ0V4cGVjdGVkIGEgZnVuY3Rpb24nO1xuXG4gIC8qKiBVc2VkIHRvIHN0YW5kLWluIGZvciBgdW5kZWZpbmVkYCBoYXNoIHZhbHVlcy4gKi9cbiAgdmFyIEhBU0hfVU5ERUZJTkVEID0gJ19fbG9kYXNoX2hhc2hfdW5kZWZpbmVkX18nO1xuXG4gIC8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xuICB2YXIgSU5GSU5JVFkgPSAxIC8gMCxcbiAgICAgIE1BWF9TQUZFX0lOVEVHRVIgPSA5MDA3MTk5MjU0NzQwOTkxLFxuICAgICAgTUFYX0lOVEVHRVIgPSAxLjc5NzY5MzEzNDg2MjMxNTdlKzMwOCxcbiAgICAgIE5BTiA9IDAgLyAwO1xuXG4gIC8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHRoZSBtYXhpbXVtIGxlbmd0aCBhbmQgaW5kZXggb2YgYW4gYXJyYXkuICovXG4gIHZhciBNQVhfQVJSQVlfTEVOR1RIID0gNDI5NDk2NzI5NSxcbiAgICAgIE1BWF9BUlJBWV9JTkRFWCA9IE1BWF9BUlJBWV9MRU5HVEggLSAxLFxuICAgICAgSEFMRl9NQVhfQVJSQVlfTEVOR1RIID0gTUFYX0FSUkFZX0xFTkdUSCA+Pj4gMTtcblxuICAvKiogVXNlZCBhcyB0aGUgaW50ZXJuYWwgYXJndW1lbnQgcGxhY2Vob2xkZXIuICovXG4gIHZhciBQTEFDRUhPTERFUiA9ICdfX2xvZGFzaF9wbGFjZWhvbGRlcl9fJztcblxuICAvKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG4gIHZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgICBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgICAgZ2VuVGFnID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJyxcbiAgICAgIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nLFxuICAgICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJyxcbiAgICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICAgIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nLFxuICAgICAgd2Vha01hcFRhZyA9ICdbb2JqZWN0IFdlYWtNYXBdJyxcbiAgICAgIHdlYWtTZXRUYWcgPSAnW29iamVjdCBXZWFrU2V0XSc7XG5cbiAgdmFyIGFycmF5QnVmZmVyVGFnID0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJyxcbiAgICAgIGZsb2F0MzJUYWcgPSAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICAgIGZsb2F0NjRUYWcgPSAnW29iamVjdCBGbG9hdDY0QXJyYXldJyxcbiAgICAgIGludDhUYWcgPSAnW29iamVjdCBJbnQ4QXJyYXldJyxcbiAgICAgIGludDE2VGFnID0gJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgICAgaW50MzJUYWcgPSAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgICB1aW50OFRhZyA9ICdbb2JqZWN0IFVpbnQ4QXJyYXldJyxcbiAgICAgIHVpbnQ4Q2xhbXBlZFRhZyA9ICdbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XScsXG4gICAgICB1aW50MTZUYWcgPSAnW29iamVjdCBVaW50MTZBcnJheV0nLFxuICAgICAgdWludDMyVGFnID0gJ1tvYmplY3QgVWludDMyQXJyYXldJztcblxuICAvKiogVXNlZCB0byBtYXRjaCBlbXB0eSBzdHJpbmcgbGl0ZXJhbHMgaW4gY29tcGlsZWQgdGVtcGxhdGUgc291cmNlLiAqL1xuICB2YXIgcmVFbXB0eVN0cmluZ0xlYWRpbmcgPSAvXFxiX19wIFxcKz0gJyc7L2csXG4gICAgICByZUVtcHR5U3RyaW5nTWlkZGxlID0gL1xcYihfX3AgXFwrPSkgJycgXFwrL2csXG4gICAgICByZUVtcHR5U3RyaW5nVHJhaWxpbmcgPSAvKF9fZVxcKC4qP1xcKXxcXGJfX3RcXCkpIFxcK1xcbicnOy9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIEhUTUwgZW50aXRpZXMgYW5kIEhUTUwgY2hhcmFjdGVycy4gKi9cbiAgdmFyIHJlRXNjYXBlZEh0bWwgPSAvJig/OmFtcHxsdHxndHxxdW90fCMzOXwjOTYpOy9nLFxuICAgICAgcmVVbmVzY2FwZWRIdG1sID0gL1smPD5cIidgXS9nLFxuICAgICAgcmVIYXNFc2NhcGVkSHRtbCA9IFJlZ0V4cChyZUVzY2FwZWRIdG1sLnNvdXJjZSksXG4gICAgICByZUhhc1VuZXNjYXBlZEh0bWwgPSBSZWdFeHAocmVVbmVzY2FwZWRIdG1sLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdGVtcGxhdGUgZGVsaW1pdGVycy4gKi9cbiAgdmFyIHJlRXNjYXBlID0gLzwlLShbXFxzXFxTXSs/KSU+L2csXG4gICAgICByZUV2YWx1YXRlID0gLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICAgIHJlSW50ZXJwb2xhdGUgPSAvPCU9KFtcXHNcXFNdKz8pJT4vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBwcm9wZXJ0eSBuYW1lcyB3aXRoaW4gcHJvcGVydHkgcGF0aHMuICovXG4gIHZhciByZUlzRGVlcFByb3AgPSAvXFwufFxcWyg/OlteW1xcXV0qfChbXCInXSkoPzooPyFcXDEpW15cXFxcXXxcXFxcLikqP1xcMSlcXF0vLFxuICAgICAgcmVJc1BsYWluUHJvcCA9IC9eXFx3KiQvLFxuICAgICAgcmVQcm9wTmFtZSA9IC9bXi5bXFxdXSt8XFxbKD86KC0/XFxkKyg/OlxcLlxcZCspPyl8KFtcIiddKSgoPzooPyFcXDIpW15cXFxcXXxcXFxcLikqPylcXDIpXFxdL2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYFJlZ0V4cGAgW3N5bnRheCBjaGFyYWN0ZXJzXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1wYXR0ZXJucykuICovXG4gIHZhciByZVJlZ0V4cENoYXIgPSAvW1xcXFxeJC4qKz8oKVtcXF17fXxdL2csXG4gICAgICByZUhhc1JlZ0V4cENoYXIgPSBSZWdFeHAocmVSZWdFeHBDaGFyLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbiAgdmFyIHJlVHJpbSA9IC9eXFxzK3xcXHMrJC9nLFxuICAgICAgcmVUcmltU3RhcnQgPSAvXlxccysvLFxuICAgICAgcmVUcmltRW5kID0gL1xccyskLztcblxuICAvKiogVXNlZCB0byBtYXRjaCBiYWNrc2xhc2hlcyBpbiBwcm9wZXJ0eSBwYXRocy4gKi9cbiAgdmFyIHJlRXNjYXBlQ2hhciA9IC9cXFxcKFxcXFwpPy9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIFtFUyB0ZW1wbGF0ZSBkZWxpbWl0ZXJzXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy10ZW1wbGF0ZS1saXRlcmFsLWxleGljYWwtY29tcG9uZW50cykuICovXG4gIHZhciByZUVzVGVtcGxhdGUgPSAvXFwkXFx7KFteXFxcXH1dKig/OlxcXFwuW15cXFxcfV0qKSopXFx9L2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYFJlZ0V4cGAgZmxhZ3MgZnJvbSB0aGVpciBjb2VyY2VkIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUZsYWdzID0gL1xcdyokLztcblxuICAvKiogVXNlZCB0byBkZXRlY3QgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlSGFzSGV4UHJlZml4ID0gL14weC9pO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBiYWQgc2lnbmVkIGhleGFkZWNpbWFsIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGJpbmFyeSBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVJc0JpbmFyeSA9IC9eMGJbMDFdKyQvaTtcblxuICAvKiogVXNlZCB0byBkZXRlY3QgaG9zdCBjb25zdHJ1Y3RvcnMgKFNhZmFyaSA+IDUpLiAqL1xuICB2YXIgcmVJc0hvc3RDdG9yID0gL15cXFtvYmplY3QgLis/Q29uc3RydWN0b3JcXF0kLztcblxuICAvKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNPY3RhbCA9IC9eMG9bMC03XSskL2k7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IHVuc2lnbmVkIGludGVnZXIgdmFsdWVzLiAqL1xuICB2YXIgcmVJc1VpbnQgPSAvXig/OjB8WzEtOV1cXGQqKSQvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGxhdGluLTEgc3VwcGxlbWVudGFyeSBsZXR0ZXJzIChleGNsdWRpbmcgbWF0aGVtYXRpY2FsIG9wZXJhdG9ycykuICovXG4gIHZhciByZUxhdGluMSA9IC9bXFx4YzAtXFx4ZDZcXHhkOC1cXHhkZVxceGRmLVxceGY2XFx4ZjgtXFx4ZmZdL2c7XG5cbiAgLyoqIFVzZWQgdG8gZW5zdXJlIGNhcHR1cmluZyBvcmRlciBvZiB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLiAqL1xuICB2YXIgcmVOb01hdGNoID0gLygkXikvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIHVuZXNjYXBlZCBjaGFyYWN0ZXJzIGluIGNvbXBpbGVkIHN0cmluZyBsaXRlcmFscy4gKi9cbiAgdmFyIHJlVW5lc2NhcGVkU3RyaW5nID0gL1snXFxuXFxyXFx1MjAyOFxcdTIwMjlcXFxcXS9nO1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgdW5pY29kZSBjaGFyYWN0ZXIgY2xhc3Nlcy4gKi9cbiAgdmFyIHJzQXN0cmFsUmFuZ2UgPSAnXFxcXHVkODAwLVxcXFx1ZGZmZicsXG4gICAgICByc0NvbWJvTWFya3NSYW5nZSA9ICdcXFxcdTAzMDAtXFxcXHUwMzZmXFxcXHVmZTIwLVxcXFx1ZmUyMycsXG4gICAgICByc0NvbWJvU3ltYm9sc1JhbmdlID0gJ1xcXFx1MjBkMC1cXFxcdTIwZjAnLFxuICAgICAgcnNEaW5nYmF0UmFuZ2UgPSAnXFxcXHUyNzAwLVxcXFx1MjdiZicsXG4gICAgICByc0xvd2VyUmFuZ2UgPSAnYS16XFxcXHhkZi1cXFxceGY2XFxcXHhmOC1cXFxceGZmJyxcbiAgICAgIHJzTWF0aE9wUmFuZ2UgPSAnXFxcXHhhY1xcXFx4YjFcXFxceGQ3XFxcXHhmNycsXG4gICAgICByc05vbkNoYXJSYW5nZSA9ICdcXFxceDAwLVxcXFx4MmZcXFxceDNhLVxcXFx4NDBcXFxceDViLVxcXFx4NjBcXFxceDdiLVxcXFx4YmYnLFxuICAgICAgcnNRdW90ZVJhbmdlID0gJ1xcXFx1MjAxOFxcXFx1MjAxOVxcXFx1MjAxY1xcXFx1MjAxZCcsXG4gICAgICByc1NwYWNlUmFuZ2UgPSAnIFxcXFx0XFxcXHgwYlxcXFxmXFxcXHhhMFxcXFx1ZmVmZlxcXFxuXFxcXHJcXFxcdTIwMjhcXFxcdTIwMjlcXFxcdTE2ODBcXFxcdTE4MGVcXFxcdTIwMDBcXFxcdTIwMDFcXFxcdTIwMDJcXFxcdTIwMDNcXFxcdTIwMDRcXFxcdTIwMDVcXFxcdTIwMDZcXFxcdTIwMDdcXFxcdTIwMDhcXFxcdTIwMDlcXFxcdTIwMGFcXFxcdTIwMmZcXFxcdTIwNWZcXFxcdTMwMDAnLFxuICAgICAgcnNVcHBlclJhbmdlID0gJ0EtWlxcXFx4YzAtXFxcXHhkNlxcXFx4ZDgtXFxcXHhkZScsXG4gICAgICByc1ZhclJhbmdlID0gJ1xcXFx1ZmUwZVxcXFx1ZmUwZicsXG4gICAgICByc0JyZWFrUmFuZ2UgPSByc01hdGhPcFJhbmdlICsgcnNOb25DaGFyUmFuZ2UgKyByc1F1b3RlUmFuZ2UgKyByc1NwYWNlUmFuZ2U7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSB1bmljb2RlIGNhcHR1cmUgZ3JvdXBzLiAqL1xuICB2YXIgcnNBc3RyYWwgPSAnWycgKyByc0FzdHJhbFJhbmdlICsgJ10nLFxuICAgICAgcnNCcmVhayA9ICdbJyArIHJzQnJlYWtSYW5nZSArICddJyxcbiAgICAgIHJzQ29tYm8gPSAnWycgKyByc0NvbWJvTWFya3NSYW5nZSArIHJzQ29tYm9TeW1ib2xzUmFuZ2UgKyAnXScsXG4gICAgICByc0RpZ2l0cyA9ICdcXFxcZCsnLFxuICAgICAgcnNEaW5nYmF0ID0gJ1snICsgcnNEaW5nYmF0UmFuZ2UgKyAnXScsXG4gICAgICByc0xvd2VyID0gJ1snICsgcnNMb3dlclJhbmdlICsgJ10nLFxuICAgICAgcnNNaXNjID0gJ1teJyArIHJzQXN0cmFsUmFuZ2UgKyByc0JyZWFrUmFuZ2UgKyByc0RpZ2l0cyArIHJzRGluZ2JhdFJhbmdlICsgcnNMb3dlclJhbmdlICsgcnNVcHBlclJhbmdlICsgJ10nLFxuICAgICAgcnNGaXR6ID0gJ1xcXFx1ZDgzY1tcXFxcdWRmZmItXFxcXHVkZmZmXScsXG4gICAgICByc01vZGlmaWVyID0gJyg/OicgKyByc0NvbWJvICsgJ3wnICsgcnNGaXR6ICsgJyknLFxuICAgICAgcnNOb25Bc3RyYWwgPSAnW14nICsgcnNBc3RyYWxSYW5nZSArICddJyxcbiAgICAgIHJzUmVnaW9uYWwgPSAnKD86XFxcXHVkODNjW1xcXFx1ZGRlNi1cXFxcdWRkZmZdKXsyfScsXG4gICAgICByc1N1cnJQYWlyID0gJ1tcXFxcdWQ4MDAtXFxcXHVkYmZmXVtcXFxcdWRjMDAtXFxcXHVkZmZmXScsXG4gICAgICByc1VwcGVyID0gJ1snICsgcnNVcHBlclJhbmdlICsgJ10nLFxuICAgICAgcnNaV0ogPSAnXFxcXHUyMDBkJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIHVuaWNvZGUgcmVnZXhlcy4gKi9cbiAgdmFyIHJzTG93ZXJNaXNjID0gJyg/OicgKyByc0xvd2VyICsgJ3wnICsgcnNNaXNjICsgJyknLFxuICAgICAgcnNVcHBlck1pc2MgPSAnKD86JyArIHJzVXBwZXIgKyAnfCcgKyByc01pc2MgKyAnKScsXG4gICAgICByZU9wdE1vZCA9IHJzTW9kaWZpZXIgKyAnPycsXG4gICAgICByc09wdFZhciA9ICdbJyArIHJzVmFyUmFuZ2UgKyAnXT8nLFxuICAgICAgcnNPcHRKb2luID0gJyg/OicgKyByc1pXSiArICcoPzonICsgW3JzTm9uQXN0cmFsLCByc1JlZ2lvbmFsLCByc1N1cnJQYWlyXS5qb2luKCd8JykgKyAnKScgKyByc09wdFZhciArIHJlT3B0TW9kICsgJykqJyxcbiAgICAgIHJzU2VxID0gcnNPcHRWYXIgKyByZU9wdE1vZCArIHJzT3B0Sm9pbixcbiAgICAgIHJzRW1vamkgPSAnKD86JyArIFtyc0RpbmdiYXQsIHJzUmVnaW9uYWwsIHJzU3VyclBhaXJdLmpvaW4oJ3wnKSArICcpJyArIHJzU2VxLFxuICAgICAgcnNTeW1ib2wgPSAnKD86JyArIFtyc05vbkFzdHJhbCArIHJzQ29tYm8gKyAnPycsIHJzQ29tYm8sIHJzUmVnaW9uYWwsIHJzU3VyclBhaXIsIHJzQXN0cmFsXS5qb2luKCd8JykgKyAnKSc7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gbWF0Y2ggW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKSBhbmRcbiAgICogW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrcyBmb3Igc3ltYm9sc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzX2Zvcl9TeW1ib2xzKS5cbiAgICovXG4gIHZhciByZUNvbWJvTWFyayA9IFJlZ0V4cChyc0NvbWJvLCAnZycpO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIFtzdHJpbmcgc3ltYm9sc10oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtdW5pY29kZSkuICovXG4gIHZhciByZUNvbXBsZXhTeW1ib2wgPSBSZWdFeHAocnNGaXR6ICsgJyg/PScgKyByc0ZpdHogKyAnKXwnICsgcnNTeW1ib2wgKyByc1NlcSwgJ2cnKTtcblxuICAvKiogVXNlZCB0byBkZXRlY3Qgc3RyaW5ncyB3aXRoIFt6ZXJvLXdpZHRoIGpvaW5lcnMgb3IgY29kZSBwb2ludHMgZnJvbSB0aGUgYXN0cmFsIHBsYW5lc10oaHR0cDovL2Vldi5lZS9ibG9nLzIwMTUvMDkvMTIvZGFyay1jb3JuZXJzLW9mLXVuaWNvZGUvKS4gKi9cbiAgdmFyIHJlSGFzQ29tcGxleFN5bWJvbCA9IFJlZ0V4cCgnWycgKyByc1pXSiArIHJzQXN0cmFsUmFuZ2UgICsgcnNDb21ib01hcmtzUmFuZ2UgKyByc0NvbWJvU3ltYm9sc1JhbmdlICsgcnNWYXJSYW5nZSArICddJyk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggbm9uLWNvbXBvdW5kIHdvcmRzIGNvbXBvc2VkIG9mIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgcmVCYXNpY1dvcmQgPSAvW2EtekEtWjAtOV0rL2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggY29tcGxleCBvciBjb21wb3VuZCB3b3Jkcy4gKi9cbiAgdmFyIHJlQ29tcGxleFdvcmQgPSBSZWdFeHAoW1xuICAgIHJzVXBwZXIgKyAnPycgKyByc0xvd2VyICsgJysoPz0nICsgW3JzQnJlYWssIHJzVXBwZXIsICckJ10uam9pbignfCcpICsgJyknLFxuICAgIHJzVXBwZXJNaXNjICsgJysoPz0nICsgW3JzQnJlYWssIHJzVXBwZXIgKyByc0xvd2VyTWlzYywgJyQnXS5qb2luKCd8JykgKyAnKScsXG4gICAgcnNVcHBlciArICc/JyArIHJzTG93ZXJNaXNjICsgJysnLFxuICAgIHJzVXBwZXIgKyAnKycsXG4gICAgcnNEaWdpdHMsXG4gICAgcnNFbW9qaVxuICBdLmpvaW4oJ3wnKSwgJ2cnKTtcblxuICAvKiogVXNlZCB0byBkZXRlY3Qgc3RyaW5ncyB0aGF0IG5lZWQgYSBtb3JlIHJvYnVzdCByZWdleHAgdG8gbWF0Y2ggd29yZHMuICovXG4gIHZhciByZUhhc0NvbXBsZXhXb3JkID0gL1thLXpdW0EtWl18WzAtOV1bYS16QS1aXXxbYS16QS1aXVswLTldfFteYS16QS1aMC05IF0vO1xuXG4gIC8qKiBVc2VkIHRvIGFzc2lnbiBkZWZhdWx0IGBjb250ZXh0YCBvYmplY3QgcHJvcGVydGllcy4gKi9cbiAgdmFyIGNvbnRleHRQcm9wcyA9IFtcbiAgICAnQXJyYXknLCAnQnVmZmVyJywgJ0RhdGUnLCAnRXJyb3InLCAnRmxvYXQzMkFycmF5JywgJ0Zsb2F0NjRBcnJheScsXG4gICAgJ0Z1bmN0aW9uJywgJ0ludDhBcnJheScsICdJbnQxNkFycmF5JywgJ0ludDMyQXJyYXknLCAnTWFwJywgJ01hdGgnLCAnT2JqZWN0JyxcbiAgICAnUmVmbGVjdCcsICdSZWdFeHAnLCAnU2V0JywgJ1N0cmluZycsICdTeW1ib2wnLCAnVHlwZUVycm9yJywgJ1VpbnQ4QXJyYXknLFxuICAgICdVaW50OENsYW1wZWRBcnJheScsICdVaW50MTZBcnJheScsICdVaW50MzJBcnJheScsICdXZWFrTWFwJywgJ18nLFxuICAgICdjbGVhclRpbWVvdXQnLCAnaXNGaW5pdGUnLCAncGFyc2VJbnQnLCAnc2V0VGltZW91dCdcbiAgXTtcblxuICAvKiogVXNlZCB0byBtYWtlIHRlbXBsYXRlIHNvdXJjZVVSTHMgZWFzaWVyIHRvIGlkZW50aWZ5LiAqL1xuICB2YXIgdGVtcGxhdGVDb3VudGVyID0gLTE7XG5cbiAgLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgb2YgdHlwZWQgYXJyYXlzLiAqL1xuICB2YXIgdHlwZWRBcnJheVRhZ3MgPSB7fTtcbiAgdHlwZWRBcnJheVRhZ3NbZmxvYXQzMlRhZ10gPSB0eXBlZEFycmF5VGFnc1tmbG9hdDY0VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2ludDhUYWddID0gdHlwZWRBcnJheVRhZ3NbaW50MTZUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbaW50MzJUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDhUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbdWludDhDbGFtcGVkVGFnXSA9IHR5cGVkQXJyYXlUYWdzW3VpbnQxNlRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbiAgdHlwZWRBcnJheVRhZ3NbYXJnc1RhZ10gPSB0eXBlZEFycmF5VGFnc1thcnJheVRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1thcnJheUJ1ZmZlclRhZ10gPSB0eXBlZEFycmF5VGFnc1tib29sVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2RhdGVUYWddID0gdHlwZWRBcnJheVRhZ3NbZXJyb3JUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbZnVuY1RhZ10gPSB0eXBlZEFycmF5VGFnc1ttYXBUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbbnVtYmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW29iamVjdFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tyZWdleHBUYWddID0gdHlwZWRBcnJheVRhZ3Nbc2V0VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3N0cmluZ1RhZ10gPSB0eXBlZEFycmF5VGFnc1t3ZWFrTWFwVGFnXSA9IGZhbHNlO1xuXG4gIC8qKiBVc2VkIHRvIGlkZW50aWZ5IGB0b1N0cmluZ1RhZ2AgdmFsdWVzIHN1cHBvcnRlZCBieSBgXy5jbG9uZWAuICovXG4gIHZhciBjbG9uZWFibGVUYWdzID0ge307XG4gIGNsb25lYWJsZVRhZ3NbYXJnc1RhZ10gPSBjbG9uZWFibGVUYWdzW2FycmF5VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbYXJyYXlCdWZmZXJUYWddID0gY2xvbmVhYmxlVGFnc1tib29sVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbZGF0ZVRhZ10gPSBjbG9uZWFibGVUYWdzW2Zsb2F0MzJUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tmbG9hdDY0VGFnXSA9IGNsb25lYWJsZVRhZ3NbaW50OFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2ludDE2VGFnXSA9IGNsb25lYWJsZVRhZ3NbaW50MzJUYWddID1cbiAgY2xvbmVhYmxlVGFnc1ttYXBUYWddID0gY2xvbmVhYmxlVGFnc1tudW1iZXJUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tvYmplY3RUYWddID0gY2xvbmVhYmxlVGFnc1tyZWdleHBUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tzZXRUYWddID0gY2xvbmVhYmxlVGFnc1tzdHJpbmdUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tzeW1ib2xUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50OFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQxNlRhZ10gPVxuICBjbG9uZWFibGVUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuICBjbG9uZWFibGVUYWdzW2Vycm9yVGFnXSA9IGNsb25lYWJsZVRhZ3NbZnVuY1RhZ10gPVxuICBjbG9uZWFibGVUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbiAgLyoqIFVzZWQgdG8gbWFwIGxhdGluLTEgc3VwcGxlbWVudGFyeSBsZXR0ZXJzIHRvIGJhc2ljIGxhdGluIGxldHRlcnMuICovXG4gIHZhciBkZWJ1cnJlZExldHRlcnMgPSB7XG4gICAgJ1xceGMwJzogJ0EnLCAgJ1xceGMxJzogJ0EnLCAnXFx4YzInOiAnQScsICdcXHhjMyc6ICdBJywgJ1xceGM0JzogJ0EnLCAnXFx4YzUnOiAnQScsXG4gICAgJ1xceGUwJzogJ2EnLCAgJ1xceGUxJzogJ2EnLCAnXFx4ZTInOiAnYScsICdcXHhlMyc6ICdhJywgJ1xceGU0JzogJ2EnLCAnXFx4ZTUnOiAnYScsXG4gICAgJ1xceGM3JzogJ0MnLCAgJ1xceGU3JzogJ2MnLFxuICAgICdcXHhkMCc6ICdEJywgICdcXHhmMCc6ICdkJyxcbiAgICAnXFx4YzgnOiAnRScsICAnXFx4YzknOiAnRScsICdcXHhjYSc6ICdFJywgJ1xceGNiJzogJ0UnLFxuICAgICdcXHhlOCc6ICdlJywgICdcXHhlOSc6ICdlJywgJ1xceGVhJzogJ2UnLCAnXFx4ZWInOiAnZScsXG4gICAgJ1xceGNDJzogJ0knLCAgJ1xceGNkJzogJ0knLCAnXFx4Y2UnOiAnSScsICdcXHhjZic6ICdJJyxcbiAgICAnXFx4ZUMnOiAnaScsICAnXFx4ZWQnOiAnaScsICdcXHhlZSc6ICdpJywgJ1xceGVmJzogJ2knLFxuICAgICdcXHhkMSc6ICdOJywgICdcXHhmMSc6ICduJyxcbiAgICAnXFx4ZDInOiAnTycsICAnXFx4ZDMnOiAnTycsICdcXHhkNCc6ICdPJywgJ1xceGQ1JzogJ08nLCAnXFx4ZDYnOiAnTycsICdcXHhkOCc6ICdPJyxcbiAgICAnXFx4ZjInOiAnbycsICAnXFx4ZjMnOiAnbycsICdcXHhmNCc6ICdvJywgJ1xceGY1JzogJ28nLCAnXFx4ZjYnOiAnbycsICdcXHhmOCc6ICdvJyxcbiAgICAnXFx4ZDknOiAnVScsICAnXFx4ZGEnOiAnVScsICdcXHhkYic6ICdVJywgJ1xceGRjJzogJ1UnLFxuICAgICdcXHhmOSc6ICd1JywgICdcXHhmYSc6ICd1JywgJ1xceGZiJzogJ3UnLCAnXFx4ZmMnOiAndScsXG4gICAgJ1xceGRkJzogJ1knLCAgJ1xceGZkJzogJ3knLCAnXFx4ZmYnOiAneScsXG4gICAgJ1xceGM2JzogJ0FlJywgJ1xceGU2JzogJ2FlJyxcbiAgICAnXFx4ZGUnOiAnVGgnLCAnXFx4ZmUnOiAndGgnLFxuICAgICdcXHhkZic6ICdzcydcbiAgfTtcblxuICAvKiogVXNlZCB0byBtYXAgY2hhcmFjdGVycyB0byBIVE1MIGVudGl0aWVzLiAqL1xuICB2YXIgaHRtbEVzY2FwZXMgPSB7XG4gICAgJyYnOiAnJmFtcDsnLFxuICAgICc8JzogJyZsdDsnLFxuICAgICc+JzogJyZndDsnLFxuICAgICdcIic6ICcmcXVvdDsnLFxuICAgIFwiJ1wiOiAnJiMzOTsnLFxuICAgICdgJzogJyYjOTY7J1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBIVE1MIGVudGl0aWVzIHRvIGNoYXJhY3RlcnMuICovXG4gIHZhciBodG1sVW5lc2NhcGVzID0ge1xuICAgICcmYW1wOyc6ICcmJyxcbiAgICAnJmx0Oyc6ICc8JyxcbiAgICAnJmd0Oyc6ICc+JyxcbiAgICAnJnF1b3Q7JzogJ1wiJyxcbiAgICAnJiMzOTsnOiBcIidcIixcbiAgICAnJiM5NjsnOiAnYCdcbiAgfTtcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyBmb3IgaW5jbHVzaW9uIGluIGNvbXBpbGVkIHN0cmluZyBsaXRlcmFscy4gKi9cbiAgdmFyIHN0cmluZ0VzY2FwZXMgPSB7XG4gICAgJ1xcXFwnOiAnXFxcXCcsXG4gICAgXCInXCI6IFwiJ1wiLFxuICAgICdcXG4nOiAnbicsXG4gICAgJ1xccic6ICdyJyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbiAgdmFyIGZyZWVQYXJzZUZsb2F0ID0gcGFyc2VGbG9hdCxcbiAgICAgIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IChvYmplY3RUeXBlc1t0eXBlb2YgZXhwb3J0c10gJiYgZXhwb3J0cyAmJiAhZXhwb3J0cy5ub2RlVHlwZSlcbiAgICA/IGV4cG9ydHNcbiAgICA6IHVuZGVmaW5lZDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG4gIHZhciBmcmVlTW9kdWxlID0gKG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlKVxuICAgID8gbW9kdWxlXG4gICAgOiB1bmRlZmluZWQ7XG5cbiAgLyoqIERldGVjdCB0aGUgcG9wdWxhciBDb21tb25KUyBleHRlbnNpb24gYG1vZHVsZS5leHBvcnRzYC4gKi9cbiAgdmFyIG1vZHVsZUV4cG9ydHMgPSAoZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLmV4cG9ydHMgPT09IGZyZWVFeHBvcnRzKVxuICAgID8gZnJlZUV4cG9ydHNcbiAgICA6IHVuZGVmaW5lZDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGNoZWNrR2xvYmFsKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwpO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgc2VsZmAuICovXG4gIHZhciBmcmVlU2VsZiA9IGNoZWNrR2xvYmFsKG9iamVjdFR5cGVzW3R5cGVvZiBzZWxmXSAmJiBzZWxmKTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHdpbmRvd2AuICovXG4gIHZhciBmcmVlV2luZG93ID0gY2hlY2tHbG9iYWwob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KTtcblxuICAvKiogRGV0ZWN0IGB0aGlzYCBhcyB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNHbG9iYWwgPSBjaGVja0dsb2JhbChvYmplY3RUeXBlc1t0eXBlb2YgdGhpc10gJiYgdGhpcyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAqXG4gICAqIFRoZSBgdGhpc2AgdmFsdWUgaXMgdXNlZCBpZiBpdCdzIHRoZSBnbG9iYWwgb2JqZWN0IHRvIGF2b2lkIEdyZWFzZW1vbmtleSdzXG4gICAqIHJlc3RyaWN0ZWQgYHdpbmRvd2Agb2JqZWN0LCBvdGhlcndpc2UgdGhlIGB3aW5kb3dgIG9iamVjdCBpcyB1c2VkLlxuICAgKi9cbiAgdmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8XG4gICAgKChmcmVlV2luZG93ICE9PSAodGhpc0dsb2JhbCAmJiB0aGlzR2xvYmFsLndpbmRvdykpICYmIGZyZWVXaW5kb3cpIHx8XG4gICAgICBmcmVlU2VsZiB8fCB0aGlzR2xvYmFsIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIEFkZHMgdGhlIGtleS12YWx1ZSBgcGFpcmAgdG8gYG1hcGAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBtYXAgVGhlIG1hcCB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHBhaXIgVGhlIGtleS12YWx1ZSBwYWlyIHRvIGFkZC5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgbWFwYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFkZE1hcEVudHJ5KG1hcCwgcGFpcikge1xuICAgIG1hcC5zZXQocGFpclswXSwgcGFpclsxXSk7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGB2YWx1ZWAgdG8gYHNldGAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFkZC5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgc2V0YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFkZFNldEVudHJ5KHNldCwgdmFsdWUpIHtcbiAgICBzZXQuYWRkKHZhbHVlKTtcbiAgICByZXR1cm4gc2V0O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgZmFzdGVyIGFsdGVybmF0aXZlIHRvIGBGdW5jdGlvbiNhcHBseWAsIHRoaXMgZnVuY3Rpb24gaW52b2tlcyBgZnVuY2BcbiAgICogd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgYHRoaXNBcmdgIGFuZCB0aGUgYXJndW1lbnRzIG9mIGBhcmdzYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaW52b2tlLlxuICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICogQHBhcmFtIHsuLi4qfSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGBmdW5jYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFwcGx5KGZ1bmMsIHRoaXNBcmcsIGFyZ3MpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJncy5sZW5ndGg7XG4gICAgc3dpdGNoIChsZW5ndGgpIHtcbiAgICAgIGNhc2UgMDogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnKTtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdKTtcbiAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlQWdncmVnYXRvcmAgZm9yIGFycmF5cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGFnZ3JlZ2F0ZWQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5QWdncmVnYXRvcihhcnJheSwgc2V0dGVyLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgIHNldHRlcihhY2N1bXVsYXRvciwgdmFsdWUsIGl0ZXJhdGVlKHZhbHVlKSwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBhcnJheSBjb25jYXRlbmF0aW5nIGBhcnJheWAgd2l0aCBgb3RoZXJgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgZmlyc3QgYXJyYXkgdG8gY29uY2F0ZW5hdGUuXG4gICAqIEBwYXJhbSB7QXJyYXl9IG90aGVyIFRoZSBzZWNvbmQgYXJyYXkgdG8gY29uY2F0ZW5hdGUuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGNvbmNhdGVuYXRlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5Q29uY2F0KGFycmF5LCBvdGhlcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIG90aEluZGV4ID0gLTEsXG4gICAgICAgIG90aExlbmd0aCA9IG90aGVyLmxlbmd0aCxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoICsgb3RoTGVuZ3RoKTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gYXJyYXlbaW5kZXhdO1xuICAgIH1cbiAgICB3aGlsZSAoKytvdGhJbmRleCA8IG90aExlbmd0aCkge1xuICAgICAgcmVzdWx0W2luZGV4KytdID0gb3RoZXJbb3RoSW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5mb3JFYWNoYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUVhY2goYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpID09PSBmYWxzZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5mb3JFYWNoUmlnaHRgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RWFjaFJpZ2h0KGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVtsZW5ndGhdLCBsZW5ndGgsIGFycmF5KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZXZlcnlgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFsbCBlbGVtZW50cyBwYXNzIHRoZSBwcmVkaWNhdGUgY2hlY2ssIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RXZlcnkoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKCFwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZpbHRlcmAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RmlsdGVyKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXNJbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgIHJlc3VsdFsrK3Jlc0luZGV4XSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5pbmNsdWRlc2AgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIHNwZWNpZnlpbmcgYW4gaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gICAqIEBwYXJhbSB7Kn0gdGFyZ2V0IFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHRhcmdldGAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5SW5jbHVkZXMoYXJyYXksIHZhbHVlKSB7XG4gICAgcmV0dXJuICEhYXJyYXkubGVuZ3RoICYmIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgMCkgPiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uaW5jbHVkZXNXaXRoYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogc3BlY2lmeWluZyBhbiBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmF0b3IgVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB0YXJnZXRgIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUluY2x1ZGVzV2l0aChhcnJheSwgdmFsdWUsIGNvbXBhcmF0b3IpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChjb21wYXJhdG9yKHZhbHVlLCBhcnJheVtpbmRleF0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLm1hcGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAqIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5TWFwKGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgcmVzdWx0W2luZGV4XSA9IGl0ZXJhdGVlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIHRoZSBlbGVtZW50cyBvZiBgdmFsdWVzYCB0byBgYXJyYXlgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBhcHBlbmQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlQdXNoKGFycmF5LCB2YWx1ZXMpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgICAgb2Zmc2V0ID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGFycmF5W29mZnNldCArIGluZGV4XSA9IHZhbHVlc1tpbmRleF07XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8ucmVkdWNlYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpbml0QWNjdW1dIFNwZWNpZnkgdXNpbmcgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YCBhcyB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlSZWR1Y2UoYXJyYXksIGl0ZXJhdGVlLCBhY2N1bXVsYXRvciwgaW5pdEFjY3VtKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIGlmIChpbml0QWNjdW0gJiYgbGVuZ3RoKSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGFycmF5WysraW5kZXhdO1xuICAgIH1cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBpdGVyYXRlZShhY2N1bXVsYXRvciwgYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnJlZHVjZVJpZ2h0YCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpbml0QWNjdW1dIFNwZWNpZnkgdXNpbmcgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVJlZHVjZVJpZ2h0KGFycmF5LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgaWYgKGluaXRBY2N1bSAmJiBsZW5ndGgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gYXJyYXlbLS1sZW5ndGhdO1xuICAgIH1cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2xlbmd0aF0sIGxlbmd0aCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNvbWVgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgKiBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVNvbWUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgaWYgKHByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8ubWF4YCBhbmQgYF8ubWluYCB3aGljaCBhY2NlcHRzIGFcbiAgICogYGNvbXBhcmF0b3JgIHRvIGRldGVybWluZSB0aGUgZXh0cmVtdW0gdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmF0b3IgVGhlIGNvbXBhcmF0b3IgdXNlZCB0byBjb21wYXJlIHZhbHVlcy5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGV4dHJlbXVtIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUV4dHJlbXVtKGFycmF5LCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgIGN1cnJlbnQgPSBpdGVyYXRlZSh2YWx1ZSk7XG5cbiAgICAgIGlmIChjdXJyZW50ICE9IG51bGwgJiYgKGNvbXB1dGVkID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gY3VycmVudCA9PT0gY3VycmVudFxuICAgICAgICAgICAgOiBjb21wYXJhdG9yKGN1cnJlbnQsIGNvbXB1dGVkKVxuICAgICAgICAgICkpIHtcbiAgICAgICAgdmFyIGNvbXB1dGVkID0gY3VycmVudCxcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIG1ldGhvZHMgbGlrZSBgXy5maW5kYCBhbmQgYF8uZmluZEtleWAsIHdpdGhvdXRcbiAgICogc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcywgd2hpY2ggaXRlcmF0ZXMgb3ZlciBgY29sbGVjdGlvbmAgdXNpbmdcbiAgICogYGVhY2hGdW5jYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBgY29sbGVjdGlvbmAuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JldEtleV0gU3BlY2lmeSByZXR1cm5pbmcgdGhlIGtleSBvZiB0aGUgZm91bmQgZWxlbWVudCBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZvdW5kIGVsZW1lbnQgb3IgaXRzIGtleSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VGaW5kKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZWFjaEZ1bmMsIHJldEtleSkge1xuICAgIHZhciByZXN1bHQ7XG4gICAgZWFjaEZ1bmMoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICByZXN1bHQgPSByZXRLZXkgPyBrZXkgOiB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmluZEluZGV4YCBhbmQgYF8uZmluZExhc3RJbmRleGAgd2l0aG91dFxuICAgKiBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlRmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIGZyb21SaWdodCkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTE7XG5cbiAgICB3aGlsZSAoKGZyb21SaWdodCA/IGluZGV4LS0gOiArK2luZGV4IDwgbGVuZ3RoKSkge1xuICAgICAgaWYgKHByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW5kZXhPZmAgd2l0aG91dCBgZnJvbUluZGV4YCBib3VuZHMgY2hlY2tzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgaWYgKHZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGluZGV4T2ZOYU4oYXJyYXksIGZyb21JbmRleCk7XG4gICAgfVxuICAgIHZhciBpbmRleCA9IGZyb21JbmRleCAtIDEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yZWR1Y2VgIGFuZCBgXy5yZWR1Y2VSaWdodGAsIHdpdGhvdXQgc3VwcG9ydFxuICAgKiBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcywgd2hpY2ggaXRlcmF0ZXMgb3ZlciBgY29sbGVjdGlvbmAgdXNpbmcgYGVhY2hGdW5jYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcGFyYW0geyp9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluaXRBY2N1bSBTcGVjaWZ5IHVzaW5nIHRoZSBmaXJzdCBvciBsYXN0IGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGBjb2xsZWN0aW9uYC5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVJlZHVjZShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSwgZWFjaEZ1bmMpIHtcbiAgICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaW5pdEFjY3VtXG4gICAgICAgID8gKGluaXRBY2N1bSA9IGZhbHNlLCB2YWx1ZSlcbiAgICAgICAgOiBpdGVyYXRlZShhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydEJ5YCB3aGljaCB1c2VzIGBjb21wYXJlcmAgdG8gZGVmaW5lXG4gICAqIHRoZSBzb3J0IG9yZGVyIG9mIGBhcnJheWAgYW5kIHJlcGxhY2VzIGNyaXRlcmlhIG9iamVjdHMgd2l0aCB0aGVpclxuICAgKiBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNvcnQuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmVyIFRoZSBmdW5jdGlvbiB0byBkZWZpbmUgc29ydCBvcmRlci5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlU29ydEJ5KGFycmF5LCBjb21wYXJlcikge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICBhcnJheS5zb3J0KGNvbXBhcmVyKTtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFycmF5W2xlbmd0aF0gPSBhcnJheVtsZW5ndGhdLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc3VtYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VTdW0oYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIHJlc3VsdCxcbiAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHZhciBjdXJyZW50ID0gaXRlcmF0ZWUoYXJyYXlbaW5kZXhdKTtcbiAgICAgIGlmIChjdXJyZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSB1bmRlZmluZWQgPyBjdXJyZW50IDogKHJlc3VsdCArIGN1cnJlbnQpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnRpbWVzYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHNcbiAgICogb3IgbWF4IGFycmF5IGxlbmd0aCBjaGVja3MuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gaW52b2tlIGBpdGVyYXRlZWAuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcmVzdWx0cy5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VUaW1lcyhuLCBpdGVyYXRlZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShuKTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbikge1xuICAgICAgcmVzdWx0W2luZGV4XSA9IGl0ZXJhdGVlKGluZGV4KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50b1BhaXJzYCBhbmQgYF8udG9QYWlyc0luYCB3aGljaCBjcmVhdGVzIGFuIGFycmF5XG4gICAqIG9mIGtleS12YWx1ZSBwYWlycyBmb3IgYG9iamVjdGAgY29ycmVzcG9uZGluZyB0byB0aGUgcHJvcGVydHkgbmFtZXMgb2YgYHByb3BzYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gZ2V0IHZhbHVlcyBmb3IuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBrZXktdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVG9QYWlycyhvYmplY3QsIHByb3BzKSB7XG4gICAgcmV0dXJuIGFycmF5TWFwKHByb3BzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBba2V5LCBvYmplY3Rba2V5XV07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udW5hcnlgIHdpdGhvdXQgc3VwcG9ydCBmb3Igc3RvcmluZyB3cmFwcGVyIG1ldGFkYXRhLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVW5hcnkoZnVuYykge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmModmFsdWUpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udmFsdWVzYCBhbmQgYF8udmFsdWVzSW5gIHdoaWNoIGNyZWF0ZXMgYW5cbiAgICogYXJyYXkgb2YgYG9iamVjdGAgcHJvcGVydHkgdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3BlcnR5IG5hbWVzXG4gICAqIG9mIGBwcm9wc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGdldCB2YWx1ZXMgZm9yLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVmFsdWVzKG9iamVjdCwgcHJvcHMpIHtcbiAgICByZXR1cm4gYXJyYXlNYXAocHJvcHMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIG9iamVjdFtrZXldO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udHJpbWAgYW5kIGBfLnRyaW1TdGFydGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgc3RyaW5nIHN5bWJvbFxuICAgKiB0aGF0IGlzIG5vdCBmb3VuZCBpbiB0aGUgY2hhcmFjdGVyIHN5bWJvbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN0clN5bWJvbHMgVGhlIHN0cmluZyBzeW1ib2xzIHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7QXJyYXl9IGNoclN5bWJvbHMgVGhlIGNoYXJhY3RlciBzeW1ib2xzIHRvIGZpbmQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCB1bm1hdGNoZWQgc3RyaW5nIHN5bWJvbC5cbiAgICovXG4gIGZ1bmN0aW9uIGNoYXJzU3RhcnRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IHN0clN5bWJvbHMubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGggJiYgYmFzZUluZGV4T2YoY2hyU3ltYm9scywgc3RyU3ltYm9sc1tpbmRleF0sIDApID4gLTEpIHt9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udHJpbWAgYW5kIGBfLnRyaW1FbmRgIHRvIGdldCB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgc3RyaW5nIHN5bWJvbFxuICAgKiB0aGF0IGlzIG5vdCBmb3VuZCBpbiB0aGUgY2hhcmFjdGVyIHN5bWJvbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN0clN5bWJvbHMgVGhlIHN0cmluZyBzeW1ib2xzIHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7QXJyYXl9IGNoclN5bWJvbHMgVGhlIGNoYXJhY3RlciBzeW1ib2xzIHRvIGZpbmQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBsYXN0IHVubWF0Y2hlZCBzdHJpbmcgc3ltYm9sLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSB7XG4gICAgdmFyIGluZGV4ID0gc3RyU3ltYm9scy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoaW5kZXgtLSAmJiBiYXNlSW5kZXhPZihjaHJTeW1ib2xzLCBzdHJTeW1ib2xzW2luZGV4XSwgMCkgPiAtMSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBnbG9iYWwgb2JqZWN0LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge251bGx8T2JqZWN0fSBSZXR1cm5zIGB2YWx1ZWAgaWYgaXQncyBhIGdsb2JhbCBvYmplY3QsIGVsc2UgYG51bGxgLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hlY2tHbG9iYWwodmFsdWUpIHtcbiAgICByZXR1cm4gKHZhbHVlICYmIHZhbHVlLk9iamVjdCA9PT0gT2JqZWN0KSA/IHZhbHVlIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wYXJlcyB2YWx1ZXMgdG8gc29ydCB0aGVtIGluIGFzY2VuZGluZyBvcmRlci5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3IgZm9yIGB2YWx1ZWAuXG4gICAqL1xuICBmdW5jdGlvbiBjb21wYXJlQXNjZW5kaW5nKHZhbHVlLCBvdGhlcikge1xuICAgIGlmICh2YWx1ZSAhPT0gb3RoZXIpIHtcbiAgICAgIHZhciB2YWxJc051bGwgPSB2YWx1ZSA9PT0gbnVsbCxcbiAgICAgICAgICB2YWxJc1VuZGVmID0gdmFsdWUgPT09IHVuZGVmaW5lZCxcbiAgICAgICAgICB2YWxJc1JlZmxleGl2ZSA9IHZhbHVlID09PSB2YWx1ZTtcblxuICAgICAgdmFyIG90aElzTnVsbCA9IG90aGVyID09PSBudWxsLFxuICAgICAgICAgIG90aElzVW5kZWYgPSBvdGhlciA9PT0gdW5kZWZpbmVkLFxuICAgICAgICAgIG90aElzUmVmbGV4aXZlID0gb3RoZXIgPT09IG90aGVyO1xuXG4gICAgICBpZiAoKHZhbHVlID4gb3RoZXIgJiYgIW90aElzTnVsbCkgfHwgIXZhbElzUmVmbGV4aXZlIHx8XG4gICAgICAgICAgKHZhbElzTnVsbCAmJiAhb3RoSXNVbmRlZiAmJiBvdGhJc1JlZmxleGl2ZSkgfHxcbiAgICAgICAgICAodmFsSXNVbmRlZiAmJiBvdGhJc1JlZmxleGl2ZSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG4gICAgICBpZiAoKHZhbHVlIDwgb3RoZXIgJiYgIXZhbElzTnVsbCkgfHwgIW90aElzUmVmbGV4aXZlIHx8XG4gICAgICAgICAgKG90aElzTnVsbCAmJiAhdmFsSXNVbmRlZiAmJiB2YWxJc1JlZmxleGl2ZSkgfHxcbiAgICAgICAgICAob3RoSXNVbmRlZiAmJiB2YWxJc1JlZmxleGl2ZSkpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLm9yZGVyQnlgIHRvIGNvbXBhcmUgbXVsdGlwbGUgcHJvcGVydGllcyBvZiBhIHZhbHVlIHRvIGFub3RoZXJcbiAgICogYW5kIHN0YWJsZSBzb3J0IHRoZW0uXG4gICAqXG4gICAqIElmIGBvcmRlcnNgIGlzIHVuc3BlY2lmaWVkLCBhbGwgdmFsdWVzIGFyZSBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyLiBPdGhlcndpc2UsXG4gICAqIHNwZWNpZnkgYW4gb3JkZXIgb2YgXCJkZXNjXCIgZm9yIGRlc2NlbmRpbmcgb3IgXCJhc2NcIiBmb3IgYXNjZW5kaW5nIHNvcnQgb3JkZXJcbiAgICogb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW5bXXxzdHJpbmdbXX0gb3JkZXJzIFRoZSBvcmRlciB0byBzb3J0IGJ5IGZvciBlYWNoIHByb3BlcnR5LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzb3J0IG9yZGVyIGluZGljYXRvciBmb3IgYG9iamVjdGAuXG4gICAqL1xuICBmdW5jdGlvbiBjb21wYXJlTXVsdGlwbGUob2JqZWN0LCBvdGhlciwgb3JkZXJzKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIG9iakNyaXRlcmlhID0gb2JqZWN0LmNyaXRlcmlhLFxuICAgICAgICBvdGhDcml0ZXJpYSA9IG90aGVyLmNyaXRlcmlhLFxuICAgICAgICBsZW5ndGggPSBvYmpDcml0ZXJpYS5sZW5ndGgsXG4gICAgICAgIG9yZGVyc0xlbmd0aCA9IG9yZGVycy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHJlc3VsdCA9IGNvbXBhcmVBc2NlbmRpbmcob2JqQ3JpdGVyaWFbaW5kZXhdLCBvdGhDcml0ZXJpYVtpbmRleF0pO1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICBpZiAoaW5kZXggPj0gb3JkZXJzTGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3JkZXIgPSBvcmRlcnNbaW5kZXhdO1xuICAgICAgICByZXR1cm4gcmVzdWx0ICogKG9yZGVyID09ICdkZXNjJyA/IC0xIDogMSk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEZpeGVzIGFuIGBBcnJheSNzb3J0YCBidWcgaW4gdGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBhcHBsaWNhdGlvbnNcbiAgICAvLyB0aGF0IGNhdXNlcyBpdCwgdW5kZXIgY2VydGFpbiBjaXJjdW1zdGFuY2VzLCB0byBwcm92aWRlIHRoZSBzYW1lIHZhbHVlIGZvclxuICAgIC8vIGBvYmplY3RgIGFuZCBgb3RoZXJgLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2phc2hrZW5hcy91bmRlcnNjb3JlL3B1bGwvMTI0N1xuICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgLy9cbiAgICAvLyBUaGlzIGFsc28gZW5zdXJlcyBhIHN0YWJsZSBzb3J0IGluIFY4IGFuZCBvdGhlciBlbmdpbmVzLlxuICAgIC8vIFNlZSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9OTAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICByZXR1cm4gb2JqZWN0LmluZGV4IC0gb3RoZXIuaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGBwbGFjZWhvbGRlcmAgb2NjdXJyZW5jZXMgaW4gYGFycmF5YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHRvIHNlYXJjaCBmb3IuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHBsYWNlaG9sZGVyIGNvdW50LlxuICAgKi9cbiAgZnVuY3Rpb24gY291bnRIb2xkZXJzKGFycmF5LCBwbGFjZWhvbGRlcikge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdCA9IDA7XG5cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGlmIChhcnJheVtsZW5ndGhdID09PSBwbGFjZWhvbGRlcikge1xuICAgICAgICByZXN1bHQrKztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLmRlYnVycmAgdG8gY29udmVydCBsYXRpbi0xIHN1cHBsZW1lbnRhcnkgbGV0dGVycyB0byBiYXNpYyBsYXRpbiBsZXR0ZXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGV0dGVyIFRoZSBtYXRjaGVkIGxldHRlciB0byBkZWJ1cnIuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGRlYnVycmVkIGxldHRlci5cbiAgICovXG4gIGZ1bmN0aW9uIGRlYnVyckxldHRlcihsZXR0ZXIpIHtcbiAgICByZXR1cm4gZGVidXJyZWRMZXR0ZXJzW2xldHRlcl07XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy5lc2NhcGVgIHRvIGNvbnZlcnQgY2hhcmFjdGVycyB0byBIVE1MIGVudGl0aWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hyIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlSHRtbENoYXIoY2hyKSB7XG4gICAgcmV0dXJuIGh0bWxFc2NhcGVzW2Nocl07XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50ZW1wbGF0ZWAgdG8gZXNjYXBlIGNoYXJhY3RlcnMgZm9yIGluY2x1c2lvbiBpbiBjb21waWxlZCBzdHJpbmcgbGl0ZXJhbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIGVzY2FwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiBlc2NhcGVTdHJpbmdDaGFyKGNocikge1xuICAgIHJldHVybiAnXFxcXCcgKyBzdHJpbmdFc2NhcGVzW2Nocl07XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYE5hTmAgaXMgZm91bmQgaW4gYGFycmF5YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGZyb21JbmRleCBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCBgTmFOYCwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gaW5kZXhPZk5hTihhcnJheSwgZnJvbUluZGV4LCBmcm9tUmlnaHQpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICBpbmRleCA9IGZyb21JbmRleCArIChmcm9tUmlnaHQgPyAwIDogLTEpO1xuXG4gICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgIHZhciBvdGhlciA9IGFycmF5W2luZGV4XTtcbiAgICAgIGlmIChvdGhlciAhPT0gb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBob3N0IG9iamVjdCBpbiBJRSA8IDkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGhvc3Qgb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RPYmplY3QodmFsdWUpIHtcbiAgICAvLyBNYW55IGhvc3Qgb2JqZWN0cyBhcmUgYE9iamVjdGAgb2JqZWN0cyB0aGF0IGNhbiBjb2VyY2UgdG8gc3RyaW5nc1xuICAgIC8vIGRlc3BpdGUgaGF2aW5nIGltcHJvcGVybHkgZGVmaW5lZCBgdG9TdHJpbmdgIG1ldGhvZHMuXG4gICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgIGlmICh2YWx1ZSAhPSBudWxsICYmIHR5cGVvZiB2YWx1ZS50b1N0cmluZyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXN1bHQgPSAhISh2YWx1ZSArICcnKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGluZGV4LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9TUFYX1NBRkVfSU5URUdFUl0gVGhlIHVwcGVyIGJvdW5kcyBvZiBhIHZhbGlkIGluZGV4LlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGluZGV4LCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0luZGV4KHZhbHVlLCBsZW5ndGgpIHtcbiAgICB2YWx1ZSA9ICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgfHwgcmVJc1VpbnQudGVzdCh2YWx1ZSkpID8gK3ZhbHVlIDogLTE7XG4gICAgbGVuZ3RoID0gbGVuZ3RoID09IG51bGwgPyBNQVhfU0FGRV9JTlRFR0VSIDogbGVuZ3RoO1xuICAgIHJldHVybiB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDwgbGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBpdGVyYXRvcmAgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVyYXRvciBUaGUgaXRlcmF0b3IgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBpdGVyYXRvclRvQXJyYXkoaXRlcmF0b3IpIHtcbiAgICB2YXIgZGF0YSxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoIShkYXRhID0gaXRlcmF0b3IubmV4dCgpKS5kb25lKSB7XG4gICAgICByZXN1bHQucHVzaChkYXRhLnZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgbWFwYCB0byBhbiBhcnJheS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gbWFwVG9BcnJheShtYXApIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobWFwLnNpemUpO1xuXG4gICAgbWFwLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0WysraW5kZXhdID0gW2tleSwgdmFsdWVdO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgYWxsIGBwbGFjZWhvbGRlcmAgZWxlbWVudHMgaW4gYGFycmF5YCB3aXRoIGFuIGludGVybmFsIHBsYWNlaG9sZGVyXG4gICAqIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZWlyIGluZGV4ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHRvIHJlcGxhY2UuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAqL1xuICBmdW5jdGlvbiByZXBsYWNlSG9sZGVycyhhcnJheSwgcGxhY2Vob2xkZXIpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXNJbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICBpZiAodmFsdWUgPT09IHBsYWNlaG9sZGVyIHx8IHZhbHVlID09PSBQTEFDRUhPTERFUikge1xuICAgICAgICBhcnJheVtpbmRleF0gPSBQTEFDRUhPTERFUjtcbiAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYHNldGAgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHNldFRvQXJyYXkoc2V0KSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KHNldC5zaXplKTtcblxuICAgIHNldC5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXN1bHRbKytpbmRleF0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIG51bWJlciBvZiBzeW1ib2xzIGluIGBzdHJpbmdgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3RyaW5nIHNpemUuXG4gICAqL1xuICBmdW5jdGlvbiBzdHJpbmdTaXplKHN0cmluZykge1xuICAgIGlmICghKHN0cmluZyAmJiByZUhhc0NvbXBsZXhTeW1ib2wudGVzdChzdHJpbmcpKSkge1xuICAgICAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSByZUNvbXBsZXhTeW1ib2wubGFzdEluZGV4ID0gMDtcbiAgICB3aGlsZSAocmVDb21wbGV4U3ltYm9sLnRlc3Qoc3RyaW5nKSkge1xuICAgICAgcmVzdWx0Kys7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYHN0cmluZ2AgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmluZ1RvQXJyYXkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHN0cmluZy5tYXRjaChyZUNvbXBsZXhTeW1ib2wpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8udW5lc2NhcGVgIHRvIGNvbnZlcnQgSFRNTCBlbnRpdGllcyB0byBjaGFyYWN0ZXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hyIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byB1bmVzY2FwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdW5lc2NhcGVkIGNoYXJhY3Rlci5cbiAgICovXG4gIGZ1bmN0aW9uIHVuZXNjYXBlSHRtbENoYXIoY2hyKSB7XG4gICAgcmV0dXJuIGh0bWxVbmVzY2FwZXNbY2hyXTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgcHJpc3RpbmUgYGxvZGFzaGAgZnVuY3Rpb24gdXNpbmcgdGhlIGBjb250ZXh0YCBvYmplY3QuXG4gICAqXG4gICAqIEBzdGF0aWNcbiAgICogQG1lbWJlck9mIF9cbiAgICogQGNhdGVnb3J5IFV0aWxcbiAgICogQHBhcmFtIHtPYmplY3R9IFtjb250ZXh0PXJvb3RdIFRoZSBjb250ZXh0IG9iamVjdC5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGEgbmV3IGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiBfLm1peGluKHsgJ2Zvbyc6IF8uY29uc3RhbnQoJ2ZvbycpIH0pO1xuICAgKlxuICAgKiB2YXIgbG9kYXNoID0gXy5ydW5JbkNvbnRleHQoKTtcbiAgICogbG9kYXNoLm1peGluKHsgJ2Jhcic6IGxvZGFzaC5jb25zdGFudCgnYmFyJykgfSk7XG4gICAqXG4gICAqIF8uaXNGdW5jdGlvbihfLmZvbyk7XG4gICAqIC8vID0+IHRydWVcbiAgICogXy5pc0Z1bmN0aW9uKF8uYmFyKTtcbiAgICogLy8gPT4gZmFsc2VcbiAgICpcbiAgICogbG9kYXNoLmlzRnVuY3Rpb24obG9kYXNoLmZvbyk7XG4gICAqIC8vID0+IGZhbHNlXG4gICAqIGxvZGFzaC5pc0Z1bmN0aW9uKGxvZGFzaC5iYXIpO1xuICAgKiAvLyA9PiB0cnVlXG4gICAqXG4gICAqIC8vIFVzZSBgY29udGV4dGAgdG8gbW9jayBgRGF0ZSNnZXRUaW1lYCB1c2UgaW4gYF8ubm93YC5cbiAgICogdmFyIG1vY2sgPSBfLnJ1bkluQ29udGV4dCh7XG4gICAqICAgJ0RhdGUnOiBmdW5jdGlvbigpIHtcbiAgICogICAgIHJldHVybiB7ICdnZXRUaW1lJzogZ2V0VGltZU1vY2sgfTtcbiAgICogICB9XG4gICAqIH0pO1xuICAgKlxuICAgKiAvLyBDcmVhdGUgYSBzdXBlZC11cCBgZGVmZXJgIGluIE5vZGUuanMuXG4gICAqIHZhciBkZWZlciA9IF8ucnVuSW5Db250ZXh0KHsgJ3NldFRpbWVvdXQnOiBzZXRJbW1lZGlhdGUgfSkuZGVmZXI7XG4gICAqL1xuICBmdW5jdGlvbiBydW5JbkNvbnRleHQoY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBjb250ZXh0ID8gXy5kZWZhdWx0cyh7fSwgY29udGV4dCwgXy5waWNrKHJvb3QsIGNvbnRleHRQcm9wcykpIDogcm9vdDtcblxuICAgIC8qKiBCdWlsdC1pbiBjb25zdHJ1Y3RvciByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBEYXRlID0gY29udGV4dC5EYXRlLFxuICAgICAgICBFcnJvciA9IGNvbnRleHQuRXJyb3IsXG4gICAgICAgIE1hdGggPSBjb250ZXh0Lk1hdGgsXG4gICAgICAgIFJlZ0V4cCA9IGNvbnRleHQuUmVnRXhwLFxuICAgICAgICBUeXBlRXJyb3IgPSBjb250ZXh0LlR5cGVFcnJvcjtcblxuICAgIC8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgICB2YXIgYXJyYXlQcm90byA9IGNvbnRleHQuQXJyYXkucHJvdG90eXBlLFxuICAgICAgICBvYmplY3RQcm90byA9IGNvbnRleHQuT2JqZWN0LnByb3RvdHlwZTtcblxuICAgIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGRlY29tcGlsZWQgc291cmNlIG9mIGZ1bmN0aW9ucy4gKi9cbiAgICB2YXIgZnVuY1RvU3RyaW5nID0gY29udGV4dC5GdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAvKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbiAgICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAgIC8qKiBVc2VkIHRvIGdlbmVyYXRlIHVuaXF1ZSBJRHMuICovXG4gICAgdmFyIGlkQ291bnRlciA9IDA7XG5cbiAgICAvKiogVXNlZCB0byBpbmZlciB0aGUgYE9iamVjdGAgY29uc3RydWN0b3IuICovXG4gICAgdmFyIG9iamVjdEN0b3JTdHJpbmcgPSBmdW5jVG9TdHJpbmcuY2FsbChPYmplY3QpO1xuXG4gICAgLyoqXG4gICAgICogVXNlZCB0byByZXNvbHZlIHRoZSBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAgICAgKiBvZiB2YWx1ZXMuXG4gICAgICovXG4gICAgdmFyIG9iamVjdFRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgICAvKiogVXNlZCB0byByZXN0b3JlIHRoZSBvcmlnaW5hbCBgX2AgcmVmZXJlbmNlIGluIGBfLm5vQ29uZmxpY3RgLiAqL1xuICAgIHZhciBvbGREYXNoID0gcm9vdC5fO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGEgbWV0aG9kIGlzIG5hdGl2ZS4gKi9cbiAgICB2YXIgcmVJc05hdGl2ZSA9IFJlZ0V4cCgnXicgK1xuICAgICAgZnVuY1RvU3RyaW5nLmNhbGwoaGFzT3duUHJvcGVydHkpLnJlcGxhY2UocmVSZWdFeHBDaGFyLCAnXFxcXCQmJylcbiAgICAgIC5yZXBsYWNlKC9oYXNPd25Qcm9wZXJ0eXwoZnVuY3Rpb24pLio/KD89XFxcXFxcKCl8IGZvciAuKz8oPz1cXFxcXFxdKS9nLCAnJDEuKj8nKSArICckJ1xuICAgICk7XG5cbiAgICAvKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbiAgICB2YXIgQnVmZmVyID0gbW9kdWxlRXhwb3J0cyA/IGNvbnRleHQuQnVmZmVyIDogdW5kZWZpbmVkLFxuICAgICAgICBSZWZsZWN0ID0gY29udGV4dC5SZWZsZWN0LFxuICAgICAgICBTeW1ib2wgPSBjb250ZXh0LlN5bWJvbCxcbiAgICAgICAgVWludDhBcnJheSA9IGNvbnRleHQuVWludDhBcnJheSxcbiAgICAgICAgY2xlYXJUaW1lb3V0ID0gY29udGV4dC5jbGVhclRpbWVvdXQsXG4gICAgICAgIGVudW1lcmF0ZSA9IFJlZmxlY3QgPyBSZWZsZWN0LmVudW1lcmF0ZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YsXG4gICAgICAgIGdldE93blByb3BlcnR5U3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMsXG4gICAgICAgIGl0ZXJhdG9yU3ltYm9sID0gdHlwZW9mIChpdGVyYXRvclN5bWJvbCA9IFN5bWJvbCAmJiBTeW1ib2wuaXRlcmF0b3IpID09ICdzeW1ib2wnID8gaXRlcmF0b3JTeW1ib2wgOiB1bmRlZmluZWQsXG4gICAgICAgIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUsXG4gICAgICAgIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvdG8ucHJvcGVydHlJc0VudW1lcmFibGUsXG4gICAgICAgIHNldFRpbWVvdXQgPSBjb250ZXh0LnNldFRpbWVvdXQsXG4gICAgICAgIHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlO1xuXG4gICAgLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xuICAgIHZhciBuYXRpdmVDZWlsID0gTWF0aC5jZWlsLFxuICAgICAgICBuYXRpdmVGbG9vciA9IE1hdGguZmxvb3IsXG4gICAgICAgIG5hdGl2ZUlzRmluaXRlID0gY29udGV4dC5pc0Zpbml0ZSxcbiAgICAgICAgbmF0aXZlSm9pbiA9IGFycmF5UHJvdG8uam9pbixcbiAgICAgICAgbmF0aXZlS2V5cyA9IE9iamVjdC5rZXlzLFxuICAgICAgICBuYXRpdmVNYXggPSBNYXRoLm1heCxcbiAgICAgICAgbmF0aXZlTWluID0gTWF0aC5taW4sXG4gICAgICAgIG5hdGl2ZVBhcnNlSW50ID0gY29udGV4dC5wYXJzZUludCxcbiAgICAgICAgbmF0aXZlUmFuZG9tID0gTWF0aC5yYW5kb20sXG4gICAgICAgIG5hdGl2ZVJldmVyc2UgPSBhcnJheVByb3RvLnJldmVyc2U7XG5cbiAgICAvKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG4gICAgdmFyIE1hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnTWFwJyksXG4gICAgICAgIFNldCA9IGdldE5hdGl2ZShjb250ZXh0LCAnU2V0JyksXG4gICAgICAgIFdlYWtNYXAgPSBnZXROYXRpdmUoY29udGV4dCwgJ1dlYWtNYXAnKSxcbiAgICAgICAgbmF0aXZlQ3JlYXRlID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2NyZWF0ZScpO1xuXG4gICAgLyoqIFVzZWQgdG8gc3RvcmUgZnVuY3Rpb24gbWV0YWRhdGEuICovXG4gICAgdmFyIG1ldGFNYXAgPSBXZWFrTWFwICYmIG5ldyBXZWFrTWFwO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IG1hcHMsIHNldHMsIGFuZCB3ZWFrbWFwcy4gKi9cbiAgICB2YXIgbWFwQ3RvclN0cmluZyA9IE1hcCA/IGZ1bmNUb1N0cmluZy5jYWxsKE1hcCkgOiAnJyxcbiAgICAgICAgc2V0Q3RvclN0cmluZyA9IFNldCA/IGZ1bmNUb1N0cmluZy5jYWxsKFNldCkgOiAnJyxcbiAgICAgICAgd2Vha01hcEN0b3JTdHJpbmcgPSBXZWFrTWFwID8gZnVuY1RvU3RyaW5nLmNhbGwoV2Vha01hcCkgOiAnJztcblxuICAgIC8qKiBVc2VkIHRvIGNvbnZlcnQgc3ltYm9scyB0byBwcmltaXRpdmVzIGFuZCBzdHJpbmdzLiAqL1xuICAgIHZhciBzeW1ib2xQcm90byA9IFN5bWJvbCA/IFN5bWJvbC5wcm90b3R5cGUgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bWJvbFZhbHVlT2YgPSBTeW1ib2wgPyBzeW1ib2xQcm90by52YWx1ZU9mIDogdW5kZWZpbmVkLFxuICAgICAgICBzeW1ib2xUb1N0cmluZyA9IFN5bWJvbCA/IHN5bWJvbFByb3RvLnRvU3RyaW5nIDogdW5kZWZpbmVkO1xuXG4gICAgLyoqIFVzZWQgdG8gbG9va3VwIHVubWluaWZpZWQgZnVuY3Rpb24gbmFtZXMuICovXG4gICAgdmFyIHJlYWxOYW1lcyA9IHt9O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIG9iamVjdCB3aGljaCB3cmFwcyBgdmFsdWVgIHRvIGVuYWJsZSBpbXBsaWNpdCBtZXRob2RcbiAgICAgKiBjaGFpbmluZy4gTWV0aG9kcyB0aGF0IG9wZXJhdGUgb24gYW5kIHJldHVybiBhcnJheXMsIGNvbGxlY3Rpb25zLCBhbmRcbiAgICAgKiBmdW5jdGlvbnMgY2FuIGJlIGNoYWluZWQgdG9nZXRoZXIuIE1ldGhvZHMgdGhhdCByZXRyaWV2ZSBhIHNpbmdsZSB2YWx1ZSBvclxuICAgICAqIG1heSByZXR1cm4gYSBwcmltaXRpdmUgdmFsdWUgd2lsbCBhdXRvbWF0aWNhbGx5IGVuZCB0aGUgY2hhaW4gc2VxdWVuY2UgYW5kXG4gICAgICogcmV0dXJuIHRoZSB1bndyYXBwZWQgdmFsdWUuIE90aGVyd2lzZSwgdGhlIHZhbHVlIG11c3QgYmUgdW53cmFwcGVkIHdpdGhcbiAgICAgKiBgXyN2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBFeHBsaWNpdCBjaGFpbmluZywgd2hpY2ggbXVzdCBiZSB1bndyYXBwZWQgd2l0aCBgXyN2YWx1ZWAgaW4gYWxsIGNhc2VzLFxuICAgICAqIG1heSBiZSBlbmFibGVkIHVzaW5nIGBfLmNoYWluYC5cbiAgICAgKlxuICAgICAqIFRoZSBleGVjdXRpb24gb2YgY2hhaW5lZCBtZXRob2RzIGlzIGxhenksIHRoYXQgaXMsIGl0J3MgZGVmZXJyZWQgdW50aWxcbiAgICAgKiBgXyN2YWx1ZWAgaXMgaW1wbGljaXRseSBvciBleHBsaWNpdGx5IGNhbGxlZC5cbiAgICAgKlxuICAgICAqIExhenkgZXZhbHVhdGlvbiBhbGxvd3Mgc2V2ZXJhbCBtZXRob2RzIHRvIHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uLiBTaG9ydGN1dFxuICAgICAqIGZ1c2lvbiBpcyBhbiBvcHRpbWl6YXRpb24gdG8gbWVyZ2UgaXRlcmF0ZWUgY2FsbHM7IHRoaXMgYXZvaWRzIHRoZSBjcmVhdGlvblxuICAgICAqIG9mIGludGVybWVkaWF0ZSBhcnJheXMgYW5kIGNhbiBncmVhdGx5IHJlZHVjZSB0aGUgbnVtYmVyIG9mIGl0ZXJhdGVlIGV4ZWN1dGlvbnMuXG4gICAgICogU2VjdGlvbnMgb2YgYSBjaGFpbiBzZXF1ZW5jZSBxdWFsaWZ5IGZvciBzaG9ydGN1dCBmdXNpb24gaWYgdGhlIHNlY3Rpb24gaXNcbiAgICAgKiBhcHBsaWVkIHRvIGFuIGFycmF5IG9mIGF0IGxlYXN0IHR3byBodW5kcmVkIGVsZW1lbnRzIGFuZCBhbnkgaXRlcmF0ZWVzXG4gICAgICogYWNjZXB0IG9ubHkgb25lIGFyZ3VtZW50LiBUaGUgaGV1cmlzdGljIGZvciB3aGV0aGVyIGEgc2VjdGlvbiBxdWFsaWZpZXNcbiAgICAgKiBmb3Igc2hvcnRjdXQgZnVzaW9uIGlzIHN1YmplY3QgdG8gY2hhbmdlLlxuICAgICAqXG4gICAgICogQ2hhaW5pbmcgaXMgc3VwcG9ydGVkIGluIGN1c3RvbSBidWlsZHMgYXMgbG9uZyBhcyB0aGUgYF8jdmFsdWVgIG1ldGhvZCBpc1xuICAgICAqIGRpcmVjdGx5IG9yIGluZGlyZWN0bHkgaW5jbHVkZWQgaW4gdGhlIGJ1aWxkLlxuICAgICAqXG4gICAgICogSW4gYWRkaXRpb24gdG8gbG9kYXNoIG1ldGhvZHMsIHdyYXBwZXJzIGhhdmUgYEFycmF5YCBhbmQgYFN0cmluZ2AgbWV0aG9kcy5cbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIGBBcnJheWAgbWV0aG9kcyBhcmU6XG4gICAgICogYGNvbmNhdGAsIGBqb2luYCwgYHBvcGAsIGBwdXNoYCwgYHNoaWZ0YCwgYHNvcnRgLCBgc3BsaWNlYCwgYW5kIGB1bnNoaWZ0YFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgYFN0cmluZ2AgbWV0aG9kcyBhcmU6XG4gICAgICogYHJlcGxhY2VgIGFuZCBgc3BsaXRgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBtZXRob2RzIHRoYXQgc3VwcG9ydCBzaG9ydGN1dCBmdXNpb24gYXJlOlxuICAgICAqIGBhdGAsIGBjb21wYWN0YCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGRyb3BXaGlsZWAsIGBmaWx0ZXJgLCBgZmluZGAsXG4gICAgICogYGZpbmRMYXN0YCwgYGhlYWRgLCBgaW5pdGlhbGAsIGBsYXN0YCwgYG1hcGAsIGByZWplY3RgLCBgcmV2ZXJzZWAsIGBzbGljZWAsXG4gICAgICogYHRhaWxgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGFrZVJpZ2h0V2hpbGVgLCBgdGFrZVdoaWxlYCwgYW5kIGB0b0FycmF5YFxuICAgICAqXG4gICAgICogVGhlIGNoYWluYWJsZSB3cmFwcGVyIG1ldGhvZHMgYXJlOlxuICAgICAqIGBhZnRlcmAsIGBhcnlgLCBgYXNzaWduYCwgYGFzc2lnbkluYCwgYGFzc2lnbkluV2l0aGAsIGBhc3NpZ25XaXRoYCwgYGF0YCxcbiAgICAgKiBgYmVmb3JlYCwgYGJpbmRgLCBgYmluZEFsbGAsIGBiaW5kS2V5YCwgYGNhc3RBcnJheWAsIGBjaGFpbmAsIGBjaHVua2AsXG4gICAgICogYGNvbW1pdGAsIGBjb21wYWN0YCwgYGNvbmNhdGAsIGBjb25mb3Jtc2AsIGBjb25zdGFudGAsIGBjb3VudEJ5YCwgYGNyZWF0ZWAsXG4gICAgICogYGN1cnJ5YCwgYGRlYm91bmNlYCwgYGRlZmF1bHRzYCwgYGRlZmF1bHRzRGVlcGAsIGBkZWZlcmAsIGBkZWxheWAsIGBkaWZmZXJlbmNlYCxcbiAgICAgKiBgZGlmZmVyZW5jZUJ5YCwgYGRpZmZlcmVuY2VXaXRoYCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGRyb3BSaWdodFdoaWxlYCxcbiAgICAgKiBgZHJvcFdoaWxlYCwgYGZpbGxgLCBgZmlsdGVyYCwgYGZsYXR0ZW5gLCBgZmxhdHRlbkRlZXBgLCBgZmxhdHRlbkRlcHRoYCxcbiAgICAgKiBgZmxpcGAsIGBmbG93YCwgYGZsb3dSaWdodGAsIGBmcm9tUGFpcnNgLCBgZnVuY3Rpb25zYCwgYGZ1bmN0aW9uc0luYCxcbiAgICAgKiBgZ3JvdXBCeWAsIGBpbml0aWFsYCwgYGludGVyc2VjdGlvbmAsIGBpbnRlcnNlY3Rpb25CeWAsIGBpbnRlcnNlY3Rpb25XaXRoYCxcbiAgICAgKiBgaW52ZXJ0YCwgYGludmVydEJ5YCwgYGludm9rZU1hcGAsIGBpdGVyYXRlZWAsIGBrZXlCeWAsIGBrZXlzYCwgYGtleXNJbmAsXG4gICAgICogYG1hcGAsIGBtYXBLZXlzYCwgYG1hcFZhbHVlc2AsIGBtYXRjaGVzYCwgYG1hdGNoZXNQcm9wZXJ0eWAsIGBtZW1vaXplYCxcbiAgICAgKiBgbWVyZ2VgLCBgbWVyZ2VXaXRoYCwgYG1ldGhvZGAsIGBtZXRob2RPZmAsIGBtaXhpbmAsIGBuZWdhdGVgLCBgbnRoQXJnYCxcbiAgICAgKiBgb21pdGAsIGBvbWl0QnlgLCBgb25jZWAsIGBvcmRlckJ5YCwgYG92ZXJgLCBgb3ZlckFyZ3NgLCBgb3ZlckV2ZXJ5YCxcbiAgICAgKiBgb3ZlclNvbWVgLCBgcGFydGlhbGAsIGBwYXJ0aWFsUmlnaHRgLCBgcGFydGl0aW9uYCwgYHBpY2tgLCBgcGlja0J5YCwgYHBsYW50YCxcbiAgICAgKiBgcHJvcGVydHlgLCBgcHJvcGVydHlPZmAsIGBwdWxsYCwgYHB1bGxBbGxgLCBgcHVsbEFsbEJ5YCwgYHB1bGxBdGAsIGBwdXNoYCxcbiAgICAgKiBgcmFuZ2VgLCBgcmFuZ2VSaWdodGAsIGByZWFyZ2AsIGByZWplY3RgLCBgcmVtb3ZlYCwgYHJlc3RgLCBgcmV2ZXJzZWAsXG4gICAgICogYHNhbXBsZVNpemVgLCBgc2V0YCwgYHNldFdpdGhgLCBgc2h1ZmZsZWAsIGBzbGljZWAsIGBzb3J0YCwgYHNvcnRCeWAsXG4gICAgICogYHNwbGljZWAsIGBzcHJlYWRgLCBgdGFpbGAsIGB0YWtlYCwgYHRha2VSaWdodGAsIGB0YWtlUmlnaHRXaGlsZWAsXG4gICAgICogYHRha2VXaGlsZWAsIGB0YXBgLCBgdGhyb3R0bGVgLCBgdGhydWAsIGB0b0FycmF5YCwgYHRvUGFpcnNgLCBgdG9QYWlyc0luYCxcbiAgICAgKiBgdG9QYXRoYCwgYHRvUGxhaW5PYmplY3RgLCBgdHJhbnNmb3JtYCwgYHVuYXJ5YCwgYHVuaW9uYCwgYHVuaW9uQnlgLFxuICAgICAqIGB1bmlvbldpdGhgLCBgdW5pcWAsIGB1bmlxQnlgLCBgdW5pcVdpdGhgLCBgdW5zZXRgLCBgdW5zaGlmdGAsIGB1bnppcGAsXG4gICAgICogYHVuemlwV2l0aGAsIGB2YWx1ZXNgLCBgdmFsdWVzSW5gLCBgd2l0aG91dGAsIGB3cmFwYCwgYHhvcmAsIGB4b3JCeWAsXG4gICAgICogYHhvcldpdGhgLCBgemlwYCwgYHppcE9iamVjdGAsIGB6aXBPYmplY3REZWVwYCwgYW5kIGB6aXBXaXRoYFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IGFyZSAqKm5vdCoqIGNoYWluYWJsZSBieSBkZWZhdWx0IGFyZTpcbiAgICAgKiBgYWRkYCwgYGF0dGVtcHRgLCBgY2FtZWxDYXNlYCwgYGNhcGl0YWxpemVgLCBgY2VpbGAsIGBjbGFtcGAsIGBjbG9uZWAsXG4gICAgICogYGNsb25lRGVlcGAsIGBjbG9uZURlZXBXaXRoYCwgYGNsb25lV2l0aGAsIGBkZWJ1cnJgLCBgZW5kc1dpdGhgLCBgZXFgLFxuICAgICAqIGBlc2NhcGVgLCBgZXNjYXBlUmVnRXhwYCwgYGV2ZXJ5YCwgYGZpbmRgLCBgZmluZEluZGV4YCwgYGZpbmRLZXlgLCBgZmluZExhc3RgLFxuICAgICAqIGBmaW5kTGFzdEluZGV4YCwgYGZpbmRMYXN0S2V5YCwgYGZsb29yYCwgYGZvckVhY2hgLCBgZm9yRWFjaFJpZ2h0YCwgYGZvckluYCxcbiAgICAgKiBgZm9ySW5SaWdodGAsIGBmb3JPd25gLCBgZm9yT3duUmlnaHRgLCBgZ2V0YCwgYGd0YCwgYGd0ZWAsIGBoYXNgLCBgaGFzSW5gLFxuICAgICAqIGBoZWFkYCwgYGlkZW50aXR5YCwgYGluY2x1ZGVzYCwgYGluZGV4T2ZgLCBgaW5SYW5nZWAsIGBpbnZva2VgLCBgaXNBcmd1bWVudHNgLFxuICAgICAqIGBpc0FycmF5YCwgYGlzQXJyYXlCdWZmZXJgLCBgaXNBcnJheUxpa2VgLCBgaXNBcnJheUxpa2VPYmplY3RgLCBgaXNCb29sZWFuYCxcbiAgICAgKiBgaXNCdWZmZXJgLCBgaXNEYXRlYCwgYGlzRWxlbWVudGAsIGBpc0VtcHR5YCwgYGlzRXF1YWxgLCBgaXNFcXVhbFdpdGhgLFxuICAgICAqIGBpc0Vycm9yYCwgYGlzRmluaXRlYCwgYGlzRnVuY3Rpb25gLCBgaXNJbnRlZ2VyYCwgYGlzTGVuZ3RoYCwgYGlzTWFwYCxcbiAgICAgKiBgaXNNYXRjaGAsIGBpc01hdGNoV2l0aGAsIGBpc05hTmAsIGBpc05hdGl2ZWAsIGBpc05pbGAsIGBpc051bGxgLCBgaXNOdW1iZXJgLFxuICAgICAqIGBpc09iamVjdGAsIGBpc09iamVjdExpa2VgLCBgaXNQbGFpbk9iamVjdGAsIGBpc1JlZ0V4cGAsIGBpc1NhZmVJbnRlZ2VyYCxcbiAgICAgKiBgaXNTZXRgLCBgaXNTdHJpbmdgLCBgaXNVbmRlZmluZWRgLCBgaXNUeXBlZEFycmF5YCwgYGlzV2Vha01hcGAsIGBpc1dlYWtTZXRgLFxuICAgICAqIGBqb2luYCwgYGtlYmFiQ2FzZWAsIGBsYXN0YCwgYGxhc3RJbmRleE9mYCwgYGxvd2VyQ2FzZWAsIGBsb3dlckZpcnN0YCxcbiAgICAgKiBgbHRgLCBgbHRlYCwgYG1heGAsIGBtYXhCeWAsIGBtZWFuYCwgYG1pbmAsIGBtaW5CeWAsIGBub0NvbmZsaWN0YCwgYG5vb3BgLFxuICAgICAqIGBub3dgLCBgcGFkYCwgYHBhZEVuZGAsIGBwYWRTdGFydGAsIGBwYXJzZUludGAsIGBwb3BgLCBgcmFuZG9tYCwgYHJlZHVjZWAsXG4gICAgICogYHJlZHVjZVJpZ2h0YCwgYHJlcGVhdGAsIGByZXN1bHRgLCBgcm91bmRgLCBgcnVuSW5Db250ZXh0YCwgYHNhbXBsZWAsXG4gICAgICogYHNoaWZ0YCwgYHNpemVgLCBgc25ha2VDYXNlYCwgYHNvbWVgLCBgc29ydGVkSW5kZXhgLCBgc29ydGVkSW5kZXhCeWAsXG4gICAgICogYHNvcnRlZExhc3RJbmRleGAsIGBzb3J0ZWRMYXN0SW5kZXhCeWAsIGBzdGFydENhc2VgLCBgc3RhcnRzV2l0aGAsIGBzdWJ0cmFjdGAsXG4gICAgICogYHN1bWAsIGBzdW1CeWAsIGB0ZW1wbGF0ZWAsIGB0aW1lc2AsIGB0b0xvd2VyYCwgYHRvSW50ZWdlcmAsIGB0b0xlbmd0aGAsXG4gICAgICogYHRvTnVtYmVyYCwgYHRvU2FmZUludGVnZXJgLCBgdG9TdHJpbmdgLCBgdG9VcHBlcmAsIGB0cmltYCwgYHRyaW1FbmRgLFxuICAgICAqIGB0cmltU3RhcnRgLCBgdHJ1bmNhdGVgLCBgdW5lc2NhcGVgLCBgdW5pcXVlSWRgLCBgdXBwZXJDYXNlYCwgYHVwcGVyRmlyc3RgLFxuICAgICAqIGB2YWx1ZWAsIGFuZCBgd29yZHNgXG4gICAgICpcbiAgICAgKiBAbmFtZSBfXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDIsIDNdKTtcbiAgICAgKlxuICAgICAqIC8vIFJldHVybnMgYW4gdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIHdyYXBwZWQucmVkdWNlKF8uYWRkKTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiAvLyBSZXR1cm5zIGEgd3JhcHBlZCB2YWx1ZS5cbiAgICAgKiB2YXIgc3F1YXJlcyA9IHdyYXBwZWQubWFwKHNxdWFyZSk7XG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShzcXVhcmVzLnZhbHVlKCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb2Rhc2godmFsdWUpIHtcbiAgICAgIGlmIChpc09iamVjdExpa2UodmFsdWUpICYmICFpc0FycmF5KHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpKSB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExvZGFzaFdyYXBwZXIpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdfX3dyYXBwZWRfXycpKSB7XG4gICAgICAgICAgcmV0dXJuIHdyYXBwZXJDbG9uZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGZ1bmN0aW9uIHdob3NlIHByb3RvdHlwZSBhbGwgY2hhaW5pbmcgd3JhcHBlcnMgaW5oZXJpdCBmcm9tLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTG9kYXNoKCkge1xuICAgICAgLy8gTm8gb3BlcmF0aW9uIHBlcmZvcm1lZC5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBjb25zdHJ1Y3RvciBmb3IgY3JlYXRpbmcgYGxvZGFzaGAgd3JhcHBlciBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NoYWluQWxsXSBFbmFibGUgY2hhaW5pbmcgZm9yIGFsbCB3cmFwcGVyIG1ldGhvZHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTG9kYXNoV3JhcHBlcih2YWx1ZSwgY2hhaW5BbGwpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgICAgIHRoaXMuX19jaGFpbl9fID0gISFjaGFpbkFsbDtcbiAgICAgIHRoaXMuX19pbmRleF9fID0gMDtcbiAgICAgIHRoaXMuX192YWx1ZXNfXyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgdGVtcGxhdGUgZGVsaW1pdGVycyB1c2VkIGJ5IGxvZGFzaCBhcmUgbGlrZSB0aG9zZSBpblxuICAgICAqIGVtYmVkZGVkIFJ1YnkgKEVSQikuIENoYW5nZSB0aGUgZm9sbG93aW5nIHRlbXBsYXRlIHNldHRpbmdzIHRvIHVzZVxuICAgICAqIGFsdGVybmF0aXZlIGRlbGltaXRlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqL1xuICAgIGxvZGFzaC50ZW1wbGF0ZVNldHRpbmdzID0ge1xuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGBkYXRhYCBwcm9wZXJ0eSB2YWx1ZXMgdG8gYmUgSFRNTC1lc2NhcGVkLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdlc2NhcGUnOiByZUVzY2FwZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIGRldGVjdCBjb2RlIHRvIGJlIGV2YWx1YXRlZC5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSB7UmVnRXhwfVxuICAgICAgICovXG4gICAgICAnZXZhbHVhdGUnOiByZUV2YWx1YXRlLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGBkYXRhYCBwcm9wZXJ0eSB2YWx1ZXMgdG8gaW5qZWN0LlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdpbnRlcnBvbGF0ZSc6IHJlSW50ZXJwb2xhdGUsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byByZWZlcmVuY2UgdGhlIGRhdGEgb2JqZWN0IGluIHRoZSB0ZW1wbGF0ZSB0ZXh0LlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICAgKi9cbiAgICAgICd2YXJpYWJsZSc6ICcnLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gaW1wb3J0IHZhcmlhYmxlcyBpbnRvIHRoZSBjb21waWxlZCB0ZW1wbGF0ZS5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzXG4gICAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAgICovXG4gICAgICAnaW1wb3J0cyc6IHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQSByZWZlcmVuY2UgdG8gdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAbWVtYmVyT2YgXy50ZW1wbGF0ZVNldHRpbmdzLmltcG9ydHNcbiAgICAgICAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgICAgICAgKi9cbiAgICAgICAgJ18nOiBsb2Rhc2hcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGxhenkgd3JhcHBlciBvYmplY3Qgd2hpY2ggd3JhcHMgYHZhbHVlYCB0byBlbmFibGUgbGF6eSBldmFsdWF0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIExhenlXcmFwcGVyKHZhbHVlKSB7XG4gICAgICB0aGlzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgICB0aGlzLl9fYWN0aW9uc19fID0gW107XG4gICAgICB0aGlzLl9fZGlyX18gPSAxO1xuICAgICAgdGhpcy5fX2ZpbHRlcmVkX18gPSBmYWxzZTtcbiAgICAgIHRoaXMuX19pdGVyYXRlZXNfXyA9IFtdO1xuICAgICAgdGhpcy5fX3Rha2VDb3VudF9fID0gTUFYX0FSUkFZX0xFTkdUSDtcbiAgICAgIHRoaXMuX192aWV3c19fID0gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBsYXp5IHdyYXBwZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbG9uZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBgTGF6eVdyYXBwZXJgIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXp5Q2xvbmUoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbmV3IExhenlXcmFwcGVyKHRoaXMuX193cmFwcGVkX18pO1xuICAgICAgcmVzdWx0Ll9fYWN0aW9uc19fID0gY29weUFycmF5KHRoaXMuX19hY3Rpb25zX18pO1xuICAgICAgcmVzdWx0Ll9fZGlyX18gPSB0aGlzLl9fZGlyX187XG4gICAgICByZXN1bHQuX19maWx0ZXJlZF9fID0gdGhpcy5fX2ZpbHRlcmVkX187XG4gICAgICByZXN1bHQuX19pdGVyYXRlZXNfXyA9IGNvcHlBcnJheSh0aGlzLl9faXRlcmF0ZWVzX18pO1xuICAgICAgcmVzdWx0Ll9fdGFrZUNvdW50X18gPSB0aGlzLl9fdGFrZUNvdW50X187XG4gICAgICByZXN1bHQuX192aWV3c19fID0gY29weUFycmF5KHRoaXMuX192aWV3c19fKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZXJzZXMgdGhlIGRpcmVjdGlvbiBvZiBsYXp5IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgcmV2ZXJzZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyByZXZlcnNlZCBgTGF6eVdyYXBwZXJgIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXp5UmV2ZXJzZSgpIHtcbiAgICAgIGlmICh0aGlzLl9fZmlsdGVyZWRfXykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IExhenlXcmFwcGVyKHRoaXMpO1xuICAgICAgICByZXN1bHQuX19kaXJfXyA9IC0xO1xuICAgICAgICByZXN1bHQuX19maWx0ZXJlZF9fID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IHRoaXMuY2xvbmUoKTtcbiAgICAgICAgcmVzdWx0Ll9fZGlyX18gKj0gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4dHJhY3RzIHRoZSB1bndyYXBwZWQgdmFsdWUgZnJvbSBpdHMgbGF6eSB3cmFwcGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSB2YWx1ZVxuICAgICAqIEBtZW1iZXJPZiBMYXp5V3JhcHBlclxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eVZhbHVlKCkge1xuICAgICAgdmFyIGFycmF5ID0gdGhpcy5fX3dyYXBwZWRfXy52YWx1ZSgpLFxuICAgICAgICAgIGRpciA9IHRoaXMuX19kaXJfXyxcbiAgICAgICAgICBpc0FyciA9IGlzQXJyYXkoYXJyYXkpLFxuICAgICAgICAgIGlzUmlnaHQgPSBkaXIgPCAwLFxuICAgICAgICAgIGFyckxlbmd0aCA9IGlzQXJyID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICB2aWV3ID0gZ2V0VmlldygwLCBhcnJMZW5ndGgsIHRoaXMuX192aWV3c19fKSxcbiAgICAgICAgICBzdGFydCA9IHZpZXcuc3RhcnQsXG4gICAgICAgICAgZW5kID0gdmlldy5lbmQsXG4gICAgICAgICAgbGVuZ3RoID0gZW5kIC0gc3RhcnQsXG4gICAgICAgICAgaW5kZXggPSBpc1JpZ2h0ID8gZW5kIDogKHN0YXJ0IC0gMSksXG4gICAgICAgICAgaXRlcmF0ZWVzID0gdGhpcy5fX2l0ZXJhdGVlc19fLFxuICAgICAgICAgIGl0ZXJMZW5ndGggPSBpdGVyYXRlZXMubGVuZ3RoLFxuICAgICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgICB0YWtlQ291bnQgPSBuYXRpdmVNaW4obGVuZ3RoLCB0aGlzLl9fdGFrZUNvdW50X18pO1xuXG4gICAgICBpZiAoIWlzQXJyIHx8IGFyckxlbmd0aCA8IExBUkdFX0FSUkFZX1NJWkUgfHxcbiAgICAgICAgICAoYXJyTGVuZ3RoID09IGxlbmd0aCAmJiB0YWtlQ291bnQgPT0gbGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gYmFzZVdyYXBwZXJWYWx1ZShhcnJheSwgdGhpcy5fX2FjdGlvbnNfXyk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG5cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKGxlbmd0aC0tICYmIHJlc0luZGV4IDwgdGFrZUNvdW50KSB7XG4gICAgICAgIGluZGV4ICs9IGRpcjtcblxuICAgICAgICB2YXIgaXRlckluZGV4ID0gLTEsXG4gICAgICAgICAgICB2YWx1ZSA9IGFycmF5W2luZGV4XTtcblxuICAgICAgICB3aGlsZSAoKytpdGVySW5kZXggPCBpdGVyTGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSBpdGVyYXRlZXNbaXRlckluZGV4XSxcbiAgICAgICAgICAgICAgaXRlcmF0ZWUgPSBkYXRhLml0ZXJhdGVlLFxuICAgICAgICAgICAgICB0eXBlID0gZGF0YS50eXBlLFxuICAgICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgICAgIGlmICh0eXBlID09IExBWllfTUFQX0ZMQUcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gY29tcHV0ZWQ7XG4gICAgICAgICAgfSBlbHNlIGlmICghY29tcHV0ZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlID09IExBWllfRklMVEVSX0ZMQUcpIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBicmVhayBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaGFzaCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBoYXNoIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBIYXNoKCkge31cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBoYXNoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gaGFzaCBUaGUgaGFzaCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc2hEZWxldGUoaGFzaCwga2V5KSB7XG4gICAgICByZXR1cm4gaGFzaEhhcyhoYXNoLCBrZXkpICYmIGRlbGV0ZSBoYXNoW2tleV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaGFzaCB2YWx1ZSBmb3IgYGtleWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoR2V0KGhhc2gsIGtleSkge1xuICAgICAgaWYgKG5hdGl2ZUNyZWF0ZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gaGFzaFtrZXldO1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSBIQVNIX1VOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGhhc2gsIGtleSkgPyBoYXNoW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgaGFzaCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gaGFzaCBUaGUgaGFzaCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaEhhcyhoYXNoLCBrZXkpIHtcbiAgICAgIHJldHVybiBuYXRpdmVDcmVhdGUgPyBoYXNoW2tleV0gIT09IHVuZGVmaW5lZCA6IGhhc093blByb3BlcnR5LmNhbGwoaGFzaCwga2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBoYXNoIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaFNldChoYXNoLCBrZXksIHZhbHVlKSB7XG4gICAgICBoYXNoW2tleV0gPSAobmF0aXZlQ3JlYXRlICYmIHZhbHVlID09PSB1bmRlZmluZWQpID8gSEFTSF9VTkRFRklORUQgOiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbWFwIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gY2FjaGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTWFwQ2FjaGUodmFsdWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB2YWx1ZXMgPyB2YWx1ZXMubGVuZ3RoIDogMDtcblxuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdmFsdWVzW2luZGV4XTtcbiAgICAgICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBtYXAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsZWFyXG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2xlYXIoKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fID0ge1xuICAgICAgICAnaGFzaCc6IG5ldyBIYXNoLFxuICAgICAgICAnbWFwJzogTWFwID8gbmV3IE1hcCA6IFtdLFxuICAgICAgICAnc3RyaW5nJzogbmV3IEhhc2hcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIG1hcC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZGVsZXRlXG4gICAgICogQG1lbWJlck9mIE1hcENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcERlbGV0ZShrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIGlmIChpc0tleWFibGUoa2V5KSkge1xuICAgICAgICByZXR1cm4gaGFzaERlbGV0ZSh0eXBlb2Yga2V5ID09ICdzdHJpbmcnID8gZGF0YS5zdHJpbmcgOiBkYXRhLmhhc2gsIGtleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gTWFwID8gZGF0YS5tYXBbJ2RlbGV0ZSddKGtleSkgOiBhc3NvY0RlbGV0ZShkYXRhLm1hcCwga2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBtYXAgdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKGlzS2V5YWJsZShrZXkpKSB7XG4gICAgICAgIHJldHVybiBoYXNoR2V0KHR5cGVvZiBrZXkgPT0gJ3N0cmluZycgPyBkYXRhLnN0cmluZyA6IGRhdGEuaGFzaCwga2V5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBNYXAgPyBkYXRhLm1hcC5nZXQoa2V5KSA6IGFzc29jR2V0KGRhdGEubWFwLCBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIG1hcCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwSGFzKGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKGlzS2V5YWJsZShrZXkpKSB7XG4gICAgICAgIHJldHVybiBoYXNoSGFzKHR5cGVvZiBrZXkgPT0gJ3N0cmluZycgPyBkYXRhLnN0cmluZyA6IGRhdGEuaGFzaCwga2V5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBNYXAgPyBkYXRhLm1hcC5oYXMoa2V5KSA6IGFzc29jSGFzKGRhdGEubWFwLCBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1hcCBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbWFwIGNhY2hlIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBTZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKGlzS2V5YWJsZShrZXkpKSB7XG4gICAgICAgIGhhc2hTZXQodHlwZW9mIGtleSA9PSAnc3RyaW5nJyA/IGRhdGEuc3RyaW5nIDogZGF0YS5oYXNoLCBrZXksIHZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAoTWFwKSB7XG4gICAgICAgIGRhdGEubWFwLnNldChrZXksIHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFzc29jU2V0KGRhdGEubWFwLCBrZXksIHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQ3JlYXRlcyBhIHNldCBjYWNoZSBvYmplY3QgdG8gc3RvcmUgdW5pcXVlIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBTZXRDYWNoZSh2YWx1ZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHZhbHVlcyA/IHZhbHVlcy5sZW5ndGggOiAwO1xuXG4gICAgICB0aGlzLl9fZGF0YV9fID0gbmV3IE1hcENhY2hlO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdGhpcy5wdXNoKHZhbHVlc1tpbmRleF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGluIGBjYWNoZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjYWNoZSBUaGUgc2V0IGNhY2hlIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYWNoZUhhcyhjYWNoZSwgdmFsdWUpIHtcbiAgICAgIHZhciBtYXAgPSBjYWNoZS5fX2RhdGFfXztcbiAgICAgIGlmIChpc0tleWFibGUodmFsdWUpKSB7XG4gICAgICAgIHZhciBkYXRhID0gbWFwLl9fZGF0YV9fLFxuICAgICAgICAgICAgaGFzaCA9IHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyA/IGRhdGEuc3RyaW5nIDogZGF0YS5oYXNoO1xuXG4gICAgICAgIHJldHVybiBoYXNoW3ZhbHVlXSA9PT0gSEFTSF9VTkRFRklORUQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gbWFwLmhhcyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBgdmFsdWVgIHRvIHRoZSBzZXQgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHB1c2hcbiAgICAgKiBAbWVtYmVyT2YgU2V0Q2FjaGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYWNoZVB1c2godmFsdWUpIHtcbiAgICAgIHZhciBtYXAgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKGlzS2V5YWJsZSh2YWx1ZSkpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBtYXAuX19kYXRhX18sXG4gICAgICAgICAgICBoYXNoID0gdHlwZW9mIHZhbHVlID09ICdzdHJpbmcnID8gZGF0YS5zdHJpbmcgOiBkYXRhLmhhc2g7XG5cbiAgICAgICAgaGFzaFt2YWx1ZV0gPSBIQVNIX1VOREVGSU5FRDtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBtYXAuc2V0KHZhbHVlLCBIQVNIX1VOREVGSU5FRCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHN0YWNrIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gY2FjaGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gU3RhY2sodmFsdWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB2YWx1ZXMgPyB2YWx1ZXMubGVuZ3RoIDogMDtcblxuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdmFsdWVzW2luZGV4XTtcbiAgICAgICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBzdGFjay5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgY2xlYXJcbiAgICAgKiBAbWVtYmVyT2YgU3RhY2tcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja0NsZWFyKCkge1xuICAgICAgdGhpcy5fX2RhdGFfXyA9IHsgJ2FycmF5JzogW10sICdtYXAnOiBudWxsIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIHN0YWNrLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgU3RhY2tcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tEZWxldGUoa2V5KSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICAgICAgYXJyYXkgPSBkYXRhLmFycmF5O1xuXG4gICAgICByZXR1cm4gYXJyYXkgPyBhc3NvY0RlbGV0ZShhcnJheSwga2V5KSA6IGRhdGEubWFwWydkZWxldGUnXShrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHN0YWNrIHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZ2V0XG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGVudHJ5IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGFycmF5ID0gZGF0YS5hcnJheTtcblxuICAgICAgcmV0dXJuIGFycmF5ID8gYXNzb2NHZXQoYXJyYXksIGtleSkgOiBkYXRhLm1hcC5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYSBzdGFjayB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgU3RhY2tcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tIYXMoa2V5KSB7XG4gICAgICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICAgICAgYXJyYXkgPSBkYXRhLmFycmF5O1xuXG4gICAgICByZXR1cm4gYXJyYXkgPyBhc3NvY0hhcyhhcnJheSwga2V5KSA6IGRhdGEubWFwLmhhcyhrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHN0YWNrIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHNldFxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBzdGFjayBjYWNoZSBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tTZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGFycmF5ID0gZGF0YS5hcnJheTtcblxuICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgIGlmIChhcnJheS5sZW5ndGggPCAoTEFSR0VfQVJSQVlfU0laRSAtIDEpKSB7XG4gICAgICAgICAgYXNzb2NTZXQoYXJyYXksIGtleSwgdmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGEuYXJyYXkgPSBudWxsO1xuICAgICAgICAgIGRhdGEubWFwID0gbmV3IE1hcENhY2hlKGFycmF5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIG1hcCA9IGRhdGEubWFwO1xuICAgICAgaWYgKG1hcCkge1xuICAgICAgICBtYXAuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGFzc29jaWF0aXZlIGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc29jRGVsZXRlKGFycmF5LCBrZXkpIHtcbiAgICAgIHZhciBpbmRleCA9IGFzc29jSW5kZXhPZihhcnJheSwga2V5KTtcbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGxhc3RJbmRleCA9IGFycmF5Lmxlbmd0aCAtIDE7XG4gICAgICBpZiAoaW5kZXggPT0gbGFzdEluZGV4KSB7XG4gICAgICAgIGFycmF5LnBvcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGFzc29jaWF0aXZlIGFycmF5IHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NvY0dldChhcnJheSwga2V5KSB7XG4gICAgICB2YXIgaW5kZXggPSBhc3NvY0luZGV4T2YoYXJyYXksIGtleSk7XG4gICAgICByZXR1cm4gaW5kZXggPCAwID8gdW5kZWZpbmVkIDogYXJyYXlbaW5kZXhdWzFdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhbiBhc3NvY2lhdGl2ZSBhcnJheSB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc29jSGFzKGFycmF5LCBrZXkpIHtcbiAgICAgIHJldHVybiBhc3NvY0luZGV4T2YoYXJyYXksIGtleSkgPiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBga2V5YCBpcyBmb3VuZCBpbiBgYXJyYXlgXG4gICAgICogb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0ga2V5IFRoZSBrZXkgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc29jSW5kZXhPZihhcnJheSwga2V5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIGlmIChlcShhcnJheVtsZW5ndGhdWzBdLCBrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGFzc29jaWF0aXZlIGFycmF5IGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc29jU2V0KGFycmF5LCBrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgaW5kZXggPSBhc3NvY0luZGV4T2YoYXJyYXksIGtleSk7XG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgIGFycmF5LnB1c2goW2tleSwgdmFsdWVdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFycmF5W2luZGV4XVsxXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNgIHRvIGN1c3RvbWl6ZSBpdHMgYF8uYXNzaWduSW5gIHVzZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBvYmpWYWx1ZSBUaGUgZGVzdGluYXRpb24gdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgc291cmNlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFzc2lnbkluRGVmYXVsdHMob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgaWYgKG9ialZhbHVlID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAoZXEob2JqVmFsdWUsIG9iamVjdFByb3RvW2tleV0pICYmICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgcmV0dXJuIHNyY1ZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYXNzaWduVmFsdWVgIGV4Y2VwdCB0aGF0IGl0IGRvZXNuJ3QgYXNzaWduIGB1bmRlZmluZWRgIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGFzc2lnbi5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICAgIGlmICgodmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhZXEob2JqZWN0W2tleV0sIHZhbHVlKSkgfHxcbiAgICAgICAgICAodHlwZW9mIGtleSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpKSB7XG4gICAgICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBgdmFsdWVgIHRvIGBrZXlgIG9mIGBvYmplY3RgIGlmIHRoZSBleGlzdGluZyB2YWx1ZSBpcyBub3QgZXF1aXZhbGVudFxuICAgICAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBvYmpWYWx1ZSA9IG9iamVjdFtrZXldO1xuICAgICAgaWYgKCEoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkgJiYgZXEob2JqVmFsdWUsIHZhbHVlKSkgfHxcbiAgICAgICAgICAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSkge1xuICAgICAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFnZ3JlZ2F0ZXMgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gIG9uIGBhY2N1bXVsYXRvcmAgd2l0aCBrZXlzIHRyYW5zZm9ybWVkXG4gICAgICogYnkgYGl0ZXJhdGVlYCBhbmQgdmFsdWVzIHNldCBieSBgc2V0dGVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGBhY2N1bXVsYXRvcmAgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gYWNjdW11bGF0b3IgVGhlIGluaXRpYWwgYWdncmVnYXRlZCBvYmplY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBhY2N1bXVsYXRvcmAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUFnZ3JlZ2F0b3IoY29sbGVjdGlvbiwgc2V0dGVyLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgc2V0dGVyKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaXRlcmF0ZWUodmFsdWUpLCBjb2xsZWN0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmFzc2lnbmAgd2l0aG91dCBzdXBwb3J0IGZvciBtdWx0aXBsZSBzb3VyY2VzXG4gICAgICogb3IgYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXNzaWduKG9iamVjdCwgc291cmNlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICYmIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyBUaGUgcHJvcGVydHkgcGF0aHMgb2YgZWxlbWVudHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwaWNrZWQgZWxlbWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUF0KG9iamVjdCwgcGF0aHMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGlzTmlsID0gb2JqZWN0ID09IG51bGwsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBpc05pbCA/IHVuZGVmaW5lZCA6IGdldChvYmplY3QsIHBhdGhzW2luZGV4XSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgdG8gYW4gZW1wdHkgYXJyYXkgaWYgaXQncyBub3QgYW4gYXJyYXkgbGlrZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2FzdEFycmF5TGlrZU9iamVjdCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KHZhbHVlKSA/IHZhbHVlIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYHZhbHVlYCB0byBgaWRlbnRpdHlgIGlmIGl0J3Mgbm90IGEgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2FzdEZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdmdW5jdGlvbicgPyB2YWx1ZSA6IGlkZW50aXR5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgdG8gYSBwYXRoIGFycmF5IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNhc3QgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2FzdFBhdGgodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogc3RyaW5nVG9QYXRoKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jbGFtcGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzIHRvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjbGFtcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xvd2VyXSBUaGUgbG93ZXIgYm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHVwcGVyIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjbGFtcGVkIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmIChudW1iZXIgPT09IG51bWJlcikge1xuICAgICAgICBpZiAodXBwZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG51bWJlciA9IG51bWJlciA8PSB1cHBlciA/IG51bWJlciA6IHVwcGVyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsb3dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbnVtYmVyID0gbnVtYmVyID49IGxvd2VyID8gbnVtYmVyIDogbG93ZXI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY2xvbmVgIGFuZCBgXy5jbG9uZURlZXBgIHdoaWNoIHRyYWNrc1xuICAgICAqIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtrZXldIFRoZSBrZXkgb2YgYHZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIHBhcmVudCBvYmplY3Qgb2YgYHZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIG9iamVjdHMgYW5kIHRoZWlyIGNsb25lIGNvdW50ZXJwYXJ0cy5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDbG9uZSh2YWx1ZSwgaXNEZWVwLCBjdXN0b21pemVyLCBrZXksIG9iamVjdCwgc3RhY2spIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICByZXN1bHQgPSBvYmplY3QgPyBjdXN0b21pemVyKHZhbHVlLCBrZXksIG9iamVjdCwgc3RhY2spIDogY3VzdG9taXplcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpO1xuICAgICAgaWYgKGlzQXJyKSB7XG4gICAgICAgIHJlc3VsdCA9IGluaXRDbG9uZUFycmF5KHZhbHVlKTtcbiAgICAgICAgaWYgKCFpc0RlZXApIHtcbiAgICAgICAgICByZXR1cm4gY29weUFycmF5KHZhbHVlLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdGFnID0gZ2V0VGFnKHZhbHVlKSxcbiAgICAgICAgICAgIGlzRnVuYyA9IHRhZyA9PSBmdW5jVGFnIHx8IHRhZyA9PSBnZW5UYWc7XG5cbiAgICAgICAgaWYgKGlzQnVmZmVyKHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBjbG9uZUJ1ZmZlcih2YWx1ZSwgaXNEZWVwKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFnID09IG9iamVjdFRhZyB8fCB0YWcgPT0gYXJnc1RhZyB8fCAoaXNGdW5jICYmICFvYmplY3QpKSB7XG4gICAgICAgICAgaWYgKGlzSG9zdE9iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QgPyB2YWx1ZSA6IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBpbml0Q2xvbmVPYmplY3QoaXNGdW5jID8ge30gOiB2YWx1ZSk7XG4gICAgICAgICAgaWYgKCFpc0RlZXApIHtcbiAgICAgICAgICAgIHJldHVybiBjb3B5U3ltYm9scyh2YWx1ZSwgYmFzZUFzc2lnbihyZXN1bHQsIHZhbHVlKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghY2xvbmVhYmxlVGFnc1t0YWddKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0ID8gdmFsdWUgOiB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0ID0gaW5pdENsb25lQnlUYWcodmFsdWUsIHRhZywgaXNEZWVwKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQ2hlY2sgZm9yIGNpcmN1bGFyIHJlZmVyZW5jZXMgYW5kIHJldHVybiBpdHMgY29ycmVzcG9uZGluZyBjbG9uZS5cbiAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICB2YXIgc3RhY2tlZCA9IHN0YWNrLmdldCh2YWx1ZSk7XG4gICAgICBpZiAoc3RhY2tlZCkge1xuICAgICAgICByZXR1cm4gc3RhY2tlZDtcbiAgICAgIH1cbiAgICAgIHN0YWNrLnNldCh2YWx1ZSwgcmVzdWx0KTtcblxuICAgICAgLy8gUmVjdXJzaXZlbHkgcG9wdWxhdGUgY2xvbmUgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgIChpc0FyciA/IGFycmF5RWFjaCA6IGJhc2VGb3JPd24pKHZhbHVlLCBmdW5jdGlvbihzdWJWYWx1ZSwga2V5KSB7XG4gICAgICAgIGFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCBiYXNlQ2xvbmUoc3ViVmFsdWUsIGlzRGVlcCwgY3VzdG9taXplciwga2V5LCB2YWx1ZSwgc3RhY2spKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGlzQXJyID8gcmVzdWx0IDogY29weVN5bWJvbHModmFsdWUsIHJlc3VsdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY29uZm9ybXNgIHdoaWNoIGRvZXNuJ3QgY2xvbmUgYHNvdXJjZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNvbmZvcm1zKHNvdXJjZSkge1xuICAgICAgdmFyIHByb3BzID0ga2V5cyhzb3VyY2UpLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gIWxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaW5kZXggPSBsZW5ndGg7XG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgdmFyIGtleSA9IHByb3BzW2luZGV4XSxcbiAgICAgICAgICAgICAgcHJlZGljYXRlID0gc291cmNlW2tleV0sXG4gICAgICAgICAgICAgIHZhbHVlID0gb2JqZWN0W2tleV07XG5cbiAgICAgICAgICBpZiAoKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gT2JqZWN0KG9iamVjdCkpKSB8fCAhcHJlZGljYXRlKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY3JlYXRlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFzc2lnbmluZ1xuICAgICAqIHByb3BlcnRpZXMgdG8gdGhlIGNyZWF0ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvdG90eXBlIFRoZSBvYmplY3QgdG8gaW5oZXJpdCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNyZWF0ZShwcm90bykge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0KHByb3RvKSA/IG9iamVjdENyZWF0ZShwcm90bykgOiB7fTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5kZWxheWAgYW5kIGBfLmRlZmVyYCB3aGljaCBhY2NlcHRzIGFuIGFycmF5XG4gICAgICogb2YgYGZ1bmNgIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkgaW52b2NhdGlvbi5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gYXJncyBUaGUgYXJndW1lbnRzIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VEZWxheShmdW5jLCB3YWl0LCBhcmdzKSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpIHsgZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpOyB9LCB3YWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uZGlmZmVyZW5jZWAgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgICAqIGV4Y2x1ZGluZyBtdWx0aXBsZSBhcnJheXMgb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRGlmZmVyZW5jZShhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzLFxuICAgICAgICAgIGlzQ29tbW9uID0gdHJ1ZSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgdmFsdWVzTGVuZ3RoID0gdmFsdWVzLmxlbmd0aDtcblxuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVyYXRlZSkge1xuICAgICAgICB2YWx1ZXMgPSBhcnJheU1hcCh2YWx1ZXMsIGJhc2VVbmFyeShpdGVyYXRlZSkpO1xuICAgICAgfVxuICAgICAgaWYgKGNvbXBhcmF0b3IpIHtcbiAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzV2l0aDtcbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHZhbHVlcy5sZW5ndGggPj0gTEFSR0VfQVJSQVlfU0laRSkge1xuICAgICAgICBpbmNsdWRlcyA9IGNhY2hlSGFzO1xuICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICB2YWx1ZXMgPSBuZXcgU2V0Q2FjaGUodmFsdWVzKTtcbiAgICAgIH1cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIGlmIChpc0NvbW1vbiAmJiBjb21wdXRlZCA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICB2YXIgdmFsdWVzSW5kZXggPSB2YWx1ZXNMZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHZhbHVlc0luZGV4LS0pIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZXNbdmFsdWVzSW5kZXhdID09PSBjb21wdXRlZCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpbmNsdWRlcyh2YWx1ZXMsIGNvbXB1dGVkLCBjb21wYXJhdG9yKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JFYWNoYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqL1xuICAgIHZhciBiYXNlRWFjaCA9IGNyZWF0ZUJhc2VFYWNoKGJhc2VGb3JPd24pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yRWFjaFJpZ2h0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqL1xuICAgIHZhciBiYXNlRWFjaFJpZ2h0ID0gY3JlYXRlQmFzZUVhY2goYmFzZUZvck93blJpZ2h0LCB0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmV2ZXJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjaywgZWxzZSBgZmFsc2VgXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUV2ZXJ5KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0ID0gISFwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5maWxsYCB3aXRob3V0IGFuIGl0ZXJhdGVlIGNhbGwgZ3VhcmQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWxsLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGZpbGwgYGFycmF5YCB3aXRoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHN0YXJ0ID0gdG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgc3RhcnQgPSAtc3RhcnQgPiBsZW5ndGggPyAwIDogKGxlbmd0aCArIHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGVuZCA9IChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiBsZW5ndGgpID8gbGVuZ3RoIDogdG9JbnRlZ2VyKGVuZCk7XG4gICAgICBpZiAoZW5kIDwgMCkge1xuICAgICAgICBlbmQgKz0gbGVuZ3RoO1xuICAgICAgfVxuICAgICAgZW5kID0gc3RhcnQgPiBlbmQgPyAwIDogdG9MZW5ndGgoZW5kKTtcbiAgICAgIHdoaWxlIChzdGFydCA8IGVuZCkge1xuICAgICAgICBhcnJheVtzdGFydCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbHRlcmAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZpbHRlcihjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mbGF0dGVuYCB3aXRoIHN1cHBvcnQgZm9yIHJlc3RyaWN0aW5nIGZsYXR0ZW5pbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkZXB0aCBUaGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGguXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNTdHJpY3RdIFJlc3RyaWN0IGZsYXR0ZW5pbmcgdG8gYXJyYXlzLWxpa2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcmVzdWx0PVtdXSBUaGUgaW5pdGlhbCByZXN1bHQgdmFsdWUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGbGF0dGVuKGFycmF5LCBkZXB0aCwgaXNTdHJpY3QsIHJlc3VsdCkge1xuICAgICAgcmVzdWx0IHx8IChyZXN1bHQgPSBbXSk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAoZGVwdGggPiAwICYmIGlzQXJyYXlMaWtlT2JqZWN0KHZhbHVlKSAmJlxuICAgICAgICAgICAgKGlzU3RyaWN0IHx8IGlzQXJyYXkodmFsdWUpIHx8IGlzQXJndW1lbnRzKHZhbHVlKSkpIHtcbiAgICAgICAgICBpZiAoZGVwdGggPiAxKSB7XG4gICAgICAgICAgICAvLyBSZWN1cnNpdmVseSBmbGF0dGVuIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICAgICAgYmFzZUZsYXR0ZW4odmFsdWUsIGRlcHRoIC0gMSwgaXNTdHJpY3QsIHJlc3VsdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFycmF5UHVzaChyZXN1bHQsIHZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWlzU3RyaWN0KSB7XG4gICAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGJhc2VGb3JJbmAgYW5kIGBiYXNlRm9yT3duYCB3aGljaCBpdGVyYXRlc1xuICAgICAqIG92ZXIgYG9iamVjdGAgcHJvcGVydGllcyByZXR1cm5lZCBieSBga2V5c0Z1bmNgIGludm9raW5nIGBpdGVyYXRlZWAgZm9yXG4gICAgICogZWFjaCBwcm9wZXJ0eS4gSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5XG4gICAgICogcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgdmFyIGJhc2VGb3IgPSBjcmVhdGVCYXNlRm9yKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGJhc2VGb3JgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllc1xuICAgICAqIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYG9iamVjdGAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUZvclJpZ2h0ID0gY3JlYXRlQmFzZUZvcih0cnVlKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvckluYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGb3JJbihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlRm9yKG9iamVjdCwgaXRlcmF0ZWUsIGtleXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yT3duYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGb3JPd24ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yKG9iamVjdCwgaXRlcmF0ZWUsIGtleXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvck93blJpZ2h0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGb3JPd25SaWdodChvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICYmIGJhc2VGb3JSaWdodChvYmplY3QsIGl0ZXJhdGVlLCBrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mdW5jdGlvbnNgIHdoaWNoIGNyZWF0ZXMgYW4gYXJyYXkgb2ZcbiAgICAgKiBgb2JqZWN0YCBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmaWx0ZXJlZCBmcm9tIGBwcm9wc2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBmaWx0ZXIuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZ1bmN0aW9ucyhvYmplY3QsIHByb3BzKSB7XG4gICAgICByZXR1cm4gYXJyYXlGaWx0ZXIocHJvcHMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICByZXR1cm4gaXNGdW5jdGlvbihvYmplY3Rba2V5XSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5nZXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVmYXVsdCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlR2V0KG9iamVjdCwgcGF0aCkge1xuICAgICAgcGF0aCA9IGlzS2V5KHBhdGgsIG9iamVjdCkgPyBbcGF0aCArICcnXSA6IGJhc2VDYXN0UGF0aChwYXRoKTtcblxuICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICBsZW5ndGggPSBwYXRoLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKG9iamVjdCAhPSBudWxsICYmIGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIG9iamVjdCA9IG9iamVjdFtwYXRoW2luZGV4KytdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoaW5kZXggJiYgaW5kZXggPT0gbGVuZ3RoKSA/IG9iamVjdCA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5oYXNgIHdpdGhvdXQgc3VwcG9ydCBmb3IgZGVlcCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBrZXkgVGhlIGtleSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUhhcyhvYmplY3QsIGtleSkge1xuICAgICAgLy8gQXZvaWQgYSBidWcgaW4gSUUgMTAtMTEgd2hlcmUgb2JqZWN0cyB3aXRoIGEgW1tQcm90b3R5cGVdXSBvZiBgbnVsbGAsXG4gICAgICAvLyB0aGF0IGFyZSBjb21wb3NlZCBlbnRpcmVseSBvZiBpbmRleCBwcm9wZXJ0aWVzLCByZXR1cm4gYGZhbHNlYCBmb3JcbiAgICAgIC8vIGBoYXNPd25Qcm9wZXJ0eWAgY2hlY2tzIG9mIHRoZW0uXG4gICAgICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkgfHxcbiAgICAgICAgKHR5cGVvZiBvYmplY3QgPT0gJ29iamVjdCcgJiYga2V5IGluIG9iamVjdCAmJiBnZXRQcm90b3R5cGVPZihvYmplY3QpID09PSBudWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5oYXNJbmAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IGtleSBUaGUga2V5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSGFzSW4ob2JqZWN0LCBrZXkpIHtcbiAgICAgIHJldHVybiBrZXkgaW4gT2JqZWN0KG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW5SYW5nZWAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzIHRvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgbnVtYmVyYCBpcyBpbiB0aGUgcmFuZ2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW5SYW5nZShudW1iZXIsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHJldHVybiBudW1iZXIgPj0gbmF0aXZlTWluKHN0YXJ0LCBlbmQpICYmIG51bWJlciA8IG5hdGl2ZU1heChzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uaW50ZXJzZWN0aW9uYCwgd2l0aG91dCBzdXBwb3J0XG4gICAgICogZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMsIHRoYXQgYWNjZXB0cyBhbiBhcnJheSBvZiBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXlzIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHNoYXJlZCB2YWx1ZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUludGVyc2VjdGlvbihhcnJheXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5jbHVkZXMgPSBjb21wYXJhdG9yID8gYXJyYXlJbmNsdWRlc1dpdGggOiBhcnJheUluY2x1ZGVzLFxuICAgICAgICAgIG90aExlbmd0aCA9IGFycmF5cy5sZW5ndGgsXG4gICAgICAgICAgb3RoSW5kZXggPSBvdGhMZW5ndGgsXG4gICAgICAgICAgY2FjaGVzID0gQXJyYXkob3RoTGVuZ3RoKSxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKG90aEluZGV4LS0pIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJyYXlzW290aEluZGV4XTtcbiAgICAgICAgaWYgKG90aEluZGV4ICYmIGl0ZXJhdGVlKSB7XG4gICAgICAgICAgYXJyYXkgPSBhcnJheU1hcChhcnJheSwgYmFzZVVuYXJ5KGl0ZXJhdGVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgY2FjaGVzW290aEluZGV4XSA9ICFjb21wYXJhdG9yICYmIChpdGVyYXRlZSB8fCBhcnJheS5sZW5ndGggPj0gMTIwKVxuICAgICAgICAgID8gbmV3IFNldENhY2hlKG90aEluZGV4ICYmIGFycmF5KVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgYXJyYXkgPSBhcnJheXNbMF07XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBzZWVuID0gY2FjaGVzWzBdO1xuXG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICBpZiAoIShzZWVuXG4gICAgICAgICAgICAgID8gY2FjaGVIYXMoc2VlbiwgY29tcHV0ZWQpXG4gICAgICAgICAgICAgIDogaW5jbHVkZXMocmVzdWx0LCBjb21wdXRlZCwgY29tcGFyYXRvcilcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICB2YXIgb3RoSW5kZXggPSBvdGhMZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKC0tb3RoSW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBjYWNoZSA9IGNhY2hlc1tvdGhJbmRleF07XG4gICAgICAgICAgICBpZiAoIShjYWNoZVxuICAgICAgICAgICAgICAgICAgPyBjYWNoZUhhcyhjYWNoZSwgY29tcHV0ZWQpXG4gICAgICAgICAgICAgICAgICA6IGluY2x1ZGVzKGFycmF5c1tvdGhJbmRleF0sIGNvbXB1dGVkLCBjb21wYXJhdG9yKSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzZWVuKSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW52ZXJ0YCBhbmQgYF8uaW52ZXJ0QnlgIHdoaWNoIGludmVydHNcbiAgICAgKiBgb2JqZWN0YCB3aXRoIHZhbHVlcyB0cmFuc2Zvcm1lZCBieSBgaXRlcmF0ZWVgIGFuZCBzZXQgYnkgYHNldHRlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW52ZXJ0ZXIob2JqZWN0LCBzZXR0ZXIsIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgYmFzZUZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICBzZXR0ZXIoYWNjdW11bGF0b3IsIGl0ZXJhdGVlKHZhbHVlKSwga2V5LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW52b2tlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGluZGl2aWR1YWxcbiAgICAgKiBtZXRob2QgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgaW52b2tlZCBtZXRob2QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmICghaXNLZXkocGF0aCwgb2JqZWN0KSkge1xuICAgICAgICBwYXRoID0gYmFzZUNhc3RQYXRoKHBhdGgpO1xuICAgICAgICBvYmplY3QgPSBwYXJlbnQob2JqZWN0LCBwYXRoKTtcbiAgICAgICAgcGF0aCA9IGxhc3QocGF0aCk7XG4gICAgICB9XG4gICAgICB2YXIgZnVuYyA9IG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogb2JqZWN0W3BhdGhdO1xuICAgICAgcmV0dXJuIGZ1bmMgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IGFwcGx5KGZ1bmMsIG9iamVjdCwgYXJncyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNFcXVhbGAgd2hpY2ggc3VwcG9ydHMgcGFydGlhbCBjb21wYXJpc29uc1xuICAgICAqIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtiaXRtYXNrXSBUaGUgYml0bWFzayBvZiBjb21wYXJpc29uIGZsYWdzLlxuICAgICAqICBUaGUgYml0bWFzayBtYXkgYmUgY29tcG9zZWQgb2YgdGhlIGZvbGxvd2luZyBmbGFnczpcbiAgICAgKiAgICAgMSAtIFVub3JkZXJlZCBjb21wYXJpc29uXG4gICAgICogICAgIDIgLSBQYXJ0aWFsIGNvbXBhcmlzb25cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlciwgY3VzdG9taXplciwgYml0bWFzaywgc3RhY2spIHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCBvdGhlciA9PSBudWxsIHx8ICghaXNPYmplY3QodmFsdWUpICYmICFpc09iamVjdExpa2Uob3RoZXIpKSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgIT09IHZhbHVlICYmIG90aGVyICE9PSBvdGhlcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlSXNFcXVhbERlZXAodmFsdWUsIG90aGVyLCBiYXNlSXNFcXVhbCwgY3VzdG9taXplciwgYml0bWFzaywgc3RhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxgIGZvciBhcnJheXMgYW5kIG9iamVjdHMgd2hpY2ggcGVyZm9ybXNcbiAgICAgKiBkZWVwIGNvbXBhcmlzb25zIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMgZW5hYmxpbmcgb2JqZWN0cyB3aXRoIGNpcmN1bGFyXG4gICAgICogcmVmZXJlbmNlcyB0byBiZSBjb21wYXJlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtiaXRtYXNrXSBUaGUgYml0bWFzayBvZiBjb21wYXJpc29uIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNFcXVhbERlZXAob2JqZWN0LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBiaXRtYXNrLCBzdGFjaykge1xuICAgICAgdmFyIG9iaklzQXJyID0gaXNBcnJheShvYmplY3QpLFxuICAgICAgICAgIG90aElzQXJyID0gaXNBcnJheShvdGhlciksXG4gICAgICAgICAgb2JqVGFnID0gYXJyYXlUYWcsXG4gICAgICAgICAgb3RoVGFnID0gYXJyYXlUYWc7XG5cbiAgICAgIGlmICghb2JqSXNBcnIpIHtcbiAgICAgICAgb2JqVGFnID0gZ2V0VGFnKG9iamVjdCk7XG4gICAgICAgIGlmIChvYmpUYWcgPT0gYXJnc1RhZykge1xuICAgICAgICAgIG9ialRhZyA9IG9iamVjdFRhZztcbiAgICAgICAgfSBlbHNlIGlmIChvYmpUYWcgIT0gb2JqZWN0VGFnKSB7XG4gICAgICAgICAgb2JqSXNBcnIgPSBpc1R5cGVkQXJyYXkob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFvdGhJc0Fycikge1xuICAgICAgICBvdGhUYWcgPSBnZXRUYWcob3RoZXIpO1xuICAgICAgICBpZiAob3RoVGFnID09IGFyZ3NUYWcpIHtcbiAgICAgICAgICBvdGhUYWcgPSBvYmplY3RUYWc7XG4gICAgICAgIH0gZWxzZSBpZiAob3RoVGFnICE9IG9iamVjdFRhZykge1xuICAgICAgICAgIG90aElzQXJyID0gaXNUeXBlZEFycmF5KG90aGVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIG9iaklzT2JqID0gb2JqVGFnID09IG9iamVjdFRhZyAmJiAhaXNIb3N0T2JqZWN0KG9iamVjdCksXG4gICAgICAgICAgb3RoSXNPYmogPSBvdGhUYWcgPT0gb2JqZWN0VGFnICYmICFpc0hvc3RPYmplY3Qob3RoZXIpLFxuICAgICAgICAgIGlzU2FtZVRhZyA9IG9ialRhZyA9PSBvdGhUYWc7XG5cbiAgICAgIGlmIChpc1NhbWVUYWcgJiYgIShvYmpJc0FyciB8fCBvYmpJc09iaikpIHtcbiAgICAgICAgcmV0dXJuIGVxdWFsQnlUYWcob2JqZWN0LCBvdGhlciwgb2JqVGFnLCBlcXVhbEZ1bmMsIGN1c3RvbWl6ZXIsIGJpdG1hc2spO1xuICAgICAgfVxuICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBQQVJUSUFMX0NPTVBBUkVfRkxBRztcbiAgICAgIGlmICghaXNQYXJ0aWFsKSB7XG4gICAgICAgIHZhciBvYmpJc1dyYXBwZWQgPSBvYmpJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgJ19fd3JhcHBlZF9fJyksXG4gICAgICAgICAgICBvdGhJc1dyYXBwZWQgPSBvdGhJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG90aGVyLCAnX193cmFwcGVkX18nKTtcblxuICAgICAgICBpZiAob2JqSXNXcmFwcGVkIHx8IG90aElzV3JhcHBlZCkge1xuICAgICAgICAgIHJldHVybiBlcXVhbEZ1bmMob2JqSXNXcmFwcGVkID8gb2JqZWN0LnZhbHVlKCkgOiBvYmplY3QsIG90aElzV3JhcHBlZCA/IG90aGVyLnZhbHVlKCkgOiBvdGhlciwgY3VzdG9taXplciwgYml0bWFzaywgc3RhY2spO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWlzU2FtZVRhZykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgcmV0dXJuIChvYmpJc0FyciA/IGVxdWFsQXJyYXlzIDogZXF1YWxPYmplY3RzKShvYmplY3QsIG90aGVyLCBlcXVhbEZ1bmMsIGN1c3RvbWl6ZXIsIGJpdG1hc2ssIHN0YWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc01hdGNoYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHBhcmFtIHtBcnJheX0gbWF0Y2hEYXRhIFRoZSBwcm9wZXJ0eSBuYW1lcywgdmFsdWVzLCBhbmQgY29tcGFyZSBmbGFncyB0byBtYXRjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBtYXRjaERhdGEsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBpbmRleCA9IG1hdGNoRGF0YS5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gaW5kZXgsXG4gICAgICAgICAgbm9DdXN0b21pemVyID0gIWN1c3RvbWl6ZXI7XG5cbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gIWxlbmd0aDtcbiAgICAgIH1cbiAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgdmFyIGRhdGEgPSBtYXRjaERhdGFbaW5kZXhdO1xuICAgICAgICBpZiAoKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKVxuICAgICAgICAgICAgICA/IGRhdGFbMV0gIT09IG9iamVjdFtkYXRhWzBdXVxuICAgICAgICAgICAgICA6ICEoZGF0YVswXSBpbiBvYmplY3QpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGRhdGEgPSBtYXRjaERhdGFbaW5kZXhdO1xuICAgICAgICB2YXIga2V5ID0gZGF0YVswXSxcbiAgICAgICAgICAgIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICBzcmNWYWx1ZSA9IGRhdGFbMV07XG5cbiAgICAgICAgaWYgKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKSB7XG4gICAgICAgICAgaWYgKG9ialZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gb2JqZWN0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgc3RhY2sgPSBuZXcgU3RhY2ssXG4gICAgICAgICAgICAgIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSwgc3RhY2spIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKCEocmVzdWx0ID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICA/IGJhc2VJc0VxdWFsKHNyY1ZhbHVlLCBvYmpWYWx1ZSwgY3VzdG9taXplciwgVU5PUkRFUkVEX0NPTVBBUkVfRkxBRyB8IFBBUlRJQUxfQ09NUEFSRV9GTEFHLCBzdGFjaylcbiAgICAgICAgICAgICAgICA6IHJlc3VsdFxuICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pdGVyYXRlZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gW3ZhbHVlPV8uaWRlbnRpdHldIFRoZSB2YWx1ZSB0byBjb252ZXJ0IHRvIGFuIGl0ZXJhdGVlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgaXRlcmF0ZWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUl0ZXJhdGVlKHZhbHVlKSB7XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgICAgIGlmICh0eXBlID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGlkZW50aXR5O1xuICAgICAgfVxuICAgICAgaWYgKHR5cGUgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodmFsdWUpXG4gICAgICAgICAgPyBiYXNlTWF0Y2hlc1Byb3BlcnR5KHZhbHVlWzBdLCB2YWx1ZVsxXSlcbiAgICAgICAgICA6IGJhc2VNYXRjaGVzKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9wZXJ0eSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c2Agd2hpY2ggZG9lc24ndCBza2lwIHRoZSBjb25zdHJ1Y3RvclxuICAgICAqIHByb3BlcnR5IG9mIHByb3RvdHlwZXMgb3IgdHJlYXQgc3BhcnNlIGFycmF5cyBhcyBkZW5zZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUtleXMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gbmF0aXZlS2V5cyhPYmplY3Qob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c0luYCB3aGljaCBkb2Vzbid0IHNraXAgdGhlIGNvbnN0cnVjdG9yXG4gICAgICogcHJvcGVydHkgb2YgcHJvdG90eXBlcyBvciB0cmVhdCBzcGFyc2UgYXJyYXlzIGFzIGRlbnNlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlS2V5c0luKG9iamVjdCkge1xuICAgICAgb2JqZWN0ID0gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBPYmplY3Qob2JqZWN0KTtcblxuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBGYWxsYmFjayBmb3IgSUUgPCA5IHdpdGggZXM2LXNoaW0uXG4gICAgaWYgKGVudW1lcmF0ZSAmJiAhcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh7ICd2YWx1ZU9mJzogMSB9LCAndmFsdWVPZicpKSB7XG4gICAgICBiYXNlS2V5c0luID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBpdGVyYXRvclRvQXJyYXkoZW51bWVyYXRlKG9iamVjdCkpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXBgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gQXJyYXkoY29sbGVjdGlvbi5sZW5ndGgpIDogW107XG5cbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmVzdWx0WysraW5kZXhdID0gaXRlcmF0ZWUodmFsdWUsIGtleSwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWF0Y2hlc2Agd2hpY2ggZG9lc24ndCBjbG9uZSBgc291cmNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHZhbHVlcyB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWF0Y2hlcyhzb3VyY2UpIHtcbiAgICAgIHZhciBtYXRjaERhdGEgPSBnZXRNYXRjaERhdGEoc291cmNlKTtcbiAgICAgIGlmIChtYXRjaERhdGEubGVuZ3RoID09IDEgJiYgbWF0Y2hEYXRhWzBdWzJdKSB7XG4gICAgICAgIHZhciBrZXkgPSBtYXRjaERhdGFbMF1bMF0sXG4gICAgICAgICAgICB2YWx1ZSA9IG1hdGNoRGF0YVswXVsxXTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBvYmplY3Rba2V5XSA9PT0gdmFsdWUgJiZcbiAgICAgICAgICAgICh2YWx1ZSAhPT0gdW5kZWZpbmVkIHx8IChrZXkgaW4gT2JqZWN0KG9iamVjdCkpKTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PT0gc291cmNlIHx8IGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBtYXRjaERhdGEpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXRjaGVzUHJvcGVydHlgIHdoaWNoIGRvZXNuJ3QgY2xvbmUgYHNyY1ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSB2YWx1ZSB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlTWF0Y2hlc1Byb3BlcnR5KHBhdGgsIHNyY1ZhbHVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHZhciBvYmpWYWx1ZSA9IGdldChvYmplY3QsIHBhdGgpO1xuICAgICAgICByZXR1cm4gKG9ialZhbHVlID09PSB1bmRlZmluZWQgJiYgb2JqVmFsdWUgPT09IHNyY1ZhbHVlKVxuICAgICAgICAgID8gaGFzSW4ob2JqZWN0LCBwYXRoKVxuICAgICAgICAgIDogYmFzZUlzRXF1YWwoc3JjVmFsdWUsIG9ialZhbHVlLCB1bmRlZmluZWQsIFVOT1JERVJFRF9DT01QQVJFX0ZMQUcgfCBQQVJUSUFMX0NPTVBBUkVfRkxBRyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1lcmdlYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzcmNJbmRleCBUaGUgaW5kZXggb2YgYHNvdXJjZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgbWVyZ2VkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIHNvdXJjZSB2YWx1ZXMgYW5kIHRoZWlyIG1lcmdlZCBjb3VudGVycGFydHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1lcmdlKG9iamVjdCwgc291cmNlLCBzcmNJbmRleCwgY3VzdG9taXplciwgc3RhY2spIHtcbiAgICAgIGlmIChvYmplY3QgPT09IHNvdXJjZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgcHJvcHMgPSAoaXNBcnJheShzb3VyY2UpIHx8IGlzVHlwZWRBcnJheShzb3VyY2UpKVxuICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICA6IGtleXNJbihzb3VyY2UpO1xuXG4gICAgICBhcnJheUVhY2gocHJvcHMgfHwgc291cmNlLCBmdW5jdGlvbihzcmNWYWx1ZSwga2V5KSB7XG4gICAgICAgIGlmIChwcm9wcykge1xuICAgICAgICAgIGtleSA9IHNyY1ZhbHVlO1xuICAgICAgICAgIHNyY1ZhbHVlID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzT2JqZWN0KHNyY1ZhbHVlKSkge1xuICAgICAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICAgICAgYmFzZU1lcmdlRGVlcChvYmplY3QsIHNvdXJjZSwga2V5LCBzcmNJbmRleCwgYmFzZU1lcmdlLCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIG5ld1ZhbHVlID0gY3VzdG9taXplclxuICAgICAgICAgICAgPyBjdXN0b21pemVyKG9iamVjdFtrZXldLCBzcmNWYWx1ZSwgKGtleSArICcnKSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBzcmNWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VNZXJnZWAgZm9yIGFycmF5cyBhbmQgb2JqZWN0cyB3aGljaCBwZXJmb3Jtc1xuICAgICAqIGRlZXAgbWVyZ2VzIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMgZW5hYmxpbmcgb2JqZWN0cyB3aXRoIGNpcmN1bGFyXG4gICAgICogcmVmZXJlbmNlcyB0byBiZSBtZXJnZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gbWVyZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNyY0luZGV4IFRoZSBpbmRleCBvZiBgc291cmNlYC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXJnZUZ1bmMgVGhlIGZ1bmN0aW9uIHRvIG1lcmdlIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBzb3VyY2UgdmFsdWVzIGFuZCB0aGVpciBtZXJnZWQgY291bnRlcnBhcnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNZXJnZURlZXAob2JqZWN0LCBzb3VyY2UsIGtleSwgc3JjSW5kZXgsIG1lcmdlRnVuYywgY3VzdG9taXplciwgc3RhY2spIHtcbiAgICAgIHZhciBvYmpWYWx1ZSA9IG9iamVjdFtrZXldLFxuICAgICAgICAgIHNyY1ZhbHVlID0gc291cmNlW2tleV0sXG4gICAgICAgICAgc3RhY2tlZCA9IHN0YWNrLmdldChzcmNWYWx1ZSk7XG5cbiAgICAgIGlmIChzdGFja2VkKSB7XG4gICAgICAgIGFzc2lnbk1lcmdlVmFsdWUob2JqZWN0LCBrZXksIHN0YWNrZWQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgbmV3VmFsdWUgPSBjdXN0b21pemVyXG4gICAgICAgID8gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUsIChrZXkgKyAnJyksIG9iamVjdCwgc291cmNlLCBzdGFjaylcbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHZhciBpc0NvbW1vbiA9IG5ld1ZhbHVlID09PSB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChpc0NvbW1vbikge1xuICAgICAgICBuZXdWYWx1ZSA9IHNyY1ZhbHVlO1xuICAgICAgICBpZiAoaXNBcnJheShzcmNWYWx1ZSkgfHwgaXNUeXBlZEFycmF5KHNyY1ZhbHVlKSkge1xuICAgICAgICAgIGlmIChpc0FycmF5KG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBvYmpWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoaXNBcnJheUxpa2VPYmplY3Qob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGNvcHlBcnJheShvYmpWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gYmFzZUNsb25lKHNyY1ZhbHVlLCB0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNQbGFpbk9iamVjdChzcmNWYWx1ZSkgfHwgaXNBcmd1bWVudHMoc3JjVmFsdWUpKSB7XG4gICAgICAgICAgaWYgKGlzQXJndW1lbnRzKG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSB0b1BsYWluT2JqZWN0KG9ialZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoIWlzT2JqZWN0KG9ialZhbHVlKSB8fCAoc3JjSW5kZXggJiYgaXNGdW5jdGlvbihvYmpWYWx1ZSkpKSB7XG4gICAgICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBiYXNlQ2xvbmUoc3JjVmFsdWUsIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gb2JqVmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YWNrLnNldChzcmNWYWx1ZSwgbmV3VmFsdWUpO1xuXG4gICAgICBpZiAoaXNDb21tb24pIHtcbiAgICAgICAgLy8gUmVjdXJzaXZlbHkgbWVyZ2Ugb2JqZWN0cyBhbmQgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICAgIG1lcmdlRnVuYyhuZXdWYWx1ZSwgc3JjVmFsdWUsIHNyY0luZGV4LCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICB9XG4gICAgICBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ub3JkZXJCeWAgd2l0aG91dCBwYXJhbSBndWFyZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW118T2JqZWN0W118c3RyaW5nW119IGl0ZXJhdGVlcyBUaGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gb3JkZXJzIFRoZSBzb3J0IG9yZGVycyBvZiBgaXRlcmF0ZWVzYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU9yZGVyQnkoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHRvSXRlcmF0ZWUgPSBnZXRJdGVyYXRlZSgpO1xuXG4gICAgICBpdGVyYXRlZXMgPSBhcnJheU1hcChpdGVyYXRlZXMubGVuZ3RoID8gaXRlcmF0ZWVzIDogQXJyYXkoMSksIGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgIHJldHVybiB0b0l0ZXJhdGVlKGl0ZXJhdGVlKTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZU1hcChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHZhciBjcml0ZXJpYSA9IGFycmF5TWFwKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHtcbiAgICAgICAgICByZXR1cm4gaXRlcmF0ZWUodmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgJ2NyaXRlcmlhJzogY3JpdGVyaWEsICdpbmRleCc6ICsraW5kZXgsICd2YWx1ZSc6IHZhbHVlIH07XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGJhc2VTb3J0QnkocmVzdWx0LCBmdW5jdGlvbihvYmplY3QsIG90aGVyKSB7XG4gICAgICAgIHJldHVybiBjb21wYXJlTXVsdGlwbGUob2JqZWN0LCBvdGhlciwgb3JkZXJzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnBpY2tgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbFxuICAgICAqIHByb3BlcnR5IG5hbWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVBpY2sob2JqZWN0LCBwcm9wcykge1xuICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICByZXR1cm4gYXJyYXlSZWR1Y2UocHJvcHMsIGZ1bmN0aW9uKHJlc3VsdCwga2V5KSB7XG4gICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSwge30pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mICBgXy5waWNrQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIHByb3BlcnR5LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVBpY2tCeShvYmplY3QsIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgYmFzZUZvckluKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBrZXkpKSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnByb3BlcnR5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eShrZXkpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZVByb3BlcnR5YCB3aGljaCBzdXBwb3J0cyBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQcm9wZXJ0eURlZXAocGF0aCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wdWxsQWxsYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVB1bGxBbGwoYXJyYXksIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGJhc2VQdWxsQWxsQnkoYXJyYXksIHZhbHVlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucHVsbEFsbEJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAgICogc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUHVsbEFsbEJ5KGFycmF5LCB2YWx1ZXMsIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgIHNlZW4gPSBhcnJheTtcblxuICAgICAgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgIHNlZW4gPSBhcnJheU1hcChhcnJheSwgZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIGl0ZXJhdGVlKHZhbHVlKTsgfSk7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgZnJvbUluZGV4ID0gMCxcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWVzW2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICB3aGlsZSAoKGZyb21JbmRleCA9IGJhc2VJbmRleE9mKHNlZW4sIGNvbXB1dGVkLCBmcm9tSW5kZXgpKSA+IC0xKSB7XG4gICAgICAgICAgaWYgKHNlZW4gIT09IGFycmF5KSB7XG4gICAgICAgICAgICBzcGxpY2UuY2FsbChzZWVuLCBmcm9tSW5kZXgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzcGxpY2UuY2FsbChhcnJheSwgZnJvbUluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnB1bGxBdGAgd2l0aG91dCBzdXBwb3J0IGZvciBpbmRpdmlkdWFsXG4gICAgICogaW5kZXhlcyBvciBjYXB0dXJpbmcgdGhlIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJbXX0gaW5kZXhlcyBUaGUgaW5kZXhlcyBvZiBlbGVtZW50cyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVB1bGxBdChhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gaW5kZXhlcy5sZW5ndGggOiAwLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgaW5kZXggPSBpbmRleGVzW2xlbmd0aF07XG4gICAgICAgIGlmIChsYXN0SW5kZXggPT0gbGVuZ3RoIHx8IGluZGV4ICE9IHByZXZpb3VzKSB7XG4gICAgICAgICAgdmFyIHByZXZpb3VzID0gaW5kZXg7XG4gICAgICAgICAgaWYgKGlzSW5kZXgoaW5kZXgpKSB7XG4gICAgICAgICAgICBzcGxpY2UuY2FsbChhcnJheSwgaW5kZXgsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmICghaXNLZXkoaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgICAgdmFyIHBhdGggPSBiYXNlQ2FzdFBhdGgoaW5kZXgpLFxuICAgICAgICAgICAgICAgIG9iamVjdCA9IHBhcmVudChhcnJheSwgcGF0aCk7XG5cbiAgICAgICAgICAgIGlmIChvYmplY3QgIT0gbnVsbCkge1xuICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W2xhc3QocGF0aCldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSBhcnJheVtpbmRleF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucmFuZG9tYCB3aXRob3V0IHN1cHBvcnQgZm9yIHJldHVybmluZ1xuICAgICAqIGZsb2F0aW5nLXBvaW50IG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsb3dlciBUaGUgbG93ZXIgYm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHVwcGVyIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSYW5kb20obG93ZXIsIHVwcGVyKSB7XG4gICAgICByZXR1cm4gbG93ZXIgKyBuYXRpdmVGbG9vcihuYXRpdmVSYW5kb20oKSAqICh1cHBlciAtIGxvd2VyICsgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJhbmdlYCBhbmQgYF8ucmFuZ2VSaWdodGAgd2hpY2ggZG9lc24ndFxuICAgICAqIGNvZXJjZSBhcmd1bWVudHMgdG8gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RlcCBUaGUgdmFsdWUgdG8gaW5jcmVtZW50IG9yIGRlY3JlbWVudCBieS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBudW1iZXJzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSYW5nZShzdGFydCwgZW5kLCBzdGVwLCBmcm9tUmlnaHQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChuYXRpdmVDZWlsKChlbmQgLSBzdGFydCkgLyAoc3RlcCB8fCAxKSksIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICByZXN1bHRbZnJvbVJpZ2h0ID8gbGVuZ3RoIDogKytpbmRleF0gPSBzdGFydDtcbiAgICAgICAgc3RhcnQgKz0gc3RlcDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc2V0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIHBhdGggY3JlYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHBhdGggPSBpc0tleShwYXRoLCBvYmplY3QpID8gW3BhdGggKyAnJ10gOiBiYXNlQ2FzdFBhdGgocGF0aCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDEsXG4gICAgICAgICAgbmVzdGVkID0gb2JqZWN0O1xuXG4gICAgICB3aGlsZSAobmVzdGVkICE9IG51bGwgJiYgKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcGF0aFtpbmRleF07XG4gICAgICAgIGlmIChpc09iamVjdChuZXN0ZWQpKSB7XG4gICAgICAgICAgdmFyIG5ld1ZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgaWYgKGluZGV4ICE9IGxhc3RJbmRleCkge1xuICAgICAgICAgICAgdmFyIG9ialZhbHVlID0gbmVzdGVkW2tleV07XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKG9ialZhbHVlLCBrZXksIG5lc3RlZCkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBuZXdWYWx1ZSA9IG9ialZhbHVlID09IG51bGxcbiAgICAgICAgICAgICAgICA/IChpc0luZGV4KHBhdGhbaW5kZXggKyAxXSkgPyBbXSA6IHt9KVxuICAgICAgICAgICAgICAgIDogb2JqVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGFzc2lnblZhbHVlKG5lc3RlZCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgbmVzdGVkID0gbmVzdGVkW2tleV07XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBzZXREYXRhYCB3aXRob3V0IHN1cHBvcnQgZm9yIGhvdCBsb29wIGRldGVjdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXNzb2NpYXRlIG1ldGFkYXRhIHdpdGguXG4gICAgICogQHBhcmFtIHsqfSBkYXRhIFRoZSBtZXRhZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBiYXNlU2V0RGF0YSA9ICFtZXRhTWFwID8gaWRlbnRpdHkgOiBmdW5jdGlvbihmdW5jLCBkYXRhKSB7XG4gICAgICBtZXRhTWFwLnNldChmdW5jLCBkYXRhKTtcbiAgICAgIHJldHVybiBmdW5jO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zbGljZWAgd2l0aG91dCBhbiBpdGVyYXRlZSBjYWxsIGd1YXJkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2xpY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IC1zdGFydCA+IGxlbmd0aCA/IDAgOiAobGVuZ3RoICsgc3RhcnQpO1xuICAgICAgfVxuICAgICAgZW5kID0gZW5kID4gbGVuZ3RoID8gbGVuZ3RoIDogZW5kO1xuICAgICAgaWYgKGVuZCA8IDApIHtcbiAgICAgICAgZW5kICs9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGxlbmd0aCA9IHN0YXJ0ID4gZW5kID8gMCA6ICgoZW5kIC0gc3RhcnQpID4+PiAwKTtcbiAgICAgIHN0YXJ0ID4+Pj0gMDtcblxuICAgICAgdmFyIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gYXJyYXlbaW5kZXggKyBzdGFydF07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvbWVgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjaywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb21lKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdDtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJlc3VsdCA9IHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gIXJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZEluZGV4YCBhbmQgYF8uc29ydGVkTGFzdEluZGV4YCB3aGljaFxuICAgICAqIHBlcmZvcm1zIGEgYmluYXJ5IHNlYXJjaCBvZiBgYXJyYXlgIHRvIGRldGVybWluZSB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYFxuICAgICAqIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHJldEhpZ2hlc3QpIHtcbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IGxvdztcblxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA9PT0gdmFsdWUgJiYgaGlnaCA8PSBIQUxGX01BWF9BUlJBWV9MRU5HVEgpIHtcbiAgICAgICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAgICAgICB2YXIgbWlkID0gKGxvdyArIGhpZ2gpID4+PiAxLFxuICAgICAgICAgICAgICBjb21wdXRlZCA9IGFycmF5W21pZF07XG5cbiAgICAgICAgICBpZiAoKHJldEhpZ2hlc3QgPyAoY29tcHV0ZWQgPD0gdmFsdWUpIDogKGNvbXB1dGVkIDwgdmFsdWUpKSAmJiBjb21wdXRlZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGlnaCA9IG1pZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhpZ2g7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBpZGVudGl0eSwgcmV0SGlnaGVzdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydGVkSW5kZXhCeWAgYW5kIGBfLnNvcnRlZExhc3RJbmRleEJ5YFxuICAgICAqIHdoaWNoIGludm9rZXMgYGl0ZXJhdGVlYCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZVxuICAgICAqIHRoZWlyIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWQgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaXRlcmF0ZWUsIHJldEhpZ2hlc3QpIHtcbiAgICAgIHZhbHVlID0gaXRlcmF0ZWUodmFsdWUpO1xuXG4gICAgICB2YXIgbG93ID0gMCxcbiAgICAgICAgICBoaWdoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwLFxuICAgICAgICAgIHZhbElzTmFOID0gdmFsdWUgIT09IHZhbHVlLFxuICAgICAgICAgIHZhbElzTnVsbCA9IHZhbHVlID09PSBudWxsLFxuICAgICAgICAgIHZhbElzVW5kZWYgPSB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xuXG4gICAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgICB2YXIgbWlkID0gbmF0aXZlRmxvb3IoKGxvdyArIGhpZ2gpIC8gMiksXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKGFycmF5W21pZF0pLFxuICAgICAgICAgICAgaXNEZWYgPSBjb21wdXRlZCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgaXNSZWZsZXhpdmUgPSBjb21wdXRlZCA9PT0gY29tcHV0ZWQ7XG5cbiAgICAgICAgaWYgKHZhbElzTmFOKSB7XG4gICAgICAgICAgdmFyIHNldExvdyA9IGlzUmVmbGV4aXZlIHx8IHJldEhpZ2hlc3Q7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsSXNOdWxsKSB7XG4gICAgICAgICAgc2V0TG93ID0gaXNSZWZsZXhpdmUgJiYgaXNEZWYgJiYgKHJldEhpZ2hlc3QgfHwgY29tcHV0ZWQgIT0gbnVsbCk7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsSXNVbmRlZikge1xuICAgICAgICAgIHNldExvdyA9IGlzUmVmbGV4aXZlICYmIChyZXRIaWdoZXN0IHx8IGlzRGVmKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb21wdXRlZCA9PSBudWxsKSB7XG4gICAgICAgICAgc2V0TG93ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0TG93ID0gcmV0SGlnaGVzdCA/IChjb21wdXRlZCA8PSB2YWx1ZSkgOiAoY29tcHV0ZWQgPCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldExvdykge1xuICAgICAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaGlnaCA9IG1pZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZU1pbihoaWdoLCBNQVhfQVJSQVlfSU5ERVgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZFVuaXFgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU29ydGVkVW5pcShhcnJheSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRVbmlxQnkoYXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZFVuaXFCeWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgICAqIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZHVwbGljYXRlIGZyZWUgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVNvcnRlZFVuaXFCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBpbmRleCA9IDAsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHZhbHVlID0gYXJyYXlbMF0sXG4gICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlLFxuICAgICAgICAgIHNlZW4gPSBjb21wdXRlZCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW3ZhbHVlXTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSkgOiB2YWx1ZTtcblxuICAgICAgICBpZiAoIWVxKGNvbXB1dGVkLCBzZWVuKSkge1xuICAgICAgICAgIHNlZW4gPSBjb21wdXRlZDtcbiAgICAgICAgICByZXN1bHRbKytyZXNJbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bmlxQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVW5pcShhcnJheSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlcyxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgaXNDb21tb24gPSB0cnVlLFxuICAgICAgICAgIHJlc3VsdCA9IFtdLFxuICAgICAgICAgIHNlZW4gPSByZXN1bHQ7XG5cbiAgICAgIGlmIChjb21wYXJhdG9yKSB7XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlc1dpdGg7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChsZW5ndGggPj0gTEFSR0VfQVJSQVlfU0laRSkge1xuICAgICAgICB2YXIgc2V0ID0gaXRlcmF0ZWUgPyBudWxsIDogY3JlYXRlU2V0KGFycmF5KTtcbiAgICAgICAgaWYgKHNldCkge1xuICAgICAgICAgIHJldHVybiBzZXRUb0FycmF5KHNldCk7XG4gICAgICAgIH1cbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgaW5jbHVkZXMgPSBjYWNoZUhhcztcbiAgICAgICAgc2VlbiA9IG5ldyBTZXRDYWNoZTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBzZWVuID0gaXRlcmF0ZWUgPyBbXSA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIGlmIChpc0NvbW1vbiAmJiBjb21wdXRlZCA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICB2YXIgc2VlbkluZGV4ID0gc2Vlbi5sZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHNlZW5JbmRleC0tKSB7XG4gICAgICAgICAgICBpZiAoc2VlbltzZWVuSW5kZXhdID09PSBjb21wdXRlZCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIWluY2x1ZGVzKHNlZW4sIGNvbXB1dGVkLCBjb21wYXJhdG9yKSkge1xuICAgICAgICAgIGlmIChzZWVuICE9PSByZXN1bHQpIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bnNldGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHVuc2V0LlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgaXMgZGVsZXRlZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VVbnNldChvYmplY3QsIHBhdGgpIHtcbiAgICAgIHBhdGggPSBpc0tleShwYXRoLCBvYmplY3QpID8gW3BhdGggKyAnJ10gOiBiYXNlQ2FzdFBhdGgocGF0aCk7XG4gICAgICBvYmplY3QgPSBwYXJlbnQob2JqZWN0LCBwYXRoKTtcbiAgICAgIHZhciBrZXkgPSBsYXN0KHBhdGgpO1xuICAgICAgcmV0dXJuIChvYmplY3QgIT0gbnVsbCAmJiBoYXMob2JqZWN0LCBrZXkpKSA/IGRlbGV0ZSBvYmplY3Rba2V5XSA6IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmRyb3BXaGlsZWAgYW5kIGBfLnRha2VXaGlsZWBcbiAgICAgKiB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0Ryb3BdIFNwZWNpZnkgZHJvcHBpbmcgZWxlbWVudHMgaW5zdGVhZCBvZiB0YWtpbmcgdGhlbS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVdoaWxlKGFycmF5LCBwcmVkaWNhdGUsIGlzRHJvcCwgZnJvbVJpZ2h0KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTE7XG5cbiAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpICYmXG4gICAgICAgIHByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHt9XG5cbiAgICAgIHJldHVybiBpc0Ryb3BcbiAgICAgICAgPyBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyAwIDogaW5kZXgpLCAoZnJvbVJpZ2h0ID8gaW5kZXggKyAxIDogbGVuZ3RoKSlcbiAgICAgICAgOiBiYXNlU2xpY2UoYXJyYXksIChmcm9tUmlnaHQgPyBpbmRleCArIDEgOiAwKSwgKGZyb21SaWdodCA/IGxlbmd0aCA6IGluZGV4KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHdyYXBwZXJWYWx1ZWAgd2hpY2ggcmV0dXJucyB0aGUgcmVzdWx0IG9mXG4gICAgICogcGVyZm9ybWluZyBhIHNlcXVlbmNlIG9mIGFjdGlvbnMgb24gdGhlIHVud3JhcHBlZCBgdmFsdWVgLCB3aGVyZSBlYWNoXG4gICAgICogc3VjY2Vzc2l2ZSBhY3Rpb24gaXMgc3VwcGxpZWQgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgcHJldmlvdXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhY3Rpb25zIEFjdGlvbnMgdG8gcGVyZm9ybSB0byByZXNvbHZlIHRoZSB1bndyYXBwZWQgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VXcmFwcGVyVmFsdWUodmFsdWUsIGFjdGlvbnMpIHtcbiAgICAgIHZhciByZXN1bHQgPSB2YWx1ZTtcbiAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudmFsdWUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheVJlZHVjZShhY3Rpb25zLCBmdW5jdGlvbihyZXN1bHQsIGFjdGlvbikge1xuICAgICAgICByZXR1cm4gYWN0aW9uLmZ1bmMuYXBwbHkoYWN0aW9uLnRoaXNBcmcsIGFycmF5UHVzaChbcmVzdWx0XSwgYWN0aW9uLmFyZ3MpKTtcbiAgICAgIH0sIHJlc3VsdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLnhvcmAsIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLCB0aGF0IGFjY2VwdHMgYW4gYXJyYXkgb2YgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5cyBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiB2YWx1ZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVhvcihhcnJheXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheXMubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gcmVzdWx0XG4gICAgICAgICAgPyBhcnJheVB1c2goXG4gICAgICAgICAgICAgIGJhc2VEaWZmZXJlbmNlKHJlc3VsdCwgYXJyYXlzW2luZGV4XSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpLFxuICAgICAgICAgICAgICBiYXNlRGlmZmVyZW5jZShhcnJheXNbaW5kZXhdLCByZXN1bHQsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKVxuICAgICAgICAgICAgKVxuICAgICAgICAgIDogYXJyYXlzW2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAocmVzdWx0ICYmIHJlc3VsdC5sZW5ndGgpID8gYmFzZVVuaXEocmVzdWx0LCBpdGVyYXRlZSwgY29tcGFyYXRvcikgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uemlwT2JqZWN0YCB3aGljaCBhc3NpZ25zIHZhbHVlcyB1c2luZyBgYXNzaWduRnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBhc3NpZ25GdW5jIFRoZSBmdW5jdGlvbiB0byBhc3NpZ24gdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVppcE9iamVjdChwcm9wcywgdmFsdWVzLCBhc3NpZ25GdW5jKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgdmFsc0xlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGFzc2lnbkZ1bmMocmVzdWx0LCBwcm9wc1tpbmRleF0sIGluZGV4IDwgdmFsc0xlbmd0aCA/IHZhbHVlc1tpbmRleF0gOiB1bmRlZmluZWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgIGBidWZmZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0J1ZmZlcn0gYnVmZmVyIFRoZSBidWZmZXIgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYnVmZmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lQnVmZmVyKGJ1ZmZlciwgaXNEZWVwKSB7XG4gICAgICBpZiAoaXNEZWVwKSB7XG4gICAgICAgIHJldHVybiBidWZmZXIuc2xpY2UoKTtcbiAgICAgIH1cbiAgICAgIHZhciBDdG9yID0gYnVmZmVyLmNvbnN0cnVjdG9yLFxuICAgICAgICAgIHJlc3VsdCA9IG5ldyBDdG9yKGJ1ZmZlci5sZW5ndGgpO1xuXG4gICAgICBidWZmZXIuY29weShyZXN1bHQpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYGFycmF5QnVmZmVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheUJ1ZmZlcn0gYXJyYXlCdWZmZXIgVGhlIGFycmF5IGJ1ZmZlciB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXlCdWZmZXJ9IFJldHVybnMgdGhlIGNsb25lZCBhcnJheSBidWZmZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVBcnJheUJ1ZmZlcihhcnJheUJ1ZmZlcikge1xuICAgICAgdmFyIEN0b3IgPSBhcnJheUJ1ZmZlci5jb25zdHJ1Y3RvcixcbiAgICAgICAgICByZXN1bHQgPSBuZXcgQ3RvcihhcnJheUJ1ZmZlci5ieXRlTGVuZ3RoKSxcbiAgICAgICAgICB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkocmVzdWx0KTtcblxuICAgICAgdmlldy5zZXQobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGBtYXBgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIG1hcC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZU1hcChtYXApIHtcbiAgICAgIHZhciBDdG9yID0gbWFwLmNvbnN0cnVjdG9yO1xuICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKG1hcFRvQXJyYXkobWFwKSwgYWRkTWFwRW50cnksIG5ldyBDdG9yKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHJlZ2V4cGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByZWdleHAgVGhlIHJlZ2V4cCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgcmVnZXhwLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lUmVnRXhwKHJlZ2V4cCkge1xuICAgICAgdmFyIEN0b3IgPSByZWdleHAuY29uc3RydWN0b3IsXG4gICAgICAgICAgcmVzdWx0ID0gbmV3IEN0b3IocmVnZXhwLnNvdXJjZSwgcmVGbGFncy5leGVjKHJlZ2V4cCkpO1xuXG4gICAgICByZXN1bHQubGFzdEluZGV4ID0gcmVnZXhwLmxhc3RJbmRleDtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGBzZXRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc2V0IFRoZSBzZXQgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHNldC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVNldChzZXQpIHtcbiAgICAgIHZhciBDdG9yID0gc2V0LmNvbnN0cnVjdG9yO1xuICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKHNldFRvQXJyYXkoc2V0KSwgYWRkU2V0RW50cnksIG5ldyBDdG9yKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGBzeW1ib2xgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHN5bWJvbCBUaGUgc3ltYm9sIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgc3ltYm9sIG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVN5bWJvbChzeW1ib2wpIHtcbiAgICAgIHJldHVybiBTeW1ib2wgPyBPYmplY3Qoc3ltYm9sVmFsdWVPZi5jYWxsKHN5bWJvbCkpIDoge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGB0eXBlZEFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHR5cGVkQXJyYXkgVGhlIHR5cGVkIGFycmF5IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHR5cGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lVHlwZWRBcnJheSh0eXBlZEFycmF5LCBpc0RlZXApIHtcbiAgICAgIHZhciBhcnJheUJ1ZmZlciA9IHR5cGVkQXJyYXkuYnVmZmVyLFxuICAgICAgICAgIGJ1ZmZlciA9IGlzRGVlcCA/IGNsb25lQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIpIDogYXJyYXlCdWZmZXIsXG4gICAgICAgICAgQ3RvciA9IHR5cGVkQXJyYXkuY29uc3RydWN0b3I7XG5cbiAgICAgIHJldHVybiBuZXcgQ3RvcihidWZmZXIsIHR5cGVkQXJyYXkuYnl0ZU9mZnNldCwgdHlwZWRBcnJheS5sZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLFxuICAgICAqIHBsYWNlaG9sZGVycywgYW5kIHByb3ZpZGVkIGFyZ3VtZW50cyBpbnRvIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGFyZ3MgVGhlIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXJ0aWFscyBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQuXG4gICAgICogQHBhcmFtIHtBcnJheX0gaG9sZGVycyBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbXMge2Jvb2xlYW59IFtpc0N1cnJpZWRdIFNwZWNpZnkgY29tcG9zaW5nIGZvciBhIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tcG9zZWQgYXJndW1lbnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBvc2VBcmdzKGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpIHtcbiAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gYXJncy5sZW5ndGgsXG4gICAgICAgICAgaG9sZGVyc0xlbmd0aCA9IGhvbGRlcnMubGVuZ3RoLFxuICAgICAgICAgIGxlZnRJbmRleCA9IC0xLFxuICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgcmFuZ2VMZW5ndGggPSBuYXRpdmVNYXgoYXJnc0xlbmd0aCAtIGhvbGRlcnNMZW5ndGgsIDApLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlZnRMZW5ndGggKyByYW5nZUxlbmd0aCksXG4gICAgICAgICAgaXNVbmN1cnJpZWQgPSAhaXNDdXJyaWVkO1xuXG4gICAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2FyZ3NJbmRleCA8IGhvbGRlcnNMZW5ndGgpIHtcbiAgICAgICAgaWYgKGlzVW5jdXJyaWVkIHx8IGFyZ3NJbmRleCA8IGFyZ3NMZW5ndGgpIHtcbiAgICAgICAgICByZXN1bHRbaG9sZGVyc1thcmdzSW5kZXhdXSA9IGFyZ3NbYXJnc0luZGV4XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2hpbGUgKHJhbmdlTGVuZ3RoLS0pIHtcbiAgICAgICAgcmVzdWx0W2xlZnRJbmRleCsrXSA9IGFyZ3NbYXJnc0luZGV4KytdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGNvbXBvc2VBcmdzYCBleGNlcHQgdGhhdCB0aGUgYXJndW1lbnRzIGNvbXBvc2l0aW9uXG4gICAgICogaXMgdGFpbG9yZWQgZm9yIGBfLnBhcnRpYWxSaWdodGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBhcmdzIFRoZSBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFydGlhbHMgVGhlIGFyZ3VtZW50cyB0byBhcHBlbmQgdG8gdGhvc2UgcHJvdmlkZWQuXG4gICAgICogQHBhcmFtIHtBcnJheX0gaG9sZGVycyBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbXMge2Jvb2xlYW59IFtpc0N1cnJpZWRdIFNwZWNpZnkgY29tcG9zaW5nIGZvciBhIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tcG9zZWQgYXJndW1lbnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBvc2VBcmdzUmlnaHQoYXJncywgcGFydGlhbHMsIGhvbGRlcnMsIGlzQ3VycmllZCkge1xuICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgIGFyZ3NMZW5ndGggPSBhcmdzLmxlbmd0aCxcbiAgICAgICAgICBob2xkZXJzSW5kZXggPSAtMSxcbiAgICAgICAgICBob2xkZXJzTGVuZ3RoID0gaG9sZGVycy5sZW5ndGgsXG4gICAgICAgICAgcmlnaHRJbmRleCA9IC0xLFxuICAgICAgICAgIHJpZ2h0TGVuZ3RoID0gcGFydGlhbHMubGVuZ3RoLFxuICAgICAgICAgIHJhbmdlTGVuZ3RoID0gbmF0aXZlTWF4KGFyZ3NMZW5ndGggLSBob2xkZXJzTGVuZ3RoLCAwKSxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShyYW5nZUxlbmd0aCArIHJpZ2h0TGVuZ3RoKSxcbiAgICAgICAgICBpc1VuY3VycmllZCA9ICFpc0N1cnJpZWQ7XG5cbiAgICAgIHdoaWxlICgrK2FyZ3NJbmRleCA8IHJhbmdlTGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFthcmdzSW5kZXhdID0gYXJnc1thcmdzSW5kZXhdO1xuICAgICAgfVxuICAgICAgdmFyIG9mZnNldCA9IGFyZ3NJbmRleDtcbiAgICAgIHdoaWxlICgrK3JpZ2h0SW5kZXggPCByaWdodExlbmd0aCkge1xuICAgICAgICByZXN1bHRbb2Zmc2V0ICsgcmlnaHRJbmRleF0gPSBwYXJ0aWFsc1tyaWdodEluZGV4XTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2hvbGRlcnNJbmRleCA8IGhvbGRlcnNMZW5ndGgpIHtcbiAgICAgICAgaWYgKGlzVW5jdXJyaWVkIHx8IGFyZ3NJbmRleCA8IGFyZ3NMZW5ndGgpIHtcbiAgICAgICAgICByZXN1bHRbb2Zmc2V0ICsgaG9sZGVyc1tob2xkZXJzSW5kZXhdXSA9IGFyZ3NbYXJnc0luZGV4KytdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyB0aGUgdmFsdWVzIG9mIGBzb3VyY2VgIHRvIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHNvdXJjZSBUaGUgYXJyYXkgdG8gY29weSB2YWx1ZXMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXk9W11dIFRoZSBhcnJheSB0byBjb3B5IHZhbHVlcyB0by5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb3B5QXJyYXkoc291cmNlLCBhcnJheSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gc291cmNlLmxlbmd0aDtcblxuICAgICAgYXJyYXkgfHwgKGFycmF5ID0gQXJyYXkobGVuZ3RoKSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBhcnJheVtpbmRleF0gPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHRvIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20uXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGNvcHkuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3Q9e31dIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIHRvLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29weU9iamVjdChzb3VyY2UsIHByb3BzLCBvYmplY3QpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0V2l0aChzb3VyY2UsIHByb3BzLCBvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgY29weU9iamVjdGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhIGZ1bmN0aW9uIHRvXG4gICAgICogY3VzdG9taXplIGNvcGllZCB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gY29weS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29waWVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlPYmplY3RXaXRoKHNvdXJjZSwgcHJvcHMsIG9iamVjdCwgY3VzdG9taXplcikge1xuICAgICAgb2JqZWN0IHx8IChvYmplY3QgPSB7fSk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGtleSA9IHByb3BzW2luZGV4XTtcblxuICAgICAgICB2YXIgbmV3VmFsdWUgPSBjdXN0b21pemVyXG4gICAgICAgICAgPyBjdXN0b21pemVyKG9iamVjdFtrZXldLCBzb3VyY2Vba2V5XSwga2V5LCBvYmplY3QsIHNvdXJjZSlcbiAgICAgICAgICA6IHNvdXJjZVtrZXldO1xuXG4gICAgICAgIGFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyBvd24gc3ltYm9sIHByb3BlcnRpZXMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgdG8uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb3B5U3ltYm9scyhzb3VyY2UsIG9iamVjdCkge1xuICAgICAgcmV0dXJuIGNvcHlPYmplY3Qoc291cmNlLCBnZXRTeW1ib2xzKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uZ3JvdXBCeWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGFjY3VtdWxhdG9yIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaW5pdGlhbGl6ZXJdIFRoZSBhY2N1bXVsYXRvciBvYmplY3QgaW5pdGlhbGl6ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWdncmVnYXRvciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVBZ2dyZWdhdG9yKHNldHRlciwgaW5pdGlhbGl6ZXIpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUFnZ3JlZ2F0b3IgOiBiYXNlQWdncmVnYXRvcixcbiAgICAgICAgICAgIGFjY3VtdWxhdG9yID0gaW5pdGlhbGl6ZXIgPyBpbml0aWFsaXplcigpIDoge307XG5cbiAgICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgc2V0dGVyLCBnZXRJdGVyYXRlZShpdGVyYXRlZSksIGFjY3VtdWxhdG9yKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uYXNzaWduYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXNzaWduZXIgVGhlIGZ1bmN0aW9uIHRvIGFzc2lnbiB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYXNzaWduZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQXNzaWduZXIoYXNzaWduZXIpIHtcbiAgICAgIHJldHVybiByZXN0KGZ1bmN0aW9uKG9iamVjdCwgc291cmNlcykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IHNvdXJjZXMubGVuZ3RoLFxuICAgICAgICAgICAgY3VzdG9taXplciA9IGxlbmd0aCA+IDEgPyBzb3VyY2VzW2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZ3VhcmQgPSBsZW5ndGggPiAyID8gc291cmNlc1syXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJ1xuICAgICAgICAgID8gKGxlbmd0aC0tLCBjdXN0b21pemVyKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChzb3VyY2VzWzBdLCBzb3VyY2VzWzFdLCBndWFyZCkpIHtcbiAgICAgICAgICBjdXN0b21pemVyID0gbGVuZ3RoIDwgMyA/IHVuZGVmaW5lZCA6IGN1c3RvbWl6ZXI7XG4gICAgICAgICAgbGVuZ3RoID0gMTtcbiAgICAgICAgfVxuICAgICAgICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgc291cmNlID0gc291cmNlc1tpbmRleF07XG4gICAgICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICAgICAgYXNzaWduZXIob2JqZWN0LCBzb3VyY2UsIGluZGV4LCBjdXN0b21pemVyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgYmFzZUVhY2hgIG9yIGBiYXNlRWFjaFJpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBhIGNvbGxlY3Rpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYmFzZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVCYXNlRWFjaChlYWNoRnVuYywgZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNBcnJheUxpa2UoY29sbGVjdGlvbikpIHtcbiAgICAgICAgICByZXR1cm4gZWFjaEZ1bmMoY29sbGVjdGlvbiwgaXRlcmF0ZWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aCxcbiAgICAgICAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTEsXG4gICAgICAgICAgICBpdGVyYWJsZSA9IE9iamVjdChjb2xsZWN0aW9uKTtcblxuICAgICAgICB3aGlsZSAoKGZyb21SaWdodCA/IGluZGV4LS0gOiArK2luZGV4IDwgbGVuZ3RoKSkge1xuICAgICAgICAgIGlmIChpdGVyYXRlZShpdGVyYWJsZVtpbmRleF0sIGluZGV4LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBiYXNlIGZ1bmN0aW9uIGZvciBtZXRob2RzIGxpa2UgYF8uZm9ySW5gLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VGb3IoZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0LCBpdGVyYXRlZSwga2V5c0Z1bmMpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBpdGVyYWJsZSA9IE9iamVjdChvYmplY3QpLFxuICAgICAgICAgICAgcHJvcHMgPSBrZXlzRnVuYyhvYmplY3QpLFxuICAgICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICAgIHZhciBrZXkgPSBwcm9wc1tmcm9tUmlnaHQgPyBsZW5ndGggOiArK2luZGV4XTtcbiAgICAgICAgICBpZiAoaXRlcmF0ZWUoaXRlcmFibGVba2V5XSwga2V5LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIHRoZSBvcHRpb25hbCBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIGB0aGlzQXJnYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBvZiB3cmFwcGVyIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBwZXJgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpc0JpbmQgPSBiaXRtYXNrICYgQklORF9GTEFHLFxuICAgICAgICAgIEN0b3IgPSBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGZuID0gKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8ubG93ZXJGaXJzdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBgU3RyaW5nYCBjYXNlIG1ldGhvZCB0byB1c2UuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ2FzZUZpcnN0KG1ldGhvZE5hbWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcblxuICAgICAgICB2YXIgc3RyU3ltYm9scyA9IHJlSGFzQ29tcGxleFN5bWJvbC50ZXN0KHN0cmluZylcbiAgICAgICAgICA/IHN0cmluZ1RvQXJyYXkoc3RyaW5nKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIHZhciBjaHIgPSBzdHJTeW1ib2xzID8gc3RyU3ltYm9sc1swXSA6IHN0cmluZy5jaGFyQXQoMCksXG4gICAgICAgICAgICB0cmFpbGluZyA9IHN0clN5bWJvbHMgPyBzdHJTeW1ib2xzLnNsaWNlKDEpLmpvaW4oJycpIDogc3RyaW5nLnNsaWNlKDEpO1xuXG4gICAgICAgIHJldHVybiBjaHJbbWV0aG9kTmFtZV0oKSArIHRyYWlsaW5nO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5jYW1lbENhc2VgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gY29tYmluZSBlYWNoIHdvcmQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY29tcG91bmRlciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDb21wb3VuZGVyKGNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBhcnJheVJlZHVjZSh3b3JkcyhkZWJ1cnIoc3RyaW5nKSksIGNhbGxiYWNrLCAnJyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGluc3RhbmNlIG9mIGBDdG9yYCByZWdhcmRsZXNzIG9mXG4gICAgICogd2hldGhlciBpdCB3YXMgaW52b2tlZCBhcyBwYXJ0IG9mIGEgYG5ld2AgZXhwcmVzc2lvbiBvciBieSBgY2FsbGAgb3IgYGFwcGx5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gQ3RvciBUaGUgY29uc3RydWN0b3IgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUN0b3JXcmFwcGVyKEN0b3IpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gVXNlIGEgYHN3aXRjaGAgc3RhdGVtZW50IHRvIHdvcmsgd2l0aCBjbGFzcyBjb25zdHJ1Y3RvcnMuXG4gICAgICAgIC8vIFNlZSBodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1lY21hc2NyaXB0LWZ1bmN0aW9uLW9iamVjdHMtY2FsbC10aGlzYXJndW1lbnQtYXJndW1lbnRzbGlzdFxuICAgICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIGNhc2UgMDogcmV0dXJuIG5ldyBDdG9yO1xuICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0pO1xuICAgICAgICAgIGNhc2UgMjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgICAgICAgIGNhc2UgMzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICAgIGNhc2UgNDogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pO1xuICAgICAgICAgIGNhc2UgNTogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0pO1xuICAgICAgICAgIGNhc2UgNjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pO1xuICAgICAgICAgIGNhc2UgNzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0sIGFyZ3NbNl0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aGlzQmluZGluZyA9IGJhc2VDcmVhdGUoQ3Rvci5wcm90b3R5cGUpLFxuICAgICAgICAgICAgcmVzdWx0ID0gQ3Rvci5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG5cbiAgICAgICAgLy8gTWltaWMgdGhlIGNvbnN0cnVjdG9yJ3MgYHJldHVybmAgYmVoYXZpb3IuXG4gICAgICAgIC8vIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxMy4yLjIgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHJlc3VsdCkgPyByZXN1bHQgOiB0aGlzQmluZGluZztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGVuYWJsZSBjdXJyeWluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBvZiB3cmFwcGVyIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBwZXJgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGFyaXR5IFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDdXJyeVdyYXBwZXIoZnVuYywgYml0bWFzaywgYXJpdHkpIHtcbiAgICAgIHZhciBDdG9yID0gY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICAgICAgYXJncyA9IEFycmF5KGxlbmd0aCksXG4gICAgICAgICAgICBpbmRleCA9IGxlbmd0aCxcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyID0gZ2V0UGxhY2Vob2xkZXIod3JhcHBlcik7XG5cbiAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhvbGRlcnMgPSAobGVuZ3RoIDwgMyAmJiBhcmdzWzBdICE9PSBwbGFjZWhvbGRlciAmJiBhcmdzW2xlbmd0aCAtIDFdICE9PSBwbGFjZWhvbGRlcilcbiAgICAgICAgICA/IFtdXG4gICAgICAgICAgOiByZXBsYWNlSG9sZGVycyhhcmdzLCBwbGFjZWhvbGRlcik7XG5cbiAgICAgICAgbGVuZ3RoIC09IGhvbGRlcnMubGVuZ3RoO1xuICAgICAgICBpZiAobGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlUmVjdXJyeVdyYXBwZXIoXG4gICAgICAgICAgICBmdW5jLCBiaXRtYXNrLCBjcmVhdGVIeWJyaWRXcmFwcGVyLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB1bmRlZmluZWQsXG4gICAgICAgICAgICBhcmdzLCBob2xkZXJzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkgLSBsZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IHJvb3QgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgICAgIHJldHVybiBhcHBseShmbiwgdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZmxvd2Agb3IgYF8uZmxvd1JpZ2h0YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZmxvdyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVGbG93KGZyb21SaWdodCkge1xuICAgICAgcmV0dXJuIHJlc3QoZnVuY3Rpb24oZnVuY3MpIHtcbiAgICAgICAgZnVuY3MgPSBiYXNlRmxhdHRlbihmdW5jcywgMSk7XG5cbiAgICAgICAgdmFyIGxlbmd0aCA9IGZ1bmNzLmxlbmd0aCxcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICAgICAgcHJlcmVxID0gTG9kYXNoV3JhcHBlci5wcm90b3R5cGUudGhydTtcblxuICAgICAgICBpZiAoZnJvbVJpZ2h0KSB7XG4gICAgICAgICAgZnVuY3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgdmFyIGZ1bmMgPSBmdW5jc1tpbmRleF07XG4gICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByZXJlcSAmJiAhd3JhcHBlciAmJiBnZXRGdW5jTmFtZShmdW5jKSA9PSAnd3JhcHBlcicpIHtcbiAgICAgICAgICAgIHZhciB3cmFwcGVyID0gbmV3IExvZGFzaFdyYXBwZXIoW10sIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IHdyYXBwZXIgPyBpbmRleCA6IGxlbmd0aDtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBmdW5jID0gZnVuY3NbaW5kZXhdO1xuXG4gICAgICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgICAgIGRhdGEgPSBmdW5jTmFtZSA9PSAnd3JhcHBlcicgPyBnZXREYXRhKGZ1bmMpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKGRhdGEgJiYgaXNMYXppYWJsZShkYXRhWzBdKSAmJlxuICAgICAgICAgICAgICAgIGRhdGFbMV0gPT0gKEFSWV9GTEFHIHwgQ1VSUllfRkxBRyB8IFBBUlRJQUxfRkxBRyB8IFJFQVJHX0ZMQUcpICYmXG4gICAgICAgICAgICAgICAgIWRhdGFbNF0ubGVuZ3RoICYmIGRhdGFbOV0gPT0gMVxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgIHdyYXBwZXIgPSB3cmFwcGVyW2dldEZ1bmNOYW1lKGRhdGFbMF0pXS5hcHBseSh3cmFwcGVyLCBkYXRhWzNdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JhcHBlciA9IChmdW5jLmxlbmd0aCA9PSAxICYmIGlzTGF6aWFibGUoZnVuYykpID8gd3JhcHBlcltmdW5jTmFtZV0oKSA6IHdyYXBwZXIudGhydShmdW5jKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAgICB2YWx1ZSA9IGFyZ3NbMF07XG5cbiAgICAgICAgICBpZiAod3JhcHBlciAmJiBhcmdzLmxlbmd0aCA9PSAxICYmXG4gICAgICAgICAgICAgIGlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+PSBMQVJHRV9BUlJBWV9TSVpFKSB7XG4gICAgICAgICAgICByZXR1cm4gd3JhcHBlci5wbGFudCh2YWx1ZSkudmFsdWUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICAgICAgcmVzdWx0ID0gbGVuZ3RoID8gZnVuY3NbaW5kZXhdLmFwcGx5KHRoaXMsIGFyZ3MpIDogdmFsdWU7XG5cbiAgICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuY3NbaW5kZXhdLmNhbGwodGhpcywgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCB0byBpbnZva2UgaXQgd2l0aCBvcHRpb25hbCBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIGB0aGlzQXJnYCwgcGFydGlhbCBhcHBsaWNhdGlvbiwgYW5kIGN1cnJ5aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBvZiB3cmFwcGVyIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBwZXJgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzXSBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc1JpZ2h0XSBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzUmlnaHRdIFRoZSBgcGFydGlhbHNSaWdodGAgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVIeWJyaWRXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQXJ5ID0gYml0bWFzayAmIEFSWV9GTEFHLFxuICAgICAgICAgIGlzQmluZCA9IGJpdG1hc2sgJiBCSU5EX0ZMQUcsXG4gICAgICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIEJJTkRfS0VZX0ZMQUcsXG4gICAgICAgICAgaXNDdXJyaWVkID0gYml0bWFzayAmIChDVVJSWV9GTEFHIHwgQ1VSUllfUklHSFRfRkxBRyksXG4gICAgICAgICAgaXNGbGlwID0gYml0bWFzayAmIEZMSVBfRkxBRyxcbiAgICAgICAgICBDdG9yID0gaXNCaW5kS2V5ID8gdW5kZWZpbmVkIDogY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG5cbiAgICAgIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICAgICAgaW5kZXggPSBsZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVuZ3RoKTtcblxuICAgICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICAgIGFyZ3NbaW5kZXhdID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNDdXJyaWVkKSB7XG4gICAgICAgICAgdmFyIHBsYWNlaG9sZGVyID0gZ2V0UGxhY2Vob2xkZXIod3JhcHBlciksXG4gICAgICAgICAgICAgIGhvbGRlcnNDb3VudCA9IGNvdW50SG9sZGVycyhhcmdzLCBwbGFjZWhvbGRlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRpYWxzKSB7XG4gICAgICAgICAgYXJncyA9IGNvbXBvc2VBcmdzKGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJ0aWFsc1JpZ2h0KSB7XG4gICAgICAgICAgYXJncyA9IGNvbXBvc2VBcmdzUmlnaHQoYXJncywgcGFydGlhbHNSaWdodCwgaG9sZGVyc1JpZ2h0LCBpc0N1cnJpZWQpO1xuICAgICAgICB9XG4gICAgICAgIGxlbmd0aCAtPSBob2xkZXJzQ291bnQ7XG4gICAgICAgIGlmIChpc0N1cnJpZWQgJiYgbGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICB2YXIgbmV3SG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcbiAgICAgICAgICByZXR1cm4gY3JlYXRlUmVjdXJyeVdyYXBwZXIoXG4gICAgICAgICAgICBmdW5jLCBiaXRtYXNrLCBjcmVhdGVIeWJyaWRXcmFwcGVyLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB0aGlzQXJnLFxuICAgICAgICAgICAgYXJncywgbmV3SG9sZGVycywgYXJnUG9zLCBhcnksIGFyaXR5IC0gbGVuZ3RoXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGhpc0JpbmRpbmcgPSBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcyxcbiAgICAgICAgICAgIGZuID0gaXNCaW5kS2V5ID8gdGhpc0JpbmRpbmdbZnVuY10gOiBmdW5jO1xuXG4gICAgICAgIGxlbmd0aCA9IGFyZ3MubGVuZ3RoO1xuICAgICAgICBpZiAoYXJnUG9zKSB7XG4gICAgICAgICAgYXJncyA9IHJlb3JkZXIoYXJncywgYXJnUG9zKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0ZsaXAgJiYgbGVuZ3RoID4gMSkge1xuICAgICAgICAgIGFyZ3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0FyeSAmJiBhcnkgPCBsZW5ndGgpIHtcbiAgICAgICAgICBhcmdzLmxlbmd0aCA9IGFyeTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSB7XG4gICAgICAgICAgZm4gPSBDdG9yIHx8IGNyZWF0ZUN0b3JXcmFwcGVyKGZuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpc0JpbmRpbmcsIGFyZ3MpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uaW52ZXJ0QnlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBhY2N1bXVsYXRvciB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdG9JdGVyYXRlZSBUaGUgZnVuY3Rpb24gdG8gcmVzb2x2ZSBpdGVyYXRlZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgaW52ZXJ0ZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlSW52ZXJ0ZXIoc2V0dGVyLCB0b0l0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgICByZXR1cm4gYmFzZUludmVydGVyKG9iamVjdCwgc2V0dGVyLCB0b0l0ZXJhdGVlKGl0ZXJhdGVlKSwge30pO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5vdmVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXJyYXlGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgaXRlcmF0ZWVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGludm9rZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlT3ZlcihhcnJheUZ1bmMpIHtcbiAgICAgIHJldHVybiByZXN0KGZ1bmN0aW9uKGl0ZXJhdGVlcykge1xuICAgICAgICBpdGVyYXRlZXMgPSBhcnJheU1hcChiYXNlRmxhdHRlbihpdGVyYXRlZXMsIDEpLCBnZXRJdGVyYXRlZSgpKTtcbiAgICAgICAgcmV0dXJuIHJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICAgIHZhciB0aGlzQXJnID0gdGhpcztcbiAgICAgICAgICByZXR1cm4gYXJyYXlGdW5jKGl0ZXJhdGVlcywgZnVuY3Rpb24oaXRlcmF0ZWUpIHtcbiAgICAgICAgICAgIHJldHVybiBhcHBseShpdGVyYXRlZSwgdGhpc0FyZywgYXJncyk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgcGFkZGluZyBmb3IgYHN0cmluZ2AgYmFzZWQgb24gYGxlbmd0aGAuIFRoZSBgY2hhcnNgIHN0cmluZ1xuICAgICAqIGlzIHRydW5jYXRlZCBpZiB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlcnMgZXhjZWVkcyBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNyZWF0ZSBwYWRkaW5nIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD0wXSBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRpbmcgZm9yIGBzdHJpbmdgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVBhZGRpbmcoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBsZW5ndGggPSB0b0ludGVnZXIobGVuZ3RoKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IHN0cmluZ1NpemUoc3RyaW5nKTtcbiAgICAgIGlmICghbGVuZ3RoIHx8IHN0ckxlbmd0aCA+PSBsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICAgdmFyIHBhZExlbmd0aCA9IGxlbmd0aCAtIHN0ckxlbmd0aDtcbiAgICAgIGNoYXJzID0gY2hhcnMgPT09IHVuZGVmaW5lZCA/ICcgJyA6IChjaGFycyArICcnKTtcblxuICAgICAgdmFyIHJlc3VsdCA9IHJlcGVhdChjaGFycywgbmF0aXZlQ2VpbChwYWRMZW5ndGggLyBzdHJpbmdTaXplKGNoYXJzKSkpO1xuICAgICAgcmV0dXJuIHJlSGFzQ29tcGxleFN5bWJvbC50ZXN0KGNoYXJzKVxuICAgICAgICA/IHN0cmluZ1RvQXJyYXkocmVzdWx0KS5zbGljZSgwLCBwYWRMZW5ndGgpLmpvaW4oJycpXG4gICAgICAgIDogcmVzdWx0LnNsaWNlKDAsIHBhZExlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIHRoZSBvcHRpb25hbCBgdGhpc2BcbiAgICAgKiBiaW5kaW5nIG9mIGB0aGlzQXJnYCBhbmQgdGhlIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRob3NlIHByb3ZpZGVkIHRvXG4gICAgICogdGhlIHdyYXBwZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2Ygd3JhcHBlciBmbGFncy4gU2VlIGBjcmVhdGVXcmFwcGVyYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFydGlhbFdyYXBwZXIoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBpc0JpbmQgPSBiaXRtYXNrICYgQklORF9GTEFHLFxuICAgICAgICAgIEN0b3IgPSBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBsZWZ0SW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVmdExlbmd0aCArIGFyZ3NMZW5ndGgpLFxuICAgICAgICAgICAgZm4gPSAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSA/IEN0b3IgOiBmdW5jO1xuXG4gICAgICAgIHdoaWxlICgrK2xlZnRJbmRleCA8IGxlZnRMZW5ndGgpIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChhcmdzTGVuZ3RoLS0pIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleCsrXSA9IGFyZ3VtZW50c1srK2FyZ3NJbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFwcGx5KGZuLCBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8ucmFuZ2VgIG9yIGBfLnJhbmdlUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByYW5nZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSYW5nZShmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdGFydCwgZW5kLCBzdGVwKSB7XG4gICAgICAgIGlmIChzdGVwICYmIHR5cGVvZiBzdGVwICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKHN0YXJ0LCBlbmQsIHN0ZXApKSB7XG4gICAgICAgICAgZW5kID0gc3RlcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbnN1cmUgdGhlIHNpZ24gb2YgYC0wYCBpcyBwcmVzZXJ2ZWQuXG4gICAgICAgIHN0YXJ0ID0gdG9OdW1iZXIoc3RhcnQpO1xuICAgICAgICBzdGFydCA9IHN0YXJ0ID09PSBzdGFydCA/IHN0YXJ0IDogMDtcbiAgICAgICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVuZCA9IHRvTnVtYmVyKGVuZCkgfHwgMDtcbiAgICAgICAgfVxuICAgICAgICBzdGVwID0gc3RlcCA9PT0gdW5kZWZpbmVkID8gKHN0YXJ0IDwgZW5kID8gMSA6IC0xKSA6ICh0b051bWJlcihzdGVwKSB8fCAwKTtcbiAgICAgICAgcmV0dXJuIGJhc2VSYW5nZShzdGFydCwgZW5kLCBzdGVwLCBmcm9tUmlnaHQpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gY29udGludWUgY3VycnlpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2Ygd3JhcHBlciBmbGFncy4gU2VlIGBjcmVhdGVXcmFwcGVyYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBGdW5jIFRoZSBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGBmdW5jYCB3cmFwcGVyLlxuICAgICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSZWN1cnJ5V3JhcHBlcihmdW5jLCBiaXRtYXNrLCB3cmFwRnVuYywgcGxhY2Vob2xkZXIsIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBhcmdQb3MsIGFyeSwgYXJpdHkpIHtcbiAgICAgIHZhciBpc0N1cnJ5ID0gYml0bWFzayAmIENVUlJZX0ZMQUcsXG4gICAgICAgICAgbmV3QXJnUG9zID0gYXJnUG9zID8gY29weUFycmF5KGFyZ1BvcykgOiB1bmRlZmluZWQsXG4gICAgICAgICAgbmV3SG9sZGVycyA9IGlzQ3VycnkgPyBob2xkZXJzIDogdW5kZWZpbmVkLFxuICAgICAgICAgIG5ld0hvbGRlcnNSaWdodCA9IGlzQ3VycnkgPyB1bmRlZmluZWQgOiBob2xkZXJzLFxuICAgICAgICAgIG5ld1BhcnRpYWxzID0gaXNDdXJyeSA/IHBhcnRpYWxzIDogdW5kZWZpbmVkLFxuICAgICAgICAgIG5ld1BhcnRpYWxzUmlnaHQgPSBpc0N1cnJ5ID8gdW5kZWZpbmVkIDogcGFydGlhbHM7XG5cbiAgICAgIGJpdG1hc2sgfD0gKGlzQ3VycnkgPyBQQVJUSUFMX0ZMQUcgOiBQQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgYml0bWFzayAmPSB+KGlzQ3VycnkgPyBQQVJUSUFMX1JJR0hUX0ZMQUcgOiBQQVJUSUFMX0ZMQUcpO1xuXG4gICAgICBpZiAoIShiaXRtYXNrICYgQ1VSUllfQk9VTkRfRkxBRykpIHtcbiAgICAgICAgYml0bWFzayAmPSB+KEJJTkRfRkxBRyB8IEJJTkRfS0VZX0ZMQUcpO1xuICAgICAgfVxuICAgICAgdmFyIG5ld0RhdGEgPSBbXG4gICAgICAgIGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIG5ld1BhcnRpYWxzLCBuZXdIb2xkZXJzLCBuZXdQYXJ0aWFsc1JpZ2h0LFxuICAgICAgICBuZXdIb2xkZXJzUmlnaHQsIG5ld0FyZ1BvcywgYXJ5LCBhcml0eVxuICAgICAgXTtcblxuICAgICAgdmFyIHJlc3VsdCA9IHdyYXBGdW5jLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICBpZiAoaXNMYXppYWJsZShmdW5jKSkge1xuICAgICAgICBzZXREYXRhKHJlc3VsdCwgbmV3RGF0YSk7XG4gICAgICB9XG4gICAgICByZXN1bHQucGxhY2Vob2xkZXIgPSBwbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8ucm91bmRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSBUaGUgbmFtZSBvZiB0aGUgYE1hdGhgIG1ldGhvZCB0byB1c2Ugd2hlbiByb3VuZGluZy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByb3VuZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSb3VuZChtZXRob2ROYW1lKSB7XG4gICAgICB2YXIgZnVuYyA9IE1hdGhbbWV0aG9kTmFtZV07XG4gICAgICByZXR1cm4gZnVuY3Rpb24obnVtYmVyLCBwcmVjaXNpb24pIHtcbiAgICAgICAgbnVtYmVyID0gdG9OdW1iZXIobnVtYmVyKTtcbiAgICAgICAgcHJlY2lzaW9uID0gdG9JbnRlZ2VyKHByZWNpc2lvbik7XG4gICAgICAgIGlmIChwcmVjaXNpb24pIHtcbiAgICAgICAgICAvLyBTaGlmdCB3aXRoIGV4cG9uZW50aWFsIG5vdGF0aW9uIHRvIGF2b2lkIGZsb2F0aW5nLXBvaW50IGlzc3Vlcy5cbiAgICAgICAgICAvLyBTZWUgW01ETl0oaHR0cHM6Ly9tZG4uaW8vcm91bmQjRXhhbXBsZXMpIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgICAgdmFyIHBhaXIgPSAodG9TdHJpbmcobnVtYmVyKSArICdlJykuc3BsaXQoJ2UnKSxcbiAgICAgICAgICAgICAgdmFsdWUgPSBmdW5jKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gKyBwcmVjaXNpb24pKTtcblxuICAgICAgICAgIHBhaXIgPSAodG9TdHJpbmcodmFsdWUpICsgJ2UnKS5zcGxpdCgnZScpO1xuICAgICAgICAgIHJldHVybiArKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gLSBwcmVjaXNpb24pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYyhudW1iZXIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2V0IG9mIGB2YWx1ZXNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBhZGQgdG8gdGhlIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgc2V0LlxuICAgICAqL1xuICAgIHZhciBjcmVhdGVTZXQgPSAhKFNldCAmJiBuZXcgU2V0KFsxLCAyXSkuc2l6ZSA9PT0gMikgPyBub29wIDogZnVuY3Rpb24odmFsdWVzKSB7XG4gICAgICByZXR1cm4gbmV3IFNldCh2YWx1ZXMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBlaXRoZXIgY3VycmllcyBvciBpbnZva2VzIGBmdW5jYCB3aXRoIG9wdGlvbmFsXG4gICAgICogYHRoaXNgIGJpbmRpbmcgYW5kIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxzdHJpbmd9IGZ1bmMgVGhlIGZ1bmN0aW9uIG9yIG1ldGhvZCBuYW1lIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2Ygd3JhcHBlciBmbGFncy5cbiAgICAgKiAgVGhlIGJpdG1hc2sgbWF5IGJlIGNvbXBvc2VkIG9mIHRoZSBmb2xsb3dpbmcgZmxhZ3M6XG4gICAgICogICAgIDEgLSBgXy5iaW5kYFxuICAgICAqICAgICAyIC0gYF8uYmluZEtleWBcbiAgICAgKiAgICAgNCAtIGBfLmN1cnJ5YCBvciBgXy5jdXJyeVJpZ2h0YCBvZiBhIGJvdW5kIGZ1bmN0aW9uXG4gICAgICogICAgIDggLSBgXy5jdXJyeWBcbiAgICAgKiAgICAxNiAtIGBfLmN1cnJ5UmlnaHRgXG4gICAgICogICAgMzIgLSBgXy5wYXJ0aWFsYFxuICAgICAqICAgIDY0IC0gYF8ucGFydGlhbFJpZ2h0YFxuICAgICAqICAgMTI4IC0gYF8ucmVhcmdgXG4gICAgICogICAyNTYgLSBgXy5hcnlgXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2hvbGRlcnNdIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ1Bvc10gVGhlIGFyZ3VtZW50IHBvc2l0aW9ucyBvZiB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJ5XSBUaGUgYXJpdHkgY2FwIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5XSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlV3JhcHBlcihmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycywgYXJnUG9zLCBhcnksIGFyaXR5KSB7XG4gICAgICB2YXIgaXNCaW5kS2V5ID0gYml0bWFzayAmIEJJTkRfS0VZX0ZMQUc7XG4gICAgICBpZiAoIWlzQmluZEtleSAmJiB0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBwYXJ0aWFscyA/IHBhcnRpYWxzLmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICBiaXRtYXNrICY9IH4oUEFSVElBTF9GTEFHIHwgUEFSVElBTF9SSUdIVF9GTEFHKTtcbiAgICAgICAgcGFydGlhbHMgPSBob2xkZXJzID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgYXJ5ID0gYXJ5ID09PSB1bmRlZmluZWQgPyBhcnkgOiBuYXRpdmVNYXgodG9JbnRlZ2VyKGFyeSksIDApO1xuICAgICAgYXJpdHkgPSBhcml0eSA9PT0gdW5kZWZpbmVkID8gYXJpdHkgOiB0b0ludGVnZXIoYXJpdHkpO1xuICAgICAgbGVuZ3RoIC09IGhvbGRlcnMgPyBob2xkZXJzLmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmIChiaXRtYXNrICYgUEFSVElBTF9SSUdIVF9GTEFHKSB7XG4gICAgICAgIHZhciBwYXJ0aWFsc1JpZ2h0ID0gcGFydGlhbHMsXG4gICAgICAgICAgICBob2xkZXJzUmlnaHQgPSBob2xkZXJzO1xuXG4gICAgICAgIHBhcnRpYWxzID0gaG9sZGVycyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHZhciBkYXRhID0gaXNCaW5kS2V5ID8gdW5kZWZpbmVkIDogZ2V0RGF0YShmdW5jKTtcblxuICAgICAgdmFyIG5ld0RhdGEgPSBbXG4gICAgICAgIGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsXG4gICAgICAgIGFyZ1BvcywgYXJ5LCBhcml0eVxuICAgICAgXTtcblxuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgbWVyZ2VEYXRhKG5ld0RhdGEsIGRhdGEpO1xuICAgICAgfVxuICAgICAgZnVuYyA9IG5ld0RhdGFbMF07XG4gICAgICBiaXRtYXNrID0gbmV3RGF0YVsxXTtcbiAgICAgIHRoaXNBcmcgPSBuZXdEYXRhWzJdO1xuICAgICAgcGFydGlhbHMgPSBuZXdEYXRhWzNdO1xuICAgICAgaG9sZGVycyA9IG5ld0RhdGFbNF07XG4gICAgICBhcml0eSA9IG5ld0RhdGFbOV0gPSBuZXdEYXRhWzldID09IG51bGxcbiAgICAgICAgPyAoaXNCaW5kS2V5ID8gMCA6IGZ1bmMubGVuZ3RoKVxuICAgICAgICA6IG5hdGl2ZU1heChuZXdEYXRhWzldIC0gbGVuZ3RoLCAwKTtcblxuICAgICAgaWYgKCFhcml0eSAmJiBiaXRtYXNrICYgKENVUlJZX0ZMQUcgfCBDVVJSWV9SSUdIVF9GTEFHKSkge1xuICAgICAgICBiaXRtYXNrICY9IH4oQ1VSUllfRkxBRyB8IENVUlJZX1JJR0hUX0ZMQUcpO1xuICAgICAgfVxuICAgICAgaWYgKCFiaXRtYXNrIHx8IGJpdG1hc2sgPT0gQklORF9GTEFHKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjcmVhdGVCYXNlV3JhcHBlcihmdW5jLCBiaXRtYXNrLCB0aGlzQXJnKTtcbiAgICAgIH0gZWxzZSBpZiAoYml0bWFzayA9PSBDVVJSWV9GTEFHIHx8IGJpdG1hc2sgPT0gQ1VSUllfUklHSFRfRkxBRykge1xuICAgICAgICByZXN1bHQgPSBjcmVhdGVDdXJyeVdyYXBwZXIoZnVuYywgYml0bWFzaywgYXJpdHkpO1xuICAgICAgfSBlbHNlIGlmICgoYml0bWFzayA9PSBQQVJUSUFMX0ZMQUcgfHwgYml0bWFzayA9PSAoQklORF9GTEFHIHwgUEFSVElBTF9GTEFHKSkgJiYgIWhvbGRlcnMubGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZVBhcnRpYWxXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZUh5YnJpZFdyYXBwZXIuYXBwbHkodW5kZWZpbmVkLCBuZXdEYXRhKTtcbiAgICAgIH1cbiAgICAgIHZhciBzZXR0ZXIgPSBkYXRhID8gYmFzZVNldERhdGEgOiBzZXREYXRhO1xuICAgICAgcmV0dXJuIHNldHRlcihyZXN1bHQsIG5ld0RhdGEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgYXJyYXlzIHdpdGggc3VwcG9ydCBmb3JcbiAgICAgKiBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG90aGVyIFRoZSBvdGhlciBhcnJheSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2JpdG1hc2tdIFRoZSBiaXRtYXNrIG9mIGNvbXBhcmlzb24gZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBgYXJyYXlgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBhcnJheXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbEFycmF5cyhhcnJheSwgb3RoZXIsIGVxdWFsRnVuYywgY3VzdG9taXplciwgYml0bWFzaywgc3RhY2spIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBQQVJUSUFMX0NPTVBBUkVfRkxBRyxcbiAgICAgICAgICBpc1Vub3JkZXJlZCA9IGJpdG1hc2sgJiBVTk9SREVSRURfQ09NUEFSRV9GTEFHLFxuICAgICAgICAgIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBvdGhMZW5ndGggPSBvdGhlci5sZW5ndGg7XG5cbiAgICAgIGlmIChhcnJMZW5ndGggIT0gb3RoTGVuZ3RoICYmICEoaXNQYXJ0aWFsICYmIG90aExlbmd0aCA+IGFyckxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gQXNzdW1lIGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgdmFyIHN0YWNrZWQgPSBzdGFjay5nZXQoYXJyYXkpO1xuICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrZWQgPT0gb3RoZXI7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgIHN0YWNrLnNldChhcnJheSwgb3RoZXIpO1xuXG4gICAgICAvLyBJZ25vcmUgbm9uLWluZGV4IHByb3BlcnRpZXMuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGFyckxlbmd0aCkge1xuICAgICAgICB2YXIgYXJyVmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2luZGV4XTtcblxuICAgICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICAgIHZhciBjb21wYXJlZCA9IGlzUGFydGlhbFxuICAgICAgICAgICAgPyBjdXN0b21pemVyKG90aFZhbHVlLCBhcnJWYWx1ZSwgaW5kZXgsIG90aGVyLCBhcnJheSwgc3RhY2spXG4gICAgICAgICAgICA6IGN1c3RvbWl6ZXIoYXJyVmFsdWUsIG90aFZhbHVlLCBpbmRleCwgYXJyYXksIG90aGVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbXBhcmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoY29tcGFyZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBpZiAoaXNVbm9yZGVyZWQpIHtcbiAgICAgICAgICBpZiAoIWFycmF5U29tZShvdGhlciwgZnVuY3Rpb24ob3RoVmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGN1c3RvbWl6ZXIsIGJpdG1hc2ssIHN0YWNrKTtcbiAgICAgICAgICAgICAgfSkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEoYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGN1c3RvbWl6ZXIsIGJpdG1hc2ssIHN0YWNrKSkpIHtcbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgc3RhY2tbJ2RlbGV0ZSddKGFycmF5KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBjb21wYXJpbmcgb2JqZWN0cyBvZlxuICAgICAqIHRoZSBzYW1lIGB0b1N0cmluZ1RhZ2AuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNvbXBhcmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gICAgICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRhZyBUaGUgYHRvU3RyaW5nVGFnYCBvZiB0aGUgb2JqZWN0cyB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2JpdG1hc2tdIFRoZSBiaXRtYXNrIG9mIGNvbXBhcmlzb24gZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXF1YWxCeVRhZyhvYmplY3QsIG90aGVyLCB0YWcsIGVxdWFsRnVuYywgY3VzdG9taXplciwgYml0bWFzaykge1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgICAgICBpZiAoKG9iamVjdC5ieXRlTGVuZ3RoICE9IG90aGVyLmJ5dGVMZW5ndGgpIHx8XG4gICAgICAgICAgICAgICFlcXVhbEZ1bmMobmV3IFVpbnQ4QXJyYXkob2JqZWN0KSwgbmV3IFVpbnQ4QXJyYXkob3RoZXIpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcblxuICAgICAgICBjYXNlIGJvb2xUYWc6XG4gICAgICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgICAgICAvLyBDb2VyY2UgZGF0ZXMgYW5kIGJvb2xlYW5zIHRvIG51bWJlcnMsIGRhdGVzIHRvIG1pbGxpc2Vjb25kcyBhbmQgYm9vbGVhbnNcbiAgICAgICAgICAvLyB0byBgMWAgb3IgYDBgIHRyZWF0aW5nIGludmFsaWQgZGF0ZXMgY29lcmNlZCB0byBgTmFOYCBhcyBub3QgZXF1YWwuXG4gICAgICAgICAgcmV0dXJuICtvYmplY3QgPT0gK290aGVyO1xuXG4gICAgICAgIGNhc2UgZXJyb3JUYWc6XG4gICAgICAgICAgcmV0dXJuIG9iamVjdC5uYW1lID09IG90aGVyLm5hbWUgJiYgb2JqZWN0Lm1lc3NhZ2UgPT0gb3RoZXIubWVzc2FnZTtcblxuICAgICAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgICAgICAvLyBUcmVhdCBgTmFOYCB2cy4gYE5hTmAgYXMgZXF1YWwuXG4gICAgICAgICAgcmV0dXJuIChvYmplY3QgIT0gK29iamVjdCkgPyBvdGhlciAhPSArb3RoZXIgOiBvYmplY3QgPT0gK290aGVyO1xuXG4gICAgICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgICAgICAvLyBDb2VyY2UgcmVnZXhlcyB0byBzdHJpbmdzIGFuZCB0cmVhdCBzdHJpbmdzIHByaW1pdGl2ZXMgYW5kIHN0cmluZ1xuICAgICAgICAgIC8vIG9iamVjdHMgYXMgZXF1YWwuIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxNS4xMC42LjQgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICByZXR1cm4gb2JqZWN0ID09IChvdGhlciArICcnKTtcblxuICAgICAgICBjYXNlIG1hcFRhZzpcbiAgICAgICAgICB2YXIgY29udmVydCA9IG1hcFRvQXJyYXk7XG5cbiAgICAgICAgY2FzZSBzZXRUYWc6XG4gICAgICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBQQVJUSUFMX0NPTVBBUkVfRkxBRztcbiAgICAgICAgICBjb252ZXJ0IHx8IChjb252ZXJ0ID0gc2V0VG9BcnJheSk7XG5cbiAgICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgICByZXR1cm4gKGlzUGFydGlhbCB8fCBvYmplY3Quc2l6ZSA9PSBvdGhlci5zaXplKSAmJlxuICAgICAgICAgICAgZXF1YWxGdW5jKGNvbnZlcnQob2JqZWN0KSwgY29udmVydChvdGhlciksIGN1c3RvbWl6ZXIsIGJpdG1hc2sgfCBVTk9SREVSRURfQ09NUEFSRV9GTEFHKTtcblxuICAgICAgICBjYXNlIHN5bWJvbFRhZzpcbiAgICAgICAgICByZXR1cm4gISFTeW1ib2wgJiYgKHN5bWJvbFZhbHVlT2YuY2FsbChvYmplY3QpID09IHN5bWJvbFZhbHVlT2YuY2FsbChvdGhlcikpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3Igb2JqZWN0cyB3aXRoIHN1cHBvcnQgZm9yXG4gICAgICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2JpdG1hc2tdIFRoZSBiaXRtYXNrIG9mIGNvbXBhcmlzb24gZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxdWFsT2JqZWN0cyhvYmplY3QsIG90aGVyLCBlcXVhbEZ1bmMsIGN1c3RvbWl6ZXIsIGJpdG1hc2ssIHN0YWNrKSB7XG4gICAgICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIFBBUlRJQUxfQ09NUEFSRV9GTEFHLFxuICAgICAgICAgIG9ialByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIG9iakxlbmd0aCA9IG9ialByb3BzLmxlbmd0aCxcbiAgICAgICAgICBvdGhQcm9wcyA9IGtleXMob3RoZXIpLFxuICAgICAgICAgIG90aExlbmd0aCA9IG90aFByb3BzLmxlbmd0aDtcblxuICAgICAgaWYgKG9iakxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIWlzUGFydGlhbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBvYmpMZW5ndGg7XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICB2YXIga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgICAgICBpZiAoIShpc1BhcnRpYWwgPyBrZXkgaW4gb3RoZXIgOiBiYXNlSGFzKG90aGVyLCBrZXkpKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQXNzdW1lIGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICAgICAgdmFyIHN0YWNrZWQgPSBzdGFjay5nZXQob2JqZWN0KTtcbiAgICAgIGlmIChzdGFja2VkKSB7XG4gICAgICAgIHJldHVybiBzdGFja2VkID09IG90aGVyO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG5cbiAgICAgIHZhciBza2lwQ3RvciA9IGlzUGFydGlhbDtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgb2JqTGVuZ3RoKSB7XG4gICAgICAgIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICAgICAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2tleV07XG5cbiAgICAgICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgICAgICB2YXIgY29tcGFyZWQgPSBpc1BhcnRpYWxcbiAgICAgICAgICAgID8gY3VzdG9taXplcihvdGhWYWx1ZSwgb2JqVmFsdWUsIGtleSwgb3RoZXIsIG9iamVjdCwgc3RhY2spXG4gICAgICAgICAgICA6IGN1c3RvbWl6ZXIob2JqVmFsdWUsIG90aFZhbHVlLCBrZXksIG9iamVjdCwgb3RoZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgaWYgKCEoY29tcGFyZWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICA/IChvYmpWYWx1ZSA9PT0gb3RoVmFsdWUgfHwgZXF1YWxGdW5jKG9ialZhbHVlLCBvdGhWYWx1ZSwgY3VzdG9taXplciwgYml0bWFzaywgc3RhY2spKVxuICAgICAgICAgICAgICA6IGNvbXBhcmVkXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc2tpcEN0b3IgfHwgKHNraXBDdG9yID0ga2V5ID09ICdjb25zdHJ1Y3RvcicpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCAmJiAhc2tpcEN0b3IpIHtcbiAgICAgICAgdmFyIG9iakN0b3IgPSBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgICBvdGhDdG9yID0gb3RoZXIuY29uc3RydWN0b3I7XG5cbiAgICAgICAgLy8gTm9uIGBPYmplY3RgIG9iamVjdCBpbnN0YW5jZXMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1YWwuXG4gICAgICAgIGlmIChvYmpDdG9yICE9IG90aEN0b3IgJiZcbiAgICAgICAgICAgICgnY29uc3RydWN0b3InIGluIG9iamVjdCAmJiAnY29uc3RydWN0b3InIGluIG90aGVyKSAmJlxuICAgICAgICAgICAgISh0eXBlb2Ygb2JqQ3RvciA9PSAnZnVuY3Rpb24nICYmIG9iakN0b3IgaW5zdGFuY2VvZiBvYmpDdG9yICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBvdGhDdG9yID09ICdmdW5jdGlvbicgJiYgb3RoQ3RvciBpbnN0YW5jZW9mIG90aEN0b3IpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YWNrWydkZWxldGUnXShvYmplY3QpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBnZXREYXRhID0gIW1ldGFNYXAgPyBub29wIDogZnVuY3Rpb24oZnVuYykge1xuICAgICAgcmV0dXJuIG1ldGFNYXAuZ2V0KGZ1bmMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBuYW1lIG9mIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZnVuY3Rpb24gbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRGdW5jTmFtZShmdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gKGZ1bmMubmFtZSArICcnKSxcbiAgICAgICAgICBhcnJheSA9IHJlYWxOYW1lc1tyZXN1bHRdLFxuICAgICAgICAgIGxlbmd0aCA9IGhhc093blByb3BlcnR5LmNhbGwocmVhbE5hbWVzLCByZXN1bHQpID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBkYXRhID0gYXJyYXlbbGVuZ3RoXSxcbiAgICAgICAgICAgIG90aGVyRnVuYyA9IGRhdGEuZnVuYztcbiAgICAgICAgaWYgKG90aGVyRnVuYyA9PSBudWxsIHx8IG90aGVyRnVuYyA9PSBmdW5jKSB7XG4gICAgICAgICAgcmV0dXJuIGRhdGEubmFtZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhcHByb3ByaWF0ZSBcIml0ZXJhdGVlXCIgZnVuY3Rpb24uIElmIHRoZSBgXy5pdGVyYXRlZWAgbWV0aG9kIGlzXG4gICAgICogY3VzdG9taXplZCB0aGlzIGZ1bmN0aW9uIHJldHVybnMgdGhlIGN1c3RvbSBtZXRob2QsIG90aGVyd2lzZSBpdCByZXR1cm5zXG4gICAgICogYGJhc2VJdGVyYXRlZWAuIElmIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdGhlIGNob3NlbiBmdW5jdGlvbiBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aGVtIGFuZCBpdHMgcmVzdWx0IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFt2YWx1ZV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYW4gaXRlcmF0ZWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIHRoZSBjcmVhdGVkIGl0ZXJhdGVlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY2hvc2VuIGZ1bmN0aW9uIG9yIGl0cyByZXN1bHQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SXRlcmF0ZWUoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoLml0ZXJhdGVlIHx8IGl0ZXJhdGVlO1xuICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSBpdGVyYXRlZSA/IGJhc2VJdGVyYXRlZSA6IHJlc3VsdDtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gcmVzdWx0KGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdKSA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IHZhbHVlIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBhdm9pZCBhIFtKSVQgYnVnXShodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTQyNzkyKVxuICAgICAqIHRoYXQgYWZmZWN0cyBTYWZhcmkgb24gYXQgbGVhc3QgaU9TIDguMS04LjMgQVJNNjQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgXCJsZW5ndGhcIiB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgZ2V0TGVuZ3RoID0gYmFzZVByb3BlcnR5KCdsZW5ndGgnKTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHByb3BlcnR5IG5hbWVzLCB2YWx1ZXMsIGFuZCBjb21wYXJlIGZsYWdzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBtYXRjaCBkYXRhIG9mIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hdGNoRGF0YShvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0b1BhaXJzKG9iamVjdCksXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHJlc3VsdFtsZW5ndGhdWzJdID0gaXNTdHJpY3RDb21wYXJhYmxlKHJlc3VsdFtsZW5ndGhdWzFdKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmF0aXZlIGZ1bmN0aW9uIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBpZiBpdCdzIG5hdGl2ZSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgICByZXR1cm4gaXNOYXRpdmUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYXJndW1lbnQgcGxhY2Vob2xkZXIgdmFsdWUgZm9yIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcGxhY2Vob2xkZXIgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UGxhY2Vob2xkZXIoZnVuYykge1xuICAgICAgdmFyIG9iamVjdCA9IGhhc093blByb3BlcnR5LmNhbGwobG9kYXNoLCAncGxhY2Vob2xkZXInKSA/IGxvZGFzaCA6IGZ1bmM7XG4gICAgICByZXR1cm4gb2JqZWN0LnBsYWNlaG9sZGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBzeW1ib2wgcHJvcGVydGllcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAgICAgKi9cbiAgICB2YXIgZ2V0U3ltYm9scyA9IGdldE93blByb3BlcnR5U3ltYm9scyB8fCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYHRvU3RyaW5nVGFnYCBvZiBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBgdG9TdHJpbmdUYWdgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFRhZyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICAgIH1cblxuICAgIC8vIEZhbGxiYWNrIGZvciBJRSAxMSBwcm92aWRpbmcgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgZm9yIG1hcHMsIHNldHMsIGFuZCB3ZWFrbWFwcy5cbiAgICBpZiAoKE1hcCAmJiBnZXRUYWcobmV3IE1hcCkgIT0gbWFwVGFnKSB8fFxuICAgICAgICAoU2V0ICYmIGdldFRhZyhuZXcgU2V0KSAhPSBzZXRUYWcpIHx8XG4gICAgICAgIChXZWFrTWFwICYmIGdldFRhZyhuZXcgV2Vha01hcCkgIT0gd2Vha01hcFRhZykpIHtcbiAgICAgIGdldFRhZyA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSxcbiAgICAgICAgICAgIEN0b3IgPSByZXN1bHQgPT0gb2JqZWN0VGFnID8gdmFsdWUuY29uc3RydWN0b3IgOiBudWxsLFxuICAgICAgICAgICAgY3RvclN0cmluZyA9IHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgPyBmdW5jVG9TdHJpbmcuY2FsbChDdG9yKSA6ICcnO1xuXG4gICAgICAgIGlmIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgc3dpdGNoIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgICBjYXNlIG1hcEN0b3JTdHJpbmc6IHJldHVybiBtYXBUYWc7XG4gICAgICAgICAgICBjYXNlIHNldEN0b3JTdHJpbmc6IHJldHVybiBzZXRUYWc7XG4gICAgICAgICAgICBjYXNlIHdlYWtNYXBDdG9yU3RyaW5nOiByZXR1cm4gd2Vha01hcFRhZztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmlldywgYXBwbHlpbmcgYW55IGB0cmFuc2Zvcm1zYCB0byB0aGUgYHN0YXJ0YCBhbmQgYGVuZGAgcG9zaXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSB2aWV3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgdmlldy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB0cmFuc2Zvcm1zIFRoZSB0cmFuc2Zvcm1hdGlvbnMgdG8gYXBwbHkgdG8gdGhlIHZpZXcuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgYHN0YXJ0YCBhbmQgYGVuZGBcbiAgICAgKiAgcG9zaXRpb25zIG9mIHRoZSB2aWV3LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZpZXcoc3RhcnQsIGVuZCwgdHJhbnNmb3Jtcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdHJhbnNmb3Jtcy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBkYXRhID0gdHJhbnNmb3Jtc1tpbmRleF0sXG4gICAgICAgICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gICAgICAgIHN3aXRjaCAoZGF0YS50eXBlKSB7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6ICAgICAgc3RhcnQgKz0gc2l6ZTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcFJpZ2h0JzogZW5kIC09IHNpemU7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2UnOiAgICAgIGVuZCA9IG5hdGl2ZU1pbihlbmQsIHN0YXJ0ICsgc2l6ZSk7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2VSaWdodCc6IHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0LCBlbmQgLSBzaXplKTsgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7ICdzdGFydCc6IHN0YXJ0LCAnZW5kJzogZW5kIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBwYXRoYCBleGlzdHMgb24gYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYXNGdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjayBwcm9wZXJ0aWVzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgcGF0aGAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzUGF0aChvYmplY3QsIHBhdGgsIGhhc0Z1bmMpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gaGFzRnVuYyhvYmplY3QsIHBhdGgpO1xuICAgICAgaWYgKCFyZXN1bHQgJiYgIWlzS2V5KHBhdGgpKSB7XG4gICAgICAgIHBhdGggPSBiYXNlQ2FzdFBhdGgocGF0aCk7XG4gICAgICAgIG9iamVjdCA9IHBhcmVudChvYmplY3QsIHBhdGgpO1xuICAgICAgICBpZiAob2JqZWN0ICE9IG51bGwpIHtcbiAgICAgICAgICBwYXRoID0gbGFzdChwYXRoKTtcbiAgICAgICAgICByZXN1bHQgPSBoYXNGdW5jKG9iamVjdCwgcGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICEhbGVuZ3RoICYmIGlzTGVuZ3RoKGxlbmd0aCkgJiYgaXNJbmRleChwYXRoLCBsZW5ndGgpICYmXG4gICAgICAgIChpc0FycmF5KG9iamVjdCkgfHwgaXNTdHJpbmcob2JqZWN0KSB8fCBpc0FyZ3VtZW50cyhvYmplY3QpKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhbiBhcnJheSBjbG9uZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5pdENsb25lQXJyYXkoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gYXJyYXkuY29uc3RydWN0b3IobGVuZ3RoKTtcblxuICAgICAgLy8gQWRkIHByb3BlcnRpZXMgYXNzaWduZWQgYnkgYFJlZ0V4cCNleGVjYC5cbiAgICAgIGlmIChsZW5ndGggJiYgdHlwZW9mIGFycmF5WzBdID09ICdzdHJpbmcnICYmIGhhc093blByb3BlcnR5LmNhbGwoYXJyYXksICdpbmRleCcpKSB7XG4gICAgICAgIHJlc3VsdC5pbmRleCA9IGFycmF5LmluZGV4O1xuICAgICAgICByZXN1bHQuaW5wdXQgPSBhcnJheS5pbnB1dDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5pdENsb25lT2JqZWN0KG9iamVjdCkge1xuICAgICAgcmV0dXJuIChpc0Z1bmN0aW9uKG9iamVjdC5jb25zdHJ1Y3RvcikgJiYgIWlzUHJvdG90eXBlKG9iamVjdCkpXG4gICAgICAgID8gYmFzZUNyZWF0ZShnZXRQcm90b3R5cGVPZihvYmplY3QpKVxuICAgICAgICA6IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY2xvbmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gICAgICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3QgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVCeVRhZyhvYmplY3QsIHRhZywgaXNEZWVwKSB7XG4gICAgICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgICAgIHN3aXRjaCAodGFnKSB7XG4gICAgICAgIGNhc2UgYXJyYXlCdWZmZXJUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lQXJyYXlCdWZmZXIob2JqZWN0KTtcblxuICAgICAgICBjYXNlIGJvb2xUYWc6XG4gICAgICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgICAgICByZXR1cm4gbmV3IEN0b3IoK29iamVjdCk7XG5cbiAgICAgICAgY2FzZSBmbG9hdDMyVGFnOiBjYXNlIGZsb2F0NjRUYWc6XG4gICAgICAgIGNhc2UgaW50OFRhZzogY2FzZSBpbnQxNlRhZzogY2FzZSBpbnQzMlRhZzpcbiAgICAgICAgY2FzZSB1aW50OFRhZzogY2FzZSB1aW50OENsYW1wZWRUYWc6IGNhc2UgdWludDE2VGFnOiBjYXNlIHVpbnQzMlRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVUeXBlZEFycmF5KG9iamVjdCwgaXNEZWVwKTtcblxuICAgICAgICBjYXNlIG1hcFRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVNYXAob2JqZWN0KTtcblxuICAgICAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBDdG9yKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSByZWdleHBUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lUmVnRXhwKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSBzZXRUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lU2V0KG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSBzeW1ib2xUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lU3ltYm9sKG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBpbmRleCBrZXlzIGZvciBgb2JqZWN0YCB2YWx1ZXMgb2YgYXJyYXlzLFxuICAgICAqIGBhcmd1bWVudHNgIG9iamVjdHMsIGFuZCBzdHJpbmdzLCBvdGhlcndpc2UgYG51bGxgIGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fG51bGx9IFJldHVybnMgaW5kZXgga2V5cywgZWxzZSBgbnVsbGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhLZXlzKG9iamVjdCkge1xuICAgICAgdmFyIGxlbmd0aCA9IG9iamVjdCA/IG9iamVjdC5sZW5ndGggOiB1bmRlZmluZWQ7XG4gICAgICBpZiAoaXNMZW5ndGgobGVuZ3RoKSAmJlxuICAgICAgICAgIChpc0FycmF5KG9iamVjdCkgfHwgaXNTdHJpbmcob2JqZWN0KSB8fCBpc0FyZ3VtZW50cyhvYmplY3QpKSkge1xuICAgICAgICByZXR1cm4gYmFzZVRpbWVzKGxlbmd0aCwgU3RyaW5nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gYXJndW1lbnRzIGFyZSBmcm9tIGFuIGl0ZXJhdGVlIGNhbGwuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHBvdGVudGlhbCBpdGVyYXRlZSB2YWx1ZSBhcmd1bWVudC5cbiAgICAgKiBAcGFyYW0geyp9IGluZGV4IFRoZSBwb3RlbnRpYWwgaXRlcmF0ZWUgaW5kZXggb3Iga2V5IGFyZ3VtZW50LlxuICAgICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBwb3RlbnRpYWwgaXRlcmF0ZWUgb2JqZWN0IGFyZ3VtZW50LlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYXJndW1lbnRzIGFyZSBmcm9tIGFuIGl0ZXJhdGVlIGNhbGwsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0l0ZXJhdGVlQ2FsbCh2YWx1ZSwgaW5kZXgsIG9iamVjdCkge1xuICAgICAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIGluZGV4O1xuICAgICAgaWYgKHR5cGUgPT0gJ251bWJlcidcbiAgICAgICAgICA/IChpc0FycmF5TGlrZShvYmplY3QpICYmIGlzSW5kZXgoaW5kZXgsIG9iamVjdC5sZW5ndGgpKVxuICAgICAgICAgIDogKHR5cGUgPT0gJ3N0cmluZycgJiYgaW5kZXggaW4gb2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gZXEob2JqZWN0W2luZGV4XSwgdmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgbm90IGEgcHJvcGVydHkgcGF0aC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkga2V5cyBvbi5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHByb3BlcnR5IG5hbWUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0tleSh2YWx1ZSwgb2JqZWN0KSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuICFpc0FycmF5KHZhbHVlKSAmJlxuICAgICAgICAocmVJc1BsYWluUHJvcC50ZXN0KHZhbHVlKSB8fCAhcmVJc0RlZXBQcm9wLnRlc3QodmFsdWUpIHx8XG4gICAgICAgICAgKG9iamVjdCAhPSBudWxsICYmIHZhbHVlIGluIE9iamVjdChvYmplY3QpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHVzZSBhcyB1bmlxdWUgb2JqZWN0IGtleS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0tleWFibGUodmFsdWUpIHtcbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgICAgcmV0dXJuIHR5cGUgPT0gJ251bWJlcicgfHwgdHlwZSA9PSAnYm9vbGVhbicgfHxcbiAgICAgICAgKHR5cGUgPT0gJ3N0cmluZycgJiYgdmFsdWUgIT0gJ19fcHJvdG9fXycpIHx8IHZhbHVlID09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgYSBsYXp5IGNvdW50ZXJwYXJ0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGhhcyBhIGxhenkgY291bnRlcnBhcnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0xhemlhYmxlKGZ1bmMpIHtcbiAgICAgIHZhciBmdW5jTmFtZSA9IGdldEZ1bmNOYW1lKGZ1bmMpLFxuICAgICAgICAgIG90aGVyID0gbG9kYXNoW2Z1bmNOYW1lXTtcblxuICAgICAgaWYgKHR5cGVvZiBvdGhlciAhPSAnZnVuY3Rpb24nIHx8ICEoZnVuY05hbWUgaW4gTGF6eVdyYXBwZXIucHJvdG90eXBlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoZnVuYyA9PT0gb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICB2YXIgZGF0YSA9IGdldERhdGEob3RoZXIpO1xuICAgICAgcmV0dXJuICEhZGF0YSAmJiBmdW5jID09PSBkYXRhWzBdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhIHByb3RvdHlwZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcHJvdG90eXBlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgIHZhciBDdG9yID0gdmFsdWUgJiYgdmFsdWUuY29uc3RydWN0b3IsXG4gICAgICAgICAgcHJvdG8gPSAoaXNGdW5jdGlvbihDdG9yKSAmJiBDdG9yLnByb3RvdHlwZSkgfHwgb2JqZWN0UHJvdG87XG5cbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gcHJvdG87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaWYgc3VpdGFibGUgZm9yIHN0cmljdFxuICAgICAqICBlcXVhbGl0eSBjb21wYXJpc29ucywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSAmJiAhaXNPYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlcyB0aGUgZnVuY3Rpb24gbWV0YWRhdGEgb2YgYHNvdXJjZWAgaW50byBgZGF0YWAuXG4gICAgICpcbiAgICAgKiBNZXJnaW5nIG1ldGFkYXRhIHJlZHVjZXMgdGhlIG51bWJlciBvZiB3cmFwcGVycyB1c2VkIHRvIGludm9rZSBhIGZ1bmN0aW9uLlxuICAgICAqIFRoaXMgaXMgcG9zc2libGUgYmVjYXVzZSBtZXRob2RzIGxpa2UgYF8uYmluZGAsIGBfLmN1cnJ5YCwgYW5kIGBfLnBhcnRpYWxgXG4gICAgICogbWF5IGJlIGFwcGxpZWQgcmVnYXJkbGVzcyBvZiBleGVjdXRpb24gb3JkZXIuIE1ldGhvZHMgbGlrZSBgXy5hcnlgIGFuZCBgXy5yZWFyZ2BcbiAgICAgKiBtb2RpZnkgZnVuY3Rpb24gYXJndW1lbnRzLCBtYWtpbmcgdGhlIG9yZGVyIGluIHdoaWNoIHRoZXkgYXJlIGV4ZWN1dGVkIGltcG9ydGFudCxcbiAgICAgKiBwcmV2ZW50aW5nIHRoZSBtZXJnaW5nIG9mIG1ldGFkYXRhLiBIb3dldmVyLCB3ZSBtYWtlIGFuIGV4Y2VwdGlvbiBmb3IgYSBzYWZlXG4gICAgICogY29tYmluZWQgY2FzZSB3aGVyZSBjdXJyaWVkIGZ1bmN0aW9ucyBoYXZlIGBfLmFyeWAgYW5kIG9yIGBfLnJlYXJnYCBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBkYXRhIFRoZSBkZXN0aW5hdGlvbiBtZXRhZGF0YS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIHNvdXJjZSBtZXRhZGF0YS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGRhdGFgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1lcmdlRGF0YShkYXRhLCBzb3VyY2UpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gZGF0YVsxXSxcbiAgICAgICAgICBzcmNCaXRtYXNrID0gc291cmNlWzFdLFxuICAgICAgICAgIG5ld0JpdG1hc2sgPSBiaXRtYXNrIHwgc3JjQml0bWFzayxcbiAgICAgICAgICBpc0NvbW1vbiA9IG5ld0JpdG1hc2sgPCAoQklORF9GTEFHIHwgQklORF9LRVlfRkxBRyB8IEFSWV9GTEFHKTtcblxuICAgICAgdmFyIGlzQ29tYm8gPVxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gQVJZX0ZMQUcpICYmIChiaXRtYXNrID09IENVUlJZX0ZMQUcpKSB8fFxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gQVJZX0ZMQUcpICYmIChiaXRtYXNrID09IFJFQVJHX0ZMQUcpICYmIChkYXRhWzddLmxlbmd0aCA8PSBzb3VyY2VbOF0pKSB8fFxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gKEFSWV9GTEFHIHwgUkVBUkdfRkxBRykpICYmIChzb3VyY2VbN10ubGVuZ3RoIDw9IHNvdXJjZVs4XSkgJiYgKGJpdG1hc2sgPT0gQ1VSUllfRkxBRykpO1xuXG4gICAgICAvLyBFeGl0IGVhcmx5IGlmIG1ldGFkYXRhIGNhbid0IGJlIG1lcmdlZC5cbiAgICAgIGlmICghKGlzQ29tbW9uIHx8IGlzQ29tYm8pKSB7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgdGhpc0FyZ2AgaWYgYXZhaWxhYmxlLlxuICAgICAgaWYgKHNyY0JpdG1hc2sgJiBCSU5EX0ZMQUcpIHtcbiAgICAgICAgZGF0YVsyXSA9IHNvdXJjZVsyXTtcbiAgICAgICAgLy8gU2V0IHdoZW4gY3VycnlpbmcgYSBib3VuZCBmdW5jdGlvbi5cbiAgICAgICAgbmV3Qml0bWFzayB8PSBiaXRtYXNrICYgQklORF9GTEFHID8gMCA6IENVUlJZX0JPVU5EX0ZMQUc7XG4gICAgICB9XG4gICAgICAvLyBDb21wb3NlIHBhcnRpYWwgYXJndW1lbnRzLlxuICAgICAgdmFyIHZhbHVlID0gc291cmNlWzNdO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHZhciBwYXJ0aWFscyA9IGRhdGFbM107XG4gICAgICAgIGRhdGFbM10gPSBwYXJ0aWFscyA/IGNvbXBvc2VBcmdzKHBhcnRpYWxzLCB2YWx1ZSwgc291cmNlWzRdKSA6IGNvcHlBcnJheSh2YWx1ZSk7XG4gICAgICAgIGRhdGFbNF0gPSBwYXJ0aWFscyA/IHJlcGxhY2VIb2xkZXJzKGRhdGFbM10sIFBMQUNFSE9MREVSKSA6IGNvcHlBcnJheShzb3VyY2VbNF0pO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIHJpZ2h0IGFyZ3VtZW50cy5cbiAgICAgIHZhbHVlID0gc291cmNlWzVdO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHBhcnRpYWxzID0gZGF0YVs1XTtcbiAgICAgICAgZGF0YVs1XSA9IHBhcnRpYWxzID8gY29tcG9zZUFyZ3NSaWdodChwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs2XSkgOiBjb3B5QXJyYXkodmFsdWUpO1xuICAgICAgICBkYXRhWzZdID0gcGFydGlhbHMgPyByZXBsYWNlSG9sZGVycyhkYXRhWzVdLCBQTEFDRUhPTERFUikgOiBjb3B5QXJyYXkoc291cmNlWzZdKTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYGFyZ1Bvc2AgaWYgYXZhaWxhYmxlLlxuICAgICAgdmFsdWUgPSBzb3VyY2VbN107XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgZGF0YVs3XSA9IGNvcHlBcnJheSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcnlgIGlmIGl0J3Mgc21hbGxlci5cbiAgICAgIGlmIChzcmNCaXRtYXNrICYgQVJZX0ZMQUcpIHtcbiAgICAgICAgZGF0YVs4XSA9IGRhdGFbOF0gPT0gbnVsbCA/IHNvdXJjZVs4XSA6IG5hdGl2ZU1pbihkYXRhWzhdLCBzb3VyY2VbOF0pO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJpdHlgIGlmIG9uZSBpcyBub3QgcHJvdmlkZWQuXG4gICAgICBpZiAoZGF0YVs5XSA9PSBudWxsKSB7XG4gICAgICAgIGRhdGFbOV0gPSBzb3VyY2VbOV07XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBmdW5jYCBhbmQgbWVyZ2UgYml0bWFza3MuXG4gICAgICBkYXRhWzBdID0gc291cmNlWzBdO1xuICAgICAgZGF0YVsxXSA9IG5ld0JpdG1hc2s7XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNEZWVwYCB0byBjdXN0b21pemUgaXRzIGBfLm1lcmdlYCB1c2UuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gb2JqVmFsdWUgVGhlIGRlc3RpbmF0aW9uIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHNvdXJjZSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIG1lcmdlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBwYXJlbnQgb2JqZWN0IG9mIGBzcmNWYWx1ZWAuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBzb3VyY2UgdmFsdWVzIGFuZCB0aGVpciBtZXJnZWQgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2VEZWZhdWx0cyhvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKSB7XG4gICAgICBpZiAoaXNPYmplY3Qob2JqVmFsdWUpICYmIGlzT2JqZWN0KHNyY1ZhbHVlKSkge1xuICAgICAgICBzdGFjay5zZXQoc3JjVmFsdWUsIG9ialZhbHVlKTtcbiAgICAgICAgYmFzZU1lcmdlKG9ialZhbHVlLCBzcmNWYWx1ZSwgdW5kZWZpbmVkLCBtZXJnZURlZmF1bHRzLCBzdGFjayk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcGFyZW50IHZhbHVlIGF0IGBwYXRoYCBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdGggVGhlIHBhdGggdG8gZ2V0IHRoZSBwYXJlbnQgdmFsdWUgb2YuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHBhcmVudCB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJlbnQob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gcGF0aC5sZW5ndGggPT0gMSA/IG9iamVjdCA6IGdldChvYmplY3QsIGJhc2VTbGljZShwYXRoLCAwLCAtMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlb3JkZXIgYGFycmF5YCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBpbmRleGVzIHdoZXJlIHRoZSBlbGVtZW50IGF0XG4gICAgICogdGhlIGZpcnN0IGluZGV4IGlzIGFzc2lnbmVkIGFzIHRoZSBmaXJzdCBlbGVtZW50LCB0aGUgZWxlbWVudCBhdFxuICAgICAqIHRoZSBzZWNvbmQgaW5kZXggaXMgYXNzaWduZWQgYXMgdGhlIHNlY29uZCBlbGVtZW50LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byByZW9yZGVyLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGluZGV4ZXMgVGhlIGFycmFuZ2VkIGFycmF5IGluZGV4ZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVvcmRlcihhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNaW4oaW5kZXhlcy5sZW5ndGgsIGFyckxlbmd0aCksXG4gICAgICAgICAgb2xkQXJyYXkgPSBjb3B5QXJyYXkoYXJyYXkpO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGluZGV4ID0gaW5kZXhlc1tsZW5ndGhdO1xuICAgICAgICBhcnJheVtsZW5ndGhdID0gaXNJbmRleChpbmRleCwgYXJyTGVuZ3RoKSA/IG9sZEFycmF5W2luZGV4XSA6IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSWYgdGhpcyBmdW5jdGlvbiBiZWNvbWVzIGhvdCwgaS5lLiBpcyBpbnZva2VkIGEgbG90IGluIGEgc2hvcnRcbiAgICAgKiBwZXJpb2Qgb2YgdGltZSwgaXQgd2lsbCB0cmlwIGl0cyBicmVha2VyIGFuZCB0cmFuc2l0aW9uIHRvIGFuIGlkZW50aXR5IGZ1bmN0aW9uXG4gICAgICogdG8gYXZvaWQgZ2FyYmFnZSBjb2xsZWN0aW9uIHBhdXNlcyBpbiBWOC4gU2VlIFtWOCBpc3N1ZSAyMDcwXShodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjA3MClcbiAgICAgKiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhc3NvY2lhdGUgbWV0YWRhdGEgd2l0aC5cbiAgICAgKiBAcGFyYW0geyp9IGRhdGEgVGhlIG1ldGFkYXRhLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgZnVuY2AuXG4gICAgICovXG4gICAgdmFyIHNldERhdGEgPSAoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgY291bnQgPSAwLFxuICAgICAgICAgIGxhc3RDYWxsZWQgPSAwO1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICAgICAgICB2YXIgc3RhbXAgPSBub3coKSxcbiAgICAgICAgICAgIHJlbWFpbmluZyA9IEhPVF9TUEFOIC0gKHN0YW1wIC0gbGFzdENhbGxlZCk7XG5cbiAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICBpZiAocmVtYWluaW5nID4gMCkge1xuICAgICAgICAgIGlmICgrK2NvdW50ID49IEhPVF9DT1VOVCkge1xuICAgICAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiYXNlU2V0RGF0YShrZXksIHZhbHVlKTtcbiAgICAgIH07XG4gICAgfSgpKTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0cmluZ1RvUGF0aChzdHJpbmcpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIHRvU3RyaW5nKHN0cmluZykucmVwbGFjZShyZVByb3BOYW1lLCBmdW5jdGlvbihtYXRjaCwgbnVtYmVyLCBxdW90ZSwgc3RyaW5nKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHF1b3RlID8gc3RyaW5nLnJlcGxhY2UocmVFc2NhcGVDaGFyLCAnJDEnKSA6IChudW1iZXIgfHwgbWF0Y2gpKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHdyYXBwZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gd3JhcHBlciBUaGUgd3JhcHBlciB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgd3JhcHBlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyQ2xvbmUod3JhcHBlcikge1xuICAgICAgaWYgKHdyYXBwZXIgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICByZXR1cm4gd3JhcHBlci5jbG9uZSgpO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMb2Rhc2hXcmFwcGVyKHdyYXBwZXIuX193cmFwcGVkX18sIHdyYXBwZXIuX19jaGFpbl9fKTtcbiAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXyA9IGNvcHlBcnJheSh3cmFwcGVyLl9fYWN0aW9uc19fKTtcbiAgICAgIHJlc3VsdC5fX2luZGV4X18gID0gd3JhcHBlci5fX2luZGV4X187XG4gICAgICByZXN1bHQuX192YWx1ZXNfXyA9IHdyYXBwZXIuX192YWx1ZXNfXztcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cyBzcGxpdCBpbnRvIGdyb3VwcyB0aGUgbGVuZ3RoIG9mIGBzaXplYC5cbiAgICAgKiBJZiBgYXJyYXlgIGNhbid0IGJlIHNwbGl0IGV2ZW5seSwgdGhlIGZpbmFsIGNodW5rIHdpbGwgYmUgdGhlIHJlbWFpbmluZ1xuICAgICAqIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzaXplPTBdIFRoZSBsZW5ndGggb2YgZWFjaCBjaHVuay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBjb250YWluaW5nIGNodW5rcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jaHVuayhbJ2EnLCAnYicsICdjJywgJ2QnXSwgMik7XG4gICAgICogLy8gPT4gW1snYScsICdiJ10sIFsnYycsICdkJ11dXG4gICAgICpcbiAgICAgKiBfLmNodW5rKFsnYScsICdiJywgJ2MnLCAnZCddLCAzKTtcbiAgICAgKiAvLyA9PiBbWydhJywgJ2InLCAnYyddLCBbJ2QnXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaHVuayhhcnJheSwgc2l6ZSkge1xuICAgICAgc2l6ZSA9IG5hdGl2ZU1heCh0b0ludGVnZXIoc2l6ZSksIDApO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGggfHwgc2l6ZSA8IDEpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICByZXNJbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KG5hdGl2ZUNlaWwobGVuZ3RoIC8gc2l6ZSkpO1xuXG4gICAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gYmFzZVNsaWNlKGFycmF5LCBpbmRleCwgKGluZGV4ICs9IHNpemUpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSB3aXRoIGFsbCBmYWxzZXkgdmFsdWVzIHJlbW92ZWQuIFRoZSB2YWx1ZXMgYGZhbHNlYCwgYG51bGxgLFxuICAgICAqIGAwYCwgYFwiXCJgLCBgdW5kZWZpbmVkYCwgYW5kIGBOYU5gIGFyZSBmYWxzZXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY29tcGFjdChbMCwgMSwgZmFsc2UsIDIsICcnLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFjdChhcnJheSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwLFxuICAgICAgICAgIHJlc0luZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgcmVzdWx0WysrcmVzSW5kZXhdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBhcnJheSBjb25jYXRlbmF0aW5nIGBhcnJheWAgd2l0aCBhbnkgYWRkaXRpb25hbCBhcnJheXNcbiAgICAgKiBhbmQvb3IgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbmNhdGVuYXRlLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjb25jYXRlbmF0ZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBjb25jYXRlbmF0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxXTtcbiAgICAgKiB2YXIgb3RoZXIgPSBfLmNvbmNhdChhcnJheSwgMiwgWzNdLCBbWzRdXSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvdGhlcik7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIFs0XV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKi9cbiAgICB2YXIgY29uY2F0ID0gcmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICBpZiAoIWlzQXJyYXkoYXJyYXkpKSB7XG4gICAgICAgIGFycmF5ID0gYXJyYXkgPT0gbnVsbCA/IFtdIDogW09iamVjdChhcnJheSldO1xuICAgICAgfVxuICAgICAgdmFsdWVzID0gYmFzZUZsYXR0ZW4odmFsdWVzLCAxKTtcbiAgICAgIHJldHVybiBhcnJheUNvbmNhdChhcnJheSwgdmFsdWVzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIGBhcnJheWAgdmFsdWVzIG5vdCBpbmNsdWRlZCBpbiB0aGUgb3RoZXJcbiAgICAgKiBnaXZlbiBhcnJheXMgdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2UoWzMsIDIsIDFdLCBbNCwgMl0pO1xuICAgICAqIC8vID0+IFszLCAxXVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlID0gcmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgdHJ1ZSkpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRpZmZlcmVuY2VgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIGFuZCBgdmFsdWVzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uXG4gICAgICogYnkgd2hpY2ggdW5pcXVlbmVzcyBpcyBjb21wdXRlZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2VCeShbMy4xLCAyLjIsIDEuM10sIFs0LjQsIDIuNV0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFszLjEsIDEuM11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZGlmZmVyZW5jZUJ5KFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgW3sgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlQnkgPSByZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QodmFsdWVzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChpdGVyYXRlZSkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgdHJ1ZSksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlKSlcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZGlmZmVyZW5jZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5YCB0byBgdmFsdWVzYC4gVGhlIGNvbXBhcmF0b3JcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XTtcbiAgICAgKlxuICAgICAqIF8uZGlmZmVyZW5jZVdpdGgob2JqZWN0cywgW3sgJ3gnOiAxLCAneSc6IDIgfV0sIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyLCAneSc6IDEgfV1cbiAgICAgKi9cbiAgICB2YXIgZGlmZmVyZW5jZVdpdGggPSByZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdCh2YWx1ZXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGNvbXBhcmF0b3IpKSB7XG4gICAgICAgIGNvbXBhcmF0b3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgdHJ1ZSksIHVuZGVmaW5lZCwgY29tcGFyYXRvcilcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIGRyb3AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wKGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCBuIDwgMCA/IDAgOiBuLCBsZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgZW5kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIGRyb3AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRyb3BSaWdodChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBuID0gKGd1YXJkIHx8IG4gPT09IHVuZGVmaW5lZCkgPyAxIDogdG9JbnRlZ2VyKG4pO1xuICAgICAgbiA9IGxlbmd0aCAtIG47XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCAwLCBuIDwgMCA/IDAgOiBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBleGNsdWRpbmcgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBlbmQuXG4gICAgICogRWxlbWVudHMgYXJlIGRyb3BwZWQgdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFJpZ2h0V2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIHRydWUsIHRydWUpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZXhjbHVkaW5nIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqIEVsZW1lbnRzIGFyZSBkcm9wcGVkIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wV2hpbGUodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcFdoaWxlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VXaGlsZShhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSwgdHJ1ZSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaWxscyBlbGVtZW50cyBvZiBgYXJyYXlgIHdpdGggYHZhbHVlYCBmcm9tIGBzdGFydGAgdXAgdG8sIGJ1dCBub3RcbiAgICAgKiBpbmNsdWRpbmcsIGBlbmRgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWxsLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGZpbGwgYGFycmF5YCB3aXRoLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXy5maWxsKGFycmF5LCAnYScpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYScsICdhJ11cbiAgICAgKlxuICAgICAqIF8uZmlsbChBcnJheSgzKSwgMik7XG4gICAgICogLy8gPT4gWzIsIDIsIDJdXG4gICAgICpcbiAgICAgKiBfLmZpbGwoWzQsIDYsIDgsIDEwXSwgJyonLCAxLCAzKTtcbiAgICAgKiAvLyA9PiBbNCwgJyonLCAnKicsIDEwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0ICYmIHR5cGVvZiBzdGFydCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgdmFsdWUsIHN0YXJ0KSkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIGVuZCA9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlRmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudCBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgaW5zdGVhZCBvZiB0aGUgZWxlbWVudCBpdHNlbGYuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLnVzZXIgPT0gJ2Jhcm5leSc7IH0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIHsgJ3VzZXInOiAnZnJlZCcsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kSW5kZXgoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUZpbmRJbmRleChhcnJheSwgZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKSlcbiAgICAgICAgOiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRJbmRleGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50c1xuICAgICAqIG9mIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby51c2VyID09ICdwZWJibGVzJzsgfSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgodXNlcnMsIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kTGFzdEluZGV4KGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VGaW5kSW5kZXgoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIHRydWUpXG4gICAgICAgIDogLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmxhdHRlbnMgYGFycmF5YCBhIHNpbmdsZSBsZXZlbCBkZWVwLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW4oWzEsIFsyLCBbMywgWzRdXSwgNV1dKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgWzMsIFs0XV0sIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbihhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlRmxhdHRlbihhcnJheSwgMSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWN1cnNpdmVseSBmbGF0dGVucyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW5EZWVwKFsxLCBbMiwgWzMsIFs0XV0sIDVdXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDQsIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbkRlZXAoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICByZXR1cm4gbGVuZ3RoID8gYmFzZUZsYXR0ZW4oYXJyYXksIElORklOSVRZKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IGZsYXR0ZW4gYGFycmF5YCB1cCB0byBgZGVwdGhgIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtkZXB0aD0xXSBUaGUgbWF4aW11bSByZWN1cnNpb24gZGVwdGguXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgWzIsIFszLCBbNF1dLCA1XV07XG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW5EZXB0aChhcnJheSwgMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIFszLCBbNF1dLCA1XVxuICAgICAqXG4gICAgICogXy5mbGF0dGVuRGVwdGgoYXJyYXksIDIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCBbNF0sIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbkRlcHRoKGFycmF5LCBkZXB0aCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGRlcHRoID0gZGVwdGggPT09IHVuZGVmaW5lZCA/IDEgOiB0b0ludGVnZXIoZGVwdGgpO1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKGFycmF5LCBkZXB0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGludmVyc2Ugb2YgYF8udG9QYWlyc2A7IHRoaXMgbWV0aG9kIHJldHVybnMgYW4gb2JqZWN0IGNvbXBvc2VkXG4gICAgICogZnJvbSBrZXktdmFsdWUgYHBhaXJzYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhaXJzIFRoZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mcm9tUGFpcnMoW1snZnJlZCcsIDMwXSwgWydiYXJuZXknLCA0MF1dKTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogMzAsICdiYXJuZXknOiA0MCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gZnJvbVBhaXJzKHBhaXJzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwYWlycyA/IHBhaXJzLmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBwYWlyID0gcGFpcnNbaW5kZXhdO1xuICAgICAgICByZXN1bHRbcGFpclswXV0gPSBwYWlyWzFdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgZmlyc3RcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5oZWFkKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5oZWFkKFtdKTtcbiAgICAgKiAvLyA9PiB1bmRlZmluZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoZWFkKGFycmF5KSB7XG4gICAgICByZXR1cm4gYXJyYXkgPyBhcnJheVswXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBgdmFsdWVgIGlzIGZvdW5kIGluIGBhcnJheWBcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gSWYgYGZyb21JbmRleGAgaXMgbmVnYXRpdmUsIGl0J3MgdXNlZCBhcyB0aGUgb2Zmc2V0XG4gICAgICogZnJvbSB0aGUgZW5kIG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9MF0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5kZXhPZihbMSwgMiwgMSwgMl0sIDIpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIFNlYXJjaCBmcm9tIHRoZSBgZnJvbUluZGV4YC5cbiAgICAgKiBfLmluZGV4T2YoWzEsIDIsIDEsIDJdLCAyLCAyKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGZyb21JbmRleCA9IHRvSW50ZWdlcihmcm9tSW5kZXgpO1xuICAgICAgaWYgKGZyb21JbmRleCA8IDApIHtcbiAgICAgICAgZnJvbUluZGV4ID0gbmF0aXZlTWF4KGxlbmd0aCArIGZyb21JbmRleCwgMCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYWxsIGJ1dCB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluaXRpYWwoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0aWFsKGFycmF5KSB7XG4gICAgICByZXR1cm4gZHJvcFJpZ2h0KGFycmF5LCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMgdGhhdCBhcmUgaW5jbHVkZWQgaW4gYWxsIGdpdmVuIGFycmF5c1xuICAgICAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHNoYXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW50ZXJzZWN0aW9uKFsyLCAxXSwgWzQsIDJdLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IFsyXVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb24gPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIG1hcHBlZCA9IGFycmF5TWFwKGFycmF5cywgYmFzZUNhc3RBcnJheUxpa2VPYmplY3QpO1xuICAgICAgcmV0dXJuIChtYXBwZWQubGVuZ3RoICYmIG1hcHBlZFswXSA9PT0gYXJyYXlzWzBdKVxuICAgICAgICA/IGJhc2VJbnRlcnNlY3Rpb24obWFwcGVkKVxuICAgICAgICA6IFtdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbnRlcnNlY3Rpb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBlYWNoIGBhcnJheXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb25cbiAgICAgKiBieSB3aGljaCB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBzaGFyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmludGVyc2VjdGlvbkJ5KFsyLjEsIDEuMl0sIFs0LjMsIDIuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjFdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmludGVyc2VjdGlvbkJ5KFt7ICd4JzogMSB9XSwgW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9XVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb25CeSA9IHJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgaXRlcmF0ZWUgPSBsYXN0KGFycmF5cyksXG4gICAgICAgICAgbWFwcGVkID0gYXJyYXlNYXAoYXJyYXlzLCBiYXNlQ2FzdEFycmF5TGlrZU9iamVjdCk7XG5cbiAgICAgIGlmIChpdGVyYXRlZSA9PT0gbGFzdChtYXBwZWQpKSB7XG4gICAgICAgIGl0ZXJhdGVlID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWFwcGVkLnBvcCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChtYXBwZWQubGVuZ3RoICYmIG1hcHBlZFswXSA9PT0gYXJyYXlzWzBdKVxuICAgICAgICA/IGJhc2VJbnRlcnNlY3Rpb24obWFwcGVkLCBnZXRJdGVyYXRlZShpdGVyYXRlZSkpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmludGVyc2VjdGlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5c2AuIFRoZSBjb21wYXJhdG9yIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2Ygc2hhcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy5pbnRlcnNlY3Rpb25XaXRoKG9iamVjdHMsIG90aGVycywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEsICd5JzogMiB9XVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb25XaXRoID0gcmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBjb21wYXJhdG9yID0gbGFzdChhcnJheXMpLFxuICAgICAgICAgIG1hcHBlZCA9IGFycmF5TWFwKGFycmF5cywgYmFzZUNhc3RBcnJheUxpa2VPYmplY3QpO1xuXG4gICAgICBpZiAoY29tcGFyYXRvciA9PT0gbGFzdChtYXBwZWQpKSB7XG4gICAgICAgIGNvbXBhcmF0b3IgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXBwZWQucG9wKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKG1hcHBlZC5sZW5ndGggJiYgbWFwcGVkWzBdID09PSBhcnJheXNbMF0pXG4gICAgICAgID8gYmFzZUludGVyc2VjdGlvbihtYXBwZWQsIHVuZGVmaW5lZCwgY29tcGFyYXRvcilcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGFsbCBlbGVtZW50cyBpbiBgYXJyYXlgIGludG8gYSBzdHJpbmcgc2VwYXJhdGVkIGJ5IGBzZXBhcmF0b3JgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9JywnXSBUaGUgZWxlbWVudCBzZXBhcmF0b3IuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgam9pbmVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5qb2luKFsnYScsICdiJywgJ2MnXSwgJ34nKTtcbiAgICAgKiAvLyA9PiAnYX5ifmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gam9pbihhcnJheSwgc2VwYXJhdG9yKSB7XG4gICAgICByZXR1cm4gYXJyYXkgPyBuYXRpdmVKb2luLmNhbGwoYXJyYXksIHNlcGFyYXRvcikgOiAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbGFzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubGFzdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXN0KGFycmF5KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGFycmF5W2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBhcnJheWAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWFycmF5Lmxlbmd0aC0xXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0SW5kZXhPZihbMSwgMiwgMSwgMl0sIDIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIC8vIFNlYXJjaCBmcm9tIHRoZSBgZnJvbUluZGV4YC5cbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAyLCAxLCAyXSwgMiwgMik7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgaWYgKGZyb21JbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGV4ID0gdG9JbnRlZ2VyKGZyb21JbmRleCk7XG4gICAgICAgIGluZGV4ID0gKGluZGV4IDwgMCA/IG5hdGl2ZU1heChsZW5ndGggKyBpbmRleCwgMCkgOiBuYXRpdmVNaW4oaW5kZXgsIGxlbmd0aCAtIDEpKSArIDE7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpbmRleE9mTmFOKGFycmF5LCBpbmRleCwgdHJ1ZSk7XG4gICAgICB9XG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGdpdmVuIHZhbHVlcyBmcm9tIGBhcnJheWAgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ud2l0aG91dGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC4gVXNlIGBfLnJlbW92ZWBcbiAgICAgKiB0byByZW1vdmUgZWxlbWVudHMgZnJvbSBhbiBhcnJheSBieSBwcmVkaWNhdGUuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzLCAxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8ucHVsbChhcnJheSwgMiwgMyk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAxXVxuICAgICAqL1xuICAgIHZhciBwdWxsID0gcmVzdChwdWxsQWxsKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucHVsbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhbiBhcnJheSBvZiB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5kaWZmZXJlbmNlYCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzLCAxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8ucHVsbEFsbChhcnJheSwgWzIsIDNdKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbEFsbChhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCAmJiB2YWx1ZXMgJiYgdmFsdWVzLmxlbmd0aClcbiAgICAgICAgPyBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzKVxuICAgICAgICA6IGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucHVsbEFsbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgYW5kIGB2YWx1ZXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb25cbiAgICAgKiBieSB3aGljaCB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZGlmZmVyZW5jZUJ5YCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9LCB7ICd4JzogMyB9LCB7ICd4JzogMSB9XTtcbiAgICAgKlxuICAgICAqIF8ucHVsbEFsbEJ5KGFycmF5LCBbeyAneCc6IDEgfSwgeyAneCc6IDMgfV0sICd4Jyk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHB1bGxBbGxCeShhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGggJiYgdmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpXG4gICAgICAgID8gYmFzZVB1bGxBbGxCeShhcnJheSwgdmFsdWVzLCBnZXRJdGVyYXRlZShpdGVyYXRlZSkpXG4gICAgICAgIDogYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBlbGVtZW50cyBmcm9tIGBhcnJheWAgY29ycmVzcG9uZGluZyB0byBgaW5kZXhlc2AgYW5kIHJldHVybnMgYW5cbiAgICAgKiBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5hdGAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHsuLi4obnVtYmVyfG51bWJlcltdKX0gW2luZGV4ZXNdIFRoZSBpbmRleGVzIG9mIGVsZW1lbnRzIHRvIHJlbW92ZSxcbiAgICAgKiAgc3BlY2lmaWVkIGluZGl2aWR1YWxseSBvciBpbiBhcnJheXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzUsIDEwLCAxNSwgMjBdO1xuICAgICAqIHZhciBldmVucyA9IF8ucHVsbEF0KGFycmF5LCAxLCAzKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbNSwgMTVdXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhldmVucyk7XG4gICAgICogLy8gPT4gWzEwLCAyMF1cbiAgICAgKi9cbiAgICB2YXIgcHVsbEF0ID0gcmVzdChmdW5jdGlvbihhcnJheSwgaW5kZXhlcykge1xuICAgICAgaW5kZXhlcyA9IGFycmF5TWFwKGJhc2VGbGF0dGVuKGluZGV4ZXMsIDEpLCBTdHJpbmcpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZUF0KGFycmF5LCBpbmRleGVzKTtcbiAgICAgIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMuc29ydChjb21wYXJlQXNjZW5kaW5nKSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSBgYXJyYXlgIHRoYXQgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yXG4gICAgICogYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgdGhlIHJlbW92ZWQgZWxlbWVudHMuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmZpbHRlcmAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC4gVXNlIGBfLnB1bGxgXG4gICAgICogdG8gcHVsbCBlbGVtZW50cyBmcm9tIGFuIGFycmF5IGJ5IHZhbHVlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgMywgNF07XG4gICAgICogdmFyIGV2ZW5zID0gXy5yZW1vdmUoYXJyYXksIGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAwO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAzXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coZXZlbnMpO1xuICAgICAqIC8vID0+IFsyLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlbW92ZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmRleGVzID0gW10sXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICAgIGluZGV4ZXMucHVzaChpbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnNlcyBgYXJyYXlgIHNvIHRoYXQgdGhlIGZpcnN0IGVsZW1lbnQgYmVjb21lcyB0aGUgbGFzdCwgdGhlIHNlY29uZFxuICAgICAqIGVsZW1lbnQgYmVjb21lcyB0aGUgc2Vjb25kIHRvIGxhc3QsIGFuZCBzbyBvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAgYW5kIGlzIGJhc2VkIG9uXG4gICAgICogW2BBcnJheSNyZXZlcnNlYF0oaHR0cHM6Ly9tZG4uaW8vQXJyYXkvcmV2ZXJzZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXy5yZXZlcnNlKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXZlcnNlKGFycmF5KSB7XG4gICAgICByZXR1cm4gYXJyYXkgPyBuYXRpdmVSZXZlcnNlLmNhbGwoYXJyYXkpIDogYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZnJvbSBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgdXNlZCBpbnN0ZWFkIG9mIFtgQXJyYXkjc2xpY2VgXShodHRwczovL21kbi5pby9BcnJheS9zbGljZSlcbiAgICAgKiB0byBlbnN1cmUgZGVuc2UgYXJyYXlzIGFyZSByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzbGljZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNsaWNlKGFycmF5LCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgaWYgKGVuZCAmJiB0eXBlb2YgZW5kICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKGFycmF5LCBzdGFydCwgZW5kKSkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIGVuZCA9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBzdGFydCA9IHN0YXJ0ID09IG51bGwgPyAwIDogdG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgICAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiB0b0ludGVnZXIoZW5kKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZXMgYSBiaW5hcnkgc2VhcmNoIHRvIGRldGVybWluZSB0aGUgbG93ZXN0IGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkXG4gICAgICogYmUgaW5zZXJ0ZWQgaW50byBgYXJyYXlgIGluIG9yZGVyIHRvIG1haW50YWluIGl0cyBzb3J0IG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleChbMzAsIDUwXSwgNDApO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXgoWzQsIDVdLCA0KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkSW5kZXgoYXJyYXksIHZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0ZWRJbmRleGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZSB0aGVpclxuICAgICAqIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWQgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZGljdCA9IHsgJ3RoaXJ0eSc6IDMwLCAnZm9ydHknOiA0MCwgJ2ZpZnR5JzogNTAgfTtcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXhCeShbJ3RoaXJ0eScsICdmaWZ0eSddLCAnZm9ydHknLCBfLnByb3BlcnR5T2YoZGljdCkpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29ydGVkSW5kZXhCeShbeyAneCc6IDQgfSwgeyAneCc6IDUgfV0sIHsgJ3gnOiA0IH0sICd4Jyk7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmluZGV4T2ZgIGV4Y2VwdCB0aGF0IGl0IHBlcmZvcm1zIGEgYmluYXJ5XG4gICAgICogc2VhcmNoIG9uIGEgc29ydGVkIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleE9mKFsxLCAxLCAyLCAyXSwgMik7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICB2YXIgaW5kZXggPSBiYXNlU29ydGVkSW5kZXgoYXJyYXksIHZhbHVlKTtcbiAgICAgICAgaWYgKGluZGV4IDwgbGVuZ3RoICYmIGVxKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0ZWRJbmRleGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaGlnaGVzdFxuICAgICAqIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YCBpbiBvcmRlciB0b1xuICAgICAqIG1haW50YWluIGl0cyBzb3J0IG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXgoWzQsIDVdLCA0KTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkTGFzdEluZGV4KGFycmF5LCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc29ydGVkTGFzdEluZGV4YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIGZvciBgdmFsdWVgIGFuZCBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCB0byBjb21wdXRlIHRoZWlyXG4gICAgICogc29ydCByYW5raW5nLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29ydGVkTGFzdEluZGV4QnkoW3sgJ3gnOiA0IH0sIHsgJ3gnOiA1IH1dLCB7ICd4JzogNCB9LCAneCcpO1xuICAgICAqIC8vID0+IDFcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRMYXN0SW5kZXhCeShhcnJheSwgdmFsdWUsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBnZXRJdGVyYXRlZShpdGVyYXRlZSksIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ubGFzdEluZGV4T2ZgIGV4Y2VwdCB0aGF0IGl0IHBlcmZvcm1zIGEgYmluYXJ5XG4gICAgICogc2VhcmNoIG9uIGEgc29ydGVkIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXhPZihbMSwgMSwgMiwgMl0sIDIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRMYXN0SW5kZXhPZihhcnJheSwgdmFsdWUpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHRydWUpIC0gMTtcbiAgICAgICAgaWYgKGVxKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlxYCBleGNlcHQgdGhhdCBpdCdzIGRlc2lnbmVkIGFuZCBvcHRpbWl6ZWRcbiAgICAgKiBmb3Igc29ydGVkIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZFVuaXEoWzEsIDEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRVbmlxKGFycmF5KSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU29ydGVkVW5pcShhcnJheSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFCeWAgZXhjZXB0IHRoYXQgaXQncyBkZXNpZ25lZCBhbmQgb3B0aW1pemVkXG4gICAgICogZm9yIHNvcnRlZCBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZFVuaXFCeShbMS4xLCAxLjIsIDIuMywgMi40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzEuMSwgMi4zXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZFVuaXFCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VTb3J0ZWRVbmlxQnkoYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlKSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBidXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGFpbChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRhaWwoYXJyYXkpIHtcbiAgICAgIHJldHVybiBkcm9wKGFycmF5LCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBiZWdpbm5pbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gdGFrZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2UoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCAwLCBuIDwgMCA/IDAgOiBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBlbmQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gdGFrZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFszXVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10sIDApO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFrZVJpZ2h0KGFycmF5LCBuLCBndWFyZCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICBuID0gbGVuZ3RoIC0gbjtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIG4gPCAwID8gMCA6IG4sIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBlbmQuIEVsZW1lbnRzIGFyZVxuICAgICAqIHRha2VuIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy50YWtlUmlnaHRXaGlsZSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VSaWdodFdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlUmlnaHRXaGlsZShhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlV2hpbGUoYXJyYXksIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIGZhbHNlLCB0cnVlKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggZWxlbWVudHMgdGFrZW4gZnJvbSB0aGUgYmVnaW5uaW5nLiBFbGVtZW50c1xuICAgICAqIGFyZSB0YWtlbiB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FjdGl2ZSc6IGZhbHNlfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlV2hpbGUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcywgaW4gb3JkZXIsIGZyb20gYWxsIGdpdmVuIGFycmF5cyB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlvbihbMiwgMV0sIFs0LCAyXSwgWzEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMiwgMSwgNF1cbiAgICAgKi9cbiAgICB2YXIgdW5pb24gPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFycmF5cywgMSwgdHJ1ZSkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGVhY2ggYGFycmF5c2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHVuaXF1ZW5lc3MgaXMgY29tcHV0ZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlvbkJ5KFsyLjEsIDEuMl0sIFs0LjMsIDIuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjEsIDEuMiwgNC4zXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy51bmlvbkJ5KFt7ICd4JzogMSB9XSwgW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIHZhciB1bmlvbkJ5ID0gcmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QoYXJyYXlzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChpdGVyYXRlZSkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVVuaXEoYmFzZUZsYXR0ZW4oYXJyYXlzLCAxLCB0cnVlKSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pb25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheXNgLiBUaGUgY29tcGFyYXRvciBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy51bmlvbldpdGgob2JqZWN0cywgb3RoZXJzLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMSB9XVxuICAgICAqL1xuICAgIHZhciB1bmlvbldpdGggPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KGFycmF5cyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoY29tcGFyYXRvcikpIHtcbiAgICAgICAgY29tcGFyYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlVW5pcShiYXNlRmxhdHRlbihhcnJheXMsIDEsIHRydWUpLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGR1cGxpY2F0ZS1mcmVlIHZlcnNpb24gb2YgYW4gYXJyYXksIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGluIHdoaWNoIG9ubHkgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgZWFjaCBlbGVtZW50XG4gICAgICogaXMga2VwdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXEoWzIsIDEsIDJdKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmlxKGFycmF5KSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlVW5pcShhcnJheSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBpbiBgYXJyYXlgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2hcbiAgICAgKiB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaXFCeShbMi4xLCAxLjIsIDIuM10sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsyLjEsIDEuMl1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udW5pcUJ5KFt7ICd4JzogMSB9LCB7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEgfSwgeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmlxQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlVW5pcShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUpKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pcWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY29tcGFyYXRvcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgZWxlbWVudHMgb2YgYGFycmF5YC4gVGhlIGNvbXBhcmF0b3IgaXMgaW52b2tlZCB3aXRoXG4gICAgICogdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfSwgIHsgJ3gnOiAxLCAneSc6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLnVuaXFXaXRoKG9iamVjdHMsIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXFXaXRoKGFycmF5LCBjb21wYXJhdG9yKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlVW5pcShhcnJheSwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGFuIGFycmF5IG9mIGdyb3VwZWRcbiAgICAgKiBlbGVtZW50cyBhbmQgY3JlYXRlcyBhbiBhcnJheSByZWdyb3VwaW5nIHRoZSBlbGVtZW50cyB0byB0aGVpciBwcmUtemlwXG4gICAgICogY29uZmlndXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgemlwcGVkID0gXy56aXAoWydmcmVkJywgJ2Jhcm5leSddLCBbMzAsIDQwXSwgW3RydWUsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gW1snZnJlZCcsIDMwLCB0cnVlXSwgWydiYXJuZXknLCA0MCwgZmFsc2VdXVxuICAgICAqXG4gICAgICogXy51bnppcCh6aXBwZWQpO1xuICAgICAqIC8vID0+IFtbJ2ZyZWQnLCAnYmFybmV5J10sIFszMCwgNDBdLCBbdHJ1ZSwgZmFsc2VdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuemlwKGFycmF5KSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSAwO1xuICAgICAgYXJyYXkgPSBhcnJheUZpbHRlcihhcnJheSwgZnVuY3Rpb24oZ3JvdXApIHtcbiAgICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGdyb3VwKSkge1xuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChncm91cC5sZW5ndGgsIGxlbmd0aCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGJhc2VUaW1lcyhsZW5ndGgsIGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgIHJldHVybiBhcnJheU1hcChhcnJheSwgYmFzZVByb3BlcnR5KGluZGV4KSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuemlwYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgdG8gc3BlY2lmeVxuICAgICAqIGhvdyByZWdyb3VwZWQgdmFsdWVzIHNob3VsZCBiZSBjb21iaW5lZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aGVcbiAgICAgKiBlbGVtZW50cyBvZiBlYWNoIGdyb3VwOiAoLi4uZ3JvdXApLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmUgcmVncm91cGVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZWdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB6aXBwZWQgPSBfLnppcChbMSwgMl0sIFsxMCwgMjBdLCBbMTAwLCAyMDBdKTtcbiAgICAgKiAvLyA9PiBbWzEsIDEwLCAxMDBdLCBbMiwgMjAsIDIwMF1dXG4gICAgICpcbiAgICAgKiBfLnVuemlwV2l0aCh6aXBwZWQsIF8uYWRkKTtcbiAgICAgKiAvLyA9PiBbMywgMzAsIDMwMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bnppcFdpdGgoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSB1bnppcChhcnJheSk7XG4gICAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5TWFwKHJlc3VsdCwgZnVuY3Rpb24oZ3JvdXApIHtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGl0ZXJhdGVlLCB1bmRlZmluZWQsIGdyb3VwKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgZXhjbHVkaW5nIGFsbCBnaXZlbiB2YWx1ZXMgdXNpbmdcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmaWx0ZXIuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndpdGhvdXQoWzEsIDIsIDEsIDNdLCAxLCAyKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKi9cbiAgICB2YXIgd2l0aG91dCA9IHJlc3QoZnVuY3Rpb24oYXJyYXksIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KGFycmF5KVxuICAgICAgICA/IGJhc2VEaWZmZXJlbmNlKGFycmF5LCB2YWx1ZXMpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMgdGhhdCBpcyB0aGUgW3N5bW1ldHJpYyBkaWZmZXJlbmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TeW1tZXRyaWNfZGlmZmVyZW5jZSlcbiAgICAgKiBvZiB0aGUgZ2l2ZW4gYXJyYXlzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy54b3IoWzIsIDFdLCBbNCwgMl0pO1xuICAgICAqIC8vID0+IFsxLCA0XVxuICAgICAqL1xuICAgIHZhciB4b3IgPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgcmV0dXJuIGJhc2VYb3IoYXJyYXlGaWx0ZXIoYXJyYXlzLCBpc0FycmF5TGlrZU9iamVjdCkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy54b3JgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBvZiBlYWNoIGBhcnJheXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2hcbiAgICAgKiB1bmlxdWVuZXNzIGlzIGNvbXB1dGVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ueG9yQnkoWzIuMSwgMS4yXSwgWzQuMywgMi40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzEuMiwgNC4zXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy54b3JCeShbeyAneCc6IDEgfV0sIFt7ICd4JzogMiB9LCB7ICd4JzogMSB9XSwgJ3gnKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICB2YXIgeG9yQnkgPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGl0ZXJhdGVlID0gbGFzdChhcnJheXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGl0ZXJhdGVlKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlWG9yKGFycmF5RmlsdGVyKGFycmF5cywgaXNBcnJheUxpa2VPYmplY3QpLCBnZXRJdGVyYXRlZShpdGVyYXRlZSkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy54b3JgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheXNgLiBUaGUgY29tcGFyYXRvciBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy54b3JXaXRoKG9iamVjdHMsIG90aGVycywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAxIH1dXG4gICAgICovXG4gICAgdmFyIHhvcldpdGggPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KGFycmF5cyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoY29tcGFyYXRvcikpIHtcbiAgICAgICAgY29tcGFyYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlWG9yKGFycmF5RmlsdGVyKGFycmF5cywgaXNBcnJheUxpa2VPYmplY3QpLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLCB0aGUgZmlyc3Qgb2Ygd2hpY2ggY29udGFpbnMgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgdGhlIHNlY29uZCBvZiB3aGljaCBjb250YWlucyB0aGUgc2Vjb25kIGVsZW1lbnRzXG4gICAgICogb2YgdGhlIGdpdmVuIGFycmF5cywgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwKFsnZnJlZCcsICdiYXJuZXknXSwgWzMwLCA0MF0sIFt0cnVlLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IFtbJ2ZyZWQnLCAzMCwgdHJ1ZV0sIFsnYmFybmV5JywgNDAsIGZhbHNlXV1cbiAgICAgKi9cbiAgICB2YXIgemlwID0gcmVzdCh1bnppcCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZyb21QYWlyc2AgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyB0d28gYXJyYXlzLFxuICAgICAqIG9uZSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgb25lIG9mIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gW3Byb3BzPVtdXSBUaGUgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlcz1bXV0gVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcE9iamVjdChbJ2EnLCAnYiddLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHppcE9iamVjdChwcm9wcywgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gYmFzZVppcE9iamVjdChwcm9wcyB8fCBbXSwgdmFsdWVzIHx8IFtdLCBhc3NpZ25WYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBPYmplY3RgIGV4Y2VwdCB0aGF0IGl0IHN1cHBvcnRzIHByb3BlcnR5IHBhdGhzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gW3Byb3BzPVtdXSBUaGUgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlcz1bXV0gVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcE9iamVjdERlZXAoWydhLmJbMF0uYycsICdhLmJbMV0uZCddLCBbMSwgMl0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdiJzogW3sgJ2MnOiAxIH0sIHsgJ2QnOiAyIH1dIH0gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHppcE9iamVjdERlZXAocHJvcHMsIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGJhc2VaaXBPYmplY3QocHJvcHMgfHwgW10sIHZhbHVlcyB8fCBbXSwgYmFzZVNldCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB0byBzcGVjaWZ5XG4gICAgICogaG93IGdyb3VwZWQgdmFsdWVzIHNob3VsZCBiZSBjb21iaW5lZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aGVcbiAgICAgKiBlbGVtZW50cyBvZiBlYWNoIGdyb3VwOiAoLi4uZ3JvdXApLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBwcm9jZXNzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gdG8gY29tYmluZSBncm91cGVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnppcFdpdGgoWzEsIDJdLCBbMTAsIDIwXSwgWzEwMCwgMjAwXSwgZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIGEgKyBiICsgYztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbMTExLCAyMjJdXG4gICAgICovXG4gICAgdmFyIHppcFdpdGggPSByZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5cy5sZW5ndGgsXG4gICAgICAgICAgaXRlcmF0ZWUgPSBsZW5ndGggPiAxID8gYXJyYXlzW2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkO1xuXG4gICAgICBpdGVyYXRlZSA9IHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nID8gKGFycmF5cy5wb3AoKSwgaXRlcmF0ZWUpIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHVuemlwV2l0aChhcnJheXMsIGl0ZXJhdGVlKTtcbiAgICB9KTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCBvYmplY3QgdGhhdCB3cmFwcyBgdmFsdWVgIHdpdGggZXhwbGljaXQgbWV0aG9kIGNoYWluaW5nIGVuYWJsZWQuXG4gICAgICogVGhlIHJlc3VsdCBvZiBzdWNoIG1ldGhvZCBjaGFpbmluZyBtdXN0IGJlIHVud3JhcHBlZCB3aXRoIGBfI3ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhZ2UnOiA0MCB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiB2YXIgeW91bmdlc3QgPSBfXG4gICAgICogICAuY2hhaW4odXNlcnMpXG4gICAgICogICAuc29ydEJ5KCdhZ2UnKVxuICAgICAqICAgLm1hcChmdW5jdGlvbihvKSB7XG4gICAgICogICAgIHJldHVybiBvLnVzZXIgKyAnIGlzICcgKyBvLmFnZTtcbiAgICAgKiAgIH0pXG4gICAgICogICAuaGVhZCgpXG4gICAgICogICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiAncGViYmxlcyBpcyAxJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNoYWluKHZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoKHZhbHVlKTtcbiAgICAgIHJlc3VsdC5fX2NoYWluX18gPSB0cnVlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpbnZva2VzIGBpbnRlcmNlcHRvcmAgYW5kIHJldHVybnMgYHZhbHVlYC4gVGhlIGludGVyY2VwdG9yXG4gICAgICogaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDsgKHZhbHVlKS4gVGhlIHB1cnBvc2Ugb2YgdGhpcyBtZXRob2QgaXMgdG9cbiAgICAgKiBcInRhcCBpbnRvXCIgYSBtZXRob2QgY2hhaW4gaW4gb3JkZXIgdG8gbW9kaWZ5IGludGVybWVkaWF0ZSByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb3ZpZGUgdG8gYGludGVyY2VwdG9yYC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpbnRlcmNlcHRvciBUaGUgZnVuY3Rpb24gdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGB2YWx1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDIsIDNdKVxuICAgICAqICAudGFwKGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICogICAgLy8gTXV0YXRlIGlucHV0IGFycmF5LlxuICAgICAqICAgIGFycmF5LnBvcCgpO1xuICAgICAqICB9KVxuICAgICAqICAucmV2ZXJzZSgpXG4gICAgICogIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRhcCh2YWx1ZSwgaW50ZXJjZXB0b3IpIHtcbiAgICAgIGludGVyY2VwdG9yKHZhbHVlKTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnRhcGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgcmVzdWx0IG9mIGBpbnRlcmNlcHRvcmAuXG4gICAgICogVGhlIHB1cnBvc2Ugb2YgdGhpcyBtZXRob2QgaXMgdG8gXCJwYXNzIHRocnVcIiB2YWx1ZXMgcmVwbGFjaW5nIGludGVybWVkaWF0ZVxuICAgICAqIHJlc3VsdHMgaW4gYSBtZXRob2QgY2hhaW4uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvdmlkZSB0byBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGludGVyY2VwdG9yIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc3VsdCBvZiBgaW50ZXJjZXB0b3JgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKCcgIGFiYyAgJylcbiAgICAgKiAgLmNoYWluKClcbiAgICAgKiAgLnRyaW0oKVxuICAgICAqICAudGhydShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgIHJldHVybiBbdmFsdWVdO1xuICAgICAqICB9KVxuICAgICAqICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbJ2FiYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGhydSh2YWx1ZSwgaW50ZXJjZXB0b3IpIHtcbiAgICAgIHJldHVybiBpbnRlcmNlcHRvcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgdGhlIHdyYXBwZXIgdmVyc2lvbiBvZiBgXy5hdGAuXG4gICAgICpcbiAgICAgKiBAbmFtZSBhdFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Li4uKHN0cmluZ3xzdHJpbmdbXSl9IFtwYXRoc10gVGhlIHByb3BlcnR5IHBhdGhzIG9mIGVsZW1lbnRzIHRvIHBpY2ssXG4gICAgICogIHNwZWNpZmllZCBpbmRpdmlkdWFsbHkgb3IgaW4gYXJyYXlzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9LCA0XSB9O1xuICAgICAqXG4gICAgICogXyhvYmplY3QpLmF0KFsnYVswXS5iLmMnLCAnYVsxXSddKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFszLCA0XVxuICAgICAqXG4gICAgICogXyhbJ2EnLCAnYicsICdjJ10pLmF0KDAsIDIpLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWydhJywgJ2MnXVxuICAgICAqL1xuICAgIHZhciB3cmFwcGVyQXQgPSByZXN0KGZ1bmN0aW9uKHBhdGhzKSB7XG4gICAgICBwYXRocyA9IGJhc2VGbGF0dGVuKHBhdGhzLCAxKTtcbiAgICAgIHZhciBsZW5ndGggPSBwYXRocy5sZW5ndGgsXG4gICAgICAgICAgc3RhcnQgPSBsZW5ndGggPyBwYXRoc1swXSA6IDAsXG4gICAgICAgICAgdmFsdWUgPSB0aGlzLl9fd3JhcHBlZF9fLFxuICAgICAgICAgIGludGVyY2VwdG9yID0gZnVuY3Rpb24ob2JqZWN0KSB7IHJldHVybiBiYXNlQXQob2JqZWN0LCBwYXRocyk7IH07XG5cbiAgICAgIGlmIChsZW5ndGggPiAxIHx8IHRoaXMuX19hY3Rpb25zX18ubGVuZ3RoIHx8XG4gICAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB8fCAhaXNJbmRleChzdGFydCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGhydShpbnRlcmNlcHRvcik7XG4gICAgICB9XG4gICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKHN0YXJ0LCArc3RhcnQgKyAobGVuZ3RoID8gMSA6IDApKTtcbiAgICAgIHZhbHVlLl9fYWN0aW9uc19fLnB1c2goe1xuICAgICAgICAnZnVuYyc6IHRocnUsXG4gICAgICAgICdhcmdzJzogW2ludGVyY2VwdG9yXSxcbiAgICAgICAgJ3RoaXNBcmcnOiB1bmRlZmluZWRcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHZhbHVlLCB0aGlzLl9fY2hhaW5fXykudGhydShmdW5jdGlvbihhcnJheSkge1xuICAgICAgICBpZiAobGVuZ3RoICYmICFhcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICBhcnJheS5wdXNoKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBFbmFibGVzIGV4cGxpY2l0IG1ldGhvZCBjaGFpbmluZyBvbiB0aGUgd3JhcHBlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBjaGFpblxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBBIHNlcXVlbmNlIHdpdGhvdXQgZXhwbGljaXQgY2hhaW5pbmcuXG4gICAgICogXyh1c2VycykuaGVhZCgpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKlxuICAgICAqIC8vIEEgc2VxdWVuY2Ugd2l0aCBleHBsaWNpdCBjaGFpbmluZy5cbiAgICAgKiBfKHVzZXJzKVxuICAgICAqICAgLmNoYWluKClcbiAgICAgKiAgIC5oZWFkKClcbiAgICAgKiAgIC5waWNrKCd1c2VyJylcbiAgICAgKiAgIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnYmFybmV5JyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlckNoYWluKCkge1xuICAgICAgcmV0dXJuIGNoYWluKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVzIHRoZSBjaGFpbmVkIHNlcXVlbmNlIGFuZCByZXR1cm5zIHRoZSB3cmFwcGVkIHJlc3VsdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGNvbW1pdFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMl07XG4gICAgICogdmFyIHdyYXBwZWQgPSBfKGFycmF5KS5wdXNoKDMpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogd3JhcHBlZCA9IHdyYXBwZWQuY29tbWl0KCk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogd3JhcHBlZC5sYXN0KCk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDb21taXQoKSB7XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodGhpcy52YWx1ZSgpLCB0aGlzLl9fY2hhaW5fXyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgdGhlIHdyYXBwZXIgdmVyc2lvbiBvZiBgXy5mbGF0TWFwYC5cbiAgICAgKlxuICAgICAqIEBuYW1lIGZsYXRNYXBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkdXBsaWNhdGUobikge1xuICAgICAqICAgcmV0dXJuIFtuLCBuXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfKFsxLCAyXSkuZmxhdE1hcChkdXBsaWNhdGUpLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzEsIDEsIDIsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlckZsYXRNYXAoaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiB0aGlzLm1hcChpdGVyYXRlZSkuZmxhdHRlbigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG5leHQgdmFsdWUgb24gYSB3cmFwcGVkIG9iamVjdCBmb2xsb3dpbmcgdGhlXG4gICAgICogW2l0ZXJhdG9yIHByb3RvY29sXShodHRwczovL21kbi5pby9pdGVyYXRpb25fcHJvdG9jb2xzI2l0ZXJhdG9yKS5cbiAgICAgKlxuICAgICAqIEBuYW1lIG5leHRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXh0IGl0ZXJhdG9yIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDJdKTtcbiAgICAgKlxuICAgICAqIHdyYXBwZWQubmV4dCgpO1xuICAgICAqIC8vID0+IHsgJ2RvbmUnOiBmYWxzZSwgJ3ZhbHVlJzogMSB9XG4gICAgICpcbiAgICAgKiB3cmFwcGVkLm5leHQoKTtcbiAgICAgKiAvLyA9PiB7ICdkb25lJzogZmFsc2UsICd2YWx1ZSc6IDIgfVxuICAgICAqXG4gICAgICogd3JhcHBlZC5uZXh0KCk7XG4gICAgICogLy8gPT4geyAnZG9uZSc6IHRydWUsICd2YWx1ZSc6IHVuZGVmaW5lZCB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlck5leHQoKSB7XG4gICAgICBpZiAodGhpcy5fX3ZhbHVlc19fID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhpcy5fX3ZhbHVlc19fID0gdG9BcnJheSh0aGlzLnZhbHVlKCkpO1xuICAgICAgfVxuICAgICAgdmFyIGRvbmUgPSB0aGlzLl9faW5kZXhfXyA+PSB0aGlzLl9fdmFsdWVzX18ubGVuZ3RoLFxuICAgICAgICAgIHZhbHVlID0gZG9uZSA/IHVuZGVmaW5lZCA6IHRoaXMuX192YWx1ZXNfX1t0aGlzLl9faW5kZXhfXysrXTtcblxuICAgICAgcmV0dXJuIHsgJ2RvbmUnOiBkb25lLCAndmFsdWUnOiB2YWx1ZSB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZXMgdGhlIHdyYXBwZXIgdG8gYmUgaXRlcmFibGUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBTeW1ib2wuaXRlcmF0b3JcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyXSk7XG4gICAgICpcbiAgICAgKiB3cmFwcGVkW1N5bWJvbC5pdGVyYXRvcl0oKSA9PT0gd3JhcHBlZDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBBcnJheS5mcm9tKHdyYXBwZWQpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJUb0l0ZXJhdG9yKCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBjaGFpbmVkIHNlcXVlbmNlIHBsYW50aW5nIGB2YWx1ZWAgYXMgdGhlIHdyYXBwZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGFudFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHBsYW50LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciB3cmFwcGVkID0gXyhbMSwgMl0pLm1hcChzcXVhcmUpO1xuICAgICAqIHZhciBvdGhlciA9IHdyYXBwZWQucGxhbnQoWzMsIDRdKTtcbiAgICAgKlxuICAgICAqIG90aGVyLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzksIDE2XVxuICAgICAqXG4gICAgICogd3JhcHBlZC52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsxLCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJQbGFudCh2YWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCxcbiAgICAgICAgICBwYXJlbnQgPSB0aGlzO1xuXG4gICAgICB3aGlsZSAocGFyZW50IGluc3RhbmNlb2YgYmFzZUxvZGFzaCkge1xuICAgICAgICB2YXIgY2xvbmUgPSB3cmFwcGVyQ2xvbmUocGFyZW50KTtcbiAgICAgICAgY2xvbmUuX19pbmRleF9fID0gMDtcbiAgICAgICAgY2xvbmUuX192YWx1ZXNfXyA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gY2xvbmU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xvbmU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZXZpb3VzID0gY2xvbmU7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5fX3dyYXBwZWRfXztcbiAgICAgIH1cbiAgICAgIHByZXZpb3VzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHRoZSB3cmFwcGVyIHZlcnNpb24gb2YgYF8ucmV2ZXJzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyB0aGUgd3JhcHBlZCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHJldmVyc2VcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDNdO1xuICAgICAqXG4gICAgICogXyhhcnJheSkucmV2ZXJzZSgpLnZhbHVlKClcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyUmV2ZXJzZSgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IHRoaXMuX193cmFwcGVkX187XG4gICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcikge1xuICAgICAgICB2YXIgd3JhcHBlZCA9IHZhbHVlO1xuICAgICAgICBpZiAodGhpcy5fX2FjdGlvbnNfXy5sZW5ndGgpIHtcbiAgICAgICAgICB3cmFwcGVkID0gbmV3IExhenlXcmFwcGVyKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHdyYXBwZWQgPSB3cmFwcGVkLnJldmVyc2UoKTtcbiAgICAgICAgd3JhcHBlZC5fX2FjdGlvbnNfXy5wdXNoKHtcbiAgICAgICAgICAnZnVuYyc6IHRocnUsXG4gICAgICAgICAgJ2FyZ3MnOiBbcmV2ZXJzZV0sXG4gICAgICAgICAgJ3RoaXNBcmcnOiB1bmRlZmluZWRcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih3cmFwcGVkLCB0aGlzLl9fY2hhaW5fXyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy50aHJ1KHJldmVyc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVzIHRoZSBjaGFpbmVkIHNlcXVlbmNlIHRvIGV4dHJhY3QgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHZhbHVlXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgdG9KU09OLCB2YWx1ZU9mXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB1bndyYXBwZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDIsIDNdKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJWYWx1ZSgpIHtcbiAgICAgIHJldHVybiBiYXNlV3JhcHBlclZhbHVlKHRoaXMuX193cmFwcGVkX18sIHRoaXMuX19hY3Rpb25zX18pO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgY29sbGVjdGlvbmAgdGhyb3VnaCBgaXRlcmF0ZWVgLiBUaGUgY29ycmVzcG9uZGluZyB2YWx1ZVxuICAgICAqIG9mIGVhY2gga2V5IGlzIHRoZSBudW1iZXIgb2YgdGltZXMgdGhlIGtleSB3YXMgcmV0dXJuZWQgYnkgYGl0ZXJhdGVlYC5cbiAgICAgKiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNvdW50QnkoWzYuMSwgNC4yLCA2LjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiB7ICc0JzogMSwgJzYnOiAyIH1cbiAgICAgKlxuICAgICAqIF8uY291bnRCeShbJ29uZScsICd0d28nLCAndGhyZWUnXSwgJ2xlbmd0aCcpO1xuICAgICAqIC8vID0+IHsgJzMnOiAyLCAnNSc6IDEgfVxuICAgICAqL1xuICAgIHZhciBjb3VudEJ5ID0gY3JlYXRlQWdncmVnYXRvcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCBrZXkpID8gKytyZXN1bHRba2V5XSA6IChyZXN1bHRba2V5XSA9IDEpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvciAqKmFsbCoqIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBJdGVyYXRpb24gaXMgc3RvcHBlZCBvbmNlIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzcyB0aGUgcHJlZGljYXRlIGNoZWNrLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXZlcnkoW3RydWUsIDEsIG51bGwsICd5ZXMnXSwgQm9vbGVhbik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ldmVyeSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmV2ZXJ5KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ldmVyeSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXZlcnkoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBndWFyZCkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlFdmVyeSA6IGJhc2VFdmVyeTtcbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSkge1xuICAgICAgICBwcmVkaWNhdGUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGFsbCBlbGVtZW50c1xuICAgICAqIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcih1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaWx0ZXIoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUZpbHRlciA6IGJhc2VGaWx0ZXI7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCwgcmV0dXJuaW5nIHRoZSBmaXJzdCBlbGVtZW50XG4gICAgICogYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6XG4gICAgICogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hdGNoZWQgZWxlbWVudCwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmQodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlIDwgNDA7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kKHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3QgZm9yICdwZWJibGVzJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2ZyZWQnXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmQodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3QgZm9yICdiYXJuZXknXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZChjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHByZWRpY2F0ZSA9IGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyk7XG4gICAgICBpZiAoaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgICB2YXIgaW5kZXggPSBiYXNlRmluZEluZGV4KGNvbGxlY3Rpb24sIHByZWRpY2F0ZSk7XG4gICAgICAgIHJldHVybiBpbmRleCA+IC0xID8gY29sbGVjdGlvbltpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUZpbmQoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBiYXNlRWFjaCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtYXRjaGVkIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3QoWzEsIDIsIDMsIDRdLCBmdW5jdGlvbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZExhc3QoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpO1xuICAgICAgaWYgKGlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gYmFzZUZpbmRJbmRleChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIHRydWUpO1xuICAgICAgICByZXR1cm4gaW5kZXggPiAtMSA/IGNvbGxlY3Rpb25baW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VGaW5kKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgYmFzZUVhY2hSaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBmbGF0dGVuZWQgdmFsdWVzIGJ5IHJ1bm5pbmcgZWFjaCBlbGVtZW50IGluIGBjb2xsZWN0aW9uYFxuICAgICAqIHRocm91Z2ggYGl0ZXJhdGVlYCBhbmQgY29uY2F0aW5nIGl0cyByZXN1bHQgdG8gdGhlIG90aGVyIG1hcHBlZCB2YWx1ZXMuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBkdXBsaWNhdGUobikge1xuICAgICAqICAgcmV0dXJuIFtuLCBuXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXAoWzEsIDJdLCBkdXBsaWNhdGUpO1xuICAgICAqIC8vID0+IFsxLCAxLCAyLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXRNYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBiYXNlRmxhdHRlbihtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCBpbnZva2luZyBgaXRlcmF0ZWVgIGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogQXMgd2l0aCBvdGhlciBcIkNvbGxlY3Rpb25zXCIgbWV0aG9kcywgb2JqZWN0cyB3aXRoIGEgXCJsZW5ndGhcIiBwcm9wZXJ0eVxuICAgICAqIGFyZSBpdGVyYXRlZCBsaWtlIGFycmF5cy4gVG8gYXZvaWQgdGhpcyBiZWhhdmlvciB1c2UgYF8uZm9ySW5gIG9yIGBfLmZvck93bmBcbiAgICAgKiBmb3Igb2JqZWN0IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBlYWNoXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDJdKS5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICBjb25zb2xlLmxvZyh2YWx1ZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyBgMWAgdGhlbiBgMmBcbiAgICAgKlxuICAgICAqIF8uZm9yRWFjaCh7ICdhJzogMSwgJ2InOiAyIH0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyAnYScgdGhlbiAnYicgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nICYmIGlzQXJyYXkoY29sbGVjdGlvbikpXG4gICAgICAgID8gYXJyYXlFYWNoKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKVxuICAgICAgICA6IGJhc2VFYWNoKGNvbGxlY3Rpb24sIGJhc2VDYXN0RnVuY3Rpb24oaXRlcmF0ZWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvckVhY2hgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGVhY2hSaWdodFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2hSaWdodChbMSwgMl0sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICBjb25zb2xlLmxvZyh2YWx1ZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyBgMmAgdGhlbiBgMWBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoUmlnaHQoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAodHlwZW9mIGl0ZXJhdGVlID09ICdmdW5jdGlvbicgJiYgaXNBcnJheShjb2xsZWN0aW9uKSlcbiAgICAgICAgPyBhcnJheUVhY2hSaWdodChjb2xsZWN0aW9uLCBpdGVyYXRlZSlcbiAgICAgICAgOiBiYXNlRWFjaFJpZ2h0KGNvbGxlY3Rpb24sIGJhc2VDYXN0RnVuY3Rpb24oaXRlcmF0ZWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiBrZXlzIGdlbmVyYXRlZCBmcm9tIHRoZSByZXN1bHRzIG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIHRocm91Z2ggYGl0ZXJhdGVlYC4gVGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVcbiAgICAgKiBvZiBlYWNoIGtleSBpcyBhbiBhcnJheSBvZiBlbGVtZW50cyByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUga2V5LlxuICAgICAqIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSBrZXlzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbXBvc2VkIGFnZ3JlZ2F0ZSBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3JvdXBCeShbNi4xLCA0LjIsIDYuM10sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IHsgJzQnOiBbNC4yXSwgJzYnOiBbNi4xLCA2LjNdIH1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZ3JvdXBCeShbJ29uZScsICd0d28nLCAndGhyZWUnXSwgJ2xlbmd0aCcpO1xuICAgICAqIC8vID0+IHsgJzMnOiBbJ29uZScsICd0d28nXSwgJzUnOiBbJ3RocmVlJ10gfVxuICAgICAqL1xuICAgIHZhciBncm91cEJ5ID0gY3JlYXRlQWdncmVnYXRvcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdCwga2V5KSkge1xuICAgICAgICByZXN1bHRba2V5XS5wdXNoKHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gW3ZhbHVlXTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGluIGBjb2xsZWN0aW9uYC4gSWYgYGNvbGxlY3Rpb25gIGlzIGEgc3RyaW5nIGl0J3MgY2hlY2tlZFxuICAgICAqIGZvciBhIHN1YnN0cmluZyBvZiBgdmFsdWVgLCBvdGhlcndpc2UgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBpcyB1c2VkIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gSWYgYGZyb21JbmRleGAgaXMgbmVnYXRpdmUsIGl0J3MgdXNlZCBhc1xuICAgICAqIHRoZSBvZmZzZXQgZnJvbSB0aGUgZW5kIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLnJlZHVjZWAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbmNsdWRlcyhbMSwgMiwgM10sIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoWzEsIDIsIDNdLCAxLCAyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pbmNsdWRlcyh7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfSwgJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKCdwZWJibGVzJywgJ2ViJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluY2x1ZGVzKGNvbGxlY3Rpb24sIHZhbHVlLCBmcm9tSW5kZXgsIGd1YXJkKSB7XG4gICAgICBjb2xsZWN0aW9uID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBjb2xsZWN0aW9uIDogdmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgZnJvbUluZGV4ID0gKGZyb21JbmRleCAmJiAhZ3VhcmQpID8gdG9JbnRlZ2VyKGZyb21JbmRleCkgOiAwO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgICBpZiAoZnJvbUluZGV4IDwgMCkge1xuICAgICAgICBmcm9tSW5kZXggPSBuYXRpdmVNYXgobGVuZ3RoICsgZnJvbUluZGV4LCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc1N0cmluZyhjb2xsZWN0aW9uKVxuICAgICAgICA/IChmcm9tSW5kZXggPD0gbGVuZ3RoICYmIGNvbGxlY3Rpb24uaW5kZXhPZih2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKVxuICAgICAgICA6ICghIWxlbmd0aCAmJiBiYXNlSW5kZXhPZihjb2xsZWN0aW9uLCB2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAsIHJldHVybmluZ1xuICAgICAqIGFuIGFycmF5IG9mIHRoZSByZXN1bHRzIG9mIGVhY2ggaW52b2tlZCBtZXRob2QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgICAqIGFyZSBwcm92aWRlZCB0byBlYWNoIGludm9rZWQgbWV0aG9kLiBJZiBgbWV0aG9kTmFtZWAgaXMgYSBmdW5jdGlvbiBpdCdzXG4gICAgICogaW52b2tlZCBmb3IsIGFuZCBgdGhpc2AgYm91bmQgdG8sIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fEZ1bmN0aW9ufHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZSBvclxuICAgICAqICB0aGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGVhY2ggbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmludm9rZU1hcChbWzUsIDEsIDddLCBbMywgMiwgMV1dLCAnc29ydCcpO1xuICAgICAqIC8vID0+IFtbMSwgNSwgN10sIFsxLCAyLCAzXV1cbiAgICAgKlxuICAgICAqIF8uaW52b2tlTWFwKFsxMjMsIDQ1Nl0sIFN0cmluZy5wcm90b3R5cGUuc3BsaXQsICcnKTtcbiAgICAgKiAvLyA9PiBbWycxJywgJzInLCAnMyddLCBbJzQnLCAnNScsICc2J11dXG4gICAgICovXG4gICAgdmFyIGludm9rZU1hcCA9IHJlc3QoZnVuY3Rpb24oY29sbGVjdGlvbiwgcGF0aCwgYXJncykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaXNGdW5jID0gdHlwZW9mIHBhdGggPT0gJ2Z1bmN0aW9uJyxcbiAgICAgICAgICBpc1Byb3AgPSBpc0tleShwYXRoKSxcbiAgICAgICAgICByZXN1bHQgPSBpc0FycmF5TGlrZShjb2xsZWN0aW9uKSA/IEFycmF5KGNvbGxlY3Rpb24ubGVuZ3RoKSA6IFtdO1xuXG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB2YXIgZnVuYyA9IGlzRnVuYyA/IHBhdGggOiAoKGlzUHJvcCAmJiB2YWx1ZSAhPSBudWxsKSA/IHZhbHVlW3BhdGhdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgcmVzdWx0WysraW5kZXhdID0gZnVuYyA/IGFwcGx5KGZ1bmMsIHZhbHVlLCBhcmdzKSA6IGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlXG4gICAgICogb2YgZWFjaCBrZXkgaXMgdGhlIGxhc3QgZWxlbWVudCByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUga2V5LiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIHRvIHRyYW5zZm9ybSBrZXlzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbXBvc2VkIGFnZ3JlZ2F0ZSBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFtcbiAgICAgKiAgIHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LFxuICAgICAqICAgeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmtleUJ5KGFycmF5LCBmdW5jdGlvbihvKSB7XG4gICAgICogICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShvLmNvZGUpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSwgJ2QnOiB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9IH1cbiAgICAgKlxuICAgICAqIF8ua2V5QnkoYXJyYXksICdkaXInKTtcbiAgICAgKiAvLyA9PiB7ICdsZWZ0JzogeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sICdyaWdodCc6IHsgJ2Rpcic6ICdyaWdodCcsICdjb2RlJzogMTAwIH0gfVxuICAgICAqL1xuICAgIHZhciBrZXlCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgYnkgcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gIHRocm91Z2hcbiAgICAgKiBgaXRlcmF0ZWVgLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBNYW55IGxvZGFzaCBtZXRob2RzIGFyZSBndWFyZGVkIHRvIHdvcmsgYXMgaXRlcmF0ZWVzIGZvciBtZXRob2RzIGxpa2VcbiAgICAgKiBgXy5ldmVyeWAsIGBfLmZpbHRlcmAsIGBfLm1hcGAsIGBfLm1hcFZhbHVlc2AsIGBfLnJlamVjdGAsIGFuZCBgXy5zb21lYC5cbiAgICAgKlxuICAgICAqIFRoZSBndWFyZGVkIG1ldGhvZHMgYXJlOlxuICAgICAqIGBhcnlgLCBgY3VycnlgLCBgY3VycnlSaWdodGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBldmVyeWAsIGBmaWxsYCxcbiAgICAgKiBgaW52ZXJ0YCwgYHBhcnNlSW50YCwgYHJhbmRvbWAsIGByYW5nZWAsIGByYW5nZVJpZ2h0YCwgYHNsaWNlYCwgYHNvbWVgLFxuICAgICAqIGBzb3J0QnlgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGVtcGxhdGVgLCBgdHJpbWAsIGB0cmltRW5kYCwgYHRyaW1TdGFydGAsXG4gICAgICogYW5kIGB3b3Jkc2BcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWFwKFs0LCA4XSwgc3F1YXJlKTtcbiAgICAgKiAvLyA9PiBbMTYsIDY0XVxuICAgICAqXG4gICAgICogXy5tYXAoeyAnYSc6IDQsICdiJzogOCB9LCBzcXVhcmUpO1xuICAgICAqIC8vID0+IFsxNiwgNjRdIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1hcCh1c2VycywgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5TWFwIDogYmFzZU1hcDtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0QnlgIGV4Y2VwdCB0aGF0IGl0IGFsbG93cyBzcGVjaWZ5aW5nIHRoZSBzb3J0XG4gICAgICogb3JkZXJzIG9mIHRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS4gSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXNcbiAgICAgKiBhcmUgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlci4gT3RoZXJ3aXNlLCBzcGVjaWZ5IGFuIG9yZGVyIG9mIFwiZGVzY1wiIGZvclxuICAgICAqIGRlc2NlbmRpbmcgb3IgXCJhc2NcIiBmb3IgYXNjZW5kaW5nIHNvcnQgb3JkZXIgb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW118T2JqZWN0W118c3RyaW5nW119IFtpdGVyYXRlZXM9W18uaWRlbnRpdHldXSBUaGUgaXRlcmF0ZWVzIHRvIHNvcnQgYnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gW29yZGVyc10gVGhlIHNvcnQgb3JkZXJzIG9mIGBpdGVyYXRlZXNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQ4IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDIgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gU29ydCBieSBgdXNlcmAgaW4gYXNjZW5kaW5nIG9yZGVyIGFuZCBieSBgYWdlYCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICAgICAqIF8ub3JkZXJCeSh1c2VycywgWyd1c2VyJywgJ2FnZSddLCBbJ2FzYycsICdkZXNjJ10pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgNDJdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9yZGVyQnkoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMsIGd1YXJkKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNBcnJheShpdGVyYXRlZXMpKSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IGl0ZXJhdGVlcyA9PSBudWxsID8gW10gOiBbaXRlcmF0ZWVzXTtcbiAgICAgIH1cbiAgICAgIG9yZGVycyA9IGd1YXJkID8gdW5kZWZpbmVkIDogb3JkZXJzO1xuICAgICAgaWYgKCFpc0FycmF5KG9yZGVycykpIHtcbiAgICAgICAgb3JkZXJzID0gb3JkZXJzID09IG51bGwgPyBbXSA6IFtvcmRlcnNdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VPcmRlckJ5KGNvbGxlY3Rpb24sIGl0ZXJhdGVlcywgb3JkZXJzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzIHNwbGl0IGludG8gdHdvIGdyb3VwcywgdGhlIGZpcnN0IG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLCB0aGUgc2Vjb25kIG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkgZm9yLiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxLCAgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5wYXJ0aXRpb24odXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydmcmVkJ10sIFsnYmFybmV5JywgJ3BlYmJsZXMnXV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5wYXJ0aXRpb24odXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydwZWJibGVzJ10sIFsnYmFybmV5JywgJ2ZyZWQnXV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnBhcnRpdGlvbih1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsICdwZWJibGVzJ10sIFsnZnJlZCddXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5wYXJ0aXRpb24odXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydmcmVkJ10sIFsnYmFybmV5JywgJ3BlYmJsZXMnXV1cbiAgICAgKi9cbiAgICB2YXIgcGFydGl0aW9uID0gY3JlYXRlQWdncmVnYXRvcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIHJlc3VsdFtrZXkgPyAwIDogMV0ucHVzaCh2YWx1ZSk7XG4gICAgfSwgZnVuY3Rpb24oKSB7IHJldHVybiBbW10sIFtdXTsgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZWR1Y2VzIGBjb2xsZWN0aW9uYCB0byBhIHZhbHVlIHdoaWNoIGlzIHRoZSBhY2N1bXVsYXRlZCByZXN1bHQgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAgdGhyb3VnaCBgaXRlcmF0ZWVgLCB3aGVyZSBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgKiBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLiBJZiBgYWNjdW11bGF0b3JgXG4gICAgICogaXMgbm90IGdpdmVuIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCBpcyB1c2VkIGFzIHRoZSBpbml0aWFsXG4gICAgICogdmFsdWUuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6XG4gICAgICogKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIE1hbnkgbG9kYXNoIG1ldGhvZHMgYXJlIGd1YXJkZWQgdG8gd29yayBhcyBpdGVyYXRlZXMgZm9yIG1ldGhvZHMgbGlrZVxuICAgICAqIGBfLnJlZHVjZWAsIGBfLnJlZHVjZVJpZ2h0YCwgYW5kIGBfLnRyYW5zZm9ybWAuXG4gICAgICpcbiAgICAgKiBUaGUgZ3VhcmRlZCBtZXRob2RzIGFyZTpcbiAgICAgKiBgYXNzaWduYCwgYGRlZmF1bHRzYCwgYGRlZmF1bHRzRGVlcGAsIGBpbmNsdWRlc2AsIGBtZXJnZWAsIGBvcmRlckJ5YCxcbiAgICAgKiBhbmQgYHNvcnRCeWBcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlKFsxLCAyXSwgZnVuY3Rpb24oc3VtLCBuKSB7XG4gICAgICogICByZXR1cm4gc3VtICsgbjtcbiAgICAgKiB9LCAwKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnJlZHVjZSh7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfSwgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICogICAocmVzdWx0W3ZhbHVlXSB8fCAocmVzdWx0W3ZhbHVlXSA9IFtdKSkucHVzaChrZXkpO1xuICAgICAqICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgKiB9LCB7fSk7XG4gICAgICogLy8gPT4geyAnMSc6IFsnYScsICdjJ10sICcyJzogWydiJ10gfSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlZHVjZShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5UmVkdWNlIDogYmFzZVJlZHVjZSxcbiAgICAgICAgICBpbml0QWNjdW0gPSBhcmd1bWVudHMubGVuZ3RoIDwgMztcblxuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDQpLCBhY2N1bXVsYXRvciwgaW5pdEFjY3VtLCBiYXNlRWFjaCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5yZWR1Y2VgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW1swLCAxXSwgWzIsIDNdLCBbNCwgNV1dO1xuICAgICAqXG4gICAgICogXy5yZWR1Y2VSaWdodChhcnJheSwgZnVuY3Rpb24oZmxhdHRlbmVkLCBvdGhlcikge1xuICAgICAqICAgcmV0dXJuIGZsYXR0ZW5lZC5jb25jYXQob3RoZXIpO1xuICAgICAqIH0sIFtdKTtcbiAgICAgKiAvLyA9PiBbNCwgNSwgMiwgMywgMCwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWR1Y2VSaWdodChjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5UmVkdWNlUmlnaHQgOiBiYXNlUmVkdWNlLFxuICAgICAgICAgIGluaXRBY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuXG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgNCksIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0sIGJhc2VFYWNoUmlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5maWx0ZXJgOyB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmBcbiAgICAgKiB0aGF0IGBwcmVkaWNhdGVgIGRvZXMgKipub3QqKiByZXR1cm4gdHJ1dGh5IGZvci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnJlamVjdCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2ZyZWQnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgeyAnYWdlJzogNDAsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnJlamVjdCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5J11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWplY3QoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUZpbHRlciA6IGJhc2VGaWx0ZXI7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiAhcHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgcmFuZG9tIGVsZW1lbnQgZnJvbSBgY29sbGVjdGlvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmFuZG9tIGVsZW1lbnQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2FtcGxlKFsxLCAyLCAzLCA0XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNhbXBsZShjb2xsZWN0aW9uKSB7XG4gICAgICB2YXIgYXJyYXkgPSBpc0FycmF5TGlrZShjb2xsZWN0aW9uKSA/IGNvbGxlY3Rpb24gOiB2YWx1ZXMoY29sbGVjdGlvbiksXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICByZXR1cm4gbGVuZ3RoID4gMCA/IGFycmF5W2Jhc2VSYW5kb20oMCwgbGVuZ3RoIC0gMSldIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYG5gIHJhbmRvbSBlbGVtZW50cyBhdCB1bmlxdWUga2V5cyBmcm9tIGBjb2xsZWN0aW9uYCB1cCB0byB0aGVcbiAgICAgKiBzaXplIG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0wXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zYW1wbGVTaXplKFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzMsIDFdXG4gICAgICpcbiAgICAgKiBfLnNhbXBsZVNpemUoWzEsIDIsIDNdLCA0KTtcbiAgICAgKiAvLyA9PiBbMiwgMywgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW1wbGVTaXplKGNvbGxlY3Rpb24sIG4pIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IHRvQXJyYXkoY29sbGVjdGlvbiksXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aCxcbiAgICAgICAgICBsYXN0SW5kZXggPSBsZW5ndGggLSAxO1xuXG4gICAgICBuID0gYmFzZUNsYW1wKHRvSW50ZWdlcihuKSwgMCwgbGVuZ3RoKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbikge1xuICAgICAgICB2YXIgcmFuZCA9IGJhc2VSYW5kb20oaW5kZXgsIGxhc3RJbmRleCksXG4gICAgICAgICAgICB2YWx1ZSA9IHJlc3VsdFtyYW5kXTtcblxuICAgICAgICByZXN1bHRbcmFuZF0gPSByZXN1bHRbaW5kZXhdO1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXN1bHQubGVuZ3RoID0gbjtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBzaHVmZmxlZCB2YWx1ZXMsIHVzaW5nIGEgdmVyc2lvbiBvZiB0aGVcbiAgICAgKiBbRmlzaGVyLVlhdGVzIHNodWZmbGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlci1ZYXRlc19zaHVmZmxlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2h1ZmZsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzaHVmZmxlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zaHVmZmxlKFsxLCAyLCAzLCA0XSk7XG4gICAgICogLy8gPT4gWzQsIDEsIDMsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2h1ZmZsZShjb2xsZWN0aW9uKSB7XG4gICAgICByZXR1cm4gc2FtcGxlU2l6ZShjb2xsZWN0aW9uLCBNQVhfQVJSQVlfTEVOR1RIKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzaXplIG9mIGBjb2xsZWN0aW9uYCBieSByZXR1cm5pbmcgaXRzIGxlbmd0aCBmb3IgYXJyYXktbGlrZVxuICAgICAqIHZhbHVlcyBvciB0aGUgbnVtYmVyIG9mIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXMgZm9yIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29sbGVjdGlvbiBzaXplLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNpemUoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnNpemUoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICpcbiAgICAgKiBfLnNpemUoJ3BlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiA3XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2l6ZShjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIChyZXN1bHQgJiYgaXNTdHJpbmcoY29sbGVjdGlvbikpID8gc3RyaW5nU2l6ZShjb2xsZWN0aW9uKSA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBrZXlzKGNvbGxlY3Rpb24pLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yICoqYW55KiogZWxlbWVudCBvZiBgY29sbGVjdGlvbmAuXG4gICAgICogSXRlcmF0aW9uIGlzIHN0b3BwZWQgb25jZSBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeS4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW55IGVsZW1lbnQgcGFzc2VzIHRoZSBwcmVkaWNhdGUgY2hlY2ssIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb21lKFtudWxsLCAwLCAneWVzJywgZmFsc2VdLCBCb29sZWFuKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zb21lKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29tZSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29tZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb21lKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZ3VhcmQpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5U29tZSA6IGJhc2VTb21lO1xuICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZ3VhcmQpKSB7XG4gICAgICAgIHByZWRpY2F0ZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZWxlbWVudHMsIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXIgYnkgdGhlIHJlc3VsdHMgb2ZcbiAgICAgKiBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBhIGNvbGxlY3Rpb24gdGhyb3VnaCBlYWNoIGl0ZXJhdGVlLiBUaGlzIG1ldGhvZFxuICAgICAqIHBlcmZvcm1zIGEgc3RhYmxlIHNvcnQsIHRoYXQgaXMsIGl0IHByZXNlcnZlcyB0aGUgb3JpZ2luYWwgc29ydCBvcmRlciBvZlxuICAgICAqIGVxdWFsIGVsZW1lbnRzLiBUaGUgaXRlcmF0ZWVzIGFyZSBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXXxPYmplY3R8T2JqZWN0W118c3RyaW5nfHN0cmluZ1tdKX0gW2l0ZXJhdGVlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieSwgc3BlY2lmaWVkIGluZGl2aWR1YWxseSBvciBpbiBhcnJheXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgc29ydGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0OCB9LFxuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQyIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uc29ydEJ5KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLnVzZXI7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgNDJdXVxuICAgICAqXG4gICAgICogXy5zb3J0QnkodXNlcnMsIFsndXNlcicsICdhZ2UnXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snYmFybmV5JywgMzRdLCBbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDJdLCBbJ2ZyZWQnLCA0OF1dXG4gICAgICpcbiAgICAgKiBfLnNvcnRCeSh1c2VycywgJ3VzZXInLCBmdW5jdGlvbihvKSB7XG4gICAgICogICByZXR1cm4gTWF0aC5mbG9vcihvLmFnZSAvIDEwKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydiYXJuZXknLCAzNl0sIFsnYmFybmV5JywgMzRdLCBbJ2ZyZWQnLCA0OF0sIFsnZnJlZCcsIDQyXV1cbiAgICAgKi9cbiAgICB2YXIgc29ydEJ5ID0gcmVzdChmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZXMpIHtcbiAgICAgIGlmIChjb2xsZWN0aW9uID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IGl0ZXJhdGVlcy5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoID4gMSAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBpdGVyYXRlZXNbMF0sIGl0ZXJhdGVlc1sxXSkpIHtcbiAgICAgICAgaXRlcmF0ZWVzID0gW107XG4gICAgICB9IGVsc2UgaWYgKGxlbmd0aCA+IDIgJiYgaXNJdGVyYXRlZUNhbGwoaXRlcmF0ZWVzWzBdLCBpdGVyYXRlZXNbMV0sIGl0ZXJhdGVlc1syXSkpIHtcbiAgICAgICAgaXRlcmF0ZWVzLmxlbmd0aCA9IDE7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZU9yZGVyQnkoY29sbGVjdGlvbiwgYmFzZUZsYXR0ZW4oaXRlcmF0ZWVzLCAxKSwgW10pO1xuICAgIH0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gICAgICogdGhlIFVuaXggZXBvY2ggKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAgICogQGNhdGVnb3J5IERhdGVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lc3RhbXAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmZXIoZnVuY3Rpb24oc3RhbXApIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gICAgICogfSwgXy5ub3coKSk7XG4gICAgICogLy8gPT4gbG9ncyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBpdCB0b29rIGZvciB0aGUgZGVmZXJyZWQgZnVuY3Rpb24gdG8gYmUgaW52b2tlZFxuICAgICAqL1xuICAgIHZhciBub3cgPSBEYXRlLm5vdztcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5iZWZvcmVgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogYGZ1bmNgIG9uY2UgaXQncyBjYWxsZWQgYG5gIG9yIG1vcmUgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGNhbGxzIGJlZm9yZSBgZnVuY2AgaXMgaW52b2tlZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F2ZXMgPSBbJ3Byb2ZpbGUnLCAnc2V0dGluZ3MnXTtcbiAgICAgKlxuICAgICAqIHZhciBkb25lID0gXy5hZnRlcihzYXZlcy5sZW5ndGgsIGZ1bmN0aW9uKCkge1xuICAgICAqICAgY29uc29sZS5sb2coJ2RvbmUgc2F2aW5nIScpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5mb3JFYWNoKHNhdmVzLCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICogICBhc3luY1NhdmUoeyAndHlwZSc6IHR5cGUsICdjb21wbGV0ZSc6IGRvbmUgfSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyAnZG9uZSBzYXZpbmchJyBhZnRlciB0aGUgdHdvIGFzeW5jIHNhdmVzIGhhdmUgY29tcGxldGVkXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWZ0ZXIobiwgZnVuYykge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKC0tbiA8IDEpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdXAgdG8gYG5gIGFyZ3VtZW50cywgaWdub3JpbmcgYW55XG4gICAgICogYWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249ZnVuYy5sZW5ndGhdIFRoZSBhcml0eSBjYXAuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1hcChbJzYnLCAnOCcsICcxMCddLCBfLmFyeShwYXJzZUludCwgMSkpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnkoZnVuYywgbiwgZ3VhcmQpIHtcbiAgICAgIG4gPSBndWFyZCA/IHVuZGVmaW5lZCA6IG47XG4gICAgICBuID0gKGZ1bmMgJiYgbiA9PSBudWxsKSA/IGZ1bmMubGVuZ3RoIDogbjtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwcGVyKGZ1bmMsIEFSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgLCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzXG4gICAgICogb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24sIHdoaWxlIGl0J3MgY2FsbGVkIGxlc3MgdGhhbiBgbmAgdGltZXMuIFN1YnNlcXVlbnRcbiAgICAgKiBjYWxscyB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgY2FsbHMgYXQgd2hpY2ggYGZ1bmNgIGlzIG5vIGxvbmdlciBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmJlZm9yZSg1LCBhZGRDb250YWN0VG9MaXN0KSk7XG4gICAgICogLy8gPT4gYWxsb3dzIGFkZGluZyB1cCB0byA0IGNvbnRhY3RzIHRvIHRoZSBsaXN0XG4gICAgICovXG4gICAgZnVuY3Rpb24gYmVmb3JlKG4sIGZ1bmMpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoLS1uID4gMCkge1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobiA8PSAxKSB7XG4gICAgICAgICAgZnVuYyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiBgdGhpc0FyZ2BcbiAgICAgKiBhbmQgcHJlcGVuZHMgYW55IGFkZGl0aW9uYWwgYF8uYmluZGAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZVxuICAgICAqIGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogVGhlIGBfLmJpbmQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpYyBidWlsZHMsXG4gICAgICogbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBuYXRpdmUgYEZ1bmN0aW9uI2JpbmRgIHRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiXG4gICAgICogcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmluZC5cbiAgICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGdyZWV0ID0gZnVuY3Rpb24oZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZChncmVldCwgb2JqZWN0LCAnaGknKTtcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkISdcbiAgICAgKlxuICAgICAqIC8vIEJvdW5kIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZChncmVldCwgb2JqZWN0LCBfLCAnIScpO1xuICAgICAqIGJvdW5kKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkISdcbiAgICAgKi9cbiAgICB2YXIgYmluZCA9IHJlc3QoZnVuY3Rpb24oZnVuYywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gQklORF9GTEFHO1xuICAgICAgaWYgKHBhcnRpYWxzLmxlbmd0aCkge1xuICAgICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBnZXRQbGFjZWhvbGRlcihiaW5kKSk7XG4gICAgICAgIGJpdG1hc2sgfD0gUEFSVElBTF9GTEFHO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBvYmplY3Rba2V5XWAgYW5kIHByZXBlbmRzXG4gICAgICogYW55IGFkZGl0aW9uYWwgYF8uYmluZEtleWAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBib3VuZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGRpZmZlcnMgZnJvbSBgXy5iaW5kYCBieSBhbGxvd2luZyBib3VuZCBmdW5jdGlvbnMgdG8gcmVmZXJlbmNlXG4gICAgICogbWV0aG9kcyB0aGF0IG1heSBiZSByZWRlZmluZWQgb3IgZG9uJ3QgeWV0IGV4aXN0LlxuICAgICAqIFNlZSBbUGV0ZXIgTWljaGF1eCdzIGFydGljbGVdKGh0dHA6Ly9wZXRlci5taWNoYXV4LmNhL2FydGljbGVzL2xhenktZnVuY3Rpb24tZGVmaW5pdGlvbi1wYXR0ZXJuKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZEtleS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7XG4gICAgICogICAndXNlcic6ICdmcmVkJyxcbiAgICAgKiAgICdncmVldCc6IGZ1bmN0aW9uKGdyZWV0aW5nLCBwdW5jdHVhdGlvbikge1xuICAgICAqICAgICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAgICAgKiAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kS2V5KG9iamVjdCwgJ2dyZWV0JywgJ2hpJyk7XG4gICAgICogYm91bmQoJyEnKTtcbiAgICAgKiAvLyA9PiAnaGkgZnJlZCEnXG4gICAgICpcbiAgICAgKiBvYmplY3QuZ3JlZXQgPSBmdW5jdGlvbihncmVldGluZywgcHVuY3R1YXRpb24pIHtcbiAgICAgKiAgIHJldHVybiBncmVldGluZyArICd5YSAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpeWEgZnJlZCEnXG4gICAgICpcbiAgICAgKiAvLyBCb3VuZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiB2YXIgYm91bmQgPSBfLmJpbmRLZXkob2JqZWN0LCAnZ3JlZXQnLCBfLCAnIScpO1xuICAgICAqIGJvdW5kKCdoaScpO1xuICAgICAqIC8vID0+ICdoaXlhIGZyZWQhJ1xuICAgICAqL1xuICAgIHZhciBiaW5kS2V5ID0gcmVzdChmdW5jdGlvbihvYmplY3QsIGtleSwgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gQklORF9GTEFHIHwgQklORF9LRVlfRkxBRztcbiAgICAgIGlmIChwYXJ0aWFscy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0UGxhY2Vob2xkZXIoYmluZEtleSkpO1xuICAgICAgICBiaXRtYXNrIHw9IFBBUlRJQUxfRkxBRztcbiAgICAgIH1cbiAgICAgIHJldHVybiBjcmVhdGVXcmFwcGVyKGtleSwgYml0bWFzaywgb2JqZWN0LCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIGFyZ3VtZW50cyBvZiBgZnVuY2AgYW5kIGVpdGhlciBpbnZva2VzXG4gICAgICogYGZ1bmNgIHJldHVybmluZyBpdHMgcmVzdWx0LCBpZiBhdCBsZWFzdCBgYXJpdHlgIG51bWJlciBvZiBhcmd1bWVudHMgaGF2ZVxuICAgICAqIGJlZW4gcHJvdmlkZWQsIG9yIHJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdGhlIHJlbWFpbmluZyBgZnVuY2BcbiAgICAgKiBhcmd1bWVudHMsIGFuZCBzbyBvbi4gVGhlIGFyaXR5IG9mIGBmdW5jYCBtYXkgYmUgc3BlY2lmaWVkIGlmIGBmdW5jLmxlbmd0aGBcbiAgICAgKiBpcyBub3Qgc3VmZmljaWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljIGJ1aWxkcyxcbiAgICAgKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgY3VycmllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5PWZ1bmMubGVuZ3RoXSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYWJjID0gZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGN1cnJpZWQgPSBfLmN1cnJ5KGFiYyk7XG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEpKDIpKDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyKSgzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSwgMiwgMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiAvLyBDdXJyaWVkIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIGN1cnJpZWQoMSkoXywgMykoMik7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3VycnkoZnVuYywgYXJpdHksIGd1YXJkKSB7XG4gICAgICBhcml0eSA9IGd1YXJkID8gdW5kZWZpbmVkIDogYXJpdHk7XG4gICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlV3JhcHBlcihmdW5jLCBDVVJSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnkucGxhY2Vob2xkZXI7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY3VycnlgIGV4Y2VwdCB0aGF0IGFyZ3VtZW50cyBhcmUgYXBwbGllZCB0byBgZnVuY2BcbiAgICAgKiBpbiB0aGUgbWFubmVyIG9mIGBfLnBhcnRpYWxSaWdodGAgaW5zdGVhZCBvZiBgXy5wYXJ0aWFsYC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeVJpZ2h0LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBjdXJyaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHk9ZnVuYy5sZW5ndGhdIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhYmMgPSBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICogICByZXR1cm4gW2EsIGIsIGNdO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgY3VycmllZCA9IF8uY3VycnlSaWdodChhYmMpO1xuICAgICAqXG4gICAgICogY3VycmllZCgzKSgyKSgxKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMiwgMykoMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIsIDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogLy8gQ3VycmllZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiBjdXJyaWVkKDMpKDEsIF8pKDIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1cnJ5UmlnaHQoZnVuYywgYXJpdHksIGd1YXJkKSB7XG4gICAgICBhcml0eSA9IGd1YXJkID8gdW5kZWZpbmVkIDogYXJpdHk7XG4gICAgICB2YXIgcmVzdWx0ID0gY3JlYXRlV3JhcHBlcihmdW5jLCBDVVJSWV9SSUdIVF9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnlSaWdodC5wbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gICAgICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gICAgICogaW52b2tlZC4gVGhlIGRlYm91bmNlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGAgbWV0aG9kIHRvIGNhbmNlbFxuICAgICAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICAgICAqIFByb3ZpZGUgYW4gb3B0aW9ucyBvYmplY3QgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb25cbiAgICAgKiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhlIGxhc3QgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnQgY2FsbHNcbiAgICAgKiB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYCBpbnZvY2F0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpcyBpbnZva2VkXG4gICAgICogb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIGlzXG4gICAgICogaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICAgICAqXG4gICAgICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHA6Ly9kcnVwYWxtb3Rpb24uY29tL2FydGljbGUvZGVib3VuY2UtYW5kLXRocm90dGxlLXZpc3VhbC1leHBsYW5hdGlvbilcbiAgICAgKiBmb3IgZGV0YWlscyBvdmVyIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGBfLmRlYm91bmNlYCBhbmQgYF8udGhyb3R0bGVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVib3VuY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz1mYWxzZV0gU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZ1xuICAgICAqICBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XSBUaGUgbWF4aW11bSB0aW1lIGBmdW5jYCBpcyBhbGxvd2VkIHRvIGJlXG4gICAgICogIGRlbGF5ZWQgYmVmb3JlIGl0J3MgaW52b2tlZC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nXG4gICAgICogIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZGVib3VuY2VkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBBdm9pZCBjb3N0bHkgY2FsY3VsYXRpb25zIHdoaWxlIHRoZSB3aW5kb3cgc2l6ZSBpcyBpbiBmbHV4LlxuICAgICAqIGpRdWVyeSh3aW5kb3cpLm9uKCdyZXNpemUnLCBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSk7XG4gICAgICpcbiAgICAgKiAvLyBJbnZva2UgYHNlbmRNYWlsYCB3aGVuIGNsaWNrZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxscy5cbiAgICAgKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5kZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gICAgICogICAnbGVhZGluZyc6IHRydWUsXG4gICAgICogICAndHJhaWxpbmcnOiBmYWxzZVxuICAgICAqIH0pKTtcbiAgICAgKlxuICAgICAqIC8vIEVuc3VyZSBgYmF0Y2hMb2dgIGlzIGludm9rZWQgb25jZSBhZnRlciAxIHNlY29uZCBvZiBkZWJvdW5jZWQgY2FsbHMuXG4gICAgICogdmFyIGRlYm91bmNlZCA9IF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwgeyAnbWF4V2FpdCc6IDEwMDAgfSk7XG4gICAgICogdmFyIHNvdXJjZSA9IG5ldyBFdmVudFNvdXJjZSgnL3N0cmVhbScpO1xuICAgICAqIGpRdWVyeShzb3VyY2UpLm9uKCdtZXNzYWdlJywgZGVib3VuY2VkKTtcbiAgICAgKlxuICAgICAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3BvcHN0YXRlJywgZGVib3VuY2VkLmNhbmNlbCk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgICAgdmFyIGFyZ3MsXG4gICAgICAgICAgbWF4VGltZW91dElkLFxuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICBzdGFtcCxcbiAgICAgICAgICB0aGlzQXJnLFxuICAgICAgICAgIHRpbWVvdXRJZCxcbiAgICAgICAgICB0cmFpbGluZ0NhbGwsXG4gICAgICAgICAgbGFzdENhbGxlZCA9IDAsXG4gICAgICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgICAgIG1heFdhaXQgPSBmYWxzZSxcbiAgICAgICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHdhaXQgPSB0b051bWJlcih3YWl0KSB8fCAwO1xuICAgICAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICAgIGxlYWRpbmcgPSAhIW9wdGlvbnMubGVhZGluZztcbiAgICAgICAgbWF4V2FpdCA9ICdtYXhXYWl0JyBpbiBvcHRpb25zICYmIG5hdGl2ZU1heCh0b051bWJlcihvcHRpb25zLm1heFdhaXQpIHx8IDAsIHdhaXQpO1xuICAgICAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjYW5jZWwoKSB7XG4gICAgICAgIGlmICh0aW1lb3V0SWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF4VGltZW91dElkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KG1heFRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICAgICAgbGFzdENhbGxlZCA9IDA7XG4gICAgICAgIGFyZ3MgPSBtYXhUaW1lb3V0SWQgPSB0aGlzQXJnID0gdGltZW91dElkID0gdHJhaWxpbmdDYWxsID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBjb21wbGV0ZShpc0NhbGxlZCwgaWQpIHtcbiAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGlkKTtcbiAgICAgICAgfVxuICAgICAgICBtYXhUaW1lb3V0SWQgPSB0aW1lb3V0SWQgPSB0cmFpbGluZ0NhbGwgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChpc0NhbGxlZCkge1xuICAgICAgICAgIGxhc3RDYWxsZWQgPSBub3coKTtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICAgIGlmICghdGltZW91dElkICYmICFtYXhUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGFyZ3MgPSB0aGlzQXJnID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBkZWxheWVkKCkge1xuICAgICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3coKSAtIHN0YW1wKTtcbiAgICAgICAgaWYgKHJlbWFpbmluZyA8PSAwIHx8IHJlbWFpbmluZyA+IHdhaXQpIHtcbiAgICAgICAgICBjb21wbGV0ZSh0cmFpbGluZ0NhbGwsIG1heFRpbWVvdXRJZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChkZWxheWVkLCByZW1haW5pbmcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgICAgICBpZiAoKHRpbWVvdXRJZCAmJiB0cmFpbGluZ0NhbGwpIHx8IChtYXhUaW1lb3V0SWQgJiYgdHJhaWxpbmcpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBjYW5jZWwoKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gbWF4RGVsYXllZCgpIHtcbiAgICAgICAgY29tcGxldGUodHJhaWxpbmcsIHRpbWVvdXRJZCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgc3RhbXAgPSBub3coKTtcbiAgICAgICAgdGhpc0FyZyA9IHRoaXM7XG4gICAgICAgIHRyYWlsaW5nQ2FsbCA9IHRyYWlsaW5nICYmICh0aW1lb3V0SWQgfHwgIWxlYWRpbmcpO1xuXG4gICAgICAgIGlmIChtYXhXYWl0ID09PSBmYWxzZSkge1xuICAgICAgICAgIHZhciBsZWFkaW5nQ2FsbCA9IGxlYWRpbmcgJiYgIXRpbWVvdXRJZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIWxhc3RDYWxsZWQgJiYgIW1heFRpbWVvdXRJZCAmJiAhbGVhZGluZykge1xuICAgICAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgcmVtYWluaW5nID0gbWF4V2FpdCAtIChzdGFtcCAtIGxhc3RDYWxsZWQpO1xuXG4gICAgICAgICAgdmFyIGlzQ2FsbGVkID0gKHJlbWFpbmluZyA8PSAwIHx8IHJlbWFpbmluZyA+IG1heFdhaXQpICYmXG4gICAgICAgICAgICAobGVhZGluZyB8fCBtYXhUaW1lb3V0SWQpO1xuXG4gICAgICAgICAgaWYgKGlzQ2FsbGVkKSB7XG4gICAgICAgICAgICBpZiAobWF4VGltZW91dElkKSB7XG4gICAgICAgICAgICAgIG1heFRpbWVvdXRJZCA9IGNsZWFyVGltZW91dChtYXhUaW1lb3V0SWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoIW1heFRpbWVvdXRJZCkge1xuICAgICAgICAgICAgbWF4VGltZW91dElkID0gc2V0VGltZW91dChtYXhEZWxheWVkLCByZW1haW5pbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNDYWxsZWQgJiYgdGltZW91dElkKSB7XG4gICAgICAgICAgdGltZW91dElkID0gY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRpbWVvdXRJZCAmJiB3YWl0ICE9PSBtYXhXYWl0KSB7XG4gICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChkZWxheWVkLCB3YWl0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGVhZGluZ0NhbGwpIHtcbiAgICAgICAgICBpc0NhbGxlZCA9IHRydWU7XG4gICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNDYWxsZWQgJiYgIXRpbWVvdXRJZCAmJiAhbWF4VGltZW91dElkKSB7XG4gICAgICAgICAgYXJncyA9IHRoaXNBcmcgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gICAgICBkZWJvdW5jZWQuZmx1c2ggPSBmbHVzaDtcbiAgICAgIHJldHVybiBkZWJvdW5jZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVmZXJzIGludm9raW5nIHRoZSBgZnVuY2AgdW50aWwgdGhlIGN1cnJlbnQgY2FsbCBzdGFjayBoYXMgY2xlYXJlZC4gQW55XG4gICAgICogYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0J3MgaW52b2tlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlZmVyLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHRpbWVyIGlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmVyKGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKHRleHQpO1xuICAgICAqIH0sICdkZWZlcnJlZCcpO1xuICAgICAqIC8vID0+IGxvZ3MgJ2RlZmVycmVkJyBhZnRlciBvbmUgb3IgbW9yZSBtaWxsaXNlY29uZHNcbiAgICAgKi9cbiAgICB2YXIgZGVmZXIgPSByZXN0KGZ1bmN0aW9uKGZ1bmMsIGFyZ3MpIHtcbiAgICAgIHJldHVybiBiYXNlRGVsYXkoZnVuYywgMSwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIGBmdW5jYCBhZnRlciBgd2FpdGAgbWlsbGlzZWNvbmRzLiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlXG4gICAgICogcHJvdmlkZWQgdG8gYGZ1bmNgIHdoZW4gaXQncyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkgaW52b2NhdGlvbi5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBgZnVuY2Agd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lciBpZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWxheShmdW5jdGlvbih0ZXh0KSB7XG4gICAgICogICBjb25zb2xlLmxvZyh0ZXh0KTtcbiAgICAgKiB9LCAxMDAwLCAnbGF0ZXInKTtcbiAgICAgKiAvLyA9PiBsb2dzICdsYXRlcicgYWZ0ZXIgb25lIHNlY29uZFxuICAgICAqL1xuICAgIHZhciBkZWxheSA9IHJlc3QoZnVuY3Rpb24oZnVuYywgd2FpdCwgYXJncykge1xuICAgICAgcmV0dXJuIGJhc2VEZWxheShmdW5jLCB0b051bWJlcih3YWl0KSB8fCAwLCBhcmdzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggYXJndW1lbnRzIHJldmVyc2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZmxpcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZmxpcHBlZCA9IF8uZmxpcChmdW5jdGlvbigpIHtcbiAgICAgKiAgIHJldHVybiBfLnRvQXJyYXkoYXJndW1lbnRzKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGZsaXBwZWQoJ2EnLCAnYicsICdjJywgJ2QnKTtcbiAgICAgKiAvLyA9PiBbJ2QnLCAnYycsICdiJywgJ2EnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsaXAoZnVuYykge1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgRkxJUF9GTEFHKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBtZW1vaXplcyB0aGUgcmVzdWx0IG9mIGBmdW5jYC4gSWYgYHJlc29sdmVyYCBpc1xuICAgICAqIHByb3ZpZGVkIGl0IGRldGVybWluZXMgdGhlIGNhY2hlIGtleSBmb3Igc3RvcmluZyB0aGUgcmVzdWx0IGJhc2VkIG9uIHRoZVxuICAgICAqIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24uIEJ5IGRlZmF1bHQsIHRoZSBmaXJzdCBhcmd1bWVudFxuICAgICAqIHByb3ZpZGVkIHRvIHRoZSBtZW1vaXplZCBmdW5jdGlvbiBpcyB1c2VkIGFzIHRoZSBtYXAgY2FjaGUga2V5LiBUaGUgYGZ1bmNgXG4gICAgICogaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhlIGNhY2hlIGlzIGV4cG9zZWQgYXMgdGhlIGBjYWNoZWAgcHJvcGVydHkgb24gdGhlIG1lbW9pemVkXG4gICAgICogZnVuY3Rpb24uIEl0cyBjcmVhdGlvbiBtYXkgYmUgY3VzdG9taXplZCBieSByZXBsYWNpbmcgdGhlIGBfLm1lbW9pemUuQ2FjaGVgXG4gICAgICogY29uc3RydWN0b3Igd2l0aCBvbmUgd2hvc2UgaW5zdGFuY2VzIGltcGxlbWVudCB0aGUgW2BNYXBgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1wcm9wZXJ0aWVzLW9mLXRoZS1tYXAtcHJvdG90eXBlLW9iamVjdClcbiAgICAgKiBtZXRob2QgaW50ZXJmYWNlIG9mIGBkZWxldGVgLCBgZ2V0YCwgYGhhc2AsIGFuZCBgc2V0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGhhdmUgaXRzIG91dHB1dCBtZW1vaXplZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcmVzb2x2ZXJdIFRoZSBmdW5jdGlvbiB0byByZXNvbHZlIHRoZSBjYWNoZSBrZXkuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbWVtb2l6aW5nIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ2MnOiAzLCAnZCc6IDQgfTtcbiAgICAgKlxuICAgICAqIHZhciB2YWx1ZXMgPSBfLm1lbW9pemUoXy52YWx1ZXMpO1xuICAgICAqIHZhbHVlcyhvYmplY3QpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogdmFsdWVzKG90aGVyKTtcbiAgICAgKiAvLyA9PiBbMywgNF1cbiAgICAgKlxuICAgICAqIG9iamVjdC5hID0gMjtcbiAgICAgKiB2YWx1ZXMob2JqZWN0KTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIC8vIE1vZGlmeSB0aGUgcmVzdWx0IGNhY2hlLlxuICAgICAqIHZhbHVlcy5jYWNoZS5zZXQob2JqZWN0LCBbJ2EnLCAnYiddKTtcbiAgICAgKiB2YWx1ZXMob2JqZWN0KTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYiddXG4gICAgICpcbiAgICAgKiAvLyBSZXBsYWNlIGBfLm1lbW9pemUuQ2FjaGVgLlxuICAgICAqIF8ubWVtb2l6ZS5DYWNoZSA9IFdlYWtNYXA7XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVtb2l6ZShmdW5jLCByZXNvbHZlcikge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicgfHwgKHJlc29sdmVyICYmIHR5cGVvZiByZXNvbHZlciAhPSAnZnVuY3Rpb24nKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICB2YXIgbWVtb2l6ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICBrZXkgPSByZXNvbHZlciA/IHJlc29sdmVyLmFwcGx5KHRoaXMsIGFyZ3MpIDogYXJnc1swXSxcbiAgICAgICAgICAgIGNhY2hlID0gbWVtb2l6ZWQuY2FjaGU7XG5cbiAgICAgICAgaWYgKGNhY2hlLmhhcyhrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGNhY2hlLmdldChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICBtZW1vaXplZC5jYWNoZSA9IGNhY2hlLnNldChrZXksIHJlc3VsdCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgICAgbWVtb2l6ZWQuY2FjaGUgPSBuZXcgbWVtb2l6ZS5DYWNoZTtcbiAgICAgIHJldHVybiBtZW1vaXplZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBuZWdhdGVzIHRoZSByZXN1bHQgb2YgdGhlIHByZWRpY2F0ZSBgZnVuY2AuIFRoZVxuICAgICAqIGBmdW5jYCBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzIG9mIHRoZVxuICAgICAqIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIHByZWRpY2F0ZSB0byBuZWdhdGUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzRXZlbihuKSB7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcihbMSwgMiwgMywgNCwgNSwgNl0sIF8ubmVnYXRlKGlzRXZlbikpO1xuICAgICAqIC8vID0+IFsxLCAzLCA1XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5lZ2F0ZShwcmVkaWNhdGUpIHtcbiAgICAgIGlmICh0eXBlb2YgcHJlZGljYXRlICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gIXByZWRpY2F0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpcyByZXN0cmljdGVkIHRvIGludm9raW5nIGBmdW5jYCBvbmNlLiBSZXBlYXQgY2FsbHNcbiAgICAgKiB0byB0aGUgZnVuY3Rpb24gcmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgaW52b2NhdGlvbi4gVGhlIGBmdW5jYCBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBpbml0aWFsaXplID0gXy5vbmNlKGNyZWF0ZUFwcGxpY2F0aW9uKTtcbiAgICAgKiBpbml0aWFsaXplKCk7XG4gICAgICogaW5pdGlhbGl6ZSgpO1xuICAgICAqIC8vIGBpbml0aWFsaXplYCBpbnZva2VzIGBjcmVhdGVBcHBsaWNhdGlvbmAgb25jZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9uY2UoZnVuYykge1xuICAgICAgcmV0dXJuIGJlZm9yZSgyLCBmdW5jKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGFyZ3VtZW50cyB0cmFuc2Zvcm1lZCBieVxuICAgICAqIGNvcnJlc3BvbmRpbmcgYHRyYW5zZm9ybXNgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW3RyYW5zZm9ybXNdIFRoZSBmdW5jdGlvbnMgdG8gdHJhbnNmb3JtXG4gICAgICogYXJndW1lbnRzLCBzcGVjaWZpZWQgaW5kaXZpZHVhbGx5IG9yIGluIGFycmF5cy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZG91YmxlZChuKSB7XG4gICAgICogICByZXR1cm4gbiAqIDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlckFyZ3MoZnVuY3Rpb24oeCwgeSkge1xuICAgICAqICAgcmV0dXJuIFt4LCB5XTtcbiAgICAgKiB9LCBzcXVhcmUsIGRvdWJsZWQpO1xuICAgICAqXG4gICAgICogZnVuYyg5LCAzKTtcbiAgICAgKiAvLyA9PiBbODEsIDZdXG4gICAgICpcbiAgICAgKiBmdW5jKDEwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTAwLCAxMF1cbiAgICAgKi9cbiAgICB2YXIgb3ZlckFyZ3MgPSByZXN0KGZ1bmN0aW9uKGZ1bmMsIHRyYW5zZm9ybXMpIHtcbiAgICAgIHRyYW5zZm9ybXMgPSBhcnJheU1hcChiYXNlRmxhdHRlbih0cmFuc2Zvcm1zLCAxKSwgZ2V0SXRlcmF0ZWUoKSk7XG5cbiAgICAgIHZhciBmdW5jc0xlbmd0aCA9IHRyYW5zZm9ybXMubGVuZ3RoO1xuICAgICAgcmV0dXJuIHJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihhcmdzLmxlbmd0aCwgZnVuY3NMZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYXJnc1tpbmRleF0gPSB0cmFuc2Zvcm1zW2luZGV4XS5jYWxsKHRoaXMsIGFyZ3NbaW5kZXhdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXBwbHkoZnVuYywgdGhpcywgYXJncyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggYHBhcnRpYWxgIGFyZ3VtZW50cyBwcmVwZW5kZWRcbiAgICAgKiB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmJpbmRgIGV4Y2VwdFxuICAgICAqIGl0IGRvZXMgKipub3QqKiBhbHRlciB0aGUgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBUaGUgYF8ucGFydGlhbC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgcGFydGlhbGx5XG4gICAgICogYXBwbGllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkgYXJndW1lbnRzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhcnRpYWxseSBhcHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZ3JlZXQgPSBmdW5jdGlvbihncmVldGluZywgbmFtZSkge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgbmFtZTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWwoZ3JlZXQsICdoZWxsbycpO1xuICAgICAqIHNheUhlbGxvVG8oJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFBhcnRpYWxseSBhcHBsaWVkIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBncmVldEZyZWQgPSBfLnBhcnRpYWwoZ3JlZXQsIF8sICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsID0gcmVzdChmdW5jdGlvbihmdW5jLCBwYXJ0aWFscykge1xuICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0UGxhY2Vob2xkZXIocGFydGlhbCkpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgUEFSVElBTF9GTEFHLCB1bmRlZmluZWQsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucGFydGlhbGAgZXhjZXB0IHRoYXQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzXG4gICAgICogYXJlIGFwcGVuZGVkIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBUaGUgYF8ucGFydGlhbFJpZ2h0LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBwYXJ0aWFsbHlcbiAgICAgKiBhcHBsaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHBhcnRpYWxseSBhcHBseSBhcmd1bWVudHMgdG8uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFydGlhbGx5IGFwcGxpZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBncmVldCA9IGZ1bmN0aW9uKGdyZWV0aW5nLCBuYW1lKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyBuYW1lO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgZ3JlZXRGcmVkID0gXy5wYXJ0aWFsUmlnaHQoZ3JlZXQsICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqXG4gICAgICogLy8gUGFydGlhbGx5IGFwcGxpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWxSaWdodChncmVldCwgJ2hlbGxvJywgXyk7XG4gICAgICogc2F5SGVsbG9UbygnZnJlZCcpO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsUmlnaHQgPSByZXN0KGZ1bmN0aW9uKGZ1bmMsIHBhcnRpYWxzKSB7XG4gICAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBnZXRQbGFjZWhvbGRlcihwYXJ0aWFsUmlnaHQpKTtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwcGVyKGZ1bmMsIFBBUlRJQUxfUklHSFRfRkxBRywgdW5kZWZpbmVkLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGFyZ3VtZW50cyBhcnJhbmdlZCBhY2NvcmRpbmdcbiAgICAgKiB0byB0aGUgc3BlY2lmaWVkIGluZGV4ZXMgd2hlcmUgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBmaXJzdCBpbmRleCBpc1xuICAgICAqIHByb3ZpZGVkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCwgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBzZWNvbmQgaW5kZXggaXNcbiAgICAgKiBwcm92aWRlZCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZWFycmFuZ2UgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW10pfSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcmd1bWVudCBpbmRleGVzLFxuICAgICAqICBzcGVjaWZpZWQgaW5kaXZpZHVhbGx5IG9yIGluIGFycmF5cy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHJlYXJnZWQgPSBfLnJlYXJnKGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBbYSwgYiwgY107XG4gICAgICogfSwgMiwgMCwgMSk7XG4gICAgICpcbiAgICAgKiByZWFyZ2VkKCdiJywgJ2MnLCAnYScpXG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgdmFyIHJlYXJnID0gcmVzdChmdW5jdGlvbihmdW5jLCBpbmRleGVzKSB7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCBSRUFSR19GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBiYXNlRmxhdHRlbihpbmRleGVzLCAxKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGVcbiAgICAgKiBjcmVhdGVkIGZ1bmN0aW9uIGFuZCBhcmd1bWVudHMgZnJvbSBgc3RhcnRgIGFuZCBiZXlvbmQgcHJvdmlkZWQgYXMgYW4gYXJyYXkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gdGhlIFtyZXN0IHBhcmFtZXRlcl0oaHR0cHM6Ly9tZG4uaW8vcmVzdF9wYXJhbWV0ZXJzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD1mdW5jLmxlbmd0aC0xXSBUaGUgc3RhcnQgcG9zaXRpb24gb2YgdGhlIHJlc3QgcGFyYW1ldGVyLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F5ID0gXy5yZXN0KGZ1bmN0aW9uKHdoYXQsIG5hbWVzKSB7XG4gICAgICogICByZXR1cm4gd2hhdCArICcgJyArIF8uaW5pdGlhbChuYW1lcykuam9pbignLCAnKSArXG4gICAgICogICAgIChfLnNpemUobmFtZXMpID4gMSA/ICcsICYgJyA6ICcnKSArIF8ubGFzdChuYW1lcyk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBzYXkoJ2hlbGxvJywgJ2ZyZWQnLCAnYmFybmV5JywgJ3BlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzdChmdW5jLCBzdGFydCkge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSBuYXRpdmVNYXgoc3RhcnQgPT09IHVuZGVmaW5lZCA/IChmdW5jLmxlbmd0aCAtIDEpIDogdG9JbnRlZ2VyKHN0YXJ0KSwgMCk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1heChhcmdzLmxlbmd0aCAtIHN0YXJ0LCAwKSxcbiAgICAgICAgICAgIGFycmF5ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGFycmF5W2luZGV4XSA9IGFyZ3Nbc3RhcnQgKyBpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgc3dpdGNoIChzdGFydCkge1xuICAgICAgICAgIGNhc2UgMDogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzLCBhcnJheSk7XG4gICAgICAgICAgY2FzZSAxOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIGFyZ3NbMF0sIGFycmF5KTtcbiAgICAgICAgICBjYXNlIDI6IHJldHVybiBmdW5jLmNhbGwodGhpcywgYXJnc1swXSwgYXJnc1sxXSwgYXJyYXkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdGhlckFyZ3MgPSBBcnJheShzdGFydCArIDEpO1xuICAgICAgICBpbmRleCA9IC0xO1xuICAgICAgICB3aGlsZSAoKytpbmRleCA8IHN0YXJ0KSB7XG4gICAgICAgICAgb3RoZXJBcmdzW2luZGV4XSA9IGFyZ3NbaW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIG90aGVyQXJnc1tzdGFydF0gPSBhcnJheTtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHRoaXMsIG90aGVyQXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkXG4gICAgICogZnVuY3Rpb24gYW5kIGFuIGFycmF5IG9mIGFyZ3VtZW50cyBtdWNoIGxpa2UgW2BGdW5jdGlvbiNhcHBseWBdKGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjMuNC4zKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiB0aGUgW3NwcmVhZCBvcGVyYXRvcl0oaHR0cHM6Ly9tZG4uaW8vc3ByZWFkX29wZXJhdG9yKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHNwcmVhZCBhcmd1bWVudHMgb3Zlci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgc3ByZWFkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F5ID0gXy5zcHJlYWQoZnVuY3Rpb24od2hvLCB3aGF0KSB7XG4gICAgICogICByZXR1cm4gd2hvICsgJyBzYXlzICcgKyB3aGF0O1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogc2F5KFsnZnJlZCcsICdoZWxsbyddKTtcbiAgICAgKiAvLyA9PiAnZnJlZCBzYXlzIGhlbGxvJ1xuICAgICAqXG4gICAgICogdmFyIG51bWJlcnMgPSBQcm9taXNlLmFsbChbXG4gICAgICogICBQcm9taXNlLnJlc29sdmUoNDApLFxuICAgICAqICAgUHJvbWlzZS5yZXNvbHZlKDM2KVxuICAgICAqIF0pO1xuICAgICAqXG4gICAgICogbnVtYmVycy50aGVuKF8uc3ByZWFkKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHJldHVybiB4ICsgeTtcbiAgICAgKiB9KSk7XG4gICAgICogLy8gPT4gYSBQcm9taXNlIG9mIDc2XG4gICAgICovXG4gICAgZnVuY3Rpb24gc3ByZWFkKGZ1bmMsIHN0YXJ0KSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBzdGFydCA9IHN0YXJ0ID09PSB1bmRlZmluZWQgPyAwIDogbmF0aXZlTWF4KHRvSW50ZWdlcihzdGFydCksIDApO1xuICAgICAgcmV0dXJuIHJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgYXJyYXkgPSBhcmdzW3N0YXJ0XSxcbiAgICAgICAgICAgIG90aGVyQXJncyA9IGFyZ3Muc2xpY2UoMCwgc3RhcnQpO1xuXG4gICAgICAgIGlmIChhcnJheSkge1xuICAgICAgICAgIGFycmF5UHVzaChvdGhlckFyZ3MsIGFycmF5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXBwbHkoZnVuYywgdGhpcywgb3RoZXJBcmdzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSB0aHJvdHRsZWQgZnVuY3Rpb24gdGhhdCBvbmx5IGludm9rZXMgYGZ1bmNgIGF0IG1vc3Qgb25jZSBwZXJcbiAgICAgKiBldmVyeSBgd2FpdGAgbWlsbGlzZWNvbmRzLiBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uIGNvbWVzIHdpdGggYSBgY2FuY2VsYFxuICAgICAqIG1ldGhvZCB0byBjYW5jZWwgZGVsYXllZCBgZnVuY2AgaW52b2NhdGlvbnMgYW5kIGEgYGZsdXNoYCBtZXRob2QgdG9cbiAgICAgKiBpbW1lZGlhdGVseSBpbnZva2UgdGhlbS4gUHJvdmlkZSBhbiBvcHRpb25zIG9iamVjdCB0byBpbmRpY2F0ZSB3aGV0aGVyXG4gICAgICogYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZSBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGBcbiAgICAgKiB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWQgd2l0aCB0aGUgbGFzdCBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlXG4gICAgICogdGhyb3R0bGVkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50IGNhbGxzIHRvIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gcmV0dXJuIHRoZVxuICAgICAqIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgLCBgZnVuY2AgaXMgaW52b2tlZFxuICAgICAqIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRocm90dGxlZCBmdW5jdGlvbiBpc1xuICAgICAqIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAgICAgKlxuICAgICAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwOi8vZHJ1cGFsbW90aW9uLmNvbS9hcnRpY2xlL2RlYm91bmNlLWFuZC10aHJvdHRsZS12aXN1YWwtZXhwbGFuYXRpb24pXG4gICAgICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy50aHJvdHRsZWAgYW5kIGBfLmRlYm91bmNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBpbnZvY2F0aW9ucyB0by5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9dHJ1ZV0gU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZ1xuICAgICAqICBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV0gU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmdcbiAgICAgKiAgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB0aHJvdHRsZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIEF2b2lkIGV4Y2Vzc2l2ZWx5IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBzY3JvbGxpbmcuXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCkpO1xuICAgICAqXG4gICAgICogLy8gSW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXMuXG4gICAgICogdmFyIHRocm90dGxlZCA9IF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7ICd0cmFpbGluZyc6IGZhbHNlIH0pO1xuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCB0aHJvdHRsZWQpO1xuICAgICAqXG4gICAgICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyB0aHJvdHRsZWQgaW52b2NhdGlvbi5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCB0aHJvdHRsZWQuY2FuY2VsKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aHJvdHRsZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgICAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHtcbiAgICAgICAgJ2xlYWRpbmcnOiBsZWFkaW5nLFxuICAgICAgICAnbWF4V2FpdCc6IHdhaXQsXG4gICAgICAgICd0cmFpbGluZyc6IHRyYWlsaW5nXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHVwIHRvIG9uZSBhcmd1bWVudCwgaWdub3JpbmcgYW55XG4gICAgICogYWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzgnLCAnMTAnXSwgXy51bmFyeShwYXJzZUludCkpO1xuICAgICAqIC8vID0+IFs2LCA4LCAxMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmFyeShmdW5jKSB7XG4gICAgICByZXR1cm4gYXJ5KGZ1bmMsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb3ZpZGVzIGB2YWx1ZWAgdG8gdGhlIHdyYXBwZXIgZnVuY3Rpb24gYXMgaXRzXG4gICAgICogZmlyc3QgYXJndW1lbnQuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZnVuY3Rpb24gYXJlXG4gICAgICogYXBwZW5kZWQgdG8gdGhvc2UgcHJvdmlkZWQgdG8gdGhlIHdyYXBwZXIgZnVuY3Rpb24uIFRoZSB3cmFwcGVyIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3dyYXBwZXI9aWRlbnRpdHldIFRoZSB3cmFwcGVyIGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgcCA9IF8ud3JhcChfLmVzY2FwZSwgZnVuY3Rpb24oZnVuYywgdGV4dCkge1xuICAgICAqICAgcmV0dXJuICc8cD4nICsgZnVuYyh0ZXh0KSArICc8L3A+JztcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHAoJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJzxwPmZyZWQsIGJhcm5leSwgJmFtcDsgcGViYmxlczwvcD4nXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcCh2YWx1ZSwgd3JhcHBlcikge1xuICAgICAgd3JhcHBlciA9IHdyYXBwZXIgPT0gbnVsbCA/IGlkZW50aXR5IDogd3JhcHBlcjtcbiAgICAgIHJldHVybiBwYXJ0aWFsKHdyYXBwZXIsIHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgdmFsdWVgIGFzIGFuIGFycmF5IGlmIGl0J3Mgbm90IG9uZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNhc3QgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KDEpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkoeyAnYSc6IDEgfSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxIH1dXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSgnYWJjJyk7XG4gICAgICogLy8gPT4gWydhYmMnXVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkobnVsbCk7XG4gICAgICogLy8gPT4gW251bGxdXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSh1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IFt1bmRlZmluZWRdXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSgpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICogY29uc29sZS5sb2coXy5jYXN0QXJyYXkoYXJyYXkpID09PSBhcnJheSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RBcnJheSgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgdmFsdWUgPSBhcmd1bWVudHNbMF07XG4gICAgICByZXR1cm4gaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNoYWxsb3cgY2xvbmUgb2YgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uIHRoZVxuICAgICAqIFtzdHJ1Y3R1cmVkIGNsb25lIGFsZ29yaXRobV0oaHR0cHM6Ly9tZG4uaW8vU3RydWN0dXJlZF9jbG9uZV9hbGdvcml0aG0pXG4gICAgICogYW5kIHN1cHBvcnRzIGNsb25pbmcgYXJyYXlzLCBhcnJheSBidWZmZXJzLCBib29sZWFucywgZGF0ZSBvYmplY3RzLCBtYXBzLFxuICAgICAqIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsIHNldHMsIHN0cmluZ3MsIHN5bWJvbHMsIGFuZCB0eXBlZFxuICAgICAqIGFycmF5cy4gVGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYGFyZ3VtZW50c2Agb2JqZWN0cyBhcmUgY2xvbmVkXG4gICAgICogYXMgcGxhaW4gb2JqZWN0cy4gQW4gZW1wdHkgb2JqZWN0IGlzIHJldHVybmVkIGZvciB1bmNsb25lYWJsZSB2YWx1ZXMgc3VjaFxuICAgICAqIGFzIGVycm9yIG9iamVjdHMsIGZ1bmN0aW9ucywgRE9NIG5vZGVzLCBhbmQgV2Vha01hcHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ2EnOiAxIH0sIHsgJ2InOiAyIH1dO1xuICAgICAqXG4gICAgICogdmFyIHNoYWxsb3cgPSBfLmNsb25lKG9iamVjdHMpO1xuICAgICAqIGNvbnNvbGUubG9nKHNoYWxsb3dbMF0gPT09IG9iamVjdHNbMF0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIGNsb25lZCB2YWx1ZS4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGBcbiAgICAgKiBjbG9uaW5nIGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aFxuICAgICAqIHVwIHRvIGZvdXIgYXJndW1lbnRzOyAodmFsdWUgWywgaW5kZXh8a2V5LCBvYmplY3QsIHN0YWNrXSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcih2YWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNFbGVtZW50KHZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdmFsdWUuY2xvbmVOb2RlKGZhbHNlKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZWwgPSBfLmNsb25lV2l0aChkb2N1bWVudC5ib2R5LCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGVsID09PSBkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqIGNvbnNvbGUubG9nKGVsLm5vZGVOYW1lKTtcbiAgICAgKiAvLyA9PiAnQk9EWSdcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5jaGlsZE5vZGVzLmxlbmd0aCk7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lV2l0aCh2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgZmFsc2UsIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY2xvbmVgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGNsb25lcyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byByZWN1cnNpdmVseSBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZGVlcCBjbG9uZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ2EnOiAxIH0sIHsgJ2InOiAyIH1dO1xuICAgICAqXG4gICAgICogdmFyIGRlZXAgPSBfLmNsb25lRGVlcChvYmplY3RzKTtcbiAgICAgKiBjb25zb2xlLmxvZyhkZWVwWzBdID09PSBvYmplY3RzWzBdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGVlcCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZVdpdGhgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGNsb25lcyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byByZWN1cnNpdmVseSBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjbG9uaW5nLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBkZWVwIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcih2YWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNFbGVtZW50KHZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdmFsdWUuY2xvbmVOb2RlKHRydWUpO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBlbCA9IF8uY2xvbmVEZWVwV2l0aChkb2N1bWVudC5ib2R5LCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGVsID09PSBkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqIGNvbnNvbGUubG9nKGVsLm5vZGVOYW1lKTtcbiAgICAgKiAvLyA9PiAnQk9EWSdcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5jaGlsZE5vZGVzLmxlbmd0aCk7XG4gICAgICogLy8gPT4gMjBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZURlZXBXaXRoKHZhbHVlLCBjdXN0b21pemVyKSB7XG4gICAgICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCB0cnVlLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlIGVxdWl2YWxlbnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIF8uZXEob2JqZWN0LCBvYmplY3QpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZXEob2JqZWN0LCBvdGhlcik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZXEoJ2EnLCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZXEoJ2EnLCBPYmplY3QoJ2EnKSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZXEoTmFOLCBOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcSh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gb3RoZXIgfHwgKHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ndCgzLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmd0KDMsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmd0KDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ3QodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPiBvdGhlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ3RlKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlID49IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhbiBgYXJndW1lbnRzYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcmd1bWVudHMoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FyZ3VtZW50cyhbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcmd1bWVudHModmFsdWUpIHtcbiAgICAgIC8vIFNhZmFyaSA4LjEgaW5jb3JyZWN0bHkgbWFrZXMgYGFyZ3VtZW50cy5jYWxsZWVgIGVudW1lcmFibGUgaW4gc3RyaWN0IG1vZGUuXG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QodmFsdWUpICYmIGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdjYWxsZWUnKSAmJlxuICAgICAgICAoIXByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwodmFsdWUsICdjYWxsZWUnKSB8fCBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBhcmdzVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGFuIGBBcnJheWAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoJ2FiYycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYEFycmF5QnVmZmVyYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUJ1ZmZlcihuZXcgQXJyYXlCdWZmZXIoMikpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUJ1ZmZlcihuZXcgQXJyYXkoMikpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcnJheUJ1ZmZlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gYXJyYXlCdWZmZXJUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYXJyYXktbGlrZS4gQSB2YWx1ZSBpcyBjb25zaWRlcmVkIGFycmF5LWxpa2UgaWYgaXQnc1xuICAgICAqIG5vdCBhIGZ1bmN0aW9uIGFuZCBoYXMgYSBgdmFsdWUubGVuZ3RoYCB0aGF0J3MgYW4gaW50ZWdlciBncmVhdGVyIHRoYW4gb3JcbiAgICAgKiBlcXVhbCB0byBgMGAgYW5kIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlKGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoJ2FiYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQXJyYXlMaWtlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJlxuICAgICAgICAhKHR5cGVvZiB2YWx1ZSA9PSAnZnVuY3Rpb24nICYmIGlzRnVuY3Rpb24odmFsdWUpKSAmJiBpc0xlbmd0aChnZXRMZW5ndGgodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmlzQXJyYXlMaWtlYCBleGNlcHQgdGhhdCBpdCBhbHNvIGNoZWNrcyBpZiBgdmFsdWVgXG4gICAgICogaXMgYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBhcnJheS1saWtlIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdChkb2N1bWVudC5ib2R5LmNoaWxkcmVuKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KCdhYmMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdChfLm5vb3ApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcnJheUxpa2VPYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGlzQXJyYXlMaWtlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYm9vbGVhbiBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQm9vbGVhbihmYWxzZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Jvb2xlYW4obnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Jvb2xlYW4odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdHJ1ZSB8fCB2YWx1ZSA9PT0gZmFsc2UgfHxcbiAgICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gYm9vbFRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBidWZmZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgYnVmZmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNCdWZmZXIobmV3IEJ1ZmZlcigyKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0J1ZmZlcihuZXcgVWludDhBcnJheSgyKSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNCdWZmZXIgPSAhQnVmZmVyID8gY29uc3RhbnQoZmFsc2UpIDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJ1ZmZlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBEYXRlYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNEYXRlKG5ldyBEYXRlKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRGF0ZSgnTW9uIEFwcmlsIDIzIDIwMTInKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRGF0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gZGF0ZVRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsaWtlbHkgYSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBET00gZWxlbWVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRWxlbWVudChkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRWxlbWVudCgnPGJvZHk+Jyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiAhIXZhbHVlICYmIHZhbHVlLm5vZGVUeXBlID09PSAxICYmIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgIWlzUGxhaW5PYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGVtcHR5LiBBIHZhbHVlIGlzIGNvbnNpZGVyZWQgZW1wdHkgdW5sZXNzIGl0J3MgYW5cbiAgICAgKiBgYXJndW1lbnRzYCBvYmplY3QsIGFycmF5LCBzdHJpbmcsIG9yIGpRdWVyeS1saWtlIGNvbGxlY3Rpb24gd2l0aCBhIGxlbmd0aFxuICAgICAqIGdyZWF0ZXIgdGhhbiBgMGAgb3IgYW4gb2JqZWN0IHdpdGggb3duIGVudW1lcmFibGUgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBlbXB0eSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHRydWUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSgxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KHsgJ2EnOiAxIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFbXB0eSh2YWx1ZSkge1xuICAgICAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSAmJlxuICAgICAgICAgIChpc0FycmF5KHZhbHVlKSB8fCBpc1N0cmluZyh2YWx1ZSkgfHxcbiAgICAgICAgICAgIGlzRnVuY3Rpb24odmFsdWUuc3BsaWNlKSB8fCBpc0FyZ3VtZW50cyh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiAhdmFsdWUubGVuZ3RoO1xuICAgICAgfVxuICAgICAgZm9yICh2YXIga2V5IGluIHZhbHVlKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBrZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlXG4gICAgICogZXF1aXZhbGVudC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBzdXBwb3J0cyBjb21wYXJpbmcgYXJyYXlzLCBhcnJheSBidWZmZXJzLCBib29sZWFucyxcbiAgICAgKiBkYXRlIG9iamVjdHMsIGVycm9yIG9iamVjdHMsIG1hcHMsIG51bWJlcnMsIGBPYmplY3RgIG9iamVjdHMsIHJlZ2V4ZXMsXG4gICAgICogc2V0cywgc3RyaW5ncywgc3ltYm9scywgYW5kIHR5cGVkIGFycmF5cy4gYE9iamVjdGAgb2JqZWN0cyBhcmUgY29tcGFyZWRcbiAgICAgKiBieSB0aGVpciBvd24sIG5vdCBpbmhlcml0ZWQsIGVudW1lcmFibGUgcHJvcGVydGllcy4gRnVuY3Rpb25zIGFuZCBET01cbiAgICAgKiBub2RlcyBhcmUgKipub3QqKiBzdXBwb3J0ZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbChvYmplY3QsIG90aGVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBvYmplY3QgPT09IG90aGVyO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcXVhbCh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiBiYXNlSXNFcXVhbCh2YWx1ZSwgb3RoZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaXNFcXVhbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2hcbiAgICAgKiBpcyBpbnZva2VkIHRvIGNvbXBhcmUgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCBjb21wYXJpc29uc1xuICAgICAqIGFyZSBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkIHdpdGggdXAgdG9cbiAgICAgKiBzaXggYXJndW1lbnRzOiAob2JqVmFsdWUsIG90aFZhbHVlIFssIGluZGV4fGtleSwgb2JqZWN0LCBvdGhlciwgc3RhY2tdKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzR3JlZXRpbmcodmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiAvXmgoPzppfGVsbG8pJC8udGVzdCh2YWx1ZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgb3RoVmFsdWUpIHtcbiAgICAgKiAgIGlmIChpc0dyZWV0aW5nKG9ialZhbHVlKSAmJiBpc0dyZWV0aW5nKG90aFZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2hlbGxvJywgJ2dvb2RieWUnXTtcbiAgICAgKiB2YXIgb3RoZXIgPSBbJ2hpJywgJ2dvb2RieWUnXTtcbiAgICAgKlxuICAgICAqIF8uaXNFcXVhbFdpdGgoYXJyYXksIG90aGVyLCBjdXN0b21pemVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcXVhbFdpdGgodmFsdWUsIG90aGVyLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICB2YXIgcmVzdWx0ID0gY3VzdG9taXplciA/IGN1c3RvbWl6ZXIodmFsdWUsIG90aGVyKSA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlciwgY3VzdG9taXplcikgOiAhIXJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhbiBgRXJyb3JgLCBgRXZhbEVycm9yYCwgYFJhbmdlRXJyb3JgLCBgUmVmZXJlbmNlRXJyb3JgLFxuICAgICAqIGBTeW50YXhFcnJvcmAsIGBUeXBlRXJyb3JgLCBvciBgVVJJRXJyb3JgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gZXJyb3Igb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFcnJvcihuZXcgRXJyb3IpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFcnJvcihFcnJvcik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Vycm9yKHZhbHVlKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBlcnJvclRhZykgfHxcbiAgICAgICAgKHR5cGVvZiB2YWx1ZS5tZXNzYWdlID09ICdzdHJpbmcnICYmIHR5cGVvZiB2YWx1ZS5uYW1lID09ICdzdHJpbmcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGZpbml0ZSBwcmltaXRpdmUgbnVtYmVyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uIFtgTnVtYmVyLmlzRmluaXRlYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzRmluaXRlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBmaW5pdGUgbnVtYmVyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZShOdW1iZXIuTUFYX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKDMuMTQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNGaW5pdGUodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiYgbmF0aXZlSXNGaW5pdGUodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgRnVuY3Rpb25gIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Z1bmN0aW9uKF8pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGdW5jdGlvbigvYWJjLyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAvLyBUaGUgdXNlIG9mIGBPYmplY3QjdG9TdHJpbmdgIGF2b2lkcyBpc3N1ZXMgd2l0aCB0aGUgYHR5cGVvZmAgb3BlcmF0b3JcbiAgICAgIC8vIGluIFNhZmFyaSA4IHdoaWNoIHJldHVybnMgJ29iamVjdCcgZm9yIHR5cGVkIGFycmF5IGNvbnN0cnVjdG9ycywgYW5kXG4gICAgICAvLyBQaGFudG9tSlMgMS45IHdoaWNoIHJldHVybnMgJ2Z1bmN0aW9uJyBmb3IgYE5vZGVMaXN0YCBpbnN0YW5jZXMuXG4gICAgICB2YXIgdGFnID0gaXNPYmplY3QodmFsdWUpID8gb2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSkgOiAnJztcbiAgICAgIHJldHVybiB0YWcgPT0gZnVuY1RhZyB8fCB0YWcgPT0gZ2VuVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGludGVnZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gW2BOdW1iZXIuaXNJbnRlZ2VyYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzSW50ZWdlcikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGludGVnZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNJbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0ludGVnZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSW50ZWdlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA9PSB0b0ludGVnZXIodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgYXJyYXktbGlrZSBsZW5ndGguXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBpcyBsb29zZWx5IGJhc2VkIG9uIFtgVG9MZW5ndGhgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy10b2xlbmd0aCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgbGVuZ3RoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aChOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0xlbmd0aChJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTGVuZ3RoKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmXG4gICAgICAgIHZhbHVlID4gLTEgJiYgdmFsdWUgJSAxID09IDAgJiYgdmFsdWUgPD0gTUFYX1NBRkVfSU5URUdFUjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGUgW2xhbmd1YWdlIHR5cGVdKGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDgpIG9mIGBPYmplY3RgLlxuICAgICAqIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdCh7fSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0KG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgICAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAgICAgKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKHt9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0TGlrZShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKF8ubm9vcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3RMaWtlKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNPYmplY3RMaWtlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBNYXBgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc01hcChuZXcgTWFwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTWFwKG5ldyBXZWFrTWFwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTWFwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IG1hcFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIHBhcnRpYWwgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYG9iamVjdGAgYW5kIGBzb3VyY2VgIHRvXG4gICAgICogZGV0ZXJtaW5lIGlmIGBvYmplY3RgIGNvbnRhaW5zIGVxdWl2YWxlbnQgcHJvcGVydHkgdmFsdWVzLiBUaGlzIG1ldGhvZCBpc1xuICAgICAqIGVxdWl2YWxlbnQgdG8gYSBgXy5tYXRjaGVzYCBmdW5jdGlvbiB3aGVuIGBzb3VyY2VgIGlzIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHN1cHBvcnRzIGNvbXBhcmluZyB0aGUgc2FtZSB2YWx1ZXMgYXMgYF8uaXNFcXVhbGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGlzIGEgbWF0Y2gsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCB9O1xuICAgICAqXG4gICAgICogXy5pc01hdGNoKG9iamVjdCwgeyAnYWdlJzogNDAgfSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc01hdGNoKG9iamVjdCwgeyAnYWdlJzogMzYgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc01hdGNoKG9iamVjdCwgc291cmNlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09PSBzb3VyY2UgfHwgYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIGdldE1hdGNoRGF0YShzb3VyY2UpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmlzTWF0Y2hgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIHZhbHVlcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAgY29tcGFyaXNvbnNcbiAgICAgKiBhcmUgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZCB3aXRoIGZpdmVcbiAgICAgKiBhcmd1bWVudHM6IChvYmpWYWx1ZSwgc3JjVmFsdWUsIGluZGV4fGtleSwgb2JqZWN0LCBzb3VyY2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBpcyBhIG1hdGNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGlzR3JlZXRpbmcodmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiAvXmgoPzppfGVsbG8pJC8udGVzdCh2YWx1ZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUpIHtcbiAgICAgKiAgIGlmIChpc0dyZWV0aW5nKG9ialZhbHVlKSAmJiBpc0dyZWV0aW5nKHNyY1ZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnZ3JlZXRpbmcnOiAnaGVsbG8nIH07XG4gICAgICogdmFyIHNvdXJjZSA9IHsgJ2dyZWV0aW5nJzogJ2hpJyB9O1xuICAgICAqXG4gICAgICogXy5pc01hdGNoV2l0aChvYmplY3QsIHNvdXJjZSwgY3VzdG9taXplcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTWF0Y2hXaXRoKG9iamVjdCwgc291cmNlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIGdldE1hdGNoRGF0YShzb3VyY2UpLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgTmFOYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBub3QgdGhlIHNhbWUgYXMgW2Bpc05hTmBdKGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjEuMi40KVxuICAgICAqIHdoaWNoIHJldHVybnMgYHRydWVgIGZvciBgdW5kZWZpbmVkYCBhbmQgb3RoZXIgbm9uLW51bWVyaWMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgTmFOYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmFOKE5hTik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05hTihuZXcgTnVtYmVyKE5hTikpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGlzTmFOKHVuZGVmaW5lZCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05hTih1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOYU4odmFsdWUpIHtcbiAgICAgIC8vIEFuIGBOYU5gIHByaW1pdGl2ZSBpcyB0aGUgb25seSB2YWx1ZSB0aGF0IGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuXG4gICAgICAvLyBQZXJmb3JtIHRoZSBgdG9TdHJpbmdUYWdgIGNoZWNrIGZpcnN0IHRvIGF2b2lkIGVycm9ycyB3aXRoIHNvbWUgQWN0aXZlWCBvYmplY3RzIGluIElFLlxuICAgICAgcmV0dXJuIGlzTnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSAhPSArdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBuYXRpdmUgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOYXRpdmUoQXJyYXkucHJvdG90eXBlLnB1c2gpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYXRpdmUoXyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc05hdGl2ZSh2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICAgIHJldHVybiByZUlzTmF0aXZlLnRlc3QoZnVuY1RvU3RyaW5nLmNhbGwodmFsdWUpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmXG4gICAgICAgIChpc0hvc3RPYmplY3QodmFsdWUpID8gcmVJc05hdGl2ZSA6IHJlSXNIb3N0Q3RvcikudGVzdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYG51bGxgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgbnVsbGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bGwobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bGwodm9pZCAwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBudWxsYCBvciBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbnVsbGlzaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTmlsKG51bGwpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOaWwodm9pZCAwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmlsKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc05pbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBOdW1iZXJgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVG8gZXhjbHVkZSBgSW5maW5pdHlgLCBgLUluZmluaXR5YCwgYW5kIGBOYU5gLCB3aGljaCBhcmUgY2xhc3NpZmllZFxuICAgICAqIGFzIG51bWJlcnMsIHVzZSB0aGUgYF8uaXNGaW5pdGVgIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcigzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTnVtYmVyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdudW1iZXInIHx8XG4gICAgICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IG51bWJlclRhZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIHRoYXQgaXMsIGFuIG9iamVjdCBjcmVhdGVkIGJ5IHRoZVxuICAgICAqIGBPYmplY3RgIGNvbnN0cnVjdG9yIG9yIG9uZSB3aXRoIGEgYFtbUHJvdG90eXBlXV1gIG9mIGBudWxsYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QobmV3IEZvbyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoeyAneCc6IDAsICd5JzogMCB9KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QoT2JqZWN0LmNyZWF0ZShudWxsKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIGlmICghaXNPYmplY3RMaWtlKHZhbHVlKSB8fFxuICAgICAgICAgIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpICE9IG9iamVjdFRhZyB8fCBpc0hvc3RPYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBwcm90byA9IGdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgIGlmIChwcm90byA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBDdG9yID0gcHJvdG8uY29uc3RydWN0b3I7XG4gICAgICByZXR1cm4gKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiZcbiAgICAgICAgQ3RvciBpbnN0YW5jZW9mIEN0b3IgJiYgZnVuY1RvU3RyaW5nLmNhbGwoQ3RvcikgPT0gb2JqZWN0Q3RvclN0cmluZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBSZWdFeHBgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1JlZ0V4cCgvYWJjLyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1JlZ0V4cCgnL2FiYy8nKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUmVnRXhwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3QodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHJlZ2V4cFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHNhZmUgaW50ZWdlci4gQW4gaW50ZWdlciBpcyBzYWZlIGlmIGl0J3MgYW4gSUVFRS03NTRcbiAgICAgKiBkb3VibGUgcHJlY2lzaW9uIG51bWJlciB3aGljaCBpc24ndCB0aGUgcmVzdWx0IG9mIGEgcm91bmRlZCB1bnNhZmUgaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiBbYE51bWJlci5pc1NhZmVJbnRlZ2VyYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzU2FmZUludGVnZXIpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNhZmUgaW50ZWdlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1NhZmVJbnRlZ2VyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU2FmZUludGVnZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0ludGVnZXIodmFsdWUpICYmIHZhbHVlID49IC1NQVhfU0FGRV9JTlRFR0VSICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTZXRgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1NldChuZXcgU2V0KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU2V0KG5ldyBXZWFrU2V0KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU2V0KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IHNldFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN0cmluZ2AgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1N0cmluZygnYWJjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1N0cmluZygxKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8XG4gICAgICAgICghaXNBcnJheSh2YWx1ZSkgJiYgaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzdHJpbmdUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU3ltYm9sYCBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU3ltYm9sKFN5bWJvbC5pdGVyYXRvcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1N5bWJvbCgnYWJjJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1N5bWJvbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgICAgICAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBvYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBzeW1ib2xUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSB0eXBlZCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1R5cGVkQXJyYXkobmV3IFVpbnQ4QXJyYXkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNUeXBlZEFycmF5KFtdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzVHlwZWRBcnJheSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiZcbiAgICAgICAgaXNMZW5ndGgodmFsdWUubGVuZ3RoKSAmJiAhIXR5cGVkQXJyYXlUYWdzW29iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1VuZGVmaW5lZCh2b2lkIDApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNVbmRlZmluZWQobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1VuZGVmaW5lZCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBXZWFrTWFwYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGNvcnJlY3RseSBjbGFzc2lmaWVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNXZWFrTWFwKG5ldyBXZWFrTWFwKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha01hcChuZXcgTWFwKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzV2Vha01hcCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSB3ZWFrTWFwVGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgV2Vha1NldGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha1NldChuZXcgV2Vha1NldCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1dlYWtTZXQobmV3IFNldCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1dlYWtTZXQodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHdlYWtTZXRUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIGBvdGhlcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gYG90aGVyYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmx0KDEsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHQoMywgMyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8ubHQoMywgMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsdCh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA8IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sdGUoMSwgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5sdGUoMywgMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5sdGUoMywgMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsdGUodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPD0gb3RoZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0FycmF5KHsgJ2EnOiAxLCAnYic6IDIgfSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkoJ2FiYycpO1xuICAgICAqIC8vID0+IFsnYScsICdiJywgJ2MnXVxuICAgICAqXG4gICAgICogXy50b0FycmF5KDEpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkobnVsbCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0FycmF5KHZhbHVlKSB7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChpc0FycmF5TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGlzU3RyaW5nKHZhbHVlKSA/IHN0cmluZ1RvQXJyYXkodmFsdWUpIDogY29weUFycmF5KHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVyYXRvclN5bWJvbCAmJiB2YWx1ZVtpdGVyYXRvclN5bWJvbF0pIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yVG9BcnJheSh2YWx1ZVtpdGVyYXRvclN5bWJvbF0oKSk7XG4gICAgICB9XG4gICAgICB2YXIgdGFnID0gZ2V0VGFnKHZhbHVlKSxcbiAgICAgICAgICBmdW5jID0gdGFnID09IG1hcFRhZyA/IG1hcFRvQXJyYXkgOiAodGFnID09IHNldFRhZyA/IHNldFRvQXJyYXkgOiB2YWx1ZXMpO1xuXG4gICAgICByZXR1cm4gZnVuYyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gaXMgbG9vc2VseSBiYXNlZCBvbiBbYFRvSW50ZWdlcmBdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy10b2ludGVnZXIpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcigzKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gMS43OTc2OTMxMzQ4NjIzMTU3ZSszMDhcbiAgICAgKlxuICAgICAqIF8udG9JbnRlZ2VyKCczJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvSW50ZWdlcih2YWx1ZSkge1xuICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6IDA7XG4gICAgICB9XG4gICAgICB2YWx1ZSA9IHRvTnVtYmVyKHZhbHVlKTtcbiAgICAgIGlmICh2YWx1ZSA9PT0gSU5GSU5JVFkgfHwgdmFsdWUgPT09IC1JTkZJTklUWSkge1xuICAgICAgICB2YXIgc2lnbiA9ICh2YWx1ZSA8IDAgPyAtMSA6IDEpO1xuICAgICAgICByZXR1cm4gc2lnbiAqIE1BWF9JTlRFR0VSO1xuICAgICAgfVxuICAgICAgdmFyIHJlbWFpbmRlciA9IHZhbHVlICUgMTtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWUgPyAocmVtYWluZGVyID8gdmFsdWUgLSByZW1haW5kZXIgOiB2YWx1ZSkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gaW50ZWdlciBzdWl0YWJsZSBmb3IgdXNlIGFzIHRoZSBsZW5ndGggb2YgYW5cbiAgICAgKiBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiBbYFRvTGVuZ3RoYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtdG9sZW5ndGgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvTGVuZ3RoKDMpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8udG9MZW5ndGgoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogXy50b0xlbmd0aChJbmZpbml0eSk7XG4gICAgICogLy8gPT4gNDI5NDk2NzI5NVxuICAgICAqXG4gICAgICogXy50b0xlbmd0aCgnMycpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0xlbmd0aCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID8gYmFzZUNsYW1wKHRvSW50ZWdlcih2YWx1ZSksIDAsIE1BWF9BUlJBWV9MRU5HVEgpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b051bWJlcigzKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvTnVtYmVyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDVlLTMyNFxuICAgICAqXG4gICAgICogXy50b051bWJlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gSW5maW5pdHlcbiAgICAgKlxuICAgICAqIF8udG9OdW1iZXIoJzMnKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9OdW1iZXIodmFsdWUpIHtcbiAgICAgIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgdmFyIG90aGVyID0gaXNGdW5jdGlvbih2YWx1ZS52YWx1ZU9mKSA/IHZhbHVlLnZhbHVlT2YoKSA6IHZhbHVlO1xuICAgICAgICB2YWx1ZSA9IGlzT2JqZWN0KG90aGVyKSA/IChvdGhlciArICcnKSA6IG90aGVyO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgPyB2YWx1ZSA6ICt2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZShyZVRyaW0sICcnKTtcbiAgICAgIHZhciBpc0JpbmFyeSA9IHJlSXNCaW5hcnkudGVzdCh2YWx1ZSk7XG4gICAgICByZXR1cm4gKGlzQmluYXJ5IHx8IHJlSXNPY3RhbC50ZXN0KHZhbHVlKSlcbiAgICAgICAgPyBmcmVlUGFyc2VJbnQodmFsdWUuc2xpY2UoMiksIGlzQmluYXJ5ID8gMiA6IDgpXG4gICAgICAgIDogKHJlSXNCYWRIZXgudGVzdCh2YWx1ZSkgPyBOQU4gOiArdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBwbGFpbiBvYmplY3QgZmxhdHRlbmluZyBpbmhlcml0ZWQgZW51bWVyYWJsZVxuICAgICAqIHByb3BlcnRpZXMgb2YgYHZhbHVlYCB0byBvd24gcHJvcGVydGllcyBvZiB0aGUgcGxhaW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBwbGFpbiBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ2EnOiAxIH0sIG5ldyBGb28pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqXG4gICAgICogXy5hc3NpZ24oeyAnYSc6IDEgfSwgXy50b1BsYWluT2JqZWN0KG5ldyBGb28pKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0KHZhbHVlLCBrZXlzSW4odmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc2FmZSBpbnRlZ2VyLiBBIHNhZmUgaW50ZWdlciBjYW4gYmUgY29tcGFyZWQgYW5kXG4gICAgICogcmVwcmVzZW50ZWQgY29ycmVjdGx5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoMyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy50b1NhZmVJbnRlZ2VyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIF8udG9TYWZlSW50ZWdlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gOTAwNzE5OTI1NDc0MDk5MVxuICAgICAqXG4gICAgICogXy50b1NhZmVJbnRlZ2VyKCczJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU2FmZUludGVnZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiBiYXNlQ2xhbXAodG9JbnRlZ2VyKHZhbHVlKSwgLU1BWF9TQUZFX0lOVEVHRVIsIE1BWF9TQUZFX0lOVEVHRVIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzdHJpbmcgaWYgaXQncyBub3Qgb25lLiBBbiBlbXB0eSBzdHJpbmcgaXMgcmV0dXJuZWRcbiAgICAgKiBmb3IgYG51bGxgIGFuZCBgdW5kZWZpbmVkYCB2YWx1ZXMuIFRoZSBzaWduIG9mIGAtMGAgaXMgcHJlc2VydmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b1N0cmluZyhudWxsKTtcbiAgICAgKiAvLyA9PiAnJ1xuICAgICAqXG4gICAgICogXy50b1N0cmluZygtMCk7XG4gICAgICogLy8gPT4gJy0wJ1xuICAgICAqXG4gICAgICogXy50b1N0cmluZyhbMSwgMiwgM10pO1xuICAgICAqIC8vID0+ICcxLDIsMydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZyh2YWx1ZSkge1xuICAgICAgLy8gRXhpdCBlYXJseSBmb3Igc3RyaW5ncyB0byBhdm9pZCBhIHBlcmZvcm1hbmNlIGhpdCBpbiBzb21lIGVudmlyb25tZW50cy5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gU3ltYm9sID8gc3ltYm9sVG9TdHJpbmcuY2FsbCh2YWx1ZSkgOiAnJztcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSAodmFsdWUgKyAnJyk7XG4gICAgICByZXR1cm4gKHJlc3VsdCA9PSAnMCcgJiYgKDEgLyB2YWx1ZSkgPT0gLUlORklOSVRZKSA/ICctMCcgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIHNvdXJjZSBvYmplY3RzIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdC4gU291cmNlIG9iamVjdHMgYXJlIGFwcGxpZWQgZnJvbSBsZWZ0IHRvIHJpZ2h0LiBTdWJzZXF1ZW50IHNvdXJjZXNcbiAgICAgKiBvdmVyd3JpdGUgcHJvcGVydHkgYXNzaWdubWVudHMgb2YgcHJldmlvdXMgc291cmNlcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgIGFuZCBpcyBsb29zZWx5IGJhc2VkIG9uXG4gICAgICogW2BPYmplY3QuYXNzaWduYF0oaHR0cHM6Ly9tZG4uaW8vT2JqZWN0L2Fzc2lnbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYyA9IDM7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQmFyKCkge1xuICAgICAqICAgdGhpcy5lID0gNTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmQgPSA0O1xuICAgICAqIEJhci5wcm90b3R5cGUuZiA9IDY7XG4gICAgICpcbiAgICAgKiBfLmFzc2lnbih7ICdhJzogMSB9LCBuZXcgRm9vLCBuZXcgQmFyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzLCAnZSc6IDUgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ24gPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgY29weU9iamVjdChzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIG93biBhbmRcbiAgICAgKiBpbmhlcml0ZWQgc291cmNlIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBleHRlbmRcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gQmFyKCkge1xuICAgICAqICAgdGhpcy5kID0gNDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqIEJhci5wcm90b3R5cGUuZSA9IDU7XG4gICAgICpcbiAgICAgKiBfLmFzc2lnbkluKHsgJ2EnOiAxIH0sIG5ldyBGb28sIG5ldyBCYXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMywgJ2QnOiA0LCAnZSc6IDUgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25JbiA9IGNyZWF0ZUFzc2lnbmVyKGZ1bmN0aW9uKG9iamVjdCwgc291cmNlKSB7XG4gICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbkluYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgYXNzaWduZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIGFzc2lnbm1lbnQgaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZFxuICAgICAqIHdpdGggZml2ZSBhcmd1bWVudHM6IChvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgZXh0ZW5kV2l0aFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQob2JqVmFsdWUpID8gc3JjVmFsdWUgOiBvYmpWYWx1ZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZGVmYXVsdHMgPSBfLnBhcnRpYWxSaWdodChfLmFzc2lnbkluV2l0aCwgY3VzdG9taXplcik7XG4gICAgICpcbiAgICAgKiBkZWZhdWx0cyh7ICdhJzogMSB9LCB7ICdiJzogMiB9LCB7ICdhJzogMyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKi9cbiAgICB2YXIgYXNzaWduSW5XaXRoID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4LCBjdXN0b21pemVyKSB7XG4gICAgICBjb3B5T2JqZWN0V2l0aChzb3VyY2UsIGtleXNJbihzb3VyY2UpLCBvYmplY3QsIGN1c3RvbWl6ZXIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5hc3NpZ25gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBwcm9kdWNlIHRoZSBhc3NpZ25lZCB2YWx1ZXMuIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgXG4gICAgICogYXNzaWdubWVudCBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkXG4gICAgICogd2l0aCBmaXZlIGFyZ3VtZW50czogKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQob2JqVmFsdWUpID8gc3JjVmFsdWUgOiBvYmpWYWx1ZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZGVmYXVsdHMgPSBfLnBhcnRpYWxSaWdodChfLmFzc2lnbldpdGgsIGN1c3RvbWl6ZXIpO1xuICAgICAqXG4gICAgICogZGVmYXVsdHMoeyAnYSc6IDEgfSwgeyAnYic6IDIgfSwgeyAnYSc6IDMgfSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiB9XG4gICAgICovXG4gICAgdmFyIGFzc2lnbldpdGggPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGNvcHlPYmplY3RXaXRoKHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QsIGN1c3RvbWl6ZXIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBgcGF0aHNgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgb2YgZWxlbWVudHMgdG8gcGljayxcbiAgICAgKiAgc3BlY2lmaWVkIGluZGl2aWR1YWxseSBvciBpbiBhcnJheXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcGlja2VkIGVsZW1lbnRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9LCA0XSB9O1xuICAgICAqXG4gICAgICogXy5hdChvYmplY3QsIFsnYVswXS5iLmMnLCAnYVsxXSddKTtcbiAgICAgKiAvLyA9PiBbMywgNF1cbiAgICAgKlxuICAgICAqIF8uYXQoWydhJywgJ2InLCAnYyddLCAwLCAyKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYyddXG4gICAgICovXG4gICAgdmFyIGF0ID0gcmVzdChmdW5jdGlvbihvYmplY3QsIHBhdGhzKSB7XG4gICAgICByZXR1cm4gYmFzZUF0KG9iamVjdCwgYmFzZUZsYXR0ZW4ocGF0aHMsIDEpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGUgYHByb3RvdHlwZWAgb2JqZWN0LiBJZiBhIGBwcm9wZXJ0aWVzYFxuICAgICAqIG9iamVjdCBpcyBnaXZlbiBpdHMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBhcmUgYXNzaWduZWQgdG8gdGhlIGNyZWF0ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwcm90b3R5cGUgVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzXSBUaGUgcHJvcGVydGllcyB0byBhc3NpZ24gdG8gdGhlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBTaGFwZSgpIHtcbiAgICAgKiAgIHRoaXMueCA9IDA7XG4gICAgICogICB0aGlzLnkgPSAwO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIENpcmNsZSgpIHtcbiAgICAgKiAgIFNoYXBlLmNhbGwodGhpcyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogQ2lyY2xlLnByb3RvdHlwZSA9IF8uY3JlYXRlKFNoYXBlLnByb3RvdHlwZSwge1xuICAgICAqICAgJ2NvbnN0cnVjdG9yJzogQ2lyY2xlXG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiB2YXIgY2lyY2xlID0gbmV3IENpcmNsZTtcbiAgICAgKiBjaXJjbGUgaW5zdGFuY2VvZiBDaXJjbGU7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogY2lyY2xlIGluc3RhbmNlb2YgU2hhcGU7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZShwcm90b3R5cGUsIHByb3BlcnRpZXMpIHtcbiAgICAgIHZhciByZXN1bHQgPSBiYXNlQ3JlYXRlKHByb3RvdHlwZSk7XG4gICAgICByZXR1cm4gcHJvcGVydGllcyA/IGJhc2VBc3NpZ24ocmVzdWx0LCBwcm9wZXJ0aWVzKSA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ25zIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0cyB0byB0aGVcbiAgICAgKiBkZXN0aW5hdGlvbiBvYmplY3QgZm9yIGFsbCBkZXN0aW5hdGlvbiBwcm9wZXJ0aWVzIHRoYXQgcmVzb2x2ZSB0byBgdW5kZWZpbmVkYC5cbiAgICAgKiBTb3VyY2Ugb2JqZWN0cyBhcmUgYXBwbGllZCBmcm9tIGxlZnQgdG8gcmlnaHQuIE9uY2UgYSBwcm9wZXJ0eSBpcyBzZXQsXG4gICAgICogYWRkaXRpb25hbCB2YWx1ZXMgb2YgdGhlIHNhbWUgcHJvcGVydHkgYXJlIGlnbm9yZWQuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IFtzb3VyY2VzXSBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0cyh7ICd1c2VyJzogJ2Jhcm5leScgfSwgeyAnYWdlJzogMzYgfSwgeyAndXNlcic6ICdmcmVkJyB9KTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9XG4gICAgICovXG4gICAgdmFyIGRlZmF1bHRzID0gcmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICBhcmdzLnB1c2godW5kZWZpbmVkLCBhc3NpZ25JbkRlZmF1bHRzKTtcbiAgICAgIHJldHVybiBhcHBseShhc3NpZ25JbldpdGgsIHVuZGVmaW5lZCwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRlZmF1bHRzYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBhc3NpZ25zXG4gICAgICogZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmYXVsdHNEZWVwKHsgJ3VzZXInOiB7ICduYW1lJzogJ2Jhcm5leScgfSB9LCB7ICd1c2VyJzogeyAnbmFtZSc6ICdmcmVkJywgJ2FnZSc6IDM2IH0gfSk7XG4gICAgICogLy8gPT4geyAndXNlcic6IHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0gfVxuICAgICAqXG4gICAgICovXG4gICAgdmFyIGRlZmF1bHRzRGVlcCA9IHJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgYXJncy5wdXNoKHVuZGVmaW5lZCwgbWVyZ2VEZWZhdWx0cyk7XG4gICAgICByZXR1cm4gYXBwbHkobWVyZ2VXaXRoLCB1bmRlZmluZWQsIGFyZ3MpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kYCBleGNlcHQgdGhhdCBpdCByZXR1cm5zIHRoZSBrZXkgb2YgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudCBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgaW5zdGVhZCBvZiB0aGUgZWxlbWVudCBpdHNlbGYuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH0gUmV0dXJucyB0aGUga2V5IG9mIHRoZSBtYXRjaGVkIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IHtcbiAgICAgKiAgICdiYXJuZXknOiAgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICAnZnJlZCc6ICAgIHsgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAnYWdlJzogMSwgICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLmFnZSA8IDQwOyB9KTtcbiAgICAgKiAvLyA9PiAnYmFybmV5JyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEtleSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gJ2Jhcm5leSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kS2V5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gYmFzZUZpbmQob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBiYXNlRm9yT3duLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRLZXlgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBhIGNvbGxlY3Rpb24gaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFJldHVybnMgdGhlIGtleSBvZiB0aGUgbWF0Y2hlZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSB7XG4gICAgICogICAnYmFybmV5JzogIHsgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgJ2ZyZWQnOiAgICB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3RLZXkodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlIDwgNDA7IH0pO1xuICAgICAqIC8vID0+IHJldHVybnMgJ3BlYmJsZXMnIGFzc3VtaW5nIGBfLmZpbmRLZXlgIHJldHVybnMgJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+ICdiYXJuZXknXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRMYXN0S2V5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gYmFzZUZpbmQob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBiYXNlRm9yT3duUmlnaHQsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdCBpbnZva2luZ1xuICAgICAqIGBpdGVyYXRlZWAgZm9yIGVhY2ggcHJvcGVydHkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwga2V5LCBvYmplY3QpLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHlcbiAgICAgKiByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvckluKG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyAnYScsICdiJywgdGhlbiAnYycgKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JJbihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGxcbiAgICAgICAgPyBvYmplY3RcbiAgICAgICAgOiBiYXNlRm9yKG9iamVjdCwgYmFzZUNhc3RGdW5jdGlvbihpdGVyYXRlZSksIGtleXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mb3JJbmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBwcm9wZXJ0aWVzIG9mXG4gICAgICogYG9iamVjdGAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9ySW5SaWdodChuZXcgRm9vLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ2MnLCAnYicsIHRoZW4gJ2EnIGFzc3VtaW5nIGBfLmZvckluYCBsb2dzICdhJywgJ2InLCB0aGVuICdjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZvckluUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsXG4gICAgICAgID8gb2JqZWN0XG4gICAgICAgIDogYmFzZUZvclJpZ2h0KG9iamVjdCwgYmFzZUNhc3RGdW5jdGlvbihpdGVyYXRlZSksIGtleXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGFuIG9iamVjdCBpbnZva2luZyBgaXRlcmF0ZWVgXG4gICAgICogZm9yIGVhY2ggcHJvcGVydHkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwga2V5LCBvYmplY3QpLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5XG4gICAgICogZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvck93bihuZXcgRm9vLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ2EnIHRoZW4gJ2InIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBvYmplY3QgJiYgYmFzZUZvck93bihvYmplY3QsIGJhc2VDYXN0RnVuY3Rpb24oaXRlcmF0ZWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvck93bmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBwcm9wZXJ0aWVzIG9mXG4gICAgICogYG9iamVjdGAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9yT3duUmlnaHQobmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzICdiJyB0aGVuICdhJyBhc3N1bWluZyBgXy5mb3JPd25gIGxvZ3MgJ2EnIHRoZW4gJ2InXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duUmlnaHQob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yT3duUmlnaHQob2JqZWN0LCBiYXNlQ2FzdEZ1bmN0aW9uKGl0ZXJhdGVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmcm9tIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXNcbiAgICAgKiBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsnYScsICdiJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmdW5jdGlvbnMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZnVuY3Rpb24gcHJvcGVydHkgbmFtZXMgZnJvbSBvd24gYW5kIGluaGVyaXRlZFxuICAgICAqIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gXy5jb25zdGFudCgnYScpO1xuICAgICAqICAgdGhpcy5iID0gXy5jb25zdGFudCgnYicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IF8uY29uc3RhbnQoJ2MnKTtcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZnVuY3Rpb25zSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VGdW5jdGlvbnMob2JqZWN0LCBrZXlzSW4ob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiB0aGUgcmVzb2x2ZWQgdmFsdWUgaXNcbiAgICAgKiBgdW5kZWZpbmVkYCB0aGUgYGRlZmF1bHRWYWx1ZWAgaXMgdXNlZCBpbiBpdHMgcGxhY2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHBhcmFtIHsqfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgcmV0dXJuZWQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGB1bmRlZmluZWRgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uZ2V0KG9iamVjdCwgJ2FbMF0uYi5jJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCBbJ2EnLCAnMCcsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCAnYS5iLmMnLCAnZGVmYXVsdCcpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gZGVmYXVsdFZhbHVlIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3QgcHJvcGVydHkgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgcGF0aGAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogeyAnYic6IHsgJ2MnOiAzIH0gfSB9O1xuICAgICAqIHZhciBvdGhlciA9IF8uY3JlYXRlKHsgJ2EnOiBfLmNyZWF0ZSh7ICdiJzogXy5jcmVhdGUoeyAnYyc6IDMgfSkgfSkgfSk7XG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsICdhJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXMob2JqZWN0LCAnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhcyhvYmplY3QsIFsnYScsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXMob3RoZXIsICdhJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXMob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gaGFzUGF0aChvYmplY3QsIHBhdGgsIGJhc2VIYXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3Qgb3IgaW5oZXJpdGVkIHByb3BlcnR5IG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHBhdGhgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0gXy5jcmVhdGUoeyAnYSc6IF8uY3JlYXRlKHsgJ2InOiBfLmNyZWF0ZSh7ICdjJzogMyB9KSB9KSB9KTtcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzSW4ob2JqZWN0LCAnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhc0luKG9iamVjdCwgWydhJywgJ2InLCAnYyddKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhc0luKG9iamVjdCwgJ2InKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc0luKG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIGhhc1BhdGgob2JqZWN0LCBwYXRoLCBiYXNlSGFzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZSBpbnZlcnRlZCBrZXlzIGFuZCB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICogSWYgYG9iamVjdGAgY29udGFpbnMgZHVwbGljYXRlIHZhbHVlcywgc3Vic2VxdWVudCB2YWx1ZXMgb3ZlcndyaXRlIHByb3BlcnR5XG4gICAgICogYXNzaWdubWVudHMgb2YgcHJldmlvdXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnZlcnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9O1xuICAgICAqXG4gICAgICogXy5pbnZlcnQob2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICcxJzogJ2MnLCAnMic6ICdiJyB9XG4gICAgICovXG4gICAgdmFyIGludmVydCA9IGNyZWF0ZUludmVydGVyKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0W3ZhbHVlXSA9IGtleTtcbiAgICB9LCBjb25zdGFudChpZGVudGl0eSkpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pbnZlcnRgIGV4Y2VwdCB0aGF0IHRoZSBpbnZlcnRlZCBvYmplY3QgaXMgZ2VuZXJhdGVkXG4gICAgICogZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nIGVhY2ggZWxlbWVudCBvZiBgb2JqZWN0YCB0aHJvdWdoIGBpdGVyYXRlZWAuXG4gICAgICogVGhlIGNvcnJlc3BvbmRpbmcgaW52ZXJ0ZWQgdmFsdWUgb2YgZWFjaCBpbnZlcnRlZCBrZXkgaXMgYW4gYXJyYXkgb2Yga2V5c1xuICAgICAqIHJlc3BvbnNpYmxlIGZvciBnZW5lcmF0aW5nIHRoZSBpbnZlcnRlZCB2YWx1ZS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW52ZXJ0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBpbnZlcnRlZCBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfTtcbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0Qnkob2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICcxJzogWydhJywgJ2MnXSwgJzInOiBbJ2InXSB9XG4gICAgICpcbiAgICAgKiBfLmludmVydEJ5KG9iamVjdCwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiAnZ3JvdXAnICsgdmFsdWU7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnZ3JvdXAxJzogWydhJywgJ2MnXSwgJ2dyb3VwMic6IFsnYiddIH1cbiAgICAgKi9cbiAgICB2YXIgaW52ZXJ0QnkgPSBjcmVhdGVJbnZlcnRlcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdCwgdmFsdWUpKSB7XG4gICAgICAgIHJlc3VsdFt2YWx1ZV0ucHVzaChrZXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W3ZhbHVlXSA9IFtrZXldO1xuICAgICAgfVxuICAgIH0sIGdldEl0ZXJhdGVlKTtcblxuICAgIC8qKlxuICAgICAqIEludm9rZXMgdGhlIG1ldGhvZCBhdCBgcGF0aGAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBtZXRob2QgdG8gaW52b2tlLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiBbMSwgMiwgMywgNF0gfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5pbnZva2Uob2JqZWN0LCAnYVswXS5iLmMuc2xpY2UnLCAxLCAzKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKi9cbiAgICB2YXIgaW52b2tlID0gcmVzdChiYXNlSW52b2tlKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuIFNlZSB0aGVcbiAgICAgKiBbRVMgc3BlY10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LmtleXMpXG4gICAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8ua2V5cyhuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYiddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiBfLmtleXMoJ2hpJyk7XG4gICAgICogLy8gPT4gWycwJywgJzEnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGtleXMob2JqZWN0KSB7XG4gICAgICB2YXIgaXNQcm90byA9IGlzUHJvdG90eXBlKG9iamVjdCk7XG4gICAgICBpZiAoIShpc1Byb3RvIHx8IGlzQXJyYXlMaWtlKG9iamVjdCkpKSB7XG4gICAgICAgIHJldHVybiBiYXNlS2V5cyhvYmplY3QpO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ZXMgPSBpbmRleEtleXMob2JqZWN0KSxcbiAgICAgICAgICBza2lwSW5kZXhlcyA9ICEhaW5kZXhlcyxcbiAgICAgICAgICByZXN1bHQgPSBpbmRleGVzIHx8IFtdLFxuICAgICAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGg7XG5cbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgaWYgKGJhc2VIYXMob2JqZWN0LCBrZXkpICYmXG4gICAgICAgICAgICAhKHNraXBJbmRleGVzICYmIChrZXkgPT0gJ2xlbmd0aCcgfHwgaXNJbmRleChrZXksIGxlbmd0aCkpKSAmJlxuICAgICAgICAgICAgIShpc1Byb3RvICYmIGtleSA9PSAnY29uc3RydWN0b3InKSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBOb24tb2JqZWN0IHZhbHVlcyBhcmUgY29lcmNlZCB0byBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5rZXlzSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5c0luKG9iamVjdCkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaXNQcm90byA9IGlzUHJvdG90eXBlKG9iamVjdCksXG4gICAgICAgICAgcHJvcHMgPSBiYXNlS2V5c0luKG9iamVjdCksXG4gICAgICAgICAgcHJvcHNMZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgaW5kZXhlcyA9IGluZGV4S2V5cyhvYmplY3QpLFxuICAgICAgICAgIHNraXBJbmRleGVzID0gISFpbmRleGVzLFxuICAgICAgICAgIHJlc3VsdCA9IGluZGV4ZXMgfHwgW10sXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBwcm9wc0xlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuICAgICAgICBpZiAoIShza2lwSW5kZXhlcyAmJiAoa2V5ID09ICdsZW5ndGgnIHx8IGlzSW5kZXgoa2V5LCBsZW5ndGgpKSkgJiZcbiAgICAgICAgICAgICEoa2V5ID09ICdjb25zdHJ1Y3RvcicgJiYgKGlzUHJvdG8gfHwgIWhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5tYXBWYWx1ZXNgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGFuIG9iamVjdCB3aXRoIHRoZVxuICAgICAqIHNhbWUgdmFsdWVzIGFzIGBvYmplY3RgIGFuZCBrZXlzIGdlbmVyYXRlZCBieSBydW5uaW5nIGVhY2ggb3duIGVudW1lcmFibGVcbiAgICAgKiBwcm9wZXJ0eSBvZiBgb2JqZWN0YCB0aHJvdWdoIGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXBLZXlzKHsgJ2EnOiAxLCAnYic6IDIgfSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgcmV0dXJuIGtleSArIHZhbHVlO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IHsgJ2ExJzogMSwgJ2IyJzogMiB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwS2V5cyhvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKTtcblxuICAgICAgYmFzZUZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICByZXN1bHRbaXRlcmF0ZWUodmFsdWUsIGtleSwgb2JqZWN0KV0gPSB2YWx1ZTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYXMgYG9iamVjdGAgYW5kIHZhbHVlcyBnZW5lcmF0ZWQgYnlcbiAgICAgKiBydW5uaW5nIGVhY2ggb3duIGVudW1lcmFibGUgcHJvcGVydHkgb2YgYG9iamVjdGAgdGhyb3VnaCBgaXRlcmF0ZWVgLiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IHtcbiAgICAgKiAgICdmcmVkJzogICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5tYXBWYWx1ZXModXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlOyB9KTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogNDAsICdwZWJibGVzJzogMSB9IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1hcFZhbHVlcyh1c2VycywgJ2FnZScpO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiA0MCwgJ3BlYmJsZXMnOiAxIH0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBWYWx1ZXMob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyk7XG5cbiAgICAgIGJhc2VGb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBpdGVyYXRlZSh2YWx1ZSwga2V5LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IG1lcmdlcyBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2Ygc291cmNlIG9iamVjdHNcbiAgICAgKiBpbnRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuIFNvdXJjZSBwcm9wZXJ0aWVzIHRoYXQgcmVzb2x2ZSB0byBgdW5kZWZpbmVkYFxuICAgICAqIGFyZSBza2lwcGVkIGlmIGEgZGVzdGluYXRpb24gdmFsdWUgZXhpc3RzLiBBcnJheSBhbmQgcGxhaW4gb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgKiBhcmUgbWVyZ2VkIHJlY3Vyc2l2ZWx5LiBPdGhlciBvYmplY3RzIGFuZCB2YWx1ZSB0eXBlcyBhcmUgb3ZlcnJpZGRlbiBieVxuICAgICAqIGFzc2lnbm1lbnQuIFNvdXJjZSBvYmplY3RzIGFyZSBhcHBsaWVkIGZyb20gbGVmdCB0byByaWdodC4gU3Vic2VxdWVudFxuICAgICAqIHNvdXJjZXMgb3ZlcndyaXRlIHByb3BlcnR5IGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHNvdXJjZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IFtzb3VyY2VzXSBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0ge1xuICAgICAqICAgJ2RhdGEnOiBbeyAndXNlcic6ICdiYXJuZXknIH0sIHsgJ3VzZXInOiAnZnJlZCcgfV1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGFnZXMgPSB7XG4gICAgICogICAnZGF0YSc6IFt7ICdhZ2UnOiAzNiB9LCB7ICdhZ2UnOiA0MCB9XVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLm1lcmdlKHVzZXJzLCBhZ2VzKTtcbiAgICAgKiAvLyA9PiB7ICdkYXRhJzogW3sgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sIHsgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCB9XSB9XG4gICAgICovXG4gICAgdmFyIG1lcmdlID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4KSB7XG4gICAgICBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ubWVyZ2VgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBwcm9kdWNlIHRoZSBtZXJnZWQgdmFsdWVzIG9mIHRoZSBkZXN0aW5hdGlvbiBhbmQgc291cmNlXG4gICAgICogcHJvcGVydGllcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAgbWVyZ2luZyBpcyBoYW5kbGVkIGJ5IHRoZVxuICAgICAqIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aCBzZXZlbiBhcmd1bWVudHM6XG4gICAgICogKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSwgc3RhY2spLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBzb3VyY2VzIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIob2JqVmFsdWUsIHNyY1ZhbHVlKSB7XG4gICAgICogICBpZiAoXy5pc0FycmF5KG9ialZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gb2JqVmFsdWUuY29uY2F0KHNyY1ZhbHVlKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ2ZydWl0cyc6IFsnYXBwbGUnXSxcbiAgICAgKiAgICd2ZWdldGFibGVzJzogWydiZWV0J11cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIG90aGVyID0ge1xuICAgICAqICAgJ2ZydWl0cyc6IFsnYmFuYW5hJ10sXG4gICAgICogICAndmVnZXRhYmxlcyc6IFsnY2Fycm90J11cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5tZXJnZVdpdGgob2JqZWN0LCBvdGhlciwgY3VzdG9taXplcik7XG4gICAgICogLy8gPT4geyAnZnJ1aXRzJzogWydhcHBsZScsICdiYW5hbmEnXSwgJ3ZlZ2V0YWJsZXMnOiBbJ2JlZXQnLCAnY2Fycm90J10gfVxuICAgICAqL1xuICAgIHZhciBtZXJnZVdpdGggPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGJhc2VNZXJnZShvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLnBpY2tgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGVcbiAgICAgKiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYG9iamVjdGAgdGhhdCBhcmUgbm90IG9taXR0ZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcHJvcHNdIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBvbWl0LCBzcGVjaWZpZWRcbiAgICAgKiAgaW5kaXZpZHVhbGx5IG9yIGluIGFycmF5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdChvYmplY3QsIFsnYScsICdjJ10pO1xuICAgICAqIC8vID0+IHsgJ2InOiAnMicgfVxuICAgICAqL1xuICAgIHZhciBvbWl0ID0gcmVzdChmdW5jdGlvbihvYmplY3QsIHByb3BzKSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfVxuICAgICAgcHJvcHMgPSBhcnJheU1hcChiYXNlRmxhdHRlbihwcm9wcywgMSksIFN0cmluZyk7XG4gICAgICByZXR1cm4gYmFzZVBpY2sob2JqZWN0LCBiYXNlRGlmZmVyZW5jZShrZXlzSW4ob2JqZWN0KSwgcHJvcHMpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5waWNrQnlgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZlxuICAgICAqIHRoZSBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYG9iamVjdGAgdGhhdCBgcHJlZGljYXRlYFxuICAgICAqIGRvZXNuJ3QgcmV0dXJuIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6XG4gICAgICogKHZhbHVlLCBrZXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdEJ5KG9iamVjdCwgXy5pc051bWJlcik7XG4gICAgICogLy8gPT4geyAnYic6ICcyJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gb21pdEJ5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUpO1xuICAgICAgcmV0dXJuIGJhc2VQaWNrQnkob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICAgIHJldHVybiAhcHJlZGljYXRlKHZhbHVlLCBrZXkpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIHBpY2tlZCBgb2JqZWN0YCBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3Byb3BzXSBUaGUgcHJvcGVydHkgbmFtZXMgdG8gcGljaywgc3BlY2lmaWVkXG4gICAgICogIGluZGl2aWR1YWxseSBvciBpbiBhcnJheXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6ICcyJywgJ2MnOiAzIH07XG4gICAgICpcbiAgICAgKiBfLnBpY2sob2JqZWN0LCBbJ2EnLCAnYyddKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2MnOiAzIH1cbiAgICAgKi9cbiAgICB2YXIgcGljayA9IHJlc3QoZnVuY3Rpb24ob2JqZWN0LCBwcm9wcykge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8ge30gOiBiYXNlUGljayhvYmplY3QsIGJhc2VGbGF0dGVuKHByb3BzLCAxKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgYG9iamVjdGAgcHJvcGVydGllcyBgcHJlZGljYXRlYCByZXR1cm5zXG4gICAgICogdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czogKHZhbHVlLCBrZXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ucGlja0J5KG9iamVjdCwgXy5pc051bWJlcik7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdjJzogMyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gcGlja0J5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB7fSA6IGJhc2VQaWNrQnkob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmdldGAgZXhjZXB0IHRoYXQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGEgZnVuY3Rpb25cbiAgICAgKiBpdCdzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgaXRzIHBhcmVudCBvYmplY3QgYW5kIGl0cyByZXN1bHRcbiAgICAgKiBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHJlc29sdmUuXG4gICAgICogQHBhcmFtIHsqfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgcmV0dXJuZWQgaWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzIGB1bmRlZmluZWRgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MxJzogMywgJ2MyJzogXy5jb25zdGFudCg0KSB9IH1dIH07XG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdhWzBdLmIuYzEnKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdhWzBdLmIuYzInKTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdhWzBdLmIuYzMnLCAnZGVmYXVsdCcpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqXG4gICAgICogXy5yZXN1bHQob2JqZWN0LCAnYVswXS5iLmMzJywgXy5jb25zdGFudCgnZGVmYXVsdCcpKTtcbiAgICAgKiAvLyA9PiAnZGVmYXVsdCdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXN1bHQob2JqZWN0LCBwYXRoLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgIGlmICghaXNLZXkocGF0aCwgb2JqZWN0KSkge1xuICAgICAgICBwYXRoID0gYmFzZUNhc3RQYXRoKHBhdGgpO1xuICAgICAgICB2YXIgcmVzdWx0ID0gZ2V0KG9iamVjdCwgcGF0aCk7XG4gICAgICAgIG9iamVjdCA9IHBhcmVudChvYmplY3QsIHBhdGgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0ID0gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3RbcGF0aF07XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzdWx0ID0gZGVmYXVsdFZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzRnVuY3Rpb24ocmVzdWx0KSA/IHJlc3VsdC5jYWxsKG9iamVjdCkgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdmFsdWUgYXQgYHBhdGhgIG9mIGBvYmplY3RgLiBJZiBhIHBvcnRpb24gb2YgYHBhdGhgIGRvZXNuJ3QgZXhpc3RcbiAgICAgKiBpdCdzIGNyZWF0ZWQuIEFycmF5cyBhcmUgY3JlYXRlZCBmb3IgbWlzc2luZyBpbmRleCBwcm9wZXJ0aWVzIHdoaWxlIG9iamVjdHNcbiAgICAgKiBhcmUgY3JlYXRlZCBmb3IgYWxsIG90aGVyIG1pc3NpbmcgcHJvcGVydGllcy4gVXNlIGBfLnNldFdpdGhgIHRvIGN1c3RvbWl6ZVxuICAgICAqIGBwYXRoYCBjcmVhdGlvbi5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8uc2V0KG9iamVjdCwgJ2FbMF0uYi5jJywgNCk7XG4gICAgICogY29uc29sZS5sb2cob2JqZWN0LmFbMF0uYi5jKTtcbiAgICAgKiAvLyA9PiA0XG4gICAgICpcbiAgICAgKiBfLnNldChvYmplY3QsICd4WzBdLnkueicsIDUpO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC54WzBdLnkueik7XG4gICAgICogLy8gPT4gNVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldChvYmplY3QsIHBhdGgsIHZhbHVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc2V0YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgb2JqZWN0cyBvZiBgcGF0aGAuICBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIHBhdGggY3JlYXRpb24gaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAobnNWYWx1ZSwga2V5LCBuc09iamVjdCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNldFdpdGgoeyAnMCc6IHsgJ2xlbmd0aCc6IDIgfSB9LCAnWzBdWzFdWzJdJywgMywgT2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICcwJzogeyAnMSc6IHsgJzInOiAzIH0sICdsZW5ndGgnOiAyIH0gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldFdpdGgob2JqZWN0LCBwYXRoLCB2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogYmFzZVNldChvYmplY3QsIHBhdGgsIHZhbHVlLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIG93biBlbnVtZXJhYmxlIGtleS12YWx1ZSBwYWlycyBmb3IgYG9iamVjdGAgd2hpY2hcbiAgICAgKiBjYW4gYmUgY29uc3VtZWQgYnkgYF8uZnJvbVBhaXJzYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxXSwgWydiJywgMl1dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYWlycyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlVG9QYWlycyhvYmplY3QsIGtleXMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIGtleS12YWx1ZSBwYWlycyBmb3JcbiAgICAgKiBgb2JqZWN0YCB3aGljaCBjYW4gYmUgY29uc3VtZWQgYnkgYF8uZnJvbVBhaXJzYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy50b1BhaXJzSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gW1snYScsIDFdLCBbJ2InLCAyXSwgWydjJywgMV1dIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYWlyc0luKG9iamVjdCkge1xuICAgICAgcmV0dXJuIGJhc2VUb1BhaXJzKG9iamVjdCwga2V5c0luKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIGFsdGVybmF0aXZlIHRvIGBfLnJlZHVjZWA7IHRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYG9iamVjdGAgdG8gYSBuZXdcbiAgICAgKiBgYWNjdW11bGF0b3JgIG9iamVjdCB3aGljaCBpcyB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgZWFjaCBvZiBpdHMgb3duIGVudW1lcmFibGVcbiAgICAgKiBwcm9wZXJ0aWVzIHRocm91Z2ggYGl0ZXJhdGVlYCwgd2l0aCBlYWNoIGludm9jYXRpb24gcG90ZW50aWFsbHkgbXV0YXRpbmdcbiAgICAgKiB0aGUgYGFjY3VtdWxhdG9yYCBvYmplY3QuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggZm91ciBhcmd1bWVudHM6XG4gICAgICogKGFjY3VtdWxhdG9yLCB2YWx1ZSwga2V5LCBvYmplY3QpLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uXG4gICAgICogZWFybHkgYnkgZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgY3VzdG9tIGFjY3VtdWxhdG9yIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmFuc2Zvcm0oWzIsIDMsIDRdLCBmdW5jdGlvbihyZXN1bHQsIG4pIHtcbiAgICAgKiAgIHJlc3VsdC5wdXNoKG4gKj0gbik7XG4gICAgICogICByZXR1cm4gbiAlIDIgPT0gMDtcbiAgICAgKiB9LCBbXSk7XG4gICAgICogLy8gPT4gWzQsIDldXG4gICAgICpcbiAgICAgKiBfLnRyYW5zZm9ybSh7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfSwgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICogICAocmVzdWx0W3ZhbHVlXSB8fCAocmVzdWx0W3ZhbHVlXSA9IFtdKSkucHVzaChrZXkpO1xuICAgICAqIH0sIHt9KTtcbiAgICAgKiAvLyA9PiB7ICcxJzogWydhJywgJ2MnXSwgJzInOiBbJ2InXSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtKG9iamVjdCwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yKSB7XG4gICAgICB2YXIgaXNBcnIgPSBpc0FycmF5KG9iamVjdCkgfHwgaXNUeXBlZEFycmF5KG9iamVjdCk7XG4gICAgICBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCA0KTtcblxuICAgICAgaWYgKGFjY3VtdWxhdG9yID09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzQXJyIHx8IGlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgICAgICAgICBpZiAoaXNBcnIpIHtcbiAgICAgICAgICAgIGFjY3VtdWxhdG9yID0gaXNBcnJheShvYmplY3QpID8gbmV3IEN0b3IgOiBbXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWNjdW11bGF0b3IgPSBpc0Z1bmN0aW9uKEN0b3IpID8gYmFzZUNyZWF0ZShnZXRQcm90b3R5cGVPZihvYmplY3QpKSA6IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciA9IHt9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAoaXNBcnIgPyBhcnJheUVhY2ggOiBiYXNlRm9yT3duKShvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgb2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBpdGVyYXRlZShhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgcHJvcGVydHkgYXQgYHBhdGhgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gdW5zZXQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSBpcyBkZWxldGVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogNyB9IH1dIH07XG4gICAgICogXy51bnNldChvYmplY3QsICdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdCk7XG4gICAgICogLy8gPT4geyAnYSc6IFt7ICdiJzoge30gfV0gfTtcbiAgICAgKlxuICAgICAqIF8udW5zZXQob2JqZWN0LCAnYVswXS5iLmMnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJ2EnOiBbeyAnYic6IHt9IH1dIH07XG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5zZXQob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB0cnVlIDogYmFzZVVuc2V0KG9iamVjdCwgcGF0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgdmFsdWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy52YWx1ZXMobmV3IEZvbyk7XG4gICAgICogLy8gPT4gWzEsIDJdIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiBfLnZhbHVlcygnaGknKTtcbiAgICAgKiAvLyA9PiBbJ2gnLCAnaSddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdmFsdWVzKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA/IGJhc2VWYWx1ZXMob2JqZWN0LCBrZXlzKG9iamVjdCkpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLnZhbHVlc0luKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlc0luKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gW10gOiBiYXNlVmFsdWVzKG9iamVjdCwga2V5c0luKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyBgbnVtYmVyYCB3aXRoaW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gY2xhbXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsb3dlcl0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY2xhbXBlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoLTEwLCAtNSwgNSk7XG4gICAgICogLy8gPT4gLTVcbiAgICAgKlxuICAgICAqIF8uY2xhbXAoMTAsIC01LCA1KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmICh1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHVwcGVyID0gbG93ZXI7XG4gICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKHVwcGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdXBwZXIgPSB0b051bWJlcih1cHBlcik7XG4gICAgICAgIHVwcGVyID0gdXBwZXIgPT09IHVwcGVyID8gdXBwZXIgOiAwO1xuICAgICAgfVxuICAgICAgaWYgKGxvd2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbG93ZXIgPSB0b051bWJlcihsb3dlcik7XG4gICAgICAgIGxvd2VyID0gbG93ZXIgPT09IGxvd2VyID8gbG93ZXIgOiAwO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VDbGFtcCh0b051bWJlcihudW1iZXIpLCBsb3dlciwgdXBwZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgbmAgaXMgYmV0d2VlbiBgc3RhcnRgIGFuZCB1cCB0byBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIElmXG4gICAgICogYGVuZGAgaXMgbm90IHNwZWNpZmllZCBpdCdzIHNldCB0byBgc3RhcnRgIHdpdGggYHN0YXJ0YCB0aGVuIHNldCB0byBgMGAuXG4gICAgICogSWYgYHN0YXJ0YCBpcyBncmVhdGVyIHRoYW4gYGVuZGAgdGhlIHBhcmFtcyBhcmUgc3dhcHBlZCB0byBzdXBwb3J0XG4gICAgICogbmVnYXRpdmUgcmFuZ2VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG51bWJlcmAgaXMgaW4gdGhlIHJhbmdlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSgzLCAyLCA0KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoNCwgOCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDQsIDIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoMiwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSgxLjIsIDIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSg1LjIsIDQpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoLTMsIC0yLCAtNik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluUmFuZ2UobnVtYmVyLCBzdGFydCwgZW5kKSB7XG4gICAgICBzdGFydCA9IHRvTnVtYmVyKHN0YXJ0KSB8fCAwO1xuICAgICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbmQgPSB0b051bWJlcihlbmQpIHx8IDA7XG4gICAgICB9XG4gICAgICBudW1iZXIgPSB0b051bWJlcihudW1iZXIpO1xuICAgICAgcmV0dXJuIGJhc2VJblJhbmdlKG51bWJlciwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvZHVjZXMgYSByYW5kb20gbnVtYmVyIGJldHdlZW4gdGhlIGluY2x1c2l2ZSBgbG93ZXJgIGFuZCBgdXBwZXJgIGJvdW5kcy5cbiAgICAgKiBJZiBvbmx5IG9uZSBhcmd1bWVudCBpcyBwcm92aWRlZCBhIG51bWJlciBiZXR3ZWVuIGAwYCBhbmQgdGhlIGdpdmVuIG51bWJlclxuICAgICAqIGlzIHJldHVybmVkLiBJZiBgZmxvYXRpbmdgIGlzIGB0cnVlYCwgb3IgZWl0aGVyIGBsb3dlcmAgb3IgYHVwcGVyYCBhcmUgZmxvYXRzLFxuICAgICAqIGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyIGlzIHJldHVybmVkIGluc3RlYWQgb2YgYW4gaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbG93ZXI9MF0gVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbdXBwZXI9MV0gVGhlIHVwcGVyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zsb2F0aW5nXSBTcGVjaWZ5IHJldHVybmluZyBhIGZsb2F0aW5nLXBvaW50IG51bWJlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByYW5kb20gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgwLCA1KTtcbiAgICAgKiAvLyA9PiBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSk7XG4gICAgICogLy8gPT4gYWxzbyBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSwgdHJ1ZSk7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAwIGFuZCA1XG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgxLjIsIDUuMik7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAxLjIgYW5kIDUuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJhbmRvbShsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSB7XG4gICAgICBpZiAoZmxvYXRpbmcgJiYgdHlwZW9mIGZsb2F0aW5nICE9ICdib29sZWFuJyAmJiBpc0l0ZXJhdGVlQ2FsbChsb3dlciwgdXBwZXIsIGZsb2F0aW5nKSkge1xuICAgICAgICB1cHBlciA9IGZsb2F0aW5nID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1cHBlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IHVwcGVyO1xuICAgICAgICAgIHVwcGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBsb3dlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICBmbG9hdGluZyA9IGxvd2VyO1xuICAgICAgICAgIGxvd2VyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG93ZXIgPT09IHVuZGVmaW5lZCAmJiB1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxvd2VyID0gMDtcbiAgICAgICAgdXBwZXIgPSAxO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGxvd2VyID0gdG9OdW1iZXIobG93ZXIpIHx8IDA7XG4gICAgICAgIGlmICh1cHBlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdXBwZXIgPSBsb3dlcjtcbiAgICAgICAgICBsb3dlciA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXBwZXIgPSB0b051bWJlcih1cHBlcikgfHwgMDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGxvd2VyID4gdXBwZXIpIHtcbiAgICAgICAgdmFyIHRlbXAgPSBsb3dlcjtcbiAgICAgICAgbG93ZXIgPSB1cHBlcjtcbiAgICAgICAgdXBwZXIgPSB0ZW1wO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nIHx8IGxvd2VyICUgMSB8fCB1cHBlciAlIDEpIHtcbiAgICAgICAgdmFyIHJhbmQgPSBuYXRpdmVSYW5kb20oKTtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZU1pbihsb3dlciArIChyYW5kICogKHVwcGVyIC0gbG93ZXIgKyBmcmVlUGFyc2VGbG9hdCgnMWUtJyArICgocmFuZCArICcnKS5sZW5ndGggLSAxKSkpKSwgdXBwZXIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VSYW5kb20obG93ZXIsIHVwcGVyKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBbY2FtZWwgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FtZWxDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNhbWVsIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJy0tZm9vLWJhcicpO1xuICAgICAqIC8vID0+ICdmb29CYXInXG4gICAgICpcbiAgICAgKiBfLmNhbWVsQ2FzZSgnX19mb29fYmFyX18nKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqL1xuICAgIHZhciBjYW1lbENhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHdvcmQgPSB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gY2FwaXRhbGl6ZSh3b3JkKSA6IHdvcmQpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBgc3RyaW5nYCB0byB1cHBlciBjYXNlIGFuZCB0aGUgcmVtYWluaW5nXG4gICAgICogdG8gbG93ZXIgY2FzZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjYXBpdGFsaXplLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jYXBpdGFsaXplKCdGUkVEJyk7XG4gICAgICogLy8gPT4gJ0ZyZWQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgICAgIHJldHVybiB1cHBlckZpcnN0KHRvU3RyaW5nKHN0cmluZykudG9Mb3dlckNhc2UoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVidXJycyBgc3RyaW5nYCBieSBjb252ZXJ0aW5nIFtsYXRpbi0xIHN1cHBsZW1lbnRhcnkgbGV0dGVyc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW4tMV9TdXBwbGVtZW50XyhVbmljb2RlX2Jsb2NrKSNDaGFyYWN0ZXJfdGFibGUpXG4gICAgICogdG8gYmFzaWMgbGF0aW4gbGV0dGVycyBhbmQgcmVtb3ZpbmcgW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBkZWJ1cnIuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlYnVycignZMOpasOgIHZ1Jyk7XG4gICAgICogLy8gPT4gJ2RlamEgdnUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVidXJyKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcgJiYgc3RyaW5nLnJlcGxhY2UocmVMYXRpbjEsIGRlYnVyckxldHRlcikucmVwbGFjZShyZUNvbWJvTWFyaywgJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgc3RyaW5nYCBlbmRzIHdpdGggdGhlIGdpdmVuIHRhcmdldCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSBUaGUgc3RyaW5nIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwb3NpdGlvbj1zdHJpbmcubGVuZ3RoXSBUaGUgcG9zaXRpb24gdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBzdHJpbmdgIGVuZHMgd2l0aCBgdGFyZ2V0YCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmVuZHNXaXRoKCdhYmMnLCAnYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZW5kc1dpdGgoJ2FiYycsICdiJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uZW5kc1dpdGgoJ2FiYycsICdiJywgMik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVuZHNXaXRoKHN0cmluZywgdGFyZ2V0LCBwb3NpdGlvbikge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHRhcmdldCA9IHR5cGVvZiB0YXJnZXQgPT0gJ3N0cmluZycgPyB0YXJnZXQgOiAodGFyZ2V0ICsgJycpO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIHBvc2l0aW9uID0gcG9zaXRpb24gPT09IHVuZGVmaW5lZFxuICAgICAgICA/IGxlbmd0aFxuICAgICAgICA6IGJhc2VDbGFtcCh0b0ludGVnZXIocG9zaXRpb24pLCAwLCBsZW5ndGgpO1xuXG4gICAgICBwb3NpdGlvbiAtPSB0YXJnZXQubGVuZ3RoO1xuICAgICAgcmV0dXJuIHBvc2l0aW9uID49IDAgJiYgc3RyaW5nLmluZGV4T2YodGFyZ2V0LCBwb3NpdGlvbikgPT0gcG9zaXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGNoYXJhY3RlcnMgXCImXCIsIFwiPFwiLCBcIj5cIiwgJ1wiJywgXCInXCIsIGFuZCBcIlxcYFwiIGluIGBzdHJpbmdgIHRvXG4gICAgICogdGhlaXIgY29ycmVzcG9uZGluZyBIVE1MIGVudGl0aWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vIG90aGVyIGNoYXJhY3RlcnMgYXJlIGVzY2FwZWQuIFRvIGVzY2FwZSBhZGRpdGlvbmFsXG4gICAgICogY2hhcmFjdGVycyB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBUaG91Z2ggdGhlIFwiPlwiIGNoYXJhY3RlciBpcyBlc2NhcGVkIGZvciBzeW1tZXRyeSwgY2hhcmFjdGVycyBsaWtlXG4gICAgICogXCI+XCIgYW5kIFwiL1wiIGRvbid0IG5lZWQgZXNjYXBpbmcgaW4gSFRNTCBhbmQgaGF2ZSBubyBzcGVjaWFsIG1lYW5pbmdcbiAgICAgKiB1bmxlc3MgdGhleSdyZSBwYXJ0IG9mIGEgdGFnIG9yIHVucXVvdGVkIGF0dHJpYnV0ZSB2YWx1ZS5cbiAgICAgKiBTZWUgW01hdGhpYXMgQnluZW5zJ3MgYXJ0aWNsZV0oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2FtYmlndW91cy1hbXBlcnNhbmRzKVxuICAgICAqICh1bmRlciBcInNlbWktcmVsYXRlZCBmdW4gZmFjdFwiKSBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQmFja3RpY2tzIGFyZSBlc2NhcGVkIGJlY2F1c2UgaW4gSUUgPCA5LCB0aGV5IGNhbiBicmVhayBvdXQgb2ZcbiAgICAgKiBhdHRyaWJ1dGUgdmFsdWVzIG9yIEhUTUwgY29tbWVudHMuIFNlZSBbIzU5XShodHRwczovL2h0bWw1c2VjLm9yZy8jNTkpLFxuICAgICAqIFsjMTAyXShodHRwczovL2h0bWw1c2VjLm9yZy8jMTAyKSwgWyMxMDhdKGh0dHBzOi8vaHRtbDVzZWMub3JnLyMxMDgpLCBhbmRcbiAgICAgKiBbIzEzM10oaHR0cHM6Ly9odG1sNXNlYy5vcmcvIzEzMykgb2YgdGhlIFtIVE1MNSBTZWN1cml0eSBDaGVhdHNoZWV0XShodHRwczovL2h0bWw1c2VjLm9yZy8pXG4gICAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIFdoZW4gd29ya2luZyB3aXRoIEhUTUwgeW91IHNob3VsZCBhbHdheXMgW3F1b3RlIGF0dHJpYnV0ZSB2YWx1ZXNdKGh0dHA6Ly93b25rby5jb20vcG9zdC9odG1sLWVzY2FwaW5nKVxuICAgICAqIHRvIHJlZHVjZSBYU1MgdmVjdG9ycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXNjYXBlKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+ICdmcmVkLCBiYXJuZXksICZhbXA7IHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXNjYXBlKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiAoc3RyaW5nICYmIHJlSGFzVW5lc2NhcGVkSHRtbC50ZXN0KHN0cmluZykpXG4gICAgICAgID8gc3RyaW5nLnJlcGxhY2UocmVVbmVzY2FwZWRIdG1sLCBlc2NhcGVIdG1sQ2hhcilcbiAgICAgICAgOiBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXNjYXBlcyB0aGUgYFJlZ0V4cGAgc3BlY2lhbCBjaGFyYWN0ZXJzIFwiXlwiLCBcIiRcIiwgXCJcXFwiLCBcIi5cIiwgXCIqXCIsIFwiK1wiLFxuICAgICAqIFwiP1wiLCBcIihcIiwgXCIpXCIsIFwiW1wiLCBcIl1cIiwgXCJ7XCIsIFwifVwiLCBhbmQgXCJ8XCIgaW4gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gZXNjYXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmVzY2FwZVJlZ0V4cCgnW2xvZGFzaF0oaHR0cHM6Ly9sb2Rhc2guY29tLyknKTtcbiAgICAgKiAvLyA9PiAnXFxbbG9kYXNoXFxdXFwoaHR0cHM6Ly9sb2Rhc2hcXC5jb20vXFwpJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cChzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gKHN0cmluZyAmJiByZUhhc1JlZ0V4cENoYXIudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlUmVnRXhwQ2hhciwgJ1xcXFwkJicpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIFtrZWJhYiBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZXR0ZXJfY2FzZSNTcGVjaWFsX2Nhc2Vfc3R5bGVzKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGtlYmFiIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5rZWJhYkNhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdfX2Zvb19iYXJfXycpO1xuICAgICAqIC8vID0+ICdmb28tYmFyJ1xuICAgICAqL1xuICAgIHZhciBrZWJhYkNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnLScgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCwgYXMgc3BhY2Ugc2VwYXJhdGVkIHdvcmRzLCB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbG93ZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnLS1Gb28tQmFyJyk7XG4gICAgICogLy8gPT4gJ2ZvbyBiYXInXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2ZvbyBiYXInXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKi9cbiAgICB2YXIgbG93ZXJDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJyAnIDogJycpICsgd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBgc3RyaW5nYCB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY29udmVydGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sb3dlckZpcnN0KCdGcmVkJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQnXG4gICAgICpcbiAgICAgKiBfLmxvd2VyRmlyc3QoJ0ZSRUQnKTtcbiAgICAgKiAvLyA9PiAnZlJFRCdcbiAgICAgKi9cbiAgICB2YXIgbG93ZXJGaXJzdCA9IGNyZWF0ZUNhc2VGaXJzdCgndG9Mb3dlckNhc2UnKTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgYHN0cmluZ2AgdG8gdXBwZXIgY2FzZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udXBwZXJGaXJzdCgnZnJlZCcpO1xuICAgICAqIC8vID0+ICdGcmVkJ1xuICAgICAqXG4gICAgICogXy51cHBlckZpcnN0KCdGUkVEJyk7XG4gICAgICogLy8gPT4gJ0ZSRUQnXG4gICAgICovXG4gICAgdmFyIHVwcGVyRmlyc3QgPSBjcmVhdGVDYXNlRmlyc3QoJ3RvVXBwZXJDYXNlJyk7XG5cbiAgICAvKipcbiAgICAgKiBQYWRzIGBzdHJpbmdgIG9uIHRoZSBsZWZ0IGFuZCByaWdodCBzaWRlcyBpZiBpdCdzIHNob3J0ZXIgdGhhbiBgbGVuZ3RoYC5cbiAgICAgKiBQYWRkaW5nIGNoYXJhY3RlcnMgYXJlIHRydW5jYXRlZCBpZiB0aGV5IGNhbid0IGJlIGV2ZW5seSBkaXZpZGVkIGJ5IGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHBhZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD0wXSBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFkKCdhYmMnLCA4KTtcbiAgICAgKiAvLyA9PiAnICBhYmMgICAnXG4gICAgICpcbiAgICAgKiBfLnBhZCgnYWJjJywgOCwgJ18tJyk7XG4gICAgICogLy8gPT4gJ18tYWJjXy1fJ1xuICAgICAqXG4gICAgICogXy5wYWQoJ2FiYycsIDMpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFkKHN0cmluZywgbGVuZ3RoLCBjaGFycykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGxlbmd0aCA9IHRvSW50ZWdlcihsZW5ndGgpO1xuXG4gICAgICB2YXIgc3RyTGVuZ3RoID0gc3RyaW5nU2l6ZShzdHJpbmcpO1xuICAgICAgaWYgKCFsZW5ndGggfHwgc3RyTGVuZ3RoID49IGxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIG1pZCA9IChsZW5ndGggLSBzdHJMZW5ndGgpIC8gMixcbiAgICAgICAgICBsZWZ0TGVuZ3RoID0gbmF0aXZlRmxvb3IobWlkKSxcbiAgICAgICAgICByaWdodExlbmd0aCA9IG5hdGl2ZUNlaWwobWlkKTtcblxuICAgICAgcmV0dXJuIGNyZWF0ZVBhZGRpbmcoJycsIGxlZnRMZW5ndGgsIGNoYXJzKSArIHN0cmluZyArIGNyZWF0ZVBhZGRpbmcoJycsIHJpZ2h0TGVuZ3RoLCBjaGFycyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgcmlnaHQgc2lkZSBpZiBpdCdzIHNob3J0ZXIgdGhhbiBgbGVuZ3RoYC4gUGFkZGluZ1xuICAgICAqIGNoYXJhY3RlcnMgYXJlIHRydW5jYXRlZCBpZiB0aGV5IGV4Y2VlZCBgbGVuZ3RoYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBwYWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9MF0gVGhlIHBhZGRpbmcgbGVuZ3RoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9JyAnXSBUaGUgc3RyaW5nIHVzZWQgYXMgcGFkZGluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBwYWRkZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhZEVuZCgnYWJjJywgNik7XG4gICAgICogLy8gPT4gJ2FiYyAgICdcbiAgICAgKlxuICAgICAqIF8ucGFkRW5kKCdhYmMnLCA2LCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnYWJjXy1fJ1xuICAgICAqXG4gICAgICogXy5wYWRFbmQoJ2FiYycsIDMpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFkRW5kKHN0cmluZywgbGVuZ3RoLCBjaGFycykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJpbmcgKyBjcmVhdGVQYWRkaW5nKHN0cmluZywgbGVuZ3RoLCBjaGFycyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFkcyBgc3RyaW5nYCBvbiB0aGUgbGVmdCBzaWRlIGlmIGl0J3Mgc2hvcnRlciB0aGFuIGBsZW5ndGhgLiBQYWRkaW5nXG4gICAgICogY2hhcmFjdGVycyBhcmUgdHJ1bmNhdGVkIGlmIHRoZXkgZXhjZWVkIGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHBhZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD0wXSBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFkU3RhcnQoJ2FiYycsIDYpO1xuICAgICAqIC8vID0+ICcgICBhYmMnXG4gICAgICpcbiAgICAgKiBfLnBhZFN0YXJ0KCdhYmMnLCA2LCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnXy1fYWJjJ1xuICAgICAqXG4gICAgICogXy5wYWRTdGFydCgnYWJjJywgMyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYWRTdGFydChzdHJpbmcsIGxlbmd0aCwgY2hhcnMpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gY3JlYXRlUGFkZGluZyhzdHJpbmcsIGxlbmd0aCwgY2hhcnMpICsgc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIGFuIGludGVnZXIgb2YgdGhlIHNwZWNpZmllZCByYWRpeC4gSWYgYHJhZGl4YCBpc1xuICAgICAqIGB1bmRlZmluZWRgIG9yIGAwYCwgYSBgcmFkaXhgIG9mIGAxMGAgaXMgdXNlZCB1bmxlc3MgYHZhbHVlYCBpcyBhIGhleGFkZWNpbWFsLFxuICAgICAqIGluIHdoaWNoIGNhc2UgYSBgcmFkaXhgIG9mIGAxNmAgaXMgdXNlZC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBhbGlnbnMgd2l0aCB0aGUgW0VTNSBpbXBsZW1lbnRhdGlvbl0oaHR0cHM6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMS4yLjIpXG4gICAgICogb2YgYHBhcnNlSW50YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3JhZGl4PTEwXSBUaGUgcmFkaXggdG8gaW50ZXJwcmV0IGB2YWx1ZWAgYnkuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhcnNlSW50KCcwOCcpO1xuICAgICAqIC8vID0+IDhcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnNicsICcwOCcsICcxMCddLCBfLnBhcnNlSW50KTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFyc2VJbnQoc3RyaW5nLCByYWRpeCwgZ3VhcmQpIHtcbiAgICAgIC8vIENocm9tZSBmYWlscyB0byB0cmltIGxlYWRpbmcgPEJPTT4gd2hpdGVzcGFjZSBjaGFyYWN0ZXJzLlxuICAgICAgLy8gU2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0zMTA5IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBpZiAoZ3VhcmQgfHwgcmFkaXggPT0gbnVsbCkge1xuICAgICAgICByYWRpeCA9IDA7XG4gICAgICB9IGVsc2UgaWYgKHJhZGl4KSB7XG4gICAgICAgIHJhZGl4ID0gK3JhZGl4O1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICAgICAgcmV0dXJuIG5hdGl2ZVBhcnNlSW50KHN0cmluZywgcmFkaXggfHwgKHJlSGFzSGV4UHJlZml4LnRlc3Qoc3RyaW5nKSA/IDE2IDogMTApKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXBlYXRzIHRoZSBnaXZlbiBzdHJpbmcgYG5gIHRpbWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHJlcGVhdC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MF0gVGhlIG51bWJlciBvZiB0aW1lcyB0byByZXBlYXQgdGhlIHN0cmluZy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByZXBlYXRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCcqJywgMyk7XG4gICAgICogLy8gPT4gJyoqKidcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCdhYmMnLCAyKTtcbiAgICAgKiAvLyA9PiAnYWJjYWJjJ1xuICAgICAqXG4gICAgICogXy5yZXBlYXQoJ2FiYycsIDApO1xuICAgICAqIC8vID0+ICcnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVwZWF0KHN0cmluZywgbikge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG5cbiAgICAgIHZhciByZXN1bHQgPSAnJztcbiAgICAgIGlmICghc3RyaW5nIHx8IG4gPCAxIHx8IG4gPiBNQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICAvLyBMZXZlcmFnZSB0aGUgZXhwb25lbnRpYXRpb24gYnkgc3F1YXJpbmcgYWxnb3JpdGhtIGZvciBhIGZhc3RlciByZXBlYXQuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRXhwb25lbnRpYXRpb25fYnlfc3F1YXJpbmcgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgIGRvIHtcbiAgICAgICAgaWYgKG4gJSAyKSB7XG4gICAgICAgICAgcmVzdWx0ICs9IHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICBuID0gbmF0aXZlRmxvb3IobiAvIDIpO1xuICAgICAgICBzdHJpbmcgKz0gc3RyaW5nO1xuICAgICAgfSB3aGlsZSAobik7XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgbWF0Y2hlcyBmb3IgYHBhdHRlcm5gIGluIGBzdHJpbmdgIHdpdGggYHJlcGxhY2VtZW50YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiBbYFN0cmluZyNyZXBsYWNlYF0oaHR0cHM6Ly9tZG4uaW8vU3RyaW5nL3JlcGxhY2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cHxzdHJpbmd9IHBhdHRlcm4gVGhlIHBhdHRlcm4gdG8gcmVwbGFjZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gcmVwbGFjZW1lbnQgVGhlIG1hdGNoIHJlcGxhY2VtZW50LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIG1vZGlmaWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZXBsYWNlKCdIaSBGcmVkJywgJ0ZyZWQnLCAnQmFybmV5Jyk7XG4gICAgICogLy8gPT4gJ0hpIEJhcm5leSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXBsYWNlKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgc3RyaW5nID0gdG9TdHJpbmcoYXJnc1swXSk7XG5cbiAgICAgIHJldHVybiBhcmdzLmxlbmd0aCA8IDMgPyBzdHJpbmcgOiBzdHJpbmcucmVwbGFjZShhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBbc25ha2UgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU25ha2VfY2FzZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzbmFrZSBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc25ha2VDYXNlKCdGb28gQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICpcbiAgICAgKiBfLnNuYWtlQ2FzZSgnLS1mb28tYmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb19iYXInXG4gICAgICovXG4gICAgdmFyIHNuYWtlQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICdfJyA6ICcnKSArIHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBieSBgc2VwYXJhdG9yYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiBbYFN0cmluZyNzcGxpdGBdKGh0dHBzOi8vbWRuLmlvL1N0cmluZy9zcGxpdCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gc3BsaXQuXG4gICAgICogQHBhcmFtIHtSZWdFeHB8c3RyaW5nfSBzZXBhcmF0b3IgVGhlIHNlcGFyYXRvciBwYXR0ZXJuIHRvIHNwbGl0IGJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGltaXRdIFRoZSBsZW5ndGggdG8gdHJ1bmNhdGUgcmVzdWx0cyB0by5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBzdHJpbmcgc2VnbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc3BsaXQoJ2EtYi1jJywgJy0nLCAyKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYiddXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3BsaXQoc3RyaW5nLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICByZXR1cm4gdG9TdHJpbmcoc3RyaW5nKS5zcGxpdChzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBbc3RhcnQgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGV0dGVyX2Nhc2UjU3R5bGlzdGljX29yX3NwZWNpYWxpc2VkX3VzYWdlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHN0YXJ0IGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdGFydENhc2UoJy0tZm9vLWJhcicpO1xuICAgICAqIC8vID0+ICdGb28gQmFyJ1xuICAgICAqXG4gICAgICogXy5zdGFydENhc2UoJ2Zvb0JhcicpO1xuICAgICAqIC8vID0+ICdGb28gQmFyJ1xuICAgICAqXG4gICAgICogXy5zdGFydENhc2UoJ19fZm9vX2Jhcl9fJyk7XG4gICAgICogLy8gPT4gJ0ZvbyBCYXInXG4gICAgICovXG4gICAgdmFyIHN0YXJ0Q2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICcgJyA6ICcnKSArIGNhcGl0YWxpemUod29yZCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHN0cmluZ2Agc3RhcnRzIHdpdGggdGhlIGdpdmVuIHRhcmdldCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gc2VhcmNoLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSBUaGUgc3RyaW5nIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwb3NpdGlvbj0wXSBUaGUgcG9zaXRpb24gdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBzdHJpbmdgIHN0YXJ0cyB3aXRoIGB0YXJnZXRgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2EnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0c1dpdGgoJ2FiYycsICdiJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2InLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhcnRzV2l0aChzdHJpbmcsIHRhcmdldCwgcG9zaXRpb24pIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwb3NpdGlvbiA9IGJhc2VDbGFtcCh0b0ludGVnZXIocG9zaXRpb24pLCAwLCBzdHJpbmcubGVuZ3RoKTtcbiAgICAgIHJldHVybiBzdHJpbmcubGFzdEluZGV4T2YodGFyZ2V0LCBwb3NpdGlvbikgPT0gcG9zaXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNvbXBpbGVkIHRlbXBsYXRlIGZ1bmN0aW9uIHRoYXQgY2FuIGludGVycG9sYXRlIGRhdGEgcHJvcGVydGllc1xuICAgICAqIGluIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXJzLCBIVE1MLWVzY2FwZSBpbnRlcnBvbGF0ZWQgZGF0YSBwcm9wZXJ0aWVzIGluXG4gICAgICogXCJlc2NhcGVcIiBkZWxpbWl0ZXJzLCBhbmQgZXhlY3V0ZSBKYXZhU2NyaXB0IGluIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXJzLiBEYXRhXG4gICAgICogcHJvcGVydGllcyBtYXkgYmUgYWNjZXNzZWQgYXMgZnJlZSB2YXJpYWJsZXMgaW4gdGhlIHRlbXBsYXRlLiBJZiBhIHNldHRpbmdcbiAgICAgKiBvYmplY3QgaXMgZ2l2ZW4gaXQgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIGBfLnRlbXBsYXRlU2V0dGluZ3NgIHZhbHVlcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBJbiB0aGUgZGV2ZWxvcG1lbnQgYnVpbGQgYF8udGVtcGxhdGVgIHV0aWxpemVzXG4gICAgICogW3NvdXJjZVVSTHNdKGh0dHA6Ly93d3cuaHRtbDVyb2Nrcy5jb20vZW4vdHV0b3JpYWxzL2RldmVsb3BlcnRvb2xzL3NvdXJjZW1hcHMvI3RvYy1zb3VyY2V1cmwpXG4gICAgICogZm9yIGVhc2llciBkZWJ1Z2dpbmcuXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBwcmVjb21waWxpbmcgdGVtcGxhdGVzIHNlZVxuICAgICAqIFtsb2Rhc2gncyBjdXN0b20gYnVpbGRzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vbG9kYXNoLmNvbS9jdXN0b20tYnVpbGRzKS5cbiAgICAgKlxuICAgICAqIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIENocm9tZSBleHRlbnNpb24gc2FuZGJveGVzIHNlZVxuICAgICAqIFtDaHJvbWUncyBleHRlbnNpb25zIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLmNocm9tZS5jb20vZXh0ZW5zaW9ucy9zYW5kYm94aW5nRXZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSB0ZW1wbGF0ZSBzdHJpbmcuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmVzY2FwZV0gVGhlIEhUTUwgXCJlc2NhcGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmV2YWx1YXRlXSBUaGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuaW1wb3J0c10gQW4gb2JqZWN0IHRvIGltcG9ydCBpbnRvIHRoZSB0ZW1wbGF0ZSBhcyBmcmVlIHZhcmlhYmxlcy5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gW29wdGlvbnMuaW50ZXJwb2xhdGVdIFRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VVUkxdIFRoZSBzb3VyY2VVUkwgb2YgdGhlIHRlbXBsYXRlJ3MgY29tcGlsZWQgc291cmNlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy52YXJpYWJsZV0gVGhlIGRhdGEgb2JqZWN0IHZhcmlhYmxlIG5hbWUuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY29tcGlsZWQgdGVtcGxhdGUgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlciB0byBjcmVhdGUgYSBjb21waWxlZCB0ZW1wbGF0ZS5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyA8JT0gdXNlciAlPiEnKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2VyJzogJ2ZyZWQnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkISdcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgSFRNTCBcImVzY2FwZVwiIGRlbGltaXRlciB0byBlc2NhcGUgZGF0YSBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPGI+PCUtIHZhbHVlICU+PC9iPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3ZhbHVlJzogJzxzY3JpcHQ+JyB9KTtcbiAgICAgKiAvLyA9PiAnPGI+Jmx0O3NjcmlwdCZndDs8L2I+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBcImV2YWx1YXRlXCIgZGVsaW1pdGVyIHRvIGV4ZWN1dGUgSmF2YVNjcmlwdCBhbmQgZ2VuZXJhdGUgSFRNTC5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8JSBfLmZvckVhY2godXNlcnMsIGZ1bmN0aW9uKHVzZXIpIHsgJT48bGk+PCUtIHVzZXIgJT48L2xpPjwlIH0pOyAlPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXJzJzogWydmcmVkJywgJ2Jhcm5leSddIH0pO1xuICAgICAqIC8vID0+ICc8bGk+ZnJlZDwvbGk+PGxpPmJhcm5leTwvbGk+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBpbnRlcm5hbCBgcHJpbnRgIGZ1bmN0aW9uIGluIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXJzLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzwlIHByaW50KFwiaGVsbG8gXCIgKyB1c2VyKTsgJT4hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdiYXJuZXknIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBiYXJuZXkhJ1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBFUyBkZWxpbWl0ZXIgYXMgYW4gYWx0ZXJuYXRpdmUgdG8gdGhlIGRlZmF1bHQgXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyAkeyB1c2VyIH0hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdwZWJibGVzJyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gcGViYmxlcyEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgY3VzdG9tIHRlbXBsYXRlIGRlbGltaXRlcnMuXG4gICAgICogXy50ZW1wbGF0ZVNldHRpbmdzLmludGVycG9sYXRlID0gL3t7KFtcXHNcXFNdKz8pfX0vZztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyB7eyB1c2VyIH19IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnbXVzdGFjaGUnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBtdXN0YWNoZSEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgYmFja3NsYXNoZXMgdG8gdHJlYXQgZGVsaW1pdGVycyBhcyBwbGFpbiB0ZXh0LlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzwlPSBcIlxcXFw8JS0gdmFsdWUgJVxcXFw+XCIgJT4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd2YWx1ZSc6ICdpZ25vcmVkJyB9KTtcbiAgICAgKiAvLyA9PiAnPCUtIHZhbHVlICU+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBgaW1wb3J0c2Agb3B0aW9uIHRvIGltcG9ydCBgalF1ZXJ5YCBhcyBganFgLlxuICAgICAqIHZhciB0ZXh0ID0gJzwlIGpxLmVhY2godXNlcnMsIGZ1bmN0aW9uKHVzZXIpIHsgJT48bGk+PCUtIHVzZXIgJT48L2xpPjwlIH0pOyAlPic7XG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSh0ZXh0LCB7ICdpbXBvcnRzJzogeyAnanEnOiBqUXVlcnkgfSB9KTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2Vycyc6IFsnZnJlZCcsICdiYXJuZXknXSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHNvdXJjZVVSTGAgb3B0aW9uIHRvIHNwZWNpZnkgYSBjdXN0b20gc291cmNlVVJMIGZvciB0aGUgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJywgeyAnc291cmNlVVJMJzogJy9iYXNpYy9ncmVldGluZy5qc3QnIH0pO1xuICAgICAqIGNvbXBpbGVkKGRhdGEpO1xuICAgICAqIC8vID0+IGZpbmQgdGhlIHNvdXJjZSBvZiBcImdyZWV0aW5nLmpzdFwiIHVuZGVyIHRoZSBTb3VyY2VzIHRhYiBvciBSZXNvdXJjZXMgcGFuZWwgb2YgdGhlIHdlYiBpbnNwZWN0b3JcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHZhcmlhYmxlYCBvcHRpb24gdG8gZW5zdXJlIGEgd2l0aC1zdGF0ZW1lbnQgaXNuJ3QgdXNlZCBpbiB0aGUgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGkgPCU9IGRhdGEudXNlciAlPiEnLCB7ICd2YXJpYWJsZSc6ICdkYXRhJyB9KTtcbiAgICAgKiBjb21waWxlZC5zb3VyY2U7XG4gICAgICogLy8gPT4gZnVuY3Rpb24oZGF0YSkge1xuICAgICAqIC8vICAgdmFyIF9fdCwgX19wID0gJyc7XG4gICAgICogLy8gICBfX3AgKz0gJ2hpICcgKyAoKF9fdCA9ICggZGF0YS51c2VyICkpID09IG51bGwgPyAnJyA6IF9fdCkgKyAnISc7XG4gICAgICogLy8gICByZXR1cm4gX19wO1xuICAgICAqIC8vIH1cbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHNvdXJjZWAgcHJvcGVydHkgdG8gaW5saW5lIGNvbXBpbGVkIHRlbXBsYXRlcyBmb3IgbWVhbmluZ2Z1bFxuICAgICAqIC8vIGxpbmUgbnVtYmVycyBpbiBlcnJvciBtZXNzYWdlcyBhbmQgc3RhY2sgdHJhY2VzLlxuICAgICAqIGZzLndyaXRlRmlsZVN5bmMocGF0aC5qb2luKGN3ZCwgJ2pzdC5qcycpLCAnXFxcbiAgICAgKiAgIHZhciBKU1QgPSB7XFxcbiAgICAgKiAgICAgXCJtYWluXCI6ICcgKyBfLnRlbXBsYXRlKG1haW5UZXh0KS5zb3VyY2UgKyAnXFxcbiAgICAgKiAgIH07XFxcbiAgICAgKiAnKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0ZW1wbGF0ZShzdHJpbmcsIG9wdGlvbnMsIGd1YXJkKSB7XG4gICAgICAvLyBCYXNlZCBvbiBKb2huIFJlc2lnJ3MgYHRtcGxgIGltcGxlbWVudGF0aW9uIChodHRwOi8vZWpvaG4ub3JnL2Jsb2cvamF2YXNjcmlwdC1taWNyby10ZW1wbGF0aW5nLylcbiAgICAgIC8vIGFuZCBMYXVyYSBEb2t0b3JvdmEncyBkb1QuanMgKGh0dHBzOi8vZ2l0aHViLmNvbS9vbGFkby9kb1QpLlxuICAgICAgdmFyIHNldHRpbmdzID0gbG9kYXNoLnRlbXBsYXRlU2V0dGluZ3M7XG5cbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIG9wdGlvbnMsIGd1YXJkKSkge1xuICAgICAgICBvcHRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIG9wdGlvbnMgPSBhc3NpZ25JbldpdGgoe30sIG9wdGlvbnMsIHNldHRpbmdzLCBhc3NpZ25JbkRlZmF1bHRzKTtcblxuICAgICAgdmFyIGltcG9ydHMgPSBhc3NpZ25JbldpdGgoe30sIG9wdGlvbnMuaW1wb3J0cywgc2V0dGluZ3MuaW1wb3J0cywgYXNzaWduSW5EZWZhdWx0cyksXG4gICAgICAgICAgaW1wb3J0c0tleXMgPSBrZXlzKGltcG9ydHMpLFxuICAgICAgICAgIGltcG9ydHNWYWx1ZXMgPSBiYXNlVmFsdWVzKGltcG9ydHMsIGltcG9ydHNLZXlzKTtcblxuICAgICAgdmFyIGlzRXNjYXBpbmcsXG4gICAgICAgICAgaXNFdmFsdWF0aW5nLFxuICAgICAgICAgIGluZGV4ID0gMCxcbiAgICAgICAgICBpbnRlcnBvbGF0ZSA9IG9wdGlvbnMuaW50ZXJwb2xhdGUgfHwgcmVOb01hdGNoLFxuICAgICAgICAgIHNvdXJjZSA9IFwiX19wICs9ICdcIjtcblxuICAgICAgLy8gQ29tcGlsZSB0aGUgcmVnZXhwIHRvIG1hdGNoIGVhY2ggZGVsaW1pdGVyLlxuICAgICAgdmFyIHJlRGVsaW1pdGVycyA9IFJlZ0V4cChcbiAgICAgICAgKG9wdGlvbnMuZXNjYXBlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wnICtcbiAgICAgICAgaW50ZXJwb2xhdGUuc291cmNlICsgJ3wnICtcbiAgICAgICAgKGludGVycG9sYXRlID09PSByZUludGVycG9sYXRlID8gcmVFc1RlbXBsYXRlIDogcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAob3B0aW9ucy5ldmFsdWF0ZSB8fCByZU5vTWF0Y2gpLnNvdXJjZSArICd8JCdcbiAgICAgICwgJ2cnKTtcblxuICAgICAgLy8gVXNlIGEgc291cmNlVVJMIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICcvLyMgc291cmNlVVJMPScgK1xuICAgICAgICAoJ3NvdXJjZVVSTCcgaW4gb3B0aW9uc1xuICAgICAgICAgID8gb3B0aW9ucy5zb3VyY2VVUkxcbiAgICAgICAgICA6ICgnbG9kYXNoLnRlbXBsYXRlU291cmNlc1snICsgKCsrdGVtcGxhdGVDb3VudGVyKSArICddJylcbiAgICAgICAgKSArICdcXG4nO1xuXG4gICAgICBzdHJpbmcucmVwbGFjZShyZURlbGltaXRlcnMsIGZ1bmN0aW9uKG1hdGNoLCBlc2NhcGVWYWx1ZSwgaW50ZXJwb2xhdGVWYWx1ZSwgZXNUZW1wbGF0ZVZhbHVlLCBldmFsdWF0ZVZhbHVlLCBvZmZzZXQpIHtcbiAgICAgICAgaW50ZXJwb2xhdGVWYWx1ZSB8fCAoaW50ZXJwb2xhdGVWYWx1ZSA9IGVzVGVtcGxhdGVWYWx1ZSk7XG5cbiAgICAgICAgLy8gRXNjYXBlIGNoYXJhY3RlcnMgdGhhdCBjYW4ndCBiZSBpbmNsdWRlZCBpbiBzdHJpbmcgbGl0ZXJhbHMuXG4gICAgICAgIHNvdXJjZSArPSBzdHJpbmcuc2xpY2UoaW5kZXgsIG9mZnNldCkucmVwbGFjZShyZVVuZXNjYXBlZFN0cmluZywgZXNjYXBlU3RyaW5nQ2hhcik7XG5cbiAgICAgICAgLy8gUmVwbGFjZSBkZWxpbWl0ZXJzIHdpdGggc25pcHBldHMuXG4gICAgICAgIGlmIChlc2NhcGVWYWx1ZSkge1xuICAgICAgICAgIGlzRXNjYXBpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbl9fZShcIiArIGVzY2FwZVZhbHVlICsgXCIpICtcXG4nXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2YWx1YXRlVmFsdWUpIHtcbiAgICAgICAgICBpc0V2YWx1YXRpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIic7XFxuXCIgKyBldmFsdWF0ZVZhbHVlICsgXCI7XFxuX19wICs9ICdcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW50ZXJwb2xhdGVWYWx1ZSkge1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbigoX190ID0gKFwiICsgaW50ZXJwb2xhdGVWYWx1ZSArIFwiKSkgPT0gbnVsbCA/ICcnIDogX190KSArXFxuJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuXG4gICAgICAgIC8vIFRoZSBKUyBlbmdpbmUgZW1iZWRkZWQgaW4gQWRvYmUgcHJvZHVjdHMgbmVlZHMgYG1hdGNoYCByZXR1cm5lZCBpblxuICAgICAgICAvLyBvcmRlciB0byBwcm9kdWNlIHRoZSBjb3JyZWN0IGBvZmZzZXRgIHZhbHVlLlxuICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICB9KTtcblxuICAgICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgICAgLy8gSWYgYHZhcmlhYmxlYCBpcyBub3Qgc3BlY2lmaWVkIHdyYXAgYSB3aXRoLXN0YXRlbWVudCBhcm91bmQgdGhlIGdlbmVyYXRlZFxuICAgICAgLy8gY29kZSB0byBhZGQgdGhlIGRhdGEgb2JqZWN0IHRvIHRoZSB0b3Agb2YgdGhlIHNjb3BlIGNoYWluLlxuICAgICAgdmFyIHZhcmlhYmxlID0gb3B0aW9ucy52YXJpYWJsZTtcbiAgICAgIGlmICghdmFyaWFibGUpIHtcbiAgICAgICAgc291cmNlID0gJ3dpdGggKG9iaikge1xcbicgKyBzb3VyY2UgKyAnXFxufVxcbic7XG4gICAgICB9XG4gICAgICAvLyBDbGVhbnVwIGNvZGUgYnkgc3RyaXBwaW5nIGVtcHR5IHN0cmluZ3MuXG4gICAgICBzb3VyY2UgPSAoaXNFdmFsdWF0aW5nID8gc291cmNlLnJlcGxhY2UocmVFbXB0eVN0cmluZ0xlYWRpbmcsICcnKSA6IHNvdXJjZSlcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ01pZGRsZSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ1RyYWlsaW5nLCAnJDE7Jyk7XG5cbiAgICAgIC8vIEZyYW1lIGNvZGUgYXMgdGhlIGZ1bmN0aW9uIGJvZHkuXG4gICAgICBzb3VyY2UgPSAnZnVuY3Rpb24oJyArICh2YXJpYWJsZSB8fCAnb2JqJykgKyAnKSB7XFxuJyArXG4gICAgICAgICh2YXJpYWJsZVxuICAgICAgICAgID8gJydcbiAgICAgICAgICA6ICdvYmogfHwgKG9iaiA9IHt9KTtcXG4nXG4gICAgICAgICkgK1xuICAgICAgICBcInZhciBfX3QsIF9fcCA9ICcnXCIgK1xuICAgICAgICAoaXNFc2NhcGluZ1xuICAgICAgICAgICA/ICcsIF9fZSA9IF8uZXNjYXBlJ1xuICAgICAgICAgICA6ICcnXG4gICAgICAgICkgK1xuICAgICAgICAoaXNFdmFsdWF0aW5nXG4gICAgICAgICAgPyAnLCBfX2ogPSBBcnJheS5wcm90b3R5cGUuam9pbjtcXG4nICtcbiAgICAgICAgICAgIFwiZnVuY3Rpb24gcHJpbnQoKSB7IF9fcCArPSBfX2ouY2FsbChhcmd1bWVudHMsICcnKSB9XFxuXCJcbiAgICAgICAgICA6ICc7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgc291cmNlICtcbiAgICAgICAgJ3JldHVybiBfX3BcXG59JztcblxuICAgICAgdmFyIHJlc3VsdCA9IGF0dGVtcHQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBGdW5jdGlvbihpbXBvcnRzS2V5cywgc291cmNlVVJMICsgJ3JldHVybiAnICsgc291cmNlKVxuICAgICAgICAgIC5hcHBseSh1bmRlZmluZWQsIGltcG9ydHNWYWx1ZXMpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uJ3Mgc291cmNlIGJ5IGl0cyBgdG9TdHJpbmdgIG1ldGhvZCBvclxuICAgICAgLy8gdGhlIGBzb3VyY2VgIHByb3BlcnR5IGFzIGEgY29udmVuaWVuY2UgZm9yIGlubGluaW5nIGNvbXBpbGVkIHRlbXBsYXRlcy5cbiAgICAgIHJlc3VsdC5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICBpZiAoaXNFcnJvcihyZXN1bHQpKSB7XG4gICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AsIGFzIGEgd2hvbGUsIHRvIGxvd2VyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBsb3dlciBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignLS1Gb28tQmFyJyk7XG4gICAgICogLy8gPT4gJy0tZm9vLWJhcidcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvb2JhcidcbiAgICAgKlxuICAgICAqIF8udG9Mb3dlcignX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnX19mb29fYmFyX18nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9Mb3dlcih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBhIHdob2xlLCB0byB1cHBlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdXBwZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvVXBwZXIoJy0tZm9vLWJhcicpO1xuICAgICAqIC8vID0+ICctLUZPTy1CQVInXG4gICAgICpcbiAgICAgKiBfLnRvVXBwZXIoJ2Zvb0JhcicpO1xuICAgICAqIC8vID0+ICdGT09CQVInXG4gICAgICpcbiAgICAgKiBfLnRvVXBwZXIoJ19fZm9vX2Jhcl9fJyk7XG4gICAgICogLy8gPT4gJ19fRk9PX0JBUl9fJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvVXBwZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB0b1N0cmluZyh2YWx1ZSkudG9VcHBlckNhc2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2Ugb3Igc3BlY2lmaWVkIGNoYXJhY3RlcnMgZnJvbSBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byB0cmltLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9d2hpdGVzcGFjZV0gVGhlIGNoYXJhY3RlcnMgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbSgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLnRyaW0oJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMnXG4gICAgICpcbiAgICAgKiBfLm1hcChbJyAgZm9vICAnLCAnICBiYXIgICddLCBfLnRyaW0pO1xuICAgICAqIC8vID0+IFsnZm9vJywgJ2JhciddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbShzdHJpbmcsIGNoYXJzLCBndWFyZCkge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGlmICghc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICBpZiAoZ3VhcmQgfHwgY2hhcnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UocmVUcmltLCAnJyk7XG4gICAgICB9XG4gICAgICBjaGFycyA9IChjaGFycyArICcnKTtcbiAgICAgIGlmICghY2hhcnMpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHZhciBzdHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShzdHJpbmcpLFxuICAgICAgICAgIGNoclN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KGNoYXJzKTtcblxuICAgICAgcmV0dXJuIHN0clN5bWJvbHNcbiAgICAgICAgLnNsaWNlKGNoYXJzU3RhcnRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSwgY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSArIDEpXG4gICAgICAgIC5qb2luKCcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRyYWlsaW5nIHdoaXRlc3BhY2Ugb3Igc3BlY2lmaWVkIGNoYXJhY3RlcnMgZnJvbSBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byB0cmltLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9d2hpdGVzcGFjZV0gVGhlIGNoYXJhY3RlcnMgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbUVuZCgnICBhYmMgICcpO1xuICAgICAqIC8vID0+ICcgIGFiYydcbiAgICAgKlxuICAgICAqIF8udHJpbUVuZCgnLV8tYWJjLV8tJywgJ18tJyk7XG4gICAgICogLy8gPT4gJy1fLWFiYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmltRW5kKHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKCFzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIGlmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZShyZVRyaW1FbmQsICcnKTtcbiAgICAgIH1cbiAgICAgIGNoYXJzID0gKGNoYXJzICsgJycpO1xuICAgICAgaWYgKCFjaGFycykge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIHN0clN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KHN0cmluZyk7XG4gICAgICByZXR1cm4gc3RyU3ltYm9sc1xuICAgICAgICAuc2xpY2UoMCwgY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBzdHJpbmdUb0FycmF5KGNoYXJzKSkgKyAxKVxuICAgICAgICAuam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsZWFkaW5nIHdoaXRlc3BhY2Ugb3Igc3BlY2lmaWVkIGNoYXJhY3RlcnMgZnJvbSBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byB0cmltLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2hhcnM9d2hpdGVzcGFjZV0gVGhlIGNoYXJhY3RlcnMgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJpbW1lZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udHJpbVN0YXJ0KCcgIGFiYyAgJyk7XG4gICAgICogLy8gPT4gJ2FiYyAgJ1xuICAgICAqXG4gICAgICogXy50cmltU3RhcnQoJy1fLWFiYy1fLScsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmMtXy0nXG4gICAgICovXG4gICAgZnVuY3Rpb24gdHJpbVN0YXJ0KHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKCFzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIGlmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZShyZVRyaW1TdGFydCwgJycpO1xuICAgICAgfVxuICAgICAgY2hhcnMgPSAoY2hhcnMgKyAnJyk7XG4gICAgICBpZiAoIWNoYXJzKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKTtcbiAgICAgIHJldHVybiBzdHJTeW1ib2xzXG4gICAgICAgIC5zbGljZShjaGFyc1N0YXJ0SW5kZXgoc3RyU3ltYm9scywgc3RyaW5nVG9BcnJheShjaGFycykpKVxuICAgICAgICAuam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGVzIGBzdHJpbmdgIGlmIGl0J3MgbG9uZ2VyIHRoYW4gdGhlIGdpdmVuIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBUaGUgbGFzdCBjaGFyYWN0ZXJzIG9mIHRoZSB0cnVuY2F0ZWQgc3RyaW5nIGFyZSByZXBsYWNlZCB3aXRoIHRoZSBvbWlzc2lvblxuICAgICAqIHN0cmluZyB3aGljaCBkZWZhdWx0cyB0byBcIi4uLlwiLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHRydW5jYXRlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz0oe30pXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmxlbmd0aD0zMF0gVGhlIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMub21pc3Npb249Jy4uLiddIFRoZSBzdHJpbmcgdG8gaW5kaWNhdGUgdGV4dCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW29wdGlvbnMuc2VwYXJhdG9yXSBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gdHJ1bmNhdGUgdG8uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJ1bmNhdGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycpO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm8uLi4nXG4gICAgICpcbiAgICAgKiBfLnRydW5jYXRlKCdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm9yaW5vJywge1xuICAgICAqICAgJ2xlbmd0aCc6IDI0LFxuICAgICAqICAgJ3NlcGFyYXRvcic6ICcgJ1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdsZW5ndGgnOiAyNCxcbiAgICAgKiAgICdzZXBhcmF0b3InOiAvLD8gKy9cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdvbWlzc2lvbic6ICcgWy4uLl0nXG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZyBbLi4uXSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cnVuY2F0ZShzdHJpbmcsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBERUZBVUxUX1RSVU5DX0xFTkdUSCxcbiAgICAgICAgICBvbWlzc2lvbiA9IERFRkFVTFRfVFJVTkNfT01JU1NJT047XG5cbiAgICAgIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gJ3NlcGFyYXRvcicgaW4gb3B0aW9ucyA/IG9wdGlvbnMuc2VwYXJhdG9yIDogc2VwYXJhdG9yO1xuICAgICAgICBsZW5ndGggPSAnbGVuZ3RoJyBpbiBvcHRpb25zID8gdG9JbnRlZ2VyKG9wdGlvbnMubGVuZ3RoKSA6IGxlbmd0aDtcbiAgICAgICAgb21pc3Npb24gPSAnb21pc3Npb24nIGluIG9wdGlvbnMgPyB0b1N0cmluZyhvcHRpb25zLm9taXNzaW9uKSA6IG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcblxuICAgICAgdmFyIHN0ckxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICBpZiAocmVIYXNDb21wbGV4U3ltYm9sLnRlc3Qoc3RyaW5nKSkge1xuICAgICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKTtcbiAgICAgICAgc3RyTGVuZ3RoID0gc3RyU3ltYm9scy5sZW5ndGg7XG4gICAgICB9XG4gICAgICBpZiAobGVuZ3RoID49IHN0ckxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIGVuZCA9IGxlbmd0aCAtIHN0cmluZ1NpemUob21pc3Npb24pO1xuICAgICAgaWYgKGVuZCA8IDEpIHtcbiAgICAgICAgcmV0dXJuIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHN0clN5bWJvbHNcbiAgICAgICAgPyBzdHJTeW1ib2xzLnNsaWNlKDAsIGVuZCkuam9pbignJylcbiAgICAgICAgOiBzdHJpbmcuc2xpY2UoMCwgZW5kKTtcblxuICAgICAgaWYgKHNlcGFyYXRvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgKyBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIGlmIChzdHJTeW1ib2xzKSB7XG4gICAgICAgIGVuZCArPSAocmVzdWx0Lmxlbmd0aCAtIGVuZCk7XG4gICAgICB9XG4gICAgICBpZiAoaXNSZWdFeHAoc2VwYXJhdG9yKSkge1xuICAgICAgICBpZiAoc3RyaW5nLnNsaWNlKGVuZCkuc2VhcmNoKHNlcGFyYXRvcikpIHtcbiAgICAgICAgICB2YXIgbWF0Y2gsXG4gICAgICAgICAgICAgIHN1YnN0cmluZyA9IHJlc3VsdDtcblxuICAgICAgICAgIGlmICghc2VwYXJhdG9yLmdsb2JhbCkge1xuICAgICAgICAgICAgc2VwYXJhdG9yID0gUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIHRvU3RyaW5nKHJlRmxhZ3MuZXhlYyhzZXBhcmF0b3IpKSArICdnJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXggPSAwO1xuICAgICAgICAgIHdoaWxlICgobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdWJzdHJpbmcpKSkge1xuICAgICAgICAgICAgdmFyIG5ld0VuZCA9IG1hdGNoLmluZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMCwgbmV3RW5kID09PSB1bmRlZmluZWQgPyBlbmQgOiBuZXdFbmQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZy5pbmRleE9mKHNlcGFyYXRvciwgZW5kKSAhPSBlbmQpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gcmVzdWx0Lmxhc3RJbmRleE9mKHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnNsaWNlKDAsIGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdCArIG9taXNzaW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBpbnZlcnNlIG9mIGBfLmVzY2FwZWA7IHRoaXMgbWV0aG9kIGNvbnZlcnRzIHRoZSBIVE1MIGVudGl0aWVzXG4gICAgICogYCZhbXA7YCwgYCZsdDtgLCBgJmd0O2AsIGAmcXVvdDtgLCBgJiMzOTtgLCBhbmQgYCYjOTY7YCBpbiBgc3RyaW5nYCB0byB0aGVpclxuICAgICAqIGNvcnJlc3BvbmRpbmcgY2hhcmFjdGVycy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBObyBvdGhlciBIVE1MIGVudGl0aWVzIGFyZSB1bmVzY2FwZWQuIFRvIHVuZXNjYXBlIGFkZGl0aW9uYWwgSFRNTFxuICAgICAqIGVudGl0aWVzIHVzZSBhIHRoaXJkLXBhcnR5IGxpYnJhcnkgbGlrZSBbX2hlX10oaHR0cHM6Ly9tdGhzLmJlL2hlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byB1bmVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmVzY2FwZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuZXNjYXBlKCdmcmVkLCBiYXJuZXksICZhbXA7IHBlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiAnZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5lc2NhcGUoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgcmV0dXJuIChzdHJpbmcgJiYgcmVIYXNFc2NhcGVkSHRtbC50ZXN0KHN0cmluZykpXG4gICAgICAgID8gc3RyaW5nLnJlcGxhY2UocmVFc2NhcGVkSHRtbCwgdW5lc2NhcGVIdG1sQ2hhcilcbiAgICAgICAgOiBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AsIGFzIHNwYWNlIHNlcGFyYXRlZCB3b3JkcywgdG8gdXBwZXIgY2FzZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVwcGVyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51cHBlckNhc2UoJy0tZm9vLWJhcicpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqXG4gICAgICogXy51cHBlckNhc2UoJ2Zvb0JhcicpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqXG4gICAgICogXy51cHBlckNhc2UoJ19fZm9vX2Jhcl9fJyk7XG4gICAgICogLy8gPT4gJ0ZPTyBCQVInXG4gICAgICovXG4gICAgdmFyIHVwcGVyQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCArIChpbmRleCA/ICcgJyA6ICcnKSArIHdvcmQudG9VcHBlckNhc2UoKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW3BhdHRlcm5dIFRoZSBwYXR0ZXJuIHRvIG1hdGNoIHdvcmRzLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+IFsnZnJlZCcsICdiYXJuZXknLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycsIC9bXiwgXSsvZyk7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ2Jhcm5leScsICcmJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdvcmRzKHN0cmluZywgcGF0dGVybiwgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwYXR0ZXJuID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBwYXR0ZXJuO1xuXG4gICAgICBpZiAocGF0dGVybiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHBhdHRlcm4gPSByZUhhc0NvbXBsZXhXb3JkLnRlc3Qoc3RyaW5nKSA/IHJlQ29tcGxleFdvcmQgOiByZUJhc2ljV29yZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHJpbmcubWF0Y2gocGF0dGVybikgfHwgW107XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQXR0ZW1wdHMgdG8gaW52b2tlIGBmdW5jYCwgcmV0dXJuaW5nIGVpdGhlciB0aGUgcmVzdWx0IG9yIHRoZSBjYXVnaHQgZXJyb3JcbiAgICAgKiBvYmplY3QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdG8gYGZ1bmNgIHdoZW4gaXQncyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhdHRlbXB0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBgZnVuY2AgcmVzdWx0IG9yIGVycm9yIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gQXZvaWQgdGhyb3dpbmcgZXJyb3JzIGZvciBpbnZhbGlkIHNlbGVjdG9ycy5cbiAgICAgKiB2YXIgZWxlbWVudHMgPSBfLmF0dGVtcHQoZnVuY3Rpb24oc2VsZWN0b3IpIHtcbiAgICAgKiAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcbiAgICAgKiB9LCAnPl8+Jyk7XG4gICAgICpcbiAgICAgKiBpZiAoXy5pc0Vycm9yKGVsZW1lbnRzKSkge1xuICAgICAqICAgZWxlbWVudHMgPSBbXTtcbiAgICAgKiB9XG4gICAgICovXG4gICAgdmFyIGF0dGVtcHQgPSByZXN0KGZ1bmN0aW9uKGZ1bmMsIGFyZ3MpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhcHBseShmdW5jLCB1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gaXNFcnJvcihlKSA/IGUgOiBuZXcgRXJyb3IoZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBCaW5kcyBtZXRob2RzIG9mIGFuIG9iamVjdCB0byB0aGUgb2JqZWN0IGl0c2VsZiwgb3ZlcndyaXRpbmcgdGhlIGV4aXN0aW5nXG4gICAgICogbWV0aG9kLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIGJvdW5kIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGJpbmQgYW5kIGFzc2lnbiB0aGUgYm91bmQgbWV0aG9kcyB0by5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBtZXRob2ROYW1lcyBUaGUgb2JqZWN0IG1ldGhvZCBuYW1lcyB0byBiaW5kLFxuICAgICAqICBzcGVjaWZpZWQgaW5kaXZpZHVhbGx5IG9yIGluIGFycmF5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdmlldyA9IHtcbiAgICAgKiAgICdsYWJlbCc6ICdkb2NzJyxcbiAgICAgKiAgICdvbkNsaWNrJzogZnVuY3Rpb24oKSB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdjbGlja2VkICcgKyB0aGlzLmxhYmVsKTtcbiAgICAgKiAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5iaW5kQWxsKHZpZXcsICdvbkNsaWNrJyk7XG4gICAgICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIHZpZXcub25DbGljayk7XG4gICAgICogLy8gPT4gbG9ncyAnY2xpY2tlZCBkb2NzJyB3aGVuIGNsaWNrZWRcbiAgICAgKi9cbiAgICB2YXIgYmluZEFsbCA9IHJlc3QoZnVuY3Rpb24ob2JqZWN0LCBtZXRob2ROYW1lcykge1xuICAgICAgYXJyYXlFYWNoKGJhc2VGbGF0dGVuKG1ldGhvZE5hbWVzLCAxKSwgZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIG9iamVjdFtrZXldID0gYmluZChvYmplY3Rba2V5XSwgb2JqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGl0ZXJhdGVzIG92ZXIgYHBhaXJzYCBpbnZva2luZyB0aGUgY29ycmVzcG9uZGluZ1xuICAgICAqIGZ1bmN0aW9uIG9mIHRoZSBmaXJzdCBwcmVkaWNhdGUgdG8gcmV0dXJuIHRydXRoeS4gVGhlIHByZWRpY2F0ZS1mdW5jdGlvblxuICAgICAqIHBhaXJzIGFyZSBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIGFuZCBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWRcbiAgICAgKiBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFpcnMgVGhlIHByZWRpY2F0ZS1mdW5jdGlvbiBwYWlycy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLmNvbmQoW1xuICAgICAqICAgW18ubWF0Y2hlcyh7ICdhJzogMSB9KSwgICAgICAgICAgIF8uY29uc3RhbnQoJ21hdGNoZXMgQScpXSxcbiAgICAgKiAgIFtfLmNvbmZvcm1zKHsgJ2InOiBfLmlzTnVtYmVyIH0pLCBfLmNvbnN0YW50KCdtYXRjaGVzIEInKV0sXG4gICAgICogICBbXy5jb25zdGFudCh0cnVlKSwgICAgICAgICAgICAgICAgXy5jb25zdGFudCgnbm8gbWF0Y2gnKV1cbiAgICAgKiBdKTtcbiAgICAgKlxuICAgICAqIGZ1bmMoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAnbWF0Y2hlcyBBJ1xuICAgICAqXG4gICAgICogZnVuYyh7ICdhJzogMCwgJ2InOiAxIH0pO1xuICAgICAqIC8vID0+ICdtYXRjaGVzIEInXG4gICAgICpcbiAgICAgKiBmdW5jKHsgJ2EnOiAnMScsICdiJzogJzInIH0pO1xuICAgICAqIC8vID0+ICdubyBtYXRjaCdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25kKHBhaXJzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gcGFpcnMgPyBwYWlycy5sZW5ndGggOiAwLFxuICAgICAgICAgIHRvSXRlcmF0ZWUgPSBnZXRJdGVyYXRlZSgpO1xuXG4gICAgICBwYWlycyA9ICFsZW5ndGggPyBbXSA6IGFycmF5TWFwKHBhaXJzLCBmdW5jdGlvbihwYWlyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcGFpclsxXSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbdG9JdGVyYXRlZShwYWlyWzBdKSwgcGFpclsxXV07XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgcGFpciA9IHBhaXJzW2luZGV4XTtcbiAgICAgICAgICBpZiAoYXBwbHkocGFpclswXSwgdGhpcywgYXJncykpIHtcbiAgICAgICAgICAgIHJldHVybiBhcHBseShwYWlyWzFdLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgdGhlIHByZWRpY2F0ZSBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHdpdGhcbiAgICAgKiB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eSB2YWx1ZXMgb2YgYSBnaXZlbiBvYmplY3QsIHJldHVybmluZyBgdHJ1ZWAgaWZcbiAgICAgKiBhbGwgcHJlZGljYXRlcyByZXR1cm4gdHJ1dGh5LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLmNvbmZvcm1zKHsgJ2FnZSc6IF8ucGFydGlhbChfLmd0LCBfLCAzOCkgfSkpO1xuICAgICAqIC8vID0+IFt7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25mb3Jtcyhzb3VyY2UpIHtcbiAgICAgIHJldHVybiBiYXNlQ29uZm9ybXMoYmFzZUNsb25lKHNvdXJjZSwgdHJ1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmV0dXJuIGZyb20gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKiB2YXIgZ2V0dGVyID0gXy5jb25zdGFudChvYmplY3QpO1xuICAgICAqXG4gICAgICogZ2V0dGVyKCkgPT09IG9iamVjdDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uc3RhbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSByZXN1bHQgb2YgaW52b2tpbmcgdGhlIGdpdmVuIGZ1bmN0aW9uc1xuICAgICAqIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLCB3aGVyZSBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgKiBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2Z1bmNzXSBGdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3coXy5hZGQsIHNxdWFyZSk7XG4gICAgICogYWRkU3F1YXJlKDEsIDIpO1xuICAgICAqIC8vID0+IDlcbiAgICAgKi9cbiAgICB2YXIgZmxvdyA9IGNyZWF0ZUZsb3coKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmxvd2AgZXhjZXB0IHRoYXQgaXQgY3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXRcbiAgICAgKiBpbnZva2VzIHRoZSBnaXZlbiBmdW5jdGlvbnMgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2Z1bmNzXSBGdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3dSaWdodChzcXVhcmUsIF8uYWRkKTtcbiAgICAgKiBhZGRTcXVhcmUoMSwgMik7XG4gICAgICogLy8gPT4gOVxuICAgICAqL1xuICAgIHZhciBmbG93UmlnaHQgPSBjcmVhdGVGbG93KHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgZ2l2ZW4gdG8gaXQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgQW55IHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGB2YWx1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnIH07XG4gICAgICpcbiAgICAgKiBfLmlkZW50aXR5KG9iamVjdCkgPT09IG9iamVjdDtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaWRlbnRpdHkodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWRcbiAgICAgKiBmdW5jdGlvbi4gSWYgYGZ1bmNgIGlzIGEgcHJvcGVydHkgbmFtZSB0aGUgY3JlYXRlZCBjYWxsYmFjayByZXR1cm5zIHRoZVxuICAgICAqIHByb3BlcnR5IHZhbHVlIGZvciBhIGdpdmVuIGVsZW1lbnQuIElmIGBmdW5jYCBpcyBhbiBvYmplY3QgdGhlIGNyZWF0ZWRcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBjb250YWluIHRoZSBlcXVpdmFsZW50IG9iamVjdFxuICAgICAqIHByb3BlcnRpZXMsIG90aGVyd2lzZSBpdCByZXR1cm5zIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gW2Z1bmM9Xy5pZGVudGl0eV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYSBjYWxsYmFjay5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBDcmVhdGUgY3VzdG9tIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICogXy5pdGVyYXRlZSA9IF8ud3JhcChfLml0ZXJhdGVlLCBmdW5jdGlvbihjYWxsYmFjaywgZnVuYykge1xuICAgICAqICAgdmFyIHAgPSAvXihcXFMrKVxccyooWzw+XSlcXHMqKFxcUyspJC8uZXhlYyhmdW5jKTtcbiAgICAgKiAgIHJldHVybiAhcCA/IGNhbGxiYWNrKGZ1bmMpIDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICogICAgIHJldHVybiAocFsyXSA9PSAnPicgPyBvYmplY3RbcFsxXV0gPiBwWzNdIDogb2JqZWN0W3BbMV1dIDwgcFszXSk7XG4gICAgICogICB9O1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIodXNlcnMsICdhZ2UgPiAzNicpO1xuICAgICAqIC8vID0+IFt7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpdGVyYXRlZShmdW5jKSB7XG4gICAgICByZXR1cm4gYmFzZUl0ZXJhdGVlKHR5cGVvZiBmdW5jID09ICdmdW5jdGlvbicgPyBmdW5jIDogYmFzZUNsb25lKGZ1bmMsIHRydWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBhIHBhcnRpYWwgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYSBnaXZlblxuICAgICAqIG9iamVjdCBhbmQgYHNvdXJjZWAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIG9iamVjdCBoYXMgZXF1aXZhbGVudFxuICAgICAqIHByb3BlcnR5IHZhbHVlcywgZWxzZSBgZmFsc2VgLiBUaGUgY3JlYXRlZCBmdW5jdGlvbiBpcyBlcXVpdmFsZW50IHRvXG4gICAgICogYF8uaXNNYXRjaGAgd2l0aCBhIGBzb3VyY2VgIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHN1cHBvcnRzIGNvbXBhcmluZyB0aGUgc2FtZSB2YWx1ZXMgYXMgYF8uaXNFcXVhbGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLm1hdGNoZXMoeyAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9KSk7XG4gICAgICogLy8gPT4gW3sgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IGZhbHNlIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hlcyhzb3VyY2UpIHtcbiAgICAgIHJldHVybiBiYXNlTWF0Y2hlcyhiYXNlQ2xvbmUoc291cmNlLCB0cnVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgYSBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZVxuICAgICAqIHZhbHVlIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdCB0byBgc3JjVmFsdWVgLCByZXR1cm5pbmcgYHRydWVgIGlmIHRoZVxuICAgICAqIG9iamVjdCB2YWx1ZSBpcyBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2Qgc3VwcG9ydHMgY29tcGFyaW5nIHRoZSBzYW1lIHZhbHVlcyBhcyBgXy5pc0VxdWFsYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcGFyYW0geyp9IHNyY1ZhbHVlIFRoZSB2YWx1ZSB0byBtYXRjaC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maW5kKHVzZXJzLCBfLm1hdGNoZXNQcm9wZXJ0eSgndXNlcicsICdmcmVkJykpO1xuICAgICAqIC8vID0+IHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hdGNoZXNQcm9wZXJ0eShwYXRoLCBzcmNWYWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VNYXRjaGVzUHJvcGVydHkocGF0aCwgYmFzZUNsb25lKHNyY1ZhbHVlLCB0cnVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdC5cbiAgICAgKiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFtcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogeyAnYyc6IF8uY29uc3RhbnQoMikgfSB9IH0sXG4gICAgICogICB7ICdhJzogeyAnYic6IHsgJ2MnOiBfLmNvbnN0YW50KDEpIH0gfSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ubWFwKG9iamVjdHMsIF8ubWV0aG9kKCdhLmIuYycpKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKlxuICAgICAqIF8uaW52b2tlTWFwKF8uc29ydEJ5KG9iamVjdHMsIF8ubWV0aG9kKFsnYScsICdiJywgJ2MnXSkpLCAnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICB2YXIgbWV0aG9kID0gcmVzdChmdW5jdGlvbihwYXRoLCBhcmdzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBiYXNlSW52b2tlKG9iamVjdCwgcGF0aCwgYXJncyk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLm1ldGhvZGA7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXNcbiAgICAgKiB0aGUgbWV0aG9kIGF0IGEgZ2l2ZW4gcGF0aCBvZiBgb2JqZWN0YC4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZVxuICAgICAqIHByb3ZpZGVkIHRvIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gXy50aW1lcygzLCBfLmNvbnN0YW50KSxcbiAgICAgKiAgICAgb2JqZWN0ID0geyAnYSc6IGFycmF5LCAnYic6IGFycmF5LCAnYyc6IGFycmF5IH07XG4gICAgICpcbiAgICAgKiBfLm1hcChbJ2FbMl0nLCAnY1swXSddLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLm1ldGhvZE9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqL1xuICAgIHZhciBtZXRob2RPZiA9IHJlc3QoZnVuY3Rpb24ob2JqZWN0LCBhcmdzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocGF0aCkge1xuICAgICAgICByZXR1cm4gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYWxsIG93biBlbnVtZXJhYmxlIGZ1bmN0aW9uIHByb3BlcnRpZXMgb2YgYSBzb3VyY2Ugb2JqZWN0IHRvIHRoZVxuICAgICAqIGRlc3RpbmF0aW9uIG9iamVjdC4gSWYgYG9iamVjdGAgaXMgYSBmdW5jdGlvbiB0aGVuIG1ldGhvZHMgYXJlIGFkZGVkIHRvXG4gICAgICogaXRzIHByb3RvdHlwZSBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVzZSBgXy5ydW5JbkNvbnRleHRgIHRvIGNyZWF0ZSBhIHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHRvXG4gICAgICogYXZvaWQgY29uZmxpY3RzIGNhdXNlZCBieSBtb2RpZnlpbmcgdGhlIG9yaWdpbmFsLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdH0gW29iamVjdD1sb2Rhc2hdIFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5jaGFpbj10cnVlXSBTcGVjaWZ5IHdoZXRoZXIgdGhlIGZ1bmN0aW9ucyBhZGRlZFxuICAgICAqICBhcmUgY2hhaW5hYmxlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbnxPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHZvd2VscyhzdHJpbmcpIHtcbiAgICAgKiAgIHJldHVybiBfLmZpbHRlcihzdHJpbmcsIGZ1bmN0aW9uKHYpIHtcbiAgICAgKiAgICAgcmV0dXJuIC9bYWVpb3VdL2kudGVzdCh2KTtcbiAgICAgKiAgIH0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWl4aW4oeyAndm93ZWxzJzogdm93ZWxzIH0pO1xuICAgICAqIF8udm93ZWxzKCdmcmVkJyk7XG4gICAgICogLy8gPT4gWydlJ11cbiAgICAgKlxuICAgICAqIF8oJ2ZyZWQnKS52b3dlbHMoKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsnZSddXG4gICAgICpcbiAgICAgKiBfLm1peGluKHsgJ3Zvd2Vscyc6IHZvd2VscyB9LCB7ICdjaGFpbic6IGZhbHNlIH0pO1xuICAgICAqIF8oJ2ZyZWQnKS52b3dlbHMoKTtcbiAgICAgKiAvLyA9PiBbJ2UnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1peGluKG9iamVjdCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgICB2YXIgcHJvcHMgPSBrZXlzKHNvdXJjZSksXG4gICAgICAgICAgbWV0aG9kTmFtZXMgPSBiYXNlRnVuY3Rpb25zKHNvdXJjZSwgcHJvcHMpO1xuXG4gICAgICBpZiAob3B0aW9ucyA9PSBudWxsICYmXG4gICAgICAgICAgIShpc09iamVjdChzb3VyY2UpICYmIChtZXRob2ROYW1lcy5sZW5ndGggfHwgIXByb3BzLmxlbmd0aCkpKSB7XG4gICAgICAgIG9wdGlvbnMgPSBzb3VyY2U7XG4gICAgICAgIHNvdXJjZSA9IG9iamVjdDtcbiAgICAgICAgb2JqZWN0ID0gdGhpcztcbiAgICAgICAgbWV0aG9kTmFtZXMgPSBiYXNlRnVuY3Rpb25zKHNvdXJjZSwga2V5cyhzb3VyY2UpKTtcbiAgICAgIH1cbiAgICAgIHZhciBjaGFpbiA9IChpc09iamVjdChvcHRpb25zKSAmJiAnY2hhaW4nIGluIG9wdGlvbnMpID8gb3B0aW9ucy5jaGFpbiA6IHRydWUsXG4gICAgICAgICAgaXNGdW5jID0gaXNGdW5jdGlvbihvYmplY3QpO1xuXG4gICAgICBhcnJheUVhY2gobWV0aG9kTmFtZXMsIGZ1bmN0aW9uKG1ldGhvZE5hbWUpIHtcbiAgICAgICAgdmFyIGZ1bmMgPSBzb3VyY2VbbWV0aG9kTmFtZV07XG4gICAgICAgIG9iamVjdFttZXRob2ROYW1lXSA9IGZ1bmM7XG4gICAgICAgIGlmIChpc0Z1bmMpIHtcbiAgICAgICAgICBvYmplY3QucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgY2hhaW5BbGwgPSB0aGlzLl9fY2hhaW5fXztcbiAgICAgICAgICAgIGlmIChjaGFpbiB8fCBjaGFpbkFsbCkge1xuICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gb2JqZWN0KHRoaXMuX193cmFwcGVkX18pLFxuICAgICAgICAgICAgICAgICAgYWN0aW9ucyA9IHJlc3VsdC5fX2FjdGlvbnNfXyA9IGNvcHlBcnJheSh0aGlzLl9fYWN0aW9uc19fKTtcblxuICAgICAgICAgICAgICBhY3Rpb25zLnB1c2goeyAnZnVuYyc6IGZ1bmMsICdhcmdzJzogYXJndW1lbnRzLCAndGhpc0FyZyc6IG9iamVjdCB9KTtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9fY2hhaW5fXyA9IGNoYWluQWxsO1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkob2JqZWN0LCBhcnJheVB1c2goW3RoaXMudmFsdWUoKV0sIGFyZ3VtZW50cykpO1xuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGBfYCB2YXJpYWJsZSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG9cbiAgICAgKiB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBsb2Rhc2ggPSBfLm5vQ29uZmxpY3QoKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgaWYgKHJvb3QuXyA9PT0gdGhpcykge1xuICAgICAgICByb290Ll8gPSBvbGREYXNoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBuby1vcGVyYXRpb24gZnVuY3Rpb24gdGhhdCByZXR1cm5zIGB1bmRlZmluZWRgIHJlZ2FyZGxlc3Mgb2YgdGhlXG4gICAgICogYXJndW1lbnRzIGl0IHJlY2VpdmVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIF8ubm9vcChvYmplY3QpID09PSB1bmRlZmluZWQ7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vb3AoKSB7XG4gICAgICAvLyBObyBvcGVyYXRpb24gcGVyZm9ybWVkLlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgaXRzIG50aCBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTBdIFRoZSBpbmRleCBvZiB0aGUgYXJndW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ubnRoQXJnKDEpO1xuICAgICAqXG4gICAgICogZnVuYygnYScsICdiJywgJ2MnKTtcbiAgICAgKiAvLyA9PiAnYidcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBudGhBcmcobikge1xuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGFyZ3VtZW50c1tuXTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgaXRlcmF0ZWVzYCB3aXRoIHRoZSBhcmd1bWVudHMgcHJvdmlkZWRcbiAgICAgKiB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbiBhbmQgcmV0dXJucyB0aGVpciByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gaXRlcmF0ZWVzIFRoZSBpdGVyYXRlZXMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlcihNYXRoLm1heCwgTWF0aC5taW4pO1xuICAgICAqXG4gICAgICogZnVuYygxLCAyLCAzLCA0KTtcbiAgICAgKiAvLyA9PiBbNCwgMV1cbiAgICAgKi9cbiAgICB2YXIgb3ZlciA9IGNyZWF0ZU92ZXIoYXJyYXlNYXApO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYWxsKiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IHByZWRpY2F0ZXMgVGhlIHByZWRpY2F0ZXMgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBmdW5jID0gXy5vdmVyRXZlcnkoQm9vbGVhbiwgaXNGaW5pdGUpO1xuICAgICAqXG4gICAgICogZnVuYygnMScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGZ1bmMobnVsbCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIGZ1bmMoTmFOKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBvdmVyRXZlcnkgPSBjcmVhdGVPdmVyKGFycmF5RXZlcnkpO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmICoqYW55Kiogb2YgdGhlIGBwcmVkaWNhdGVzYCByZXR1cm5cbiAgICAgKiB0cnV0aHkgd2hlbiBpbnZva2VkIHdpdGggdGhlIGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IHByZWRpY2F0ZXMgVGhlIHByZWRpY2F0ZXMgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBmdW5jID0gXy5vdmVyU29tZShCb29sZWFuLCBpc0Zpbml0ZSk7XG4gICAgICpcbiAgICAgKiBmdW5jKCcxJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogZnVuYyhudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBmdW5jKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgb3ZlclNvbWUgPSBjcmVhdGVPdmVyKGFycmF5U29tZSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSB2YWx1ZSBhdCBgcGF0aGAgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiB7ICdjJzogMiB9IH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogeyAnYyc6IDEgfSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5wcm9wZXJ0eSgnYS5iLmMnKSk7XG4gICAgICogLy8gPT4gWzIsIDFdXG4gICAgICpcbiAgICAgKiBfLm1hcChfLnNvcnRCeShvYmplY3RzLCBfLnByb3BlcnR5KFsnYScsICdiJywgJ2MnXSkpLCAnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eShwYXRoKSB7XG4gICAgICByZXR1cm4gaXNLZXkocGF0aCkgPyBiYXNlUHJvcGVydHkocGF0aCkgOiBiYXNlUHJvcGVydHlEZWVwKHBhdGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5wcm9wZXJ0eWA7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnNcbiAgICAgKiB0aGUgdmFsdWUgYXQgYSBnaXZlbiBwYXRoIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFswLCAxLCAyXSxcbiAgICAgKiAgICAgb2JqZWN0ID0geyAnYSc6IGFycmF5LCAnYic6IGFycmF5LCAnYyc6IGFycmF5IH07XG4gICAgICpcbiAgICAgKiBfLm1hcChbJ2FbMl0nLCAnY1swXSddLCBfLnByb3BlcnR5T2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICpcbiAgICAgKiBfLm1hcChbWydhJywgJzInXSwgWydjJywgJzAnXV0sIF8ucHJvcGVydHlPZihvYmplY3QpKTtcbiAgICAgKiAvLyA9PiBbMiwgMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eU9mKG9iamVjdCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIG51bWJlcnMgKHBvc2l0aXZlIGFuZC9vciBuZWdhdGl2ZSkgcHJvZ3Jlc3NpbmcgZnJvbVxuICAgICAqIGBzdGFydGAgdXAgdG8sIGJ1dCBub3QgaW5jbHVkaW5nLCBgZW5kYC4gQSBzdGVwIG9mIGAtMWAgaXMgdXNlZCBpZiBhIG5lZ2F0aXZlXG4gICAgICogYHN0YXJ0YCBpcyBzcGVjaWZpZWQgd2l0aG91dCBhbiBgZW5kYCBvciBgc3RlcGAuIElmIGBlbmRgIGlzIG5vdCBzcGVjaWZpZWRcbiAgICAgKiBpdCdzIHNldCB0byBgc3RhcnRgIHdpdGggYHN0YXJ0YCB0aGVuIHNldCB0byBgMGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSmF2YVNjcmlwdCBmb2xsb3dzIHRoZSBJRUVFLTc1NCBzdGFuZGFyZCBmb3IgcmVzb2x2aW5nXG4gICAgICogZmxvYXRpbmctcG9pbnQgdmFsdWVzIHdoaWNoIGNhbiBwcm9kdWNlIHVuZXhwZWN0ZWQgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGVwPTFdIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIG51bWJlcnMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoNCk7XG4gICAgICogLy8gPT4gWzAsIDEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKC00KTtcbiAgICAgKiAvLyA9PiBbMCwgLTEsIC0yLCAtM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDRdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMCwgNSwgMTAsIDE1XVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwLCAtNCwgLTEpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA0LCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMSwgMV1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICB2YXIgcmFuZ2UgPSBjcmVhdGVSYW5nZSgpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5yYW5nZWAgZXhjZXB0IHRoYXQgaXQgcG9wdWxhdGVzIHZhbHVlcyBpblxuICAgICAqIGRlc2NlbmRpbmcgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RlcD0xXSBUaGUgdmFsdWUgdG8gaW5jcmVtZW50IG9yIGRlY3JlbWVudCBieS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBudW1iZXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoNCk7XG4gICAgICogLy8gPT4gWzMsIDIsIDEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoLTQpO1xuICAgICAqIC8vID0+IFstMywgLTIsIC0xLCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDEsIDUpO1xuICAgICAqIC8vID0+IFs0LCAzLCAyLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTUsIDEwLCA1LCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWy0zLCAtMiwgLTEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMSwgNCwgMCk7XG4gICAgICogLy8gPT4gWzEsIDEsIDFdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICB2YXIgcmFuZ2VSaWdodCA9IGNyZWF0ZVJhbmdlKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyB0aGUgaXRlcmF0ZWUgYG5gIHRpbWVzLCByZXR1cm5pbmcgYW4gYXJyYXkgb2YgdGhlIHJlc3VsdHMgb2ZcbiAgICAgKiBlYWNoIGludm9jYXRpb24uIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAoaW5kZXgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIHRpbWVzIHRvIGludm9rZSBgaXRlcmF0ZWVgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcmVzdWx0cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygzLCBTdHJpbmcpO1xuICAgICAqIC8vID0+IFsnMCcsICcxJywgJzInXVxuICAgICAqXG4gICAgICogIF8udGltZXMoNCwgXy5jb25zdGFudCh0cnVlKSk7XG4gICAgICogLy8gPT4gW3RydWUsIHRydWUsIHRydWUsIHRydWVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGltZXMobiwgaXRlcmF0ZWUpIHtcbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICBpZiAobiA8IDEgfHwgbiA+IE1BWF9TQUZFX0lOVEVHRVIpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gTUFYX0FSUkFZX0xFTkdUSCxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNaW4obiwgTUFYX0FSUkFZX0xFTkdUSCk7XG5cbiAgICAgIGl0ZXJhdGVlID0gYmFzZUNhc3RGdW5jdGlvbihpdGVyYXRlZSk7XG4gICAgICBuIC09IE1BWF9BUlJBWV9MRU5HVEg7XG5cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlVGltZXMobGVuZ3RoLCBpdGVyYXRlZSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgaXRlcmF0ZWUoaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvUGF0aCgnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIF8udG9QYXRoKCdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IFsnYScsICcwJywgJ2InLCAnYyddXG4gICAgICpcbiAgICAgKiB2YXIgcGF0aCA9IFsnYScsICdiJywgJ2MnXSxcbiAgICAgKiAgICAgbmV3UGF0aCA9IF8udG9QYXRoKHBhdGgpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2cobmV3UGF0aCk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhwYXRoID09PSBuZXdQYXRoKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvUGF0aCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzQXJyYXkodmFsdWUpID8gYXJyYXlNYXAodmFsdWUsIFN0cmluZykgOiBzdHJpbmdUb1BhdGgodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBJRC4gSWYgYHByZWZpeGAgaXMgZ2l2ZW4gdGhlIElEIGlzIGFwcGVuZGVkIHRvIGl0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD0nJ10gVGhlIHZhbHVlIHRvIHByZWZpeCB0aGUgSUQgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmlxdWUgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoJ2NvbnRhY3RfJyk7XG4gICAgICogLy8gPT4gJ2NvbnRhY3RfMTA0J1xuICAgICAqXG4gICAgICogXy51bmlxdWVJZCgpO1xuICAgICAqIC8vID0+ICcxMDUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcXVlSWQocHJlZml4KSB7XG4gICAgICB2YXIgaWQgPSArK2lkQ291bnRlcjtcbiAgICAgIHJldHVybiB0b1N0cmluZyhwcmVmaXgpICsgaWQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyB0d28gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGF1Z2VuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGFuIGFkZGl0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYW4gYWRkaXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdG90YWwuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYWRkKDYsIDQpO1xuICAgICAqIC8vID0+IDEwXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWRkKGF1Z2VuZCwgYWRkZW5kKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgaWYgKGF1Z2VuZCA9PT0gdW5kZWZpbmVkICYmIGFkZGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgICAgaWYgKGF1Z2VuZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc3VsdCA9IGF1Z2VuZDtcbiAgICAgIH1cbiAgICAgIGlmIChhZGRlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGFkZGVuZCA6IChyZXN1bHQgKyBhZGRlbmQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHVwIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gcm91bmQgdXAuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwcmVjaXNpb249MF0gVGhlIHByZWNpc2lvbiB0byByb3VuZCB1cCB0by5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByb3VuZGVkIHVwIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jZWlsKDQuMDA2KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICpcbiAgICAgKiBfLmNlaWwoNi4wMDQsIDIpO1xuICAgICAqIC8vID0+IDYuMDFcbiAgICAgKlxuICAgICAqIF8uY2VpbCg2MDQwLCAtMik7XG4gICAgICogLy8gPT4gNjEwMFxuICAgICAqL1xuICAgIHZhciBjZWlsID0gY3JlYXRlUm91bmQoJ2NlaWwnKTtcblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIGBudW1iZXJgIHJvdW5kZWQgZG93biB0byBgcHJlY2lzaW9uYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kIGRvd24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwcmVjaXNpb249MF0gVGhlIHByZWNpc2lvbiB0byByb3VuZCBkb3duIHRvLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHJvdW5kZWQgZG93biBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmxvb3IoNC4wMDYpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8uZmxvb3IoMC4wNDYsIDIpO1xuICAgICAqIC8vID0+IDAuMDRcbiAgICAgKlxuICAgICAqIF8uZmxvb3IoNDA2MCwgLTIpO1xuICAgICAqIC8vID0+IDQwMDBcbiAgICAgKi9cbiAgICB2YXIgZmxvb3IgPSBjcmVhdGVSb3VuZCgnZmxvb3InKTtcblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBtYXhpbXVtIHZhbHVlIG9mIGBhcnJheWAuIElmIGBhcnJheWAgaXMgZW1wdHkgb3IgZmFsc2V5XG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXgoW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1heChhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgZ3QpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ubWF4YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgaW4gYGFycmF5YCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5IHdoaWNoXG4gICAgICogdGhlIHZhbHVlIGlzIHJhbmtlZC4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ24nOiAxIH0sIHsgJ24nOiAyIH1dO1xuICAgICAqXG4gICAgICogXy5tYXhCeShvYmplY3RzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLm47IH0pO1xuICAgICAqIC8vID0+IHsgJ24nOiAyIH1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ubWF4Qnkob2JqZWN0cywgJ24nKTtcbiAgICAgKiAvLyA9PiB7ICduJzogMiB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF4QnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlRXh0cmVtdW0oYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlKSwgZ3QpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBtZWFuIG9mIHRoZSB2YWx1ZXMgaW4gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1lYW4oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVhbihhcnJheSkge1xuICAgICAgcmV0dXJuIHN1bShhcnJheSkgLyAoYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyB0aGUgbWluaW11bSB2YWx1ZSBvZiBgYXJyYXlgLiBJZiBgYXJyYXlgIGlzIGVtcHR5IG9yIGZhbHNleVxuICAgICAqIGB1bmRlZmluZWRgIGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtaW5pbXVtIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1pbihbNCwgMiwgOCwgNl0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIF8ubWluKFtdKTtcbiAgICAgKiAvLyA9PiB1bmRlZmluZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaW4oYXJyYXkpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgaWRlbnRpdHksIGx0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1pbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtaW5pbXVtIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICduJzogMSB9LCB7ICduJzogMiB9XTtcbiAgICAgKlxuICAgICAqIF8ubWluQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiB7ICduJzogMSB9XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1pbkJ5KG9iamVjdHMsICduJyk7XG4gICAgICogLy8gPT4geyAnbic6IDEgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1pbkJ5KGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSksIGx0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gcm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwcmVjaXNpb249MF0gVGhlIHByZWNpc2lvbiB0byByb3VuZCB0by5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSByb3VuZGVkIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yb3VuZCg0LjAwNik7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5yb3VuZCg0LjAwNiwgMik7XG4gICAgICogLy8gPT4gNC4wMVxuICAgICAqXG4gICAgICogXy5yb3VuZCg0MDYwLCAtMik7XG4gICAgICogLy8gPT4gNDEwMFxuICAgICAqL1xuICAgIHZhciByb3VuZCA9IGNyZWF0ZVJvdW5kKCdyb3VuZCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidHJhY3QgdHdvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW51ZW5kIFRoZSBmaXJzdCBudW1iZXIgaW4gYSBzdWJ0cmFjdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3VidHJhaGVuZCBUaGUgc2Vjb25kIG51bWJlciBpbiBhIHN1YnRyYWN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGRpZmZlcmVuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc3VidHJhY3QoNiwgNCk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN1YnRyYWN0KG1pbnVlbmQsIHN1YnRyYWhlbmQpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBpZiAobWludWVuZCA9PT0gdW5kZWZpbmVkICYmIHN1YnRyYWhlbmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICAgIGlmIChtaW51ZW5kICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzdWx0ID0gbWludWVuZDtcbiAgICAgIH1cbiAgICAgIGlmIChzdWJ0cmFoZW5kICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSB1bmRlZmluZWQgPyBzdWJ0cmFoZW5kIDogKHJlc3VsdCAtIHN1YnRyYWhlbmQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyB0aGUgc3VtIG9mIHRoZSB2YWx1ZXMgaW4gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdW0uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc3VtKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMjBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdW0oYXJyYXkpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VTdW0oYXJyYXksIGlkZW50aXR5KVxuICAgICAgICA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zdW1gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgZm9yIGVhY2ggZWxlbWVudCBpbiBgYXJyYXlgIHRvIGdlbmVyYXRlIHRoZSB2YWx1ZSB0byBiZSBzdW1tZWQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICduJzogNCB9LCB7ICduJzogMiB9LCB7ICduJzogOCB9LCB7ICduJzogNiB9XTtcbiAgICAgKlxuICAgICAqIF8uc3VtQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zdW1CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDIwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3VtQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU3VtKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSkpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBFbnN1cmUgd3JhcHBlcnMgYXJlIGluc3RhbmNlcyBvZiBgYmFzZUxvZGFzaGAuXG4gICAgbG9kYXNoLnByb3RvdHlwZSA9IGJhc2VMb2Rhc2gucHJvdG90eXBlO1xuXG4gICAgTG9kYXNoV3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMb2Rhc2hXcmFwcGVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IExvZGFzaFdyYXBwZXI7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBMYXp5V3JhcHBlcjtcblxuICAgIC8vIEF2b2lkIGluaGVyaXRpbmcgZnJvbSBgT2JqZWN0LnByb3RvdHlwZWAgd2hlbiBwb3NzaWJsZS5cbiAgICBIYXNoLnByb3RvdHlwZSA9IG5hdGl2ZUNyZWF0ZSA/IG5hdGl2ZUNyZWF0ZShudWxsKSA6IG9iamVjdFByb3RvO1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0byB0aGUgYE1hcENhY2hlYC5cbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuY2xlYXIgPSBtYXBDbGVhcjtcbiAgICBNYXBDYWNoZS5wcm90b3R5cGVbJ2RlbGV0ZSddID0gbWFwRGVsZXRlO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZS5nZXQgPSBtYXBHZXQ7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlLmhhcyA9IG1hcEhhcztcbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuc2V0ID0gbWFwU2V0O1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0byB0aGUgYFNldENhY2hlYC5cbiAgICBTZXRDYWNoZS5wcm90b3R5cGUucHVzaCA9IGNhY2hlUHVzaDtcblxuICAgIC8vIEFkZCBmdW5jdGlvbnMgdG8gdGhlIGBTdGFja2AgY2FjaGUuXG4gICAgU3RhY2sucHJvdG90eXBlLmNsZWFyID0gc3RhY2tDbGVhcjtcbiAgICBTdGFjay5wcm90b3R5cGVbJ2RlbGV0ZSddID0gc3RhY2tEZWxldGU7XG4gICAgU3RhY2sucHJvdG90eXBlLmdldCA9IHN0YWNrR2V0O1xuICAgIFN0YWNrLnByb3RvdHlwZS5oYXMgPSBzdGFja0hhcztcbiAgICBTdGFjay5wcm90b3R5cGUuc2V0ID0gc3RhY2tTZXQ7XG5cbiAgICAvLyBBc3NpZ24gY2FjaGUgdG8gYF8ubWVtb2l6ZWAuXG4gICAgbWVtb2l6ZS5DYWNoZSA9IE1hcENhY2hlO1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0aGF0IHJldHVybiB3cmFwcGVkIHZhbHVlcyB3aGVuIGNoYWluaW5nLlxuICAgIGxvZGFzaC5hZnRlciA9IGFmdGVyO1xuICAgIGxvZGFzaC5hcnkgPSBhcnk7XG4gICAgbG9kYXNoLmFzc2lnbiA9IGFzc2lnbjtcbiAgICBsb2Rhc2guYXNzaWduSW4gPSBhc3NpZ25JbjtcbiAgICBsb2Rhc2guYXNzaWduSW5XaXRoID0gYXNzaWduSW5XaXRoO1xuICAgIGxvZGFzaC5hc3NpZ25XaXRoID0gYXNzaWduV2l0aDtcbiAgICBsb2Rhc2guYXQgPSBhdDtcbiAgICBsb2Rhc2guYmVmb3JlID0gYmVmb3JlO1xuICAgIGxvZGFzaC5iaW5kID0gYmluZDtcbiAgICBsb2Rhc2guYmluZEFsbCA9IGJpbmRBbGw7XG4gICAgbG9kYXNoLmJpbmRLZXkgPSBiaW5kS2V5O1xuICAgIGxvZGFzaC5jYXN0QXJyYXkgPSBjYXN0QXJyYXk7XG4gICAgbG9kYXNoLmNoYWluID0gY2hhaW47XG4gICAgbG9kYXNoLmNodW5rID0gY2h1bms7XG4gICAgbG9kYXNoLmNvbXBhY3QgPSBjb21wYWN0O1xuICAgIGxvZGFzaC5jb25jYXQgPSBjb25jYXQ7XG4gICAgbG9kYXNoLmNvbmQgPSBjb25kO1xuICAgIGxvZGFzaC5jb25mb3JtcyA9IGNvbmZvcm1zO1xuICAgIGxvZGFzaC5jb25zdGFudCA9IGNvbnN0YW50O1xuICAgIGxvZGFzaC5jb3VudEJ5ID0gY291bnRCeTtcbiAgICBsb2Rhc2guY3JlYXRlID0gY3JlYXRlO1xuICAgIGxvZGFzaC5jdXJyeSA9IGN1cnJ5O1xuICAgIGxvZGFzaC5jdXJyeVJpZ2h0ID0gY3VycnlSaWdodDtcbiAgICBsb2Rhc2guZGVib3VuY2UgPSBkZWJvdW5jZTtcbiAgICBsb2Rhc2guZGVmYXVsdHMgPSBkZWZhdWx0cztcbiAgICBsb2Rhc2guZGVmYXVsdHNEZWVwID0gZGVmYXVsdHNEZWVwO1xuICAgIGxvZGFzaC5kZWZlciA9IGRlZmVyO1xuICAgIGxvZGFzaC5kZWxheSA9IGRlbGF5O1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlID0gZGlmZmVyZW5jZTtcbiAgICBsb2Rhc2guZGlmZmVyZW5jZUJ5ID0gZGlmZmVyZW5jZUJ5O1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlV2l0aCA9IGRpZmZlcmVuY2VXaXRoO1xuICAgIGxvZGFzaC5kcm9wID0gZHJvcDtcbiAgICBsb2Rhc2guZHJvcFJpZ2h0ID0gZHJvcFJpZ2h0O1xuICAgIGxvZGFzaC5kcm9wUmlnaHRXaGlsZSA9IGRyb3BSaWdodFdoaWxlO1xuICAgIGxvZGFzaC5kcm9wV2hpbGUgPSBkcm9wV2hpbGU7XG4gICAgbG9kYXNoLmZpbGwgPSBmaWxsO1xuICAgIGxvZGFzaC5maWx0ZXIgPSBmaWx0ZXI7XG4gICAgbG9kYXNoLmZsYXRNYXAgPSBmbGF0TWFwO1xuICAgIGxvZGFzaC5mbGF0dGVuID0gZmxhdHRlbjtcbiAgICBsb2Rhc2guZmxhdHRlbkRlZXAgPSBmbGF0dGVuRGVlcDtcbiAgICBsb2Rhc2guZmxhdHRlbkRlcHRoID0gZmxhdHRlbkRlcHRoO1xuICAgIGxvZGFzaC5mbGlwID0gZmxpcDtcbiAgICBsb2Rhc2guZmxvdyA9IGZsb3c7XG4gICAgbG9kYXNoLmZsb3dSaWdodCA9IGZsb3dSaWdodDtcbiAgICBsb2Rhc2guZnJvbVBhaXJzID0gZnJvbVBhaXJzO1xuICAgIGxvZGFzaC5mdW5jdGlvbnMgPSBmdW5jdGlvbnM7XG4gICAgbG9kYXNoLmZ1bmN0aW9uc0luID0gZnVuY3Rpb25zSW47XG4gICAgbG9kYXNoLmdyb3VwQnkgPSBncm91cEJ5O1xuICAgIGxvZGFzaC5pbml0aWFsID0gaW5pdGlhbDtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uID0gaW50ZXJzZWN0aW9uO1xuICAgIGxvZGFzaC5pbnRlcnNlY3Rpb25CeSA9IGludGVyc2VjdGlvbkJ5O1xuICAgIGxvZGFzaC5pbnRlcnNlY3Rpb25XaXRoID0gaW50ZXJzZWN0aW9uV2l0aDtcbiAgICBsb2Rhc2guaW52ZXJ0ID0gaW52ZXJ0O1xuICAgIGxvZGFzaC5pbnZlcnRCeSA9IGludmVydEJ5O1xuICAgIGxvZGFzaC5pbnZva2VNYXAgPSBpbnZva2VNYXA7XG4gICAgbG9kYXNoLml0ZXJhdGVlID0gaXRlcmF0ZWU7XG4gICAgbG9kYXNoLmtleUJ5ID0ga2V5Qnk7XG4gICAgbG9kYXNoLmtleXMgPSBrZXlzO1xuICAgIGxvZGFzaC5rZXlzSW4gPSBrZXlzSW47XG4gICAgbG9kYXNoLm1hcCA9IG1hcDtcbiAgICBsb2Rhc2gubWFwS2V5cyA9IG1hcEtleXM7XG4gICAgbG9kYXNoLm1hcFZhbHVlcyA9IG1hcFZhbHVlcztcbiAgICBsb2Rhc2gubWF0Y2hlcyA9IG1hdGNoZXM7XG4gICAgbG9kYXNoLm1hdGNoZXNQcm9wZXJ0eSA9IG1hdGNoZXNQcm9wZXJ0eTtcbiAgICBsb2Rhc2gubWVtb2l6ZSA9IG1lbW9pemU7XG4gICAgbG9kYXNoLm1lcmdlID0gbWVyZ2U7XG4gICAgbG9kYXNoLm1lcmdlV2l0aCA9IG1lcmdlV2l0aDtcbiAgICBsb2Rhc2gubWV0aG9kID0gbWV0aG9kO1xuICAgIGxvZGFzaC5tZXRob2RPZiA9IG1ldGhvZE9mO1xuICAgIGxvZGFzaC5taXhpbiA9IG1peGluO1xuICAgIGxvZGFzaC5uZWdhdGUgPSBuZWdhdGU7XG4gICAgbG9kYXNoLm50aEFyZyA9IG50aEFyZztcbiAgICBsb2Rhc2gub21pdCA9IG9taXQ7XG4gICAgbG9kYXNoLm9taXRCeSA9IG9taXRCeTtcbiAgICBsb2Rhc2gub25jZSA9IG9uY2U7XG4gICAgbG9kYXNoLm9yZGVyQnkgPSBvcmRlckJ5O1xuICAgIGxvZGFzaC5vdmVyID0gb3ZlcjtcbiAgICBsb2Rhc2gub3ZlckFyZ3MgPSBvdmVyQXJncztcbiAgICBsb2Rhc2gub3ZlckV2ZXJ5ID0gb3ZlckV2ZXJ5O1xuICAgIGxvZGFzaC5vdmVyU29tZSA9IG92ZXJTb21lO1xuICAgIGxvZGFzaC5wYXJ0aWFsID0gcGFydGlhbDtcbiAgICBsb2Rhc2gucGFydGlhbFJpZ2h0ID0gcGFydGlhbFJpZ2h0O1xuICAgIGxvZGFzaC5wYXJ0aXRpb24gPSBwYXJ0aXRpb247XG4gICAgbG9kYXNoLnBpY2sgPSBwaWNrO1xuICAgIGxvZGFzaC5waWNrQnkgPSBwaWNrQnk7XG4gICAgbG9kYXNoLnByb3BlcnR5ID0gcHJvcGVydHk7XG4gICAgbG9kYXNoLnByb3BlcnR5T2YgPSBwcm9wZXJ0eU9mO1xuICAgIGxvZGFzaC5wdWxsID0gcHVsbDtcbiAgICBsb2Rhc2gucHVsbEFsbCA9IHB1bGxBbGw7XG4gICAgbG9kYXNoLnB1bGxBbGxCeSA9IHB1bGxBbGxCeTtcbiAgICBsb2Rhc2gucHVsbEF0ID0gcHVsbEF0O1xuICAgIGxvZGFzaC5yYW5nZSA9IHJhbmdlO1xuICAgIGxvZGFzaC5yYW5nZVJpZ2h0ID0gcmFuZ2VSaWdodDtcbiAgICBsb2Rhc2gucmVhcmcgPSByZWFyZztcbiAgICBsb2Rhc2gucmVqZWN0ID0gcmVqZWN0O1xuICAgIGxvZGFzaC5yZW1vdmUgPSByZW1vdmU7XG4gICAgbG9kYXNoLnJlc3QgPSByZXN0O1xuICAgIGxvZGFzaC5yZXZlcnNlID0gcmV2ZXJzZTtcbiAgICBsb2Rhc2guc2FtcGxlU2l6ZSA9IHNhbXBsZVNpemU7XG4gICAgbG9kYXNoLnNldCA9IHNldDtcbiAgICBsb2Rhc2guc2V0V2l0aCA9IHNldFdpdGg7XG4gICAgbG9kYXNoLnNodWZmbGUgPSBzaHVmZmxlO1xuICAgIGxvZGFzaC5zbGljZSA9IHNsaWNlO1xuICAgIGxvZGFzaC5zb3J0QnkgPSBzb3J0Qnk7XG4gICAgbG9kYXNoLnNvcnRlZFVuaXEgPSBzb3J0ZWRVbmlxO1xuICAgIGxvZGFzaC5zb3J0ZWRVbmlxQnkgPSBzb3J0ZWRVbmlxQnk7XG4gICAgbG9kYXNoLnNwbGl0ID0gc3BsaXQ7XG4gICAgbG9kYXNoLnNwcmVhZCA9IHNwcmVhZDtcbiAgICBsb2Rhc2gudGFpbCA9IHRhaWw7XG4gICAgbG9kYXNoLnRha2UgPSB0YWtlO1xuICAgIGxvZGFzaC50YWtlUmlnaHQgPSB0YWtlUmlnaHQ7XG4gICAgbG9kYXNoLnRha2VSaWdodFdoaWxlID0gdGFrZVJpZ2h0V2hpbGU7XG4gICAgbG9kYXNoLnRha2VXaGlsZSA9IHRha2VXaGlsZTtcbiAgICBsb2Rhc2gudGFwID0gdGFwO1xuICAgIGxvZGFzaC50aHJvdHRsZSA9IHRocm90dGxlO1xuICAgIGxvZGFzaC50aHJ1ID0gdGhydTtcbiAgICBsb2Rhc2gudG9BcnJheSA9IHRvQXJyYXk7XG4gICAgbG9kYXNoLnRvUGFpcnMgPSB0b1BhaXJzO1xuICAgIGxvZGFzaC50b1BhaXJzSW4gPSB0b1BhaXJzSW47XG4gICAgbG9kYXNoLnRvUGF0aCA9IHRvUGF0aDtcbiAgICBsb2Rhc2gudG9QbGFpbk9iamVjdCA9IHRvUGxhaW5PYmplY3Q7XG4gICAgbG9kYXNoLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbiAgICBsb2Rhc2gudW5hcnkgPSB1bmFyeTtcbiAgICBsb2Rhc2gudW5pb24gPSB1bmlvbjtcbiAgICBsb2Rhc2gudW5pb25CeSA9IHVuaW9uQnk7XG4gICAgbG9kYXNoLnVuaW9uV2l0aCA9IHVuaW9uV2l0aDtcbiAgICBsb2Rhc2gudW5pcSA9IHVuaXE7XG4gICAgbG9kYXNoLnVuaXFCeSA9IHVuaXFCeTtcbiAgICBsb2Rhc2gudW5pcVdpdGggPSB1bmlxV2l0aDtcbiAgICBsb2Rhc2gudW5zZXQgPSB1bnNldDtcbiAgICBsb2Rhc2gudW56aXAgPSB1bnppcDtcbiAgICBsb2Rhc2gudW56aXBXaXRoID0gdW56aXBXaXRoO1xuICAgIGxvZGFzaC52YWx1ZXMgPSB2YWx1ZXM7XG4gICAgbG9kYXNoLnZhbHVlc0luID0gdmFsdWVzSW47XG4gICAgbG9kYXNoLndpdGhvdXQgPSB3aXRob3V0O1xuICAgIGxvZGFzaC53b3JkcyA9IHdvcmRzO1xuICAgIGxvZGFzaC53cmFwID0gd3JhcDtcbiAgICBsb2Rhc2gueG9yID0geG9yO1xuICAgIGxvZGFzaC54b3JCeSA9IHhvckJ5O1xuICAgIGxvZGFzaC54b3JXaXRoID0geG9yV2l0aDtcbiAgICBsb2Rhc2guemlwID0gemlwO1xuICAgIGxvZGFzaC56aXBPYmplY3QgPSB6aXBPYmplY3Q7XG4gICAgbG9kYXNoLnppcE9iamVjdERlZXAgPSB6aXBPYmplY3REZWVwO1xuICAgIGxvZGFzaC56aXBXaXRoID0gemlwV2l0aDtcblxuICAgIC8vIEFkZCBhbGlhc2VzLlxuICAgIGxvZGFzaC5leHRlbmQgPSBhc3NpZ25JbjtcbiAgICBsb2Rhc2guZXh0ZW5kV2l0aCA9IGFzc2lnbkluV2l0aDtcblxuICAgIC8vIEFkZCBmdW5jdGlvbnMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIG1peGluKGxvZGFzaCwgbG9kYXNoKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIEFkZCBmdW5jdGlvbnMgdGhhdCByZXR1cm4gdW53cmFwcGVkIHZhbHVlcyB3aGVuIGNoYWluaW5nLlxuICAgIGxvZGFzaC5hZGQgPSBhZGQ7XG4gICAgbG9kYXNoLmF0dGVtcHQgPSBhdHRlbXB0O1xuICAgIGxvZGFzaC5jYW1lbENhc2UgPSBjYW1lbENhc2U7XG4gICAgbG9kYXNoLmNhcGl0YWxpemUgPSBjYXBpdGFsaXplO1xuICAgIGxvZGFzaC5jZWlsID0gY2VpbDtcbiAgICBsb2Rhc2guY2xhbXAgPSBjbGFtcDtcbiAgICBsb2Rhc2guY2xvbmUgPSBjbG9uZTtcbiAgICBsb2Rhc2guY2xvbmVEZWVwID0gY2xvbmVEZWVwO1xuICAgIGxvZGFzaC5jbG9uZURlZXBXaXRoID0gY2xvbmVEZWVwV2l0aDtcbiAgICBsb2Rhc2guY2xvbmVXaXRoID0gY2xvbmVXaXRoO1xuICAgIGxvZGFzaC5kZWJ1cnIgPSBkZWJ1cnI7XG4gICAgbG9kYXNoLmVuZHNXaXRoID0gZW5kc1dpdGg7XG4gICAgbG9kYXNoLmVxID0gZXE7XG4gICAgbG9kYXNoLmVzY2FwZSA9IGVzY2FwZTtcbiAgICBsb2Rhc2guZXNjYXBlUmVnRXhwID0gZXNjYXBlUmVnRXhwO1xuICAgIGxvZGFzaC5ldmVyeSA9IGV2ZXJ5O1xuICAgIGxvZGFzaC5maW5kID0gZmluZDtcbiAgICBsb2Rhc2guZmluZEluZGV4ID0gZmluZEluZGV4O1xuICAgIGxvZGFzaC5maW5kS2V5ID0gZmluZEtleTtcbiAgICBsb2Rhc2guZmluZExhc3QgPSBmaW5kTGFzdDtcbiAgICBsb2Rhc2guZmluZExhc3RJbmRleCA9IGZpbmRMYXN0SW5kZXg7XG4gICAgbG9kYXNoLmZpbmRMYXN0S2V5ID0gZmluZExhc3RLZXk7XG4gICAgbG9kYXNoLmZsb29yID0gZmxvb3I7XG4gICAgbG9kYXNoLmZvckVhY2ggPSBmb3JFYWNoO1xuICAgIGxvZGFzaC5mb3JFYWNoUmlnaHQgPSBmb3JFYWNoUmlnaHQ7XG4gICAgbG9kYXNoLmZvckluID0gZm9ySW47XG4gICAgbG9kYXNoLmZvckluUmlnaHQgPSBmb3JJblJpZ2h0O1xuICAgIGxvZGFzaC5mb3JPd24gPSBmb3JPd247XG4gICAgbG9kYXNoLmZvck93blJpZ2h0ID0gZm9yT3duUmlnaHQ7XG4gICAgbG9kYXNoLmdldCA9IGdldDtcbiAgICBsb2Rhc2guZ3QgPSBndDtcbiAgICBsb2Rhc2guZ3RlID0gZ3RlO1xuICAgIGxvZGFzaC5oYXMgPSBoYXM7XG4gICAgbG9kYXNoLmhhc0luID0gaGFzSW47XG4gICAgbG9kYXNoLmhlYWQgPSBoZWFkO1xuICAgIGxvZGFzaC5pZGVudGl0eSA9IGlkZW50aXR5O1xuICAgIGxvZGFzaC5pbmNsdWRlcyA9IGluY2x1ZGVzO1xuICAgIGxvZGFzaC5pbmRleE9mID0gaW5kZXhPZjtcbiAgICBsb2Rhc2guaW5SYW5nZSA9IGluUmFuZ2U7XG4gICAgbG9kYXNoLmludm9rZSA9IGludm9rZTtcbiAgICBsb2Rhc2guaXNBcmd1bWVudHMgPSBpc0FyZ3VtZW50cztcbiAgICBsb2Rhc2guaXNBcnJheSA9IGlzQXJyYXk7XG4gICAgbG9kYXNoLmlzQXJyYXlCdWZmZXIgPSBpc0FycmF5QnVmZmVyO1xuICAgIGxvZGFzaC5pc0FycmF5TGlrZSA9IGlzQXJyYXlMaWtlO1xuICAgIGxvZGFzaC5pc0FycmF5TGlrZU9iamVjdCA9IGlzQXJyYXlMaWtlT2JqZWN0O1xuICAgIGxvZGFzaC5pc0Jvb2xlYW4gPSBpc0Jvb2xlYW47XG4gICAgbG9kYXNoLmlzQnVmZmVyID0gaXNCdWZmZXI7XG4gICAgbG9kYXNoLmlzRGF0ZSA9IGlzRGF0ZTtcbiAgICBsb2Rhc2guaXNFbGVtZW50ID0gaXNFbGVtZW50O1xuICAgIGxvZGFzaC5pc0VtcHR5ID0gaXNFbXB0eTtcbiAgICBsb2Rhc2guaXNFcXVhbCA9IGlzRXF1YWw7XG4gICAgbG9kYXNoLmlzRXF1YWxXaXRoID0gaXNFcXVhbFdpdGg7XG4gICAgbG9kYXNoLmlzRXJyb3IgPSBpc0Vycm9yO1xuICAgIGxvZGFzaC5pc0Zpbml0ZSA9IGlzRmluaXRlO1xuICAgIGxvZGFzaC5pc0Z1bmN0aW9uID0gaXNGdW5jdGlvbjtcbiAgICBsb2Rhc2guaXNJbnRlZ2VyID0gaXNJbnRlZ2VyO1xuICAgIGxvZGFzaC5pc0xlbmd0aCA9IGlzTGVuZ3RoO1xuICAgIGxvZGFzaC5pc01hcCA9IGlzTWFwO1xuICAgIGxvZGFzaC5pc01hdGNoID0gaXNNYXRjaDtcbiAgICBsb2Rhc2guaXNNYXRjaFdpdGggPSBpc01hdGNoV2l0aDtcbiAgICBsb2Rhc2guaXNOYU4gPSBpc05hTjtcbiAgICBsb2Rhc2guaXNOYXRpdmUgPSBpc05hdGl2ZTtcbiAgICBsb2Rhc2guaXNOaWwgPSBpc05pbDtcbiAgICBsb2Rhc2guaXNOdWxsID0gaXNOdWxsO1xuICAgIGxvZGFzaC5pc051bWJlciA9IGlzTnVtYmVyO1xuICAgIGxvZGFzaC5pc09iamVjdCA9IGlzT2JqZWN0O1xuICAgIGxvZGFzaC5pc09iamVjdExpa2UgPSBpc09iamVjdExpa2U7XG4gICAgbG9kYXNoLmlzUGxhaW5PYmplY3QgPSBpc1BsYWluT2JqZWN0O1xuICAgIGxvZGFzaC5pc1JlZ0V4cCA9IGlzUmVnRXhwO1xuICAgIGxvZGFzaC5pc1NhZmVJbnRlZ2VyID0gaXNTYWZlSW50ZWdlcjtcbiAgICBsb2Rhc2guaXNTZXQgPSBpc1NldDtcbiAgICBsb2Rhc2guaXNTdHJpbmcgPSBpc1N0cmluZztcbiAgICBsb2Rhc2guaXNTeW1ib2wgPSBpc1N5bWJvbDtcbiAgICBsb2Rhc2guaXNUeXBlZEFycmF5ID0gaXNUeXBlZEFycmF5O1xuICAgIGxvZGFzaC5pc1VuZGVmaW5lZCA9IGlzVW5kZWZpbmVkO1xuICAgIGxvZGFzaC5pc1dlYWtNYXAgPSBpc1dlYWtNYXA7XG4gICAgbG9kYXNoLmlzV2Vha1NldCA9IGlzV2Vha1NldDtcbiAgICBsb2Rhc2guam9pbiA9IGpvaW47XG4gICAgbG9kYXNoLmtlYmFiQ2FzZSA9IGtlYmFiQ2FzZTtcbiAgICBsb2Rhc2gubGFzdCA9IGxhc3Q7XG4gICAgbG9kYXNoLmxhc3RJbmRleE9mID0gbGFzdEluZGV4T2Y7XG4gICAgbG9kYXNoLmxvd2VyQ2FzZSA9IGxvd2VyQ2FzZTtcbiAgICBsb2Rhc2gubG93ZXJGaXJzdCA9IGxvd2VyRmlyc3Q7XG4gICAgbG9kYXNoLmx0ID0gbHQ7XG4gICAgbG9kYXNoLmx0ZSA9IGx0ZTtcbiAgICBsb2Rhc2gubWF4ID0gbWF4O1xuICAgIGxvZGFzaC5tYXhCeSA9IG1heEJ5O1xuICAgIGxvZGFzaC5tZWFuID0gbWVhbjtcbiAgICBsb2Rhc2gubWluID0gbWluO1xuICAgIGxvZGFzaC5taW5CeSA9IG1pbkJ5O1xuICAgIGxvZGFzaC5ub0NvbmZsaWN0ID0gbm9Db25mbGljdDtcbiAgICBsb2Rhc2gubm9vcCA9IG5vb3A7XG4gICAgbG9kYXNoLm5vdyA9IG5vdztcbiAgICBsb2Rhc2gucGFkID0gcGFkO1xuICAgIGxvZGFzaC5wYWRFbmQgPSBwYWRFbmQ7XG4gICAgbG9kYXNoLnBhZFN0YXJ0ID0gcGFkU3RhcnQ7XG4gICAgbG9kYXNoLnBhcnNlSW50ID0gcGFyc2VJbnQ7XG4gICAgbG9kYXNoLnJhbmRvbSA9IHJhbmRvbTtcbiAgICBsb2Rhc2gucmVkdWNlID0gcmVkdWNlO1xuICAgIGxvZGFzaC5yZWR1Y2VSaWdodCA9IHJlZHVjZVJpZ2h0O1xuICAgIGxvZGFzaC5yZXBlYXQgPSByZXBlYXQ7XG4gICAgbG9kYXNoLnJlcGxhY2UgPSByZXBsYWNlO1xuICAgIGxvZGFzaC5yZXN1bHQgPSByZXN1bHQ7XG4gICAgbG9kYXNoLnJvdW5kID0gcm91bmQ7XG4gICAgbG9kYXNoLnJ1bkluQ29udGV4dCA9IHJ1bkluQ29udGV4dDtcbiAgICBsb2Rhc2guc2FtcGxlID0gc2FtcGxlO1xuICAgIGxvZGFzaC5zaXplID0gc2l6ZTtcbiAgICBsb2Rhc2guc25ha2VDYXNlID0gc25ha2VDYXNlO1xuICAgIGxvZGFzaC5zb21lID0gc29tZTtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXggPSBzb3J0ZWRJbmRleDtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXhCeSA9IHNvcnRlZEluZGV4Qnk7XG4gICAgbG9kYXNoLnNvcnRlZEluZGV4T2YgPSBzb3J0ZWRJbmRleE9mO1xuICAgIGxvZGFzaC5zb3J0ZWRMYXN0SW5kZXggPSBzb3J0ZWRMYXN0SW5kZXg7XG4gICAgbG9kYXNoLnNvcnRlZExhc3RJbmRleEJ5ID0gc29ydGVkTGFzdEluZGV4Qnk7XG4gICAgbG9kYXNoLnNvcnRlZExhc3RJbmRleE9mID0gc29ydGVkTGFzdEluZGV4T2Y7XG4gICAgbG9kYXNoLnN0YXJ0Q2FzZSA9IHN0YXJ0Q2FzZTtcbiAgICBsb2Rhc2guc3RhcnRzV2l0aCA9IHN0YXJ0c1dpdGg7XG4gICAgbG9kYXNoLnN1YnRyYWN0ID0gc3VidHJhY3Q7XG4gICAgbG9kYXNoLnN1bSA9IHN1bTtcbiAgICBsb2Rhc2guc3VtQnkgPSBzdW1CeTtcbiAgICBsb2Rhc2gudGVtcGxhdGUgPSB0ZW1wbGF0ZTtcbiAgICBsb2Rhc2gudGltZXMgPSB0aW1lcztcbiAgICBsb2Rhc2gudG9JbnRlZ2VyID0gdG9JbnRlZ2VyO1xuICAgIGxvZGFzaC50b0xlbmd0aCA9IHRvTGVuZ3RoO1xuICAgIGxvZGFzaC50b0xvd2VyID0gdG9Mb3dlcjtcbiAgICBsb2Rhc2gudG9OdW1iZXIgPSB0b051bWJlcjtcbiAgICBsb2Rhc2gudG9TYWZlSW50ZWdlciA9IHRvU2FmZUludGVnZXI7XG4gICAgbG9kYXNoLnRvU3RyaW5nID0gdG9TdHJpbmc7XG4gICAgbG9kYXNoLnRvVXBwZXIgPSB0b1VwcGVyO1xuICAgIGxvZGFzaC50cmltID0gdHJpbTtcbiAgICBsb2Rhc2gudHJpbUVuZCA9IHRyaW1FbmQ7XG4gICAgbG9kYXNoLnRyaW1TdGFydCA9IHRyaW1TdGFydDtcbiAgICBsb2Rhc2gudHJ1bmNhdGUgPSB0cnVuY2F0ZTtcbiAgICBsb2Rhc2gudW5lc2NhcGUgPSB1bmVzY2FwZTtcbiAgICBsb2Rhc2gudW5pcXVlSWQgPSB1bmlxdWVJZDtcbiAgICBsb2Rhc2gudXBwZXJDYXNlID0gdXBwZXJDYXNlO1xuICAgIGxvZGFzaC51cHBlckZpcnN0ID0gdXBwZXJGaXJzdDtcblxuICAgIC8vIEFkZCBhbGlhc2VzLlxuICAgIGxvZGFzaC5lYWNoID0gZm9yRWFjaDtcbiAgICBsb2Rhc2guZWFjaFJpZ2h0ID0gZm9yRWFjaFJpZ2h0O1xuICAgIGxvZGFzaC5maXJzdCA9IGhlYWQ7XG5cbiAgICBtaXhpbihsb2Rhc2gsIChmdW5jdGlvbigpIHtcbiAgICAgIHZhciBzb3VyY2UgPSB7fTtcbiAgICAgIGJhc2VGb3JPd24obG9kYXNoLCBmdW5jdGlvbihmdW5jLCBtZXRob2ROYW1lKSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChsb2Rhc2gucHJvdG90eXBlLCBtZXRob2ROYW1lKSkge1xuICAgICAgICAgIHNvdXJjZVttZXRob2ROYW1lXSA9IGZ1bmM7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9KCkpLCB7ICdjaGFpbic6IGZhbHNlIH0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHNlbWFudGljIHZlcnNpb24gbnVtYmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cbiAgICBsb2Rhc2guVkVSU0lPTiA9IFZFUlNJT047XG5cbiAgICAvLyBBc3NpZ24gZGVmYXVsdCBwbGFjZWhvbGRlcnMuXG4gICAgYXJyYXlFYWNoKFsnYmluZCcsICdiaW5kS2V5JywgJ2N1cnJ5JywgJ2N1cnJ5UmlnaHQnLCAncGFydGlhbCcsICdwYXJ0aWFsUmlnaHQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgbG9kYXNoW21ldGhvZE5hbWVdLnBsYWNlaG9sZGVyID0gbG9kYXNoO1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIGBMYXp5V3JhcHBlcmAgbWV0aG9kcyBmb3IgYF8uZHJvcGAgYW5kIGBfLnRha2VgIHZhcmlhbnRzLlxuICAgIGFycmF5RWFjaChbJ2Ryb3AnLCAndGFrZSddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgTGF6eVdyYXBwZXIucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24obikge1xuICAgICAgICB2YXIgZmlsdGVyZWQgPSB0aGlzLl9fZmlsdGVyZWRfXztcbiAgICAgICAgaWYgKGZpbHRlcmVkICYmICFpbmRleCkge1xuICAgICAgICAgIHJldHVybiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgbiA9IG4gPT09IHVuZGVmaW5lZCA/IDEgOiBuYXRpdmVNYXgodG9JbnRlZ2VyKG4pLCAwKTtcblxuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5jbG9uZSgpO1xuICAgICAgICBpZiAoZmlsdGVyZWQpIHtcbiAgICAgICAgICByZXN1bHQuX190YWtlQ291bnRfXyA9IG5hdGl2ZU1pbihuLCByZXN1bHQuX190YWtlQ291bnRfXyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0Ll9fdmlld3NfXy5wdXNoKHtcbiAgICAgICAgICAgICdzaXplJzogbmF0aXZlTWluKG4sIE1BWF9BUlJBWV9MRU5HVEgpLFxuICAgICAgICAgICAgJ3R5cGUnOiBtZXRob2ROYW1lICsgKHJlc3VsdC5fX2Rpcl9fIDwgMCA/ICdSaWdodCcgOiAnJylcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcblxuICAgICAgTGF6eVdyYXBwZXIucHJvdG90eXBlW21ldGhvZE5hbWUgKyAnUmlnaHQnXSA9IGZ1bmN0aW9uKG4pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpW21ldGhvZE5hbWVdKG4pLnJldmVyc2UoKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIHRoYXQgYWNjZXB0IGFuIGBpdGVyYXRlZWAgdmFsdWUuXG4gICAgYXJyYXlFYWNoKFsnZmlsdGVyJywgJ21hcCcsICd0YWtlV2hpbGUnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciB0eXBlID0gaW5kZXggKyAxLFxuICAgICAgICAgIGlzRmlsdGVyID0gdHlwZSA9PSBMQVpZX0ZJTFRFUl9GTEFHIHx8IHR5cGUgPT0gTEFaWV9XSElMRV9GTEFHO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihpdGVyYXRlZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gdGhpcy5jbG9uZSgpO1xuICAgICAgICByZXN1bHQuX19pdGVyYXRlZXNfXy5wdXNoKHtcbiAgICAgICAgICAnaXRlcmF0ZWUnOiBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyksXG4gICAgICAgICAgJ3R5cGUnOiB0eXBlXG4gICAgICAgIH0pO1xuICAgICAgICByZXN1bHQuX19maWx0ZXJlZF9fID0gcmVzdWx0Ll9fZmlsdGVyZWRfXyB8fCBpc0ZpbHRlcjtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5oZWFkYCBhbmQgYF8ubGFzdGAuXG4gICAgYXJyYXlFYWNoKFsnaGVhZCcsICdsYXN0J10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICB2YXIgdGFrZU5hbWUgPSAndGFrZScgKyAoaW5kZXggPyAnUmlnaHQnIDogJycpO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbdGFrZU5hbWVdKDEpLnZhbHVlKClbMF07XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIGBMYXp5V3JhcHBlcmAgbWV0aG9kcyBmb3IgYF8uaW5pdGlhbGAgYW5kIGBfLnRhaWxgLlxuICAgIGFycmF5RWFjaChbJ2luaXRpYWwnLCAndGFpbCddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIGRyb3BOYW1lID0gJ2Ryb3AnICsgKGluZGV4ID8gJycgOiAnUmlnaHQnKTtcblxuICAgICAgTGF6eVdyYXBwZXIucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9fZmlsdGVyZWRfXyA/IG5ldyBMYXp5V3JhcHBlcih0aGlzKSA6IHRoaXNbZHJvcE5hbWVdKDEpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5jb21wYWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIoaWRlbnRpdHkpO1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyKHByZWRpY2F0ZSkuaGVhZCgpO1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuZmluZExhc3QgPSBmdW5jdGlvbihwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJldmVyc2UoKS5maW5kKHByZWRpY2F0ZSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5pbnZva2VNYXAgPSByZXN0KGZ1bmN0aW9uKHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUucmVqZWN0ID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICBwcmVkaWNhdGUgPSBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpO1xuICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiAhcHJlZGljYXRlKHZhbHVlKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICBzdGFydCA9IHRvSW50ZWdlcihzdGFydCk7XG5cbiAgICAgIHZhciByZXN1bHQgPSB0aGlzO1xuICAgICAgaWYgKHJlc3VsdC5fX2ZpbHRlcmVkX18gJiYgKHN0YXJ0ID4gMCB8fCBlbmQgPCAwKSkge1xuICAgICAgICByZXR1cm4gbmV3IExhenlXcmFwcGVyKHJlc3VsdCk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC50YWtlUmlnaHQoLXN0YXJ0KTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhcnQpIHtcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmRyb3Aoc3RhcnQpO1xuICAgICAgfVxuICAgICAgaWYgKGVuZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVuZCA9IHRvSW50ZWdlcihlbmQpO1xuICAgICAgICByZXN1bHQgPSBlbmQgPCAwID8gcmVzdWx0LmRyb3BSaWdodCgtZW5kKSA6IHJlc3VsdC50YWtlKGVuZCAtIHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS50YWtlUmlnaHRXaGlsZSA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpLnRha2VXaGlsZShwcmVkaWNhdGUpLnJldmVyc2UoKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnRvQXJyYXkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnRha2UoTUFYX0FSUkFZX0xFTkdUSCk7XG4gICAgfTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIGJhc2VGb3JPd24oTGF6eVdyYXBwZXIucHJvdG90eXBlLCBmdW5jdGlvbihmdW5jLCBtZXRob2ROYW1lKSB7XG4gICAgICB2YXIgY2hlY2tJdGVyYXRlZSA9IC9eKD86ZmlsdGVyfGZpbmR8bWFwfHJlamVjdCl8V2hpbGUkLy50ZXN0KG1ldGhvZE5hbWUpLFxuICAgICAgICAgIGlzVGFrZXIgPSAvXig/OmhlYWR8bGFzdCkkLy50ZXN0KG1ldGhvZE5hbWUpLFxuICAgICAgICAgIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbaXNUYWtlciA/ICgndGFrZScgKyAobWV0aG9kTmFtZSA9PSAnbGFzdCcgPyAnUmlnaHQnIDogJycpKSA6IG1ldGhvZE5hbWVdLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IGlzVGFrZXIgfHwgL15maW5kLy50ZXN0KG1ldGhvZE5hbWUpO1xuXG4gICAgICBpZiAoIWxvZGFzaEZ1bmMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgbG9kYXNoLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLl9fd3JhcHBlZF9fLFxuICAgICAgICAgICAgYXJncyA9IGlzVGFrZXIgPyBbMV0gOiBhcmd1bWVudHMsXG4gICAgICAgICAgICBpc0xhenkgPSB2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyLFxuICAgICAgICAgICAgaXRlcmF0ZWUgPSBhcmdzWzBdLFxuICAgICAgICAgICAgdXNlTGF6eSA9IGlzTGF6eSB8fCBpc0FycmF5KHZhbHVlKTtcblxuICAgICAgICB2YXIgaW50ZXJjZXB0b3IgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgIHZhciByZXN1bHQgPSBsb2Rhc2hGdW5jLmFwcGx5KGxvZGFzaCwgYXJyYXlQdXNoKFt2YWx1ZV0sIGFyZ3MpKTtcbiAgICAgICAgICByZXR1cm4gKGlzVGFrZXIgJiYgY2hhaW5BbGwpID8gcmVzdWx0WzBdIDogcmVzdWx0O1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh1c2VMYXp5ICYmIGNoZWNrSXRlcmF0ZWUgJiYgdHlwZW9mIGl0ZXJhdGVlID09ICdmdW5jdGlvbicgJiYgaXRlcmF0ZWUubGVuZ3RoICE9IDEpIHtcbiAgICAgICAgICAvLyBBdm9pZCBsYXp5IHVzZSBpZiB0aGUgaXRlcmF0ZWUgaGFzIGEgXCJsZW5ndGhcIiB2YWx1ZSBvdGhlciB0aGFuIGAxYC5cbiAgICAgICAgICBpc0xhenkgPSB1c2VMYXp5ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoYWluQWxsID0gdGhpcy5fX2NoYWluX18sXG4gICAgICAgICAgICBpc0h5YnJpZCA9ICEhdGhpcy5fX2FjdGlvbnNfXy5sZW5ndGgsXG4gICAgICAgICAgICBpc1Vud3JhcHBlZCA9IHJldFVud3JhcHBlZCAmJiAhY2hhaW5BbGwsXG4gICAgICAgICAgICBvbmx5TGF6eSA9IGlzTGF6eSAmJiAhaXNIeWJyaWQ7XG5cbiAgICAgICAgaWYgKCFyZXRVbndyYXBwZWQgJiYgdXNlTGF6eSkge1xuICAgICAgICAgIHZhbHVlID0gb25seUxhenkgPyB2YWx1ZSA6IG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseSh2YWx1ZSwgYXJncyk7XG4gICAgICAgICAgcmVzdWx0Ll9fYWN0aW9uc19fLnB1c2goeyAnZnVuYyc6IHRocnUsICdhcmdzJzogW2ludGVyY2VwdG9yXSwgJ3RoaXNBcmcnOiB1bmRlZmluZWQgfSk7XG4gICAgICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHJlc3VsdCwgY2hhaW5BbGwpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1Vud3JhcHBlZCAmJiBvbmx5TGF6eSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9IHRoaXMudGhydShpbnRlcmNlcHRvcik7XG4gICAgICAgIHJldHVybiBpc1Vud3JhcHBlZCA/IChpc1Rha2VyID8gcmVzdWx0LnZhbHVlKClbMF0gOiByZXN1bHQudmFsdWUoKSkgOiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIGBBcnJheWAgYW5kIGBTdHJpbmdgIG1ldGhvZHMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIGFycmF5RWFjaChbJ3BvcCcsICdwdXNoJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBhcnJheVByb3RvW21ldGhvZE5hbWVdLFxuICAgICAgICAgIGNoYWluTmFtZSA9IC9eKD86cHVzaHxzb3J0fHVuc2hpZnQpJC8udGVzdChtZXRob2ROYW1lKSA/ICd0YXAnIDogJ3RocnUnLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86cG9wfHNoaWZ0KSQvLnRlc3QobWV0aG9kTmFtZSk7XG5cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmIChyZXRVbndyYXBwZWQgJiYgIXRoaXMuX19jaGFpbl9fKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcy52YWx1ZSgpLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpc1tjaGFpbk5hbWVdKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBNYXAgbWluaWZpZWQgZnVuY3Rpb24gbmFtZXMgdG8gdGhlaXIgcmVhbCBuYW1lcy5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbbWV0aG9kTmFtZV07XG4gICAgICBpZiAobG9kYXNoRnVuYykge1xuICAgICAgICB2YXIga2V5ID0gKGxvZGFzaEZ1bmMubmFtZSArICcnKSxcbiAgICAgICAgICAgIG5hbWVzID0gcmVhbE5hbWVzW2tleV0gfHwgKHJlYWxOYW1lc1trZXldID0gW10pO1xuXG4gICAgICAgIG5hbWVzLnB1c2goeyAnbmFtZSc6IG1ldGhvZE5hbWUsICdmdW5jJzogbG9kYXNoRnVuYyB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlYWxOYW1lc1tjcmVhdGVIeWJyaWRXcmFwcGVyKHVuZGVmaW5lZCwgQklORF9LRVlfRkxBRykubmFtZV0gPSBbe1xuICAgICAgJ25hbWUnOiAnd3JhcHBlcicsXG4gICAgICAnZnVuYyc6IHVuZGVmaW5lZFxuICAgIH1dO1xuXG4gICAgLy8gQWRkIGZ1bmN0aW9ucyB0byB0aGUgbGF6eSB3cmFwcGVyLlxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5jbG9uZSA9IGxhenlDbG9uZTtcbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUucmV2ZXJzZSA9IGxhenlSZXZlcnNlO1xuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS52YWx1ZSA9IGxhenlWYWx1ZTtcblxuICAgIC8vIEFkZCBjaGFpbmluZyBmdW5jdGlvbnMgdG8gdGhlIGBsb2Rhc2hgIHdyYXBwZXIuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5hdCA9IHdyYXBwZXJBdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29tbWl0ID0gd3JhcHBlckNvbW1pdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmZsYXRNYXAgPSB3cmFwcGVyRmxhdE1hcDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLm5leHQgPSB3cmFwcGVyTmV4dDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnBsYW50ID0gd3JhcHBlclBsYW50O1xuICAgIGxvZGFzaC5wcm90b3R5cGUucmV2ZXJzZSA9IHdyYXBwZXJSZXZlcnNlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudG9KU09OID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZU9mID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZSA9IHdyYXBwZXJWYWx1ZTtcblxuICAgIGlmIChpdGVyYXRvclN5bWJvbCkge1xuICAgICAgbG9kYXNoLnByb3RvdHlwZVtpdGVyYXRvclN5bWJvbF0gPSB3cmFwcGVyVG9JdGVyYXRvcjtcbiAgICB9XG4gICAgcmV0dXJuIGxvZGFzaDtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBsb2Rhc2guXG4gIHZhciBfID0gcnVuSW5Db250ZXh0KCk7XG5cbiAgLy8gRXhwb3NlIGxvZGFzaCBvbiB0aGUgZnJlZSB2YXJpYWJsZSBgd2luZG93YCBvciBgc2VsZmAgd2hlbiBhdmFpbGFibGUuIFRoaXNcbiAgLy8gcHJldmVudHMgZXJyb3JzIGluIGNhc2VzIHdoZXJlIGxvZGFzaCBpcyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGluIHRoZSBwcmVzZW5jZVxuICAvLyBvZiBhbiBBTUQgbG9hZGVyLiBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAoZnJlZVdpbmRvdyB8fCBmcmVlU2VsZiB8fCB7fSkuXyA9IF87XG5cbiAgLy8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycyBsaWtlIHIuanMgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvLCB0aHJvdWdoIHBhdGggbWFwcGluZywgaXQgY2FuIGJlXG4gICAgLy8gcmVmZXJlbmNlZCBhcyB0aGUgXCJ1bmRlcnNjb3JlXCIgbW9kdWxlLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIE5vZGUuanMuXG4gICAgaWYgKG1vZHVsZUV4cG9ydHMpIHtcbiAgICAgIChmcmVlTW9kdWxlLmV4cG9ydHMgPSBfKS5fID0gXztcbiAgICB9XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwidmFyIENsYXNzID0gcmVxdWlyZShcImFiaXRib2xcIik7XHJcbnZhciBCaW5hcnlIZWFwID0gcmVxdWlyZShcIi4vQmluYXJ5SGVhcC5qc1wiKTtcclxuXHJcbnZhciBBc3RhciA9IENsYXNzLiRleHRlbmQoe1xyXG5cclxuIFx0aW5pdDogZnVuY3Rpb24gKGdyYXBoKSB7XHJcblx0XHRmb3IgKHZhciB4ID0gMDsgeCA8IGdyYXBoLmxlbmd0aDsgeCsrKSB7XHJcblx0XHRcdC8vZm9yKHZhciB4IGluIGdyYXBoKSB7XHJcblx0XHRcdHZhciBub2RlID0gZ3JhcGhbeF07XHJcblx0XHRcdG5vZGUuZiA9IDA7XHJcblx0XHRcdG5vZGUuZyA9IDA7XHJcblx0XHRcdG5vZGUuaCA9IDA7XHJcblx0XHRcdG5vZGUuY29zdCA9IDEuMDtcclxuXHRcdFx0bm9kZS52aXNpdGVkID0gZmFsc2U7XHJcblx0XHRcdG5vZGUuY2xvc2VkID0gZmFsc2U7XHJcblx0XHRcdG5vZGUucGFyZW50ID0gbnVsbDtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRjbGVhblVwOiBmdW5jdGlvbiAoZ3JhcGgpIHtcclxuXHRcdGZvciAodmFyIHggPSAwOyB4IDwgZ3JhcGgubGVuZ3RoOyB4KyspIHtcclxuXHRcdFx0dmFyIG5vZGUgPSBncmFwaFt4XTtcclxuXHRcdFx0ZGVsZXRlIG5vZGUuZjtcclxuXHRcdFx0ZGVsZXRlIG5vZGUuZztcclxuXHRcdFx0ZGVsZXRlIG5vZGUuaDtcclxuXHRcdFx0ZGVsZXRlIG5vZGUuY29zdDtcclxuXHRcdFx0ZGVsZXRlIG5vZGUudmlzaXRlZDtcclxuXHRcdFx0ZGVsZXRlIG5vZGUuY2xvc2VkO1xyXG5cdFx0XHRkZWxldGUgbm9kZS5wYXJlbnQ7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0aGVhcDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBCaW5hcnlIZWFwKGZ1bmN0aW9uIChub2RlKSB7XHJcblx0XHRcdHJldHVybiBub2RlLmY7XHJcblx0XHR9KTtcclxuXHR9LFxyXG5cdFxyXG5cdHNlYXJjaDogZnVuY3Rpb24gKGdyYXBoLCBzdGFydCwgZW5kKSB7XHJcblx0XHR0aGlzLmluaXQoZ3JhcGgpO1xyXG5cdFx0Ly9oZXVyaXN0aWMgPSBoZXVyaXN0aWMgfHwgYXN0YXIubWFuaGF0dGFuO1xyXG5cclxuXHJcblx0XHR2YXIgb3BlbkhlYXAgPSB0aGlzLmhlYXAoKTtcclxuXHJcblx0XHRvcGVuSGVhcC5wdXNoKHN0YXJ0KTtcclxuXHJcblx0XHR3aGlsZSAob3BlbkhlYXAuc2l6ZSgpID4gMCkge1xyXG5cclxuXHRcdFx0Ly8gR3JhYiB0aGUgbG93ZXN0IGYoeCkgdG8gcHJvY2VzcyBuZXh0LiAgSGVhcCBrZWVwcyB0aGlzIHNvcnRlZCBmb3IgdXMuXHJcblx0XHRcdHZhciBjdXJyZW50Tm9kZSA9IG9wZW5IZWFwLnBvcCgpO1xyXG5cclxuXHRcdFx0Ly8gRW5kIGNhc2UgLS0gcmVzdWx0IGhhcyBiZWVuIGZvdW5kLCByZXR1cm4gdGhlIHRyYWNlZCBwYXRoLlxyXG5cdFx0XHRpZiAoY3VycmVudE5vZGUgPT09IGVuZCkge1xyXG5cdFx0XHRcdHZhciBjdXJyID0gY3VycmVudE5vZGU7XHJcblx0XHRcdFx0dmFyIHJldCA9IFtdO1xyXG5cdFx0XHRcdHdoaWxlIChjdXJyLnBhcmVudCkge1xyXG5cdFx0XHRcdFx0cmV0LnB1c2goY3Vycik7XHJcblx0XHRcdFx0XHRjdXJyID0gY3Vyci5wYXJlbnQ7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHRoaXMuY2xlYW5VcChyZXQpO1xyXG5cdFx0XHRcdHJldHVybiByZXQucmV2ZXJzZSgpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBOb3JtYWwgY2FzZSAtLSBtb3ZlIGN1cnJlbnROb2RlIGZyb20gb3BlbiB0byBjbG9zZWQsIHByb2Nlc3MgZWFjaCBvZiBpdHMgbmVpZ2hib3Vycy5cclxuXHRcdFx0Y3VycmVudE5vZGUuY2xvc2VkID0gdHJ1ZTtcclxuXHJcblx0XHRcdC8vIEZpbmQgYWxsIG5laWdoYm91cnMgZm9yIHRoZSBjdXJyZW50IG5vZGUuIE9wdGlvbmFsbHkgZmluZCBkaWFnb25hbCBuZWlnaGJvdXJzIGFzIHdlbGwgKGZhbHNlIGJ5IGRlZmF1bHQpLlxyXG5cdFx0XHR2YXIgbmVpZ2hib3VycyA9IHRoaXMubmVpZ2hib3VycyhncmFwaCwgY3VycmVudE5vZGUpO1xyXG5cclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGlsID0gbmVpZ2hib3Vycy5sZW5ndGg7IGkgPCBpbDsgaSsrKSB7XHJcblx0XHRcdFx0dmFyIG5laWdoYm91ciA9IG5laWdoYm91cnNbaV07XHJcblxyXG5cdFx0XHRcdGlmIChuZWlnaGJvdXIuY2xvc2VkKSB7XHJcblx0XHRcdFx0XHQvLyBOb3QgYSB2YWxpZCBub2RlIHRvIHByb2Nlc3MsIHNraXAgdG8gbmV4dCBuZWlnaGJvdXIuXHJcblx0XHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIFRoZSBnIHNjb3JlIGlzIHRoZSBzaG9ydGVzdCBkaXN0YW5jZSBmcm9tIHN0YXJ0IHRvIGN1cnJlbnQgbm9kZS5cclxuXHRcdFx0XHQvLyBXZSBuZWVkIHRvIGNoZWNrIGlmIHRoZSBwYXRoIHdlIGhhdmUgYXJyaXZlZCBhdCB0aGlzIG5laWdoYm91ciBpcyB0aGUgc2hvcnRlc3Qgb25lIHdlIGhhdmUgc2VlbiB5ZXQuXHJcblx0XHRcdFx0dmFyIGdTY29yZSA9IGN1cnJlbnROb2RlLmcgKyBuZWlnaGJvdXIuY29zdDtcclxuXHRcdFx0XHR2YXIgYmVlblZpc2l0ZWQgPSBuZWlnaGJvdXIudmlzaXRlZDtcclxuXHJcblx0XHRcdFx0aWYgKCFiZWVuVmlzaXRlZCB8fCBnU2NvcmUgPCBuZWlnaGJvdXIuZykge1xyXG5cclxuXHRcdFx0XHRcdC8vIEZvdW5kIGFuIG9wdGltYWwgKHNvIGZhcikgcGF0aCB0byB0aGlzIG5vZGUuICBUYWtlIHNjb3JlIGZvciBub2RlIHRvIHNlZSBob3cgZ29vZCBpdCBpcy5cclxuXHRcdFx0XHRcdG5laWdoYm91ci52aXNpdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdG5laWdoYm91ci5wYXJlbnQgPSBjdXJyZW50Tm9kZTtcclxuXHRcdFx0XHRcdGlmICghbmVpZ2hib3VyLmNlbnRyb2lkIHx8ICFlbmQuY2VudHJvaWQpIGRlYnVnZ2VyO1xyXG5cdFx0XHRcdFx0bmVpZ2hib3VyLmggPSBuZWlnaGJvdXIuaCB8fCB0aGlzLmhldXJpc3RpYyhuZWlnaGJvdXIuY2VudHJvaWQsIGVuZC5jZW50cm9pZCk7XHJcblx0XHRcdFx0XHRuZWlnaGJvdXIuZyA9IGdTY29yZTtcclxuXHRcdFx0XHRcdG5laWdoYm91ci5mID0gbmVpZ2hib3VyLmcgKyBuZWlnaGJvdXIuaDtcclxuXHJcblx0XHRcdFx0XHRpZiAoIWJlZW5WaXNpdGVkKSB7XHJcblx0XHRcdFx0XHRcdC8vIFB1c2hpbmcgdG8gaGVhcCB3aWxsIHB1dCBpdCBpbiBwcm9wZXIgcGxhY2UgYmFzZWQgb24gdGhlICdmJyB2YWx1ZS5cclxuXHRcdFx0XHRcdFx0b3BlbkhlYXAucHVzaChuZWlnaGJvdXIpO1xyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0Ly8gQWxyZWFkeSBzZWVuIHRoZSBub2RlLCBidXQgc2luY2UgaXQgaGFzIGJlZW4gcmVzY29yZWQgd2UgbmVlZCB0byByZW9yZGVyIGl0IGluIHRoZSBoZWFwXHJcblx0XHRcdFx0XHRcdG9wZW5IZWFwLnJlc2NvcmVFbGVtZW50KG5laWdoYm91cik7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gTm8gcmVzdWx0IHdhcyBmb3VuZCAtIGVtcHR5IGFycmF5IHNpZ25pZmllcyBmYWlsdXJlIHRvIGZpbmQgcGF0aC5cclxuXHRcdHJldHVybiBbXTtcclxuXHR9LFxyXG5cdGhldXJpc3RpYzogZnVuY3Rpb24gKHBvczEsIHBvczIpIHtcclxuXHRcdHJldHVybiBCQUJZTE9OLlZlY3RvcjMuRGlzdGFuY2VTcXVhcmVkKHBvczEsIHBvczIpO1xyXG5cdH0sXHJcblx0bmVpZ2hib3VyczogZnVuY3Rpb24gKGdyYXBoLCBub2RlKSB7XHJcblx0XHR2YXIgcmV0ID0gW107XHJcblxyXG5cdFx0Zm9yICh2YXIgZSA9IDA7IGUgPCBub2RlLm5laWdoYm91cnMubGVuZ3RoOyBlKyspIHtcclxuXHRcdFx0cmV0LnB1c2goZ3JhcGhbbm9kZS5uZWlnaGJvdXJzW2VdXSk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJldDtcclxuXHR9XHJcblxyXG59KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gQXN0YXI7IiwidmFyIENsYXNzID0gcmVxdWlyZShcImFiaXRib2xcIik7XHJcblxyXG52YXIgQmluYXJ5SGVhcCA9IENsYXNzLiRleHRlbmQoe1xyXG4gICAgX19pbml0X186IGZ1bmN0aW9uKHNjb3JlRnVuY3Rpb24pIHtcclxuXHRcdHRoaXMuY29udGVudCA9IFtdO1xyXG5cdFx0dGhpcy5zY29yZUZ1bmN0aW9uID0gc2NvcmVGdW5jdGlvbiB8fCBuZXcgZnVuY3Rpb24gKCkge307XHJcbiAgICB9LFxyXG5cclxuXHRwdXNoOiBmdW5jdGlvbiAoZWxlbWVudCkge1xyXG5cdFx0Ly8gQWRkIHRoZSBuZXcgZWxlbWVudCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheS5cclxuXHRcdHRoaXMuY29udGVudC5wdXNoKGVsZW1lbnQpO1xyXG5cclxuXHRcdC8vIEFsbG93IGl0IHRvIHNpbmsgZG93bi5cclxuXHRcdHRoaXMuc2lua0Rvd24odGhpcy5jb250ZW50Lmxlbmd0aCAtIDEpO1xyXG5cdH0sXHJcblx0cG9wOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBTdG9yZSB0aGUgZmlyc3QgZWxlbWVudCBzbyB3ZSBjYW4gcmV0dXJuIGl0IGxhdGVyLlxyXG5cdFx0dmFyIHJlc3VsdCA9IHRoaXMuY29udGVudFswXTtcclxuXHRcdC8vIEdldCB0aGUgZWxlbWVudCBhdCB0aGUgZW5kIG9mIHRoZSBhcnJheS5cclxuXHRcdHZhciBlbmQgPSB0aGlzLmNvbnRlbnQucG9wKCk7XHJcblx0XHQvLyBJZiB0aGVyZSBhcmUgYW55IGVsZW1lbnRzIGxlZnQsIHB1dCB0aGUgZW5kIGVsZW1lbnQgYXQgdGhlXHJcblx0XHQvLyBzdGFydCwgYW5kIGxldCBpdCBidWJibGUgdXAuXHJcblx0XHRpZiAodGhpcy5jb250ZW50Lmxlbmd0aCA+IDApIHtcclxuXHRcdFx0dGhpcy5jb250ZW50WzBdID0gZW5kO1xyXG5cdFx0XHR0aGlzLmJ1YmJsZVVwKDApO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHR9LFxyXG5cdHJlbW92ZTogZnVuY3Rpb24gKG5vZGUpIHtcclxuXHRcdHZhciBpID0gdGhpcy5jb250ZW50LmluZGV4T2Yobm9kZSk7XHJcblxyXG5cdFx0Ly8gV2hlbiBpdCBpcyBmb3VuZCwgdGhlIHByb2Nlc3Mgc2VlbiBpbiAncG9wJyBpcyByZXBlYXRlZFxyXG5cdFx0Ly8gdG8gZmlsbCB1cCB0aGUgaG9sZS5cclxuXHRcdHZhciBlbmQgPSB0aGlzLmNvbnRlbnQucG9wKCk7XHJcblxyXG5cdFx0aWYgKGkgIT09IHRoaXMuY29udGVudC5sZW5ndGggLSAxKSB7XHJcblx0XHRcdHRoaXMuY29udGVudFtpXSA9IGVuZDtcclxuXHJcblx0XHRcdGlmICh0aGlzLnNjb3JlRnVuY3Rpb24oZW5kKSA8IHRoaXMuc2NvcmVGdW5jdGlvbihub2RlKSkge1xyXG5cdFx0XHRcdHRoaXMuc2lua0Rvd24oaSk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGhpcy5idWJibGVVcChpKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblx0c2l6ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY29udGVudC5sZW5ndGg7XHJcblx0fSxcclxuXHRyZXNjb3JlRWxlbWVudDogZnVuY3Rpb24gKG5vZGUpIHtcclxuXHRcdHRoaXMuc2lua0Rvd24odGhpcy5jb250ZW50LmluZGV4T2Yobm9kZSkpO1xyXG5cdH0sXHJcblx0c2lua0Rvd246IGZ1bmN0aW9uIChuKSB7XHJcblx0XHQvLyBGZXRjaCB0aGUgZWxlbWVudCB0aGF0IGhhcyB0byBiZSBzdW5rLlxyXG5cdFx0dmFyIGVsZW1lbnQgPSB0aGlzLmNvbnRlbnRbbl07XHJcblxyXG5cdFx0Ly8gV2hlbiBhdCAwLCBhbiBlbGVtZW50IGNhbiBub3Qgc2luayBhbnkgZnVydGhlci5cclxuXHRcdHdoaWxlIChuID4gMCkge1xyXG5cclxuXHRcdFx0Ly8gQ29tcHV0ZSB0aGUgcGFyZW50IGVsZW1lbnQncyBpbmRleCwgYW5kIGZldGNoIGl0LlxyXG5cdFx0XHR2YXIgcGFyZW50TiA9ICgobiArIDEpID4+IDEpIC0gMSxcclxuXHRcdFx0XHRwYXJlbnQgPSB0aGlzLmNvbnRlbnRbcGFyZW50Tl07XHJcblx0XHRcdC8vIFN3YXAgdGhlIGVsZW1lbnRzIGlmIHRoZSBwYXJlbnQgaXMgZ3JlYXRlci5cclxuXHRcdFx0aWYgKHRoaXMuc2NvcmVGdW5jdGlvbihlbGVtZW50KSA8IHRoaXMuc2NvcmVGdW5jdGlvbihwYXJlbnQpKSB7XHJcblx0XHRcdFx0dGhpcy5jb250ZW50W3BhcmVudE5dID0gZWxlbWVudDtcclxuXHRcdFx0XHR0aGlzLmNvbnRlbnRbbl0gPSBwYXJlbnQ7XHJcblx0XHRcdFx0Ly8gVXBkYXRlICduJyB0byBjb250aW51ZSBhdCB0aGUgbmV3IHBvc2l0aW9uLlxyXG5cdFx0XHRcdG4gPSBwYXJlbnROO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBGb3VuZCBhIHBhcmVudCB0aGF0IGlzIGxlc3MsIG5vIG5lZWQgdG8gc2luayBhbnkgZnVydGhlci5cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cdGJ1YmJsZVVwOiBmdW5jdGlvbiAobikge1xyXG5cdFx0Ly8gTG9vayB1cCB0aGUgdGFyZ2V0IGVsZW1lbnQgYW5kIGl0cyBzY29yZS5cclxuXHRcdHZhciBsZW5ndGggPSB0aGlzLmNvbnRlbnQubGVuZ3RoLFxyXG5cdFx0XHRlbGVtZW50ID0gdGhpcy5jb250ZW50W25dLFxyXG5cdFx0XHRlbGVtU2NvcmUgPSB0aGlzLnNjb3JlRnVuY3Rpb24oZWxlbWVudCk7XHJcblxyXG5cdFx0d2hpbGUgKHRydWUpIHtcclxuXHRcdFx0Ly8gQ29tcHV0ZSB0aGUgaW5kaWNlcyBvZiB0aGUgY2hpbGQgZWxlbWVudHMuXHJcblx0XHRcdHZhciBjaGlsZDJOID0gKG4gKyAxKSA8PCAxLFxyXG5cdFx0XHRcdGNoaWxkMU4gPSBjaGlsZDJOIC0gMTtcclxuXHRcdFx0Ly8gVGhpcyBpcyB1c2VkIHRvIHN0b3JlIHRoZSBuZXcgcG9zaXRpb24gb2YgdGhlIGVsZW1lbnQsXHJcblx0XHRcdC8vIGlmIGFueS5cclxuXHRcdFx0dmFyIHN3YXAgPSBudWxsO1xyXG5cdFx0XHQvLyBJZiB0aGUgZmlyc3QgY2hpbGQgZXhpc3RzIChpcyBpbnNpZGUgdGhlIGFycmF5KS4uLlxyXG5cdFx0XHRpZiAoY2hpbGQxTiA8IGxlbmd0aCkge1xyXG5cdFx0XHRcdC8vIExvb2sgaXQgdXAgYW5kIGNvbXB1dGUgaXRzIHNjb3JlLlxyXG5cdFx0XHRcdHZhciBjaGlsZDEgPSB0aGlzLmNvbnRlbnRbY2hpbGQxTl0sXHJcblx0XHRcdFx0XHRjaGlsZDFTY29yZSA9IHRoaXMuc2NvcmVGdW5jdGlvbihjaGlsZDEpO1xyXG5cclxuXHRcdFx0XHQvLyBJZiB0aGUgc2NvcmUgaXMgbGVzcyB0aGFuIG91ciBlbGVtZW50J3MsIHdlIG5lZWQgdG8gc3dhcC5cclxuXHRcdFx0XHRpZiAoY2hpbGQxU2NvcmUgPCBlbGVtU2NvcmUpXHJcblx0XHRcdFx0XHRzd2FwID0gY2hpbGQxTjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gRG8gdGhlIHNhbWUgY2hlY2tzIGZvciB0aGUgb3RoZXIgY2hpbGQuXHJcblx0XHRcdGlmIChjaGlsZDJOIDwgbGVuZ3RoKSB7XHJcblx0XHRcdFx0dmFyIGNoaWxkMiA9IHRoaXMuY29udGVudFtjaGlsZDJOXSxcclxuXHRcdFx0XHRcdGNoaWxkMlNjb3JlID0gdGhpcy5zY29yZUZ1bmN0aW9uKGNoaWxkMik7XHJcblx0XHRcdFx0aWYgKGNoaWxkMlNjb3JlIDwgKHN3YXAgPT09IG51bGwgPyBlbGVtU2NvcmUgOiBjaGlsZDFTY29yZSkpIHtcclxuXHRcdFx0XHRcdHN3YXAgPSBjaGlsZDJOO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gSWYgdGhlIGVsZW1lbnQgbmVlZHMgdG8gYmUgbW92ZWQsIHN3YXAgaXQsIGFuZCBjb250aW51ZS5cclxuXHRcdFx0aWYgKHN3YXAgIT09IG51bGwpIHtcclxuXHRcdFx0XHR0aGlzLmNvbnRlbnRbbl0gPSB0aGlzLmNvbnRlbnRbc3dhcF07XHJcblx0XHRcdFx0dGhpcy5jb250ZW50W3N3YXBdID0gZWxlbWVudDtcclxuXHRcdFx0XHRuID0gc3dhcDtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gT3RoZXJ3aXNlLCB3ZSBhcmUgZG9uZS5cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcbn0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBCaW5hcnlIZWFwOyIsInZhciBDbGFzcyA9IHJlcXVpcmUoXCJhYml0Ym9sXCIpO1xyXG5cclxudmFyIENoYW5uZWwgPSBDbGFzcy4kZXh0ZW5kKHtcclxuXHRfX2luaXRfXzogZnVuY3Rpb24oKSB7XHJcblx0ICAgIHRoaXMucG9ydGFscyA9IFtdO1xyXG5cdH0sXHJcblxyXG5cdHB1c2g6IGZ1bmN0aW9uIChwMSwgcDIpIHtcclxuXHRcdGlmIChwMiA9PT0gdW5kZWZpbmVkKSBwMiA9IHAxO1xyXG5cdFx0dGhpcy5wb3J0YWxzLnB1c2goe1xyXG5cdFx0XHRsZWZ0OiBwMSxcclxuXHRcdFx0cmlnaHQ6IHAyXHJcblx0XHR9KTtcclxuXHR9LFxyXG5cclxuXHRfdmVxdWFsOiBmdW5jdGlvbiAoYSwgYikge1xyXG5cdFx0cmV0dXJuIEJBQllMT04uVmVjdG9yMy5EaXN0YW5jZVNxdWFyZWQoYSwgYikgPCAwLjAwMDAxO1xyXG5cdH0sXHJcblxyXG5cdF90cmlhcmVhMjogZnVuY3Rpb24gKGEsIGIsIGMpIHtcclxuXHRcdHZhciBheCA9IGIueCAtIGEueDtcclxuXHRcdHZhciBheiA9IGIueiAtIGEuejtcclxuXHRcdHZhciBieCA9IGMueCAtIGEueDtcclxuXHRcdHZhciBieiA9IGMueiAtIGEuejtcclxuXHRcdHJldHVybiBieCAqIGF6IC0gYXggKiBiejtcclxuXHR9LFxyXG5cclxuXHRzdHJpbmdQdWxsOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgcG9ydGFscyA9IHRoaXMucG9ydGFscztcclxuXHRcdHZhciBwdHMgPSBbXTtcclxuXHRcdC8vIEluaXQgc2NhbiBzdGF0ZVxyXG5cdFx0dmFyIHBvcnRhbEFwZXgsIHBvcnRhbExlZnQsIHBvcnRhbFJpZ2h0O1xyXG5cdFx0dmFyIGFwZXhJbmRleCA9IDAsXHJcblx0XHRcdGxlZnRJbmRleCA9IDAsXHJcblx0XHRcdHJpZ2h0SW5kZXggPSAwO1xyXG5cclxuXHRcdHBvcnRhbEFwZXggPSBwb3J0YWxzWzBdLmxlZnQ7XHJcblx0XHRwb3J0YWxMZWZ0ID0gcG9ydGFsc1swXS5sZWZ0O1xyXG5cdFx0cG9ydGFsUmlnaHQgPSBwb3J0YWxzWzBdLnJpZ2h0O1xyXG5cclxuXHRcdC8vIEFkZCBzdGFydCBwb2ludC5cclxuXHRcdHB0cy5wdXNoKHBvcnRhbEFwZXgpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAxOyBpIDwgcG9ydGFscy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHR2YXIgbGVmdCA9IHBvcnRhbHNbaV0ubGVmdDtcclxuXHRcdFx0dmFyIHJpZ2h0ID0gcG9ydGFsc1tpXS5yaWdodDtcclxuXHJcblx0XHRcdC8vIFVwZGF0ZSByaWdodCB2ZXJ0ZXguXHJcblx0XHRcdGlmICh0aGlzLl90cmlhcmVhMihwb3J0YWxBcGV4LCBwb3J0YWxSaWdodCwgcmlnaHQpID49IDAuMCkge1xyXG5cdFx0XHRcdGlmICh0aGlzLl92ZXF1YWwocG9ydGFsQXBleCwgcG9ydGFsUmlnaHQpIHx8IHRoaXMuX3RyaWFyZWEyKHBvcnRhbEFwZXgsIHBvcnRhbExlZnQsIHJpZ2h0KSA8IDAuMCkge1xyXG5cdFx0XHRcdFx0Ly8gVGlnaHRlbiB0aGUgZnVubmVsLlxyXG5cdFx0XHRcdFx0cG9ydGFsUmlnaHQgPSByaWdodDtcclxuXHRcdFx0XHRcdHJpZ2h0SW5kZXggPSBpO1xyXG5cdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHQvLyBSaWdodCBvdmVyIGxlZnQsIGluc2VydCBsZWZ0IHRvIHBhdGggYW5kIHJlc3RhcnQgc2NhbiBmcm9tIHBvcnRhbCBsZWZ0IHBvaW50LlxyXG5cdFx0XHRcdFx0cHRzLnB1c2gocG9ydGFsTGVmdCk7XHJcblx0XHRcdFx0XHQvLyBNYWtlIGN1cnJlbnQgbGVmdCB0aGUgbmV3IGFwZXguXHJcblx0XHRcdFx0XHRwb3J0YWxBcGV4ID0gcG9ydGFsTGVmdDtcclxuXHRcdFx0XHRcdGFwZXhJbmRleCA9IGxlZnRJbmRleDtcclxuXHRcdFx0XHRcdC8vIFJlc2V0IHBvcnRhbFxyXG5cdFx0XHRcdFx0cG9ydGFsTGVmdCA9IHBvcnRhbEFwZXg7XHJcblx0XHRcdFx0XHRwb3J0YWxSaWdodCA9IHBvcnRhbEFwZXg7XHJcblx0XHRcdFx0XHRsZWZ0SW5kZXggPSBhcGV4SW5kZXg7XHJcblx0XHRcdFx0XHRyaWdodEluZGV4ID0gYXBleEluZGV4O1xyXG5cdFx0XHRcdFx0Ly8gUmVzdGFydCBzY2FuXHJcblx0XHRcdFx0XHRpID0gYXBleEluZGV4O1xyXG5cdFx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBVcGRhdGUgbGVmdCB2ZXJ0ZXguXHJcblx0XHRcdGlmICh0aGlzLl90cmlhcmVhMihwb3J0YWxBcGV4LCBwb3J0YWxMZWZ0LCBsZWZ0KSA8PSAwLjApIHtcclxuXHRcdFx0XHRpZiAodGhpcy5fdmVxdWFsKHBvcnRhbEFwZXgsIHBvcnRhbExlZnQpIHx8IHRoaXMuX3RyaWFyZWEyKHBvcnRhbEFwZXgsIHBvcnRhbFJpZ2h0LCBsZWZ0KSA+IDAuMCkge1xyXG5cdFx0XHRcdFx0Ly8gVGlnaHRlbiB0aGUgZnVubmVsLlxyXG5cdFx0XHRcdFx0cG9ydGFsTGVmdCA9IGxlZnQ7XHJcblx0XHRcdFx0XHRsZWZ0SW5kZXggPSBpO1xyXG5cdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHQvLyBMZWZ0IG92ZXIgcmlnaHQsIGluc2VydCByaWdodCB0byBwYXRoIGFuZCByZXN0YXJ0IHNjYW4gZnJvbSBwb3J0YWwgcmlnaHQgcG9pbnQuXHJcblx0XHRcdFx0XHRwdHMucHVzaChwb3J0YWxSaWdodCk7XHJcblx0XHRcdFx0XHQvLyBNYWtlIGN1cnJlbnQgcmlnaHQgdGhlIG5ldyBhcGV4LlxyXG5cdFx0XHRcdFx0cG9ydGFsQXBleCA9IHBvcnRhbFJpZ2h0O1xyXG5cdFx0XHRcdFx0YXBleEluZGV4ID0gcmlnaHRJbmRleDtcclxuXHRcdFx0XHRcdC8vIFJlc2V0IHBvcnRhbFxyXG5cdFx0XHRcdFx0cG9ydGFsTGVmdCA9IHBvcnRhbEFwZXg7XHJcblx0XHRcdFx0XHRwb3J0YWxSaWdodCA9IHBvcnRhbEFwZXg7XHJcblx0XHRcdFx0XHRsZWZ0SW5kZXggPSBhcGV4SW5kZXg7XHJcblx0XHRcdFx0XHRyaWdodEluZGV4ID0gYXBleEluZGV4O1xyXG5cdFx0XHRcdFx0Ly8gUmVzdGFydCBzY2FuXHJcblx0XHRcdFx0XHRpID0gYXBleEluZGV4O1xyXG5cdFx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKChwdHMubGVuZ3RoID09PSAwKSB8fCAoIXRoaXMuX3ZlcXVhbChwdHNbcHRzLmxlbmd0aCAtIDFdLCBwb3J0YWxzW3BvcnRhbHMubGVuZ3RoIC0gMV0ubGVmdCkpKSB7XHJcblx0XHRcdC8vIEFwcGVuZCBsYXN0IHBvaW50IHRvIHBhdGguXHJcblx0XHRcdHB0cy5wdXNoKHBvcnRhbHNbcG9ydGFscy5sZW5ndGggLSAxXS5sZWZ0KTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLnBhdGggPSBwdHM7XHJcblx0XHRyZXR1cm4gcHRzO1xyXG5cdH1cclxufSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IENoYW5uZWw7IiwidmFyIENsYXNzID0gcmVxdWlyZShcImFiaXRib2xcIik7XHJcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcclxudmFyIEFzdGFyID0gcmVxdWlyZShcIi4vQXN0YXIuanNcIik7XHJcbnZhciBDaGFubmVsID0gcmVxdWlyZShcIi4vQ2hhbm5lbC5qc1wiKTtcclxuXHJcbi8qKlxyXG4gKiBUaGlzIGNvbXBvbmVudCBnZW5lcmF0ZXMgc2NyZWVuc2hvdHMgb2YgM0QgbW9kZWxzLCBpbiBvcmRlciB0byBwcmV2aWV3IHRoZW0gd2hlbiB0aGV5IGFyZSByZW5kZXJlZC5cclxuICpcclxuICogQGNsYXNzIEZvY3VzM0RcclxuICogQGNvbnN0cnVjdG9yXHJcbiAqL1xyXG5cclxudmFyIE5hdmlnYXRpb24gPSBDbGFzcy4kZXh0ZW5kKHtcclxuICAgIF9faW5pdF9fOiBmdW5jdGlvbigpIHtcclxuICAgICAgICB0aGlzLnpvbmVOb2RlcyA9IHt9O1xyXG4gICAgICAgIHRoaXMuYXN0YXIgPSBuZXcgQXN0YXIoKTtcclxuICAgIH0sXHJcbiBcclxuXHRidWlsZE5vZGVzOiBmdW5jdGlvbiAobWVzaCkge1xyXG5cdFx0dmFyIG5hdmlnYXRpb25NZXNoID0gdGhpcy5fYnVpbGROYXZpZ2F0aW9uTWVzaChtZXNoLmdlb21ldHJ5KTtcclxuXHJcblx0XHR2YXIgem9uZU5vZGVzID0gdGhpcy5fZ3JvdXBOYXZNZXNoKG5hdmlnYXRpb25NZXNoKTtcclxuXHJcblx0XHRyZXR1cm4gem9uZU5vZGVzO1xyXG5cdH0sXHJcblxyXG5cdHNldFpvbmVEYXRhOiBmdW5jdGlvbiAoem9uZSwgZGF0YSkge1xyXG5cdFx0dGhpcy56b25lTm9kZXNbem9uZV0gPSBkYXRhO1xyXG5cdH0sXHJcblxyXG5cdGdldEdyb3VwOiBmdW5jdGlvbiAoem9uZSwgcG9zaXRpb24pIHtcclxuXHJcblx0XHRpZiAoIXRoaXMuem9uZU5vZGVzW3pvbmVdKSByZXR1cm4gbnVsbDtcclxuXHJcblx0XHR2YXIgY2xvc2VzdE5vZGVHcm91cCA9IG51bGw7XHJcblxyXG5cdFx0dmFyIGRpc3RhbmNlID0gSW5maW5pdHk7XHJcblxyXG5cdFx0Xy5lYWNoKHRoaXMuem9uZU5vZGVzW3pvbmVdLmdyb3VwcywgZnVuY3Rpb24gKGdyb3VwLCBpbmRleCkge1xyXG5cdFx0XHRfLmVhY2goZ3JvdXAsIGZ1bmN0aW9uIChub2RlKSB7XHJcblx0XHRcdFx0dmFyIG1lYXN1cmVkRGlzdGFuY2UgPSBCQUJZTE9OLlZlY3RvcjMuRGlzdGFuY2VTcXVhcmVkKG5vZGUuY2VudHJvaWQsIHBvc2l0aW9uKTtcclxuXHRcdFx0XHRpZiAobWVhc3VyZWREaXN0YW5jZSA8IGRpc3RhbmNlKSB7XHJcblx0XHRcdFx0XHRjbG9zZXN0Tm9kZUdyb3VwID0gaW5kZXg7XHJcblx0XHRcdFx0XHRkaXN0YW5jZSA9IG1lYXN1cmVkRGlzdGFuY2U7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdHJldHVybiBjbG9zZXN0Tm9kZUdyb3VwO1xyXG5cdH0sXHJcblxyXG5cdGdldFJhbmRvbU5vZGU6IGZ1bmN0aW9uICh6b25lLCBncm91cCwgbmVhclBvc2l0aW9uLCBuZWFyUmFuZ2UpIHtcclxuXHJcblx0XHRpZiAoIXRoaXMuem9uZU5vZGVzW3pvbmVdKSByZXR1cm4gbmV3IEJBQllMT04uVmVjdG9yMygpO1xyXG5cclxuXHRcdG5lYXJQb3NpdGlvbiA9IG5lYXJQb3NpdGlvbiB8fCBudWxsO1xyXG5cdFx0bmVhclJhbmdlID0gbmVhclJhbmdlIHx8IDA7XHJcblxyXG5cdFx0dmFyIGNhbmRpZGF0ZXMgPSBbXTtcclxuXHJcblx0XHR2YXIgcG9seWdvbnMgPSB0aGlzLnpvbmVOb2Rlc1t6b25lXS5ncm91cHNbZ3JvdXBdO1xyXG5cclxuXHRcdF8uZWFjaChwb2x5Z29ucywgZnVuY3Rpb24gKHApIHtcclxuXHRcdFx0aWYgKG5lYXJQb3NpdGlvbiAmJiBuZWFyUmFuZ2UpIHtcclxuXHRcdFx0XHRpZiAoQkFCWUxPTi5WZWN0b3IzLkRpc3RhbmNlU3F1YXJlZChuZWFyUG9zaXRpb24sIHAuY2VudHJvaWQpIDwgbmVhclJhbmdlICogbmVhclJhbmdlKSB7XHJcblx0XHRcdFx0XHRjYW5kaWRhdGVzLnB1c2gocC5jZW50cm9pZCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGNhbmRpZGF0ZXMucHVzaChwLmNlbnRyb2lkKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0cmV0dXJuIF8uc2FtcGxlKGNhbmRpZGF0ZXMpIHx8IG5ldyBCQUJZTE9OLlZlY3RvcjMoKTtcclxuXHR9LFxyXG5cclxuXHRwcm9qZWN0T25OYXZtZXNoOiBmdW5jdGlvbiAocG9zaXRpb24sIHpvbmUsIGdyb3VwKSB7XHJcblx0XHR2YXIgYWxsTm9kZXMgPSB0aGlzLnpvbmVOb2Rlc1t6b25lXS5ncm91cHNbZ3JvdXBdO1xyXG5cdFx0dmFyIHZlcnRpY2VzID0gdGhpcy56b25lTm9kZXNbem9uZV0udmVydGljZXM7XHJcblxyXG5cdFx0dmFyIGNsb3Nlc3ROb2RlID0gbnVsbDtcclxuXHRcdHZhciBkaXN0YW5jZSA9IEluZmluaXR5O1xyXG5cdFx0dmFyIGZpbmFsUHJvaiA9IG51bGwsIHByb2ogPSBudWxsO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYWxsTm9kZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dmFyIG5vZGUgPSBhbGxOb2Rlc1tpXTtcclxuXHJcblx0XHRcdHZhciBwcm9qID0gdGhpcy5fZ2V0UHJvamVjdGlvbk9uTm9kZShwb3NpdGlvbiwgbm9kZSwgdmVydGljZXMpO1xyXG5cdFx0XHR2YXIgbWVhc3VyZWREaXN0YW5jZSA9IEJBQllMT04uVmVjdG9yMy5EaXN0YW5jZVNxdWFyZWQocHJvaiwgcG9zaXRpb24pO1xyXG5cclxuXHRcdFx0aWYgKG1lYXN1cmVkRGlzdGFuY2UgPCBkaXN0YW5jZSkge1xyXG5cdFx0XHRcdGRpc3RhbmNlID0gbWVhc3VyZWREaXN0YW5jZTtcclxuXHRcdFx0XHQvL3RoaXMubWVzaGVzWzNdLnBvc2l0aW9uLmNvcHlGcm9tKHByb2opO1xyXG5cdFx0XHRcdGZpbmFsUHJvaiA9IHByb2o7XHJcblx0XHRcdFx0Y2xvc2VzdE5vZGUgPSBub2RlO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBmaW5hbFByb2o7XHJcblx0fSxcclxuXHJcblx0X2dldFByb2plY3Rpb25Pbk5vZGU6IGZ1bmN0aW9uKHBvc2l0aW9uLCBub2RlLCB2ZXJ0aWNlcykge1xyXG5cclxuXHRcdHZhciBBID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBub2RlLnZlcnRleElkc1swXSk7XHJcblx0XHR2YXIgQiA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgbm9kZS52ZXJ0ZXhJZHNbMV0pO1xyXG5cdFx0dmFyIEMgPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIG5vZGUudmVydGV4SWRzWzJdKTtcclxuXHRcdHZhciB1ID0gQi5zdWJ0cmFjdChBKTtcclxuXHQgICAgdmFyIHYgPSBDLnN1YnRyYWN0KEEpO1xyXG5cdCAgICB2YXIgbiA9IEJBQllMT04uVmVjdG9yMy5Dcm9zcyh1LCB2KS5ub3JtYWxpemUoKTtcclxuXHQgICAgXHJcblx0ICAgIHZhciBwbGFuZSA9IHtcclxuXHQgICAgXHRub3JtYWw6IG4sXHJcblx0ICAgIFx0ZDogLUEuZG90KG4pXHJcblx0ICAgIH07XHJcblx0ICAgIHZhciBwID0gcG9zaXRpb24ucHJvamVjdE9uUGxhbmUocGxhbmUpO1xyXG5cdFx0Ly8gQ29tcHV0ZSBiYXJ5Y2VudHJpYyBjb29yZGluYXRlcyAodSwgdiwgdykgZm9yXHJcblx0XHQvLyBwb2ludCBwIHdpdGggcmVzcGVjdCB0byB0cmlhbmdsZSAoYSwgYiwgYylcclxuXHRcdHZhciBiYXJ5Y2VudHJpYyA9IGZ1bmN0aW9uKHAsIGEsIGIsIGMpIHtcclxuXHRcdFx0dmFyIHJldCA9IHt9O1xyXG5cclxuXHRcdCAgICB2YXIgdjAgPSBjLnN1YnRyYWN0KGEpLCBcclxuXHRcdCAgICBcdHYxID0gYi5zdWJ0cmFjdChhKSxcclxuXHRcdCAgICBcdHYyID0gcC5zdWJ0cmFjdChhKTtcclxuXHJcblx0XHQgICAgdmFyIGQwMCA9IHYwLmRvdCh2MCk7XHJcblx0XHQgICAgdmFyIGQwMSA9IHYwLmRvdCh2MSk7XHJcblx0XHQgICAgdmFyIGQwMiA9IHYwLmRvdCh2Mik7XHJcblx0XHQgICAgdmFyIGQxMSA9IHYxLmRvdCh2MSk7XHJcblx0XHQgICAgdmFyIGQxMiA9IHYxLmRvdCh2Mik7XHJcblx0XHQgICAgdmFyIGRlbm9tID0gZDAwICogZDExIC0gZDAxICogZDAxO1xyXG5cdFx0ICAgIHJldC51ID0gKGQxMSAqIGQwMiAtIGQwMSAqIGQxMikgLyBkZW5vbTtcclxuXHRcdCAgICByZXQudiA9IChkMDAgKiBkMTIgLSBkMDEgKiBkMDIpIC8gZGVub207XHJcblx0XHQgICAgcmV0LncgPSAxIC0gcmV0LnUgLSByZXQudjtcclxuXHJcblx0XHQgICAgcmV0dXJuIHJldDtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgYmFyeSA9IGJhcnljZW50cmljKHAsIEEsIEIsIEMpO1xyXG5cclxuXHRcdGJhcnkudSA9IE1hdGgubWluKE1hdGgubWF4KGJhcnkudSwgMCksIDEpO1xyXG5cdFx0YmFyeS52ID0gTWF0aC5taW4oTWF0aC5tYXgoYmFyeS52LCAwKSwgMSk7XHJcblxyXG5cdFx0aWYgKGJhcnkudSArIGJhcnkudiA+PSAxKSB7XHJcblx0XHRcdHZhciBzdW0gPSBiYXJ5LnUgKyBiYXJ5LnY7XHJcblx0XHRcdGJhcnkudSAvPSBzdW07XHJcblx0XHRcdGJhcnkudiAvPSBzdW07XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIHByb2ogPSBBLmFkZChCLnN1YnRyYWN0KEEpLnNjYWxlKGJhcnkudikuYWRkKEMuc3VidHJhY3QoQSkuc2NhbGUoYmFyeS51KSkpO1xyXG5cclxuXHRcdHJldHVybiBwcm9qO1xyXG5cdH0sXHJcblxyXG5cdGZpbmRQYXRoOiBmdW5jdGlvbiAoc3RhcnRQb3NpdGlvbiwgdGFyZ2V0UG9zaXRpb24sIHpvbmUsIGdyb3VwKSB7XHJcblxyXG5cdFx0dmFyIGFsbE5vZGVzID0gdGhpcy56b25lTm9kZXNbem9uZV0uZ3JvdXBzW2dyb3VwXTtcclxuXHRcdHZhciB2ZXJ0aWNlcyA9IHRoaXMuem9uZU5vZGVzW3pvbmVdLnZlcnRpY2VzO1xyXG5cclxuXHRcdHZhciBjbG9zZXN0Tm9kZSA9IG51bGw7XHJcblx0XHR2YXIgZGlzdGFuY2UgPSBJbmZpbml0eTtcclxuXHJcblx0XHRhbGxOb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XHJcblx0XHRcdHZhciBtZWFzdXJlZERpc3RhbmNlID0gQkFCWUxPTi5WZWN0b3IzLkRpc3RhbmNlU3F1YXJlZChub2RlLmNlbnRyb2lkLCBzdGFydFBvc2l0aW9uKTtcclxuXHRcdFx0aWYgKG1lYXN1cmVkRGlzdGFuY2UgPCBkaXN0YW5jZSkge1xyXG5cdFx0XHRcdGNsb3Nlc3ROb2RlID0gbm9kZTtcclxuXHRcdFx0XHRkaXN0YW5jZSA9IG1lYXN1cmVkRGlzdGFuY2U7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHJcblx0XHR2YXIgZmFydGhlc3ROb2RlID0gbnVsbDtcclxuXHRcdGRpc3RhbmNlID0gSW5maW5pdHk7XHJcblxyXG5cdFx0YWxsTm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xyXG5cdFx0XHR2YXIgbWVhc3VyZWREaXN0YW5jZSA9IEJBQllMT04uVmVjdG9yMy5EaXN0YW5jZVNxdWFyZWQobm9kZS5jZW50cm9pZCwgdGFyZ2V0UG9zaXRpb24pO1xyXG5cdFx0XHRpZiAobWVhc3VyZWREaXN0YW5jZSA8IGRpc3RhbmNlICYmXHJcblx0XHRcdFx0dGhpcy5faXNWZWN0b3JJblBvbHlnb24odGFyZ2V0UG9zaXRpb24sIG5vZGUsIHZlcnRpY2VzKSkge1xyXG5cdFx0XHRcdGZhcnRoZXN0Tm9kZSA9IG5vZGU7XHJcblx0XHRcdFx0ZGlzdGFuY2UgPSBtZWFzdXJlZERpc3RhbmNlO1xyXG5cdFx0XHR9XHJcblx0XHR9LmJpbmQodGhpcykpO1xyXG5cclxuXHRcdC8vIElmIHdlIGNhbid0IGZpbmQgYW55IG5vZGUsIGp1c3QgZ28gc3RyYWlnaHQgdG8gdGhlIHRhcmdldFxyXG5cdFx0aWYgKCFjbG9zZXN0Tm9kZSB8fCAhZmFydGhlc3ROb2RlKSB7XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBwYXRocyA9IHRoaXMuYXN0YXIuc2VhcmNoKGFsbE5vZGVzLCBjbG9zZXN0Tm9kZSwgZmFydGhlc3ROb2RlKTtcclxuXHJcblx0XHR2YXIgZ2V0UG9ydGFsRnJvbVRvID0gZnVuY3Rpb24gKGEsIGIpIHtcclxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhLm5laWdoYm91cnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0XHRpZiAoYS5uZWlnaGJvdXJzW2ldID09PSBiLmlkKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gYS5wb3J0YWxzW2ldO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fTtcclxuXHJcblx0XHQvLyBXZSBnb3QgdGhlIGNvcnJpZG9yXHJcblx0XHQvLyBOb3cgcHVsbCB0aGUgcm9wZVxyXG5cclxuXHRcdHZhciBjaGFubmVsID0gbmV3IENoYW5uZWwoKTtcclxuXHJcblx0XHRjaGFubmVsLnB1c2goc3RhcnRQb3NpdGlvbik7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHR2YXIgcG9seWdvbiA9IHBhdGhzW2ldO1xyXG5cclxuXHRcdFx0dmFyIG5leHRQb2x5Z29uID0gcGF0aHNbaSArIDFdO1xyXG5cclxuXHRcdFx0aWYgKG5leHRQb2x5Z29uKSB7XHJcblx0XHRcdFx0dmFyIHBvcnRhbHMgPSBnZXRQb3J0YWxGcm9tVG8ocG9seWdvbiwgbmV4dFBvbHlnb24pO1xyXG5cdFx0XHRcdGNoYW5uZWwucHVzaChcclxuXHRcdFx0XHRcdHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgcG9ydGFsc1swXSksXHJcblx0XHRcdFx0XHR0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIHBvcnRhbHNbMV0pXHJcblx0XHRcdFx0KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdH1cclxuXHJcblx0XHRjaGFubmVsLnB1c2godGFyZ2V0UG9zaXRpb24pO1xyXG5cclxuXHRcdGNoYW5uZWwuc3RyaW5nUHVsbCgpO1xyXG5cclxuXHJcblx0XHR2YXIgdmVjdG9ycyA9IFtdO1xyXG5cclxuXHRcdGNoYW5uZWwucGF0aC5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7XHJcblx0XHRcdHZhciB2ZWMgPSBuZXcgQkFCWUxPTi5WZWN0b3IzKGMueCwgYy55LCBjLnopO1xyXG5cclxuXHRcdFx0Ly8gY29uc29sZS5sb2codmVjLmNsb25lKCkuc3ViKHN0YXJ0UG9zaXRpb24pLmxlbmd0aCgpKTtcclxuXHJcblx0XHRcdC8vIEVuc3VyZSB0aGUgaW50ZXJtZWRpYXRlIHN0ZXBzIGFyZW4ndCB0b28gY2xvc2UgdG8gdGhlIHN0YXJ0IHBvc2l0aW9uXHJcblx0XHRcdC8vIHZhciBkaXN0ID0gdmVjLmNsb25lKCkuc3ViKHN0YXJ0UG9zaXRpb24pLmxlbmd0aFNxKCk7XHJcblx0XHRcdC8vIGlmIChkaXN0ID4gMC4wMSAqIDAuMDEpIHtcclxuXHRcdFx0XHR2ZWN0b3JzLnB1c2godmVjKTtcclxuXHRcdFx0Ly8gfVxyXG5cclxuXHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBXZSBkb24ndCBuZWVkIHRoZSBmaXJzdCBvbmUsIGFzIHdlIGFscmVhZHkga25vdyBvdXIgc3RhcnQgcG9zaXRpb25cclxuXHRcdHZlY3RvcnMuc2hpZnQoKTtcclxuXHJcblx0XHRyZXR1cm4gdmVjdG9ycztcclxuXHR9LFxyXG5cclxuXHRfaXNQb2ludEluUG9seTogZnVuY3Rpb24gKHBvbHksIHB0KSB7XHJcblx0XHRmb3IgKHZhciBjID0gZmFsc2UsIGkgPSAtMSwgbCA9IHBvbHkubGVuZ3RoLCBqID0gbCAtIDE7ICsraSA8IGw7IGogPSBpKVxyXG5cdFx0XHQoKHBvbHlbaV0ueiA8PSBwdC56ICYmIHB0LnogPCBwb2x5W2pdLnopIHx8IChwb2x5W2pdLnogPD0gcHQueiAmJiBwdC56IDwgcG9seVtpXS56KSkgJiYgKHB0LnggPCAocG9seVtqXS54IC0gcG9seVtpXS54KSAqIChwdC56IC0gcG9seVtpXS56KSAvIChwb2x5W2pdLnogLSBwb2x5W2ldLnopICsgcG9seVtpXS54KSAmJiAoYyA9ICFjKTtcclxuXHRcdHJldHVybiBjO1xyXG5cdH0sXHJcblxyXG5cdF9pc1ZlY3RvckluUG9seWdvbjogZnVuY3Rpb24gKHZlY3RvciwgcG9seWdvbiwgdmVydGljZXMpIHtcclxuXHJcblx0XHQvLyByZWZlcmVuY2UgcG9pbnQgd2lsbCBiZSB0aGUgY2VudHJvaWQgb2YgdGhlIHBvbHlnb25cclxuXHRcdC8vIFdlIG5lZWQgdG8gcm90YXRlIHRoZSB2ZWN0b3IgYXMgd2VsbCBhcyBhbGwgdGhlIHBvaW50cyB3aGljaCB0aGUgcG9seWdvbiB1c2VzXHJcblxyXG5cdFx0dmFyIGNlbnRlciA9IHBvbHlnb24uY2VudHJvaWQ7XHJcblxyXG5cdFx0dmFyIGxvd2VzdFBvaW50ID0gMTAwMDAwO1xyXG5cdFx0dmFyIGhpZ2hlc3RQb2ludCA9IC0xMDAwMDA7XHJcblxyXG5cdFx0dmFyIHBvbHlnb25WZXJ0aWNlcyA9IFtdO1xyXG5cclxuXHRcdF8uZWFjaChwb2x5Z29uLnZlcnRleElkcywgZnVuY3Rpb24gKHZJZCkge1xyXG5cdFx0XHR2YXIgcG9pbnQgPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIHZJZCk7XHJcblx0XHRcdGxvd2VzdFBvaW50ID0gTWF0aC5taW4ocG9pbnQueSwgbG93ZXN0UG9pbnQpO1xyXG5cdFx0XHRoaWdoZXN0UG9pbnQgPSBNYXRoLm1heChwb2ludC55LCBoaWdoZXN0UG9pbnQpO1xyXG5cdFx0XHRwb2x5Z29uVmVydGljZXMucHVzaChwb2ludCk7XHJcblx0XHR9LmJpbmQodGhpcykpO1xyXG5cclxuXHRcdGlmICh2ZWN0b3IueSA8IGhpZ2hlc3RQb2ludCArIDAuNSAmJiB2ZWN0b3IueSA+IGxvd2VzdFBvaW50IC0gMC41ICYmXHJcblx0XHRcdHRoaXMuX2lzUG9pbnRJblBvbHkocG9seWdvblZlcnRpY2VzLCB2ZWN0b3IpKSB7XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGZhbHNlO1xyXG5cdH0sXHJcblxyXG5cdF9jb21wdXRlQ2VudHJvaWRzOiBmdW5jdGlvbiAoZ2VvbWV0cnkpIHtcclxuXHRcdHZhciBmLCBmbCwgZmFjZTtcclxuXHRcdHZhciBjZW50cm9pZHMgPSBbXTtcclxuXHRcdHZhciBpbmRpY2VzID0gZ2VvbWV0cnkuZ2V0SW5kaWNlcygpO1xyXG5cdFx0dmFyIHZlcnRpY2VzID0gZ2VvbWV0cnkuZ2V0VmVydGljZXNEYXRhKEJBQllMT04uVmVydGV4QnVmZmVyLlBvc2l0aW9uS2luZCk7XHJcblx0XHR2YXIgYyA9IG5ldyBCQUJZTE9OLlZlY3RvcjMoMCwgMCwgMCk7XHJcblxyXG5cdFx0Zm9yICggZiA9IDAsIGZsID0gaW5kaWNlcy5sZW5ndGg7IGYgPCBmbDsgZiArPSAzICkge1xyXG5cdFx0XHR2YXIgcDEgPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIGluZGljZXNbZl0pO1xyXG5cdFx0XHR2YXIgcDIgPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIGluZGljZXNbZisxXSk7XHJcblx0XHRcdHZhciBwMyA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgaW5kaWNlc1tmKzJdKTtcclxuXHJcblx0XHRcdGMuY29weUZyb21GbG9hdHMoIDAsIDAsIDAgKTtcclxuXHJcblx0XHRcdGMuYWRkSW5QbGFjZShwMSk7XHJcblx0XHRcdGMuYWRkSW5QbGFjZShwMik7XHJcblx0XHRcdGMuYWRkSW5QbGFjZShwMyk7XHJcblxyXG5cdFx0XHRjLnNjYWxlSW5QbGFjZSggMS8zICk7XHJcblxyXG5cdFx0XHRjZW50cm9pZHMucHVzaChjLmNsb25lKCkpO1xyXG5cdFx0fVxyXG5cdFx0Z2VvbWV0cnkuY2VudHJvaWRzID0gY2VudHJvaWRzO1xyXG5cdH0sXHJcblxyXG5cclxuICAgIF9yb3VuZE51bWJlcjogZnVuY3Rpb24gKG51bWJlciwgZGVjaW1hbHMpIHtcclxuICAgICAgICB2YXIgbmV3bnVtYmVyID0gbmV3IE51bWJlcihudW1iZXIgKyAnJykudG9GaXhlZChwYXJzZUludChkZWNpbWFscykpO1xyXG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KG5ld251bWJlcik7XHJcbiAgICB9LFxyXG5cclxuXHRfbWVyZ2VWZXJ0ZXhJZHM6IGZ1bmN0aW9uIChhTGlzdCwgYkxpc3QpIHtcclxuXHJcblx0XHR2YXIgc2hhcmVkVmVydGljZXMgPSBbXTtcclxuXHJcblx0XHRhTGlzdC5mb3JFYWNoKGZ1bmN0aW9uICh2SWQpIHtcclxuXHRcdFx0aWYgKF8uaW5jbHVkZXMoYkxpc3QsIHZJZCkpIHtcclxuXHRcdFx0XHRzaGFyZWRWZXJ0aWNlcy5wdXNoKHZJZCk7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHRcdGlmIChzaGFyZWRWZXJ0aWNlcy5sZW5ndGggPCAyKSByZXR1cm4gW107XHJcblxyXG5cdFx0Ly8gY29uc29sZS5sb2coXCJUUllJTkcgYUxpc3Q6XCIsIGFMaXN0LCBcIiwgYkxpc3Q6XCIsIGJMaXN0LCBcIiwgc2hhcmVkVmVydGljZXM6XCIsIHNoYXJlZFZlcnRpY2VzKTtcclxuXHJcblx0XHRpZiAoXy5pbmNsdWRlcyhzaGFyZWRWZXJ0aWNlcywgYUxpc3RbMF0pICYmIF8uaW5jbHVkZXMoc2hhcmVkVmVydGljZXMsIGFMaXN0W2FMaXN0Lmxlbmd0aCAtIDFdKSkge1xyXG5cdFx0XHQvLyBWZXJ0aWNlcyBvbiBib3RoIGVkZ2VzIGFyZSBiYWQsIHNvIHNoaWZ0IHRoZW0gb25jZSB0byB0aGUgbGVmdFxyXG5cdFx0XHRhTGlzdC5wdXNoKGFMaXN0LnNoaWZ0KCkpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChfLmluY2x1ZGVzKHNoYXJlZFZlcnRpY2VzLCBiTGlzdFswXSkgJiYgXy5pbmNsdWRlcyhzaGFyZWRWZXJ0aWNlcywgYkxpc3RbYkxpc3QubGVuZ3RoIC0gMV0pKSB7XHJcblx0XHRcdC8vIFZlcnRpY2VzIG9uIGJvdGggZWRnZXMgYXJlIGJhZCwgc28gc2hpZnQgdGhlbSBvbmNlIHRvIHRoZSBsZWZ0XHJcblx0XHRcdGJMaXN0LnB1c2goYkxpc3Quc2hpZnQoKSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQWdhaW4hXHJcblx0XHRzaGFyZWRWZXJ0aWNlcyA9IFtdO1xyXG5cclxuXHRcdGFMaXN0LmZvckVhY2goZnVuY3Rpb24gKHZJZCkge1xyXG5cdFx0XHRpZiAoXy5pbmNsdWRlcyhiTGlzdCwgdklkKSkge1xyXG5cdFx0XHRcdHNoYXJlZFZlcnRpY2VzLnB1c2godklkKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0dmFyIGNsb2Nrd2lzZU1vc3RTaGFyZWRWZXJ0ZXggPSBzaGFyZWRWZXJ0aWNlc1sxXTtcclxuXHRcdHZhciBjb3VudGVyQ2xvY2t3aXNlTW9zdFNoYXJlZFZlcnRleCA9IHNoYXJlZFZlcnRpY2VzWzBdO1xyXG5cclxuXHJcblx0XHR2YXIgY0xpc3QgPSBfLmNsb25lKGFMaXN0KTtcclxuXHRcdHdoaWxlIChjTGlzdFswXSAhPT0gY2xvY2t3aXNlTW9zdFNoYXJlZFZlcnRleCkge1xyXG5cdFx0XHRjTGlzdC5wdXNoKGNMaXN0LnNoaWZ0KCkpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBjID0gMDtcclxuXHJcblx0XHR2YXIgdGVtcCA9IF8uY2xvbmUoYkxpc3QpO1xyXG5cdFx0d2hpbGUgKHRlbXBbMF0gIT09IGNvdW50ZXJDbG9ja3dpc2VNb3N0U2hhcmVkVmVydGV4KSB7XHJcblx0XHRcdHRlbXAucHVzaCh0ZW1wLnNoaWZ0KCkpO1xyXG5cclxuXHRcdFx0aWYgKGMrKyA+IDEwKSBkZWJ1Z2dlcjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBTaGF2ZVxyXG5cdFx0dGVtcC5zaGlmdCgpO1xyXG5cdFx0dGVtcC5wb3AoKTtcclxuXHJcblx0XHRjTGlzdCA9IGNMaXN0LmNvbmNhdCh0ZW1wKTtcclxuXHJcblx0XHQvLyBjb25zb2xlLmxvZyhcImFMaXN0OlwiLCBhTGlzdCwgXCIsIGJMaXN0OlwiLCBiTGlzdCwgXCIsIGNMaXN0OlwiLCBjTGlzdCwgXCIsIHNoYXJlZFZlcnRpY2VzOlwiLCBzaGFyZWRWZXJ0aWNlcyk7XHJcblxyXG5cdFx0cmV0dXJuIGNMaXN0O1xyXG5cdH0sXHJcblxyXG5cdF9zZXRQb2x5Z29uQ2VudHJvaWQ6IGZ1bmN0aW9uIChwb2x5Z29uLCBuYXZpZ2F0aW9uTWVzaCkge1xyXG5cdFx0dmFyIHN1bSA9IG5ldyBCQUJZTE9OLlZlY3RvcjMoMCwgMCwgMCk7XHJcblxyXG5cdFx0dmFyIHZlcnRpY2VzID0gbmF2aWdhdGlvbk1lc2gudmVydGljZXM7XHJcblxyXG5cdFx0Xy5lYWNoKHBvbHlnb24udmVydGV4SWRzLCBmdW5jdGlvbiAodklkKSB7XHJcblx0XHRcdHN1bS54ICs9IHZlcnRpY2VzW3ZJZCozXTtcclxuXHRcdFx0c3VtLnkgKz0gdmVydGljZXNbdklkKjMrMV07XHJcblx0XHRcdHN1bS56ICs9IHZlcnRpY2VzW3ZJZCozKzJdO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0c3VtLnNjYWxlSW5QbGFjZSgxL3BvbHlnb24udmVydGV4SWRzLmxlbmd0aCk7XHJcblxyXG5cdFx0cG9seWdvbi5jZW50cm9pZC5jb3B5RnJvbShzdW0pO1xyXG5cdH0sXHJcblxyXG5cdGdldFZlY3RvckZyb206IGZ1bmN0aW9uICh2ZXJ0aWNlcywgaWQsIF92ZWN0b3IpIHtcclxuXHRcdGlmIChfdmVjdG9yKSB7XHJcblx0XHRcdF92ZWN0b3IuY29weUZyb21GbG9hdHModmVydGljZXNbaWQqM10sIHZlcnRpY2VzW2lkKjMrMV0sIHZlcnRpY2VzW2lkKjMrMl0pO1xyXG5cdFx0XHRyZXR1cm4gX3ZlY3RvcjtcclxuXHRcdH1cclxuXHRcdHJldHVybiBuZXcgQkFCWUxPTi5WZWN0b3IzKHZlcnRpY2VzW2lkKjNdLCB2ZXJ0aWNlc1tpZCozKzFdLCB2ZXJ0aWNlc1tpZCozKzJdKTtcclxuXHR9LFxyXG5cclxuXHRfY2xlYW5Qb2x5Z29uOiBmdW5jdGlvbiAocG9seWdvbiwgbmF2aWdhdGlvbk1lc2gpIHtcclxuXHJcblx0XHR2YXIgbmV3VmVydGV4SWRzID0gW107XHJcblxyXG5cdFx0dmFyIHZlcnRpY2VzID0gbmF2aWdhdGlvbk1lc2gudmVydGljZXM7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwb2x5Z29uLnZlcnRleElkcy5sZW5ndGg7IGkrKykge1xyXG5cclxuXHRcdFx0dmFyIHZlcnRleCA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgcG9seWdvbi52ZXJ0ZXhJZHNbaV0pO1xyXG5cclxuXHRcdFx0dmFyIG5leHRWZXJ0ZXhJZCwgcHJldmlvdXNWZXJ0ZXhJZDtcclxuXHRcdFx0dmFyIG5leHRWZXJ0ZXgsIHByZXZpb3VzVmVydGV4O1xyXG5cclxuXHRcdFx0Ly8gY29uc29sZS5sb2coXCJuZXh0VmVydGV4OiBcIiwgbmV4dFZlcnRleCk7XHJcblxyXG5cdFx0XHRpZiAoaSA9PT0gMCkge1xyXG5cdFx0XHRcdG5leHRWZXJ0ZXhJZCA9IHBvbHlnb24udmVydGV4SWRzWzFdO1xyXG5cdFx0XHRcdHByZXZpb3VzVmVydGV4SWQgPSBwb2x5Z29uLnZlcnRleElkc1twb2x5Z29uLnZlcnRleElkcy5sZW5ndGggLSAxXTtcclxuXHRcdFx0fSBlbHNlIGlmIChpID09PSBwb2x5Z29uLnZlcnRleElkcy5sZW5ndGggLSAxKSB7XHJcblx0XHRcdFx0bmV4dFZlcnRleElkID0gcG9seWdvbi52ZXJ0ZXhJZHNbMF07XHJcblx0XHRcdFx0cHJldmlvdXNWZXJ0ZXhJZCA9IHBvbHlnb24udmVydGV4SWRzW3BvbHlnb24udmVydGV4SWRzLmxlbmd0aCAtIDJdO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdG5leHRWZXJ0ZXhJZCA9IHBvbHlnb24udmVydGV4SWRzW2kgKyAxXTtcclxuXHRcdFx0XHRwcmV2aW91c1ZlcnRleElkID0gcG9seWdvbi52ZXJ0ZXhJZHNbaSAtIDFdO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRuZXh0VmVydGV4ID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBuZXh0VmVydGV4SWQpO1xyXG5cdFx0XHRwcmV2aW91c1ZlcnRleCA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgcHJldmlvdXNWZXJ0ZXhJZCk7XHJcblxyXG5cdFx0XHR2YXIgYSA9IG5leHRWZXJ0ZXguY2xvbmUoKS5zdWIodmVydGV4KTtcclxuXHRcdFx0dmFyIGIgPSBwcmV2aW91c1ZlcnRleC5jbG9uZSgpLnN1Yih2ZXJ0ZXgpO1xyXG5cclxuXHRcdFx0dmFyIGFuZ2xlID0gYS5hbmdsZVRvKGIpO1xyXG5cclxuXHRcdFx0Ly8gY29uc29sZS5sb2coYW5nbGUpO1xyXG5cclxuXHRcdFx0aWYgKGFuZ2xlID4gTWF0aC5QSSAtIDAuMDEgJiYgYW5nbGUgPCBNYXRoLlBJICsgMC4wMSkge1xyXG5cdFx0XHRcdC8vIFVubmVjY2VzYXJ5IHZlcnRleFxyXG5cdFx0XHRcdC8vIGNvbnNvbGUubG9nKFwiVW5uZWNjZXNhcnkgdmVydGV4OiBcIiwgcG9seWdvbi52ZXJ0ZXhJZHNbaV0pO1xyXG5cdFx0XHRcdC8vIGNvbnNvbGUubG9nKFwiQW5nbGUgYmV0d2VlbiBcIitwcmV2aW91c1ZlcnRleElkK1wiLCBcIitwb2x5Z29uLnZlcnRleElkc1tpXStcIiBcIituZXh0VmVydGV4SWQrXCIgd2FzOiBcIiwgYW5nbGUpO1xyXG5cclxuXHJcblx0XHRcdFx0Ly8gUmVtb3ZlIHRoZSBuZWlnaGJvdXJzIHdobyBoYWQgdGhpcyB2ZXJ0ZXhcclxuXHRcdFx0XHR2YXIgZ29vZE5laWdoYm91cnMgPSBbXTtcclxuXHRcdFx0XHRwb2x5Z29uLm5laWdoYm91cnMuZm9yRWFjaChmdW5jdGlvbiAobmVpZ2hib3VyKSB7XHJcblx0XHRcdFx0XHRpZiAoIV8uaW5jbHVkZXMobmVpZ2hib3VyLnZlcnRleElkcywgcG9seWdvbi52ZXJ0ZXhJZHNbaV0pKSB7XHJcblx0XHRcdFx0XHRcdGdvb2ROZWlnaGJvdXJzLnB1c2gobmVpZ2hib3VyKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0XHRwb2x5Z29uLm5laWdoYm91cnMgPSBnb29kTmVpZ2hib3VycztcclxuXHJcblxyXG5cdFx0XHRcdC8vIFRPRE8gY2xlYW51cCB0aGUgbGlzdCBvZiB2ZXJ0aWNlcyBhbmQgcmVidWlsZCB2ZXJ0ZXhJZHMgZm9yIGFsbCBwb2x5Z29uc1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdG5ld1ZlcnRleElkcy5wdXNoKHBvbHlnb24udmVydGV4SWRzW2ldKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdH1cclxuXHJcblx0XHQvLyBjb25zb2xlLmxvZyhcIk5ldyB2ZXJ0ZXhJZHM6IFwiLCBuZXdWZXJ0ZXhJZHMpO1xyXG5cclxuXHRcdHBvbHlnb24udmVydGV4SWRzID0gbmV3VmVydGV4SWRzO1xyXG5cclxuXHRcdHRoaXMuX3NldFBvbHlnb25DZW50cm9pZChwb2x5Z29uLCBuYXZpZ2F0aW9uTWVzaCk7XHJcblxyXG5cdH0sXHJcblxyXG5cdF9pc0NvbnZleDogZnVuY3Rpb24gKHBvbHlnb24sIG5hdmlnYXRpb25NZXNoKSB7XHJcblxyXG5cdFx0dmFyIHZlcnRpY2VzID0gbmF2aWdhdGlvbk1lc2gudmVydGljZXM7XHJcblxyXG5cdFx0aWYgKHBvbHlnb24udmVydGV4SWRzLmxlbmd0aCA8IDMpIHJldHVybiBmYWxzZTtcclxuXHJcblx0XHR2YXIgY29udmV4ID0gdHJ1ZTtcclxuXHJcblx0XHR2YXIgdG90YWwgPSAwO1xyXG5cclxuXHRcdHZhciByZXN1bHRzID0gW107XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwb2x5Z29uLnZlcnRleElkcy5sZW5ndGg7IGkrKykge1xyXG5cclxuXHRcdFx0dmFyIHZlcnRleCA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgcG9seWdvbi52ZXJ0ZXhJZHNbaV0pO1xyXG5cclxuXHRcdFx0dmFyIG5leHRWZXJ0ZXgsIHByZXZpb3VzVmVydGV4O1xyXG5cclxuXHRcdFx0Ly8gY29uc29sZS5sb2coXCJuZXh0VmVydGV4OiBcIiwgbmV4dFZlcnRleCk7XHJcblxyXG5cdFx0XHRpZiAoaSA9PT0gMCkge1xyXG5cdFx0XHRcdG5leHRWZXJ0ZXggPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIHBvbHlnb24udmVydGV4SWRzWzFdKTtcclxuXHRcdFx0XHRwcmV2aW91c1ZlcnRleCA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgcG9seWdvbi52ZXJ0ZXhJZHNbcG9seWdvbi52ZXJ0ZXhJZHMubGVuZ3RoIC0gMV0pO1xyXG5cdFx0XHR9IGVsc2UgaWYgKGkgPT09IHBvbHlnb24udmVydGV4SWRzLmxlbmd0aCAtIDEpIHtcclxuXHRcdFx0XHRuZXh0VmVydGV4ID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBwb2x5Z29uLnZlcnRleElkc1swXSk7XHJcblx0XHRcdFx0cHJldmlvdXNWZXJ0ZXggPSB0aGlzLmdldFZlY3RvckZyb20odmVydGljZXMsIHBvbHlnb24udmVydGV4SWRzW3BvbHlnb24udmVydGV4SWRzLmxlbmd0aCAtIDJdKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRuZXh0VmVydGV4ID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBwb2x5Z29uLnZlcnRleElkc1tpICsgMV0pO1xyXG5cdFx0XHRcdHByZXZpb3VzVmVydGV4ID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBwb2x5Z29uLnZlcnRleElkc1tpIC0gMV0pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgYSA9IG5leHRWZXJ0ZXguY2xvbmUoKS5zdWIodmVydGV4KTtcclxuXHRcdFx0dmFyIGIgPSBwcmV2aW91c1ZlcnRleC5jbG9uZSgpLnN1Yih2ZXJ0ZXgpO1xyXG5cclxuXHRcdFx0dmFyIGFuZ2xlID0gYS5hbmdsZVRvKGIpO1xyXG5cdFx0XHR0b3RhbCArPSBhbmdsZTtcclxuXHJcblx0XHRcdC8vIGNvbnNvbGUubG9nKGFuZ2xlKTtcclxuXHRcdFx0aWYgKGFuZ2xlID09PSBNYXRoLlBJIHx8IGFuZ2xlID09PSAwKSByZXR1cm4gZmFsc2U7XHJcblxyXG5cdFx0XHR2YXIgciA9IEJBQllMT04uVmVjdG9yMy5Dcm9zcyhhLCBiKS55O1xyXG5cdFx0XHRyZXN1bHRzLnB1c2gocik7XHJcblx0XHRcdC8vIGNvbnNvbGUubG9nKFwicHVzaGVkOiBcIiwgcik7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gaWYgKCB0b3RhbCA+IChwb2x5Z29uLnZlcnRleElkcy5sZW5ndGgtMikqTWF0aC5QSSApIHJldHVybiBmYWxzZTtcclxuXHJcblx0XHRyZXN1bHRzLmZvckVhY2goZnVuY3Rpb24gKHIpIHtcclxuXHRcdFx0aWYgKHIgPT09IDApIGNvbnZleCA9IGZhbHNlO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKHJlc3VsdHNbMF0gPiAwKSB7XHJcblx0XHRcdHJlc3VsdHMuZm9yRWFjaChmdW5jdGlvbiAocikge1xyXG5cdFx0XHRcdGlmIChyIDwgMCkgY29udmV4ID0gZmFsc2U7XHJcblx0XHRcdH0pO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmVzdWx0cy5mb3JFYWNoKGZ1bmN0aW9uIChyKSB7XHJcblx0XHRcdFx0aWYgKHIgPiAwKSBjb252ZXggPSBmYWxzZTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gY29uc29sZS5sb2coXCJhbGxvd2VkOiBcIit0b3RhbCtcIiwgbWF4OiBcIisocG9seWdvbi52ZXJ0ZXhJZHMubGVuZ3RoLTIpKk1hdGguUEkpO1xyXG5cdFx0Ly8gaWYgKCB0b3RhbCA+IChwb2x5Z29uLnZlcnRleElkcy5sZW5ndGgtMikqTWF0aC5QSSApIGNvbnZleCA9IGZhbHNlO1xyXG5cclxuXHRcdC8vIGNvbnNvbGUubG9nKFwiQ29udmV4OiBcIisoY29udmV4ID8gXCJ0cnVlXCI6IFwiZmFsc2VcIikpO1xyXG5cclxuXHJcblxyXG5cdFx0cmV0dXJuIGNvbnZleDtcclxuXHR9LFxyXG5cclxuXHRfYnVpbGRQb2x5Z29uR3JvdXBzOiBmdW5jdGlvbiAobmF2aWdhdGlvbk1lc2gpIHtcclxuXHJcblx0XHR2YXIgcG9seWdvbnMgPSBuYXZpZ2F0aW9uTWVzaC5wb2x5Z29ucztcclxuXHRcdHZhciB2ZXJ0aWNlcyA9IG5hdmlnYXRpb25NZXNoLnZlcnRpY2VzO1xyXG5cclxuXHRcdHZhciBwb2x5Z29uR3JvdXBzID0gW107XHJcblx0XHR2YXIgZ3JvdXBDb3VudCA9IDA7XHJcblxyXG5cdFx0dmFyIHNwcmVhZEdyb3VwSWQgPSBmdW5jdGlvbiAocG9seWdvbikge1xyXG5cdFx0XHRfLmVhY2gocG9seWdvbi5uZWlnaGJvdXJzLCBmdW5jdGlvbiAobmVpZ2hib3VyKSB7XHJcblx0XHRcdFx0aWYgKF8uaXNVbmRlZmluZWQobmVpZ2hib3VyLmdyb3VwKSkge1xyXG5cdFx0XHRcdFx0bmVpZ2hib3VyLmdyb3VwID0gcG9seWdvbi5ncm91cDtcclxuXHRcdFx0XHRcdHNwcmVhZEdyb3VwSWQobmVpZ2hib3VyKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0fTtcclxuXHJcblx0XHRfLmVhY2gocG9seWdvbnMsIGZ1bmN0aW9uIChwb2x5Z29uLCBpKSB7XHJcblxyXG5cdFx0XHRpZiAoXy5pc1VuZGVmaW5lZChwb2x5Z29uLmdyb3VwKSkge1xyXG5cdFx0XHRcdHBvbHlnb24uZ3JvdXAgPSBncm91cENvdW50Kys7XHJcblx0XHRcdFx0Ly8gU3ByZWFkIGl0XHJcblx0XHRcdFx0c3ByZWFkR3JvdXBJZChwb2x5Z29uKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKCFwb2x5Z29uR3JvdXBzW3BvbHlnb24uZ3JvdXBdKSBwb2x5Z29uR3JvdXBzW3BvbHlnb24uZ3JvdXBdID0gW107XHJcblxyXG5cdFx0XHRwb2x5Z29uR3JvdXBzW3BvbHlnb24uZ3JvdXBdLnB1c2gocG9seWdvbik7XHJcblx0XHR9KTtcclxuXHJcblx0XHRjb25zb2xlLmxvZyhcIkdyb3VwcyBidWlsdDogXCIsIHBvbHlnb25Hcm91cHMubGVuZ3RoKTtcclxuXHJcblx0XHRyZXR1cm4gcG9seWdvbkdyb3VwcztcclxuXHR9LFxyXG5cclxuXHRfYXJyYXlfaW50ZXJzZWN0OiBmdW5jdGlvbigpIHtcclxuXHRcdHZhciBpLCBhbGwsIHNob3J0ZXN0LCBuU2hvcnRlc3QsIG4sIGxlbiwgcmV0ID0gW10sXHJcblx0XHRcdG9iaiA9IHt9LFxyXG5cdFx0XHRuT3RoZXJzO1xyXG5cdFx0bk90aGVycyA9IGFyZ3VtZW50cy5sZW5ndGggLSAxO1xyXG5cdFx0blNob3J0ZXN0ID0gYXJndW1lbnRzWzBdLmxlbmd0aDtcclxuXHRcdHNob3J0ZXN0ID0gMDtcclxuXHRcdGZvciAoaSA9IDA7IGkgPD0gbk90aGVyczsgaSsrKSB7XHJcblx0XHRcdG4gPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG5cdFx0XHRpZiAobiA8IG5TaG9ydGVzdCkge1xyXG5cdFx0XHRcdHNob3J0ZXN0ID0gaTtcclxuXHRcdFx0XHRuU2hvcnRlc3QgPSBuO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yIChpID0gMDsgaSA8PSBuT3RoZXJzOyBpKyspIHtcclxuXHRcdFx0biA9IChpID09PSBzaG9ydGVzdCkgPyAwIDogKGkgfHwgc2hvcnRlc3QpOyAvL1JlYWQgdGhlIHNob3J0ZXN0IGFycmF5IGZpcnN0LiBSZWFkIHRoZSBmaXJzdCBhcnJheSBpbnN0ZWFkIG9mIHRoZSBzaG9ydGVzdFxyXG5cdFx0XHRsZW4gPSBhcmd1bWVudHNbbl0ubGVuZ3RoO1xyXG5cdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IGxlbjsgaisrKSB7XHJcblx0XHRcdFx0dmFyIGVsZW0gPSBhcmd1bWVudHNbbl1bal07XHJcblx0XHRcdFx0aWYgKG9ialtlbGVtXSA9PT0gaSAtIDEpIHtcclxuXHRcdFx0XHRcdGlmIChpID09PSBuT3RoZXJzKSB7XHJcblx0XHRcdFx0XHRcdHJldC5wdXNoKGVsZW0pO1xyXG5cdFx0XHRcdFx0XHRvYmpbZWxlbV0gPSAwO1xyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0b2JqW2VsZW1dID0gaTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9IGVsc2UgaWYgKGkgPT09IDApIHtcclxuXHRcdFx0XHRcdG9ialtlbGVtXSA9IDA7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcmV0O1xyXG5cdH0sXHJcblxyXG5cdF9idWlsZFBvbHlnb25OZWlnaGJvdXJzOiBmdW5jdGlvbiAocG9seWdvbiwgbmF2aWdhdGlvbk1lc2gpIHtcclxuXHRcdHBvbHlnb24ubmVpZ2hib3VycyA9IFtdO1xyXG5cclxuXHRcdC8vIEFsbCBvdGhlciBub2RlcyB0aGF0IGNvbnRhaW4gYXQgbGVhc3QgdHdvIG9mIG91ciB2ZXJ0aWNlcyBhcmUgb3VyIG5laWdoYm91cnNcclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBuYXZpZ2F0aW9uTWVzaC5wb2x5Z29ucy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRpZiAocG9seWdvbiA9PT0gbmF2aWdhdGlvbk1lc2gucG9seWdvbnNbaV0pIGNvbnRpbnVlO1xyXG5cclxuXHRcdFx0Ly8gRG9uJ3QgY2hlY2sgcG9seWdvbnMgdGhhdCBhcmUgdG9vIGZhciwgc2luY2UgdGhlIGludGVyc2VjdGlvbiB0ZXN0cyB0YWtlIGEgbG9uZyB0aW1lXHJcblx0XHRcdGlmIChCQUJZTE9OLlZlY3RvcjMuRGlzdGFuY2VTcXVhcmVkKHBvbHlnb24uY2VudHJvaWQsIG5hdmlnYXRpb25NZXNoLnBvbHlnb25zW2ldLmNlbnRyb2lkKSA+IDEwMCAqIDEwMCkgY29udGludWU7XHJcblxyXG5cdFx0XHR2YXIgbWF0Y2hlcyA9IHRoaXMuX2FycmF5X2ludGVyc2VjdChwb2x5Z29uLnZlcnRleElkcywgbmF2aWdhdGlvbk1lc2gucG9seWdvbnNbaV0udmVydGV4SWRzKTtcclxuXHRcdFx0Ly8gdmFyIG1hdGNoZXMgPSBfLmludGVyc2VjdGlvbihwb2x5Z29uLnZlcnRleElkcywgbmF2aWdhdGlvbk1lc2gucG9seWdvbnNbaV0udmVydGV4SWRzKTtcclxuXHJcblx0XHRcdGlmIChtYXRjaGVzLmxlbmd0aCA+PSAyKSB7XHJcblx0XHRcdFx0cG9seWdvbi5uZWlnaGJvdXJzLnB1c2gobmF2aWdhdGlvbk1lc2gucG9seWdvbnNbaV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2J1aWxkUG9seWdvbnNGcm9tR2VvbWV0cnk6IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xyXG5cclxuXHRcdHZhciBwb2x5Z29ucyA9IFtdO1xyXG5cdFx0dmFyIHZlcnRpY2VzID0gZ2VvbWV0cnkuZ2V0VmVydGljZXNEYXRhKEJBQllMT04uVmVydGV4QnVmZmVyLlBvc2l0aW9uS2luZCk7XHJcblx0XHR2YXIgaW5kaWNlcyA9IGdlb21ldHJ5LmdldEluZGljZXMoKTtcclxuXHRcdHZhciBwb2x5Z29uSWQgPSAxO1xyXG5cclxuXHRcdGNvbnNvbGUubG9nKFwiVmVydGljZXM6XCIsIHZlcnRpY2VzLmxlbmd0aC8zLCBcInBvbHlnb25zOlwiLCBpbmRpY2VzLmxlbmd0aC8zKTtcclxuXHJcblx0XHQvLyBDb252ZXJ0IHRoZSBmYWNlcyBpbnRvIGEgY3VzdG9tIGZvcm1hdCB0aGF0IHN1cHBvcnRzIG1vcmUgdGhhbiAzIHZlcnRpY2VzXHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKz0zKSB7XHJcblxyXG5cdFx0XHR2YXIgYSA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgaW5kaWNlc1tpXSk7XHJcblx0XHRcdHZhciBiID0gdGhpcy5nZXRWZWN0b3JGcm9tKHZlcnRpY2VzLCBpbmRpY2VzW2krMV0pO1xyXG5cdFx0XHR2YXIgYyA9IHRoaXMuZ2V0VmVjdG9yRnJvbSh2ZXJ0aWNlcywgaW5kaWNlc1tpKzJdKTtcclxuXHRcdFx0dmFyIG5vcm1hbCA9IEJBQllMT04uVmVjdG9yMy5Dcm9zcyhiLnN1YnRyYWN0KGEpLCBiLnN1YnRyYWN0KGMpKS5ub3JtYWxpemUoKTtcclxuXHJcblx0XHRcdHBvbHlnb25zLnB1c2goe1xyXG5cdFx0XHRcdGlkOiBwb2x5Z29uSWQrKyxcclxuXHRcdFx0XHR2ZXJ0ZXhJZHM6IFtpbmRpY2VzW2ldLCBpbmRpY2VzW2krMV0sIGluZGljZXNbaSsyXV0sXHJcblx0XHRcdFx0Y2VudHJvaWQ6IGdlb21ldHJ5LmNlbnRyb2lkc1tpLzNdLFxyXG5cdFx0XHRcdG5vcm1hbDogbm9ybWFsLFxyXG5cdFx0XHRcdG5laWdoYm91cnM6IFtdXHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBuYXZpZ2F0aW9uTWVzaCA9IHtcclxuXHRcdFx0cG9seWdvbnM6IHBvbHlnb25zLFxyXG5cdFx0XHR2ZXJ0aWNlczogdmVydGljZXNcclxuXHRcdH07XHJcblxyXG5cdFx0Ly8gQnVpbGQgYSBsaXN0IG9mIGFkamFjZW50IHBvbHlnb25zXHJcblx0XHRfLmVhY2gocG9seWdvbnMsIGZ1bmN0aW9uIChwb2x5Z29uKSB7XHJcblx0XHRcdHRoaXMuX2J1aWxkUG9seWdvbk5laWdoYm91cnMocG9seWdvbiwgbmF2aWdhdGlvbk1lc2gpO1xyXG5cdFx0fS5iaW5kKHRoaXMpKTtcclxuXHJcblx0XHRyZXR1cm4gbmF2aWdhdGlvbk1lc2g7XHJcblx0fSxcclxuXHJcblx0X2NsZWFuTmF2aWdhdGlvbk1lc2g6IGZ1bmN0aW9uIChuYXZpZ2F0aW9uTWVzaCkge1xyXG5cclxuXHRcdHZhciBwb2x5Z29ucyA9IG5hdmlnYXRpb25NZXNoLnBvbHlnb25zO1xyXG5cdFx0dmFyIHZlcnRpY2VzID0gbmF2aWdhdGlvbk1lc2gudmVydGljZXM7XHJcblxyXG5cclxuXHRcdC8vIFJlbW92ZSBzdGVlcCB0cmlhbmdsZXNcclxuXHRcdHZhciB1cCA9IG5ldyBCQUJZTE9OLlZlY3RvcjMoMCwgMSwgMCk7XHJcblx0XHRwb2x5Z29ucyA9IF8uZmlsdGVyKHBvbHlnb25zLCBmdW5jdGlvbiAocG9seWdvbikge1xyXG5cdFx0XHR2YXIgYW5nbGUgPSBNYXRoLmFjb3ModXAuZG90KHBvbHlnb24ubm9ybWFsKSk7XHJcblx0XHRcdHJldHVybiBhbmdsZSA8IChNYXRoLlBJIC8gNCk7XHJcblx0XHR9KTtcclxuXHJcblxyXG5cdFx0Ly8gUmVtb3ZlIHVubmVjZXNzYXJ5IGVkZ2VzIHVzaW5nIHRoZSBIZXJ0ZWwtTWVobGhvcm4gYWxnb3JpdGhtXHJcblxyXG5cdFx0Ly8gMS4gRmluZCBhIHBhaXIgb2YgYWRqYWNlbnQgbm9kZXMgKGkuZS4sIHR3byBub2RlcyB0aGF0IHNoYXJlIGFuIGVkZ2UgYmV0d2VlbiB0aGVtKVxyXG5cdFx0Ly8gICAgd2hvc2Ugbm9ybWFscyBhcmUgbmVhcmx5IGlkZW50aWNhbCAoaS5lLiwgdGhlaXIgc3VyZmFjZXMgZmFjZSB0aGUgc2FtZSBkaXJlY3Rpb24pLlxyXG5cclxuXHJcblx0XHR2YXIgbmV3UG9seWdvbnMgPSBbXTtcclxuXHJcblx0XHRfLmVhY2gocG9seWdvbnMsIGZ1bmN0aW9uIChwb2x5Z29uKSB7XHJcblxyXG5cdFx0XHRpZiAocG9seWdvbi50b0JlRGVsZXRlZCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIGtlZXBMb29raW5nID0gdHJ1ZTtcclxuXHJcblx0XHRcdHdoaWxlIChrZWVwTG9va2luZykge1xyXG5cdFx0XHRcdGtlZXBMb29raW5nID0gZmFsc2U7XHJcblxyXG5cdFx0XHRcdF8uZWFjaChwb2x5Z29uLm5laWdoYm91cnMsIGZ1bmN0aW9uIChvdGhlclBvbHlnb24pIHtcclxuXHJcblx0XHRcdFx0XHRpZiAocG9seWdvbiA9PT0gb3RoZXJQb2x5Z29uKSByZXR1cm47XHJcblxyXG5cdFx0XHRcdFx0aWYgKE1hdGguYWNvcyhwb2x5Z29uLm5vcm1hbC5kb3Qob3RoZXJQb2x5Z29uLm5vcm1hbCkpIDwgMC4wMSkge1xyXG5cdFx0XHRcdFx0XHQvLyBUaGF0J3MgcHJldHR5IGVxdWFsIGFscmlnaHQhXHJcblxyXG5cdFx0XHRcdFx0XHQvLyBNZXJnZSBvdGhlclBvbHlnb24gd2l0aCBwb2x5Z29uXHJcblxyXG5cdFx0XHRcdFx0XHR2YXIgdGVzdFZlcnRleElkTGlzdCA9IFtdO1xyXG5cclxuXHRcdFx0XHRcdFx0dmFyIHRlc3RQb2x5Z29uID0ge1xyXG5cdFx0XHRcdFx0XHRcdHZlcnRleElkczogbWVyZ2VWZXJ0ZXhJZHMocG9seWdvbi52ZXJ0ZXhJZHMsIG90aGVyUG9seWdvbi52ZXJ0ZXhJZHMpLFxyXG5cdFx0XHRcdFx0XHRcdG5laWdoYm91cnM6IHBvbHlnb24ubmVpZ2hib3VycyxcclxuXHRcdFx0XHRcdFx0XHRub3JtYWw6IHBvbHlnb24ubm9ybWFsLmNsb25lKCksXHJcblx0XHRcdFx0XHRcdFx0Y2VudHJvaWQ6IHBvbHlnb24uY2VudHJvaWQuY2xvbmUoKVxyXG5cdFx0XHRcdFx0XHR9O1xyXG5cclxuXHRcdFx0XHRcdFx0dGhpcy5fY2xlYW5Qb2x5Z29uKHRlc3RQb2x5Z29uLCBuYXZpZ2F0aW9uTWVzaCk7XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoaXNDb252ZXgodGVzdFBvbHlnb24sIG5hdmlnYXRpb25NZXNoKSkge1xyXG5cdFx0XHRcdFx0XHRcdG90aGVyUG9seWdvbi50b0JlRGVsZXRlZCA9IHRydWU7XHJcblxyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBJbmhlcml0IHRoZSBuZWlnaGJvdXJzIGZyb20gdGhlIHRvIGJlIG1lcmdlZCBwb2x5Z29uLCBleGNlcHQgb3Vyc2VsZlxyXG5cdFx0XHRcdFx0XHRcdF8uZWFjaChvdGhlclBvbHlnb24ubmVpZ2hib3VycywgZnVuY3Rpb24gKG90aGVyUG9seWdvbk5laWdoYm91cikge1xyXG5cclxuXHRcdFx0XHRcdFx0XHRcdC8vIFNldCB0aGlzIHBvbHkgdG8gYmUgbWVyZ2VkIHRvIGJlIG5vIGxvbmdlciBvdXIgbmVpZ2hib3VyXHJcblx0XHRcdFx0XHRcdFx0XHRvdGhlclBvbHlnb25OZWlnaGJvdXIubmVpZ2hib3VycyA9IF8ud2l0aG91dChvdGhlclBvbHlnb25OZWlnaGJvdXIubmVpZ2hib3Vycywgb3RoZXJQb2x5Z29uKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRpZiAob3RoZXJQb2x5Z29uTmVpZ2hib3VyICE9PSBwb2x5Z29uKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdC8vIFRlbGwgdGhlIG9sZCBQb2x5Z29uJ3MgbmVpZ2hib3VycyBhYm91dCB0aGUgbmV3IG5laWdoYm91ciB3aG8gaGFzIG1lcmdlZFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRvdGhlclBvbHlnb25OZWlnaGJvdXIubmVpZ2hib3Vycy5wdXNoKHBvbHlnb24pO1xyXG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gRm9yIG91cnNlbGYsIHdlIGRvbid0IG5lZWQgdG8ga25vdyBhYm91dCBvdXJzZWx2ZXNcclxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gQnV0IHdlIGluaGVyaXQgdGhlIG9sZCBuZWlnaGJvdXJzXHJcblx0XHRcdFx0XHRcdFx0XHRcdHBvbHlnb24ubmVpZ2hib3VycyA9IHBvbHlnb24ubmVpZ2hib3Vycy5jb25jYXQob3RoZXJQb2x5Z29uLm5laWdoYm91cnMpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRwb2x5Z29uLm5laWdoYm91cnMgPSBfLnVuaXEocG9seWdvbi5uZWlnaGJvdXJzKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdC8vIFdpdGhvdXQgb3Vyc2VsdmVzIGluIGl0IVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRwb2x5Z29uLm5laWdoYm91cnMgPSBfLndpdGhvdXQocG9seWdvbi5uZWlnaGJvdXJzLCBwb2x5Z29uKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHJcblx0XHRcdFx0XHRcdFx0cG9seWdvbi52ZXJ0ZXhJZHMgPSBtZXJnZVZlcnRleElkcyhwb2x5Z29uLnZlcnRleElkcywgb3RoZXJQb2x5Z29uLnZlcnRleElkcyk7XHJcblxyXG5cdFx0XHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKHBvbHlnb24udmVydGV4SWRzKTtcclxuXHRcdFx0XHRcdFx0XHQvLyBjb25zb2xlLmxvZyhcIk1lcmdlIVwiKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0Y2xlYW5Qb2x5Z29uKHBvbHlnb24sIG5hdmlnYXRpb25NZXNoKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0a2VlcExvb2tpbmcgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0uYmluZCh0aGlzKSk7XHJcblx0XHRcdH1cclxuXHJcblxyXG5cdFx0XHRpZiAoIXBvbHlnb24udG9CZURlbGV0ZWQpIHtcclxuXHRcdFx0XHRuZXdQb2x5Z29ucy5wdXNoKHBvbHlnb24pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0fSk7XHJcblxyXG5cdFx0dmFyIGlzVXNlZCA9IGZ1bmN0aW9uICh2SWQpIHtcclxuXHRcdFx0dmFyIGNvbnRhaW5zID0gZmFsc2U7XHJcblx0XHRcdF8uZWFjaChuZXdQb2x5Z29ucywgZnVuY3Rpb24gKHApIHtcclxuXHRcdFx0XHRpZiAoIWNvbnRhaW5zICYmIF8uaW5jbHVkZXMocC52ZXJ0ZXhJZHMsIHZJZCkpIHtcclxuXHRcdFx0XHRcdGNvbnRhaW5zID0gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0XHRyZXR1cm4gY29udGFpbnM7XHJcblx0XHR9O1xyXG5cclxuXHRcdC8vIENsZWFuIHZlcnRpY2VzXHJcblx0XHR2YXIga2VlcENoZWNraW5nID0gZmFsc2U7XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHZlcnRpY2VzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdGlmICghaXNVc2VkKGkpKSB7XHJcblxyXG5cdFx0XHRcdC8vIERlY3JlbWVudCBhbGwgdmVydGljZXMgdGhhdCBhcmUgaGlnaGVyIHRoYW4gaVxyXG5cdFx0XHRcdF8uZWFjaChuZXdQb2x5Z29ucywgZnVuY3Rpb24gKHApIHtcclxuXHRcdFx0XHRcdGZvciAodmFyIGogPSAwOyBqIDwgcC52ZXJ0ZXhJZHMubGVuZ3RoOyBqKyspIHtcclxuXHRcdFx0XHRcdFx0aWYgKHAudmVydGV4SWRzW2pdID4gaSkge1xyXG5cdFx0XHRcdFx0XHRcdHAudmVydGV4SWRzW2pdIC0tO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSk7XHJcblxyXG5cdFx0XHRcdHZlcnRpY2VzLnNwbGljZShpLCAxKTtcclxuXHRcdFx0XHRpLS07XHJcblx0XHRcdH1cclxuXHJcblx0XHR9O1xyXG5cclxuXHJcblx0XHRuYXZpZ2F0aW9uTWVzaC5wb2x5Z29ucyA9IG5ld1BvbHlnb25zO1xyXG5cdFx0bmF2aWdhdGlvbk1lc2gudmVydGljZXMgPSB2ZXJ0aWNlcztcclxuXHJcblx0fSxcclxuXHJcblx0X2J1aWxkTmF2aWdhdGlvbk1lc2g6IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xyXG5cdFx0Ly8gUHJlcGFyZSBnZW9tZXRyeVxyXG5cdFx0dGhpcy5fY29tcHV0ZUNlbnRyb2lkcyhnZW9tZXRyeSk7XHJcblxyXG5cdFx0dGhpcy5fbWVyZ2VWZXJ0aWNlcyhnZW9tZXRyeSk7XHJcblx0XHQvLyBCQUJZTE9OLkdlb21ldHJ5VXRpbHMudHJpYW5ndWxhdGVRdWFkcyhnZW9tZXRyeSk7XHJcblxyXG5cdFx0Ly8gY29uc29sZS5sb2coXCJ2ZXJ0aWNlczpcIiwgZ2VvbWV0cnkudmVydGljZXMubGVuZ3RoLCBcInBvbHlnb25zOlwiLCBnZW9tZXRyeS5mYWNlcy5sZW5ndGgpO1xyXG5cclxuXHRcdHZhciBuYXZpZ2F0aW9uTWVzaCA9IHRoaXMuX2J1aWxkUG9seWdvbnNGcm9tR2VvbWV0cnkoZ2VvbWV0cnkpO1xyXG5cclxuXHRcdC8vIGNsZWFuTmF2aWdhdGlvbk1lc2gobmF2aWdhdGlvbk1lc2gpO1xyXG5cdFx0Ly8gY29uc29sZS5sb2coXCJQcmUtY2xlYW46XCIsIG5hdmlnYXRpb25NZXNoLnBvbHlnb25zLmxlbmd0aCwgXCJwb2x5Z29ucyxcIiwgbmF2aWdhdGlvbk1lc2gudmVydGljZXMubGVuZ3RoLCBcInZlcnRpY2VzLlwiKTtcclxuXHJcblx0XHQvLyBjb25zb2xlLmxvZyhcIlwiKVxyXG5cdFx0Ly8gY29uc29sZS5sb2coXCJWZXJ0aWNlczpcIiwgbmF2aWdhdGlvbk1lc2gudmVydGljZXMubGVuZ3RoLCBcInBvbHlnb25zLFwiLCBuYXZpZ2F0aW9uTWVzaC5wb2x5Z29ucy5sZW5ndGgsIFwidmVydGljZXMuXCIpO1xyXG5cclxuXHRcdHJldHVybiBuYXZpZ2F0aW9uTWVzaDtcclxuXHR9LFxyXG5cclxuXHRfbWVyZ2VWZXJ0aWNlczogZnVuY3Rpb24gKGdlb21ldHJ5KSB7XHJcblx0XHR2YXIgdmVydGljZXNNYXAgPSB7fTsgLy8gSGFzaG1hcCBmb3IgbG9va2luZyB1cCB2ZXJ0aWNlcyBieSBwb3NpdGlvbiBjb29yZGluYXRlcyAoYW5kIG1ha2luZyBzdXJlIHRoZXkgYXJlIHVuaXF1ZSlcclxuXHRcdHZhciB1bmlxdWUgPSBbXSwgY2hhbmdlcyA9IFtdO1xyXG5cclxuXHRcdHZhciB2LCBrZXk7XHJcblx0XHR2YXIgcHJlY2lzaW9uUG9pbnRzID0gNDsgLy8gbnVtYmVyIG9mIGRlY2ltYWwgcG9pbnRzLCBlLmcuIDQgZm9yIGVwc2lsb24gb2YgMC4wMDAxXHJcblx0XHR2YXIgcHJlY2lzaW9uID0gTWF0aC5wb3coIDEwLCBwcmVjaXNpb25Qb2ludHMgKTtcclxuXHRcdHZhciBpLCBpbCwgZmFjZTtcclxuXHRcdHZhciBpbmRpY2VzLCBqLCBqbDtcclxuXHRcdHZhciBpbmQgPSBnZW9tZXRyeS5nZXRJbmRpY2VzKCksIFxyXG5cdFx0XHR2ZXJ0ID0gZ2VvbWV0cnkuZ2V0VmVydGljZXNEYXRhKEJBQllMT04uVmVydGV4QnVmZmVyLlBvc2l0aW9uS2luZCk7XHJcblxyXG5cdFx0Zm9yICggaSA9IDAsIGlsID0gdmVydC5sZW5ndGg7IGkgPCBpbDsgaSArPSAzICkge1xyXG5cclxuXHRcdFx0diA9IG5ldyBCQUJZTE9OLlZlY3RvcjModmVydFsgaSBdLCB2ZXJ0WyBpICsxXSwgdmVydFsgaSArMl0pO1xyXG5cdFx0XHRrZXkgPSBNYXRoLnJvdW5kKCB2LnggKiBwcmVjaXNpb24gKSArICdfJyArIE1hdGgucm91bmQoIHYueSAqIHByZWNpc2lvbiApICsgJ18nICsgTWF0aC5yb3VuZCggdi56ICogcHJlY2lzaW9uICk7XHJcblxyXG5cdFx0XHRpZiAoIHZlcnRpY2VzTWFwWyBrZXkgXSA9PT0gdW5kZWZpbmVkICkge1xyXG5cclxuXHRcdFx0XHR2ZXJ0aWNlc01hcFsga2V5IF0gPSBpLzM7XHJcblx0XHRcdFx0dW5pcXVlLnB1c2goIHYuY2xvbmUoKSApO1xyXG5cdFx0XHRcdGNoYW5nZXNbIGkvMyBdID0gdW5pcXVlLmxlbmd0aCAtIDE7XHJcblxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cclxuXHRcdFx0XHQvL2NvbnNvbGUubG9nKCdEdXBsaWNhdGUgdmVydGV4IGZvdW5kLiAnLCBpLCAnIGNvdWxkIGJlIHVzaW5nICcsIHZlcnRpY2VzTWFwW2tleV0pO1xyXG5cdFx0XHRcdGNoYW5nZXNbIGkvMyBdID0gY2hhbmdlc1sgdmVydGljZXNNYXBbIGtleSBdIF07XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHQvLyBpZiBmYWNlcyBhcmUgY29tcGxldGVseSBkZWdlbmVyYXRlIGFmdGVyIG1lcmdpbmcgdmVydGljZXMsIHdlXHJcblx0XHQvLyBoYXZlIHRvIHJlbW92ZSB0aGVtIGZyb20gdGhlIGdlb21ldHJ5LlxyXG5cdFx0dmFyIGZhY2VJbmRpY2VzVG9SZW1vdmUgPSBbXTtcclxuXHJcblx0XHRmb3IgKCBpID0gMCwgaWwgPSBpbmQubGVuZ3RoOyBpIDwgaWw7IGkgKz0gMyApIHtcclxuXHJcblx0XHRcdGluZFtpXSA9IGNoYW5nZXNbIGluZFtpXSBdO1xyXG5cdFx0XHRpbmRbaSsxXSA9IGNoYW5nZXNbIGluZFtpKzFdIF07XHJcblx0XHRcdGluZFtpKzJdID0gY2hhbmdlc1sgaW5kW2krMl0gXTtcclxuXHJcblx0XHRcdGluZGljZXMgPSBbIGluZFtpXSwgaW5kW2krMV0sIGluZFtpKzJdIF07XHJcblxyXG5cdFx0XHR2YXIgZHVwSW5kZXggPSAtIDE7XHJcblxyXG5cdFx0XHQvLyBpZiBhbnkgZHVwbGljYXRlIHZlcnRpY2VzIGFyZSBmb3VuZCBpbiBhIEZhY2UzXHJcblx0XHRcdC8vIHdlIGhhdmUgdG8gcmVtb3ZlIHRoZSBmYWNlIGFzIG5vdGhpbmcgY2FuIGJlIHNhdmVkXHJcblx0XHRcdGZvciAoIHZhciBuID0gMDsgbiA8IDM7IG4gKysgKSB7XHJcblxyXG5cdFx0XHRcdGlmICggaW5kaWNlc1sgbiBdID09PSBpbmRpY2VzWyAoIG4gKyAxICkgJSAzIF0gKSB7XHJcblxyXG5cdFx0XHRcdFx0ZHVwSW5kZXggPSBuO1xyXG5cdFx0XHRcdFx0ZmFjZUluZGljZXNUb1JlbW92ZS5wdXNoKCBpICk7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0fVxyXG5cclxuXHRcdH1cclxuXHJcblx0XHRmb3IgKCBpID0gZmFjZUluZGljZXNUb1JlbW92ZS5sZW5ndGggLSAxOyBpID49IDA7IGkgLS0gKSB7XHJcblxyXG5cdFx0XHR2YXIgaWR4ID0gZmFjZUluZGljZXNUb1JlbW92ZVsgaSBdO1xyXG5cclxuXHRcdFx0aW5kLnNwbGljZSggaWR4LCAzICk7XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFVzZSB1bmlxdWUgc2V0IG9mIHZlcnRpY2VzXHJcblxyXG5cdFx0dmFyIGRpZmYgPSB2ZXJ0Lmxlbmd0aC8zIC0gdW5pcXVlLmxlbmd0aDtcclxuXHRcdHZlcnQgPSBbXTtcclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdW5pcXVlLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHZlcnQucHVzaCh1bmlxdWVbaV0ueCwgdW5pcXVlW2ldLnksIHVuaXF1ZVtpXS56KTtcclxuXHRcdH1cclxuXHJcblx0XHRnZW9tZXRyeS5zZXRJbmRpY2VzKGluZCk7XHJcblx0XHRnZW9tZXRyeS5zZXRWZXJ0aWNlc0RhdGEoQkFCWUxPTi5WZXJ0ZXhCdWZmZXIuUG9zaXRpb25LaW5kLCB2ZXJ0KTtcclxuXHJcblx0XHRyZXR1cm4gZGlmZjtcclxuXHR9LFxyXG5cclxuXHJcblx0X2dldFNoYXJlZFZlcnRpY2VzSW5PcmRlcjogZnVuY3Rpb24gKGEsIGIpIHtcclxuXHJcblx0XHR2YXIgYUxpc3QgPSBhLnZlcnRleElkcztcclxuXHRcdHZhciBiTGlzdCA9IGIudmVydGV4SWRzO1xyXG5cclxuXHRcdHZhciBzaGFyZWRWZXJ0aWNlcyA9IFtdO1xyXG5cclxuXHRcdF8uZWFjaChhTGlzdCwgZnVuY3Rpb24gKHZJZCkge1xyXG5cdFx0XHRpZiAoXy5pbmNsdWRlcyhiTGlzdCwgdklkKSkge1xyXG5cdFx0XHRcdHNoYXJlZFZlcnRpY2VzLnB1c2godklkKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKHNoYXJlZFZlcnRpY2VzLmxlbmd0aCA8IDIpIHJldHVybiBbXTtcclxuXHJcblx0XHQvLyBjb25zb2xlLmxvZyhcIlRSWUlORyBhTGlzdDpcIiwgYUxpc3QsIFwiLCBiTGlzdDpcIiwgYkxpc3QsIFwiLCBzaGFyZWRWZXJ0aWNlczpcIiwgc2hhcmVkVmVydGljZXMpO1xyXG5cclxuXHRcdGlmIChfLmluY2x1ZGVzKHNoYXJlZFZlcnRpY2VzLCBhTGlzdFswXSkgJiYgXy5pbmNsdWRlcyhzaGFyZWRWZXJ0aWNlcywgYUxpc3RbYUxpc3QubGVuZ3RoIC0gMV0pKSB7XHJcblx0XHRcdC8vIFZlcnRpY2VzIG9uIGJvdGggZWRnZXMgYXJlIGJhZCwgc28gc2hpZnQgdGhlbSBvbmNlIHRvIHRoZSBsZWZ0XHJcblx0XHRcdGFMaXN0LnB1c2goYUxpc3Quc2hpZnQoKSk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKF8uaW5jbHVkZXMoc2hhcmVkVmVydGljZXMsIGJMaXN0WzBdKSAmJiBfLmluY2x1ZGVzKHNoYXJlZFZlcnRpY2VzLCBiTGlzdFtiTGlzdC5sZW5ndGggLSAxXSkpIHtcclxuXHRcdFx0Ly8gVmVydGljZXMgb24gYm90aCBlZGdlcyBhcmUgYmFkLCBzbyBzaGlmdCB0aGVtIG9uY2UgdG8gdGhlIGxlZnRcclxuXHRcdFx0Ykxpc3QucHVzaChiTGlzdC5zaGlmdCgpKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBBZ2FpbiFcclxuXHRcdHNoYXJlZFZlcnRpY2VzID0gW107XHJcblxyXG5cdFx0Xy5lYWNoKGFMaXN0LCBmdW5jdGlvbiAodklkKSB7XHJcblx0XHRcdGlmIChfLmluY2x1ZGVzKGJMaXN0LCB2SWQpKSB7XHJcblx0XHRcdFx0c2hhcmVkVmVydGljZXMucHVzaCh2SWQpO1xyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHJcblx0XHRyZXR1cm4gc2hhcmVkVmVydGljZXM7XHJcblx0fSxcclxuXHJcblx0X2dyb3VwTmF2TWVzaDogZnVuY3Rpb24gKG5hdmlnYXRpb25NZXNoKSB7XHJcblxyXG5cdFx0dmFyIHNhdmVPYmogPSB7fTtcclxuXHJcblx0XHRfLmVhY2gobmF2aWdhdGlvbk1lc2gudmVydGljZXMsIGZ1bmN0aW9uICh2KSB7XHJcblx0XHRcdHYgPSB0aGlzLl9yb3VuZE51bWJlcih2LCAyKTtcclxuXHRcdH0uYmluZCh0aGlzKSk7XHJcblxyXG5cdFx0c2F2ZU9iai52ZXJ0aWNlcyA9IG5hdmlnYXRpb25NZXNoLnZlcnRpY2VzO1xyXG5cclxuXHRcdHZhciBncm91cHMgPSB0aGlzLl9idWlsZFBvbHlnb25Hcm91cHMobmF2aWdhdGlvbk1lc2gpO1xyXG5cclxuXHRcdHNhdmVPYmouZ3JvdXBzID0gW107XHJcblxyXG5cdFx0dmFyIGZpbmRQb2x5Z29uSW5kZXggPSBmdW5jdGlvbiAoZ3JvdXAsIHApIHtcclxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBncm91cC5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdGlmIChwID09PSBncm91cFtpXSkgcmV0dXJuIGk7XHJcblx0XHRcdH1cclxuXHRcdH07XHJcblxyXG5cdFx0Xy5lYWNoKGdyb3VwcywgZnVuY3Rpb24gKGdyb3VwKSB7XHJcblxyXG5cdFx0XHR2YXIgbmV3R3JvdXAgPSBbXTtcclxuXHJcblx0XHRcdF8uZWFjaChncm91cCwgZnVuY3Rpb24gKHApIHtcclxuXHJcblx0XHRcdFx0dmFyIG5laWdoYm91cnMgPSBbXTtcclxuXHJcblx0XHRcdFx0Xy5lYWNoKHAubmVpZ2hib3VycywgZnVuY3Rpb24gKG4pIHtcclxuXHRcdFx0XHRcdG5laWdoYm91cnMucHVzaChmaW5kUG9seWdvbkluZGV4KGdyb3VwLCBuKSk7XHJcblx0XHRcdFx0fSk7XHJcblxyXG5cclxuXHRcdFx0XHQvLyBCdWlsZCBhIHBvcnRhbCBsaXN0IHRvIGVhY2ggbmVpZ2hib3VyXHJcblx0XHRcdFx0dmFyIHBvcnRhbHMgPSBbXTtcclxuXHRcdFx0XHRfLmVhY2gocC5uZWlnaGJvdXJzLCBmdW5jdGlvbiAobikge1xyXG5cdFx0XHRcdFx0cG9ydGFscy5wdXNoKHRoaXMuX2dldFNoYXJlZFZlcnRpY2VzSW5PcmRlcihwLCBuKSk7XHJcblx0XHRcdFx0fS5iaW5kKHRoaXMpKTtcclxuXHJcblxyXG5cdFx0XHRcdHAuY2VudHJvaWQueCA9IHRoaXMuX3JvdW5kTnVtYmVyKHAuY2VudHJvaWQueCwgMik7XHJcblx0XHRcdFx0cC5jZW50cm9pZC55ID0gdGhpcy5fcm91bmROdW1iZXIocC5jZW50cm9pZC55LCAyKTtcclxuXHRcdFx0XHRwLmNlbnRyb2lkLnogPSB0aGlzLl9yb3VuZE51bWJlcihwLmNlbnRyb2lkLnosIDIpO1xyXG5cclxuXHRcdFx0XHRuZXdHcm91cC5wdXNoKHtcclxuXHRcdFx0XHRcdGlkOiBmaW5kUG9seWdvbkluZGV4KGdyb3VwLCBwKSxcclxuXHRcdFx0XHRcdG5laWdoYm91cnM6IG5laWdoYm91cnMsXHJcblx0XHRcdFx0XHR2ZXJ0ZXhJZHM6IHAudmVydGV4SWRzLFxyXG5cdFx0XHRcdFx0Y2VudHJvaWQ6IHAuY2VudHJvaWQsXHJcblx0XHRcdFx0XHRwb3J0YWxzOiBwb3J0YWxzXHJcblx0XHRcdFx0fSk7XHJcblxyXG5cdFx0XHR9LmJpbmQodGhpcykpO1xyXG5cclxuXHRcdFx0c2F2ZU9iai5ncm91cHMucHVzaChuZXdHcm91cCk7XHJcblx0XHR9LmJpbmQodGhpcykpO1xyXG5cclxuXHRcdHJldHVybiBzYXZlT2JqO1xyXG5cdH0sXHJcbn0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBOYXZpZ2F0aW9uOyJdfQ==