12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216 |
- /******/ (function(modules) { // webpackBootstrap
- /******/ // The module cache
- /******/ var installedModules = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/
- /******/ // Check if module is in cache
- /******/ if(installedModules[moduleId]) {
- /******/ return installedModules[moduleId].exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = installedModules[moduleId] = {
- /******/ i: moduleId,
- /******/ l: false,
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
- /******/
- /******/ // Flag the module as loaded
- /******/ module.l = true;
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /******/
- /******/ // expose the modules object (__webpack_modules__)
- /******/ __webpack_require__.m = modules;
- /******/
- /******/ // expose the module cache
- /******/ __webpack_require__.c = installedModules;
- /******/
- /******/ // define getter function for harmony exports
- /******/ __webpack_require__.d = function(exports, name, getter) {
- /******/ if(!__webpack_require__.o(exports, name)) {
- /******/ Object.defineProperty(exports, name, {
- /******/ configurable: false,
- /******/ enumerable: true,
- /******/ get: getter
- /******/ });
- /******/ }
- /******/ };
- /******/
- /******/ // getDefaultExport function for compatibility with non-harmony modules
- /******/ __webpack_require__.n = function(module) {
- /******/ var getter = module && module.__esModule ?
- /******/ function getDefault() { return module['default']; } :
- /******/ function getModuleExports() { return module; };
- /******/ __webpack_require__.d(getter, 'a', getter);
- /******/ return getter;
- /******/ };
- /******/
- /******/ // Object.prototype.hasOwnProperty.call
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
- /******/
- /******/ // __webpack_public_path__
- /******/ __webpack_require__.p = "";
- /******/
- /******/ // Load entry module and return exports
- /******/ return __webpack_require__(__webpack_require__.s = 1);
- /******/ })
- /************************************************************************/
- /******/ ([
- /* 0 */
- /***/ (function(module, exports, __webpack_require__) {
- var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
- * jQuery JavaScript Library v3.2.1
- * https://jquery.com/
- *
- * Includes Sizzle.js
- * https://sizzlejs.com/
- *
- * Copyright JS Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2017-03-20T18:59Z
- */
- ( function( global, factory ) {
- "use strict";
- if ( typeof module === "object" && typeof module.exports === "object" ) {
- // For CommonJS and CommonJS-like environments where a proper `window`
- // is present, execute the factory and get jQuery.
- // For environments that do not have a `window` with a `document`
- // (such as Node.js), expose a factory as module.exports.
- // This accentuates the need for the creation of a real `window`.
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info.
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
- // Pass this if window is not defined yet
- } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
- // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
- // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
- // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
- // enough that all such attempts are guarded in a try block.
- "use strict";
- var arr = [];
- var document = window.document;
- var getProto = Object.getPrototypeOf;
- var slice = arr.slice;
- var concat = arr.concat;
- var push = arr.push;
- var indexOf = arr.indexOf;
- var class2type = {};
- var toString = class2type.toString;
- var hasOwn = class2type.hasOwnProperty;
- var fnToString = hasOwn.toString;
- var ObjectFunctionString = fnToString.call( Object );
- var support = {};
- function DOMEval( code, doc ) {
- doc = doc || document;
- var script = doc.createElement( "script" );
- script.text = code;
- doc.head.appendChild( script ).parentNode.removeChild( script );
- }
- /* global Symbol */
- // Defining this global in .eslintrc.json would create a danger of using the global
- // unguarded in another place, it seems safer to define global only for this module
- var
- version = "3.2.1",
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- // Need init if jQuery is called (just allow error to be thrown if not included)
- return new jQuery.fn.init( selector, context );
- },
- // Support: Android <=4.0 only
- // Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
- // Matches dashed string for camelizing
- rmsPrefix = /^-ms-/,
- rdashAlpha = /-([a-z])/g,
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return letter.toUpperCase();
- };
- jQuery.fn = jQuery.prototype = {
- // The current version of jQuery being used
- jquery: version,
- constructor: jQuery,
- // The default length of a jQuery object is 0
- length: 0,
- toArray: function() {
- return slice.call( this );
- },
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- // Return all the elements in a clean array
- if ( num == null ) {
- return slice.call( this );
- }
- // Return just the one element from the set
- return num < 0 ? this[ num + this.length ] : this[ num ];
- },
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
- // Return the newly-formed element set
- return ret;
- },
- // Execute a callback for every element in the matched set.
- each: function( callback ) {
- return jQuery.each( this, callback );
- },
- map: function( callback ) {
- return this.pushStack( jQuery.map( this, function( elem, i ) {
- return callback.call( elem, i, elem );
- } ) );
- },
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ) );
- },
- first: function() {
- return this.eq( 0 );
- },
- last: function() {
- return this.eq( -1 );
- },
- eq: function( i ) {
- var len = this.length,
- j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
- },
- end: function() {
- return this.prevObject || this.constructor();
- },
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: arr.sort,
- splice: arr.splice
- };
- jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[ 0 ] || {},
- i = 1,
- length = arguments.length,
- deep = false;
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- // Skip the boolean and the target
- target = arguments[ i ] || {};
- i++;
- }
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
- target = {};
- }
- // Extend jQuery itself if only one argument is passed
- if ( i === length ) {
- target = this;
- i--;
- }
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( ( options = arguments[ i ] ) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
- ( copyIsArray = Array.isArray( copy ) ) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && Array.isArray( src ) ? src : [];
- } else {
- clone = src && jQuery.isPlainObject( src ) ? src : {};
- }
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
- // Return the modified object
- return target;
- };
- jQuery.extend( {
- // Unique for each copy of jQuery on the page
- expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
- // Assume jQuery is ready without the ready module
- isReady: true,
- error: function( msg ) {
- throw new Error( msg );
- },
- noop: function() {},
- isFunction: function( obj ) {
- return jQuery.type( obj ) === "function";
- },
- isWindow: function( obj ) {
- return obj != null && obj === obj.window;
- },
- isNumeric: function( obj ) {
- // As of jQuery 3.0, isNumeric is limited to
- // strings and numbers (primitives or objects)
- // that can be coerced to finite numbers (gh-2662)
- var type = jQuery.type( obj );
- return ( type === "number" || type === "string" ) &&
- // parseFloat NaNs numeric-cast false positives ("")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- !isNaN( obj - parseFloat( obj ) );
- },
- isPlainObject: function( obj ) {
- var proto, Ctor;
- // Detect obvious negatives
- // Use toString instead of jQuery.type to catch host objects
- if ( !obj || toString.call( obj ) !== "[object Object]" ) {
- return false;
- }
- proto = getProto( obj );
- // Objects with no prototype (e.g., `Object.create( null )`) are plain
- if ( !proto ) {
- return true;
- }
- // Objects with prototype are plain iff they were constructed by a global Object function
- Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
- return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
- },
- isEmptyObject: function( obj ) {
- /* eslint-disable no-unused-vars */
- // See https://github.com/eslint/eslint/issues/6125
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
- },
- type: function( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
- // Support: Android <=2.3 only (functionish RegExp)
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call( obj ) ] || "object" :
- typeof obj;
- },
- // Evaluates a script in a global context
- globalEval: function( code ) {
- DOMEval( code );
- },
- // Convert dashed to camelCase; used by the css and data modules
- // Support: IE <=9 - 11, Edge 12 - 13
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
- each: function( obj, callback ) {
- var length, i = 0;
- if ( isArrayLike( obj ) ) {
- length = obj.length;
- for ( ; i < length; i++ ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- }
- return obj;
- },
- // Support: Android <=4.0 only
- trim: function( text ) {
- return text == null ?
- "" :
- ( text + "" ).replace( rtrim, "" );
- },
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var ret = results || [];
- if ( arr != null ) {
- if ( isArrayLike( Object( arr ) ) ) {
- jQuery.merge( ret,
- typeof arr === "string" ?
- [ arr ] : arr
- );
- } else {
- push.call( ret, arr );
- }
- }
- return ret;
- },
- inArray: function( elem, arr, i ) {
- return arr == null ? -1 : indexOf.call( arr, elem, i );
- },
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- merge: function( first, second ) {
- var len = +second.length,
- j = 0,
- i = first.length;
- for ( ; j < len; j++ ) {
- first[ i++ ] = second[ j ];
- }
- first.length = i;
- return first;
- },
- grep: function( elems, callback, invert ) {
- var callbackInverse,
- matches = [],
- i = 0,
- length = elems.length,
- callbackExpect = !invert;
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- callbackInverse = !callback( elems[ i ], i );
- if ( callbackInverse !== callbackExpect ) {
- matches.push( elems[ i ] );
- }
- }
- return matches;
- },
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var length, value,
- i = 0,
- ret = [];
- // Go through the array, translating each of the items to their new values
- if ( isArrayLike( elems ) ) {
- length = elems.length;
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
- if ( value != null ) {
- ret.push( value );
- }
- }
- // Go through every key on the object,
- } else {
- for ( i in elems ) {
- value = callback( elems[ i ], i, arg );
- if ( value != null ) {
- ret.push( value );
- }
- }
- }
- // Flatten any nested arrays
- return concat.apply( [], ret );
- },
- // A global GUID counter for objects
- guid: 1,
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var tmp, args, proxy;
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
- // Simulated bind
- args = slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
- };
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
- return proxy;
- },
- now: Date.now,
- // jQuery.support is not used in Core but other projects attach their
- // properties to it so it needs to exist.
- support: support
- } );
- if ( typeof Symbol === "function" ) {
- jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
- }
- // Populate the class2type map
- jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
- function( i, name ) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
- } );
- function isArrayLike( obj ) {
- // Support: real iOS 8.2 only (not reproducible in simulator)
- // `in` check used to prevent JIT error (gh-2145)
- // hasOwn isn't used here due to false negatives
- // regarding Nodelist length in IE
- var length = !!obj && "length" in obj && obj.length,
- type = jQuery.type( obj );
- if ( type === "function" || jQuery.isWindow( obj ) ) {
- return false;
- }
- return type === "array" || length === 0 ||
- typeof length === "number" && length > 0 && ( length - 1 ) in obj;
- }
- var Sizzle =
- /*!
- * Sizzle CSS Selector Engine v2.3.3
- * https://sizzlejs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2016-08-08
- */
- (function( window ) {
- var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
- // Instance-specific data
- expando = "sizzle" + 1 * new Date(),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf as it's faster than native
- // https://jsperf.com/thor-indexof-vs-for/5
- indexOf = function( list, elem ) {
- var i = 0,
- len = list.length;
- for ( ; i < len; i++ ) {
- if ( list[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
- // Regular expressions
- // http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
- // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
- pseudos = ":(" + identifier + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rwhitespace = new RegExp( whitespace + "+", "g" ),
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
- matchExpr = {
- "ID": new RegExp( "^#(" + identifier + ")" ),
- "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
- "TAG": new RegExp( "^(" + identifier + "|[*])" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
- rnative = /^[^{]+\{\s*\[native \w/,
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
- rsibling = /[+~]/,
- // CSS escapes
- // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- },
- // CSS string/identifier serialization
- // https://drafts.csswg.org/cssom/#common-serializing-idioms
- rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
- fcssescape = function( ch, asCodePoint ) {
- if ( asCodePoint ) {
- // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
- if ( ch === "\0" ) {
- return "\uFFFD";
- }
- // Control characters and (dependent upon position) numbers get escaped as code points
- return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
- }
- // Other potentially-special ASCII characters get backslash-escaped
- return "\\" + ch;
- },
- // Used for iframes
- // See setDocument()
- // Removing the function wrapper causes a "Permission Denied"
- // error in IE
- unloadHandler = function() {
- setDocument();
- },
- disabledAncestor = addCombinator(
- function( elem ) {
- return elem.disabled === true && ("form" in elem || "label" in elem);
- },
- { dir: "parentNode", next: "legend" }
- );
- // Optimize for push.apply( _, NodeList )
- try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
- } catch ( e ) {
- push = { apply: arr.length ?
- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
- }
- function Sizzle( selector, context, results, seed ) {
- var m, i, elem, nid, match, groups, newSelector,
- newContext = context && context.ownerDocument,
- // nodeType defaults to 9, since context defaults to document
- nodeType = context ? context.nodeType : 9;
- results = results || [];
- // Return early from calls with invalid selector or context
- if ( typeof selector !== "string" || !selector ||
- nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
- return results;
- }
- // Try to shortcut find operations (as opposed to filters) in HTML documents
- if ( !seed ) {
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
- context = context || document;
- if ( documentIsHTML ) {
- // If the selector is sufficiently simple, try using a "get*By*" DOM method
- // (excepting DocumentFragment context, where the methods don't exist)
- if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
- // ID selector
- if ( (m = match[1]) ) {
- // Document context
- if ( nodeType === 9 ) {
- if ( (elem = context.getElementById( m )) ) {
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
- // Element context
- } else {
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( newContext && (elem = newContext.getElementById( m )) &&
- contains( context, elem ) &&
- elem.id === m ) {
- results.push( elem );
- return results;
- }
- }
- // Type selector
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
- // Class selector
- } else if ( (m = match[3]) && support.getElementsByClassName &&
- context.getElementsByClassName ) {
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
- // Take advantage of querySelectorAll
- if ( support.qsa &&
- !compilerCache[ selector + " " ] &&
- (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- if ( nodeType !== 1 ) {
- newContext = context;
- newSelector = selector;
- // qSA looks outside Element context, which is not what we want
- // Thanks to Andrew Dupont for this workaround technique
- // Support: IE <=8
- // Exclude object elements
- } else if ( context.nodeName.toLowerCase() !== "object" ) {
- // Capture the context ID, setting it first if necessary
- if ( (nid = context.getAttribute( "id" )) ) {
- nid = nid.replace( rcssescape, fcssescape );
- } else {
- context.setAttribute( "id", (nid = expando) );
- }
- // Prefix every selector in the list
- groups = tokenize( selector );
- i = groups.length;
- while ( i-- ) {
- groups[i] = "#" + nid + " " + toSelector( groups[i] );
- }
- newSelector = groups.join( "," );
- // Expand context for sibling selectors
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
- context;
- }
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch ( qsaError ) {
- } finally {
- if ( nid === expando ) {
- context.removeAttribute( "id" );
- }
- }
- }
- }
- }
- }
- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
- }
- /**
- * Create key-value caches of limited size
- * @returns {function(string, object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
- function createCache() {
- var keys = [];
- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
- }
- /**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
- function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
- }
- /**
- * Support testing using an element
- * @param {Function} fn Passed the created element and returns a boolean result
- */
- function assert( fn ) {
- var el = document.createElement("fieldset");
- try {
- return !!fn( el );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( el.parentNode ) {
- el.parentNode.removeChild( el );
- }
- // release memory in IE
- el = null;
- }
- }
- /**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
- function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = arr.length;
- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
- }
- /**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
- function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- a.sourceIndex - b.sourceIndex;
- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
- return a ? 1 : -1;
- }
- /**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
- function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
- }
- /**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
- function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
- }
- /**
- * Returns a function to use in pseudos for :enabled/:disabled
- * @param {Boolean} disabled true for :disabled; false for :enabled
- */
- function createDisabledPseudo( disabled ) {
- // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
- return function( elem ) {
- // Only certain elements can match :enabled or :disabled
- // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
- // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
- if ( "form" in elem ) {
- // Check for inherited disabledness on relevant non-disabled elements:
- // * listed form-associated elements in a disabled fieldset
- // https://html.spec.whatwg.org/multipage/forms.html#category-listed
- // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
- // * option elements in a disabled optgroup
- // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
- // All such elements have a "form" property.
- if ( elem.parentNode && elem.disabled === false ) {
- // Option elements defer to a parent optgroup if present
- if ( "label" in elem ) {
- if ( "label" in elem.parentNode ) {
- return elem.parentNode.disabled === disabled;
- } else {
- return elem.disabled === disabled;
- }
- }
- // Support: IE 6 - 11
- // Use the isDisabled shortcut property to check for disabled fieldset ancestors
- return elem.isDisabled === disabled ||
- // Where there is no isDisabled, check manually
- /* jshint -W018 */
- elem.isDisabled !== !disabled &&
- disabledAncestor( elem ) === disabled;
- }
- return elem.disabled === disabled;
- // Try to winnow out elements that can't be disabled before trusting the disabled property.
- // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
- // even exist on them, let alone have a boolean value.
- } else if ( "label" in elem ) {
- return elem.disabled === disabled;
- }
- // Remaining elements are neither :enabled nor :disabled
- return false;
- };
- }
- /**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
- function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
- }
- /**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
- function testContext( context ) {
- return context && typeof context.getElementsByTagName !== "undefined" && context;
- }
- // Expose support vars for convenience
- support = Sizzle.support = {};
- /**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
- isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
- };
- /**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
- setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare, subWindow,
- doc = node ? node.ownerDocument || node : preferredDoc;
- // Return early if doc is invalid or already selected
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
- // Update global variables
- document = doc;
- docElem = document.documentElement;
- documentIsHTML = !isXML( document );
- // Support: IE 9-11, Edge
- // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
- if ( preferredDoc !== document &&
- (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
- // Support: IE 11, Edge
- if ( subWindow.addEventListener ) {
- subWindow.addEventListener( "unload", unloadHandler, false );
- // Support: IE 9 - 10 only
- } else if ( subWindow.attachEvent ) {
- subWindow.attachEvent( "onunload", unloadHandler );
- }
- }
- /* Attributes
- ---------------------------------------------------------------------- */
- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties
- // (excepting IE8 booleans)
- support.attributes = assert(function( el ) {
- el.className = "i";
- return !el.getAttribute("className");
- });
- /* getElement(s)By*
- ---------------------------------------------------------------------- */
- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( el ) {
- el.appendChild( document.createComment("") );
- return !el.getElementsByTagName("*").length;
- });
- // Support: IE<9
- support.getElementsByClassName = rnative.test( document.getElementsByClassName );
- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programmatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( el ) {
- docElem.appendChild( el ).id = expando;
- return !document.getElementsByName || !document.getElementsByName( expando ).length;
- });
- // ID filter and find
- if ( support.getById ) {
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
- var elem = context.getElementById( id );
- return elem ? [ elem ] : [];
- }
- };
- } else {
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== "undefined" &&
- elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
- // Support: IE 6 - 7 only
- // getElementById is not reliable as a find shortcut
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
- var node, i, elems,
- elem = context.getElementById( id );
- if ( elem ) {
- // Verify the id attribute
- node = elem.getAttributeNode("id");
- if ( node && node.value === id ) {
- return [ elem ];
- }
- // Fall back on getElementsByName
- elems = context.getElementsByName( id );
- i = 0;
- while ( (elem = elems[i++]) ) {
- node = elem.getAttributeNode("id");
- if ( node && node.value === id ) {
- return [ elem ];
- }
- }
- }
- return [];
- }
- };
- }
- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- return context.getElementsByTagName( tag );
- // DocumentFragment nodes don't have gEBTN
- } else if ( support.qsa ) {
- return context.querySelectorAll( tag );
- }
- } :
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
- results = context.getElementsByTagName( tag );
- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
- return tmp;
- }
- return results;
- };
- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
- // QSA and matchesSelector support
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See https://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
- if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( el ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // https://bugs.jquery.com/ticket/12359
- docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
- "<select id='" + expando + "-\r\\' msallowcapture=''>" +
- "<option selected=''></option></select>";
- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( el.querySelectorAll("[msallowcapture^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !el.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
- // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
- if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
- rbuggyQSA.push("~=");
- }
- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !el.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
- // Support: Safari 8+, iOS 8+
- // https://bugs.webkit.org/show_bug.cgi?id=136851
- // In-page `selector#id sibling-combinator selector` fails
- if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
- rbuggyQSA.push(".#.+[+~]");
- }
- });
- assert(function( el ) {
- el.innerHTML = "<a href='' disabled='disabled'></a>" +
- "<select disabled='disabled'><option/></select>";
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = document.createElement("input");
- input.setAttribute( "type", "hidden" );
- el.appendChild( input ).setAttribute( "name", "D" );
- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( el.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( el.querySelectorAll(":enabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
- // Support: IE9-11+
- // IE's :disabled selector does not pick up the children of disabled fieldsets
- docElem.appendChild( el ).disabled = true;
- if ( el.querySelectorAll(":disabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
- // Opera 10-11 does not throw on post-comma invalid pseudos
- el.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
- assert(function( el ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( el, "*" );
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( el, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
- // Element contains another
- // Purposefully self-exclusive
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
- /* Sorting
- ---------------------------------------------------------------------- */
- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
- // Otherwise we know they are disconnected
- 1;
- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
- // Choose the first element that is related to our preferred document
- if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
- // Maintain original order
- return sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
- }
- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === document ? -1 :
- b === document ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
- return document;
- };
- Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
- };
- Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
- if ( support.matchesSelector && documentIsHTML &&
- !compilerCache[ expr + " " ] &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
- try {
- var ret = matches.call( elem, expr );
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch (e) {}
- }
- return Sizzle( expr, document, null, [ elem ] ).length > 0;
- };
- Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
- };
- Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
- };
- Sizzle.escape = function( sel ) {
- return (sel + "").replace( rcssescape, fcssescape );
- };
- Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
- };
- /**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
- Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
- return results;
- };
- /**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
- getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
- return ret;
- };
- Expr = Sizzle.selectors = {
- // Can be adjusted by the user
- cacheLength: 50,
- createPseudo: markFunction,
- match: matchExpr,
- attrHandle: {},
- find: {},
- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
- return match.slice( 0, 4 );
- },
- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
- return match;
- },
- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
- filter: {
- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
- });
- },
- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
- result += "";
- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
- return first === 1 && last === 0 ?
- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
- function( elem, context, xml ) {
- var cache, uniqueCache, outerCache, node, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType,
- diff = false;
- if ( parent ) {
- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) {
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
- start = [ forward ? parent.firstChild : parent.lastChild ];
- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
- // Seek `elem` from a previously-cached index
- // ...in a gzip-friendly way
- node = parent;
- outerCache = node[ expando ] || (node[ expando ] = {});
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex && cache[ 2 ];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
- } else {
- // Use previously-cached element index if available
- if ( useCache ) {
- // ...in a gzip-friendly way
- node = elem;
- outerCache = node[ expando ] || (node[ expando ] = {});
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex;
- }
- // xml :nth-child(...)
- // or :nth-last-child(...) or :nth(-last)?-of-type(...)
- if ( diff === false ) {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
- if ( ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) &&
- ++diff ) {
- // Cache the index of each encountered element
- if ( useCache ) {
- outerCache = node[ expando ] || (node[ expando ] = {});
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
- uniqueCache[ type ] = [ dirruns, diff ];
- }
- if ( node === elem ) {
- break;
- }
- }
- }
- }
- }
- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
- return fn;
- }
- },
- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- // Don't keep the element (issue #299)
- input[0] = null;
- return !results.pop();
- };
- }),
- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
- "contains": markFunction(function( text ) {
- text = text.replace( runescape, funescape );
- return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
- "root": function( elem ) {
- return elem === docElem;
- },
- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
- // Boolean properties
- "enabled": createDisabledPseudo( false ),
- "disabled": createDisabledPseudo( true ),
- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
- return elem.selected === true;
- },
- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
- };
- Expr.pseudos["nth"] = Expr.pseudos["eq"];
- // Add button/input type pseudos
- for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
- }
- for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
- }
- // Easy API for creating new setFilters
- function setFilters() {}
- setFilters.prototype = Expr.filters = Expr.pseudos;
- Expr.setFilters = new setFilters();
- tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
- while ( soFar ) {
- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
- matched = false;
- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
- if ( !matched ) {
- break;
- }
- }
- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
- };
- function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
- }
- function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- skip = combinator.next,
- key = skip || dir,
- checkNonElements = base && key === "parentNode",
- doneName = done++;
- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- return false;
- } :
- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, uniqueCache, outerCache,
- newCache = [ dirruns, doneName ];
- // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
- if ( skip && skip === elem.nodeName.toLowerCase() ) {
- elem = elem[ dir ] || elem;
- } else if ( (oldCache = uniqueCache[ key ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- uniqueCache[ key ] = newCache;
- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- return false;
- };
- }
- function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
- }
- function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
- }
- function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
- return newUnmatched;
- }
- function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
- // ...intermediate processing is necessary
- [] :
- // ...otherwise use results directly
- results :
- matcherIn;
- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
- seed[temp] = !(results[temp] = elem);
- }
- }
- }
- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
- }
- function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- // Avoid hanging onto element (issue #299)
- checkContext = null;
- return ret;
- } ];
- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
- return elementMatcher( matchers );
- }
- function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
- if ( outermost ) {
- outermostContext = context === document || context || outermost;
- }
- // Add elements passing elementMatchers directly to results
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- if ( !context && elem.ownerDocument !== document ) {
- setDocument( elem );
- xml = !documentIsHTML;
- }
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context || document, xml) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
- // `i` is now the count of elements visited above, and adding it to `matchedCount`
- // makes the latter nonnegative.
- matchedCount += i;
- // Apply set filters to unmatched elements
- // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
- // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
- // no element matchers and no seed.
- // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
- // case, which will result in a "00" `matchedCount` that differs from `i` but is also
- // numerically zero.
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
- // Add matches to results
- push.apply( results, setMatched );
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
- Sizzle.uniqueSort( results );
- }
- }
- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
- return unmatched;
- };
- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
- }
- compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
- };
- /**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
- select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
- results = results || [];
- // Try to minimize operations if there is only one selector in the list and no seed
- // (the latter of which guarantees us context)
- if ( match.length === 1 ) {
- // Reduce context if the leading compound selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
- selector = selector.slice( tokens.shift().value.length );
- }
- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
- break;
- }
- }
- }
- }
- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
- };
- // One-time assignments
- // Sort stability
- support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
- // Support: Chrome 14-35+
- // Always assume duplicates if they aren't passed to the comparison function
- support.detectDuplicates = !!hasDuplicate;
- // Initialize against the default document
- setDocument();
- // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
- // Detached nodes confoundingly follow *each other*
- support.sortDetached = assert(function( el ) {
- // Should return 1, but returns 4 (following)
- return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
- });
- // Support: IE<8
- // Prevent attribute/property "interpolation"
- // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
- if ( !assert(function( el ) {
- el.innerHTML = "<a href='#'></a>";
- return el.firstChild.getAttribute("href") === "#" ;
- }) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
- }
- // Support: IE<9
- // Use defaultValue in place of getAttribute("value")
- if ( !support.attributes || !assert(function( el ) {
- el.innerHTML = "<input/>";
- el.firstChild.setAttribute( "value", "" );
- return el.firstChild.getAttribute( "value" ) === "";
- }) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
- }
- // Support: IE<9
- // Use getAttributeNode to fetch booleans when getAttribute lies
- if ( !assert(function( el ) {
- return el.getAttribute("disabled") == null;
- }) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
- }
- return Sizzle;
- })( window );
- jQuery.find = Sizzle;
- jQuery.expr = Sizzle.selectors;
- // Deprecated
- jQuery.expr[ ":" ] = jQuery.expr.pseudos;
- jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
- jQuery.text = Sizzle.getText;
- jQuery.isXMLDoc = Sizzle.isXML;
- jQuery.contains = Sizzle.contains;
- jQuery.escapeSelector = Sizzle.escape;
- var dir = function( elem, dir, until ) {
- var matched = [],
- truncate = until !== undefined;
- while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
- if ( elem.nodeType === 1 ) {
- if ( truncate && jQuery( elem ).is( until ) ) {
- break;
- }
- matched.push( elem );
- }
- }
- return matched;
- };
- var siblings = function( n, elem ) {
- var matched = [];
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- matched.push( n );
- }
- }
- return matched;
- };
- var rneedsContext = jQuery.expr.match.needsContext;
- function nodeName( elem, name ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
- };
- var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
- var risSimple = /^.[^:#\[\.,]*$/;
- // Implement the identical functionality for filter and not
- function winnow( elements, qualifier, not ) {
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep( elements, function( elem, i ) {
- return !!qualifier.call( elem, i, elem ) !== not;
- } );
- }
- // Single element
- if ( qualifier.nodeType ) {
- return jQuery.grep( elements, function( elem ) {
- return ( elem === qualifier ) !== not;
- } );
- }
- // Arraylike of elements (jQuery, arguments, Array)
- if ( typeof qualifier !== "string" ) {
- return jQuery.grep( elements, function( elem ) {
- return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
- } );
- }
- // Simple selector that can be filtered directly, removing non-Elements
- if ( risSimple.test( qualifier ) ) {
- return jQuery.filter( qualifier, elements, not );
- }
- // Complex selector, compare the two sets, removing non-Elements
- qualifier = jQuery.filter( qualifier, elements );
- return jQuery.grep( elements, function( elem ) {
- return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
- } );
- }
- jQuery.filter = function( expr, elems, not ) {
- var elem = elems[ 0 ];
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
- if ( elems.length === 1 && elem.nodeType === 1 ) {
- return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
- }
- return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
- return elem.nodeType === 1;
- } ) );
- };
- jQuery.fn.extend( {
- find: function( selector ) {
- var i, ret,
- len = this.length,
- self = this;
- if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter( function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- } ) );
- }
- ret = this.pushStack( [] );
- for ( i = 0; i < len; i++ ) {
- jQuery.find( selector, self[ i ], ret );
- }
- return len > 1 ? jQuery.uniqueSort( ret ) : ret;
- },
- filter: function( selector ) {
- return this.pushStack( winnow( this, selector || [], false ) );
- },
- not: function( selector ) {
- return this.pushStack( winnow( this, selector || [], true ) );
- },
- is: function( selector ) {
- return !!winnow(
- this,
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- typeof selector === "string" && rneedsContext.test( selector ) ?
- jQuery( selector ) :
- selector || [],
- false
- ).length;
- }
- } );
- // Initialize a jQuery object
- // A central reference to the root jQuery(document)
- var rootjQuery,
- // A simple way to check for HTML strings
- // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
- // Strict HTML recognition (#11290: must start with <)
- // Shortcut simple #id case for speed
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
- init = jQuery.fn.init = function( selector, context, root ) {
- var match, elem;
- // HANDLE: $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
- // Method init() accepts an alternate rootjQuery
- // so migrate can support jQuery.sub (gh-2101)
- root = root || rootjQuery;
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector[ 0 ] === "<" &&
- selector[ selector.length - 1 ] === ">" &&
- selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
- } else {
- match = rquickExpr.exec( selector );
- }
- // Match html or make sure no context is specified for #id
- if ( match && ( match[ 1 ] || !context ) ) {
- // HANDLE: $(html) -> $(array)
- if ( match[ 1 ] ) {
- context = context instanceof jQuery ? context[ 0 ] : context;
- // Option to run scripts is true for back-compat
- // Intentionally let the error be thrown if parseHTML is not present
- jQuery.merge( this, jQuery.parseHTML(
- match[ 1 ],
- context && context.nodeType ? context.ownerDocument || context : document,
- true
- ) );
- // HANDLE: $(html, props)
- if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
- for ( match in context ) {
- // Properties of context are called as methods if possible
- if ( jQuery.isFunction( this[ match ] ) ) {
- this[ match ]( context[ match ] );
- // ...and otherwise set as attributes
- } else {
- this.attr( match, context[ match ] );
- }
- }
- }
- return this;
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[ 2 ] );
- if ( elem ) {
- // Inject the element directly into the jQuery object
- this[ 0 ] = elem;
- this.length = 1;
- }
- return this;
- }
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || root ).find( selector );
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
- // HANDLE: $(DOMElement)
- } else if ( selector.nodeType ) {
- this[ 0 ] = selector;
- this.length = 1;
- return this;
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return root.ready !== undefined ?
- root.ready( selector ) :
- // Execute immediately if ready is not present
- selector( jQuery );
- }
- return jQuery.makeArray( selector, this );
- };
- // Give the init function the jQuery prototype for later instantiation
- init.prototype = jQuery.fn;
- // Initialize central reference
- rootjQuery = jQuery( document );
- var rparentsprev = /^(?:parents|prev(?:Until|All))/,
- // Methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
- jQuery.fn.extend( {
- has: function( target ) {
- var targets = jQuery( target, this ),
- l = targets.length;
- return this.filter( function() {
- var i = 0;
- for ( ; i < l; i++ ) {
- if ( jQuery.contains( this, targets[ i ] ) ) {
- return true;
- }
- }
- } );
- },
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- matched = [],
- targets = typeof selectors !== "string" && jQuery( selectors );
- // Positional selectors never match, since there's no _selection_ context
- if ( !rneedsContext.test( selectors ) ) {
- for ( ; i < l; i++ ) {
- for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
- // Always skip document fragments
- if ( cur.nodeType < 11 && ( targets ?
- targets.index( cur ) > -1 :
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector( cur, selectors ) ) ) {
- matched.push( cur );
- break;
- }
- }
- }
- }
- return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
- },
- // Determine the position of an element within the set
- index: function( elem ) {
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
- }
- // Index in selector
- if ( typeof elem === "string" ) {
- return indexOf.call( jQuery( elem ), this[ 0 ] );
- }
- // Locate the position of the desired element
- return indexOf.call( this,
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[ 0 ] : elem
- );
- },
- add: function( selector, context ) {
- return this.pushStack(
- jQuery.uniqueSort(
- jQuery.merge( this.get(), jQuery( selector, context ) )
- )
- );
- },
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter( selector )
- );
- }
- } );
- function sibling( cur, dir ) {
- while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
- return cur;
- }
- jQuery.each( {
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return siblings( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return siblings( elem.firstChild );
- },
- contents: function( elem ) {
- if ( nodeName( elem, "iframe" ) ) {
- return elem.contentDocument;
- }
- // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
- // Treat the template element as a regular one in browsers that
- // don't support it.
- if ( nodeName( elem, "template" ) ) {
- elem = elem.content || elem;
- }
- return jQuery.merge( [], elem.childNodes );
- }
- }, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var matched = jQuery.map( this, fn, until );
- if ( name.slice( -5 ) !== "Until" ) {
- selector = until;
- }
- if ( selector && typeof selector === "string" ) {
- matched = jQuery.filter( selector, matched );
- }
- if ( this.length > 1 ) {
- // Remove duplicates
- if ( !guaranteedUnique[ name ] ) {
- jQuery.uniqueSort( matched );
- }
- // Reverse order for parents* and prev-derivatives
- if ( rparentsprev.test( name ) ) {
- matched.reverse();
- }
- }
- return this.pushStack( matched );
- };
- } );
- var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
- // Convert String-formatted options into Object-formatted ones
- function createOptions( options ) {
- var object = {};
- jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
- object[ flag ] = true;
- } );
- return object;
- }
- /*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
- jQuery.Callbacks = function( options ) {
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- createOptions( options ) :
- jQuery.extend( {}, options );
- var // Flag to know if list is currently firing
- firing,
- // Last fire value for non-forgettable lists
- memory,
- // Flag to know if list was already fired
- fired,
- // Flag to prevent firing
- locked,
- // Actual callback list
- list = [],
- // Queue of execution data for repeatable lists
- queue = [],
- // Index of currently firing callback (modified by add/remove as needed)
- firingIndex = -1,
- // Fire callbacks
- fire = function() {
- // Enforce single-firing
- locked = locked || options.once;
- // Execute callbacks for all pending executions,
- // respecting firingIndex overrides and runtime changes
- fired = firing = true;
- for ( ; queue.length; firingIndex = -1 ) {
- memory = queue.shift();
- while ( ++firingIndex < list.length ) {
- // Run callback and check for early termination
- if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
- options.stopOnFalse ) {
- // Jump to end and forget the data so .add doesn't re-fire
- firingIndex = list.length;
- memory = false;
- }
- }
- }
- // Forget the data if we're done with it
- if ( !options.memory ) {
- memory = false;
- }
- firing = false;
- // Clean up if we're done firing for good
- if ( locked ) {
- // Keep an empty list if we have data for future add calls
- if ( memory ) {
- list = [];
- // Otherwise, this object is spent
- } else {
- list = "";
- }
- }
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- // If we have memory from a past run, we should fire after adding
- if ( memory && !firing ) {
- firingIndex = list.length - 1;
- queue.push( memory );
- }
- ( function add( args ) {
- jQuery.each( args, function( _, arg ) {
- if ( jQuery.isFunction( arg ) ) {
- if ( !options.unique || !self.has( arg ) ) {
- list.push( arg );
- }
- } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
- // Inspect recursively
- add( arg );
- }
- } );
- } )( arguments );
- if ( memory && !firing ) {
- fire();
- }
- }
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
- // Handle firing indexes
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
- } );
- return this;
- },
- // Check if a given callback is in the list.
- // If no argument is given, return whether or not list has callbacks attached.
- has: function( fn ) {
- return fn ?
- jQuery.inArray( fn, list ) > -1 :
- list.length > 0;
- },
- // Remove all callbacks from the list
- empty: function() {
- if ( list ) {
- list = [];
- }
- return this;
- },
- // Disable .fire and .add
- // Abort any current/pending executions
- // Clear all callbacks and values
- disable: function() {
- locked = queue = [];
- list = memory = "";
- return this;
- },
- disabled: function() {
- return !list;
- },
- // Disable .fire
- // Also disable .add unless we have memory (since it would have no effect)
- // Abort any pending executions
- lock: function() {
- locked = queue = [];
- if ( !memory && !firing ) {
- list = memory = "";
- }
- return this;
- },
- locked: function() {
- return !!locked;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( !locked ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- queue.push( args );
- if ( !firing ) {
- fire();
- }
- }
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
- return self;
- };
- function Identity( v ) {
- return v;
- }
- function Thrower( ex ) {
- throw ex;
- }
- function adoptValue( value, resolve, reject, noValue ) {
- var method;
- try {
- // Check for promise aspect first to privilege synchronous behavior
- if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
- method.call( value ).done( resolve ).fail( reject );
- // Other thenables
- } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
- method.call( value, resolve, reject );
- // Other non-thenables
- } else {
- // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
- // * false: [ value ].slice( 0 ) => resolve( value )
- // * true: [ value ].slice( 1 ) => resolve()
- resolve.apply( undefined, [ value ].slice( noValue ) );
- }
- // For Promises/A+, convert exceptions into rejections
- // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
- // Deferred#then to conditionally suppress rejection.
- } catch ( value ) {
- // Support: Android 4.0 only
- // Strict mode functions invoked without .call/.apply get global-object context
- reject.apply( undefined, [ value ] );
- }
- }
- jQuery.extend( {
- Deferred: function( func ) {
- var tuples = [
- // action, add listener, callbacks,
- // ... .then handlers, argument index, [final state]
- [ "notify", "progress", jQuery.Callbacks( "memory" ),
- jQuery.Callbacks( "memory" ), 2 ],
- [ "resolve", "done", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 0, "resolved" ],
- [ "reject", "fail", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 1, "rejected" ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- "catch": function( fn ) {
- return promise.then( null, fn );
- },
- // Keep pipe for back-compat
- pipe: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
- return jQuery.Deferred( function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
- // Map tuples (progress, done, fail) to arguments (done, fail, progress)
- var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
- // deferred.progress(function() { bind to newDefer or newDefer.notify })
- // deferred.done(function() { bind to newDefer or newDefer.resolve })
- // deferred.fail(function() { bind to newDefer or newDefer.reject })
- deferred[ tuple[ 1 ] ]( function() {
- var returned = fn && fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise()
- .progress( newDefer.notify )
- .done( newDefer.resolve )
- .fail( newDefer.reject );
- } else {
- newDefer[ tuple[ 0 ] + "With" ](
- this,
- fn ? [ returned ] : arguments
- );
- }
- } );
- } );
- fns = null;
- } ).promise();
- },
- then: function( onFulfilled, onRejected, onProgress ) {
- var maxDepth = 0;
- function resolve( depth, deferred, handler, special ) {
- return function() {
- var that = this,
- args = arguments,
- mightThrow = function() {
- var returned, then;
- // Support: Promises/A+ section 2.3.3.3.3
- // https://promisesaplus.com/#point-59
- // Ignore double-resolution attempts
- if ( depth < maxDepth ) {
- return;
- }
- returned = handler.apply( that, args );
- // Support: Promises/A+ section 2.3.1
- // https://promisesaplus.com/#point-48
- if ( returned === deferred.promise() ) {
- throw new TypeError( "Thenable self-resolution" );
- }
- // Support: Promises/A+ sections 2.3.3.1, 3.5
- // https://promisesaplus.com/#point-54
- // https://promisesaplus.com/#point-75
- // Retrieve `then` only once
- then = returned &&
- // Support: Promises/A+ section 2.3.4
- // https://promisesaplus.com/#point-64
- // Only check objects and functions for thenability
- ( typeof returned === "object" ||
- typeof returned === "function" ) &&
- returned.then;
- // Handle a returned thenable
- if ( jQuery.isFunction( then ) ) {
- // Special processors (notify) just wait for resolution
- if ( special ) {
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special )
- );
- // Normal processors (resolve) also hook into progress
- } else {
- // ...and disregard older resolution values
- maxDepth++;
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special ),
- resolve( maxDepth, deferred, Identity,
- deferred.notifyWith )
- );
- }
- // Handle all other returned values
- } else {
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Identity ) {
- that = undefined;
- args = [ returned ];
- }
- // Process the value(s)
- // Default process is resolve
- ( special || deferred.resolveWith )( that, args );
- }
- },
- // Only normal processors (resolve) catch and reject exceptions
- process = special ?
- mightThrow :
- function() {
- try {
- mightThrow();
- } catch ( e ) {
- if ( jQuery.Deferred.exceptionHook ) {
- jQuery.Deferred.exceptionHook( e,
- process.stackTrace );
- }
- // Support: Promises/A+ section 2.3.3.3.4.1
- // https://promisesaplus.com/#point-61
- // Ignore post-resolution exceptions
- if ( depth + 1 >= maxDepth ) {
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Thrower ) {
- that = undefined;
- args = [ e ];
- }
- deferred.rejectWith( that, args );
- }
- }
- };
- // Support: Promises/A+ section 2.3.3.3.1
- // https://promisesaplus.com/#point-57
- // Re-resolve promises immediately to dodge false rejection from
- // subsequent errors
- if ( depth ) {
- process();
- } else {
- // Call an optional hook to record the stack, in case of exception
- // since it's otherwise lost when execution goes async
- if ( jQuery.Deferred.getStackHook ) {
- process.stackTrace = jQuery.Deferred.getStackHook();
- }
- window.setTimeout( process );
- }
- };
- }
- return jQuery.Deferred( function( newDefer ) {
- // progress_handlers.add( ... )
- tuples[ 0 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onProgress ) ?
- onProgress :
- Identity,
- newDefer.notifyWith
- )
- );
- // fulfilled_handlers.add( ... )
- tuples[ 1 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onFulfilled ) ?
- onFulfilled :
- Identity
- )
- );
- // rejected_handlers.add( ... )
- tuples[ 2 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onRejected ) ?
- onRejected :
- Thrower
- )
- );
- } ).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return obj != null ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 5 ];
- // promise.progress = list.add
- // promise.done = list.add
- // promise.fail = list.add
- promise[ tuple[ 1 ] ] = list.add;
- // Handle state
- if ( stateString ) {
- list.add(
- function() {
- // state = "resolved" (i.e., fulfilled)
- // state = "rejected"
- state = stateString;
- },
- // rejected_callbacks.disable
- // fulfilled_callbacks.disable
- tuples[ 3 - i ][ 2 ].disable,
- // progress_callbacks.lock
- tuples[ 0 ][ 2 ].lock
- );
- }
- // progress_handlers.fire
- // fulfilled_handlers.fire
- // rejected_handlers.fire
- list.add( tuple[ 3 ].fire );
- // deferred.notify = function() { deferred.notifyWith(...) }
- // deferred.resolve = function() { deferred.resolveWith(...) }
- // deferred.reject = function() { deferred.rejectWith(...) }
- deferred[ tuple[ 0 ] ] = function() {
- deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
- return this;
- };
- // deferred.notifyWith = list.fireWith
- // deferred.resolveWith = list.fireWith
- // deferred.rejectWith = list.fireWith
- deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
- } );
- // Make the deferred a promise
- promise.promise( deferred );
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
- // All done!
- return deferred;
- },
- // Deferred helper
- when: function( singleValue ) {
- var
- // count of uncompleted subordinates
- remaining = arguments.length,
- // count of unprocessed arguments
- i = remaining,
- // subordinate fulfillment data
- resolveContexts = Array( i ),
- resolveValues = slice.call( arguments ),
- // the master Deferred
- master = jQuery.Deferred(),
- // subordinate callback factory
- updateFunc = function( i ) {
- return function( value ) {
- resolveContexts[ i ] = this;
- resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( !( --remaining ) ) {
- master.resolveWith( resolveContexts, resolveValues );
- }
- };
- };
- // Single- and empty arguments are adopted like Promise.resolve
- if ( remaining <= 1 ) {
- adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
- !remaining );
- // Use .then() to unwrap secondary thenables (cf. gh-3000)
- if ( master.state() === "pending" ||
- jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
- return master.then();
- }
- }
- // Multiple arguments are aggregated like Promise.all array elements
- while ( i-- ) {
- adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
- }
- return master.promise();
- }
- } );
- // These usually indicate a programmer mistake during development,
- // warn about them ASAP rather than swallowing them by default.
- var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
- jQuery.Deferred.exceptionHook = function( error, stack ) {
- // Support: IE 8 - 9 only
- // Console exists when dev tools are open, which can happen at any time
- if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
- window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
- }
- };
- jQuery.readyException = function( error ) {
- window.setTimeout( function() {
- throw error;
- } );
- };
- // The deferred used on DOM ready
- var readyList = jQuery.Deferred();
- jQuery.fn.ready = function( fn ) {
- readyList
- .then( fn )
- // Wrap jQuery.readyException in a function so that the lookup
- // happens at the time of error handling instead of callback
- // registration.
- .catch( function( error ) {
- jQuery.readyException( error );
- } );
- return this;
- };
- jQuery.extend( {
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
- // Handle when the DOM is ready
- ready: function( wait ) {
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
- // Remember that the DOM is ready
- jQuery.isReady = true;
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
- }
- } );
- jQuery.ready.then = readyList.then;
- // The ready event handler and self cleanup method
- function completed() {
- document.removeEventListener( "DOMContentLoaded", completed );
- window.removeEventListener( "load", completed );
- jQuery.ready();
- }
- // Catch cases where $(document).ready() is called
- // after the browser event has already occurred.
- // Support: IE <=9 - 10 only
- // Older IE sometimes signals "interactive" too soon
- if ( document.readyState === "complete" ||
- ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- window.setTimeout( jQuery.ready );
- } else {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed );
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed );
- }
- // Multifunctional method to get and set values of a collection
- // The value/s can optionally be executed if it's a function
- var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- len = elems.length,
- bulk = key == null;
- // Sets many values
- if ( jQuery.type( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- access( elems, fn, i, key[ i ], true, emptyGet, raw );
- }
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
- if ( !jQuery.isFunction( value ) ) {
- raw = true;
- }
- if ( bulk ) {
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
- }
- }
- if ( fn ) {
- for ( ; i < len; i++ ) {
- fn(
- elems[ i ], key, raw ?
- value :
- value.call( elems[ i ], i, fn( elems[ i ], key ) )
- );
- }
- }
- }
- if ( chainable ) {
- return elems;
- }
- // Gets
- if ( bulk ) {
- return fn.call( elems );
- }
- return len ? fn( elems[ 0 ], key ) : emptyGet;
- };
- var acceptData = function( owner ) {
- // Accepts only:
- // - Node
- // - Node.ELEMENT_NODE
- // - Node.DOCUMENT_NODE
- // - Object
- // - Any
- return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
- };
- function Data() {
- this.expando = jQuery.expando + Data.uid++;
- }
- Data.uid = 1;
- Data.prototype = {
- cache: function( owner ) {
- // Check if the owner object already has a cache
- var value = owner[ this.expando ];
- // If not, create one
- if ( !value ) {
- value = {};
- // We can accept data for non-element nodes in modern browsers,
- // but we should not, see #8335.
- // Always return an empty object.
- if ( acceptData( owner ) ) {
- // If it is a node unlikely to be stringify-ed or looped over
- // use plain assignment
- if ( owner.nodeType ) {
- owner[ this.expando ] = value;
- // Otherwise secure it in a non-enumerable property
- // configurable must be true to allow the property to be
- // deleted when data is removed
- } else {
- Object.defineProperty( owner, this.expando, {
- value: value,
- configurable: true
- } );
- }
- }
- }
- return value;
- },
- set: function( owner, data, value ) {
- var prop,
- cache = this.cache( owner );
- // Handle: [ owner, key, value ] args
- // Always use camelCase key (gh-2257)
- if ( typeof data === "string" ) {
- cache[ jQuery.camelCase( data ) ] = value;
- // Handle: [ owner, { properties } ] args
- } else {
- // Copy the properties one-by-one to the cache object
- for ( prop in data ) {
- cache[ jQuery.camelCase( prop ) ] = data[ prop ];
- }
- }
- return cache;
- },
- get: function( owner, key ) {
- return key === undefined ?
- this.cache( owner ) :
- // Always use camelCase key (gh-2257)
- owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
- },
- access: function( owner, key, value ) {
- // In cases where either:
- //
- // 1. No key was specified
- // 2. A string key was specified, but no value provided
- //
- // Take the "read" path and allow the get method to determine
- // which value to return, respectively either:
- //
- // 1. The entire cache object
- // 2. The data stored at the key
- //
- if ( key === undefined ||
- ( ( key && typeof key === "string" ) && value === undefined ) ) {
- return this.get( owner, key );
- }
- // When the key is not a string, or both a key and value
- // are specified, set or extend (existing objects) with either:
- //
- // 1. An object of properties
- // 2. A key and value
- //
- this.set( owner, key, value );
- // Since the "set" path can have two possible entry points
- // return the expected data based on which path was taken[*]
- return value !== undefined ? value : key;
- },
- remove: function( owner, key ) {
- var i,
- cache = owner[ this.expando ];
- if ( cache === undefined ) {
- return;
- }
- if ( key !== undefined ) {
- // Support array or space separated string of keys
- if ( Array.isArray( key ) ) {
- // If key is an array of keys...
- // We always set camelCase keys, so remove that.
- key = key.map( jQuery.camelCase );
- } else {
- key = jQuery.camelCase( key );
- // If a key with the spaces exists, use it.
- // Otherwise, create an array by matching non-whitespace
- key = key in cache ?
- [ key ] :
- ( key.match( rnothtmlwhite ) || [] );
- }
- i = key.length;
- while ( i-- ) {
- delete cache[ key[ i ] ];
- }
- }
- // Remove the expando if there's no more data
- if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
- // Support: Chrome <=35 - 45
- // Webkit & Blink performance suffers when deleting properties
- // from DOM nodes, so set to undefined instead
- // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
- if ( owner.nodeType ) {
- owner[ this.expando ] = undefined;
- } else {
- delete owner[ this.expando ];
- }
- }
- },
- hasData: function( owner ) {
- var cache = owner[ this.expando ];
- return cache !== undefined && !jQuery.isEmptyObject( cache );
- }
- };
- var dataPriv = new Data();
- var dataUser = new Data();
- // Implementation Summary
- //
- // 1. Enforce API surface and semantic compatibility with 1.9.x branch
- // 2. Improve the module's maintainability by reducing the storage
- // paths to a single mechanism.
- // 3. Use the same single mechanism to support "private" and "user" data.
- // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
- // 5. Avoid exposing implementation details on user objects (eg. expando properties)
- // 6. Provide a clear path for implementation upgrade to WeakMap in 2014
- var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /[A-Z]/g;
- function getData( data ) {
- if ( data === "true" ) {
- return true;
- }
- if ( data === "false" ) {
- return false;
- }
- if ( data === "null" ) {
- return null;
- }
- // Only convert to a number if it doesn't change the string
- if ( data === +data + "" ) {
- return +data;
- }
- if ( rbrace.test( data ) ) {
- return JSON.parse( data );
- }
- return data;
- }
- function dataAttr( elem, key, data ) {
- var name;
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
- name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
- data = elem.getAttribute( name );
- if ( typeof data === "string" ) {
- try {
- data = getData( data );
- } catch ( e ) {}
- // Make sure we set the data so it isn't changed later
- dataUser.set( elem, key, data );
- } else {
- data = undefined;
- }
- }
- return data;
- }
- jQuery.extend( {
- hasData: function( elem ) {
- return dataUser.hasData( elem ) || dataPriv.hasData( elem );
- },
- data: function( elem, name, data ) {
- return dataUser.access( elem, name, data );
- },
- removeData: function( elem, name ) {
- dataUser.remove( elem, name );
- },
- // TODO: Now that all calls to _data and _removeData have been replaced
- // with direct calls to dataPriv methods, these can be deprecated.
- _data: function( elem, name, data ) {
- return dataPriv.access( elem, name, data );
- },
- _removeData: function( elem, name ) {
- dataPriv.remove( elem, name );
- }
- } );
- jQuery.fn.extend( {
- data: function( key, value ) {
- var i, name, data,
- elem = this[ 0 ],
- attrs = elem && elem.attributes;
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = dataUser.get( elem );
- if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
- i = attrs.length;
- while ( i-- ) {
- // Support: IE 11 only
- // The attrs elements can be null (#14894)
- if ( attrs[ i ] ) {
- name = attrs[ i ].name;
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice( 5 ) );
- dataAttr( elem, name, data[ name ] );
- }
- }
- }
- dataPriv.set( elem, "hasDataAttrs", true );
- }
- }
- return data;
- }
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each( function() {
- dataUser.set( this, key );
- } );
- }
- return access( this, function( value ) {
- var data;
- // The calling jQuery object (element matches) is not empty
- // (and therefore has an element appears at this[ 0 ]) and the
- // `value` parameter was not undefined. An empty jQuery object
- // will result in `undefined` for elem = this[ 0 ] which will
- // throw an exception if an attempt to read a data cache is made.
- if ( elem && value === undefined ) {
- // Attempt to get data from the cache
- // The key will always be camelCased in Data
- data = dataUser.get( elem, key );
- if ( data !== undefined ) {
- return data;
- }
- // Attempt to "discover" the data in
- // HTML5 custom data-* attrs
- data = dataAttr( elem, key );
- if ( data !== undefined ) {
- return data;
- }
- // We tried really hard, but the data doesn't exist.
- return;
- }
- // Set the data...
- this.each( function() {
- // We always store the camelCased key
- dataUser.set( this, key, value );
- } );
- }, null, value, arguments.length > 1, null, true );
- },
- removeData: function( key ) {
- return this.each( function() {
- dataUser.remove( this, key );
- } );
- }
- } );
- jQuery.extend( {
- queue: function( elem, type, data ) {
- var queue;
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = dataPriv.get( elem, type );
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || Array.isArray( data ) ) {
- queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
- dequeue: function( elem, type ) {
- type = type || "fx";
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
- if ( fn ) {
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
- // Clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
- // Not public - generate a queueHooks object, or return the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
- empty: jQuery.Callbacks( "once memory" ).add( function() {
- dataPriv.remove( elem, [ type + "queue", key ] );
- } )
- } );
- }
- } );
- jQuery.fn.extend( {
- queue: function( type, data ) {
- var setter = 2;
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
- if ( arguments.length < setter ) {
- return jQuery.queue( this[ 0 ], type );
- }
- return data === undefined ?
- this :
- this.each( function() {
- var queue = jQuery.queue( this, type, data );
- // Ensure a hooks for this queue
- jQuery._queueHooks( this, type );
- if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- } );
- },
- dequeue: function( type ) {
- return this.each( function() {
- jQuery.dequeue( this, type );
- } );
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
- while ( i-- ) {
- tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
- } );
- var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
- var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
- var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
- var isHiddenWithinTree = function( elem, el ) {
- // isHiddenWithinTree might be called from jQuery#filter function;
- // in that case, element will be second argument
- elem = el || elem;
- // Inline style trumps all
- return elem.style.display === "none" ||
- elem.style.display === "" &&
- // Otherwise, check computed style
- // Support: Firefox <=43 - 45
- // Disconnected elements can have computed display: none, so first confirm that elem is
- // in the document.
- jQuery.contains( elem.ownerDocument, elem ) &&
- jQuery.css( elem, "display" ) === "none";
- };
- var swap = function( elem, options, callback, args ) {
- var ret, name,
- old = {};
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
- ret = callback.apply( elem, args || [] );
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
- return ret;
- };
- function adjustCSS( elem, prop, valueParts, tween ) {
- var adjusted,
- scale = 1,
- maxIterations = 20,
- currentValue = tween ?
- function() {
- return tween.cur();
- } :
- function() {
- return jQuery.css( elem, prop, "" );
- },
- initial = currentValue(),
- unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
- // Starting value computation is required for potential unit mismatches
- initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
- rcssNum.exec( jQuery.css( elem, prop ) );
- if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
- // Trust units reported by jQuery.css
- unit = unit || initialInUnit[ 3 ];
- // Make sure we update the tween properties later on
- valueParts = valueParts || [];
- // Iteratively approximate from a nonzero starting point
- initialInUnit = +initial || 1;
- do {
- // If previous iteration zeroed out, double until we get *something*.
- // Use string for doubling so we don't accidentally see scale as unchanged below
- scale = scale || ".5";
- // Adjust and apply
- initialInUnit = initialInUnit / scale;
- jQuery.style( elem, prop, initialInUnit + unit );
- // Update scale, tolerating zero or NaN from tween.cur()
- // Break the loop if scale is unchanged or perfect, or if we've just had enough.
- } while (
- scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
- );
- }
- if ( valueParts ) {
- initialInUnit = +initialInUnit || +initial || 0;
- // Apply relative offset (+=/-=) if specified
- adjusted = valueParts[ 1 ] ?
- initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
- +valueParts[ 2 ];
- if ( tween ) {
- tween.unit = unit;
- tween.start = initialInUnit;
- tween.end = adjusted;
- }
- }
- return adjusted;
- }
- var defaultDisplayMap = {};
- function getDefaultDisplay( elem ) {
- var temp,
- doc = elem.ownerDocument,
- nodeName = elem.nodeName,
- display = defaultDisplayMap[ nodeName ];
- if ( display ) {
- return display;
- }
- temp = doc.body.appendChild( doc.createElement( nodeName ) );
- display = jQuery.css( temp, "display" );
- temp.parentNode.removeChild( temp );
- if ( display === "none" ) {
- display = "block";
- }
- defaultDisplayMap[ nodeName ] = display;
- return display;
- }
- function showHide( elements, show ) {
- var display, elem,
- values = [],
- index = 0,
- length = elements.length;
- // Determine new display value for elements that need to change
- for ( ; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
- display = elem.style.display;
- if ( show ) {
- // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
- // check is required in this first loop unless we have a nonempty display value (either
- // inline or about-to-be-restored)
- if ( display === "none" ) {
- values[ index ] = dataPriv.get( elem, "display" ) || null;
- if ( !values[ index ] ) {
- elem.style.display = "";
- }
- }
- if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
- values[ index ] = getDefaultDisplay( elem );
- }
- } else {
- if ( display !== "none" ) {
- values[ index ] = "none";
- // Remember what we're overwriting
- dataPriv.set( elem, "display", display );
- }
- }
- }
- // Set the display of the elements in a second loop to avoid constant reflow
- for ( index = 0; index < length; index++ ) {
- if ( values[ index ] != null ) {
- elements[ index ].style.display = values[ index ];
- }
- }
- return elements;
- }
- jQuery.fn.extend( {
- show: function() {
- return showHide( this, true );
- },
- hide: function() {
- return showHide( this );
- },
- toggle: function( state ) {
- if ( typeof state === "boolean" ) {
- return state ? this.show() : this.hide();
- }
- return this.each( function() {
- if ( isHiddenWithinTree( this ) ) {
- jQuery( this ).show();
- } else {
- jQuery( this ).hide();
- }
- } );
- }
- } );
- var rcheckableType = ( /^(?:checkbox|radio)$/i );
- var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
- var rscriptType = ( /^$|\/(?:java|ecma)script/i );
- // We have to close these tags to support XHTML (#13200)
- var wrapMap = {
- // Support: IE <=9 only
- option: [ 1, "<select multiple='multiple'>", "</select>" ],
- // XHTML parsers do not magically insert elements in the
- // same way that tag soup parsers do. So we cannot shorten
- // this by omitting <tbody> or other required elements.
- thead: [ 1, "<table>", "</table>" ],
- col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
- tr: [ 2, "<table><tbody>", "</tbody></table>" ],
- td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
- _default: [ 0, "", "" ]
- };
- // Support: IE <=9 only
- wrapMap.optgroup = wrapMap.option;
- wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
- wrapMap.th = wrapMap.td;
- function getAll( context, tag ) {
- // Support: IE <=9 - 11 only
- // Use typeof to avoid zero-argument method invocation on host objects (#15151)
- var ret;
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- ret = context.getElementsByTagName( tag || "*" );
- } else if ( typeof context.querySelectorAll !== "undefined" ) {
- ret = context.querySelectorAll( tag || "*" );
- } else {
- ret = [];
- }
- if ( tag === undefined || tag && nodeName( context, tag ) ) {
- return jQuery.merge( [ context ], ret );
- }
- return ret;
- }
- // Mark scripts as having already been evaluated
- function setGlobalEval( elems, refElements ) {
- var i = 0,
- l = elems.length;
- for ( ; i < l; i++ ) {
- dataPriv.set(
- elems[ i ],
- "globalEval",
- !refElements || dataPriv.get( refElements[ i ], "globalEval" )
- );
- }
- }
- var rhtml = /<|&#?\w+;/;
- function buildFragment( elems, context, scripts, selection, ignored ) {
- var elem, tmp, tag, wrap, contains, j,
- fragment = context.createDocumentFragment(),
- nodes = [],
- i = 0,
- l = elems.length;
- for ( ; i < l; i++ ) {
- elem = elems[ i ];
- if ( elem || elem === 0 ) {
- // Add nodes directly
- if ( jQuery.type( elem ) === "object" ) {
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
- // Convert non-html into a text node
- } else if ( !rhtml.test( elem ) ) {
- nodes.push( context.createTextNode( elem ) );
- // Convert html into DOM nodes
- } else {
- tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
- // Deserialize a standard representation
- tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
- wrap = wrapMap[ tag ] || wrapMap._default;
- tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
- // Descend through wrappers to the right content
- j = wrap[ 0 ];
- while ( j-- ) {
- tmp = tmp.lastChild;
- }
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, tmp.childNodes );
- // Remember the top-level container
- tmp = fragment.firstChild;
- // Ensure the created nodes are orphaned (#12392)
- tmp.textContent = "";
- }
- }
- }
- // Remove wrapper from fragment
- fragment.textContent = "";
- i = 0;
- while ( ( elem = nodes[ i++ ] ) ) {
- // Skip elements already in the context collection (trac-4087)
- if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
- if ( ignored ) {
- ignored.push( elem );
- }
- continue;
- }
- contains = jQuery.contains( elem.ownerDocument, elem );
- // Append to fragment
- tmp = getAll( fragment.appendChild( elem ), "script" );
- // Preserve script evaluation history
- if ( contains ) {
- setGlobalEval( tmp );
- }
- // Capture executables
- if ( scripts ) {
- j = 0;
- while ( ( elem = tmp[ j++ ] ) ) {
- if ( rscriptType.test( elem.type || "" ) ) {
- scripts.push( elem );
- }
- }
- }
- }
- return fragment;
- }
- ( function() {
- var fragment = document.createDocumentFragment(),
- div = fragment.appendChild( document.createElement( "div" ) ),
- input = document.createElement( "input" );
- // Support: Android 4.0 - 4.3 only
- // Check state lost if the name is set (#11217)
- // Support: Windows Web Apps (WWA)
- // `name` and `type` must use .setAttribute for WWA (#14901)
- input.setAttribute( "type", "radio" );
- input.setAttribute( "checked", "checked" );
- input.setAttribute( "name", "t" );
- div.appendChild( input );
- // Support: Android <=4.1 only
- // Older WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
- // Support: IE <=11 only
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- div.innerHTML = "<textarea>x</textarea>";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
- } )();
- var documentElement = document.documentElement;
- var
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
- function returnTrue() {
- return true;
- }
- function returnFalse() {
- return false;
- }
- // Support: IE <=9 only
- // See #13393 for more info
- function safeActiveElement() {
- try {
- return document.activeElement;
- } catch ( err ) { }
- }
- function on( elem, types, selector, data, fn, one ) {
- var origFn, type;
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- on( elem, type, selector, data, types[ type ], one );
- }
- return elem;
- }
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return elem;
- }
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return elem.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- } );
- }
- /*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
- jQuery.event = {
- global: {},
- add: function( elem, types, handler, data, selector ) {
- var handleObjIn, eventHandle, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.get( elem );
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
- // Ensure that invalid selectors throw exceptions at attach time
- // Evaluate against documentElement in case elem is a non-element node (e.g., document)
- if ( selector ) {
- jQuery.find.matchesSelector( documentElement, selector );
- }
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
- // Init the element's event structure and main handler, if this is the first
- if ( !( events = elemData.events ) ) {
- events = elemData.events = {};
- }
- if ( !( eventHandle = elemData.handle ) ) {
- eventHandle = elemData.handle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
- jQuery.event.dispatch.apply( elem, arguments ) : undefined;
- };
- }
- // Handle multiple events separated by a space
- types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
- // There *must* be a type, no attaching namespace-only handlers
- if ( !type ) {
- continue;
- }
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend( {
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join( "." )
- }, handleObjIn );
- // Init the event handler queue if we're the first
- if ( !( handlers = events[ type ] ) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
- // Only use addEventListener if the special events handler returns false
- if ( !special.setup ||
- special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle );
- }
- }
- }
- if ( special.add ) {
- special.add.call( elem, handleObj );
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
- },
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
- var j, origCount, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
- if ( !elemData || !( events = elemData.events ) ) {
- return;
- }
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[ 2 ] &&
- new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector ||
- selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown ||
- special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
- delete events[ type ];
- }
- }
- // Remove data and the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- dataPriv.remove( elem, "handle events" );
- }
- },
- dispatch: function( nativeEvent ) {
- // Make a writable jQuery.Event from the native event object
- var event = jQuery.event.fix( nativeEvent );
- var i, j, ret, matched, handleObj, handlerQueue,
- args = new Array( arguments.length ),
- handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[ 0 ] = event;
- for ( i = 1; i < arguments.length; i++ ) {
- args[ i ] = arguments[ i ];
- }
- event.delegateTarget = this;
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
- j = 0;
- while ( ( handleObj = matched.handlers[ j++ ] ) &&
- !event.isImmediatePropagationStopped() ) {
- // Triggered event must either 1) have no namespace, or 2) have namespace(s)
- // a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
- event.handleObj = handleObj;
- event.data = handleObj.data;
- ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
- handleObj.handler ).apply( matched.elem, args );
- if ( ret !== undefined ) {
- if ( ( event.result = ret ) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
- return event.result;
- },
- handlers: function( event, handlers ) {
- var i, handleObj, sel, matchedHandlers, matchedSelectors,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
- // Find delegate handlers
- if ( delegateCount &&
- // Support: IE <=9
- // Black-hole SVG <use> instance trees (trac-13180)
- cur.nodeType &&
- // Support: Firefox <=42
- // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
- // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
- // Support: IE 11 only
- // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
- !( event.type === "click" && event.button >= 1 ) ) {
- for ( ; cur !== this; cur = cur.parentNode || this ) {
- // Don't check non-elements (#13208)
- // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
- if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
- matchedHandlers = [];
- matchedSelectors = {};
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
- // Don't conflict with Object.prototype properties (#13203)
- sel = handleObj.selector + " ";
- if ( matchedSelectors[ sel ] === undefined ) {
- matchedSelectors[ sel ] = handleObj.needsContext ?
- jQuery( sel, this ).index( cur ) > -1 :
- jQuery.find( sel, this, null, [ cur ] ).length;
- }
- if ( matchedSelectors[ sel ] ) {
- matchedHandlers.push( handleObj );
- }
- }
- if ( matchedHandlers.length ) {
- handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
- }
- }
- }
- }
- // Add the remaining (directly-bound) handlers
- cur = this;
- if ( delegateCount < handlers.length ) {
- handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
- }
- return handlerQueue;
- },
- addProp: function( name, hook ) {
- Object.defineProperty( jQuery.Event.prototype, name, {
- enumerable: true,
- configurable: true,
- get: jQuery.isFunction( hook ) ?
- function() {
- if ( this.originalEvent ) {
- return hook( this.originalEvent );
- }
- } :
- function() {
- if ( this.originalEvent ) {
- return this.originalEvent[ name ];
- }
- },
- set: function( value ) {
- Object.defineProperty( this, name, {
- enumerable: true,
- configurable: true,
- writable: true,
- value: value
- } );
- }
- } );
- },
- fix: function( originalEvent ) {
- return originalEvent[ jQuery.expando ] ?
- originalEvent :
- new jQuery.Event( originalEvent );
- },
- special: {
- load: {
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
- },
- focus: {
- // Fire native event if possible so blur/focus sequence is correct
- trigger: function() {
- if ( this !== safeActiveElement() && this.focus ) {
- this.focus();
- return false;
- }
- },
- delegateType: "focusin"
- },
- blur: {
- trigger: function() {
- if ( this === safeActiveElement() && this.blur ) {
- this.blur();
- return false;
- }
- },
- delegateType: "focusout"
- },
- click: {
- // For checkbox, fire native event so checked state will be right
- trigger: function() {
- if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
- this.click();
- return false;
- }
- },
- // For cross-browser consistency, don't fire native .click() on links
- _default: function( event ) {
- return nodeName( event.target, "a" );
- }
- },
- beforeunload: {
- postDispatch: function( event ) {
- // Support: Firefox 20+
- // Firefox doesn't alert if the returnValue field is not set.
- if ( event.result !== undefined && event.originalEvent ) {
- event.originalEvent.returnValue = event.result;
- }
- }
- }
- }
- };
- jQuery.removeEvent = function( elem, type, handle ) {
- // This "if" is needed for plain objects
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle );
- }
- };
- jQuery.Event = function( src, props ) {
- // Allow instantiation without the 'new' keyword
- if ( !( this instanceof jQuery.Event ) ) {
- return new jQuery.Event( src, props );
- }
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = src.defaultPrevented ||
- src.defaultPrevented === undefined &&
- // Support: Android <=2.3 only
- src.returnValue === false ?
- returnTrue :
- returnFalse;
- // Create target properties
- // Support: Safari <=6 - 7 only
- // Target should not be a text node (#504, #13143)
- this.target = ( src.target && src.target.nodeType === 3 ) ?
- src.target.parentNode :
- src.target;
- this.currentTarget = src.currentTarget;
- this.relatedTarget = src.relatedTarget;
- // Event type
- } else {
- this.type = src;
- }
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
- // Mark it as fixed
- this[ jQuery.expando ] = true;
- };
- // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
- // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
- jQuery.Event.prototype = {
- constructor: jQuery.Event,
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse,
- isSimulated: false,
- preventDefault: function() {
- var e = this.originalEvent;
- this.isDefaultPrevented = returnTrue;
- if ( e && !this.isSimulated ) {
- e.preventDefault();
- }
- },
- stopPropagation: function() {
- var e = this.originalEvent;
- this.isPropagationStopped = returnTrue;
- if ( e && !this.isSimulated ) {
- e.stopPropagation();
- }
- },
- stopImmediatePropagation: function() {
- var e = this.originalEvent;
- this.isImmediatePropagationStopped = returnTrue;
- if ( e && !this.isSimulated ) {
- e.stopImmediatePropagation();
- }
- this.stopPropagation();
- }
- };
- // Includes all common event props including KeyEvent and MouseEvent specific props
- jQuery.each( {
- altKey: true,
- bubbles: true,
- cancelable: true,
- changedTouches: true,
- ctrlKey: true,
- detail: true,
- eventPhase: true,
- metaKey: true,
- pageX: true,
- pageY: true,
- shiftKey: true,
- view: true,
- "char": true,
- charCode: true,
- key: true,
- keyCode: true,
- button: true,
- buttons: true,
- clientX: true,
- clientY: true,
- offsetX: true,
- offsetY: true,
- pointerId: true,
- pointerType: true,
- screenX: true,
- screenY: true,
- targetTouches: true,
- toElement: true,
- touches: true,
- which: function( event ) {
- var button = event.button;
- // Add which for key events
- if ( event.which == null && rkeyEvent.test( event.type ) ) {
- return event.charCode != null ? event.charCode : event.keyCode;
- }
- // Add which for click: 1 === left; 2 === middle; 3 === right
- if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
- if ( button & 1 ) {
- return 1;
- }
- if ( button & 2 ) {
- return 3;
- }
- if ( button & 4 ) {
- return 2;
- }
- return 0;
- }
- return event.which;
- }
- }, jQuery.event.addProp );
- // Create mouseenter/leave events using mouseover/out and event-time checks
- // so that event delegation works in jQuery.
- // Do the same for pointerenter/pointerleave and pointerover/pointerout
- //
- // Support: Safari 7 only
- // Safari sends mouseenter too often; see:
- // https://bugs.chromium.org/p/chromium/issues/detail?id=470258
- // for the description of the bug (it existed in older Chrome versions as well).
- jQuery.each( {
- mouseenter: "mouseover",
- mouseleave: "mouseout",
- pointerenter: "pointerover",
- pointerleave: "pointerout"
- }, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
- handle: function( event ) {
- var ret,
- target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj;
- // For mouseenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
- } );
- jQuery.fn.extend( {
- on: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn );
- },
- one: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- var handleObj, type;
- if ( types && types.preventDefault && types.handleObj ) {
- // ( event ) dispatched jQuery.Event
- handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace ?
- handleObj.origType + "." + handleObj.namespace :
- handleObj.origType,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
- // ( types-object [, selector] )
- for ( type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each( function() {
- jQuery.event.remove( this, types, fn, selector );
- } );
- }
- } );
- var
- /* eslint-disable max-len */
- // See https://github.com/eslint/eslint/issues/3229
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
- /* eslint-enable */
- // Support: IE <=10 - 11, Edge 12 - 13
- // In IE/Edge using regex groups here causes severe slowdowns.
- // See https://connect.microsoft.com/IE/feedback/details/1736512/
- rnoInnerhtml = /<script|<style|<link/i,
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptTypeMasked = /^true\/(.*)/,
- rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
- // Prefer a tbody over its parent table for containing new rows
- function manipulationTarget( elem, content ) {
- if ( nodeName( elem, "table" ) &&
- nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
- return jQuery( ">tbody", elem )[ 0 ] || elem;
- }
- return elem;
- }
- // Replace/restore the type attribute of script elements for safe DOM manipulation
- function disableScript( elem ) {
- elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
- return elem;
- }
- function restoreScript( elem ) {
- var match = rscriptTypeMasked.exec( elem.type );
- if ( match ) {
- elem.type = match[ 1 ];
- } else {
- elem.removeAttribute( "type" );
- }
- return elem;
- }
- function cloneCopyEvent( src, dest ) {
- var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
- if ( dest.nodeType !== 1 ) {
- return;
- }
- // 1. Copy private data: events, handlers, etc.
- if ( dataPriv.hasData( src ) ) {
- pdataOld = dataPriv.access( src );
- pdataCur = dataPriv.set( dest, pdataOld );
- events = pdataOld.events;
- if ( events ) {
- delete pdataCur.handle;
- pdataCur.events = {};
- for ( type in events ) {
- for ( i = 0, l = events[ type ].length; i < l; i++ ) {
- jQuery.event.add( dest, type, events[ type ][ i ] );
- }
- }
- }
- }
- // 2. Copy user data
- if ( dataUser.hasData( src ) ) {
- udataOld = dataUser.access( src );
- udataCur = jQuery.extend( {}, udataOld );
- dataUser.set( dest, udataCur );
- }
- }
- // Fix IE bugs, see support tests
- function fixInput( src, dest ) {
- var nodeName = dest.nodeName.toLowerCase();
- // Fails to persist the checked state of a cloned checkbox or radio button.
- if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
- dest.checked = src.checked;
- // Fails to return the selected option to the default selected state when cloning options
- } else if ( nodeName === "input" || nodeName === "textarea" ) {
- dest.defaultValue = src.defaultValue;
- }
- }
- function domManip( collection, args, callback, ignored ) {
- // Flatten any nested arrays
- args = concat.apply( [], args );
- var fragment, first, scripts, hasScripts, node, doc,
- i = 0,
- l = collection.length,
- iNoClone = l - 1,
- value = args[ 0 ],
- isFunction = jQuery.isFunction( value );
- // We can't cloneNode fragments that contain checked, in WebKit
- if ( isFunction ||
- ( l > 1 && typeof value === "string" &&
- !support.checkClone && rchecked.test( value ) ) ) {
- return collection.each( function( index ) {
- var self = collection.eq( index );
- if ( isFunction ) {
- args[ 0 ] = value.call( this, index, self.html() );
- }
- domManip( self, args, callback, ignored );
- } );
- }
- if ( l ) {
- fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
- first = fragment.firstChild;
- if ( fragment.childNodes.length === 1 ) {
- fragment = first;
- }
- // Require either new content or an interest in ignored elements to invoke the callback
- if ( first || ignored ) {
- scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
- hasScripts = scripts.length;
- // Use the original fragment for the last item
- // instead of the first because it can end up
- // being emptied incorrectly in certain situations (#8070).
- for ( ; i < l; i++ ) {
- node = fragment;
- if ( i !== iNoClone ) {
- node = jQuery.clone( node, true, true );
- // Keep references to cloned scripts for later restoration
- if ( hasScripts ) {
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( scripts, getAll( node, "script" ) );
- }
- }
- callback.call( collection[ i ], node, i );
- }
- if ( hasScripts ) {
- doc = scripts[ scripts.length - 1 ].ownerDocument;
- // Reenable scripts
- jQuery.map( scripts, restoreScript );
- // Evaluate executable scripts on first document insertion
- for ( i = 0; i < hasScripts; i++ ) {
- node = scripts[ i ];
- if ( rscriptType.test( node.type || "" ) &&
- !dataPriv.access( node, "globalEval" ) &&
- jQuery.contains( doc, node ) ) {
- if ( node.src ) {
- // Optional AJAX dependency, but won't run scripts if not present
- if ( jQuery._evalUrl ) {
- jQuery._evalUrl( node.src );
- }
- } else {
- DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
- }
- }
- }
- }
- }
- }
- return collection;
- }
- function remove( elem, selector, keepData ) {
- var node,
- nodes = selector ? jQuery.filter( selector, elem ) : elem,
- i = 0;
- for ( ; ( node = nodes[ i ] ) != null; i++ ) {
- if ( !keepData && node.nodeType === 1 ) {
- jQuery.cleanData( getAll( node ) );
- }
- if ( node.parentNode ) {
- if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
- setGlobalEval( getAll( node, "script" ) );
- }
- node.parentNode.removeChild( node );
- }
- }
- return elem;
- }
- jQuery.extend( {
- htmlPrefilter: function( html ) {
- return html.replace( rxhtmlTag, "<$1></$2>" );
- },
- clone: function( elem, dataAndEvents, deepDataAndEvents ) {
- var i, l, srcElements, destElements,
- clone = elem.cloneNode( true ),
- inPage = jQuery.contains( elem.ownerDocument, elem );
- // Fix IE cloning issues
- if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
- !jQuery.isXMLDoc( elem ) ) {
- // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
- destElements = getAll( clone );
- srcElements = getAll( elem );
- for ( i = 0, l = srcElements.length; i < l; i++ ) {
- fixInput( srcElements[ i ], destElements[ i ] );
- }
- }
- // Copy the events from the original to the clone
- if ( dataAndEvents ) {
- if ( deepDataAndEvents ) {
- srcElements = srcElements || getAll( elem );
- destElements = destElements || getAll( clone );
- for ( i = 0, l = srcElements.length; i < l; i++ ) {
- cloneCopyEvent( srcElements[ i ], destElements[ i ] );
- }
- } else {
- cloneCopyEvent( elem, clone );
- }
- }
- // Preserve script evaluation history
- destElements = getAll( clone, "script" );
- if ( destElements.length > 0 ) {
- setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
- }
- // Return the cloned set
- return clone;
- },
- cleanData: function( elems ) {
- var data, elem, type,
- special = jQuery.event.special,
- i = 0;
- for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
- if ( acceptData( elem ) ) {
- if ( ( data = elem[ dataPriv.expando ] ) ) {
- if ( data.events ) {
- for ( type in data.events ) {
- if ( special[ type ] ) {
- jQuery.event.remove( elem, type );
- // This is a shortcut to avoid jQuery.event.remove's overhead
- } else {
- jQuery.removeEvent( elem, type, data.handle );
- }
- }
- }
- // Support: Chrome <=35 - 45+
- // Assign undefined instead of using delete, see Data#remove
- elem[ dataPriv.expando ] = undefined;
- }
- if ( elem[ dataUser.expando ] ) {
- // Support: Chrome <=35 - 45+
- // Assign undefined instead of using delete, see Data#remove
- elem[ dataUser.expando ] = undefined;
- }
- }
- }
- }
- } );
- jQuery.fn.extend( {
- detach: function( selector ) {
- return remove( this, selector, true );
- },
- remove: function( selector ) {
- return remove( this, selector );
- },
- text: function( value ) {
- return access( this, function( value ) {
- return value === undefined ?
- jQuery.text( this ) :
- this.empty().each( function() {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- this.textContent = value;
- }
- } );
- }, null, value, arguments.length );
- },
- append: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- var target = manipulationTarget( this, elem );
- target.appendChild( elem );
- }
- } );
- },
- prepend: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- var target = manipulationTarget( this, elem );
- target.insertBefore( elem, target.firstChild );
- }
- } );
- },
- before: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.parentNode ) {
- this.parentNode.insertBefore( elem, this );
- }
- } );
- },
- after: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.parentNode ) {
- this.parentNode.insertBefore( elem, this.nextSibling );
- }
- } );
- },
- empty: function() {
- var elem,
- i = 0;
- for ( ; ( elem = this[ i ] ) != null; i++ ) {
- if ( elem.nodeType === 1 ) {
- // Prevent memory leaks
- jQuery.cleanData( getAll( elem, false ) );
- // Remove any remaining nodes
- elem.textContent = "";
- }
- }
- return this;
- },
- clone: function( dataAndEvents, deepDataAndEvents ) {
- dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
- deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
- return this.map( function() {
- return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
- } );
- },
- html: function( value ) {
- return access( this, function( value ) {
- var elem = this[ 0 ] || {},
- i = 0,
- l = this.length;
- if ( value === undefined && elem.nodeType === 1 ) {
- return elem.innerHTML;
- }
- // See if we can take a shortcut and just use innerHTML
- if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
- !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
- value = jQuery.htmlPrefilter( value );
- try {
- for ( ; i < l; i++ ) {
- elem = this[ i ] || {};
- // Remove element nodes and prevent memory leaks
- if ( elem.nodeType === 1 ) {
- jQuery.cleanData( getAll( elem, false ) );
- elem.innerHTML = value;
- }
- }
- elem = 0;
- // If using innerHTML throws an exception, use the fallback method
- } catch ( e ) {}
- }
- if ( elem ) {
- this.empty().append( value );
- }
- }, null, value, arguments.length );
- },
- replaceWith: function() {
- var ignored = [];
- // Make the changes, replacing each non-ignored context element with the new content
- return domManip( this, arguments, function( elem ) {
- var parent = this.parentNode;
- if ( jQuery.inArray( this, ignored ) < 0 ) {
- jQuery.cleanData( getAll( this ) );
- if ( parent ) {
- parent.replaceChild( elem, this );
- }
- }
- // Force callback invocation
- }, ignored );
- }
- } );
- jQuery.each( {
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
- }, function( name, original ) {
- jQuery.fn[ name ] = function( selector ) {
- var elems,
- ret = [],
- insert = jQuery( selector ),
- last = insert.length - 1,
- i = 0;
- for ( ; i <= last; i++ ) {
- elems = i === last ? this : this.clone( true );
- jQuery( insert[ i ] )[ original ]( elems );
- // Support: Android <=4.0 only, PhantomJS 1 only
- // .get() because push.apply(_, arraylike) throws on ancient WebKit
- push.apply( ret, elems.get() );
- }
- return this.pushStack( ret );
- };
- } );
- var rmargin = ( /^margin/ );
- var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
- var getStyles = function( elem ) {
- // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
- // IE throws on elements created in popups
- // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
- var view = elem.ownerDocument.defaultView;
- if ( !view || !view.opener ) {
- view = window;
- }
- return view.getComputedStyle( elem );
- };
- ( function() {
- // Executing both pixelPosition & boxSizingReliable tests require only one layout
- // so they're executed at the same time to save the second computation.
- function computeStyleTests() {
- // This is a singleton, we need to execute it only once
- if ( !div ) {
- return;
- }
- div.style.cssText =
- "box-sizing:border-box;" +
- "position:relative;display:block;" +
- "margin:auto;border:1px;padding:1px;" +
- "top:1%;width:50%";
- div.innerHTML = "";
- documentElement.appendChild( container );
- var divStyle = window.getComputedStyle( div );
- pixelPositionVal = divStyle.top !== "1%";
- // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
- reliableMarginLeftVal = divStyle.marginLeft === "2px";
- boxSizingReliableVal = divStyle.width === "4px";
- // Support: Android 4.0 - 4.3 only
- // Some styles come back with percentage values, even though they shouldn't
- div.style.marginRight = "50%";
- pixelMarginRightVal = divStyle.marginRight === "4px";
- documentElement.removeChild( container );
- // Nullify the div so it wouldn't be stored in the memory and
- // it will also be a sign that checks already performed
- div = null;
- }
- var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
- container = document.createElement( "div" ),
- div = document.createElement( "div" );
- // Finish early in limited (non-browser) environments
- if ( !div.style ) {
- return;
- }
- // Support: IE <=9 - 11 only
- // Style of cloned element affects source element cloned (#8908)
- div.style.backgroundClip = "content-box";
- div.cloneNode( true ).style.backgroundClip = "";
- support.clearCloneStyle = div.style.backgroundClip === "content-box";
- container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
- "padding:0;margin-top:1px;position:absolute";
- container.appendChild( div );
- jQuery.extend( support, {
- pixelPosition: function() {
- computeStyleTests();
- return pixelPositionVal;
- },
- boxSizingReliable: function() {
- computeStyleTests();
- return boxSizingReliableVal;
- },
- pixelMarginRight: function() {
- computeStyleTests();
- return pixelMarginRightVal;
- },
- reliableMarginLeft: function() {
- computeStyleTests();
- return reliableMarginLeftVal;
- }
- } );
- } )();
- function curCSS( elem, name, computed ) {
- var width, minWidth, maxWidth, ret,
- // Support: Firefox 51+
- // Retrieving style before computed somehow
- // fixes an issue with getting wrong values
- // on detached elements
- style = elem.style;
- computed = computed || getStyles( elem );
- // getPropertyValue is needed for:
- // .css('filter') (IE 9 only, #12537)
- // .css('--customProperty) (#3144)
- if ( computed ) {
- ret = computed.getPropertyValue( name ) || computed[ name ];
- if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
- ret = jQuery.style( elem, name );
- }
- // A tribute to the "awesome hack by Dean Edwards"
- // Android Browser returns percentage for some values,
- // but width seems to be reliably pixels.
- // This is against the CSSOM draft spec:
- // https://drafts.csswg.org/cssom/#resolved-values
- if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
- // Remember the original values
- width = style.width;
- minWidth = style.minWidth;
- maxWidth = style.maxWidth;
- // Put in the new values to get a computed value out
- style.minWidth = style.maxWidth = style.width = ret;
- ret = computed.width;
- // Revert the changed values
- style.width = width;
- style.minWidth = minWidth;
- style.maxWidth = maxWidth;
- }
- }
- return ret !== undefined ?
- // Support: IE <=9 - 11 only
- // IE returns zIndex value as an integer.
- ret + "" :
- ret;
- }
- function addGetHookIf( conditionFn, hookFn ) {
- // Define the hook, we'll check on the first run if it's really needed.
- return {
- get: function() {
- if ( conditionFn() ) {
- // Hook not needed (or it's not possible to use it due
- // to missing dependency), remove it.
- delete this.get;
- return;
- }
- // Hook needed; redefine it so that the support test is not executed again.
- return ( this.get = hookFn ).apply( this, arguments );
- }
- };
- }
- var
- // Swappable if display is none or starts with table
- // except "table", "table-cell", or "table-caption"
- // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
- rdisplayswap = /^(none|table(?!-c[ea]).+)/,
- rcustomProp = /^--/,
- cssShow = { position: "absolute", visibility: "hidden", display: "block" },
- cssNormalTransform = {
- letterSpacing: "0",
- fontWeight: "400"
- },
- cssPrefixes = [ "Webkit", "Moz", "ms" ],
- emptyStyle = document.createElement( "div" ).style;
- // Return a css property mapped to a potentially vendor prefixed property
- function vendorPropName( name ) {
- // Shortcut for names that are not vendor prefixed
- if ( name in emptyStyle ) {
- return name;
- }
- // Check for vendor prefixed names
- var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
- i = cssPrefixes.length;
- while ( i-- ) {
- name = cssPrefixes[ i ] + capName;
- if ( name in emptyStyle ) {
- return name;
- }
- }
- }
- // Return a property mapped along what jQuery.cssProps suggests or to
- // a vendor prefixed property.
- function finalPropName( name ) {
- var ret = jQuery.cssProps[ name ];
- if ( !ret ) {
- ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
- }
- return ret;
- }
- function setPositiveNumber( elem, value, subtract ) {
- // Any relative (+/-) values have already been
- // normalized at this point
- var matches = rcssNum.exec( value );
- return matches ?
- // Guard against undefined "subtract", e.g., when used as in cssHooks
- Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
- value;
- }
- function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
- var i,
- val = 0;
- // If we already have the right measurement, avoid augmentation
- if ( extra === ( isBorderBox ? "border" : "content" ) ) {
- i = 4;
- // Otherwise initialize for horizontal or vertical properties
- } else {
- i = name === "width" ? 1 : 0;
- }
- for ( ; i < 4; i += 2 ) {
- // Both box models exclude margin, so add it if we want it
- if ( extra === "margin" ) {
- val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
- }
- if ( isBorderBox ) {
- // border-box includes padding, so remove it if we want content
- if ( extra === "content" ) {
- val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
- }
- // At this point, extra isn't border nor margin, so remove border
- if ( extra !== "margin" ) {
- val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
- }
- } else {
- // At this point, extra isn't content, so add padding
- val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
- // At this point, extra isn't content nor padding, so add border
- if ( extra !== "padding" ) {
- val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
- }
- }
- }
- return val;
- }
- function getWidthOrHeight( elem, name, extra ) {
- // Start with computed style
- var valueIsBorderBox,
- styles = getStyles( elem ),
- val = curCSS( elem, name, styles ),
- isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
- // Computed unit is not pixels. Stop here and return.
- if ( rnumnonpx.test( val ) ) {
- return val;
- }
- // Check for style in case a browser which returns unreliable values
- // for getComputedStyle silently falls back to the reliable elem.style
- valueIsBorderBox = isBorderBox &&
- ( support.boxSizingReliable() || val === elem.style[ name ] );
- // Fall back to offsetWidth/Height when value is "auto"
- // This happens for inline elements with no explicit setting (gh-3571)
- if ( val === "auto" ) {
- val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
- }
- // Normalize "", auto, and prepare for extra
- val = parseFloat( val ) || 0;
- // Use the active box-sizing model to add/subtract irrelevant styles
- return ( val +
- augmentWidthOrHeight(
- elem,
- name,
- extra || ( isBorderBox ? "border" : "content" ),
- valueIsBorderBox,
- styles
- )
- ) + "px";
- }
- jQuery.extend( {
- // Add in style property hooks for overriding the default
- // behavior of getting and setting a style property
- cssHooks: {
- opacity: {
- get: function( elem, computed ) {
- if ( computed ) {
- // We should always get a number back from opacity
- var ret = curCSS( elem, "opacity" );
- return ret === "" ? "1" : ret;
- }
- }
- }
- },
- // Don't automatically add "px" to these possibly-unitless properties
- cssNumber: {
- "animationIterationCount": true,
- "columnCount": true,
- "fillOpacity": true,
- "flexGrow": true,
- "flexShrink": true,
- "fontWeight": true,
- "lineHeight": true,
- "opacity": true,
- "order": true,
- "orphans": true,
- "widows": true,
- "zIndex": true,
- "zoom": true
- },
- // Add in properties whose names you wish to fix before
- // setting or getting the value
- cssProps: {
- "float": "cssFloat"
- },
- // Get and set the style property on a DOM Node
- style: function( elem, name, value, extra ) {
- // Don't set styles on text and comment nodes
- if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
- return;
- }
- // Make sure that we're working with the right name
- var ret, type, hooks,
- origName = jQuery.camelCase( name ),
- isCustomProp = rcustomProp.test( name ),
- style = elem.style;
- // Make sure that we're working with the right name. We don't
- // want to query the value if it is a CSS custom property
- // since they are user-defined.
- if ( !isCustomProp ) {
- name = finalPropName( origName );
- }
- // Gets hook for the prefixed version, then unprefixed version
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
- // Check if we're setting a value
- if ( value !== undefined ) {
- type = typeof value;
- // Convert "+=" or "-=" to relative numbers (#7345)
- if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
- value = adjustCSS( elem, name, ret );
- // Fixes bug #9237
- type = "number";
- }
- // Make sure that null and NaN values aren't set (#7116)
- if ( value == null || value !== value ) {
- return;
- }
- // If a number was passed in, add the unit (except for certain CSS properties)
- if ( type === "number" ) {
- value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
- }
- // background-* props affect original clone's values
- if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
- style[ name ] = "inherit";
- }
- // If a hook was provided, use that value, otherwise just set the specified value
- if ( !hooks || !( "set" in hooks ) ||
- ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
- if ( isCustomProp ) {
- style.setProperty( name, value );
- } else {
- style[ name ] = value;
- }
- }
- } else {
- // If a hook was provided get the non-computed value from there
- if ( hooks && "get" in hooks &&
- ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
- return ret;
- }
- // Otherwise just get the value from the style object
- return style[ name ];
- }
- },
- css: function( elem, name, extra, styles ) {
- var val, num, hooks,
- origName = jQuery.camelCase( name ),
- isCustomProp = rcustomProp.test( name );
- // Make sure that we're working with the right name. We don't
- // want to modify the value if it is a CSS custom property
- // since they are user-defined.
- if ( !isCustomProp ) {
- name = finalPropName( origName );
- }
- // Try prefixed name followed by the unprefixed name
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
- // If a hook was provided get the computed value from there
- if ( hooks && "get" in hooks ) {
- val = hooks.get( elem, true, extra );
- }
- // Otherwise, if a way to get the computed value exists, use that
- if ( val === undefined ) {
- val = curCSS( elem, name, styles );
- }
- // Convert "normal" to computed value
- if ( val === "normal" && name in cssNormalTransform ) {
- val = cssNormalTransform[ name ];
- }
- // Make numeric if forced or a qualifier was provided and val looks numeric
- if ( extra === "" || extra ) {
- num = parseFloat( val );
- return extra === true || isFinite( num ) ? num || 0 : val;
- }
- return val;
- }
- } );
- jQuery.each( [ "height", "width" ], function( i, name ) {
- jQuery.cssHooks[ name ] = {
- get: function( elem, computed, extra ) {
- if ( computed ) {
- // Certain elements can have dimension info if we invisibly show them
- // but it must have a current display style that would benefit
- return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
- // Support: Safari 8+
- // Table columns in Safari have non-zero offsetWidth & zero
- // getBoundingClientRect().width unless display is changed.
- // Support: IE <=11 only
- // Running getBoundingClientRect on a disconnected node
- // in IE throws an error.
- ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
- swap( elem, cssShow, function() {
- return getWidthOrHeight( elem, name, extra );
- } ) :
- getWidthOrHeight( elem, name, extra );
- }
- },
- set: function( elem, value, extra ) {
- var matches,
- styles = extra && getStyles( elem ),
- subtract = extra && augmentWidthOrHeight(
- elem,
- name,
- extra,
- jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
- styles
- );
- // Convert to pixels if value adjustment is needed
- if ( subtract && ( matches = rcssNum.exec( value ) ) &&
- ( matches[ 3 ] || "px" ) !== "px" ) {
- elem.style[ name ] = value;
- value = jQuery.css( elem, name );
- }
- return setPositiveNumber( elem, value, subtract );
- }
- };
- } );
- jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
- function( elem, computed ) {
- if ( computed ) {
- return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
- elem.getBoundingClientRect().left -
- swap( elem, { marginLeft: 0 }, function() {
- return elem.getBoundingClientRect().left;
- } )
- ) + "px";
- }
- }
- );
- // These hooks are used by animate to expand properties
- jQuery.each( {
- margin: "",
- padding: "",
- border: "Width"
- }, function( prefix, suffix ) {
- jQuery.cssHooks[ prefix + suffix ] = {
- expand: function( value ) {
- var i = 0,
- expanded = {},
- // Assumes a single number if not a string
- parts = typeof value === "string" ? value.split( " " ) : [ value ];
- for ( ; i < 4; i++ ) {
- expanded[ prefix + cssExpand[ i ] + suffix ] =
- parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
- }
- return expanded;
- }
- };
- if ( !rmargin.test( prefix ) ) {
- jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
- }
- } );
- jQuery.fn.extend( {
- css: function( name, value ) {
- return access( this, function( elem, name, value ) {
- var styles, len,
- map = {},
- i = 0;
- if ( Array.isArray( name ) ) {
- styles = getStyles( elem );
- len = name.length;
- for ( ; i < len; i++ ) {
- map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
- }
- return map;
- }
- return value !== undefined ?
- jQuery.style( elem, name, value ) :
- jQuery.css( elem, name );
- }, name, value, arguments.length > 1 );
- }
- } );
- function Tween( elem, options, prop, end, easing ) {
- return new Tween.prototype.init( elem, options, prop, end, easing );
- }
- jQuery.Tween = Tween;
- Tween.prototype = {
- constructor: Tween,
- init: function( elem, options, prop, end, easing, unit ) {
- this.elem = elem;
- this.prop = prop;
- this.easing = easing || jQuery.easing._default;
- this.options = options;
- this.start = this.now = this.cur();
- this.end = end;
- this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
- },
- cur: function() {
- var hooks = Tween.propHooks[ this.prop ];
- return hooks && hooks.get ?
- hooks.get( this ) :
- Tween.propHooks._default.get( this );
- },
- run: function( percent ) {
- var eased,
- hooks = Tween.propHooks[ this.prop ];
- if ( this.options.duration ) {
- this.pos = eased = jQuery.easing[ this.easing ](
- percent, this.options.duration * percent, 0, 1, this.options.duration
- );
- } else {
- this.pos = eased = percent;
- }
- this.now = ( this.end - this.start ) * eased + this.start;
- if ( this.options.step ) {
- this.options.step.call( this.elem, this.now, this );
- }
- if ( hooks && hooks.set ) {
- hooks.set( this );
- } else {
- Tween.propHooks._default.set( this );
- }
- return this;
- }
- };
- Tween.prototype.init.prototype = Tween.prototype;
- Tween.propHooks = {
- _default: {
- get: function( tween ) {
- var result;
- // Use a property on the element directly when it is not a DOM element,
- // or when there is no matching style property that exists.
- if ( tween.elem.nodeType !== 1 ||
- tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
- return tween.elem[ tween.prop ];
- }
- // Passing an empty string as a 3rd parameter to .css will automatically
- // attempt a parseFloat and fallback to a string if the parse fails.
- // Simple values such as "10px" are parsed to Float;
- // complex values such as "rotate(1rad)" are returned as-is.
- result = jQuery.css( tween.elem, tween.prop, "" );
- // Empty strings, null, undefined and "auto" are converted to 0.
- return !result || result === "auto" ? 0 : result;
- },
- set: function( tween ) {
- // Use step hook for back compat.
- // Use cssHook if its there.
- // Use .style if available and use plain properties where available.
- if ( jQuery.fx.step[ tween.prop ] ) {
- jQuery.fx.step[ tween.prop ]( tween );
- } else if ( tween.elem.nodeType === 1 &&
- ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
- jQuery.cssHooks[ tween.prop ] ) ) {
- jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
- } else {
- tween.elem[ tween.prop ] = tween.now;
- }
- }
- }
- };
- // Support: IE <=9 only
- // Panic based approach to setting things on disconnected nodes
- Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
- set: function( tween ) {
- if ( tween.elem.nodeType && tween.elem.parentNode ) {
- tween.elem[ tween.prop ] = tween.now;
- }
- }
- };
- jQuery.easing = {
- linear: function( p ) {
- return p;
- },
- swing: function( p ) {
- return 0.5 - Math.cos( p * Math.PI ) / 2;
- },
- _default: "swing"
- };
- jQuery.fx = Tween.prototype.init;
- // Back compat <1.8 extension point
- jQuery.fx.step = {};
- var
- fxNow, inProgress,
- rfxtypes = /^(?:toggle|show|hide)$/,
- rrun = /queueHooks$/;
- function schedule() {
- if ( inProgress ) {
- if ( document.hidden === false && window.requestAnimationFrame ) {
- window.requestAnimationFrame( schedule );
- } else {
- window.setTimeout( schedule, jQuery.fx.interval );
- }
- jQuery.fx.tick();
- }
- }
- // Animations created synchronously will run synchronously
- function createFxNow() {
- window.setTimeout( function() {
- fxNow = undefined;
- } );
- return ( fxNow = jQuery.now() );
- }
- // Generate parameters to create a standard animation
- function genFx( type, includeWidth ) {
- var which,
- i = 0,
- attrs = { height: type };
- // If we include width, step value is 1 to do all cssExpand values,
- // otherwise step value is 2 to skip over Left and Right
- includeWidth = includeWidth ? 1 : 0;
- for ( ; i < 4; i += 2 - includeWidth ) {
- which = cssExpand[ i ];
- attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
- }
- if ( includeWidth ) {
- attrs.opacity = attrs.width = type;
- }
- return attrs;
- }
- function createTween( value, prop, animation ) {
- var tween,
- collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
- index = 0,
- length = collection.length;
- for ( ; index < length; index++ ) {
- if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
- // We're done with this property
- return tween;
- }
- }
- }
- function defaultPrefilter( elem, props, opts ) {
- var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
- isBox = "width" in props || "height" in props,
- anim = this,
- orig = {},
- style = elem.style,
- hidden = elem.nodeType && isHiddenWithinTree( elem ),
- dataShow = dataPriv.get( elem, "fxshow" );
- // Queue-skipping animations hijack the fx hooks
- if ( !opts.queue ) {
- hooks = jQuery._queueHooks( elem, "fx" );
- if ( hooks.unqueued == null ) {
- hooks.unqueued = 0;
- oldfire = hooks.empty.fire;
- hooks.empty.fire = function() {
- if ( !hooks.unqueued ) {
- oldfire();
- }
- };
- }
- hooks.unqueued++;
- anim.always( function() {
- // Ensure the complete handler is called before this completes
- anim.always( function() {
- hooks.unqueued--;
- if ( !jQuery.queue( elem, "fx" ).length ) {
- hooks.empty.fire();
- }
- } );
- } );
- }
- // Detect show/hide animations
- for ( prop in props ) {
- value = props[ prop ];
- if ( rfxtypes.test( value ) ) {
- delete props[ prop ];
- toggle = toggle || value === "toggle";
- if ( value === ( hidden ? "hide" : "show" ) ) {
- // Pretend to be hidden if this is a "show" and
- // there is still data from a stopped show/hide
- if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
- hidden = true;
- // Ignore all other no-op show/hide data
- } else {
- continue;
- }
- }
- orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
- }
- }
- // Bail out if this is a no-op like .hide().hide()
- propTween = !jQuery.isEmptyObject( props );
- if ( !propTween && jQuery.isEmptyObject( orig ) ) {
- return;
- }
- // Restrict "overflow" and "display" styles during box animations
- if ( isBox && elem.nodeType === 1 ) {
- // Support: IE <=9 - 11, Edge 12 - 13
- // Record all 3 overflow attributes because IE does not infer the shorthand
- // from identically-valued overflowX and overflowY
- opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
- // Identify a display type, preferring old show/hide data over the CSS cascade
- restoreDisplay = dataShow && dataShow.display;
- if ( restoreDisplay == null ) {
- restoreDisplay = dataPriv.get( elem, "display" );
- }
- display = jQuery.css( elem, "display" );
- if ( display === "none" ) {
- if ( restoreDisplay ) {
- display = restoreDisplay;
- } else {
- // Get nonempty value(s) by temporarily forcing visibility
- showHide( [ elem ], true );
- restoreDisplay = elem.style.display || restoreDisplay;
- display = jQuery.css( elem, "display" );
- showHide( [ elem ] );
- }
- }
- // Animate inline elements as inline-block
- if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
- if ( jQuery.css( elem, "float" ) === "none" ) {
- // Restore the original display value at the end of pure show/hide animations
- if ( !propTween ) {
- anim.done( function() {
- style.display = restoreDisplay;
- } );
- if ( restoreDisplay == null ) {
- display = style.display;
- restoreDisplay = display === "none" ? "" : display;
- }
- }
- style.display = "inline-block";
- }
- }
- }
- if ( opts.overflow ) {
- style.overflow = "hidden";
- anim.always( function() {
- style.overflow = opts.overflow[ 0 ];
- style.overflowX = opts.overflow[ 1 ];
- style.overflowY = opts.overflow[ 2 ];
- } );
- }
- // Implement show/hide animations
- propTween = false;
- for ( prop in orig ) {
- // General show/hide setup for this element animation
- if ( !propTween ) {
- if ( dataShow ) {
- if ( "hidden" in dataShow ) {
- hidden = dataShow.hidden;
- }
- } else {
- dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
- }
- // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
- if ( toggle ) {
- dataShow.hidden = !hidden;
- }
- // Show elements before animating them
- if ( hidden ) {
- showHide( [ elem ], true );
- }
- /* eslint-disable no-loop-func */
- anim.done( function() {
- /* eslint-enable no-loop-func */
- // The final step of a "hide" animation is actually hiding the element
- if ( !hidden ) {
- showHide( [ elem ] );
- }
- dataPriv.remove( elem, "fxshow" );
- for ( prop in orig ) {
- jQuery.style( elem, prop, orig[ prop ] );
- }
- } );
- }
- // Per-property setup
- propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
- if ( !( prop in dataShow ) ) {
- dataShow[ prop ] = propTween.start;
- if ( hidden ) {
- propTween.end = propTween.start;
- propTween.start = 0;
- }
- }
- }
- }
- function propFilter( props, specialEasing ) {
- var index, name, easing, value, hooks;
- // camelCase, specialEasing and expand cssHook pass
- for ( index in props ) {
- name = jQuery.camelCase( index );
- easing = specialEasing[ name ];
- value = props[ index ];
- if ( Array.isArray( value ) ) {
- easing = value[ 1 ];
- value = props[ index ] = value[ 0 ];
- }
- if ( index !== name ) {
- props[ name ] = value;
- delete props[ index ];
- }
- hooks = jQuery.cssHooks[ name ];
- if ( hooks && "expand" in hooks ) {
- value = hooks.expand( value );
- delete props[ name ];
- // Not quite $.extend, this won't overwrite existing keys.
- // Reusing 'index' because we have the correct "name"
- for ( index in value ) {
- if ( !( index in props ) ) {
- props[ index ] = value[ index ];
- specialEasing[ index ] = easing;
- }
- }
- } else {
- specialEasing[ name ] = easing;
- }
- }
- }
- function Animation( elem, properties, options ) {
- var result,
- stopped,
- index = 0,
- length = Animation.prefilters.length,
- deferred = jQuery.Deferred().always( function() {
- // Don't match elem in the :animated selector
- delete tick.elem;
- } ),
- tick = function() {
- if ( stopped ) {
- return false;
- }
- var currentTime = fxNow || createFxNow(),
- remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
- // Support: Android 2.3 only
- // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
- temp = remaining / animation.duration || 0,
- percent = 1 - temp,
- index = 0,
- length = animation.tweens.length;
- for ( ; index < length; index++ ) {
- animation.tweens[ index ].run( percent );
- }
- deferred.notifyWith( elem, [ animation, percent, remaining ] );
- // If there's more to do, yield
- if ( percent < 1 && length ) {
- return remaining;
- }
- // If this was an empty animation, synthesize a final progress notification
- if ( !length ) {
- deferred.notifyWith( elem, [ animation, 1, 0 ] );
- }
- // Resolve the animation and report its conclusion
- deferred.resolveWith( elem, [ animation ] );
- return false;
- },
- animation = deferred.promise( {
- elem: elem,
- props: jQuery.extend( {}, properties ),
- opts: jQuery.extend( true, {
- specialEasing: {},
- easing: jQuery.easing._default
- }, options ),
- originalProperties: properties,
- originalOptions: options,
- startTime: fxNow || createFxNow(),
- duration: options.duration,
- tweens: [],
- createTween: function( prop, end ) {
- var tween = jQuery.Tween( elem, animation.opts, prop, end,
- animation.opts.specialEasing[ prop ] || animation.opts.easing );
- animation.tweens.push( tween );
- return tween;
- },
- stop: function( gotoEnd ) {
- var index = 0,
- // If we are going to the end, we want to run all the tweens
- // otherwise we skip this part
- length = gotoEnd ? animation.tweens.length : 0;
- if ( stopped ) {
- return this;
- }
- stopped = true;
- for ( ; index < length; index++ ) {
- animation.tweens[ index ].run( 1 );
- }
- // Resolve when we played the last frame; otherwise, reject
- if ( gotoEnd ) {
- deferred.notifyWith( elem, [ animation, 1, 0 ] );
- deferred.resolveWith( elem, [ animation, gotoEnd ] );
- } else {
- deferred.rejectWith( elem, [ animation, gotoEnd ] );
- }
- return this;
- }
- } ),
- props = animation.props;
- propFilter( props, animation.opts.specialEasing );
- for ( ; index < length; index++ ) {
- result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
- if ( result ) {
- if ( jQuery.isFunction( result.stop ) ) {
- jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
- jQuery.proxy( result.stop, result );
- }
- return result;
- }
- }
- jQuery.map( props, createTween, animation );
- if ( jQuery.isFunction( animation.opts.start ) ) {
- animation.opts.start.call( elem, animation );
- }
- // Attach callbacks from options
- animation
- .progress( animation.opts.progress )
- .done( animation.opts.done, animation.opts.complete )
- .fail( animation.opts.fail )
- .always( animation.opts.always );
- jQuery.fx.timer(
- jQuery.extend( tick, {
- elem: elem,
- anim: animation,
- queue: animation.opts.queue
- } )
- );
- return animation;
- }
- jQuery.Animation = jQuery.extend( Animation, {
- tweeners: {
- "*": [ function( prop, value ) {
- var tween = this.createTween( prop, value );
- adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
- return tween;
- } ]
- },
- tweener: function( props, callback ) {
- if ( jQuery.isFunction( props ) ) {
- callback = props;
- props = [ "*" ];
- } else {
- props = props.match( rnothtmlwhite );
- }
- var prop,
- index = 0,
- length = props.length;
- for ( ; index < length; index++ ) {
- prop = props[ index ];
- Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
- Animation.tweeners[ prop ].unshift( callback );
- }
- },
- prefilters: [ defaultPrefilter ],
- prefilter: function( callback, prepend ) {
- if ( prepend ) {
- Animation.prefilters.unshift( callback );
- } else {
- Animation.prefilters.push( callback );
- }
- }
- } );
- jQuery.speed = function( speed, easing, fn ) {
- var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
- complete: fn || !fn && easing ||
- jQuery.isFunction( speed ) && speed,
- duration: speed,
- easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
- };
- // Go to the end state if fx are off
- if ( jQuery.fx.off ) {
- opt.duration = 0;
- } else {
- if ( typeof opt.duration !== "number" ) {
- if ( opt.duration in jQuery.fx.speeds ) {
- opt.duration = jQuery.fx.speeds[ opt.duration ];
- } else {
- opt.duration = jQuery.fx.speeds._default;
- }
- }
- }
- // Normalize opt.queue - true/undefined/null -> "fx"
- if ( opt.queue == null || opt.queue === true ) {
- opt.queue = "fx";
- }
- // Queueing
- opt.old = opt.complete;
- opt.complete = function() {
- if ( jQuery.isFunction( opt.old ) ) {
- opt.old.call( this );
- }
- if ( opt.queue ) {
- jQuery.dequeue( this, opt.queue );
- }
- };
- return opt;
- };
- jQuery.fn.extend( {
- fadeTo: function( speed, to, easing, callback ) {
- // Show any hidden elements after setting opacity to 0
- return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
- // Animate to the value specified
- .end().animate( { opacity: to }, speed, easing, callback );
- },
- animate: function( prop, speed, easing, callback ) {
- var empty = jQuery.isEmptyObject( prop ),
- optall = jQuery.speed( speed, easing, callback ),
- doAnimation = function() {
- // Operate on a copy of prop so per-property easing won't be lost
- var anim = Animation( this, jQuery.extend( {}, prop ), optall );
- // Empty animations, or finishing resolves immediately
- if ( empty || dataPriv.get( this, "finish" ) ) {
- anim.stop( true );
- }
- };
- doAnimation.finish = doAnimation;
- return empty || optall.queue === false ?
- this.each( doAnimation ) :
- this.queue( optall.queue, doAnimation );
- },
- stop: function( type, clearQueue, gotoEnd ) {
- var stopQueue = function( hooks ) {
- var stop = hooks.stop;
- delete hooks.stop;
- stop( gotoEnd );
- };
- if ( typeof type !== "string" ) {
- gotoEnd = clearQueue;
- clearQueue = type;
- type = undefined;
- }
- if ( clearQueue && type !== false ) {
- this.queue( type || "fx", [] );
- }
- return this.each( function() {
- var dequeue = true,
- index = type != null && type + "queueHooks",
- timers = jQuery.timers,
- data = dataPriv.get( this );
- if ( index ) {
- if ( data[ index ] && data[ index ].stop ) {
- stopQueue( data[ index ] );
- }
- } else {
- for ( index in data ) {
- if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
- stopQueue( data[ index ] );
- }
- }
- }
- for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this &&
- ( type == null || timers[ index ].queue === type ) ) {
- timers[ index ].anim.stop( gotoEnd );
- dequeue = false;
- timers.splice( index, 1 );
- }
- }
- // Start the next in the queue if the last step wasn't forced.
- // Timers currently will call their complete callbacks, which
- // will dequeue but only if they were gotoEnd.
- if ( dequeue || !gotoEnd ) {
- jQuery.dequeue( this, type );
- }
- } );
- },
- finish: function( type ) {
- if ( type !== false ) {
- type = type || "fx";
- }
- return this.each( function() {
- var index,
- data = dataPriv.get( this ),
- queue = data[ type + "queue" ],
- hooks = data[ type + "queueHooks" ],
- timers = jQuery.timers,
- length = queue ? queue.length : 0;
- // Enable finishing flag on private data
- data.finish = true;
- // Empty the queue first
- jQuery.queue( this, type, [] );
- if ( hooks && hooks.stop ) {
- hooks.stop.call( this, true );
- }
- // Look for any active animations, and finish them
- for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
- timers[ index ].anim.stop( true );
- timers.splice( index, 1 );
- }
- }
- // Look for any animations in the old queue and finish them
- for ( index = 0; index < length; index++ ) {
- if ( queue[ index ] && queue[ index ].finish ) {
- queue[ index ].finish.call( this );
- }
- }
- // Turn off finishing flag
- delete data.finish;
- } );
- }
- } );
- jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
- var cssFn = jQuery.fn[ name ];
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return speed == null || typeof speed === "boolean" ?
- cssFn.apply( this, arguments ) :
- this.animate( genFx( name, true ), speed, easing, callback );
- };
- } );
- // Generate shortcuts for custom animations
- jQuery.each( {
- slideDown: genFx( "show" ),
- slideUp: genFx( "hide" ),
- slideToggle: genFx( "toggle" ),
- fadeIn: { opacity: "show" },
- fadeOut: { opacity: "hide" },
- fadeToggle: { opacity: "toggle" }
- }, function( name, props ) {
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return this.animate( props, speed, easing, callback );
- };
- } );
- jQuery.timers = [];
- jQuery.fx.tick = function() {
- var timer,
- i = 0,
- timers = jQuery.timers;
- fxNow = jQuery.now();
- for ( ; i < timers.length; i++ ) {
- timer = timers[ i ];
- // Run the timer and safely remove it when done (allowing for external removal)
- if ( !timer() && timers[ i ] === timer ) {
- timers.splice( i--, 1 );
- }
- }
- if ( !timers.length ) {
- jQuery.fx.stop();
- }
- fxNow = undefined;
- };
- jQuery.fx.timer = function( timer ) {
- jQuery.timers.push( timer );
- jQuery.fx.start();
- };
- jQuery.fx.interval = 13;
- jQuery.fx.start = function() {
- if ( inProgress ) {
- return;
- }
- inProgress = true;
- schedule();
- };
- jQuery.fx.stop = function() {
- inProgress = null;
- };
- jQuery.fx.speeds = {
- slow: 600,
- fast: 200,
- // Default speed
- _default: 400
- };
- // Based off of the plugin by Clint Helfers, with permission.
- // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
- jQuery.fn.delay = function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
- return this.queue( type, function( next, hooks ) {
- var timeout = window.setTimeout( next, time );
- hooks.stop = function() {
- window.clearTimeout( timeout );
- };
- } );
- };
- ( function() {
- var input = document.createElement( "input" ),
- select = document.createElement( "select" ),
- opt = select.appendChild( document.createElement( "option" ) );
- input.type = "checkbox";
- // Support: Android <=4.3 only
- // Default value for a checkbox should be "on"
- support.checkOn = input.value !== "";
- // Support: IE <=11 only
- // Must access selectedIndex to make default options select
- support.optSelected = opt.selected;
- // Support: IE <=11 only
- // An input loses its value after becoming a radio
- input = document.createElement( "input" );
- input.value = "t";
- input.type = "radio";
- support.radioValue = input.value === "t";
- } )();
- var boolHook,
- attrHandle = jQuery.expr.attrHandle;
- jQuery.fn.extend( {
- attr: function( name, value ) {
- return access( this, jQuery.attr, name, value, arguments.length > 1 );
- },
- removeAttr: function( name ) {
- return this.each( function() {
- jQuery.removeAttr( this, name );
- } );
- }
- } );
- jQuery.extend( {
- attr: function( elem, name, value ) {
- var ret, hooks,
- nType = elem.nodeType;
- // Don't get/set attributes on text, comment and attribute nodes
- if ( nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === "undefined" ) {
- return jQuery.prop( elem, name, value );
- }
- // Attribute hooks are determined by the lowercase version
- // Grab necessary hook if one is defined
- if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
- hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
- ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
- }
- if ( value !== undefined ) {
- if ( value === null ) {
- jQuery.removeAttr( elem, name );
- return;
- }
- if ( hooks && "set" in hooks &&
- ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
- return ret;
- }
- elem.setAttribute( name, value + "" );
- return value;
- }
- if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
- return ret;
- }
- ret = jQuery.find.attr( elem, name );
- // Non-existent attributes return null, we normalize to undefined
- return ret == null ? undefined : ret;
- },
- attrHooks: {
- type: {
- set: function( elem, value ) {
- if ( !support.radioValue && value === "radio" &&
- nodeName( elem, "input" ) ) {
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- return value;
- }
- }
- }
- },
- removeAttr: function( elem, value ) {
- var name,
- i = 0,
- // Attribute names can contain non-HTML whitespace characters
- // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
- attrNames = value && value.match( rnothtmlwhite );
- if ( attrNames && elem.nodeType === 1 ) {
- while ( ( name = attrNames[ i++ ] ) ) {
- elem.removeAttribute( name );
- }
- }
- }
- } );
- // Hooks for boolean attributes
- boolHook = {
- set: function( elem, value, name ) {
- if ( value === false ) {
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- elem.setAttribute( name, name );
- }
- return name;
- }
- };
- jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
- var getter = attrHandle[ name ] || jQuery.find.attr;
- attrHandle[ name ] = function( elem, name, isXML ) {
- var ret, handle,
- lowercaseName = name.toLowerCase();
- if ( !isXML ) {
- // Avoid an infinite loop by temporarily removing this function from the getter
- handle = attrHandle[ lowercaseName ];
- attrHandle[ lowercaseName ] = ret;
- ret = getter( elem, name, isXML ) != null ?
- lowercaseName :
- null;
- attrHandle[ lowercaseName ] = handle;
- }
- return ret;
- };
- } );
- var rfocusable = /^(?:input|select|textarea|button)$/i,
- rclickable = /^(?:a|area)$/i;
- jQuery.fn.extend( {
- prop: function( name, value ) {
- return access( this, jQuery.prop, name, value, arguments.length > 1 );
- },
- removeProp: function( name ) {
- return this.each( function() {
- delete this[ jQuery.propFix[ name ] || name ];
- } );
- }
- } );
- jQuery.extend( {
- prop: function( elem, name, value ) {
- var ret, hooks,
- nType = elem.nodeType;
- // Don't get/set properties on text, comment and attribute nodes
- if ( nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
- if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks &&
- ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
- return ret;
- }
- return ( elem[ name ] = value );
- }
- if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
- return ret;
- }
- return elem[ name ];
- },
- propHooks: {
- tabIndex: {
- get: function( elem ) {
- // Support: IE <=9 - 11 only
- // elem.tabIndex doesn't always return the
- // correct value when it hasn't been explicitly set
- // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- // Use proper attribute retrieval(#12072)
- var tabindex = jQuery.find.attr( elem, "tabindex" );
- if ( tabindex ) {
- return parseInt( tabindex, 10 );
- }
- if (
- rfocusable.test( elem.nodeName ) ||
- rclickable.test( elem.nodeName ) &&
- elem.href
- ) {
- return 0;
- }
- return -1;
- }
- }
- },
- propFix: {
- "for": "htmlFor",
- "class": "className"
- }
- } );
- // Support: IE <=11 only
- // Accessing the selectedIndex property
- // forces the browser to respect setting selected
- // on the option
- // The getter ensures a default option is selected
- // when in an optgroup
- // eslint rule "no-unused-expressions" is disabled for this code
- // since it considers such accessions noop
- if ( !support.optSelected ) {
- jQuery.propHooks.selected = {
- get: function( elem ) {
- /* eslint no-unused-expressions: "off" */
- var parent = elem.parentNode;
- if ( parent && parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- return null;
- },
- set: function( elem ) {
- /* eslint no-unused-expressions: "off" */
- var parent = elem.parentNode;
- if ( parent ) {
- parent.selectedIndex;
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- }
- };
- }
- jQuery.each( [
- "tabIndex",
- "readOnly",
- "maxLength",
- "cellSpacing",
- "cellPadding",
- "rowSpan",
- "colSpan",
- "useMap",
- "frameBorder",
- "contentEditable"
- ], function() {
- jQuery.propFix[ this.toLowerCase() ] = this;
- } );
- // Strip and collapse whitespace according to HTML spec
- // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
- function stripAndCollapse( value ) {
- var tokens = value.match( rnothtmlwhite ) || [];
- return tokens.join( " " );
- }
- function getClass( elem ) {
- return elem.getAttribute && elem.getAttribute( "class" ) || "";
- }
- jQuery.fn.extend( {
- addClass: function( value ) {
- var classes, elem, cur, curValue, clazz, j, finalValue,
- i = 0;
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( j ) {
- jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
- } );
- }
- if ( typeof value === "string" && value ) {
- classes = value.match( rnothtmlwhite ) || [];
- while ( ( elem = this[ i++ ] ) ) {
- curValue = getClass( elem );
- cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
- if ( cur ) {
- j = 0;
- while ( ( clazz = classes[ j++ ] ) ) {
- if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
- cur += clazz + " ";
- }
- }
- // Only assign if different to avoid unneeded rendering.
- finalValue = stripAndCollapse( cur );
- if ( curValue !== finalValue ) {
- elem.setAttribute( "class", finalValue );
- }
- }
- }
- }
- return this;
- },
- removeClass: function( value ) {
- var classes, elem, cur, curValue, clazz, j, finalValue,
- i = 0;
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( j ) {
- jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
- } );
- }
- if ( !arguments.length ) {
- return this.attr( "class", "" );
- }
- if ( typeof value === "string" && value ) {
- classes = value.match( rnothtmlwhite ) || [];
- while ( ( elem = this[ i++ ] ) ) {
- curValue = getClass( elem );
- // This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
- if ( cur ) {
- j = 0;
- while ( ( clazz = classes[ j++ ] ) ) {
- // Remove *all* instances
- while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
- cur = cur.replace( " " + clazz + " ", " " );
- }
- }
- // Only assign if different to avoid unneeded rendering.
- finalValue = stripAndCollapse( cur );
- if ( curValue !== finalValue ) {
- elem.setAttribute( "class", finalValue );
- }
- }
- }
- }
- return this;
- },
- toggleClass: function( value, stateVal ) {
- var type = typeof value;
- if ( typeof stateVal === "boolean" && type === "string" ) {
- return stateVal ? this.addClass( value ) : this.removeClass( value );
- }
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( i ) {
- jQuery( this ).toggleClass(
- value.call( this, i, getClass( this ), stateVal ),
- stateVal
- );
- } );
- }
- return this.each( function() {
- var className, i, self, classNames;
- if ( type === "string" ) {
- // Toggle individual class names
- i = 0;
- self = jQuery( this );
- classNames = value.match( rnothtmlwhite ) || [];
- while ( ( className = classNames[ i++ ] ) ) {
- // Check each className given, space separated list
- if ( self.hasClass( className ) ) {
- self.removeClass( className );
- } else {
- self.addClass( className );
- }
- }
- // Toggle whole class name
- } else if ( value === undefined || type === "boolean" ) {
- className = getClass( this );
- if ( className ) {
- // Store className if set
- dataPriv.set( this, "__className__", className );
- }
- // If the element has a class name or if we're passed `false`,
- // then remove the whole classname (if there was one, the above saved it).
- // Otherwise bring back whatever was previously saved (if anything),
- // falling back to the empty string if nothing was stored.
- if ( this.setAttribute ) {
- this.setAttribute( "class",
- className || value === false ?
- "" :
- dataPriv.get( this, "__className__" ) || ""
- );
- }
- }
- } );
- },
- hasClass: function( selector ) {
- var className, elem,
- i = 0;
- className = " " + selector + " ";
- while ( ( elem = this[ i++ ] ) ) {
- if ( elem.nodeType === 1 &&
- ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
- return true;
- }
- }
- return false;
- }
- } );
- var rreturn = /\r/g;
- jQuery.fn.extend( {
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[ 0 ];
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] ||
- jQuery.valHooks[ elem.nodeName.toLowerCase() ];
- if ( hooks &&
- "get" in hooks &&
- ( ret = hooks.get( elem, "value" ) ) !== undefined
- ) {
- return ret;
- }
- ret = elem.value;
- // Handle most common string cases
- if ( typeof ret === "string" ) {
- return ret.replace( rreturn, "" );
- }
- // Handle cases where value is null/undef or number
- return ret == null ? "" : ret;
- }
- return;
- }
- isFunction = jQuery.isFunction( value );
- return this.each( function( i ) {
- var val;
- if ( this.nodeType !== 1 ) {
- return;
- }
- if ( isFunction ) {
- val = value.call( this, i, jQuery( this ).val() );
- } else {
- val = value;
- }
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( Array.isArray( val ) ) {
- val = jQuery.map( val, function( value ) {
- return value == null ? "" : value + "";
- } );
- }
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- } );
- }
- } );
- jQuery.extend( {
- valHooks: {
- option: {
- get: function( elem ) {
- var val = jQuery.find.attr( elem, "value" );
- return val != null ?
- val :
- // Support: IE <=10 - 11 only
- // option.text throws exceptions (#14686, #14858)
- // Strip and collapse whitespace
- // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
- stripAndCollapse( jQuery.text( elem ) );
- }
- },
- select: {
- get: function( elem ) {
- var value, option, i,
- options = elem.options,
- index = elem.selectedIndex,
- one = elem.type === "select-one",
- values = one ? null : [],
- max = one ? index + 1 : options.length;
- if ( index < 0 ) {
- i = max;
- } else {
- i = one ? index : 0;
- }
- // Loop through all the selected options
- for ( ; i < max; i++ ) {
- option = options[ i ];
- // Support: IE <=9 only
- // IE8-9 doesn't update selected after form reset (#2551)
- if ( ( option.selected || i === index ) &&
- // Don't return options that are disabled or in a disabled optgroup
- !option.disabled &&
- ( !option.parentNode.disabled ||
- !nodeName( option.parentNode, "optgroup" ) ) ) {
- // Get the specific value for the option
- value = jQuery( option ).val();
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
- // Multi-Selects return an array
- values.push( value );
- }
- }
- return values;
- },
- set: function( elem, value ) {
- var optionSet, option,
- options = elem.options,
- values = jQuery.makeArray( value ),
- i = options.length;
- while ( i-- ) {
- option = options[ i ];
- /* eslint-disable no-cond-assign */
- if ( option.selected =
- jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
- ) {
- optionSet = true;
- }
- /* eslint-enable no-cond-assign */
- }
- // Force browsers to behave consistently when non-matching value is set
- if ( !optionSet ) {
- elem.selectedIndex = -1;
- }
- return values;
- }
- }
- }
- } );
- // Radios and checkboxes getter/setter
- jQuery.each( [ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- set: function( elem, value ) {
- if ( Array.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
- }
- }
- };
- if ( !support.checkOn ) {
- jQuery.valHooks[ this ].get = function( elem ) {
- return elem.getAttribute( "value" ) === null ? "on" : elem.value;
- };
- }
- } );
- // Return jQuery for attributes-only inclusion
- var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
- jQuery.extend( jQuery.event, {
- trigger: function( event, data, elem, onlyHandlers ) {
- var i, cur, tmp, bubbleType, ontype, handle, special,
- eventPath = [ elem || document ],
- type = hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
- cur = tmp = elem = elem || document;
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
- if ( type.indexOf( "." ) > -1 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split( "." );
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf( ":" ) < 0 && "on" + type;
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
- // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
- event.isTrigger = onlyHandlers ? 2 : 3;
- event.namespace = namespaces.join( "." );
- event.rnamespace = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
- null;
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === ( elem.ownerDocument || document ) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
- // Fire handlers on the event path
- i = 0;
- while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
- // jQuery handler
- handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
- dataPriv.get( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && handle.apply && acceptData( cur ) ) {
- event.result = handle.apply( cur, data );
- if ( event.result === false ) {
- event.preventDefault();
- }
- }
- }
- event.type = type;
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
- if ( ( !special._default ||
- special._default.apply( eventPath.pop(), data ) === false ) &&
- acceptData( elem ) ) {
- // Call a native DOM method on the target with the same name as the event.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
- if ( tmp ) {
- elem[ ontype ] = null;
- }
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- elem[ type ]();
- jQuery.event.triggered = undefined;
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
- return event.result;
- },
- // Piggyback on a donor event to simulate a different one
- // Used only for `focus(in | out)` events
- simulate: function( type, elem, event ) {
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- {
- type: type,
- isSimulated: true
- }
- );
- jQuery.event.trigger( e, null, elem );
- }
- } );
- jQuery.fn.extend( {
- trigger: function( type, data ) {
- return this.each( function() {
- jQuery.event.trigger( type, data, this );
- } );
- },
- triggerHandler: function( type, data ) {
- var elem = this[ 0 ];
- if ( elem ) {
- return jQuery.event.trigger( type, data, elem, true );
- }
- }
- } );
- jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
- "change select submit keydown keypress keyup contextmenu" ).split( " " ),
- function( i, name ) {
- // Handle event binding
- jQuery.fn[ name ] = function( data, fn ) {
- return arguments.length > 0 ?
- this.on( name, null, data, fn ) :
- this.trigger( name );
- };
- } );
- jQuery.fn.extend( {
- hover: function( fnOver, fnOut ) {
- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- }
- } );
- support.focusin = "onfocusin" in window;
- // Support: Firefox <=44
- // Firefox doesn't have focus(in | out) events
- // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
- //
- // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
- // focus(in | out) events fire after focus & blur events,
- // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
- // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
- if ( !support.focusin ) {
- jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
- // Attach a single capturing handler on the document while someone wants focusin/focusout
- var handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
- };
- jQuery.event.special[ fix ] = {
- setup: function() {
- var doc = this.ownerDocument || this,
- attaches = dataPriv.access( doc, fix );
- if ( !attaches ) {
- doc.addEventListener( orig, handler, true );
- }
- dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
- },
- teardown: function() {
- var doc = this.ownerDocument || this,
- attaches = dataPriv.access( doc, fix ) - 1;
- if ( !attaches ) {
- doc.removeEventListener( orig, handler, true );
- dataPriv.remove( doc, fix );
- } else {
- dataPriv.access( doc, fix, attaches );
- }
- }
- };
- } );
- }
- var location = window.location;
- var nonce = jQuery.now();
- var rquery = ( /\?/ );
- // Cross-browser xml parsing
- jQuery.parseXML = function( data ) {
- var xml;
- if ( !data || typeof data !== "string" ) {
- return null;
- }
- // Support: IE 9 - 11 only
- // IE throws on parseFromString with invalid input.
- try {
- xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
- } catch ( e ) {
- xml = undefined;
- }
- if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
- }
- return xml;
- };
- var
- rbracket = /\[\]$/,
- rCRLF = /\r?\n/g,
- rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
- rsubmittable = /^(?:input|select|textarea|keygen)/i;
- function buildParams( prefix, obj, traditional, add ) {
- var name;
- if ( Array.isArray( obj ) ) {
- // Serialize array item.
- jQuery.each( obj, function( i, v ) {
- if ( traditional || rbracket.test( prefix ) ) {
- // Treat each array item as a scalar.
- add( prefix, v );
- } else {
- // Item is non-scalar (array or object), encode its numeric index.
- buildParams(
- prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
- v,
- traditional,
- add
- );
- }
- } );
- } else if ( !traditional && jQuery.type( obj ) === "object" ) {
- // Serialize object item.
- for ( name in obj ) {
- buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
- }
- } else {
- // Serialize scalar item.
- add( prefix, obj );
- }
- }
- // Serialize an array of form elements or a set of
- // key/values into a query string
- jQuery.param = function( a, traditional ) {
- var prefix,
- s = [],
- add = function( key, valueOrFunction ) {
- // If value is a function, invoke it and use its return value
- var value = jQuery.isFunction( valueOrFunction ) ?
- valueOrFunction() :
- valueOrFunction;
- s[ s.length ] = encodeURIComponent( key ) + "=" +
- encodeURIComponent( value == null ? "" : value );
- };
- // If an array was passed in, assume that it is an array of form elements.
- if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
- // Serialize the form elements
- jQuery.each( a, function() {
- add( this.name, this.value );
- } );
- } else {
- // If traditional, encode the "old" way (the way 1.3.2 or older
- // did it), otherwise encode params recursively.
- for ( prefix in a ) {
- buildParams( prefix, a[ prefix ], traditional, add );
- }
- }
- // Return the resulting serialization
- return s.join( "&" );
- };
- jQuery.fn.extend( {
- serialize: function() {
- return jQuery.param( this.serializeArray() );
- },
- serializeArray: function() {
- return this.map( function() {
- // Can add propHook for "elements" to filter or add form elements
- var elements = jQuery.prop( this, "elements" );
- return elements ? jQuery.makeArray( elements ) : this;
- } )
- .filter( function() {
- var type = this.type;
- // Use .is( ":disabled" ) so that fieldset[disabled] works
- return this.name && !jQuery( this ).is( ":disabled" ) &&
- rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
- ( this.checked || !rcheckableType.test( type ) );
- } )
- .map( function( i, elem ) {
- var val = jQuery( this ).val();
- if ( val == null ) {
- return null;
- }
- if ( Array.isArray( val ) ) {
- return jQuery.map( val, function( val ) {
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- } );
- }
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- } ).get();
- }
- } );
- var
- r20 = /%20/g,
- rhash = /#.*$/,
- rantiCache = /([?&])_=[^&]*/,
- rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
- // #7653, #8125, #8152: local protocol detection
- rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
- rnoContent = /^(?:GET|HEAD)$/,
- rprotocol = /^\/\//,
- /* Prefilters
- * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
- * 2) These are called:
- * - BEFORE asking for a transport
- * - AFTER param serialization (s.data is a string if s.processData is true)
- * 3) key is the dataType
- * 4) the catchall symbol "*" can be used
- * 5) execution will start with transport dataType and THEN continue down to "*" if needed
- */
- prefilters = {},
- /* Transports bindings
- * 1) key is the dataType
- * 2) the catchall symbol "*" can be used
- * 3) selection will start with transport dataType and THEN go to "*" if needed
- */
- transports = {},
- // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
- allTypes = "*/".concat( "*" ),
- // Anchor tag for parsing the document origin
- originAnchor = document.createElement( "a" );
- originAnchor.href = location.href;
- // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
- function addToPrefiltersOrTransports( structure ) {
- // dataTypeExpression is optional and defaults to "*"
- return function( dataTypeExpression, func ) {
- if ( typeof dataTypeExpression !== "string" ) {
- func = dataTypeExpression;
- dataTypeExpression = "*";
- }
- var dataType,
- i = 0,
- dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
- if ( jQuery.isFunction( func ) ) {
- // For each dataType in the dataTypeExpression
- while ( ( dataType = dataTypes[ i++ ] ) ) {
- // Prepend if requested
- if ( dataType[ 0 ] === "+" ) {
- dataType = dataType.slice( 1 ) || "*";
- ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
- // Otherwise append
- } else {
- ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
- }
- }
- }
- };
- }
- // Base inspection function for prefilters and transports
- function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
- var inspected = {},
- seekingTransport = ( structure === transports );
- function inspect( dataType ) {
- var selected;
- inspected[ dataType ] = true;
- jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
- var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
- if ( typeof dataTypeOrTransport === "string" &&
- !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
- options.dataTypes.unshift( dataTypeOrTransport );
- inspect( dataTypeOrTransport );
- return false;
- } else if ( seekingTransport ) {
- return !( selected = dataTypeOrTransport );
- }
- } );
- return selected;
- }
- return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
- }
- // A special extend for ajax options
- // that takes "flat" options (not to be deep extended)
- // Fixes #9887
- function ajaxExtend( target, src ) {
- var key, deep,
- flatOptions = jQuery.ajaxSettings.flatOptions || {};
- for ( key in src ) {
- if ( src[ key ] !== undefined ) {
- ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
- }
- }
- if ( deep ) {
- jQuery.extend( true, target, deep );
- }
- return target;
- }
- /* Handles responses to an ajax request:
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
- function ajaxHandleResponses( s, jqXHR, responses ) {
- var ct, type, finalDataType, firstDataType,
- contents = s.contents,
- dataTypes = s.dataTypes;
- // Remove auto dataType and get content-type in the process
- while ( dataTypes[ 0 ] === "*" ) {
- dataTypes.shift();
- if ( ct === undefined ) {
- ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
- }
- }
- // Check if we're dealing with a known content-type
- if ( ct ) {
- for ( type in contents ) {
- if ( contents[ type ] && contents[ type ].test( ct ) ) {
- dataTypes.unshift( type );
- break;
- }
- }
- }
- // Check to see if we have a response for the expected dataType
- if ( dataTypes[ 0 ] in responses ) {
- finalDataType = dataTypes[ 0 ];
- } else {
- // Try convertible dataTypes
- for ( type in responses ) {
- if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
- finalDataType = type;
- break;
- }
- if ( !firstDataType ) {
- firstDataType = type;
- }
- }
- // Or just use first one
- finalDataType = finalDataType || firstDataType;
- }
- // If we found a dataType
- // We add the dataType to the list if needed
- // and return the corresponding response
- if ( finalDataType ) {
- if ( finalDataType !== dataTypes[ 0 ] ) {
- dataTypes.unshift( finalDataType );
- }
- return responses[ finalDataType ];
- }
- }
- /* Chain conversions given the request and the original response
- * Also sets the responseXXX fields on the jqXHR instance
- */
- function ajaxConvert( s, response, jqXHR, isSuccess ) {
- var conv2, current, conv, tmp, prev,
- converters = {},
- // Work with a copy of dataTypes in case we need to modify it for conversion
- dataTypes = s.dataTypes.slice();
- // Create converters map with lowercased keys
- if ( dataTypes[ 1 ] ) {
- for ( conv in s.converters ) {
- converters[ conv.toLowerCase() ] = s.converters[ conv ];
- }
- }
- current = dataTypes.shift();
- // Convert to each sequential dataType
- while ( current ) {
- if ( s.responseFields[ current ] ) {
- jqXHR[ s.responseFields[ current ] ] = response;
- }
- // Apply the dataFilter if provided
- if ( !prev && isSuccess && s.dataFilter ) {
- response = s.dataFilter( response, s.dataType );
- }
- prev = current;
- current = dataTypes.shift();
- if ( current ) {
- // There's only work to do if current dataType is non-auto
- if ( current === "*" ) {
- current = prev;
- // Convert response if prev dataType is non-auto and differs from current
- } else if ( prev !== "*" && prev !== current ) {
- // Seek a direct converter
- conv = converters[ prev + " " + current ] || converters[ "* " + current ];
- // If none found, seek a pair
- if ( !conv ) {
- for ( conv2 in converters ) {
- // If conv2 outputs current
- tmp = conv2.split( " " );
- if ( tmp[ 1 ] === current ) {
- // If prev can be converted to accepted input
- conv = converters[ prev + " " + tmp[ 0 ] ] ||
- converters[ "* " + tmp[ 0 ] ];
- if ( conv ) {
- // Condense equivalence converters
- if ( conv === true ) {
- conv = converters[ conv2 ];
- // Otherwise, insert the intermediate dataType
- } else if ( converters[ conv2 ] !== true ) {
- current = tmp[ 0 ];
- dataTypes.unshift( tmp[ 1 ] );
- }
- break;
- }
- }
- }
- }
- // Apply converter (if not an equivalence)
- if ( conv !== true ) {
- // Unless errors are allowed to bubble, catch and return them
- if ( conv && s.throws ) {
- response = conv( response );
- } else {
- try {
- response = conv( response );
- } catch ( e ) {
- return {
- state: "parsererror",
- error: conv ? e : "No conversion from " + prev + " to " + current
- };
- }
- }
- }
- }
- }
- }
- return { state: "success", data: response };
- }
- jQuery.extend( {
- // Counter for holding the number of active queries
- active: 0,
- // Last-Modified header cache for next request
- lastModified: {},
- etag: {},
- ajaxSettings: {
- url: location.href,
- type: "GET",
- isLocal: rlocalProtocol.test( location.protocol ),
- global: true,
- processData: true,
- async: true,
- contentType: "application/x-www-form-urlencoded; charset=UTF-8",
- /*
- timeout: 0,
- data: null,
- dataType: null,
- username: null,
- password: null,
- cache: null,
- throws: false,
- traditional: false,
- headers: {},
- */
- accepts: {
- "*": allTypes,
- text: "text/plain",
- html: "text/html",
- xml: "application/xml, text/xml",
- json: "application/json, text/javascript"
- },
- contents: {
- xml: /\bxml\b/,
- html: /\bhtml/,
- json: /\bjson\b/
- },
- responseFields: {
- xml: "responseXML",
- text: "responseText",
- json: "responseJSON"
- },
- // Data converters
- // Keys separate source (or catchall "*") and destination types with a single space
- converters: {
- // Convert anything to text
- "* text": String,
- // Text to html (true = no transformation)
- "text html": true,
- // Evaluate text as a json expression
- "text json": JSON.parse,
- // Parse text as xml
- "text xml": jQuery.parseXML
- },
- // For options that shouldn't be deep extended:
- // you can add your own custom options here if
- // and when you create one that shouldn't be
- // deep extended (see ajaxExtend)
- flatOptions: {
- url: true,
- context: true
- }
- },
- // Creates a full fledged settings object into target
- // with both ajaxSettings and settings fields.
- // If target is omitted, writes into ajaxSettings.
- ajaxSetup: function( target, settings ) {
- return settings ?
- // Building a settings object
- ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
- // Extending ajaxSettings
- ajaxExtend( jQuery.ajaxSettings, target );
- },
- ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
- ajaxTransport: addToPrefiltersOrTransports( transports ),
- // Main method
- ajax: function( url, options ) {
- // If url is an object, simulate pre-1.5 signature
- if ( typeof url === "object" ) {
- options = url;
- url = undefined;
- }
- // Force options to be an object
- options = options || {};
- var transport,
- // URL without anti-cache param
- cacheURL,
- // Response headers
- responseHeadersString,
- responseHeaders,
- // timeout handle
- timeoutTimer,
- // Url cleanup var
- urlAnchor,
- // Request state (becomes false upon send and true upon completion)
- completed,
- // To know if global events are to be dispatched
- fireGlobals,
- // Loop variable
- i,
- // uncached part of the url
- uncached,
- // Create the final options object
- s = jQuery.ajaxSetup( {}, options ),
- // Callbacks context
- callbackContext = s.context || s,
- // Context for global events is callbackContext if it is a DOM node or jQuery collection
- globalEventContext = s.context &&
- ( callbackContext.nodeType || callbackContext.jquery ) ?
- jQuery( callbackContext ) :
- jQuery.event,
- // Deferreds
- deferred = jQuery.Deferred(),
- completeDeferred = jQuery.Callbacks( "once memory" ),
- // Status-dependent callbacks
- statusCode = s.statusCode || {},
- // Headers (they are sent all at once)
- requestHeaders = {},
- requestHeadersNames = {},
- // Default abort message
- strAbort = "canceled",
- // Fake xhr
- jqXHR = {
- readyState: 0,
- // Builds headers hashtable if needed
- getResponseHeader: function( key ) {
- var match;
- if ( completed ) {
- if ( !responseHeaders ) {
- responseHeaders = {};
- while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
- responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
- }
- }
- match = responseHeaders[ key.toLowerCase() ];
- }
- return match == null ? null : match;
- },
- // Raw string
- getAllResponseHeaders: function() {
- return completed ? responseHeadersString : null;
- },
- // Caches the header
- setRequestHeader: function( name, value ) {
- if ( completed == null ) {
- name = requestHeadersNames[ name.toLowerCase() ] =
- requestHeadersNames[ name.toLowerCase() ] || name;
- requestHeaders[ name ] = value;
- }
- return this;
- },
- // Overrides response content-type header
- overrideMimeType: function( type ) {
- if ( completed == null ) {
- s.mimeType = type;
- }
- return this;
- },
- // Status-dependent callbacks
- statusCode: function( map ) {
- var code;
- if ( map ) {
- if ( completed ) {
- // Execute the appropriate callbacks
- jqXHR.always( map[ jqXHR.status ] );
- } else {
- // Lazy-add the new callbacks in a way that preserves old ones
- for ( code in map ) {
- statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
- }
- }
- }
- return this;
- },
- // Cancel the request
- abort: function( statusText ) {
- var finalText = statusText || strAbort;
- if ( transport ) {
- transport.abort( finalText );
- }
- done( 0, finalText );
- return this;
- }
- };
- // Attach deferreds
- deferred.promise( jqXHR );
- // Add protocol if not provided (prefilters might expect it)
- // Handle falsy url in the settings object (#10093: consistency with old signature)
- // We also use the url parameter if available
- s.url = ( ( url || s.url || location.href ) + "" )
- .replace( rprotocol, location.protocol + "//" );
- // Alias method option to type as per ticket #12004
- s.type = options.method || options.type || s.method || s.type;
- // Extract dataTypes list
- s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
- // A cross-domain request is in order when the origin doesn't match the current origin.
- if ( s.crossDomain == null ) {
- urlAnchor = document.createElement( "a" );
- // Support: IE <=8 - 11, Edge 12 - 13
- // IE throws exception on accessing the href property if url is malformed,
- // e.g. http://example.com:80x/
- try {
- urlAnchor.href = s.url;
- // Support: IE <=8 - 11 only
- // Anchor's host property isn't correctly set when s.url is relative
- urlAnchor.href = urlAnchor.href;
- s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
- urlAnchor.protocol + "//" + urlAnchor.host;
- } catch ( e ) {
- // If there is an error parsing the URL, assume it is crossDomain,
- // it can be rejected by the transport if it is invalid
- s.crossDomain = true;
- }
- }
- // Convert data if not already a string
- if ( s.data && s.processData && typeof s.data !== "string" ) {
- s.data = jQuery.param( s.data, s.traditional );
- }
- // Apply prefilters
- inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
- // If request was aborted inside a prefilter, stop there
- if ( completed ) {
- return jqXHR;
- }
- // We can fire global events as of now if asked to
- // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
- fireGlobals = jQuery.event && s.global;
- // Watch for a new set of requests
- if ( fireGlobals && jQuery.active++ === 0 ) {
- jQuery.event.trigger( "ajaxStart" );
- }
- // Uppercase the type
- s.type = s.type.toUpperCase();
- // Determine if request has content
- s.hasContent = !rnoContent.test( s.type );
- // Save the URL in case we're toying with the If-Modified-Since
- // and/or If-None-Match header later on
- // Remove hash to simplify url manipulation
- cacheURL = s.url.replace( rhash, "" );
- // More options handling for requests with no content
- if ( !s.hasContent ) {
- // Remember the hash so we can put it back
- uncached = s.url.slice( cacheURL.length );
- // If data is available, append data to url
- if ( s.data ) {
- cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
- // #9682: remove data so that it's not used in an eventual retry
- delete s.data;
- }
- // Add or update anti-cache param if needed
- if ( s.cache === false ) {
- cacheURL = cacheURL.replace( rantiCache, "$1" );
- uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
- }
- // Put hash and anti-cache on the URL that will be requested (gh-1732)
- s.url = cacheURL + uncached;
- // Change '%20' to '+' if this is encoded form body content (gh-2658)
- } else if ( s.data && s.processData &&
- ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
- s.data = s.data.replace( r20, "+" );
- }
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
- if ( jQuery.lastModified[ cacheURL ] ) {
- jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
- }
- if ( jQuery.etag[ cacheURL ] ) {
- jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
- }
- }
- // Set the correct header, if data is being sent
- if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
- jqXHR.setRequestHeader( "Content-Type", s.contentType );
- }
- // Set the Accepts header for the server, depending on the dataType
- jqXHR.setRequestHeader(
- "Accept",
- s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
- s.accepts[ s.dataTypes[ 0 ] ] +
- ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
- s.accepts[ "*" ]
- );
- // Check for headers option
- for ( i in s.headers ) {
- jqXHR.setRequestHeader( i, s.headers[ i ] );
- }
- // Allow custom headers/mimetypes and early abort
- if ( s.beforeSend &&
- ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
- // Abort if not done already and return
- return jqXHR.abort();
- }
- // Aborting is no longer a cancellation
- strAbort = "abort";
- // Install callbacks on deferreds
- completeDeferred.add( s.complete );
- jqXHR.done( s.success );
- jqXHR.fail( s.error );
- // Get transport
- transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
- // If no transport, we auto-abort
- if ( !transport ) {
- done( -1, "No Transport" );
- } else {
- jqXHR.readyState = 1;
- // Send global event
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
- }
- // If request was aborted inside ajaxSend, stop there
- if ( completed ) {
- return jqXHR;
- }
- // Timeout
- if ( s.async && s.timeout > 0 ) {
- timeoutTimer = window.setTimeout( function() {
- jqXHR.abort( "timeout" );
- }, s.timeout );
- }
- try {
- completed = false;
- transport.send( requestHeaders, done );
- } catch ( e ) {
- // Rethrow post-completion exceptions
- if ( completed ) {
- throw e;
- }
- // Propagate others as results
- done( -1, e );
- }
- }
- // Callback for when everything is done
- function done( status, nativeStatusText, responses, headers ) {
- var isSuccess, success, error, response, modified,
- statusText = nativeStatusText;
- // Ignore repeat invocations
- if ( completed ) {
- return;
- }
- completed = true;
- // Clear timeout if it exists
- if ( timeoutTimer ) {
- window.clearTimeout( timeoutTimer );
- }
- // Dereference transport for early garbage collection
- // (no matter how long the jqXHR object will be used)
- transport = undefined;
- // Cache response headers
- responseHeadersString = headers || "";
- // Set readyState
- jqXHR.readyState = status > 0 ? 4 : 0;
- // Determine if successful
- isSuccess = status >= 200 && status < 300 || status === 304;
- // Get response data
- if ( responses ) {
- response = ajaxHandleResponses( s, jqXHR, responses );
- }
- // Convert no matter what (that way responseXXX fields are always set)
- response = ajaxConvert( s, response, jqXHR, isSuccess );
- // If successful, handle type chaining
- if ( isSuccess ) {
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
- modified = jqXHR.getResponseHeader( "Last-Modified" );
- if ( modified ) {
- jQuery.lastModified[ cacheURL ] = modified;
- }
- modified = jqXHR.getResponseHeader( "etag" );
- if ( modified ) {
- jQuery.etag[ cacheURL ] = modified;
- }
- }
- // if no content
- if ( status === 204 || s.type === "HEAD" ) {
- statusText = "nocontent";
- // if not modified
- } else if ( status === 304 ) {
- statusText = "notmodified";
- // If we have data, let's convert it
- } else {
- statusText = response.state;
- success = response.data;
- error = response.error;
- isSuccess = !error;
- }
- } else {
- // Extract error from statusText and normalize for non-aborts
- error = statusText;
- if ( status || !statusText ) {
- statusText = "error";
- if ( status < 0 ) {
- status = 0;
- }
- }
- }
- // Set data for the fake xhr object
- jqXHR.status = status;
- jqXHR.statusText = ( nativeStatusText || statusText ) + "";
- // Success/Error
- if ( isSuccess ) {
- deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
- } else {
- deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
- }
- // Status-dependent callbacks
- jqXHR.statusCode( statusCode );
- statusCode = undefined;
- if ( fireGlobals ) {
- globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
- [ jqXHR, s, isSuccess ? success : error ] );
- }
- // Complete
- completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
- // Handle the global AJAX counter
- if ( !( --jQuery.active ) ) {
- jQuery.event.trigger( "ajaxStop" );
- }
- }
- }
- return jqXHR;
- },
- getJSON: function( url, data, callback ) {
- return jQuery.get( url, data, callback, "json" );
- },
- getScript: function( url, callback ) {
- return jQuery.get( url, undefined, callback, "script" );
- }
- } );
- jQuery.each( [ "get", "post" ], function( i, method ) {
- jQuery[ method ] = function( url, data, callback, type ) {
- // Shift arguments if data argument was omitted
- if ( jQuery.isFunction( data ) ) {
- type = type || callback;
- callback = data;
- data = undefined;
- }
- // The url can be an options object (which then must have .url)
- return jQuery.ajax( jQuery.extend( {
- url: url,
- type: method,
- dataType: type,
- data: data,
- success: callback
- }, jQuery.isPlainObject( url ) && url ) );
- };
- } );
- jQuery._evalUrl = function( url ) {
- return jQuery.ajax( {
- url: url,
- // Make this explicit, since user can override this through ajaxSetup (#11264)
- type: "GET",
- dataType: "script",
- cache: true,
- async: false,
- global: false,
- "throws": true
- } );
- };
- jQuery.fn.extend( {
- wrapAll: function( html ) {
- var wrap;
- if ( this[ 0 ] ) {
- if ( jQuery.isFunction( html ) ) {
- html = html.call( this[ 0 ] );
- }
- // The elements to wrap the target around
- wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
- if ( this[ 0 ].parentNode ) {
- wrap.insertBefore( this[ 0 ] );
- }
- wrap.map( function() {
- var elem = this;
- while ( elem.firstElementChild ) {
- elem = elem.firstElementChild;
- }
- return elem;
- } ).append( this );
- }
- return this;
- },
- wrapInner: function( html ) {
- if ( jQuery.isFunction( html ) ) {
- return this.each( function( i ) {
- jQuery( this ).wrapInner( html.call( this, i ) );
- } );
- }
- return this.each( function() {
- var self = jQuery( this ),
- contents = self.contents();
- if ( contents.length ) {
- contents.wrapAll( html );
- } else {
- self.append( html );
- }
- } );
- },
- wrap: function( html ) {
- var isFunction = jQuery.isFunction( html );
- return this.each( function( i ) {
- jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
- } );
- },
- unwrap: function( selector ) {
- this.parent( selector ).not( "body" ).each( function() {
- jQuery( this ).replaceWith( this.childNodes );
- } );
- return this;
- }
- } );
- jQuery.expr.pseudos.hidden = function( elem ) {
- return !jQuery.expr.pseudos.visible( elem );
- };
- jQuery.expr.pseudos.visible = function( elem ) {
- return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
- };
- jQuery.ajaxSettings.xhr = function() {
- try {
- return new window.XMLHttpRequest();
- } catch ( e ) {}
- };
- var xhrSuccessStatus = {
- // File protocol always yields status code 0, assume 200
- 0: 200,
- // Support: IE <=9 only
- // #1450: sometimes IE returns 1223 when it should be 204
- 1223: 204
- },
- xhrSupported = jQuery.ajaxSettings.xhr();
- support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
- support.ajax = xhrSupported = !!xhrSupported;
- jQuery.ajaxTransport( function( options ) {
- var callback, errorCallback;
- // Cross domain only allowed if supported through XMLHttpRequest
- if ( support.cors || xhrSupported && !options.crossDomain ) {
- return {
- send: function( headers, complete ) {
- var i,
- xhr = options.xhr();
- xhr.open(
- options.type,
- options.url,
- options.async,
- options.username,
- options.password
- );
- // Apply custom fields if provided
- if ( options.xhrFields ) {
- for ( i in options.xhrFields ) {
- xhr[ i ] = options.xhrFields[ i ];
- }
- }
- // Override mime type if needed
- if ( options.mimeType && xhr.overrideMimeType ) {
- xhr.overrideMimeType( options.mimeType );
- }
- // X-Requested-With header
- // For cross-domain requests, seeing as conditions for a preflight are
- // akin to a jigsaw puzzle, we simply never set it to be sure.
- // (it can always be set on a per-request basis or even using ajaxSetup)
- // For same-domain requests, won't change header if already provided.
- if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
- headers[ "X-Requested-With" ] = "XMLHttpRequest";
- }
- // Set headers
- for ( i in headers ) {
- xhr.setRequestHeader( i, headers[ i ] );
- }
- // Callback
- callback = function( type ) {
- return function() {
- if ( callback ) {
- callback = errorCallback = xhr.onload =
- xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
- if ( type === "abort" ) {
- xhr.abort();
- } else if ( type === "error" ) {
- // Support: IE <=9 only
- // On a manual native abort, IE9 throws
- // errors on any property access that is not readyState
- if ( typeof xhr.status !== "number" ) {
- complete( 0, "error" );
- } else {
- complete(
- // File: protocol always yields status 0; see #8605, #14207
- xhr.status,
- xhr.statusText
- );
- }
- } else {
- complete(
- xhrSuccessStatus[ xhr.status ] || xhr.status,
- xhr.statusText,
- // Support: IE <=9 only
- // IE9 has no XHR2 but throws on binary (trac-11426)
- // For XHR2 non-text, let the caller handle it (gh-2498)
- ( xhr.responseType || "text" ) !== "text" ||
- typeof xhr.responseText !== "string" ?
- { binary: xhr.response } :
- { text: xhr.responseText },
- xhr.getAllResponseHeaders()
- );
- }
- }
- };
- };
- // Listen to events
- xhr.onload = callback();
- errorCallback = xhr.onerror = callback( "error" );
- // Support: IE 9 only
- // Use onreadystatechange to replace onabort
- // to handle uncaught aborts
- if ( xhr.onabort !== undefined ) {
- xhr.onabort = errorCallback;
- } else {
- xhr.onreadystatechange = function() {
- // Check readyState before timeout as it changes
- if ( xhr.readyState === 4 ) {
- // Allow onerror to be called first,
- // but that will not handle a native abort
- // Also, save errorCallback to a variable
- // as xhr.onerror cannot be accessed
- window.setTimeout( function() {
- if ( callback ) {
- errorCallback();
- }
- } );
- }
- };
- }
- // Create the abort callback
- callback = callback( "abort" );
- try {
- // Do send the request (this may raise an exception)
- xhr.send( options.hasContent && options.data || null );
- } catch ( e ) {
- // #14683: Only rethrow if this hasn't been notified as an error yet
- if ( callback ) {
- throw e;
- }
- }
- },
- abort: function() {
- if ( callback ) {
- callback();
- }
- }
- };
- }
- } );
- // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
- jQuery.ajaxPrefilter( function( s ) {
- if ( s.crossDomain ) {
- s.contents.script = false;
- }
- } );
- // Install script dataType
- jQuery.ajaxSetup( {
- accepts: {
- script: "text/javascript, application/javascript, " +
- "application/ecmascript, application/x-ecmascript"
- },
- contents: {
- script: /\b(?:java|ecma)script\b/
- },
- converters: {
- "text script": function( text ) {
- jQuery.globalEval( text );
- return text;
- }
- }
- } );
- // Handle cache's special case and crossDomain
- jQuery.ajaxPrefilter( "script", function( s ) {
- if ( s.cache === undefined ) {
- s.cache = false;
- }
- if ( s.crossDomain ) {
- s.type = "GET";
- }
- } );
- // Bind script tag hack transport
- jQuery.ajaxTransport( "script", function( s ) {
- // This transport only deals with cross domain requests
- if ( s.crossDomain ) {
- var script, callback;
- return {
- send: function( _, complete ) {
- script = jQuery( "<script>" ).prop( {
- charset: s.scriptCharset,
- src: s.url
- } ).on(
- "load error",
- callback = function( evt ) {
- script.remove();
- callback = null;
- if ( evt ) {
- complete( evt.type === "error" ? 404 : 200, evt.type );
- }
- }
- );
- // Use native DOM manipulation to avoid our domManip AJAX trickery
- document.head.appendChild( script[ 0 ] );
- },
- abort: function() {
- if ( callback ) {
- callback();
- }
- }
- };
- }
- } );
- var oldCallbacks = [],
- rjsonp = /(=)\?(?=&|$)|\?\?/;
- // Default jsonp settings
- jQuery.ajaxSetup( {
- jsonp: "callback",
- jsonpCallback: function() {
- var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
- this[ callback ] = true;
- return callback;
- }
- } );
- // Detect, normalize options and install callbacks for jsonp requests
- jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
- var callbackName, overwritten, responseContainer,
- jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
- "url" :
- typeof s.data === "string" &&
- ( s.contentType || "" )
- .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
- rjsonp.test( s.data ) && "data"
- );
- // Handle iff the expected data type is "jsonp" or we have a parameter to set
- if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
- // Get callback name, remembering preexisting value associated with it
- callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
- s.jsonpCallback() :
- s.jsonpCallback;
- // Insert callback into url or form data
- if ( jsonProp ) {
- s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
- } else if ( s.jsonp !== false ) {
- s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
- }
- // Use data converter to retrieve json after script execution
- s.converters[ "script json" ] = function() {
- if ( !responseContainer ) {
- jQuery.error( callbackName + " was not called" );
- }
- return responseContainer[ 0 ];
- };
- // Force json dataType
- s.dataTypes[ 0 ] = "json";
- // Install callback
- overwritten = window[ callbackName ];
- window[ callbackName ] = function() {
- responseContainer = arguments;
- };
- // Clean-up function (fires after converters)
- jqXHR.always( function() {
- // If previous value didn't exist - remove it
- if ( overwritten === undefined ) {
- jQuery( window ).removeProp( callbackName );
- // Otherwise restore preexisting value
- } else {
- window[ callbackName ] = overwritten;
- }
- // Save back as free
- if ( s[ callbackName ] ) {
- // Make sure that re-using the options doesn't screw things around
- s.jsonpCallback = originalSettings.jsonpCallback;
- // Save the callback name for future use
- oldCallbacks.push( callbackName );
- }
- // Call if it was a function and we have a response
- if ( responseContainer && jQuery.isFunction( overwritten ) ) {
- overwritten( responseContainer[ 0 ] );
- }
- responseContainer = overwritten = undefined;
- } );
- // Delegate to script
- return "script";
- }
- } );
- // Support: Safari 8 only
- // In Safari 8 documents created via document.implementation.createHTMLDocument
- // collapse sibling forms: the second one becomes a child of the first one.
- // Because of that, this security measure has to be disabled in Safari 8.
- // https://bugs.webkit.org/show_bug.cgi?id=137337
- support.createHTMLDocument = ( function() {
- var body = document.implementation.createHTMLDocument( "" ).body;
- body.innerHTML = "<form></form><form></form>";
- return body.childNodes.length === 2;
- } )();
- // Argument "data" should be string of html
- // context (optional): If specified, the fragment will be created in this context,
- // defaults to document
- // keepScripts (optional): If true, will include scripts passed in the html string
- jQuery.parseHTML = function( data, context, keepScripts ) {
- if ( typeof data !== "string" ) {
- return [];
- }
- if ( typeof context === "boolean" ) {
- keepScripts = context;
- context = false;
- }
- var base, parsed, scripts;
- if ( !context ) {
- // Stop scripts or inline event handlers from being executed immediately
- // by using document.implementation
- if ( support.createHTMLDocument ) {
- context = document.implementation.createHTMLDocument( "" );
- // Set the base href for the created document
- // so any parsed elements with URLs
- // are based on the document's URL (gh-2965)
- base = context.createElement( "base" );
- base.href = document.location.href;
- context.head.appendChild( base );
- } else {
- context = document;
- }
- }
- parsed = rsingleTag.exec( data );
- scripts = !keepScripts && [];
- // Single tag
- if ( parsed ) {
- return [ context.createElement( parsed[ 1 ] ) ];
- }
- parsed = buildFragment( [ data ], context, scripts );
- if ( scripts && scripts.length ) {
- jQuery( scripts ).remove();
- }
- return jQuery.merge( [], parsed.childNodes );
- };
- /**
- * Load a url into a page
- */
- jQuery.fn.load = function( url, params, callback ) {
- var selector, type, response,
- self = this,
- off = url.indexOf( " " );
- if ( off > -1 ) {
- selector = stripAndCollapse( url.slice( off ) );
- url = url.slice( 0, off );
- }
- // If it's a function
- if ( jQuery.isFunction( params ) ) {
- // We assume that it's the callback
- callback = params;
- params = undefined;
- // Otherwise, build a param string
- } else if ( params && typeof params === "object" ) {
- type = "POST";
- }
- // If we have elements to modify, make the request
- if ( self.length > 0 ) {
- jQuery.ajax( {
- url: url,
- // If "type" variable is undefined, then "GET" method will be used.
- // Make value of this field explicit since
- // user can override it through ajaxSetup method
- type: type || "GET",
- dataType: "html",
- data: params
- } ).done( function( responseText ) {
- // Save response for use in complete callback
- response = arguments;
- self.html( selector ?
- // If a selector was specified, locate the right elements in a dummy div
- // Exclude scripts to avoid IE 'Permission Denied' errors
- jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
- // Otherwise use the full result
- responseText );
- // If the request succeeds, this function gets "data", "status", "jqXHR"
- // but they are ignored because response was set above.
- // If it fails, this function gets "jqXHR", "status", "error"
- } ).always( callback && function( jqXHR, status ) {
- self.each( function() {
- callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
- } );
- } );
- }
- return this;
- };
- // Attach a bunch of functions for handling common AJAX events
- jQuery.each( [
- "ajaxStart",
- "ajaxStop",
- "ajaxComplete",
- "ajaxError",
- "ajaxSuccess",
- "ajaxSend"
- ], function( i, type ) {
- jQuery.fn[ type ] = function( fn ) {
- return this.on( type, fn );
- };
- } );
- jQuery.expr.pseudos.animated = function( elem ) {
- return jQuery.grep( jQuery.timers, function( fn ) {
- return elem === fn.elem;
- } ).length;
- };
- jQuery.offset = {
- setOffset: function( elem, options, i ) {
- var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
- position = jQuery.css( elem, "position" ),
- curElem = jQuery( elem ),
- props = {};
- // Set position first, in-case top/left are set even on static elem
- if ( position === "static" ) {
- elem.style.position = "relative";
- }
- curOffset = curElem.offset();
- curCSSTop = jQuery.css( elem, "top" );
- curCSSLeft = jQuery.css( elem, "left" );
- calculatePosition = ( position === "absolute" || position === "fixed" ) &&
- ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
- // Need to be able to calculate position if either
- // top or left is auto and position is either absolute or fixed
- if ( calculatePosition ) {
- curPosition = curElem.position();
- curTop = curPosition.top;
- curLeft = curPosition.left;
- } else {
- curTop = parseFloat( curCSSTop ) || 0;
- curLeft = parseFloat( curCSSLeft ) || 0;
- }
- if ( jQuery.isFunction( options ) ) {
- // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
- options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
- }
- if ( options.top != null ) {
- props.top = ( options.top - curOffset.top ) + curTop;
- }
- if ( options.left != null ) {
- props.left = ( options.left - curOffset.left ) + curLeft;
- }
- if ( "using" in options ) {
- options.using.call( elem, props );
- } else {
- curElem.css( props );
- }
- }
- };
- jQuery.fn.extend( {
- offset: function( options ) {
- // Preserve chaining for setter
- if ( arguments.length ) {
- return options === undefined ?
- this :
- this.each( function( i ) {
- jQuery.offset.setOffset( this, options, i );
- } );
- }
- var doc, docElem, rect, win,
- elem = this[ 0 ];
- if ( !elem ) {
- return;
- }
- // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
- // Support: IE <=11 only
- // Running getBoundingClientRect on a
- // disconnected node in IE throws an error
- if ( !elem.getClientRects().length ) {
- return { top: 0, left: 0 };
- }
- rect = elem.getBoundingClientRect();
- doc = elem.ownerDocument;
- docElem = doc.documentElement;
- win = doc.defaultView;
- return {
- top: rect.top + win.pageYOffset - docElem.clientTop,
- left: rect.left + win.pageXOffset - docElem.clientLeft
- };
- },
- position: function() {
- if ( !this[ 0 ] ) {
- return;
- }
- var offsetParent, offset,
- elem = this[ 0 ],
- parentOffset = { top: 0, left: 0 };
- // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
- // because it is its only offset parent
- if ( jQuery.css( elem, "position" ) === "fixed" ) {
- // Assume getBoundingClientRect is there when computed position is fixed
- offset = elem.getBoundingClientRect();
- } else {
- // Get *real* offsetParent
- offsetParent = this.offsetParent();
- // Get correct offsets
- offset = this.offset();
- if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
- parentOffset = offsetParent.offset();
- }
- // Add offsetParent borders
- parentOffset = {
- top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
- left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
- };
- }
- // Subtract parent offsets and element margins
- return {
- top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
- left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
- };
- },
- // This method will return documentElement in the following cases:
- // 1) For the element inside the iframe without offsetParent, this method will return
- // documentElement of the parent window
- // 2) For the hidden or detached element
- // 3) For body or html element, i.e. in case of the html node - it will return itself
- //
- // but those exceptions were never presented as a real life use-cases
- // and might be considered as more preferable results.
- //
- // This logic, however, is not guaranteed and can change at any point in the future
- offsetParent: function() {
- return this.map( function() {
- var offsetParent = this.offsetParent;
- while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
- offsetParent = offsetParent.offsetParent;
- }
- return offsetParent || documentElement;
- } );
- }
- } );
- // Create scrollLeft and scrollTop methods
- jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
- var top = "pageYOffset" === prop;
- jQuery.fn[ method ] = function( val ) {
- return access( this, function( elem, method, val ) {
- // Coalesce documents and windows
- var win;
- if ( jQuery.isWindow( elem ) ) {
- win = elem;
- } else if ( elem.nodeType === 9 ) {
- win = elem.defaultView;
- }
- if ( val === undefined ) {
- return win ? win[ prop ] : elem[ method ];
- }
- if ( win ) {
- win.scrollTo(
- !top ? val : win.pageXOffset,
- top ? val : win.pageYOffset
- );
- } else {
- elem[ method ] = val;
- }
- }, method, val, arguments.length );
- };
- } );
- // Support: Safari <=7 - 9.1, Chrome <=37 - 49
- // Add the top/left cssHooks using jQuery.fn.position
- // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
- // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
- // getComputedStyle returns percent when specified for top/left/bottom/right;
- // rather than make the css module depend on the offset module, just check for it here
- jQuery.each( [ "top", "left" ], function( i, prop ) {
- jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
- function( elem, computed ) {
- if ( computed ) {
- computed = curCSS( elem, prop );
- // If curCSS returns percentage, fallback to offset
- return rnumnonpx.test( computed ) ?
- jQuery( elem ).position()[ prop ] + "px" :
- computed;
- }
- }
- );
- } );
- // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
- jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
- jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
- function( defaultExtra, funcName ) {
- // Margin is only for outerHeight, outerWidth
- jQuery.fn[ funcName ] = function( margin, value ) {
- var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
- extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
- return access( this, function( elem, type, value ) {
- var doc;
- if ( jQuery.isWindow( elem ) ) {
- // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
- return funcName.indexOf( "outer" ) === 0 ?
- elem[ "inner" + name ] :
- elem.document.documentElement[ "client" + name ];
- }
- // Get document width or height
- if ( elem.nodeType === 9 ) {
- doc = elem.documentElement;
- // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
- // whichever is greatest
- return Math.max(
- elem.body[ "scroll" + name ], doc[ "scroll" + name ],
- elem.body[ "offset" + name ], doc[ "offset" + name ],
- doc[ "client" + name ]
- );
- }
- return value === undefined ?
- // Get width or height on the element, requesting but not forcing parseFloat
- jQuery.css( elem, type, extra ) :
- // Set width or height on the element
- jQuery.style( elem, type, value, extra );
- }, type, chainable ? margin : undefined, chainable );
- };
- } );
- } );
- jQuery.fn.extend( {
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length === 1 ?
- this.off( selector, "**" ) :
- this.off( types, selector || "**", fn );
- }
- } );
- jQuery.holdReady = function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- };
- jQuery.isArray = Array.isArray;
- jQuery.parseJSON = JSON.parse;
- jQuery.nodeName = nodeName;
- // Register as a named AMD module, since jQuery can be concatenated with other
- // files that may use define, but not via a proper concatenation script that
- // understands anonymous AMD modules. A named AMD is safest and most robust
- // way to register. Lowercase jquery is used because AMD module names are
- // derived from file names, and jQuery is normally delivered in a lowercase
- // file name. Do this after creating the global so that if an AMD module wants
- // to call noConflict to hide this version of jQuery, it will work.
- // Note that for maximum portability, libraries that are not jQuery should
- // declare themselves as anonymous modules, and avoid setting a global if an
- // AMD loader is present. jQuery is a special case. For more information, see
- // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
- if ( true ) {
- !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
- return jQuery;
- }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
- __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
- }
- var
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
- // Map over the $ in case of overwrite
- _$ = window.$;
- jQuery.noConflict = function( deep ) {
- if ( window.$ === jQuery ) {
- window.$ = _$;
- }
- if ( deep && window.jQuery === jQuery ) {
- window.jQuery = _jQuery;
- }
- return jQuery;
- };
- // Expose jQuery and $ identifiers, even in AMD
- // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
- // and CommonJS for browser emulators (#13566)
- if ( !noGlobal ) {
- window.jQuery = window.$ = jQuery;
- }
- return jQuery;
- } );
- /***/ }),
- /* 1 */
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery__ = __webpack_require__(0);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_jquery__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_bootstrap__ = __webpack_require__(2);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_bootstrap___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_bootstrap__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap_select__ = __webpack_require__(15);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap_select___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_bootstrap_select__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_bootstrap_validator__ = __webpack_require__(16);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_bootstrap_validator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_bootstrap_validator__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput__ = __webpack_require__(17);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_bootstrap_fileinput__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css__ = __webpack_require__(18);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_bootstrap_dist_css_bootstrap_css__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css__ = __webpack_require__(19);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_bootstrap_select_dist_css_bootstrap_select_css__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css__ = __webpack_require__(20);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_bootstrap_fileinput_css_fileinput_css__);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css__ = __webpack_require__(21);
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__style_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8__style_css__);
- // Javascript
- // CSS
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(function () {
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#myInput").on("keyup", function(eventObject) {
-
- var input, filter, ul, li, a, i;
- input = eventObject.currentTarget;
- filter = input.value.toUpperCase();
- ul = document.getElementById("myUL");
- li = ul.getElementsByTagName('a');
- // Loop through all list items, and hide those who don't match the search query
- for (i = 0; i < li.length; i++) {
- a = li[i]; //li[i].getElementsByTagName("a")[0];
- if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
- li[i].style.display = "";
- } else {
- li[i].style.display = "none";
- }
- }
- });
- function checkUsernameInputHandler(eventObject) {
- var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
- var data = JSON.stringify({"username": input_el.val()});
- var url = `/teachers/check_username/${input_el.val()}`
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
- url,
- data,
- function(result) {
- if (result.exists) {
- console.log("Username exists");
- }
- },
- "json"
- );
- }
- function usernameGenerator(eventObject, firstname, surname) {
- var input_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(eventObject.currentTarget);
- input_el.val(firstname+"."+surname);
- }
- function deleteRelationHandler(eventObject) {
- var url = this.dataset.url;
- var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
-
- var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
- modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
- url: url,
- type: 'DELETE',
- success: function(result) {
- el.closest(".list-group-item").remove();
- modalEl.modal('hide');
- }
- });
-
- });
-
- return false;
- };
- function deleteHandler(eventObject) {
- var url = this.dataset.url;
- var modalEl = __WEBPACK_IMPORTED_MODULE_0_jquery___default()('#karmen-modal-remove');
-
- var el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()(this);
- modalEl.modal({backdrop: 'static'}).one('click', '#karmen-modal-btn-confirm', function() {
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.ajax({
- url: url,
- type: 'DELETE',
- success: function(result) {
- modalEl.modal('hide');
- window.location.replace(result.redirect_url);
- }
- });
-
- });
-
- return false;
- };
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".ajax-post").on("click", function(eventObject) {
- var select_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.select).first();
- var listgroup_el = __WEBPACK_IMPORTED_MODULE_0_jquery___default()("#"+this.dataset.listgroup).first();
- var url = this.dataset.url;
- var data = JSON.stringify({"ids": select_el.val()});
-
- __WEBPACK_IMPORTED_MODULE_0_jquery___default.a.post(
- url,
- data,
- function(result) {
- var i;
- if (result.elements != null) {
- for (i = 0; i < result.elements.length; i++) {
- var newItem = `
- <a href="#" class="list-group-item clearfix">
- <span class="glyphicon glyphicon-book"></span>
- ${result.elements[i].Name}
- <span class="pull-right">
- <button data-url="/${result.name1}/${result.id1}/${result.name2}/${result.id2[i]}/delete" class="btn btn-xs btn-warning karmen-ajax-delete">
- <span class="glyphicon glyphicon-trash"></span>
- </button>
- </span>
- `;
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(listgroup_el).append(newItem);
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
- }
- }
-
- },
- "json"
- );
- select_el.val('default');
- select_el.selectpicker("refresh");
-
- return false;
-
- });
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete-relation").on("click", deleteRelationHandler);
- __WEBPACK_IMPORTED_MODULE_0_jquery___default()(".karmen-ajax-delete").on("click", deleteHandler);
- });
- /***/ }),
- /* 2 */
- /***/ (function(module, exports, __webpack_require__) {
- // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
- __webpack_require__(3)
- __webpack_require__(4)
- __webpack_require__(5)
- __webpack_require__(6)
- __webpack_require__(7)
- __webpack_require__(8)
- __webpack_require__(9)
- __webpack_require__(10)
- __webpack_require__(11)
- __webpack_require__(12)
- __webpack_require__(13)
- __webpack_require__(14)
- /***/ }),
- /* 3 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: transition.js v3.3.7
- * http://getbootstrap.com/javascript/#transitions
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
- // ============================================================
- function transitionEnd() {
- var el = document.createElement('bootstrap')
- var transEndEventNames = {
- WebkitTransition : 'webkitTransitionEnd',
- MozTransition : 'transitionend',
- OTransition : 'oTransitionEnd otransitionend',
- transition : 'transitionend'
- }
- for (var name in transEndEventNames) {
- if (el.style[name] !== undefined) {
- return { end: transEndEventNames[name] }
- }
- }
- return false // explicit for ie8 ( ._.)
- }
- // http://blog.alexmaccaw.com/css-transitions
- $.fn.emulateTransitionEnd = function (duration) {
- var called = false
- var $el = this
- $(this).one('bsTransitionEnd', function () { called = true })
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
- setTimeout(callback, duration)
- return this
- }
- $(function () {
- $.support.transition = transitionEnd()
- if (!$.support.transition) return
- $.event.special.bsTransitionEnd = {
- bindType: $.support.transition.end,
- delegateType: $.support.transition.end,
- handle: function (e) {
- if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
- }
- }
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 4 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: alert.js v3.3.7
- * http://getbootstrap.com/javascript/#alerts
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // ALERT CLASS DEFINITION
- // ======================
- var dismiss = '[data-dismiss="alert"]'
- var Alert = function (el) {
- $(el).on('click', dismiss, this.close)
- }
- Alert.VERSION = '3.3.7'
- Alert.TRANSITION_DURATION = 150
- Alert.prototype.close = function (e) {
- var $this = $(this)
- var selector = $this.attr('data-target')
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
- var $parent = $(selector === '#' ? [] : selector)
- if (e) e.preventDefault()
- if (!$parent.length) {
- $parent = $this.closest('.alert')
- }
- $parent.trigger(e = $.Event('close.bs.alert'))
- if (e.isDefaultPrevented()) return
- $parent.removeClass('in')
- function removeElement() {
- // detach from parent, fire event then clean up data
- $parent.detach().trigger('closed.bs.alert').remove()
- }
- $.support.transition && $parent.hasClass('fade') ?
- $parent
- .one('bsTransitionEnd', removeElement)
- .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
- removeElement()
- }
- // ALERT PLUGIN DEFINITION
- // =======================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.alert')
- if (!data) $this.data('bs.alert', (data = new Alert(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
- var old = $.fn.alert
- $.fn.alert = Plugin
- $.fn.alert.Constructor = Alert
- // ALERT NO CONFLICT
- // =================
- $.fn.alert.noConflict = function () {
- $.fn.alert = old
- return this
- }
- // ALERT DATA-API
- // ==============
- $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 5 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: button.js v3.3.7
- * http://getbootstrap.com/javascript/#buttons
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // BUTTON PUBLIC CLASS DEFINITION
- // ==============================
- var Button = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Button.DEFAULTS, options)
- this.isLoading = false
- }
- Button.VERSION = '3.3.7'
- Button.DEFAULTS = {
- loadingText: 'loading...'
- }
- Button.prototype.setState = function (state) {
- var d = 'disabled'
- var $el = this.$element
- var val = $el.is('input') ? 'val' : 'html'
- var data = $el.data()
- state += 'Text'
- if (data.resetText == null) $el.data('resetText', $el[val]())
- // push to event loop to allow forms to submit
- setTimeout($.proxy(function () {
- $el[val](data[state] == null ? this.options[state] : data[state])
- if (state == 'loadingText') {
- this.isLoading = true
- $el.addClass(d).attr(d, d).prop(d, true)
- } else if (this.isLoading) {
- this.isLoading = false
- $el.removeClass(d).removeAttr(d).prop(d, false)
- }
- }, this), 0)
- }
- Button.prototype.toggle = function () {
- var changed = true
- var $parent = this.$element.closest('[data-toggle="buttons"]')
- if ($parent.length) {
- var $input = this.$element.find('input')
- if ($input.prop('type') == 'radio') {
- if ($input.prop('checked')) changed = false
- $parent.find('.active').removeClass('active')
- this.$element.addClass('active')
- } else if ($input.prop('type') == 'checkbox') {
- if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
- this.$element.toggleClass('active')
- }
- $input.prop('checked', this.$element.hasClass('active'))
- if (changed) $input.trigger('change')
- } else {
- this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
- this.$element.toggleClass('active')
- }
- }
- // BUTTON PLUGIN DEFINITION
- // ========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.button')
- var options = typeof option == 'object' && option
- if (!data) $this.data('bs.button', (data = new Button(this, options)))
- if (option == 'toggle') data.toggle()
- else if (option) data.setState(option)
- })
- }
- var old = $.fn.button
- $.fn.button = Plugin
- $.fn.button.Constructor = Button
- // BUTTON NO CONFLICT
- // ==================
- $.fn.button.noConflict = function () {
- $.fn.button = old
- return this
- }
- // BUTTON DATA-API
- // ===============
- $(document)
- .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- var $btn = $(e.target).closest('.btn')
- Plugin.call($btn, 'toggle')
- if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
- // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
- e.preventDefault()
- // The target component still receive the focus
- if ($btn.is('input,button')) $btn.trigger('focus')
- else $btn.find('input:visible,button:visible').first().trigger('focus')
- }
- })
- .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 6 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: carousel.js v3.3.7
- * http://getbootstrap.com/javascript/#carousel
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // CAROUSEL CLASS DEFINITION
- // =========================
- var Carousel = function (element, options) {
- this.$element = $(element)
- this.$indicators = this.$element.find('.carousel-indicators')
- this.options = options
- this.paused = null
- this.sliding = null
- this.interval = null
- this.$active = null
- this.$items = null
- this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
- this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
- .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
- .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
- }
- Carousel.VERSION = '3.3.7'
- Carousel.TRANSITION_DURATION = 600
- Carousel.DEFAULTS = {
- interval: 5000,
- pause: 'hover',
- wrap: true,
- keyboard: true
- }
- Carousel.prototype.keydown = function (e) {
- if (/input|textarea/i.test(e.target.tagName)) return
- switch (e.which) {
- case 37: this.prev(); break
- case 39: this.next(); break
- default: return
- }
- e.preventDefault()
- }
- Carousel.prototype.cycle = function (e) {
- e || (this.paused = false)
- this.interval && clearInterval(this.interval)
- this.options.interval
- && !this.paused
- && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
- return this
- }
- Carousel.prototype.getItemIndex = function (item) {
- this.$items = item.parent().children('.item')
- return this.$items.index(item || this.$active)
- }
- Carousel.prototype.getItemForDirection = function (direction, active) {
- var activeIndex = this.getItemIndex(active)
- var willWrap = (direction == 'prev' && activeIndex === 0)
- || (direction == 'next' && activeIndex == (this.$items.length - 1))
- if (willWrap && !this.options.wrap) return active
- var delta = direction == 'prev' ? -1 : 1
- var itemIndex = (activeIndex + delta) % this.$items.length
- return this.$items.eq(itemIndex)
- }
- Carousel.prototype.to = function (pos) {
- var that = this
- var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
- if (pos > (this.$items.length - 1) || pos < 0) return
- if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
- if (activeIndex == pos) return this.pause().cycle()
- return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
- }
- Carousel.prototype.pause = function (e) {
- e || (this.paused = true)
- if (this.$element.find('.next, .prev').length && $.support.transition) {
- this.$element.trigger($.support.transition.end)
- this.cycle(true)
- }
- this.interval = clearInterval(this.interval)
- return this
- }
- Carousel.prototype.next = function () {
- if (this.sliding) return
- return this.slide('next')
- }
- Carousel.prototype.prev = function () {
- if (this.sliding) return
- return this.slide('prev')
- }
- Carousel.prototype.slide = function (type, next) {
- var $active = this.$element.find('.item.active')
- var $next = next || this.getItemForDirection(type, $active)
- var isCycling = this.interval
- var direction = type == 'next' ? 'left' : 'right'
- var that = this
- if ($next.hasClass('active')) return (this.sliding = false)
- var relatedTarget = $next[0]
- var slideEvent = $.Event('slide.bs.carousel', {
- relatedTarget: relatedTarget,
- direction: direction
- })
- this.$element.trigger(slideEvent)
- if (slideEvent.isDefaultPrevented()) return
- this.sliding = true
- isCycling && this.pause()
- if (this.$indicators.length) {
- this.$indicators.find('.active').removeClass('active')
- var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
- $nextIndicator && $nextIndicator.addClass('active')
- }
- var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
- if ($.support.transition && this.$element.hasClass('slide')) {
- $next.addClass(type)
- $next[0].offsetWidth // force reflow
- $active.addClass(direction)
- $next.addClass(direction)
- $active
- .one('bsTransitionEnd', function () {
- $next.removeClass([type, direction].join(' ')).addClass('active')
- $active.removeClass(['active', direction].join(' '))
- that.sliding = false
- setTimeout(function () {
- that.$element.trigger(slidEvent)
- }, 0)
- })
- .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
- } else {
- $active.removeClass('active')
- $next.addClass('active')
- this.sliding = false
- this.$element.trigger(slidEvent)
- }
- isCycling && this.cycle()
- return this
- }
- // CAROUSEL PLUGIN DEFINITION
- // ==========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.carousel')
- var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
- var action = typeof option == 'string' ? option : options.slide
- if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
- if (typeof option == 'number') data.to(option)
- else if (action) data[action]()
- else if (options.interval) data.pause().cycle()
- })
- }
- var old = $.fn.carousel
- $.fn.carousel = Plugin
- $.fn.carousel.Constructor = Carousel
- // CAROUSEL NO CONFLICT
- // ====================
- $.fn.carousel.noConflict = function () {
- $.fn.carousel = old
- return this
- }
- // CAROUSEL DATA-API
- // =================
- var clickHandler = function (e) {
- var href
- var $this = $(this)
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
- if (!$target.hasClass('carousel')) return
- var options = $.extend({}, $target.data(), $this.data())
- var slideIndex = $this.attr('data-slide-to')
- if (slideIndex) options.interval = false
- Plugin.call($target, options)
- if (slideIndex) {
- $target.data('bs.carousel').to(slideIndex)
- }
- e.preventDefault()
- }
- $(document)
- .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
- .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
- $(window).on('load', function () {
- $('[data-ride="carousel"]').each(function () {
- var $carousel = $(this)
- Plugin.call($carousel, $carousel.data())
- })
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 7 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: collapse.js v3.3.7
- * http://getbootstrap.com/javascript/#collapse
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- /* jshint latedef: false */
- +function ($) {
- 'use strict';
- // COLLAPSE PUBLIC CLASS DEFINITION
- // ================================
- var Collapse = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Collapse.DEFAULTS, options)
- this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
- '[data-toggle="collapse"][data-target="#' + element.id + '"]')
- this.transitioning = null
- if (this.options.parent) {
- this.$parent = this.getParent()
- } else {
- this.addAriaAndCollapsedClass(this.$element, this.$trigger)
- }
- if (this.options.toggle) this.toggle()
- }
- Collapse.VERSION = '3.3.7'
- Collapse.TRANSITION_DURATION = 350
- Collapse.DEFAULTS = {
- toggle: true
- }
- Collapse.prototype.dimension = function () {
- var hasWidth = this.$element.hasClass('width')
- return hasWidth ? 'width' : 'height'
- }
- Collapse.prototype.show = function () {
- if (this.transitioning || this.$element.hasClass('in')) return
- var activesData
- var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
- if (actives && actives.length) {
- activesData = actives.data('bs.collapse')
- if (activesData && activesData.transitioning) return
- }
- var startEvent = $.Event('show.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
- if (actives && actives.length) {
- Plugin.call(actives, 'hide')
- activesData || actives.data('bs.collapse', null)
- }
- var dimension = this.dimension()
- this.$element
- .removeClass('collapse')
- .addClass('collapsing')[dimension](0)
- .attr('aria-expanded', true)
- this.$trigger
- .removeClass('collapsed')
- .attr('aria-expanded', true)
- this.transitioning = 1
- var complete = function () {
- this.$element
- .removeClass('collapsing')
- .addClass('collapse in')[dimension]('')
- this.transitioning = 0
- this.$element
- .trigger('shown.bs.collapse')
- }
- if (!$.support.transition) return complete.call(this)
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
- this.$element
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
- }
- Collapse.prototype.hide = function () {
- if (this.transitioning || !this.$element.hasClass('in')) return
- var startEvent = $.Event('hide.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
- var dimension = this.dimension()
- this.$element[dimension](this.$element[dimension]())[0].offsetHeight
- this.$element
- .addClass('collapsing')
- .removeClass('collapse in')
- .attr('aria-expanded', false)
- this.$trigger
- .addClass('collapsed')
- .attr('aria-expanded', false)
- this.transitioning = 1
- var complete = function () {
- this.transitioning = 0
- this.$element
- .removeClass('collapsing')
- .addClass('collapse')
- .trigger('hidden.bs.collapse')
- }
- if (!$.support.transition) return complete.call(this)
- this.$element
- [dimension](0)
- .one('bsTransitionEnd', $.proxy(complete, this))
- .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
- }
- Collapse.prototype.toggle = function () {
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
- }
- Collapse.prototype.getParent = function () {
- return $(this.options.parent)
- .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
- .each($.proxy(function (i, element) {
- var $element = $(element)
- this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
- }, this))
- .end()
- }
- Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
- var isOpen = $element.hasClass('in')
- $element.attr('aria-expanded', isOpen)
- $trigger
- .toggleClass('collapsed', !isOpen)
- .attr('aria-expanded', isOpen)
- }
- function getTargetFromTrigger($trigger) {
- var href
- var target = $trigger.attr('data-target')
- || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
- return $(target)
- }
- // COLLAPSE PLUGIN DEFINITION
- // ==========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.collapse')
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
- if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.collapse
- $.fn.collapse = Plugin
- $.fn.collapse.Constructor = Collapse
- // COLLAPSE NO CONFLICT
- // ====================
- $.fn.collapse.noConflict = function () {
- $.fn.collapse = old
- return this
- }
- // COLLAPSE DATA-API
- // =================
- $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
- var $this = $(this)
- if (!$this.attr('data-target')) e.preventDefault()
- var $target = getTargetFromTrigger($this)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $this.data()
- Plugin.call($target, option)
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 8 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: dropdown.js v3.3.7
- * http://getbootstrap.com/javascript/#dropdowns
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // DROPDOWN CLASS DEFINITION
- // =========================
- var backdrop = '.dropdown-backdrop'
- var toggle = '[data-toggle="dropdown"]'
- var Dropdown = function (element) {
- $(element).on('click.bs.dropdown', this.toggle)
- }
- Dropdown.VERSION = '3.3.7'
- function getParent($this) {
- var selector = $this.attr('data-target')
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
- var $parent = selector && $(selector)
- return $parent && $parent.length ? $parent : $this.parent()
- }
- function clearMenus(e) {
- if (e && e.which === 3) return
- $(backdrop).remove()
- $(toggle).each(function () {
- var $this = $(this)
- var $parent = getParent($this)
- var relatedTarget = { relatedTarget: this }
- if (!$parent.hasClass('open')) return
- if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
- $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
- if (e.isDefaultPrevented()) return
- $this.attr('aria-expanded', 'false')
- $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
- })
- }
- Dropdown.prototype.toggle = function (e) {
- var $this = $(this)
- if ($this.is('.disabled, :disabled')) return
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
- clearMenus()
- if (!isActive) {
- if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
- // if mobile we use a backdrop because click events don't delegate
- $(document.createElement('div'))
- .addClass('dropdown-backdrop')
- .insertAfter($(this))
- .on('click', clearMenus)
- }
- var relatedTarget = { relatedTarget: this }
- $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
- if (e.isDefaultPrevented()) return
- $this
- .trigger('focus')
- .attr('aria-expanded', 'true')
- $parent
- .toggleClass('open')
- .trigger($.Event('shown.bs.dropdown', relatedTarget))
- }
- return false
- }
- Dropdown.prototype.keydown = function (e) {
- if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
- var $this = $(this)
- e.preventDefault()
- e.stopPropagation()
- if ($this.is('.disabled, :disabled')) return
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
- if (!isActive && e.which != 27 || isActive && e.which == 27) {
- if (e.which == 27) $parent.find(toggle).trigger('focus')
- return $this.trigger('click')
- }
- var desc = ' li:not(.disabled):visible a'
- var $items = $parent.find('.dropdown-menu' + desc)
- if (!$items.length) return
- var index = $items.index(e.target)
- if (e.which == 38 && index > 0) index-- // up
- if (e.which == 40 && index < $items.length - 1) index++ // down
- if (!~index) index = 0
- $items.eq(index).trigger('focus')
- }
- // DROPDOWN PLUGIN DEFINITION
- // ==========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.dropdown')
- if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
- var old = $.fn.dropdown
- $.fn.dropdown = Plugin
- $.fn.dropdown.Constructor = Dropdown
- // DROPDOWN NO CONFLICT
- // ====================
- $.fn.dropdown.noConflict = function () {
- $.fn.dropdown = old
- return this
- }
- // APPLY TO STANDARD DROPDOWN ELEMENTS
- // ===================================
- $(document)
- .on('click.bs.dropdown.data-api', clearMenus)
- .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
- .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
- .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
- .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 9 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: modal.js v3.3.7
- * http://getbootstrap.com/javascript/#modals
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // MODAL CLASS DEFINITION
- // ======================
- var Modal = function (element, options) {
- this.options = options
- this.$body = $(document.body)
- this.$element = $(element)
- this.$dialog = this.$element.find('.modal-dialog')
- this.$backdrop = null
- this.isShown = null
- this.originalBodyPad = null
- this.scrollbarWidth = 0
- this.ignoreBackdropClick = false
- if (this.options.remote) {
- this.$element
- .find('.modal-content')
- .load(this.options.remote, $.proxy(function () {
- this.$element.trigger('loaded.bs.modal')
- }, this))
- }
- }
- Modal.VERSION = '3.3.7'
- Modal.TRANSITION_DURATION = 300
- Modal.BACKDROP_TRANSITION_DURATION = 150
- Modal.DEFAULTS = {
- backdrop: true,
- keyboard: true,
- show: true
- }
- Modal.prototype.toggle = function (_relatedTarget) {
- return this.isShown ? this.hide() : this.show(_relatedTarget)
- }
- Modal.prototype.show = function (_relatedTarget) {
- var that = this
- var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
- this.$element.trigger(e)
- if (this.isShown || e.isDefaultPrevented()) return
- this.isShown = true
- this.checkScrollbar()
- this.setScrollbar()
- this.$body.addClass('modal-open')
- this.escape()
- this.resize()
- this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
- this.$dialog.on('mousedown.dismiss.bs.modal', function () {
- that.$element.one('mouseup.dismiss.bs.modal', function (e) {
- if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
- })
- })
- this.backdrop(function () {
- var transition = $.support.transition && that.$element.hasClass('fade')
- if (!that.$element.parent().length) {
- that.$element.appendTo(that.$body) // don't move modals dom position
- }
- that.$element
- .show()
- .scrollTop(0)
- that.adjustDialog()
- if (transition) {
- that.$element[0].offsetWidth // force reflow
- }
- that.$element.addClass('in')
- that.enforceFocus()
- var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
- transition ?
- that.$dialog // wait for modal to slide in
- .one('bsTransitionEnd', function () {
- that.$element.trigger('focus').trigger(e)
- })
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
- that.$element.trigger('focus').trigger(e)
- })
- }
- Modal.prototype.hide = function (e) {
- if (e) e.preventDefault()
- e = $.Event('hide.bs.modal')
- this.$element.trigger(e)
- if (!this.isShown || e.isDefaultPrevented()) return
- this.isShown = false
- this.escape()
- this.resize()
- $(document).off('focusin.bs.modal')
- this.$element
- .removeClass('in')
- .off('click.dismiss.bs.modal')
- .off('mouseup.dismiss.bs.modal')
- this.$dialog.off('mousedown.dismiss.bs.modal')
- $.support.transition && this.$element.hasClass('fade') ?
- this.$element
- .one('bsTransitionEnd', $.proxy(this.hideModal, this))
- .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
- this.hideModal()
- }
- Modal.prototype.enforceFocus = function () {
- $(document)
- .off('focusin.bs.modal') // guard against infinite focus loop
- .on('focusin.bs.modal', $.proxy(function (e) {
- if (document !== e.target &&
- this.$element[0] !== e.target &&
- !this.$element.has(e.target).length) {
- this.$element.trigger('focus')
- }
- }, this))
- }
- Modal.prototype.escape = function () {
- if (this.isShown && this.options.keyboard) {
- this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
- e.which == 27 && this.hide()
- }, this))
- } else if (!this.isShown) {
- this.$element.off('keydown.dismiss.bs.modal')
- }
- }
- Modal.prototype.resize = function () {
- if (this.isShown) {
- $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
- } else {
- $(window).off('resize.bs.modal')
- }
- }
- Modal.prototype.hideModal = function () {
- var that = this
- this.$element.hide()
- this.backdrop(function () {
- that.$body.removeClass('modal-open')
- that.resetAdjustments()
- that.resetScrollbar()
- that.$element.trigger('hidden.bs.modal')
- })
- }
- Modal.prototype.removeBackdrop = function () {
- this.$backdrop && this.$backdrop.remove()
- this.$backdrop = null
- }
- Modal.prototype.backdrop = function (callback) {
- var that = this
- var animate = this.$element.hasClass('fade') ? 'fade' : ''
- if (this.isShown && this.options.backdrop) {
- var doAnimate = $.support.transition && animate
- this.$backdrop = $(document.createElement('div'))
- .addClass('modal-backdrop ' + animate)
- .appendTo(this.$body)
- this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
- if (this.ignoreBackdropClick) {
- this.ignoreBackdropClick = false
- return
- }
- if (e.target !== e.currentTarget) return
- this.options.backdrop == 'static'
- ? this.$element[0].focus()
- : this.hide()
- }, this))
- if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
- this.$backdrop.addClass('in')
- if (!callback) return
- doAnimate ?
- this.$backdrop
- .one('bsTransitionEnd', callback)
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
- callback()
- } else if (!this.isShown && this.$backdrop) {
- this.$backdrop.removeClass('in')
- var callbackRemove = function () {
- that.removeBackdrop()
- callback && callback()
- }
- $.support.transition && this.$element.hasClass('fade') ?
- this.$backdrop
- .one('bsTransitionEnd', callbackRemove)
- .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
- callbackRemove()
- } else if (callback) {
- callback()
- }
- }
- // these following methods are used to handle overflowing modals
- Modal.prototype.handleUpdate = function () {
- this.adjustDialog()
- }
- Modal.prototype.adjustDialog = function () {
- var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
- this.$element.css({
- paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
- paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
- })
- }
- Modal.prototype.resetAdjustments = function () {
- this.$element.css({
- paddingLeft: '',
- paddingRight: ''
- })
- }
- Modal.prototype.checkScrollbar = function () {
- var fullWindowWidth = window.innerWidth
- if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
- var documentElementRect = document.documentElement.getBoundingClientRect()
- fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
- }
- this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
- this.scrollbarWidth = this.measureScrollbar()
- }
- Modal.prototype.setScrollbar = function () {
- var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
- this.originalBodyPad = document.body.style.paddingRight || ''
- if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
- }
- Modal.prototype.resetScrollbar = function () {
- this.$body.css('padding-right', this.originalBodyPad)
- }
- Modal.prototype.measureScrollbar = function () { // thx walsh
- var scrollDiv = document.createElement('div')
- scrollDiv.className = 'modal-scrollbar-measure'
- this.$body.append(scrollDiv)
- var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
- this.$body[0].removeChild(scrollDiv)
- return scrollbarWidth
- }
- // MODAL PLUGIN DEFINITION
- // =======================
- function Plugin(option, _relatedTarget) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.modal')
- var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
- if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
- if (typeof option == 'string') data[option](_relatedTarget)
- else if (options.show) data.show(_relatedTarget)
- })
- }
- var old = $.fn.modal
- $.fn.modal = Plugin
- $.fn.modal.Constructor = Modal
- // MODAL NO CONFLICT
- // =================
- $.fn.modal.noConflict = function () {
- $.fn.modal = old
- return this
- }
- // MODAL DATA-API
- // ==============
- $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
- var $this = $(this)
- var href = $this.attr('href')
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
- var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
- if ($this.is('a')) e.preventDefault()
- $target.one('show.bs.modal', function (showEvent) {
- if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
- $target.one('hidden.bs.modal', function () {
- $this.is(':visible') && $this.trigger('focus')
- })
- })
- Plugin.call($target, option, this)
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 10 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: tooltip.js v3.3.7
- * http://getbootstrap.com/javascript/#tooltip
- * Inspired by the original jQuery.tipsy by Jason Frame
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // TOOLTIP PUBLIC CLASS DEFINITION
- // ===============================
- var Tooltip = function (element, options) {
- this.type = null
- this.options = null
- this.enabled = null
- this.timeout = null
- this.hoverState = null
- this.$element = null
- this.inState = null
- this.init('tooltip', element, options)
- }
- Tooltip.VERSION = '3.3.7'
- Tooltip.TRANSITION_DURATION = 150
- Tooltip.DEFAULTS = {
- animation: true,
- placement: 'top',
- selector: false,
- template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
- trigger: 'hover focus',
- title: '',
- delay: 0,
- html: false,
- container: false,
- viewport: {
- selector: 'body',
- padding: 0
- }
- }
- Tooltip.prototype.init = function (type, element, options) {
- this.enabled = true
- this.type = type
- this.$element = $(element)
- this.options = this.getOptions(options)
- this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
- this.inState = { click: false, hover: false, focus: false }
- if (this.$element[0] instanceof document.constructor && !this.options.selector) {
- throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
- }
- var triggers = this.options.trigger.split(' ')
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i]
- if (trigger == 'click') {
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
- } else if (trigger != 'manual') {
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
- }
- }
- this.options.selector ?
- (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
- this.fixTitle()
- }
- Tooltip.prototype.getDefaults = function () {
- return Tooltip.DEFAULTS
- }
- Tooltip.prototype.getOptions = function (options) {
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
- if (options.delay && typeof options.delay == 'number') {
- options.delay = {
- show: options.delay,
- hide: options.delay
- }
- }
- return options
- }
- Tooltip.prototype.getDelegateOptions = function () {
- var options = {}
- var defaults = this.getDefaults()
- this._options && $.each(this._options, function (key, value) {
- if (defaults[key] != value) options[key] = value
- })
- return options
- }
- Tooltip.prototype.enter = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget).data('bs.' + this.type)
- if (!self) {
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
- $(obj.currentTarget).data('bs.' + this.type, self)
- }
- if (obj instanceof $.Event) {
- self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
- }
- if (self.tip().hasClass('in') || self.hoverState == 'in') {
- self.hoverState = 'in'
- return
- }
- clearTimeout(self.timeout)
- self.hoverState = 'in'
- if (!self.options.delay || !self.options.delay.show) return self.show()
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'in') self.show()
- }, self.options.delay.show)
- }
- Tooltip.prototype.isInStateTrue = function () {
- for (var key in this.inState) {
- if (this.inState[key]) return true
- }
- return false
- }
- Tooltip.prototype.leave = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget).data('bs.' + this.type)
- if (!self) {
- self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
- $(obj.currentTarget).data('bs.' + this.type, self)
- }
- if (obj instanceof $.Event) {
- self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
- }
- if (self.isInStateTrue()) return
- clearTimeout(self.timeout)
- self.hoverState = 'out'
- if (!self.options.delay || !self.options.delay.hide) return self.hide()
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'out') self.hide()
- }, self.options.delay.hide)
- }
- Tooltip.prototype.show = function () {
- var e = $.Event('show.bs.' + this.type)
- if (this.hasContent() && this.enabled) {
- this.$element.trigger(e)
- var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
- if (e.isDefaultPrevented() || !inDom) return
- var that = this
- var $tip = this.tip()
- var tipId = this.getUID(this.type)
- this.setContent()
- $tip.attr('id', tipId)
- this.$element.attr('aria-describedby', tipId)
- if (this.options.animation) $tip.addClass('fade')
- var placement = typeof this.options.placement == 'function' ?
- this.options.placement.call(this, $tip[0], this.$element[0]) :
- this.options.placement
- var autoToken = /\s?auto?\s?/i
- var autoPlace = autoToken.test(placement)
- if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
- $tip
- .detach()
- .css({ top: 0, left: 0, display: 'block' })
- .addClass(placement)
- .data('bs.' + this.type, this)
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
- this.$element.trigger('inserted.bs.' + this.type)
- var pos = this.getPosition()
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
- if (autoPlace) {
- var orgPlacement = placement
- var viewportDim = this.getPosition(this.$viewport)
- placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
- placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
- placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
- placement
- $tip
- .removeClass(orgPlacement)
- .addClass(placement)
- }
- var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
- this.applyPlacement(calculatedOffset, placement)
- var complete = function () {
- var prevHoverState = that.hoverState
- that.$element.trigger('shown.bs.' + that.type)
- that.hoverState = null
- if (prevHoverState == 'out') that.leave(that)
- }
- $.support.transition && this.$tip.hasClass('fade') ?
- $tip
- .one('bsTransitionEnd', complete)
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
- complete()
- }
- }
- Tooltip.prototype.applyPlacement = function (offset, placement) {
- var $tip = this.tip()
- var width = $tip[0].offsetWidth
- var height = $tip[0].offsetHeight
- // manually read margins because getBoundingClientRect includes difference
- var marginTop = parseInt($tip.css('margin-top'), 10)
- var marginLeft = parseInt($tip.css('margin-left'), 10)
- // we must check for NaN for ie 8/9
- if (isNaN(marginTop)) marginTop = 0
- if (isNaN(marginLeft)) marginLeft = 0
- offset.top += marginTop
- offset.left += marginLeft
- // $.fn.offset doesn't round pixel values
- // so we use setOffset directly with our own function B-0
- $.offset.setOffset($tip[0], $.extend({
- using: function (props) {
- $tip.css({
- top: Math.round(props.top),
- left: Math.round(props.left)
- })
- }
- }, offset), 0)
- $tip.addClass('in')
- // check to see if placing tip in new offset caused the tip to resize itself
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
- if (placement == 'top' && actualHeight != height) {
- offset.top = offset.top + height - actualHeight
- }
- var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
- if (delta.left) offset.left += delta.left
- else offset.top += delta.top
- var isVertical = /top|bottom/.test(placement)
- var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
- var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
- $tip.offset(offset)
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
- }
- Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
- this.arrow()
- .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
- .css(isVertical ? 'top' : 'left', '')
- }
- Tooltip.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
- $tip.removeClass('fade in top bottom left right')
- }
- Tooltip.prototype.hide = function (callback) {
- var that = this
- var $tip = $(this.$tip)
- var e = $.Event('hide.bs.' + this.type)
- function complete() {
- if (that.hoverState != 'in') $tip.detach()
- if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
- that.$element
- .removeAttr('aria-describedby')
- .trigger('hidden.bs.' + that.type)
- }
- callback && callback()
- }
- this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
- $tip.removeClass('in')
- $.support.transition && $tip.hasClass('fade') ?
- $tip
- .one('bsTransitionEnd', complete)
- .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
- complete()
- this.hoverState = null
- return this
- }
- Tooltip.prototype.fixTitle = function () {
- var $e = this.$element
- if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
- $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
- }
- }
- Tooltip.prototype.hasContent = function () {
- return this.getTitle()
- }
- Tooltip.prototype.getPosition = function ($element) {
- $element = $element || this.$element
- var el = $element[0]
- var isBody = el.tagName == 'BODY'
- var elRect = el.getBoundingClientRect()
- if (elRect.width == null) {
- // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
- elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
- }
- var isSvg = window.SVGElement && el instanceof window.SVGElement
- // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
- // See https://github.com/twbs/bootstrap/issues/20280
- var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
- var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
- var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
- return $.extend({}, elRect, scroll, outerDims, elOffset)
- }
- Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
- }
- Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
- var delta = { top: 0, left: 0 }
- if (!this.$viewport) return delta
- var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
- var viewportDimensions = this.getPosition(this.$viewport)
- if (/right|left/.test(placement)) {
- var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
- var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
- if (topEdgeOffset < viewportDimensions.top) { // top overflow
- delta.top = viewportDimensions.top - topEdgeOffset
- } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
- delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
- }
- } else {
- var leftEdgeOffset = pos.left - viewportPadding
- var rightEdgeOffset = pos.left + viewportPadding + actualWidth
- if (leftEdgeOffset < viewportDimensions.left) { // left overflow
- delta.left = viewportDimensions.left - leftEdgeOffset
- } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
- delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
- }
- }
- return delta
- }
- Tooltip.prototype.getTitle = function () {
- var title
- var $e = this.$element
- var o = this.options
- title = $e.attr('data-original-title')
- || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
- return title
- }
- Tooltip.prototype.getUID = function (prefix) {
- do prefix += ~~(Math.random() * 1000000)
- while (document.getElementById(prefix))
- return prefix
- }
- Tooltip.prototype.tip = function () {
- if (!this.$tip) {
- this.$tip = $(this.options.template)
- if (this.$tip.length != 1) {
- throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
- }
- }
- return this.$tip
- }
- Tooltip.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
- }
- Tooltip.prototype.enable = function () {
- this.enabled = true
- }
- Tooltip.prototype.disable = function () {
- this.enabled = false
- }
- Tooltip.prototype.toggleEnabled = function () {
- this.enabled = !this.enabled
- }
- Tooltip.prototype.toggle = function (e) {
- var self = this
- if (e) {
- self = $(e.currentTarget).data('bs.' + this.type)
- if (!self) {
- self = new this.constructor(e.currentTarget, this.getDelegateOptions())
- $(e.currentTarget).data('bs.' + this.type, self)
- }
- }
- if (e) {
- self.inState.click = !self.inState.click
- if (self.isInStateTrue()) self.enter(self)
- else self.leave(self)
- } else {
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
- }
- }
- Tooltip.prototype.destroy = function () {
- var that = this
- clearTimeout(this.timeout)
- this.hide(function () {
- that.$element.off('.' + that.type).removeData('bs.' + that.type)
- if (that.$tip) {
- that.$tip.detach()
- }
- that.$tip = null
- that.$arrow = null
- that.$viewport = null
- that.$element = null
- })
- }
- // TOOLTIP PLUGIN DEFINITION
- // =========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tooltip')
- var options = typeof option == 'object' && option
- if (!data && /destroy|hide/.test(option)) return
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.tooltip
- $.fn.tooltip = Plugin
- $.fn.tooltip.Constructor = Tooltip
- // TOOLTIP NO CONFLICT
- // ===================
- $.fn.tooltip.noConflict = function () {
- $.fn.tooltip = old
- return this
- }
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 11 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: popover.js v3.3.7
- * http://getbootstrap.com/javascript/#popovers
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // POPOVER PUBLIC CLASS DEFINITION
- // ===============================
- var Popover = function (element, options) {
- this.init('popover', element, options)
- }
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
- Popover.VERSION = '3.3.7'
- Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
- placement: 'right',
- trigger: 'click',
- content: '',
- template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
- })
- // NOTE: POPOVER EXTENDS tooltip.js
- // ================================
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
- Popover.prototype.constructor = Popover
- Popover.prototype.getDefaults = function () {
- return Popover.DEFAULTS
- }
- Popover.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
- var content = this.getContent()
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
- this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
- ](content)
- $tip.removeClass('fade top bottom left right in')
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
- // this manually by checking the contents.
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
- }
- Popover.prototype.hasContent = function () {
- return this.getTitle() || this.getContent()
- }
- Popover.prototype.getContent = function () {
- var $e = this.$element
- var o = this.options
- return $e.attr('data-content')
- || (typeof o.content == 'function' ?
- o.content.call($e[0]) :
- o.content)
- }
- Popover.prototype.arrow = function () {
- return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
- }
- // POPOVER PLUGIN DEFINITION
- // =========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
- if (!data && /destroy|hide/.test(option)) return
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.popover
- $.fn.popover = Plugin
- $.fn.popover.Constructor = Popover
- // POPOVER NO CONFLICT
- // ===================
- $.fn.popover.noConflict = function () {
- $.fn.popover = old
- return this
- }
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 12 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: scrollspy.js v3.3.7
- * http://getbootstrap.com/javascript/#scrollspy
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // SCROLLSPY CLASS DEFINITION
- // ==========================
- function ScrollSpy(element, options) {
- this.$body = $(document.body)
- this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
- this.selector = (this.options.target || '') + ' .nav li > a'
- this.offsets = []
- this.targets = []
- this.activeTarget = null
- this.scrollHeight = 0
- this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
- this.refresh()
- this.process()
- }
- ScrollSpy.VERSION = '3.3.7'
- ScrollSpy.DEFAULTS = {
- offset: 10
- }
- ScrollSpy.prototype.getScrollHeight = function () {
- return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
- }
- ScrollSpy.prototype.refresh = function () {
- var that = this
- var offsetMethod = 'offset'
- var offsetBase = 0
- this.offsets = []
- this.targets = []
- this.scrollHeight = this.getScrollHeight()
- if (!$.isWindow(this.$scrollElement[0])) {
- offsetMethod = 'position'
- offsetBase = this.$scrollElement.scrollTop()
- }
- this.$body
- .find(this.selector)
- .map(function () {
- var $el = $(this)
- var href = $el.data('target') || $el.attr('href')
- var $href = /^#./.test(href) && $(href)
- return ($href
- && $href.length
- && $href.is(':visible')
- && [[$href[offsetMethod]().top + offsetBase, href]]) || null
- })
- .sort(function (a, b) { return a[0] - b[0] })
- .each(function () {
- that.offsets.push(this[0])
- that.targets.push(this[1])
- })
- }
- ScrollSpy.prototype.process = function () {
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
- var scrollHeight = this.getScrollHeight()
- var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
- var offsets = this.offsets
- var targets = this.targets
- var activeTarget = this.activeTarget
- var i
- if (this.scrollHeight != scrollHeight) {
- this.refresh()
- }
- if (scrollTop >= maxScroll) {
- return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
- }
- if (activeTarget && scrollTop < offsets[0]) {
- this.activeTarget = null
- return this.clear()
- }
- for (i = offsets.length; i--;) {
- activeTarget != targets[i]
- && scrollTop >= offsets[i]
- && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
- && this.activate(targets[i])
- }
- }
- ScrollSpy.prototype.activate = function (target) {
- this.activeTarget = target
- this.clear()
- var selector = this.selector +
- '[data-target="' + target + '"],' +
- this.selector + '[href="' + target + '"]'
- var active = $(selector)
- .parents('li')
- .addClass('active')
- if (active.parent('.dropdown-menu').length) {
- active = active
- .closest('li.dropdown')
- .addClass('active')
- }
- active.trigger('activate.bs.scrollspy')
- }
- ScrollSpy.prototype.clear = function () {
- $(this.selector)
- .parentsUntil(this.options.target, '.active')
- .removeClass('active')
- }
- // SCROLLSPY PLUGIN DEFINITION
- // ===========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.scrollspy')
- var options = typeof option == 'object' && option
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.scrollspy
- $.fn.scrollspy = Plugin
- $.fn.scrollspy.Constructor = ScrollSpy
- // SCROLLSPY NO CONFLICT
- // =====================
- $.fn.scrollspy.noConflict = function () {
- $.fn.scrollspy = old
- return this
- }
- // SCROLLSPY DATA-API
- // ==================
- $(window).on('load.bs.scrollspy.data-api', function () {
- $('[data-spy="scroll"]').each(function () {
- var $spy = $(this)
- Plugin.call($spy, $spy.data())
- })
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 13 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: tab.js v3.3.7
- * http://getbootstrap.com/javascript/#tabs
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // TAB CLASS DEFINITION
- // ====================
- var Tab = function (element) {
- // jscs:disable requireDollarBeforejQueryAssignment
- this.element = $(element)
- // jscs:enable requireDollarBeforejQueryAssignment
- }
- Tab.VERSION = '3.3.7'
- Tab.TRANSITION_DURATION = 150
- Tab.prototype.show = function () {
- var $this = this.element
- var $ul = $this.closest('ul:not(.dropdown-menu)')
- var selector = $this.data('target')
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
- if ($this.parent('li').hasClass('active')) return
- var $previous = $ul.find('.active:last a')
- var hideEvent = $.Event('hide.bs.tab', {
- relatedTarget: $this[0]
- })
- var showEvent = $.Event('show.bs.tab', {
- relatedTarget: $previous[0]
- })
- $previous.trigger(hideEvent)
- $this.trigger(showEvent)
- if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
- var $target = $(selector)
- this.activate($this.closest('li'), $ul)
- this.activate($target, $target.parent(), function () {
- $previous.trigger({
- type: 'hidden.bs.tab',
- relatedTarget: $this[0]
- })
- $this.trigger({
- type: 'shown.bs.tab',
- relatedTarget: $previous[0]
- })
- })
- }
- Tab.prototype.activate = function (element, container, callback) {
- var $active = container.find('> .active')
- var transition = callback
- && $.support.transition
- && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
- function next() {
- $active
- .removeClass('active')
- .find('> .dropdown-menu > .active')
- .removeClass('active')
- .end()
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', false)
- element
- .addClass('active')
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', true)
- if (transition) {
- element[0].offsetWidth // reflow for transition
- element.addClass('in')
- } else {
- element.removeClass('fade')
- }
- if (element.parent('.dropdown-menu').length) {
- element
- .closest('li.dropdown')
- .addClass('active')
- .end()
- .find('[data-toggle="tab"]')
- .attr('aria-expanded', true)
- }
- callback && callback()
- }
- $active.length && transition ?
- $active
- .one('bsTransitionEnd', next)
- .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
- next()
- $active.removeClass('in')
- }
- // TAB PLUGIN DEFINITION
- // =====================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tab')
- if (!data) $this.data('bs.tab', (data = new Tab(this)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.tab
- $.fn.tab = Plugin
- $.fn.tab.Constructor = Tab
- // TAB NO CONFLICT
- // ===============
- $.fn.tab.noConflict = function () {
- $.fn.tab = old
- return this
- }
- // TAB DATA-API
- // ============
- var clickHandler = function (e) {
- e.preventDefault()
- Plugin.call($(this), 'show')
- }
- $(document)
- .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
- .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 14 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap: affix.js v3.3.7
- * http://getbootstrap.com/javascript/#affix
- * ========================================================================
- * Copyright 2011-2016 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // AFFIX CLASS DEFINITION
- // ======================
- var Affix = function (element, options) {
- this.options = $.extend({}, Affix.DEFAULTS, options)
- this.$target = $(this.options.target)
- .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
- .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
- this.$element = $(element)
- this.affixed = null
- this.unpin = null
- this.pinnedOffset = null
- this.checkPosition()
- }
- Affix.VERSION = '3.3.7'
- Affix.RESET = 'affix affix-top affix-bottom'
- Affix.DEFAULTS = {
- offset: 0,
- target: window
- }
- Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
- var targetHeight = this.$target.height()
- if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
- if (this.affixed == 'bottom') {
- if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
- return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
- }
- var initializing = this.affixed == null
- var colliderTop = initializing ? scrollTop : position.top
- var colliderHeight = initializing ? targetHeight : height
- if (offsetTop != null && scrollTop <= offsetTop) return 'top'
- if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
- return false
- }
- Affix.prototype.getPinnedOffset = function () {
- if (this.pinnedOffset) return this.pinnedOffset
- this.$element.removeClass(Affix.RESET).addClass('affix')
- var scrollTop = this.$target.scrollTop()
- var position = this.$element.offset()
- return (this.pinnedOffset = position.top - scrollTop)
- }
- Affix.prototype.checkPositionWithEventLoop = function () {
- setTimeout($.proxy(this.checkPosition, this), 1)
- }
- Affix.prototype.checkPosition = function () {
- if (!this.$element.is(':visible')) return
- var height = this.$element.height()
- var offset = this.options.offset
- var offsetTop = offset.top
- var offsetBottom = offset.bottom
- var scrollHeight = Math.max($(document).height(), $(document.body).height())
- if (typeof offset != 'object') offsetBottom = offsetTop = offset
- if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
- var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
- if (this.affixed != affix) {
- if (this.unpin != null) this.$element.css('top', '')
- var affixType = 'affix' + (affix ? '-' + affix : '')
- var e = $.Event(affixType + '.bs.affix')
- this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
- this.affixed = affix
- this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
- this.$element
- .removeClass(Affix.RESET)
- .addClass(affixType)
- .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
- }
- if (affix == 'bottom') {
- this.$element.offset({
- top: scrollHeight - height - offsetBottom
- })
- }
- }
- // AFFIX PLUGIN DEFINITION
- // =======================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.affix')
- var options = typeof option == 'object' && option
- if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.affix
- $.fn.affix = Plugin
- $.fn.affix.Constructor = Affix
- // AFFIX NO CONFLICT
- // =================
- $.fn.affix.noConflict = function () {
- $.fn.affix = old
- return this
- }
- // AFFIX DATA-API
- // ==============
- $(window).on('load', function () {
- $('[data-spy="affix"]').each(function () {
- var $spy = $(this)
- var data = $spy.data()
- data.offset = data.offset || {}
- if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
- if (data.offsetTop != null) data.offset.top = data.offsetTop
- Plugin.call($spy, data)
- })
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 15 */
- /***/ (function(module, exports, __webpack_require__) {
- var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
- * Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
- *
- * Copyright 2013-2017 bootstrap-select
- * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
- */
- (function (root, factory) {
- if (true) {
- // AMD. Register as an anonymous module unless amdModuleId is set
- !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = function (a0) {
- return (factory(a0));
- }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
- __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
- } else if (typeof module === 'object' && module.exports) {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory(require("jquery"));
- } else {
- factory(root["jQuery"]);
- }
- }(this, function (jQuery) {
- (function ($) {
- 'use strict';
- //<editor-fold desc="Shims">
- if (!String.prototype.includes) {
- (function () {
- 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
- var toString = {}.toString;
- var defineProperty = (function () {
- // IE 8 only supports `Object.defineProperty` on DOM elements
- try {
- var object = {};
- var $defineProperty = Object.defineProperty;
- var result = $defineProperty(object, object, object) && $defineProperty;
- } catch (error) {
- }
- return result;
- }());
- var indexOf = ''.indexOf;
- var includes = function (search) {
- if (this == null) {
- throw new TypeError();
- }
- var string = String(this);
- if (search && toString.call(search) == '[object RegExp]') {
- throw new TypeError();
- }
- var stringLength = string.length;
- var searchString = String(search);
- var searchLength = searchString.length;
- var position = arguments.length > 1 ? arguments[1] : undefined;
- // `ToInteger`
- var pos = position ? Number(position) : 0;
- if (pos != pos) { // better `isNaN`
- pos = 0;
- }
- var start = Math.min(Math.max(pos, 0), stringLength);
- // Avoid the `indexOf` call if no match is possible
- if (searchLength + start > stringLength) {
- return false;
- }
- return indexOf.call(string, searchString, pos) != -1;
- };
- if (defineProperty) {
- defineProperty(String.prototype, 'includes', {
- 'value': includes,
- 'configurable': true,
- 'writable': true
- });
- } else {
- String.prototype.includes = includes;
- }
- }());
- }
- if (!String.prototype.startsWith) {
- (function () {
- 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
- var defineProperty = (function () {
- // IE 8 only supports `Object.defineProperty` on DOM elements
- try {
- var object = {};
- var $defineProperty = Object.defineProperty;
- var result = $defineProperty(object, object, object) && $defineProperty;
- } catch (error) {
- }
- return result;
- }());
- var toString = {}.toString;
- var startsWith = function (search) {
- if (this == null) {
- throw new TypeError();
- }
- var string = String(this);
- if (search && toString.call(search) == '[object RegExp]') {
- throw new TypeError();
- }
- var stringLength = string.length;
- var searchString = String(search);
- var searchLength = searchString.length;
- var position = arguments.length > 1 ? arguments[1] : undefined;
- // `ToInteger`
- var pos = position ? Number(position) : 0;
- if (pos != pos) { // better `isNaN`
- pos = 0;
- }
- var start = Math.min(Math.max(pos, 0), stringLength);
- // Avoid the `indexOf` call if no match is possible
- if (searchLength + start > stringLength) {
- return false;
- }
- var index = -1;
- while (++index < searchLength) {
- if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
- return false;
- }
- }
- return true;
- };
- if (defineProperty) {
- defineProperty(String.prototype, 'startsWith', {
- 'value': startsWith,
- 'configurable': true,
- 'writable': true
- });
- } else {
- String.prototype.startsWith = startsWith;
- }
- }());
- }
- if (!Object.keys) {
- Object.keys = function (
- o, // object
- k, // key
- r // result array
- ){
- // initialize object and result
- r=[];
- // iterate over object keys
- for (k in o)
- // fill result array with non-prototypical keys
- r.hasOwnProperty.call(o, k) && r.push(k);
- // return result
- return r;
- };
- }
- // set data-selected on select element if the value has been programmatically selected
- // prior to initialization of bootstrap-select
- // * consider removing or replacing an alternative method *
- var valHooks = {
- useDefault: false,
- _set: $.valHooks.select.set
- };
- $.valHooks.select.set = function(elem, value) {
- if (value && !valHooks.useDefault) $(elem).data('selected', true);
- return valHooks._set.apply(this, arguments);
- };
- var changed_arguments = null;
- var EventIsSupported = (function() {
- try {
- new Event('change');
- return true;
- } catch (e) {
- return false;
- }
- })();
- $.fn.triggerNative = function (eventName) {
- var el = this[0],
- event;
- if (el.dispatchEvent) { // for modern browsers & IE9+
- if (EventIsSupported) {
- // For modern browsers
- event = new Event(eventName, {
- bubbles: true
- });
- } else {
- // For IE since it doesn't support Event constructor
- event = document.createEvent('Event');
- event.initEvent(eventName, true, false);
- }
- el.dispatchEvent(event);
- } else if (el.fireEvent) { // for IE8
- event = document.createEventObject();
- event.eventType = eventName;
- el.fireEvent('on' + eventName, event);
- } else {
- // fall back to jQuery.trigger
- this.trigger(eventName);
- }
- };
- //</editor-fold>
- // Case insensitive contains search
- $.expr.pseudos.icontains = function (obj, index, meta) {
- var $obj = $(obj).find('a');
- var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
- return haystack.includes(meta[3].toUpperCase());
- };
- // Case insensitive begins search
- $.expr.pseudos.ibegins = function (obj, index, meta) {
- var $obj = $(obj).find('a');
- var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
- return haystack.startsWith(meta[3].toUpperCase());
- };
- // Case and accent insensitive contains search
- $.expr.pseudos.aicontains = function (obj, index, meta) {
- var $obj = $(obj).find('a');
- var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
- return haystack.includes(meta[3].toUpperCase());
- };
- // Case and accent insensitive begins search
- $.expr.pseudos.aibegins = function (obj, index, meta) {
- var $obj = $(obj).find('a');
- var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
- return haystack.startsWith(meta[3].toUpperCase());
- };
- /**
- * Remove all diatrics from the given text.
- * @access private
- * @param {String} text
- * @returns {String}
- */
- function normalizeToBase(text) {
- var rExps = [
- {re: /[\xC0-\xC6]/g, ch: "A"},
- {re: /[\xE0-\xE6]/g, ch: "a"},
- {re: /[\xC8-\xCB]/g, ch: "E"},
- {re: /[\xE8-\xEB]/g, ch: "e"},
- {re: /[\xCC-\xCF]/g, ch: "I"},
- {re: /[\xEC-\xEF]/g, ch: "i"},
- {re: /[\xD2-\xD6]/g, ch: "O"},
- {re: /[\xF2-\xF6]/g, ch: "o"},
- {re: /[\xD9-\xDC]/g, ch: "U"},
- {re: /[\xF9-\xFC]/g, ch: "u"},
- {re: /[\xC7-\xE7]/g, ch: "c"},
- {re: /[\xD1]/g, ch: "N"},
- {re: /[\xF1]/g, ch: "n"}
- ];
- $.each(rExps, function () {
- text = text ? text.replace(this.re, this.ch) : '';
- });
- return text;
- }
- // List of HTML entities for escaping.
- var escapeMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '`': '`'
- };
-
- var unescapeMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- ''': "'",
- '`': '`'
- };
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- var createEscaper = function(map) {
- var escaper = function(match) {
- return map[match];
- };
- // Regexes for identifying a key that needs to be escaped.
- var source = '(?:' + Object.keys(map).join('|') + ')';
- var testRegexp = RegExp(source);
- var replaceRegexp = RegExp(source, 'g');
- return function(string) {
- string = string == null ? '' : '' + string;
- return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
- };
- };
- var htmlEscape = createEscaper(escapeMap);
- var htmlUnescape = createEscaper(unescapeMap);
- var Selectpicker = function (element, options) {
- // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
- if (!valHooks.useDefault) {
- $.valHooks.select.set = valHooks._set;
- valHooks.useDefault = true;
- }
- this.$element = $(element);
- this.$newElement = null;
- this.$button = null;
- this.$menu = null;
- this.$lis = null;
- this.options = options;
- // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
- // data-attribute)
- if (this.options.title === null) {
- this.options.title = this.$element.attr('title');
- }
- // Format window padding
- var winPad = this.options.windowPadding;
- if (typeof winPad === 'number') {
- this.options.windowPadding = [winPad, winPad, winPad, winPad];
- }
- //Expose public methods
- this.val = Selectpicker.prototype.val;
- this.render = Selectpicker.prototype.render;
- this.refresh = Selectpicker.prototype.refresh;
- this.setStyle = Selectpicker.prototype.setStyle;
- this.selectAll = Selectpicker.prototype.selectAll;
- this.deselectAll = Selectpicker.prototype.deselectAll;
- this.destroy = Selectpicker.prototype.destroy;
- this.remove = Selectpicker.prototype.remove;
- this.show = Selectpicker.prototype.show;
- this.hide = Selectpicker.prototype.hide;
- this.init();
- };
- Selectpicker.VERSION = '1.12.4';
- // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
- Selectpicker.DEFAULTS = {
- noneSelectedText: 'Nothing selected',
- noneResultsText: 'No results matched {0}',
- countSelectedText: function (numSelected, numTotal) {
- return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
- },
- maxOptionsText: function (numAll, numGroup) {
- return [
- (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
- (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
- ];
- },
- selectAllText: 'Select All',
- deselectAllText: 'Deselect All',
- doneButton: false,
- doneButtonText: 'Close',
- multipleSeparator: ', ',
- styleBase: 'btn',
- style: 'btn-default',
- size: 'auto',
- title: null,
- selectedTextFormat: 'values',
- width: false,
- container: false,
- hideDisabled: false,
- showSubtext: false,
- showIcon: true,
- showContent: true,
- dropupAuto: true,
- header: false,
- liveSearch: false,
- liveSearchPlaceholder: null,
- liveSearchNormalize: false,
- liveSearchStyle: 'contains',
- actionsBox: false,
- iconBase: 'glyphicon',
- tickIcon: 'glyphicon-ok',
- showTick: false,
- template: {
- caret: '<span class="caret"></span>'
- },
- maxOptions: false,
- mobile: false,
- selectOnTab: false,
- dropdownAlignRight: false,
- windowPadding: 0
- };
- Selectpicker.prototype = {
- constructor: Selectpicker,
- init: function () {
- var that = this,
- id = this.$element.attr('id');
- this.$element.addClass('bs-select-hidden');
- // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
- // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
- this.liObj = {};
- this.multiple = this.$element.prop('multiple');
- this.autofocus = this.$element.prop('autofocus');
- this.$newElement = this.createView();
- this.$element
- .after(this.$newElement)
- .appendTo(this.$newElement);
- this.$button = this.$newElement.children('button');
- this.$menu = this.$newElement.children('.dropdown-menu');
- this.$menuInner = this.$menu.children('.inner');
- this.$searchbox = this.$menu.find('input');
- this.$element.removeClass('bs-select-hidden');
- if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
- if (typeof id !== 'undefined') {
- this.$button.attr('data-id', id);
- $('label[for="' + id + '"]').click(function (e) {
- e.preventDefault();
- that.$button.focus();
- });
- }
- this.checkDisabled();
- this.clickListener();
- if (this.options.liveSearch) this.liveSearchListener();
- this.render();
- this.setStyle();
- this.setWidth();
- if (this.options.container) this.selectPosition();
- this.$menu.data('this', this);
- this.$newElement.data('this', this);
- if (this.options.mobile) this.mobile();
- this.$newElement.on({
- 'hide.bs.dropdown': function (e) {
- that.$menuInner.attr('aria-expanded', false);
- that.$element.trigger('hide.bs.select', e);
- },
- 'hidden.bs.dropdown': function (e) {
- that.$element.trigger('hidden.bs.select', e);
- },
- 'show.bs.dropdown': function (e) {
- that.$menuInner.attr('aria-expanded', true);
- that.$element.trigger('show.bs.select', e);
- },
- 'shown.bs.dropdown': function (e) {
- that.$element.trigger('shown.bs.select', e);
- }
- });
- if (that.$element[0].hasAttribute('required')) {
- this.$element.on('invalid', function () {
- that.$button.addClass('bs-invalid');
- that.$element.on({
- 'focus.bs.select': function () {
- that.$button.focus();
- that.$element.off('focus.bs.select');
- },
- 'shown.bs.select': function () {
- that.$element
- .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
- .off('shown.bs.select');
- },
- 'rendered.bs.select': function () {
- // if select is no longer invalid, remove the bs-invalid class
- if (this.validity.valid) that.$button.removeClass('bs-invalid');
- that.$element.off('rendered.bs.select');
- }
- });
- that.$button.on('blur.bs.select', function() {
- that.$element.focus().blur();
- that.$button.off('blur.bs.select');
- });
- });
- }
- setTimeout(function () {
- that.$element.trigger('loaded.bs.select');
- });
- },
- createDropdown: function () {
- // Options
- // If we are multiple or showTick option is set, then add the show-tick class
- var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
- inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
- autofocus = this.autofocus ? ' autofocus' : '';
- // Elements
- var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">×</button>' + this.options.header + '</div>' : '';
- var searchbox = this.options.liveSearch ?
- '<div class="bs-searchbox">' +
- '<input type="text" class="form-control" autocomplete="off"' +
- (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
- '</div>'
- : '';
- var actionsbox = this.multiple && this.options.actionsBox ?
- '<div class="bs-actionsbox">' +
- '<div class="btn-group btn-group-sm btn-block">' +
- '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
- this.options.selectAllText +
- '</button>' +
- '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
- this.options.deselectAllText +
- '</button>' +
- '</div>' +
- '</div>'
- : '';
- var donebutton = this.multiple && this.options.doneButton ?
- '<div class="bs-donebutton">' +
- '<div class="btn-group btn-block">' +
- '<button type="button" class="btn btn-sm btn-default">' +
- this.options.doneButtonText +
- '</button>' +
- '</div>' +
- '</div>'
- : '';
- var drop =
- '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
- '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
- '<span class="filter-option pull-left"></span> ' +
- '<span class="bs-caret">' +
- this.options.template.caret +
- '</span>' +
- '</button>' +
- '<div class="dropdown-menu open" role="combobox">' +
- header +
- searchbox +
- actionsbox +
- '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
- '</ul>' +
- donebutton +
- '</div>' +
- '</div>';
- return $(drop);
- },
- createView: function () {
- var $drop = this.createDropdown(),
- li = this.createLi();
- $drop.find('ul')[0].innerHTML = li;
- return $drop;
- },
- reloadLi: function () {
- // rebuild
- var li = this.createLi();
- this.$menuInner[0].innerHTML = li;
- },
- createLi: function () {
- var that = this,
- _li = [],
- optID = 0,
- titleOption = document.createElement('option'),
- liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
- // Helper functions
- /**
- * @param content
- * @param [index]
- * @param [classes]
- * @param [optgroup]
- * @returns {string}
- */
- var generateLI = function (content, index, classes, optgroup) {
- return '<li' +
- ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
- ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
- ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
- '>' + content + '</li>';
- };
- /**
- * @param text
- * @param [classes]
- * @param [inline]
- * @param [tokens]
- * @returns {string}
- */
- var generateA = function (text, classes, inline, tokens) {
- return '<a tabindex="0"' +
- (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
- (inline ? ' style="' + inline + '"' : '') +
- (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
- (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
- ' role="option">' + text +
- '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
- '</a>';
- };
- if (this.options.title && !this.multiple) {
- // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
- // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
- liIndex--;
- if (!this.$element.find('.bs-title-option').length) {
- // Use native JS to prepend option (faster)
- var element = this.$element[0];
- titleOption.className = 'bs-title-option';
- titleOption.innerHTML = this.options.title;
- titleOption.value = '';
- element.insertBefore(titleOption, element.firstChild);
- // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
- // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
- // if so, the select will have the data-selected attribute
- var $opt = $(element.options[element.selectedIndex]);
- if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
- titleOption.selected = true;
- }
- }
- }
- var $selectOptions = this.$element.find('option');
- $selectOptions.each(function (index) {
- var $this = $(this);
- liIndex++;
- if ($this.hasClass('bs-title-option')) return;
- // Get the class and text for the option
- var optionClass = this.className || '',
- inline = htmlEscape(this.style.cssText),
- text = $this.data('content') ? $this.data('content') : $this.html(),
- tokens = $this.data('tokens') ? $this.data('tokens') : null,
- subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
- icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
- $parent = $this.parent(),
- isOptgroup = $parent[0].tagName === 'OPTGROUP',
- isOptgroupDisabled = isOptgroup && $parent[0].disabled,
- isDisabled = this.disabled || isOptgroupDisabled,
- prevHiddenIndex;
- if (icon !== '' && isDisabled) {
- icon = '<span>' + icon + '</span>';
- }
- if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
- // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
- // used to determine whether or not a divider should be placed after an optgroup if there are
- // hidden options between the optgroup and the first visible option
- prevHiddenIndex = $this.data('prevHiddenIndex');
- $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
- liIndex--;
- return;
- }
- if (!$this.data('content')) {
- // Prepend any icon and append any subtext to the main text.
- text = icon + '<span class="text">' + text + subtext + '</span>';
- }
- if (isOptgroup && $this.data('divider') !== true) {
- if (that.options.hideDisabled && isDisabled) {
- if ($parent.data('allOptionsDisabled') === undefined) {
- var $options = $parent.children();
- $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
- }
- if ($parent.data('allOptionsDisabled')) {
- liIndex--;
- return;
- }
- }
- var optGroupClass = ' ' + $parent[0].className || '';
- if ($this.index() === 0) { // Is it the first option of the optgroup?
- optID += 1;
- // Get the opt group label
- var label = $parent[0].label,
- labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
- labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
- label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
- if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
- liIndex++;
- _li.push(generateLI('', null, 'divider', optID + 'div'));
- }
- liIndex++;
- _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
- }
- if (that.options.hideDisabled && isDisabled) {
- liIndex--;
- return;
- }
- _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
- } else if ($this.data('divider') === true) {
- _li.push(generateLI('', index, 'divider'));
- } else if ($this.data('hidden') === true) {
- // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
- // used to determine whether or not a divider should be placed after an optgroup if there are
- // hidden options between the optgroup and the first visible option
- prevHiddenIndex = $this.data('prevHiddenIndex');
- $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
- _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
- } else {
- var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
- // if previous element is not an optgroup and hideDisabled is true
- if (!showDivider && that.options.hideDisabled) {
- prevHiddenIndex = $this.data('prevHiddenIndex');
- if (prevHiddenIndex !== undefined) {
- // select the element **before** the first hidden element in the group
- var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
-
- if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
- showDivider = true;
- }
- }
- }
- if (showDivider) {
- liIndex++;
- _li.push(generateLI('', null, 'divider', optID + 'div'));
- }
- _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
- }
- that.liObj[index] = liIndex;
- });
- //If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
- if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
- this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
- }
- return _li.join('');
- },
- findLis: function () {
- if (this.$lis == null) this.$lis = this.$menu.find('li');
- return this.$lis;
- },
- /**
- * @param [updateLi] defaults to true
- */
- render: function (updateLi) {
- var that = this,
- notDisabled,
- $selectOptions = this.$element.find('option');
- //Update the LI to match the SELECT
- if (updateLi !== false) {
- $selectOptions.each(function (index) {
- var $lis = that.findLis().eq(that.liObj[index]);
- that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
- that.setSelected(index, this.selected, $lis);
- });
- }
- this.togglePlaceholder();
- this.tabIndex();
- var selectedItems = $selectOptions.map(function () {
- if (this.selected) {
- if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
- var $this = $(this),
- icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
- subtext;
- if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
- subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
- } else {
- subtext = '';
- }
- if (typeof $this.attr('title') !== 'undefined') {
- return $this.attr('title');
- } else if ($this.data('content') && that.options.showContent) {
- return $this.data('content').toString();
- } else {
- return icon + $this.html() + subtext;
- }
- }
- }).toArray();
- //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
- //Convert all the values into a comma delimited string
- var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
- //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
- if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
- var max = this.options.selectedTextFormat.split('>');
- if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
- notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
- var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
- tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
- title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
- }
- }
- if (this.options.title == undefined) {
- this.options.title = this.$element.attr('title');
- }
- if (this.options.selectedTextFormat == 'static') {
- title = this.options.title;
- }
- //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
- if (!title) {
- title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
- }
- //strip all HTML tags and trim the result, then unescape any escaped tags
- this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
- this.$button.children('.filter-option').html(title);
- this.$element.trigger('rendered.bs.select');
- },
- /**
- * @param [style]
- * @param [status]
- */
- setStyle: function (style, status) {
- if (this.$element.attr('class')) {
- this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
- }
- var buttonClass = style ? style : this.options.style;
- if (status == 'add') {
- this.$button.addClass(buttonClass);
- } else if (status == 'remove') {
- this.$button.removeClass(buttonClass);
- } else {
- this.$button.removeClass(this.options.style);
- this.$button.addClass(buttonClass);
- }
- },
- liHeight: function (refresh) {
- if (!refresh && (this.options.size === false || this.sizeInfo)) return;
- var newElement = document.createElement('div'),
- menu = document.createElement('div'),
- menuInner = document.createElement('ul'),
- divider = document.createElement('li'),
- li = document.createElement('li'),
- a = document.createElement('a'),
- text = document.createElement('span'),
- header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
- search = this.options.liveSearch ? document.createElement('div') : null,
- actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
- doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
- text.className = 'text';
- newElement.className = this.$menu[0].parentNode.className + ' open';
- menu.className = 'dropdown-menu open';
- menuInner.className = 'dropdown-menu inner';
- divider.className = 'divider';
- text.appendChild(document.createTextNode('Inner text'));
- a.appendChild(text);
- li.appendChild(a);
- menuInner.appendChild(li);
- menuInner.appendChild(divider);
- if (header) menu.appendChild(header);
- if (search) {
- var input = document.createElement('input');
- search.className = 'bs-searchbox';
- input.className = 'form-control';
- search.appendChild(input);
- menu.appendChild(search);
- }
- if (actions) menu.appendChild(actions);
- menu.appendChild(menuInner);
- if (doneButton) menu.appendChild(doneButton);
- newElement.appendChild(menu);
- document.body.appendChild(newElement);
- var liHeight = a.offsetHeight,
- headerHeight = header ? header.offsetHeight : 0,
- searchHeight = search ? search.offsetHeight : 0,
- actionsHeight = actions ? actions.offsetHeight : 0,
- doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
- dividerHeight = $(divider).outerHeight(true),
- // fall back to jQuery if getComputedStyle is not supported
- menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
- $menu = menuStyle ? null : $(menu),
- menuPadding = {
- vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
- parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
- parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
- parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
- horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
- parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
- parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
- parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
- },
- menuExtras = {
- vert: menuPadding.vert +
- parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
- parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
- horiz: menuPadding.horiz +
- parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
- parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
- }
- document.body.removeChild(newElement);
- this.sizeInfo = {
- liHeight: liHeight,
- headerHeight: headerHeight,
- searchHeight: searchHeight,
- actionsHeight: actionsHeight,
- doneButtonHeight: doneButtonHeight,
- dividerHeight: dividerHeight,
- menuPadding: menuPadding,
- menuExtras: menuExtras
- };
- },
- setSize: function () {
- this.findLis();
- this.liHeight();
- if (this.options.header) this.$menu.css('padding-top', 0);
- if (this.options.size === false) return;
- var that = this,
- $menu = this.$menu,
- $menuInner = this.$menuInner,
- $window = $(window),
- selectHeight = this.$newElement[0].offsetHeight,
- selectWidth = this.$newElement[0].offsetWidth,
- liHeight = this.sizeInfo['liHeight'],
- headerHeight = this.sizeInfo['headerHeight'],
- searchHeight = this.sizeInfo['searchHeight'],
- actionsHeight = this.sizeInfo['actionsHeight'],
- doneButtonHeight = this.sizeInfo['doneButtonHeight'],
- divHeight = this.sizeInfo['dividerHeight'],
- menuPadding = this.sizeInfo['menuPadding'],
- menuExtras = this.sizeInfo['menuExtras'],
- notDisabled = this.options.hideDisabled ? '.disabled' : '',
- menuHeight,
- menuWidth,
- getHeight,
- getWidth,
- selectOffsetTop,
- selectOffsetBot,
- selectOffsetLeft,
- selectOffsetRight,
- getPos = function() {
- var pos = that.$newElement.offset(),
- $container = $(that.options.container),
- containerPos;
- if (that.options.container && !$container.is('body')) {
- containerPos = $container.offset();
- containerPos.top += parseInt($container.css('borderTopWidth'));
- containerPos.left += parseInt($container.css('borderLeftWidth'));
- } else {
- containerPos = { top: 0, left: 0 };
- }
- var winPad = that.options.windowPadding;
- selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
- selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
- selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
- selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
- selectOffsetTop -= winPad[0];
- selectOffsetLeft -= winPad[3];
- };
- getPos();
- if (this.options.size === 'auto') {
- var getSize = function () {
- var minHeight,
- hasClass = function (className, include) {
- return function (element) {
- if (include) {
- return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
- } else {
- return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
- }
- };
- },
- lis = that.$menuInner[0].getElementsByTagName('li'),
- lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
- optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
- getPos();
- menuHeight = selectOffsetBot - menuExtras.vert;
- menuWidth = selectOffsetRight - menuExtras.horiz;
- if (that.options.container) {
- if (!$menu.data('height')) $menu.data('height', $menu.height());
- getHeight = $menu.data('height');
- if (!$menu.data('width')) $menu.data('width', $menu.width());
- getWidth = $menu.data('width');
- } else {
- getHeight = $menu.height();
- getWidth = $menu.width();
- }
- if (that.options.dropupAuto) {
- that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
- }
- if (that.$newElement.hasClass('dropup')) {
- menuHeight = selectOffsetTop - menuExtras.vert;
- }
- if (that.options.dropdownAlignRight === 'auto') {
- $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
- }
- if ((lisVisible.length + optGroup.length) > 3) {
- minHeight = liHeight * 3 + menuExtras.vert - 2;
- } else {
- minHeight = 0;
- }
- $menu.css({
- 'max-height': menuHeight + 'px',
- 'overflow': 'hidden',
- 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
- });
- $menuInner.css({
- 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
- 'overflow-y': 'auto',
- 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
- });
- };
- getSize();
- this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
- $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
- } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
- var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
- divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
- menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
- if (that.options.container) {
- if (!$menu.data('height')) $menu.data('height', $menu.height());
- getHeight = $menu.data('height');
- } else {
- getHeight = $menu.height();
- }
- if (that.options.dropupAuto) {
- //noinspection JSUnusedAssignment
- this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
- }
- $menu.css({
- 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
- 'overflow': 'hidden',
- 'min-height': ''
- });
- $menuInner.css({
- 'max-height': menuHeight - menuPadding.vert + 'px',
- 'overflow-y': 'auto',
- 'min-height': ''
- });
- }
- },
- setWidth: function () {
- if (this.options.width === 'auto') {
- this.$menu.css('min-width', '0');
- // Get correct width if element is hidden
- var $selectClone = this.$menu.parent().clone().appendTo('body'),
- $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
- ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
- btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
- $selectClone.remove();
- $selectClone2.remove();
- // Set width to whatever's larger, button title or longest option
- this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
- } else if (this.options.width === 'fit') {
- // Remove inline min-width so width can be changed from 'auto'
- this.$menu.css('min-width', '');
- this.$newElement.css('width', '').addClass('fit-width');
- } else if (this.options.width) {
- // Remove inline min-width so width can be changed from 'auto'
- this.$menu.css('min-width', '');
- this.$newElement.css('width', this.options.width);
- } else {
- // Remove inline min-width/width so width can be changed
- this.$menu.css('min-width', '');
- this.$newElement.css('width', '');
- }
- // Remove fit-width class if width is changed programmatically
- if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
- this.$newElement.removeClass('fit-width');
- }
- },
- selectPosition: function () {
- this.$bsContainer = $('<div class="bs-container" />');
- var that = this,
- $container = $(this.options.container),
- pos,
- containerPos,
- actualHeight,
- getPlacement = function ($element) {
- that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
- pos = $element.offset();
- if (!$container.is('body')) {
- containerPos = $container.offset();
- containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
- containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
- } else {
- containerPos = { top: 0, left: 0 };
- }
- actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
- that.$bsContainer.css({
- 'top': pos.top - containerPos.top + actualHeight,
- 'left': pos.left - containerPos.left,
- 'width': $element[0].offsetWidth
- });
- };
- this.$button.on('click', function () {
- var $this = $(this);
- if (that.isDisabled()) {
- return;
- }
- getPlacement(that.$newElement);
- that.$bsContainer
- .appendTo(that.options.container)
- .toggleClass('open', !$this.hasClass('open'))
- .append(that.$menu);
- });
- $(window).on('resize scroll', function () {
- getPlacement(that.$newElement);
- });
- this.$element.on('hide.bs.select', function () {
- that.$menu.data('height', that.$menu.height());
- that.$bsContainer.detach();
- });
- },
- /**
- * @param {number} index - the index of the option that is being changed
- * @param {boolean} selected - true if the option is being selected, false if being deselected
- * @param {JQuery} $lis - the 'li' element that is being modified
- */
- setSelected: function (index, selected, $lis) {
- if (!$lis) {
- this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
- $lis = this.findLis().eq(this.liObj[index]);
- }
- $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
- },
- /**
- * @param {number} index - the index of the option that is being disabled
- * @param {boolean} disabled - true if the option is being disabled, false if being enabled
- * @param {JQuery} $lis - the 'li' element that is being modified
- */
- setDisabled: function (index, disabled, $lis) {
- if (!$lis) {
- $lis = this.findLis().eq(this.liObj[index]);
- }
- if (disabled) {
- $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
- } else {
- $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
- }
- },
- isDisabled: function () {
- return this.$element[0].disabled;
- },
- checkDisabled: function () {
- var that = this;
- if (this.isDisabled()) {
- this.$newElement.addClass('disabled');
- this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
- } else {
- if (this.$button.hasClass('disabled')) {
- this.$newElement.removeClass('disabled');
- this.$button.removeClass('disabled').attr('aria-disabled', false);
- }
- if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
- this.$button.removeAttr('tabindex');
- }
- }
- this.$button.click(function () {
- return !that.isDisabled();
- });
- },
- togglePlaceholder: function () {
- var value = this.$element.val();
- this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
- },
- tabIndex: function () {
- if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
- (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
- this.$element.data('tabindex', this.$element.attr('tabindex'));
- this.$button.attr('tabindex', this.$element.data('tabindex'));
- }
- this.$element.attr('tabindex', -98);
- },
- clickListener: function () {
- var that = this,
- $document = $(document);
- $document.data('spaceSelect', false);
- this.$button.on('keyup', function (e) {
- if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
- e.preventDefault();
- $document.data('spaceSelect', false);
- }
- });
- this.$button.on('click', function () {
- that.setSize();
- });
- this.$element.on('shown.bs.select', function () {
- if (!that.options.liveSearch && !that.multiple) {
- that.$menuInner.find('.selected a').focus();
- } else if (!that.multiple) {
- var selectedIndex = that.liObj[that.$element[0].selectedIndex];
- if (typeof selectedIndex !== 'number' || that.options.size === false) return;
- // scroll to selected option
- var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
- offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
- that.$menuInner[0].scrollTop = offset;
- }
- });
- this.$menuInner.on('click', 'li a', function (e) {
- var $this = $(this),
- clickedIndex = $this.parent().data('originalIndex'),
- prevValue = that.$element.val(),
- prevIndex = that.$element.prop('selectedIndex'),
- triggerChange = true;
- // Don't close on multi choice menu
- if (that.multiple && that.options.maxOptions !== 1) {
- e.stopPropagation();
- }
- e.preventDefault();
- //Don't run if we have been disabled
- if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
- var $options = that.$element.find('option'),
- $option = $options.eq(clickedIndex),
- state = $option.prop('selected'),
- $optgroup = $option.parent('optgroup'),
- maxOptions = that.options.maxOptions,
- maxOptionsGrp = $optgroup.data('maxOptions') || false;
- if (!that.multiple) { // Deselect all others if not multi select box
- $options.prop('selected', false);
- $option.prop('selected', true);
- that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
- that.setSelected(clickedIndex, true);
- } else { // Toggle the one we have chosen if we are multi select.
- $option.prop('selected', !state);
- that.setSelected(clickedIndex, !state);
- $this.blur();
- if (maxOptions !== false || maxOptionsGrp !== false) {
- var maxReached = maxOptions < $options.filter(':selected').length,
- maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
- if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
- if (maxOptions && maxOptions == 1) {
- $options.prop('selected', false);
- $option.prop('selected', true);
- that.$menuInner.find('.selected').removeClass('selected');
- that.setSelected(clickedIndex, true);
- } else if (maxOptionsGrp && maxOptionsGrp == 1) {
- $optgroup.find('option:selected').prop('selected', false);
- $option.prop('selected', true);
- var optgroupID = $this.parent().data('optgroup');
- that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
- that.setSelected(clickedIndex, true);
- } else {
- var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
- maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
- maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
- maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
- $notify = $('<div class="notify"></div>');
- // If {var} is set in array, replace it
- /** @deprecated */
- if (maxOptionsArr[2]) {
- maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
- maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
- }
- $option.prop('selected', false);
- that.$menu.append($notify);
- if (maxOptions && maxReached) {
- $notify.append($('<div>' + maxTxt + '</div>'));
- triggerChange = false;
- that.$element.trigger('maxReached.bs.select');
- }
- if (maxOptionsGrp && maxReachedGrp) {
- $notify.append($('<div>' + maxTxtGrp + '</div>'));
- triggerChange = false;
- that.$element.trigger('maxReachedGrp.bs.select');
- }
- setTimeout(function () {
- that.setSelected(clickedIndex, false);
- }, 10);
- $notify.delay(750).fadeOut(300, function () {
- $(this).remove();
- });
- }
- }
- }
- }
- if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
- that.$button.focus();
- } else if (that.options.liveSearch) {
- that.$searchbox.focus();
- }
- // Trigger select 'change'
- if (triggerChange) {
- if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
- // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
- changed_arguments = [clickedIndex, $option.prop('selected'), state];
- that.$element
- .triggerNative('change');
- }
- }
- }
- });
- this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
- if (e.currentTarget == this) {
- e.preventDefault();
- e.stopPropagation();
- if (that.options.liveSearch && !$(e.target).hasClass('close')) {
- that.$searchbox.focus();
- } else {
- that.$button.focus();
- }
- }
- });
- this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
- e.preventDefault();
- e.stopPropagation();
- if (that.options.liveSearch) {
- that.$searchbox.focus();
- } else {
- that.$button.focus();
- }
- });
- this.$menu.on('click', '.popover-title .close', function () {
- that.$button.click();
- });
- this.$searchbox.on('click', function (e) {
- e.stopPropagation();
- });
- this.$menu.on('click', '.actions-btn', function (e) {
- if (that.options.liveSearch) {
- that.$searchbox.focus();
- } else {
- that.$button.focus();
- }
- e.preventDefault();
- e.stopPropagation();
- if ($(this).hasClass('bs-select-all')) {
- that.selectAll();
- } else {
- that.deselectAll();
- }
- });
- this.$element.change(function () {
- that.render(false);
- that.$element.trigger('changed.bs.select', changed_arguments);
- changed_arguments = null;
- });
- },
- liveSearchListener: function () {
- var that = this,
- $no_results = $('<li class="no-results"></li>');
- this.$button.on('click.dropdown.data-api', function () {
- that.$menuInner.find('.active').removeClass('active');
- if (!!that.$searchbox.val()) {
- that.$searchbox.val('');
- that.$lis.not('.is-hidden').removeClass('hidden');
- if (!!$no_results.parent().length) $no_results.remove();
- }
- if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
- setTimeout(function () {
- that.$searchbox.focus();
- }, 10);
- });
- this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
- e.stopPropagation();
- });
- this.$searchbox.on('input propertychange', function () {
- that.$lis.not('.is-hidden').removeClass('hidden');
- that.$lis.filter('.active').removeClass('active');
- $no_results.remove();
- if (that.$searchbox.val()) {
- var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
- $hideItems;
- if (that.options.liveSearchNormalize) {
- $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
- } else {
- $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
- }
- if ($hideItems.length === $searchBase.length) {
- $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
- that.$menuInner.append($no_results);
- that.$lis.addClass('hidden');
- } else {
- $hideItems.addClass('hidden');
- var $lisVisible = that.$lis.not('.hidden'),
- $foundDiv;
- // hide divider if first or last visible, or if followed by another divider
- $lisVisible.each(function (index) {
- var $this = $(this);
- if ($this.hasClass('divider')) {
- if ($foundDiv === undefined) {
- $this.addClass('hidden');
- } else {
- if ($foundDiv) $foundDiv.addClass('hidden');
- $foundDiv = $this;
- }
- } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
- $this.addClass('hidden');
- } else {
- $foundDiv = null;
- }
- });
- if ($foundDiv) $foundDiv.addClass('hidden');
- $searchBase.not('.hidden').first().addClass('active');
- that.$menuInner.scrollTop(0);
- }
- }
- });
- },
- _searchStyle: function () {
- var styles = {
- begins: 'ibegins',
- startsWith: 'ibegins'
- };
- return styles[this.options.liveSearchStyle] || 'icontains';
- },
- val: function (value) {
- if (typeof value !== 'undefined') {
- this.$element.val(value);
- this.render();
- return this.$element;
- } else {
- return this.$element.val();
- }
- },
- changeAll: function (status) {
- if (!this.multiple) return;
- if (typeof status === 'undefined') status = true;
- this.findLis();
- var $options = this.$element.find('option'),
- $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
- lisVisLen = $lisVisible.length,
- selectedOptions = [];
-
- if (status) {
- if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
- } else {
- if ($lisVisible.filter('.selected').length === 0) return;
- }
-
- $lisVisible.toggleClass('selected', status);
- for (var i = 0; i < lisVisLen; i++) {
- var origIndex = $lisVisible[i].getAttribute('data-original-index');
- selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
- }
- $(selectedOptions).prop('selected', status);
- this.render(false);
- this.togglePlaceholder();
- this.$element
- .triggerNative('change');
- },
- selectAll: function () {
- return this.changeAll(true);
- },
- deselectAll: function () {
- return this.changeAll(false);
- },
- toggle: function (e) {
- e = e || window.event;
- if (e) e.stopPropagation();
- this.$button.trigger('click');
- },
- keydown: function (e) {
- var $this = $(this),
- $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
- $items,
- that = $parent.data('this'),
- index,
- prevIndex,
- isActive,
- selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
- keyCodeMap = {
- 32: ' ',
- 48: '0',
- 49: '1',
- 50: '2',
- 51: '3',
- 52: '4',
- 53: '5',
- 54: '6',
- 55: '7',
- 56: '8',
- 57: '9',
- 59: ';',
- 65: 'a',
- 66: 'b',
- 67: 'c',
- 68: 'd',
- 69: 'e',
- 70: 'f',
- 71: 'g',
- 72: 'h',
- 73: 'i',
- 74: 'j',
- 75: 'k',
- 76: 'l',
- 77: 'm',
- 78: 'n',
- 79: 'o',
- 80: 'p',
- 81: 'q',
- 82: 'r',
- 83: 's',
- 84: 't',
- 85: 'u',
- 86: 'v',
- 87: 'w',
- 88: 'x',
- 89: 'y',
- 90: 'z',
- 96: '0',
- 97: '1',
- 98: '2',
- 99: '3',
- 100: '4',
- 101: '5',
- 102: '6',
- 103: '7',
- 104: '8',
- 105: '9'
- };
- isActive = that.$newElement.hasClass('open');
- if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
- if (!that.options.container) {
- that.setSize();
- that.$menu.parent().addClass('open');
- isActive = true;
- } else {
- that.$button.trigger('click');
- }
- that.$searchbox.focus();
- return;
- }
- if (that.options.liveSearch) {
- if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
- e.preventDefault();
- e.stopPropagation();
- that.$menuInner.click();
- that.$button.focus();
- }
- }
- if (/(38|40)/.test(e.keyCode.toString(10))) {
- $items = that.$lis.filter(selector);
- if (!$items.length) return;
- if (!that.options.liveSearch) {
- index = $items.index($items.find('a').filter(':focus').parent());
- } else {
- index = $items.index($items.filter('.active'));
- }
- prevIndex = that.$menuInner.data('prevIndex');
- if (e.keyCode == 38) {
- if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
- if (index < 0) index += $items.length;
- } else if (e.keyCode == 40) {
- if (that.options.liveSearch || index == prevIndex) index++;
- index = index % $items.length;
- }
- that.$menuInner.data('prevIndex', index);
- if (!that.options.liveSearch) {
- $items.eq(index).children('a').focus();
- } else {
- e.preventDefault();
- if (!$this.hasClass('dropdown-toggle')) {
- $items.removeClass('active').eq(index).addClass('active').children('a').focus();
- $this.focus();
- }
- }
- } else if (!$this.is('input')) {
- var keyIndex = [],
- count,
- prevKey;
- $items = that.$lis.filter(selector);
- $items.each(function (i) {
- if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
- keyIndex.push(i);
- }
- });
- count = $(document).data('keycount');
- count++;
- $(document).data('keycount', count);
- prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
- if (prevKey != keyCodeMap[e.keyCode]) {
- count = 1;
- $(document).data('keycount', count);
- } else if (count >= keyIndex.length) {
- $(document).data('keycount', 0);
- if (count > keyIndex.length) count = 1;
- }
- $items.eq(keyIndex[count - 1]).children('a').focus();
- }
- // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
- if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
- if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
- if (!that.options.liveSearch) {
- var elem = $(':focus');
- elem.click();
- // Bring back focus for multiselects
- elem.focus();
- // Prevent screen from scrolling if the user hit the spacebar
- e.preventDefault();
- // Fixes spacebar selection of dropdown items in FF & IE
- $(document).data('spaceSelect', true);
- } else if (!/(32)/.test(e.keyCode.toString(10))) {
- that.$menuInner.find('.active a').click();
- $this.focus();
- }
- $(document).data('keycount', 0);
- }
- if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
- that.$menu.parent().removeClass('open');
- if (that.options.container) that.$newElement.removeClass('open');
- that.$button.focus();
- }
- },
- mobile: function () {
- this.$element.addClass('mobile-device');
- },
- refresh: function () {
- this.$lis = null;
- this.liObj = {};
- this.reloadLi();
- this.render();
- this.checkDisabled();
- this.liHeight(true);
- this.setStyle();
- this.setWidth();
- if (this.$lis) this.$searchbox.trigger('propertychange');
- this.$element.trigger('refreshed.bs.select');
- },
- hide: function () {
- this.$newElement.hide();
- },
- show: function () {
- this.$newElement.show();
- },
- remove: function () {
- this.$newElement.remove();
- this.$element.remove();
- },
- destroy: function () {
- this.$newElement.before(this.$element).remove();
- if (this.$bsContainer) {
- this.$bsContainer.remove();
- } else {
- this.$menu.remove();
- }
- this.$element
- .off('.bs.select')
- .removeData('selectpicker')
- .removeClass('bs-select-hidden selectpicker');
- }
- };
- // SELECTPICKER PLUGIN DEFINITION
- // ==============================
- function Plugin(option) {
- // get the args of the outer function..
- var args = arguments;
- // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
- // to get lost/corrupted in android 2.3 and IE9 #715 #775
- var _option = option;
- [].shift.apply(args);
- var value;
- var chain = this.each(function () {
- var $this = $(this);
- if ($this.is('select')) {
- var data = $this.data('selectpicker'),
- options = typeof _option == 'object' && _option;
- if (!data) {
- var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
- config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
- $this.data('selectpicker', (data = new Selectpicker(this, config)));
- } else if (options) {
- for (var i in options) {
- if (options.hasOwnProperty(i)) {
- data.options[i] = options[i];
- }
- }
- }
- if (typeof _option == 'string') {
- if (data[_option] instanceof Function) {
- value = data[_option].apply(data, args);
- } else {
- value = data.options[_option];
- }
- }
- }
- });
- if (typeof value !== 'undefined') {
- //noinspection JSUnusedAssignment
- return value;
- } else {
- return chain;
- }
- }
- var old = $.fn.selectpicker;
- $.fn.selectpicker = Plugin;
- $.fn.selectpicker.Constructor = Selectpicker;
- // SELECTPICKER NO CONFLICT
- // ========================
- $.fn.selectpicker.noConflict = function () {
- $.fn.selectpicker = old;
- return this;
- };
- $(document)
- .data('keycount', 0)
- .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
- .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
- e.stopPropagation();
- });
- // SELECTPICKER DATA-API
- // =====================
- $(window).on('load.bs.select.data-api', function () {
- $('.selectpicker').each(function () {
- var $selectpicker = $(this);
- Plugin.call($selectpicker, $selectpicker.data());
- })
- });
- })(jQuery);
- }));
- /***/ }),
- /* 16 */
- /***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(jQuery) {/* ========================================================================
- * Bootstrap (plugin): validator.js v0.11.9
- * ========================================================================
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Cina Saffary.
- * Made by @1000hz in the style of Bootstrap 3 era @fat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- * ======================================================================== */
- +function ($) {
- 'use strict';
- // VALIDATOR CLASS DEFINITION
- // ==========================
- function getValue($el) {
- return $el.is('[type="checkbox"]') ? $el.prop('checked') :
- $el.is('[type="radio"]') ? !!$('[name="' + $el.attr('name') + '"]:checked').length :
- $el.is('select[multiple]') ? ($el.val() || []).length :
- $el.val()
- }
- var Validator = function (element, options) {
- this.options = options
- this.validators = $.extend({}, Validator.VALIDATORS, options.custom)
- this.$element = $(element)
- this.$btn = $('button[type="submit"], input[type="submit"]')
- .filter('[form="' + this.$element.attr('id') + '"]')
- .add(this.$element.find('input[type="submit"], button[type="submit"]'))
- this.update()
- this.$element.on('input.bs.validator change.bs.validator focusout.bs.validator', $.proxy(this.onInput, this))
- this.$element.on('submit.bs.validator', $.proxy(this.onSubmit, this))
- this.$element.on('reset.bs.validator', $.proxy(this.reset, this))
- this.$element.find('[data-match]').each(function () {
- var $this = $(this)
- var target = $this.attr('data-match')
- $(target).on('input.bs.validator', function (e) {
- getValue($this) && $this.trigger('input.bs.validator')
- })
- })
- // run validators for fields with values, but don't clobber server-side errors
- this.$inputs.filter(function () {
- return getValue($(this)) && !$(this).closest('.has-error').length
- }).trigger('focusout')
- this.$element.attr('novalidate', true) // disable automatic native validation
- }
- Validator.VERSION = '0.11.9'
- Validator.INPUT_SELECTOR = ':input:not([type="hidden"], [type="submit"], [type="reset"], button)'
- Validator.FOCUS_OFFSET = 20
- Validator.DEFAULTS = {
- delay: 500,
- html: false,
- disable: true,
- focus: true,
- custom: {},
- errors: {
- match: 'Does not match',
- minlength: 'Not long enough'
- },
- feedback: {
- success: 'glyphicon-ok',
- error: 'glyphicon-remove'
- }
- }
- Validator.VALIDATORS = {
- 'native': function ($el) {
- var el = $el[0]
- if (el.checkValidity) {
- return !el.checkValidity() && !el.validity.valid && (el.validationMessage || "error!")
- }
- },
- 'match': function ($el) {
- var target = $el.attr('data-match')
- return $el.val() !== $(target).val() && Validator.DEFAULTS.errors.match
- },
- 'minlength': function ($el) {
- var minlength = $el.attr('data-minlength')
- return $el.val().length < minlength && Validator.DEFAULTS.errors.minlength
- }
- }
- Validator.prototype.update = function () {
- var self = this
- this.$inputs = this.$element.find(Validator.INPUT_SELECTOR)
- .add(this.$element.find('[data-validate="true"]'))
- .not(this.$element.find('[data-validate="false"]')
- .each(function () { self.clearErrors($(this)) })
- )
- this.toggleSubmit()
- return this
- }
- Validator.prototype.onInput = function (e) {
- var self = this
- var $el = $(e.target)
- var deferErrors = e.type !== 'focusout'
- if (!this.$inputs.is($el)) return
- this.validateInput($el, deferErrors).done(function () {
- self.toggleSubmit()
- })
- }
- Validator.prototype.validateInput = function ($el, deferErrors) {
- var value = getValue($el)
- var prevErrors = $el.data('bs.validator.errors')
- if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr('name') + '"]')
- var e = $.Event('validate.bs.validator', {relatedTarget: $el[0]})
- this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
- var self = this
- return this.runValidators($el).done(function (errors) {
- $el.data('bs.validator.errors', errors)
- errors.length
- ? deferErrors ? self.defer($el, self.showErrors) : self.showErrors($el)
- : self.clearErrors($el)
- if (!prevErrors || errors.toString() !== prevErrors.toString()) {
- e = errors.length
- ? $.Event('invalid.bs.validator', {relatedTarget: $el[0], detail: errors})
- : $.Event('valid.bs.validator', {relatedTarget: $el[0], detail: prevErrors})
- self.$element.trigger(e)
- }
- self.toggleSubmit()
- self.$element.trigger($.Event('validated.bs.validator', {relatedTarget: $el[0]}))
- })
- }
- Validator.prototype.runValidators = function ($el) {
- var errors = []
- var deferred = $.Deferred()
- $el.data('bs.validator.deferred') && $el.data('bs.validator.deferred').reject()
- $el.data('bs.validator.deferred', deferred)
- function getValidatorSpecificError(key) {
- return $el.attr('data-' + key + '-error')
- }
- function getValidityStateError() {
- var validity = $el[0].validity
- return validity.typeMismatch ? $el.attr('data-type-error')
- : validity.patternMismatch ? $el.attr('data-pattern-error')
- : validity.stepMismatch ? $el.attr('data-step-error')
- : validity.rangeOverflow ? $el.attr('data-max-error')
- : validity.rangeUnderflow ? $el.attr('data-min-error')
- : validity.valueMissing ? $el.attr('data-required-error')
- : null
- }
- function getGenericError() {
- return $el.attr('data-error')
- }
- function getErrorMessage(key) {
- return getValidatorSpecificError(key)
- || getValidityStateError()
- || getGenericError()
- }
- $.each(this.validators, $.proxy(function (key, validator) {
- var error = null
- if ((getValue($el) || $el.attr('required')) &&
- ($el.attr('data-' + key) !== undefined || key == 'native') &&
- (error = validator.call(this, $el))) {
- error = getErrorMessage(key) || error
- !~errors.indexOf(error) && errors.push(error)
- }
- }, this))
- if (!errors.length && getValue($el) && $el.attr('data-remote')) {
- this.defer($el, function () {
- var data = {}
- data[$el.attr('name')] = getValue($el)
- $.get($el.attr('data-remote'), data)
- .fail(function (jqXHR, textStatus, error) { errors.push(getErrorMessage('remote') || error) })
- .always(function () { deferred.resolve(errors)})
- })
- } else deferred.resolve(errors)
- return deferred.promise()
- }
- Validator.prototype.validate = function () {
- var self = this
- $.when(this.$inputs.map(function (el) {
- return self.validateInput($(this), false)
- })).then(function () {
- self.toggleSubmit()
- self.focusError()
- })
- return this
- }
- Validator.prototype.focusError = function () {
- if (!this.options.focus) return
- var $input = this.$element.find(".has-error:first :input")
- if ($input.length === 0) return
- $('html, body').animate({scrollTop: $input.offset().top - Validator.FOCUS_OFFSET}, 250)
- $input.focus()
- }
- Validator.prototype.showErrors = function ($el) {
- var method = this.options.html ? 'html' : 'text'
- var errors = $el.data('bs.validator.errors')
- var $group = $el.closest('.form-group')
- var $block = $group.find('.help-block.with-errors')
- var $feedback = $group.find('.form-control-feedback')
- if (!errors.length) return
- errors = $('<ul/>')
- .addClass('list-unstyled')
- .append($.map(errors, function (error) { return $('<li/>')[method](error) }))
- $block.data('bs.validator.originalContent') === undefined && $block.data('bs.validator.originalContent', $block.html())
- $block.empty().append(errors)
- $group.addClass('has-error has-danger')
- $group.hasClass('has-feedback')
- && $feedback.removeClass(this.options.feedback.success)
- && $feedback.addClass(this.options.feedback.error)
- && $group.removeClass('has-success')
- }
- Validator.prototype.clearErrors = function ($el) {
- var $group = $el.closest('.form-group')
- var $block = $group.find('.help-block.with-errors')
- var $feedback = $group.find('.form-control-feedback')
- $block.html($block.data('bs.validator.originalContent'))
- $group.removeClass('has-error has-danger has-success')
- $group.hasClass('has-feedback')
- && $feedback.removeClass(this.options.feedback.error)
- && $feedback.removeClass(this.options.feedback.success)
- && getValue($el)
- && $feedback.addClass(this.options.feedback.success)
- && $group.addClass('has-success')
- }
- Validator.prototype.hasErrors = function () {
- function fieldErrors() {
- return !!($(this).data('bs.validator.errors') || []).length
- }
- return !!this.$inputs.filter(fieldErrors).length
- }
- Validator.prototype.isIncomplete = function () {
- function fieldIncomplete() {
- var value = getValue($(this))
- return !(typeof value == "string" ? $.trim(value) : value)
- }
- return !!this.$inputs.filter('[required]').filter(fieldIncomplete).length
- }
- Validator.prototype.onSubmit = function (e) {
- this.validate()
- if (this.isIncomplete() || this.hasErrors()) e.preventDefault()
- }
- Validator.prototype.toggleSubmit = function () {
- if (!this.options.disable) return
- this.$btn.toggleClass('disabled', this.isIncomplete() || this.hasErrors())
- }
- Validator.prototype.defer = function ($el, callback) {
- callback = $.proxy(callback, this, $el)
- if (!this.options.delay) return callback()
- window.clearTimeout($el.data('bs.validator.timeout'))
- $el.data('bs.validator.timeout', window.setTimeout(callback, this.options.delay))
- }
- Validator.prototype.reset = function () {
- this.$element.find('.form-control-feedback')
- .removeClass(this.options.feedback.error)
- .removeClass(this.options.feedback.success)
- this.$inputs
- .removeData(['bs.validator.errors', 'bs.validator.deferred'])
- .each(function () {
- var $this = $(this)
- var timeout = $this.data('bs.validator.timeout')
- window.clearTimeout(timeout) && $this.removeData('bs.validator.timeout')
- })
- this.$element.find('.help-block.with-errors')
- .each(function () {
- var $this = $(this)
- var originalContent = $this.data('bs.validator.originalContent')
- $this
- .removeData('bs.validator.originalContent')
- .html(originalContent)
- })
- this.$btn.removeClass('disabled')
- this.$element.find('.has-error, .has-danger, .has-success').removeClass('has-error has-danger has-success')
- return this
- }
- Validator.prototype.destroy = function () {
- this.reset()
- this.$element
- .removeAttr('novalidate')
- .removeData('bs.validator')
- .off('.bs.validator')
- this.$inputs
- .off('.bs.validator')
- this.options = null
- this.validators = null
- this.$element = null
- this.$btn = null
- this.$inputs = null
- return this
- }
- // VALIDATOR PLUGIN DEFINITION
- // ===========================
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this)
- var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == 'object' && option)
- var data = $this.data('bs.validator')
- if (!data && option == 'destroy') return
- if (!data) $this.data('bs.validator', (data = new Validator(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
- var old = $.fn.validator
- $.fn.validator = Plugin
- $.fn.validator.Constructor = Validator
- // VALIDATOR NO CONFLICT
- // =====================
- $.fn.validator.noConflict = function () {
- $.fn.validator = old
- return this
- }
- // VALIDATOR DATA-API
- // ==================
- $(window).on('load', function () {
- $('form[data-toggle="validator"]').each(function () {
- var $form = $(this)
- Plugin.call($form, $form.data())
- })
- })
- }(jQuery);
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
- /***/ }),
- /* 17 */
- /***/ (function(module, exports, __webpack_require__) {
- var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
- * bootstrap-fileinput v4.4.2
- * http://plugins.krajee.com/file-input
- *
- * Author: Kartik Visweswaran
- * Copyright: 2014 - 2017, Kartik Visweswaran, Krajee.com
- *
- * Licensed under the BSD 3-Clause
- * https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
- */
- (function (factory) {
- "use strict";
- //noinspection JSUnresolvedVariable
- if (true) { // jshint ignore:line
- // AMD. Register as an anonymous module.
- !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
- __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
- (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
- __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // jshint ignore:line
- } else { // noinspection JSUnresolvedVariable
- if (typeof module === 'object' && module.exports) { // jshint ignore:line
- // Node/CommonJS
- // noinspection JSUnresolvedVariable
- module.exports = factory(require('jquery')); // jshint ignore:line
- } else {
- // Browser globals
- factory(window.jQuery);
- }
- }
- }(function ($) {
- "use strict";
- $.fn.fileinputLocales = {};
- $.fn.fileinputThemes = {};
- String.prototype.setTokens = function (replacePairs) {
- var str = this.toString(), key, re;
- for (key in replacePairs) {
- if (replacePairs.hasOwnProperty(key)) {
- re = new RegExp("\{" + key + "\}", "g");
- str = str.replace(re, replacePairs[key]);
- }
- }
- return str;
- };
- var $h, FileInput;
- // fileinput helper object for all global variables and internal helper methods
- //noinspection JSUnresolvedVariable
- $h = {
- FRAMES: '.kv-preview-thumb',
- SORT_CSS: 'file-sortable',
- STYLE_SETTING: 'style="width:{width};height:{height};"',
- OBJECT_PARAMS: '<param name="controller" value="true" />\n' +
- '<param name="allowFullScreen" value="true" />\n' +
- '<param name="allowScriptAccess" value="always" />\n' +
- '<param name="autoPlay" value="false" />\n' +
- '<param name="autoStart" value="false" />\n' +
- '<param name="quality" value="high" />\n',
- DEFAULT_PREVIEW: '<div class="file-preview-other">\n' +
- '<span class="{previewFileIconClass}">{previewFileIcon}</span>\n' +
- '</div>',
- MODAL_ID: 'kvFileinputModal',
- MODAL_EVENTS: ['show', 'shown', 'hide', 'hidden', 'loaded'],
- objUrl: window.URL || window.webkitURL,
- compare: function (input, str, exact) {
- return input !== undefined && (exact ? input === str : input.match(str));
- },
- isIE: function (ver) {
- // check for IE versions < 11
- if (navigator.appName !== 'Microsoft Internet Explorer') {
- return false;
- }
- if (ver === 10) {
- return new RegExp('msie\\s' + ver, 'i').test(navigator.userAgent);
- }
- var div = document.createElement("div"), status;
- div.innerHTML = "<!--[if IE " + ver + "]> <i></i> <![endif]-->";
- status = div.getElementsByTagName("i").length;
- document.body.appendChild(div);
- div.parentNode.removeChild(div);
- return status;
- },
- initModal: function ($modal) {
- var $body = $('body');
- if ($body.length) {
- $modal.appendTo($body);
- }
- },
- isEmpty: function (value, trim) {
- return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
- },
- isArray: function (a) {
- return Array.isArray(a) || Object.prototype.toString.call(a) === '[object Array]';
- },
- ifSet: function (needle, haystack, def) {
- def = def || '';
- return (haystack && typeof haystack === 'object' && needle in haystack) ? haystack[needle] : def;
- },
- cleanArray: function (arr) {
- if (!(arr instanceof Array)) {
- arr = [];
- }
- return arr.filter(function (e) {
- return (e !== undefined && e !== null);
- });
- },
- spliceArray: function (arr, index) {
- var i, j = 0, out = [];
- if (!(arr instanceof Array)) {
- return [];
- }
- for (i = 0; i < arr.length; i++) {
- if (i !== index) {
- out[j] = arr[i];
- j++;
- }
- }
- return out;
- },
- getNum: function (num, def) {
- def = def || 0;
- if (typeof num === "number") {
- return num;
- }
- if (typeof num === "string") {
- num = parseFloat(num);
- }
- return isNaN(num) ? def : num;
- },
- hasFileAPISupport: function () {
- return !!(window.File && window.FileReader);
- },
- hasDragDropSupport: function () {
- var div = document.createElement('div');
- /** @namespace div.draggable */
- /** @namespace div.ondragstart */
- /** @namespace div.ondrop */
- return !$h.isIE(9) &&
- (div.draggable !== undefined || (div.ondragstart !== undefined && div.ondrop !== undefined));
- },
- hasFileUploadSupport: function () {
- return $h.hasFileAPISupport() && window.FormData;
- },
- hasBlobSupport: function () {
- try {
- return !!window.Blob && Boolean(new Blob());
- } catch (e) {
- return false;
- }
- },
- hasArrayBufferViewSupport: function () {
- try {
- return new Blob([new Uint8Array(100)]).size === 100;
- } catch (e) {
- return false;
- }
- },
- dataURI2Blob: function (dataURI) {
- //noinspection JSUnresolvedVariable
- var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder ||
- window.MSBlobBuilder, canBlob = $h.hasBlobSupport(), byteStr, arrayBuffer, intArray, i, mimeStr, bb,
- canProceed = (canBlob || BlobBuilder) && window.atob && window.ArrayBuffer && window.Uint8Array;
- if (!canProceed) {
- return null;
- }
- if (dataURI.split(',')[0].indexOf('base64') >= 0) {
- byteStr = atob(dataURI.split(',')[1]);
- } else {
- byteStr = decodeURIComponent(dataURI.split(',')[1]);
- }
- arrayBuffer = new ArrayBuffer(byteStr.length);
- intArray = new Uint8Array(arrayBuffer);
- for (i = 0; i < byteStr.length; i += 1) {
- intArray[i] = byteStr.charCodeAt(i);
- }
- mimeStr = dataURI.split(',')[0].split(':')[1].split(';')[0];
- if (canBlob) {
- return new Blob([$h.hasArrayBufferViewSupport() ? intArray : arrayBuffer], {type: mimeStr});
- }
- bb = new BlobBuilder();
- bb.append(arrayBuffer);
- return bb.getBlob(mimeStr);
- },
- addCss: function ($el, css) {
- $el.removeClass(css).addClass(css);
- },
- getElement: function (options, param, value) {
- return ($h.isEmpty(options) || $h.isEmpty(options[param])) ? value : $(options[param]);
- },
- uniqId: function () {
- return Math.round(new Date().getTime() + (Math.random() * 100));
- },
- htmlEncode: function (str) {
- return str.replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''');
- },
- replaceTags: function (str, tags) {
- var out = str;
- if (!tags) {
- return out;
- }
- $.each(tags, function (key, value) {
- if (typeof value === "function") {
- value = value();
- }
- out = out.split(key).join(value);
- });
- return out;
- },
- cleanMemory: function ($thumb) {
- var data = $thumb.is('img') ? $thumb.attr('src') : $thumb.find('source').attr('src');
- /** @namespace $h.objUrl.revokeObjectURL */
- $h.objUrl.revokeObjectURL(data);
- },
- findFileName: function (filePath) {
- var sepIndex = filePath.lastIndexOf('/');
- if (sepIndex === -1) {
- sepIndex = filePath.lastIndexOf('\\');
- }
- return filePath.split(filePath.substring(sepIndex, sepIndex + 1)).pop();
- },
- checkFullScreen: function () {
- //noinspection JSUnresolvedVariable
- return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
- document.msFullscreenElement;
- },
- toggleFullScreen: function (maximize) {
- var doc = document, de = doc.documentElement;
- if (de && maximize && !$h.checkFullScreen()) {
- /** @namespace document.requestFullscreen */
- /** @namespace document.msRequestFullscreen */
- /** @namespace document.mozRequestFullScreen */
- /** @namespace document.webkitRequestFullscreen */
- /** @namespace Element.ALLOW_KEYBOARD_INPUT */
- if (de.requestFullscreen) {
- de.requestFullscreen();
- } else if (de.msRequestFullscreen) {
- de.msRequestFullscreen();
- } else if (de.mozRequestFullScreen) {
- de.mozRequestFullScreen();
- } else if (de.webkitRequestFullscreen) {
- de.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
- }
- } else {
- /** @namespace document.exitFullscreen */
- /** @namespace document.msExitFullscreen */
- /** @namespace document.mozCancelFullScreen */
- /** @namespace document.webkitExitFullscreen */
- if (doc.exitFullscreen) {
- doc.exitFullscreen();
- } else if (doc.msExitFullscreen) {
- doc.msExitFullscreen();
- } else if (doc.mozCancelFullScreen) {
- doc.mozCancelFullScreen();
- } else if (doc.webkitExitFullscreen) {
- doc.webkitExitFullscreen();
- }
- }
- },
- moveArray: function (arr, oldIndex, newIndex) {
- if (newIndex >= arr.length) {
- var k = newIndex - arr.length;
- while ((k--) + 1) {
- arr.push(undefined);
- }
- }
- arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);
- return arr;
- },
- cleanZoomCache: function ($el) {
- var $cache = $el.closest('.kv-zoom-cache-theme');
- if (!$cache.length) {
- $cache = $el.closest('.kv-zoom-cache');
- }
- $cache.remove();
- },
- setOrientation: function (buffer, callback) {
- var scanner = new DataView(buffer), idx = 0, value = 1, // Non-rotated is the default
- maxBytes, uInt16, exifLength;
- if (scanner.getUint16(idx) !== 0xFFD8 || buffer.length < 2) {
- return; // not a proper JPEG
- }
- idx += 2;
- maxBytes = scanner.byteLength;
- while (idx < maxBytes - 2) {
- uInt16 = scanner.getUint16(idx);
- idx += 2;
- switch (uInt16) {
- case 0xFFE1: // Start of EXIF
- exifLength = scanner.getUint16(idx);
- maxBytes = exifLength - idx;
- idx += 2;
- break;
- case 0x0112: // Orientation tag
- value = scanner.getUint16(idx + 6, false);
- maxBytes = 0; // Stop scanning
- break;
- }
- }
- if (callback) {
- callback(value);
- }
- },
- validateOrientation: function (file, callback) {
- if (!window.FileReader || !window.DataView) {
- return; // skip orientation if pre-requisite libraries not supported by browser
- }
- var reader = new FileReader(), buffer;
- reader.onloadend = function () {
- buffer = reader.result;
- $h.setOrientation(buffer, callback);
- };
- reader.readAsArrayBuffer(file);
- },
- adjustOrientedImage: function ($img, isZoom) {
- var offsetContTop, offsetTop, newTop;
- if (!$img.hasClass('is-portrait-gt4')) {
- return;
- }
- if (isZoom) {
- $img.css({width: $img.parent().height()});
- return;
- } else {
- $img.css({height: 'auto', width: $img.height()});
- }
- offsetContTop = $img.parent().offset().top;
- offsetTop = $img.offset().top;
- newTop = offsetContTop - offsetTop;
- $img.css('margin-top', newTop);
- }
- };
- FileInput = function (element, options) {
- var self = this;
- self.$element = $(element);
- if (!self._validate()) {
- return;
- }
- self.isPreviewable = $h.hasFileAPISupport();
- self.isIE9 = $h.isIE(9);
- self.isIE10 = $h.isIE(10);
- if (self.isPreviewable || self.isIE9) {
- self._init(options);
- self._listen();
- } else {
- self.$element.removeClass('file-loading');
- }
- };
- //noinspection JSUnusedGlobalSymbols
- FileInput.prototype = {
- constructor: FileInput,
- _cleanup: function () {
- var self = this;
- self.reader = null;
- self.formdata = {};
- self.uploadCount = 0;
- self.uploadStatus = {};
- self.uploadLog = [];
- self.uploadAsyncCount = 0;
- self.loadedImages = [];
- self.totalImagesCount = 0;
- self.ajaxRequests = [];
- self.clearStack();
- self.fileInputCleared = false;
- self.fileBatchCompleted = true;
- if (!self.isPreviewable) {
- self.showPreview = false;
- }
- self.isError = false;
- self.ajaxAborted = false;
- self.cancelling = false;
- },
- _init: function (options) {
- var self = this, $el = self.$element, $cont, t, tmp;
- self.options = options;
- $.each(options, function (key, value) {
- switch (key) {
- case 'minFileCount':
- case 'maxFileCount':
- case 'minFileSize':
- case 'maxFileSize':
- case 'maxFilePreviewSize':
- case 'resizeImageQuality':
- case 'resizeIfSizeMoreThan':
- case 'progressUploadThreshold':
- case 'initialPreviewCount':
- case 'zoomModalHeight':
- case 'minImageHeight':
- case 'maxImageHeight':
- case 'minImageWidth':
- case 'maxImageWidth':
- self[key] = $h.getNum(value);
- break;
- default:
- self[key] = value;
- break;
- }
- });
- if (self.rtl) { // swap buttons for rtl
- tmp = self.previewZoomButtonIcons.prev;
- self.previewZoomButtonIcons.prev = self.previewZoomButtonIcons.next;
- self.previewZoomButtonIcons.next = tmp;
- }
- self._cleanup();
- self.$form = $el.closest('form');
- self._initTemplateDefaults();
- self.uploadFileAttr = !$h.isEmpty($el.attr('name')) ? $el.attr('name') : 'file_data';
- t = self._getLayoutTemplate('progress');
- self.progressTemplate = t.replace('{class}', self.progressClass);
- self.progressCompleteTemplate = t.replace('{class}', self.progressCompleteClass);
- self.progressErrorTemplate = t.replace('{class}', self.progressErrorClass);
- self.dropZoneEnabled = $h.hasDragDropSupport() && self.dropZoneEnabled;
- self.isDisabled = $el.attr('disabled') || $el.attr('readonly');
- if (self.isDisabled) {
- $el.attr('disabled', true);
- }
- self.isUploadable = $h.hasFileUploadSupport() && !$h.isEmpty(self.uploadUrl);
- self.isClickable = self.browseOnZoneClick && self.showPreview &&
- (self.isUploadable && self.dropZoneEnabled || !$h.isEmpty(self.defaultPreviewContent));
- self.slug = typeof options.slugCallback === "function" ? options.slugCallback : self._slugDefault;
- self.mainTemplate = self.showCaption ? self._getLayoutTemplate('main1') : self._getLayoutTemplate('main2');
- self.captionTemplate = self._getLayoutTemplate('caption');
- self.previewGenericTemplate = self._getPreviewTemplate('generic');
- if (self.resizeImage && (self.maxImageWidth || self.maxImageHeight)) {
- self.imageCanvas = document.createElement('canvas');
- self.imageCanvasContext = self.imageCanvas.getContext('2d');
- }
- if ($h.isEmpty($el.attr('id'))) {
- $el.attr('id', $h.uniqId());
- }
- self.namespace = '.fileinput_' + $el.attr('id').replace(/-/g, '_');
- if (self.$container === undefined) {
- self.$container = self._createContainer();
- } else {
- self._refreshContainer();
- }
- $cont = self.$container;
- self.$dropZone = $cont.find('.file-drop-zone');
- self.$progress = $cont.find('.kv-upload-progress');
- self.$btnUpload = $cont.find('.fileinput-upload');
- self.$captionContainer = $h.getElement(options, 'elCaptionContainer', $cont.find('.file-caption'));
- self.$caption = $h.getElement(options, 'elCaptionText', $cont.find('.file-caption-name'));
- self.$previewContainer = $h.getElement(options, 'elPreviewContainer', $cont.find('.file-preview'));
- self.$preview = $h.getElement(options, 'elPreviewImage', $cont.find('.file-preview-thumbnails'));
- self.$previewStatus = $h.getElement(options, 'elPreviewStatus', $cont.find('.file-preview-status'));
- self.$errorContainer = $h.getElement(options, 'elErrorContainer',
- self.$previewContainer.find('.kv-fileinput-error'));
- if (!$h.isEmpty(self.msgErrorClass)) {
- $h.addCss(self.$errorContainer, self.msgErrorClass);
- }
- self.$errorContainer.hide();
- self.previewInitId = "preview-" + $h.uniqId();
- self._initPreviewCache();
- self._initPreview(true);
- self._initPreviewActions();
- self._setFileDropZoneTitle();
- $el.removeClass('file-loading');
- if ($el.attr('disabled')) {
- self.disable();
- }
- self._initZoom();
- if (self.hideThumbnailContent) {
- $h.addCss(self.$preview, 'hide-content');
- }
- },
- _initTemplateDefaults: function () {
- var self = this, tMain1, tMain2, tPreview, tFileIcon, tClose, tCaption, tBtnDefault, tBtnLink, tBtnBrowse,
- tModalMain, tModal, tProgress, tSize, tFooter, tActions, tActionDelete, tActionUpload, tActionZoom,
- tActionDrag, tIndicator, tTagBef, tTagBef1, tTagBef2, tTagAft, tGeneric, tHtml, tImage, tText, tVideo,
- tAudio, tFlash, tObject, tPdf, tOther, tZoomCache, vDefaultDim;
- tMain1 = '{preview}\n' +
- '<div class="kv-upload-progress hide"></div>\n' +
- '<div class="input-group {class}">\n' +
- ' {caption}\n' +
- ' <div class="input-group-btn">\n' +
- ' {remove}\n' +
- ' {cancel}\n' +
- ' {upload}\n' +
- ' {browse}\n' +
- ' </div>\n' +
- '</div>';
- tMain2 = '{preview}\n<div class="kv-upload-progress hide"></div>\n{remove}\n{cancel}\n{upload}\n{browse}\n';
- tPreview = '<div class="file-preview {class}">\n' +
- ' {close}' +
- ' <div class="{dropClass}">\n' +
- ' <div class="file-preview-thumbnails">\n' +
- ' </div>\n' +
- ' <div class="clearfix"></div>' +
- ' <div class="file-preview-status text-center text-success"></div>\n' +
- ' <div class="kv-fileinput-error"></div>\n' +
- ' </div>\n' +
- '</div>';
- tClose = '<div class="close fileinput-remove">×</div>\n';
- tFileIcon = '<i class="glyphicon glyphicon-file kv-caption-icon"></i>';
- tCaption = '<div tabindex="500" class="form-control file-caption {class}">\n' +
- ' <div class="file-caption-name"></div>\n' +
- '</div>\n';
- //noinspection HtmlUnknownAttribute
- tBtnDefault = '<button type="{type}" tabindex="500" title="{title}" class="{css}" ' +
- '{status}>{icon} {label}</button>';
- //noinspection HtmlUnknownAttribute
- tBtnLink = '<a href="{href}" tabindex="500" title="{title}" class="{css}" {status}>{icon} {label}</a>';
- //noinspection HtmlUnknownAttribute
- tBtnBrowse = '<div tabindex="500" class="{css}" {status}>{icon} {label}</div>';
- tModalMain = '<div id="' + $h.MODAL_ID + '" class="file-zoom-dialog modal fade" ' +
- 'tabindex="-1" aria-labelledby="' + $h.MODAL_ID + 'Label"></div>';
- tModal = '<div class="modal-dialog modal-lg{rtl}" role="document">\n' +
- ' <div class="modal-content">\n' +
- ' <div class="modal-header">\n' +
- ' <div class="kv-zoom-actions pull-right">{toggleheader}{fullscreen}{borderless}{close}</div>\n' +
- ' <h3 class="modal-title">{heading} <small><span class="kv-zoom-title"></span></small></h3>\n' +
- ' </div>\n' +
- ' <div class="modal-body">\n' +
- ' <div class="floating-buttons"></div>\n' +
- ' <div class="kv-zoom-body file-zoom-content {zoomFrameClass}"></div>\n' + '{prev} {next}\n' +
- ' </div>\n' +
- ' </div>\n' +
- '</div>\n';
- tProgress = '<div class="progress">\n' +
- ' <div class="{class}" role="progressbar"' +
- ' aria-valuenow="{percent}" aria-valuemin="0" aria-valuemax="100" style="width:{percent}%;">\n' +
- ' {status}\n' +
- ' </div>\n' +
- '</div>';
- tSize = ' <samp>({sizeText})</samp>';
- tFooter = '<div class="file-thumbnail-footer">\n' +
- ' <div class="file-footer-caption" title="{caption}">{caption}<br>{size}</div>\n' +
- ' {progress} {indicator} {actions}\n' +
- '</div>';
- tActions = '{drag}\n' +
- '<div class="file-actions">\n' +
- ' <div class="file-footer-buttons">\n' +
- ' {upload} {delete} {zoom} {other}' +
- ' </div>\n' +
- ' <div class="clearfix"></div>\n' +
- '</div>';
- //noinspection HtmlUnknownAttribute
- tActionDelete = '<button type="button" class="kv-file-remove {removeClass}" ' +
- 'title="{removeTitle}" {dataUrl}{dataKey}>{removeIcon}</button>\n';
- tActionUpload = '<button type="button" class="kv-file-upload {uploadClass}" title="{uploadTitle}">' +
- '{uploadIcon}</button>';
- tActionZoom = '<button type="button" class="kv-file-zoom {zoomClass}" ' +
- 'title="{zoomTitle}">{zoomIcon}</button>';
- tActionDrag = '<span class="file-drag-handle {dragClass}" title="{dragTitle}">{dragIcon}</span>';
- tIndicator = '<div class="file-upload-indicator" title="{indicatorTitle}">{indicator}</div>';
- tTagBef = '<div class="file-preview-frame {frameClass}" id="{previewId}" data-fileindex="{fileindex}"' +
- ' data-template="{template}"';
- tTagBef1 = tTagBef + '><div class="kv-file-content">\n';
- tTagBef2 = tTagBef + ' title="{caption}"><div class="kv-file-content">\n';
- tTagAft = '</div>{footer}\n</div>\n';
- tGeneric = '{content}\n';
- tHtml = '<div class="kv-preview-data file-preview-html" title="{caption}" ' + $h.STYLE_SETTING +
- '>{data}</div>\n';
- tImage = '<img src="{data}" class="file-preview-image kv-preview-data" title="{caption}" alt="{caption}" ' +
- $h.STYLE_SETTING + '>\n';
- tText = '<textarea class="kv-preview-data file-preview-text" title="{caption}" readonly ' +
- $h.STYLE_SETTING + '>{data}</textarea>\n';
- tVideo = '<video class="kv-preview-data file-preview-video" width="{width}" ' +
- 'height="{height}" controls>\n' + '<source src="{data}" type="{type}">\n' + $h.DEFAULT_PREVIEW +
- '\n</video>\n';
- tAudio = '<div class="file-preview-audio"><audio class="kv-preview-data" controls>\n<source src="{data}" ' +
- 'type="{type}">\n' + $h.DEFAULT_PREVIEW + '\n</audio></div>\n';
- tFlash = '<object class="kv-preview-data file-object" type="application/x-shockwave-flash" ' +
- 'width="{width}" height="{height}" data="{data}">\n' + $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW +
- '\n</object>\n';
- tObject = '<object class="kv-preview-data file-object {typeCss}" data="{data}" type="{type}" ' +
- 'width="{width}" height="{height}">\n' + '<param name="movie" value="{caption}" />\n' +
- $h.OBJECT_PARAMS + ' ' + $h.DEFAULT_PREVIEW + '\n</object>\n';
- tPdf = '<embed class="kv-preview-data" src="{data}" ' +
- 'width="{width}" height="{height}" type="application/pdf">\n';
- tOther = '<div class="kv-preview-data file-preview-other-frame">\n' + $h.DEFAULT_PREVIEW + '\n</div>\n';
- tZoomCache = '<div class="kv-zoom-cache" style="display:none">{zoomContent}</div>';
- vDefaultDim = {width: "100%", height: "100%", 'min-height': "480px"};
- self.defaults = {
- layoutTemplates: {
- main1: tMain1,
- main2: tMain2,
- preview: tPreview,
- close: tClose,
- fileIcon: tFileIcon,
- caption: tCaption,
- modalMain: tModalMain,
- modal: tModal,
- progress: tProgress,
- size: tSize,
- footer: tFooter,
- indicator: tIndicator,
- actions: tActions,
- actionDelete: tActionDelete,
- actionUpload: tActionUpload,
- actionZoom: tActionZoom,
- actionDrag: tActionDrag,
- btnDefault: tBtnDefault,
- btnLink: tBtnLink,
- btnBrowse: tBtnBrowse,
- zoomCache: tZoomCache
- },
- previewMarkupTags: {
- tagBefore1: tTagBef1,
- tagBefore2: tTagBef2,
- tagAfter: tTagAft
- },
- previewContentTemplates: {
- generic: tGeneric,
- html: tHtml,
- image: tImage,
- text: tText,
- video: tVideo,
- audio: tAudio,
- flash: tFlash,
- object: tObject,
- pdf: tPdf,
- other: tOther
- },
- allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash', 'pdf', 'object'],
- previewTemplates: {},
- previewSettings: {
- image: {width: "auto", height: "160px"},
- html: {width: "213px", height: "160px"},
- text: {width: "213px", height: "160px"},
- video: {width: "auto", height: "100%", 'max-width': "100%"},
- audio: {width: "100%", height: "30px"},
- flash: {width: "auto", height: "100%", 'max-width': "100%"},
- object: {height: "100%"},
- pdf: {width: "160px", height: "160px"},
- other: {width: "160px", height: "160px"}
- },
- previewZoomSettings: {
- image: {width: "auto", height: "auto", 'max-width': "100%", 'max-height': "100%"},
- html: vDefaultDim,
- text: vDefaultDim,
- video: {width: "auto", height: "100%", 'max-width': "100%"},
- audio: {width: "100%", height: "30px"},
- flash: {width: "auto", height: "480px"},
- object: {width: "auto", height: "100%", 'max-width': "100%", 'min-height': "480px"},
- pdf: vDefaultDim,
- other: {width: "auto", height: "100%", 'min-height': "480px"}
- },
- fileTypeSettings: {
- image: function (vType, vName) {
- return $h.compare(vType, 'image.*') || $h.compare(vName, /\.(gif|png|jpe?g)$/i);
- },
- html: function (vType, vName) {
- return $h.compare(vType, 'text/html') || $h.compare(vName, /\.(htm|html)$/i);
- },
- text: function (vType, vName) {
- return $h.compare(vType, 'text.*') || $h.compare(vName, /\.(xml|javascript)$/i) ||
- $h.compare(vName, /\.(txt|md|csv|nfo|ini|json|php|js|css)$/i);
- },
- video: function (vType, vName) {
- return $h.compare(vType, 'video.*') && ($h.compare(vType, /(ogg|mp4|mp?g|mov|webm|3gp)$/i) ||
- $h.compare(vName, /\.(og?|mp4|webm|mp?g|mov|3gp)$/i));
- },
- audio: function (vType, vName) {
- return $h.compare(vType, 'audio.*') && ($h.compare(vName, /(ogg|mp3|mp?g|wav)$/i) ||
- $h.compare(vName, /\.(og?|mp3|mp?g|wav)$/i));
- },
- flash: function (vType, vName) {
- return $h.compare(vType, 'application/x-shockwave-flash', true) || $h.compare(vName, /\.(swf)$/i);
- },
- pdf: function (vType, vName) {
- return $h.compare(vType, 'application/pdf', true) || $h.compare(vName, /\.(pdf)$/i);
- },
- object: function () {
- return true;
- },
- other: function () {
- return true;
- }
- },
- fileActionSettings: {
- showRemove: true,
- showUpload: true,
- showZoom: true,
- showDrag: true,
- removeIcon: '<i class="glyphicon glyphicon-trash text-danger"></i>',
- removeClass: 'btn btn-xs btn-default',
- removeTitle: 'Remove file',
- uploadIcon: '<i class="glyphicon glyphicon-upload text-info"></i>',
- uploadClass: 'btn btn-xs btn-default',
- uploadTitle: 'Upload file',
- zoomIcon: '<i class="glyphicon glyphicon-zoom-in"></i>',
- zoomClass: 'btn btn-xs btn-default',
- zoomTitle: 'View Details',
- dragIcon: '<i class="glyphicon glyphicon-menu-hamburger"></i>',
- dragClass: 'text-info',
- dragTitle: 'Move / Rearrange',
- dragSettings: {},
- indicatorNew: '<i class="glyphicon glyphicon-hand-down text-warning"></i>',
- indicatorSuccess: '<i class="glyphicon glyphicon-ok-sign text-success"></i>',
- indicatorError: '<i class="glyphicon glyphicon-exclamation-sign text-danger"></i>',
- indicatorLoading: '<i class="glyphicon glyphicon-hand-up text-muted"></i>',
- indicatorNewTitle: 'Not uploaded yet',
- indicatorSuccessTitle: 'Uploaded',
- indicatorErrorTitle: 'Upload Error',
- indicatorLoadingTitle: 'Uploading ...'
- }
- };
- $.each(self.defaults, function (key, setting) {
- if (key === 'allowedPreviewTypes') {
- if (self.allowedPreviewTypes === undefined) {
- self.allowedPreviewTypes = setting;
- }
- return;
- }
- self[key] = $.extend(true, {}, setting, self[key]);
- });
- self._initPreviewTemplates();
- },
- _initPreviewTemplates: function () {
- var self = this, cfg = self.defaults, tags = self.previewMarkupTags, tagBef, tagAft = tags.tagAfter;
- $.each(cfg.previewContentTemplates, function (key, value) {
- if ($h.isEmpty(self.previewTemplates[key])) {
- tagBef = tags.tagBefore2;
- if (key === 'generic' || key === 'image' || key === 'html' || key === 'text') {
- tagBef = tags.tagBefore1;
- }
- self.previewTemplates[key] = tagBef + value + tagAft;
- }
- });
- },
- _initPreviewCache: function () {
- var self = this;
- self.previewCache = {
- data: {},
- init: function () {
- var content = self.initialPreview;
- if (content.length > 0 && !$h.isArray(content)) {
- content = content.split(self.initialPreviewDelimiter);
- }
- self.previewCache.data = {
- content: content,
- config: self.initialPreviewConfig,
- tags: self.initialPreviewThumbTags
- };
- },
- fetch: function () {
- return self.previewCache.data.content.filter(function (n) {
- return n !== null;
- });
- },
- count: function (all) {
- return !!self.previewCache.data && !!self.previewCache.data.content ?
- (all ? self.previewCache.data.content.length : self.previewCache.fetch().length) : 0;
- },
- get: function (i, isDisabled) {
- var ind = 'init_' + i, data = self.previewCache.data, config = data.config[i],
- content = data.content[i], previewId = self.previewInitId + '-' + ind, out, $tmp, cat, ftr,
- fname, ftype, frameClass, asData = $h.ifSet('previewAsData', config, self.initialPreviewAsData),
- parseTemplate = function (cat, dat, fn, ft, id, ftr, ind, fc, t) {
- fc = ' file-preview-initial ' + $h.SORT_CSS + (fc ? ' ' + fc : '');
- return self._generatePreviewTemplate(cat, dat, fn, ft, id, false, null, fc, ftr, ind, t);
- };
- if (!content) {
- return '';
- }
- isDisabled = isDisabled === undefined ? true : isDisabled;
- cat = $h.ifSet('type', config, self.initialPreviewFileType || 'generic');
- fname = $h.ifSet('filename', config, $h.ifSet('caption', config));
- ftype = $h.ifSet('filetype', config, cat);
- ftr = self.previewCache.footer(i, isDisabled, (config && config.size || null));
- frameClass = $h.ifSet('frameClass', config);
- if (asData) {
- out = parseTemplate(cat, content, fname, ftype, previewId, ftr, ind, frameClass);
- } else {
- out = parseTemplate('generic', content, fname, ftype, previewId, ftr, ind, frameClass, cat)
- .setTokens({'content': data.content[i]});
- }
- if (data.tags.length && data.tags[i]) {
- out = $h.replaceTags(out, data.tags[i]);
- }
- /** @namespace config.frameAttr */
- if (!$h.isEmpty(config) && !$h.isEmpty(config.frameAttr)) {
- $tmp = $(document.createElement('div')).html(out);
- $tmp.find('.file-preview-initial').attr(config.frameAttr);
- out = $tmp.html();
- $tmp.remove();
- }
- return out;
- },
- add: function (content, config, tags, append) {
- var data = self.previewCache.data, index;
- if (!$h.isArray(content)) {
- content = content.split(self.initialPreviewDelimiter);
- }
- if (append) {
- index = data.content.push(content) - 1;
- data.config[index] = config;
- data.tags[index] = tags;
- } else {
- index = content.length - 1;
- data.content = content;
- data.config = config;
- data.tags = tags;
- }
- self.previewCache.data = data;
- return index;
- },
- set: function (content, config, tags, append) {
- var data = self.previewCache.data, i, chk;
- if (!content || !content.length) {
- return;
- }
- if (!$h.isArray(content)) {
- content = content.split(self.initialPreviewDelimiter);
- }
- chk = content.filter(function (n) {
- return n !== null;
- });
- if (!chk.length) {
- return;
- }
- if (data.content === undefined) {
- data.content = [];
- }
- if (data.config === undefined) {
- data.config = [];
- }
- if (data.tags === undefined) {
- data.tags = [];
- }
- if (append) {
- for (i = 0; i < content.length; i++) {
- if (content[i]) {
- data.content.push(content[i]);
- }
- }
- for (i = 0; i < config.length; i++) {
- if (config[i]) {
- data.config.push(config[i]);
- }
- }
- for (i = 0; i < tags.length; i++) {
- if (tags[i]) {
- data.tags.push(tags[i]);
- }
- }
- } else {
- data.content = content;
- data.config = config;
- data.tags = tags;
- }
- self.previewCache.data = data;
- },
- unset: function (index) {
- var chk = self.previewCache.count();
- if (!chk) {
- return;
- }
- if (chk === 1) {
- self.previewCache.data.content = [];
- self.previewCache.data.config = [];
- self.previewCache.data.tags = [];
- self.initialPreview = [];
- self.initialPreviewConfig = [];
- self.initialPreviewThumbTags = [];
- return;
- }
- self.previewCache.data.content[index] = null;
- self.previewCache.data.config[index] = null;
- self.previewCache.data.tags[index] = null;
- },
- out: function () {
- var html = '', caption, len = self.previewCache.count(true), i;
- if (len === 0) {
- return {content: '', caption: ''};
- }
- for (i = 0; i < len; i++) {
- html += self.previewCache.get(i);
- }
- caption = self._getMsgSelected(self.previewCache.count());
- return {content: html, caption: caption};
- },
- footer: function (i, isDisabled, size) {
- var data = self.previewCache.data;
- if (!data || !data.config || data.config.length === 0 || $h.isEmpty(data.config[i])) {
- return '';
- }
- isDisabled = isDisabled === undefined ? true : isDisabled;
- var config = data.config[i], caption = $h.ifSet('caption', config), actions,
- width = $h.ifSet('width', config, 'auto'), url = $h.ifSet('url', config, false),
- key = $h.ifSet('key', config, null), fs = self.fileActionSettings,
- initPreviewShowDel = self.initialPreviewShowDelete || false,
- showDel = $h.ifSet('showDelete', config, $h.ifSet('showDelete', fs, initPreviewShowDel)),
- showZoom = $h.ifSet('showZoom', config, $h.ifSet('showZoom', fs, true)),
- showDrag = $h.ifSet('showDrag', config, $h.ifSet('showDrag', fs, true)),
- disabled = (url === false) && isDisabled;
- actions = self._renderFileActions(false, showDel, showZoom, showDrag, disabled, url, key, true);
- return self._getLayoutTemplate('footer').setTokens({
- 'progress': self._renderThumbProgress(),
- 'actions': actions,
- 'caption': caption,
- 'size': self._getSize(size),
- 'width': width,
- 'indicator': ''
- });
- }
- };
- self.previewCache.init();
- },
- _handler: function ($el, event, callback) {
- var self = this, ns = self.namespace, ev = event.split(' ').join(ns + ' ') + ns;
- if (!$el || !$el.length) {
- return;
- }
- $el.off(ev).on(ev, callback);
- },
- _log: function (msg) {
- var self = this, id = self.$element.attr('id');
- if (id) {
- msg = '"' + id + '": ' + msg;
- }
- if (typeof window.console.log !== "undefined") {
- window.console.log(msg);
- } else {
- window.alert(msg);
- }
- },
- _validate: function () {
- var self = this, status = self.$element.attr('type') === 'file';
- if (!status) {
- self._log('The input "type" must be set to "file" for initializing the "bootstrap-fileinput" plugin.');
- }
- return status;
- },
- _errorsExist: function () {
- var self = this, $err;
- if (self.$errorContainer.find('li').length) {
- return true;
- }
- $err = $(document.createElement('div')).html(self.$errorContainer.html());
- $err.find('span.kv-error-close').remove();
- $err.find('ul').remove();
- return $.trim($err.text()).length ? true : false;
- },
- _errorHandler: function (evt, caption) {
- var self = this, err = evt.target.error, showError = function (msg) {
- self._showError(msg.replace('{name}', caption));
- };
- /** @namespace err.NOT_FOUND_ERR */
- /** @namespace err.SECURITY_ERR */
- /** @namespace err.NOT_READABLE_ERR */
- if (err.code === err.NOT_FOUND_ERR) {
- showError(self.msgFileNotFound);
- } else if (err.code === err.SECURITY_ERR) {
- showError(self.msgFileSecured);
- } else if (err.code === err.NOT_READABLE_ERR) {
- showError(self.msgFileNotReadable);
- } else if (err.code === err.ABORT_ERR) {
- showError(self.msgFilePreviewAborted);
- } else {
- showError(self.msgFilePreviewError);
- }
- },
- _addError: function (msg) {
- var self = this, $error = self.$errorContainer;
- if (msg && $error.length) {
- $error.html(self.errorCloseButton + msg);
- self._handler($error.find('.kv-error-close'), 'click', function () {
- $error.fadeOut('slow');
- });
- }
- },
- _resetErrors: function (fade) {
- var self = this, $error = self.$errorContainer;
- self.isError = false;
- self.$container.removeClass('has-error');
- $error.html('');
- if (fade) {
- $error.fadeOut('slow');
- } else {
- $error.hide();
- }
- },
- _showFolderError: function (folders) {
- var self = this, $error = self.$errorContainer, msg;
- if (!folders) {
- return;
- }
- msg = self.msgFoldersNotAllowed.replace('{n}', folders);
- self._addError(msg);
- $h.addCss(self.$container, 'has-error');
- $error.fadeIn(800);
- self._raise('filefoldererror', [folders, msg]);
- },
- _showUploadError: function (msg, params, event) {
- var self = this, $error = self.$errorContainer, ev = event || 'fileuploaderror', e = params && params.id ?
- '<li data-file-id="' + params.id + '">' + msg + '</li>' : '<li>' + msg + '</li>';
- if ($error.find('ul').length === 0) {
- self._addError('<ul>' + e + '</ul>');
- } else {
- $error.find('ul').append(e);
- }
- $error.fadeIn(800);
- self._raise(ev, [params, msg]);
- self.$container.removeClass('file-input-new');
- $h.addCss(self.$container, 'has-error');
- return true;
- },
- _showError: function (msg, params, event) {
- var self = this, $error = self.$errorContainer, ev = event || 'fileerror';
- params = params || {};
- params.reader = self.reader;
- self._addError(msg);
- $error.fadeIn(800);
- self._raise(ev, [params, msg]);
- if (!self.isUploadable) {
- self._clearFileInput();
- }
- self.$container.removeClass('file-input-new');
- $h.addCss(self.$container, 'has-error');
- self.$btnUpload.attr('disabled', true);
- return true;
- },
- _noFilesError: function (params) {
- var self = this, label = self.minFileCount > 1 ? self.filePlural : self.fileSingle,
- msg = self.msgFilesTooLess.replace('{n}', self.minFileCount).replace('{files}', label),
- $error = self.$errorContainer;
- self._addError(msg);
- self.isError = true;
- self._updateFileDetails(0);
- $error.fadeIn(800);
- self._raise('fileerror', [params, msg]);
- self._clearFileInput();
- $h.addCss(self.$container, 'has-error');
- },
- _parseError: function (operation, jqXHR, errorThrown, fileName) {
- /** @namespace jqXHR.responseJSON */
- var self = this, errMsg = $.trim(errorThrown + ''), dot = errMsg.slice(-1) === '.' ? '' : '.',
- text = jqXHR.responseJSON !== undefined && jqXHR.responseJSON.error !== undefined ?
- jqXHR.responseJSON.error : jqXHR.responseText;
- if (self.cancelling && self.msgUploadAborted) {
- errMsg = self.msgUploadAborted;
- }
- if (self.showAjaxErrorDetails && text) {
- text = $.trim(text.replace(/\n\s*\n/g, '\n'));
- text = text.length > 0 ? '<pre>' + text + '</pre>' : '';
- errMsg += dot + text;
- } else {
- errMsg += dot;
- }
- if (errMsg === dot) {
- errMsg = self.msgAjaxError.replace('{operation}', operation);
- }
- self.cancelling = false;
- return fileName ? '<b>' + fileName + ': </b>' + errMsg : errMsg;
- },
- _parseFileType: function (file) {
- var self = this, isValid, vType, cat, i, types = self.allowedPreviewTypes || [];
- for (i = 0; i < types.length; i++) {
- cat = types[i];
- isValid = self.fileTypeSettings[cat];
- vType = isValid(file.type, file.name) ? cat : '';
- if (!$h.isEmpty(vType)) {
- return vType;
- }
- }
- return 'other';
- },
- _getPreviewIcon: function (fname) {
- var self = this, ext, out = null;
- if (fname && fname.indexOf('.') > -1) {
- ext = fname.split('.').pop();
- if (self.previewFileIconSettings) {
- out = self.previewFileIconSettings[ext] || self.previewFileIconSettings[ext.toLowerCase()] || null;
- }
- if (self.previewFileExtSettings) {
- $.each(self.previewFileExtSettings, function (key, func) {
- if (self.previewFileIconSettings[key] && func(ext)) {
- out = self.previewFileIconSettings[key];
- //noinspection UnnecessaryReturnStatementJS
- return;
- }
- });
- }
- }
- return out;
- },
- _parseFilePreviewIcon: function (content, fname) {
- var self = this, icn = self._getPreviewIcon(fname) || self.previewFileIcon, out = content;
- if (out.indexOf('{previewFileIcon}') > -1) {
- out = out.setTokens({'previewFileIconClass': self.previewFileIconClass, 'previewFileIcon': icn});
- }
- return out;
- },
- _raise: function (event, params) {
- var self = this, e = $.Event(event);
- if (params !== undefined) {
- self.$element.trigger(e, params);
- } else {
- self.$element.trigger(e);
- }
- if (e.isDefaultPrevented() || e.result === false) {
- return false;
- }
- switch (event) {
- // ignore these events
- case 'filebatchuploadcomplete':
- case 'filebatchuploadsuccess':
- case 'fileuploaded':
- case 'fileclear':
- case 'filecleared':
- case 'filereset':
- case 'fileerror':
- case 'filefoldererror':
- case 'fileuploaderror':
- case 'filebatchuploaderror':
- case 'filedeleteerror':
- case 'filecustomerror':
- case 'filesuccessremove':
- break;
- // receive data response via `filecustomerror` event`
- default:
- if (!self.ajaxAborted) {
- self.ajaxAborted = e.result;
- }
- break;
- }
- return true;
- },
- _listenFullScreen: function (isFullScreen) {
- var self = this, $modal = self.$modal, $btnFull, $btnBord;
- if (!$modal || !$modal.length) {
- return;
- }
- $btnFull = $modal && $modal.find('.btn-fullscreen');
- $btnBord = $modal && $modal.find('.btn-borderless');
- if (!$btnFull.length || !$btnBord.length) {
- return;
- }
- $btnFull.removeClass('active').attr('aria-pressed', 'false');
- $btnBord.removeClass('active').attr('aria-pressed', 'false');
- if (isFullScreen) {
- $btnFull.addClass('active').attr('aria-pressed', 'true');
- } else {
- $btnBord.addClass('active').attr('aria-pressed', 'true');
- }
- if ($modal.hasClass('file-zoom-fullscreen')) {
- self._maximizeZoomDialog();
- } else {
- if (isFullScreen) {
- self._maximizeZoomDialog();
- } else {
- $btnBord.removeClass('active').attr('aria-pressed', 'false');
- }
- }
- },
- _listen: function () {
- var self = this, $el = self.$element, $form = self.$form, $cont = self.$container, fullScreenEvents;
- self._handler($el, 'change', $.proxy(self._change, self));
- if (self.showBrowse) {
- self._handler(self.$btnFile, 'click', $.proxy(self._browse, self));
- }
- self._handler($cont.find('.fileinput-remove:not([disabled])'), 'click', $.proxy(self.clear, self));
- self._handler($cont.find('.fileinput-cancel'), 'click', $.proxy(self.cancel, self));
- self._initDragDrop();
- self._handler($form, 'reset', $.proxy(self.reset, self));
- if (!self.isUploadable) {
- self._handler($form, 'submit', $.proxy(self._submitForm, self));
- }
- self._handler(self.$container.find('.fileinput-upload'), 'click', $.proxy(self._uploadClick, self));
- self._handler($(window), 'resize', function () {
- self._listenFullScreen(screen.width === window.innerWidth && screen.height === window.innerHeight);
- });
- fullScreenEvents = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange';
- self._handler($(document), fullScreenEvents, function () {
- self._listenFullScreen($h.checkFullScreen());
- });
- self._initClickable();
- },
- _initClickable: function () {
- var self = this, $zone;
- if (!self.isClickable) {
- return;
- }
- $zone = self.isUploadable ? self.$dropZone : self.$preview.find('.file-default-preview');
- $h.addCss($zone, 'clickable');
- $zone.attr('tabindex', -1);
- self._handler($zone, 'click', function (e) {
- var $tar = $(e.target);
- if (!$tar.parents('.file-preview-thumbnails').length || $tar.parents('.file-default-preview').length) {
- self.$element.trigger('click');
- $zone.blur();
- }
- });
- },
- _initDragDrop: function () {
- var self = this, $zone = self.$dropZone;
- if (self.isUploadable && self.dropZoneEnabled && self.showPreview) {
- self._handler($zone, 'dragenter dragover', $.proxy(self._zoneDragEnter, self));
- self._handler($zone, 'dragleave', $.proxy(self._zoneDragLeave, self));
- self._handler($zone, 'drop', $.proxy(self._zoneDrop, self));
- self._handler($(document), 'dragenter dragover drop', self._zoneDragDropInit);
- }
- },
- _zoneDragDropInit: function (e) {
- e.stopPropagation();
- e.preventDefault();
- },
- _zoneDragEnter: function (e) {
- var self = this, hasFiles = $.inArray('Files', e.originalEvent.dataTransfer.types) > -1;
- self._zoneDragDropInit(e);
- if (self.isDisabled || !hasFiles) {
- e.originalEvent.dataTransfer.effectAllowed = 'none';
- e.originalEvent.dataTransfer.dropEffect = 'none';
- return;
- }
- $h.addCss(self.$dropZone, 'file-highlighted');
- },
- _zoneDragLeave: function (e) {
- var self = this;
- self._zoneDragDropInit(e);
- if (self.isDisabled) {
- return;
- }
- self.$dropZone.removeClass('file-highlighted');
- },
- _zoneDrop: function (e) {
- var self = this;
- e.preventDefault();
- /** @namespace e.originalEvent.dataTransfer */
- if (self.isDisabled || $h.isEmpty(e.originalEvent.dataTransfer.files)) {
- return;
- }
- self._change(e, 'dragdrop');
- self.$dropZone.removeClass('file-highlighted');
- },
- _uploadClick: function (e) {
- var self = this, $btn = self.$container.find('.fileinput-upload'), $form,
- isEnabled = !$btn.hasClass('disabled') && $h.isEmpty($btn.attr('disabled'));
- if (e && e.isDefaultPrevented()) {
- return;
- }
- if (!self.isUploadable) {
- if (isEnabled && $btn.attr('type') !== 'submit') {
- $form = $btn.closest('form');
- // downgrade to normal form submit if possible
- if ($form.length) {
- $form.trigger('submit');
- }
- e.preventDefault();
- }
- return;
- }
- e.preventDefault();
- if (isEnabled) {
- self.upload();
- }
- },
- _submitForm: function () {
- var self = this;
- return self._isFileSelectionValid() && !self._abort({});
- },
- _clearPreview: function () {
- var self = this, $p = self.$preview,
- $thumbs = self.showUploadedThumbs ? self.getFrames(':not(.file-preview-success)') : self.getFrames();
- $thumbs.each(function () {
- var $thumb = $(this);
- $thumb.remove();
- $h.cleanZoomCache($p.find('#zoom-' + $thumb.attr('id')));
- });
- if (!self.getFrames().length || !self.showPreview) {
- self._resetUpload();
- }
- self._validateDefaultPreview();
- },
- _initSortable: function () {
- var self = this, $el = self.$preview, settings, selector = '.' + $h.SORT_CSS;
- if (!window.KvSortable || $el.find(selector).length === 0) {
- return;
- }
- //noinspection JSUnusedGlobalSymbols
- settings = {
- handle: '.drag-handle-init',
- dataIdAttr: 'data-preview-id',
- scroll: false,
- draggable: selector,
- onSort: function (e) {
- var oldIndex = e.oldIndex, newIndex = e.newIndex, key, $frame;
- self.initialPreview = $h.moveArray(self.initialPreview, oldIndex, newIndex);
- self.initialPreviewConfig = $h.moveArray(self.initialPreviewConfig, oldIndex, newIndex);
- self.previewCache.init();
- for (var i = 0; i < self.initialPreviewConfig.length; i++) {
- if (self.initialPreviewConfig[i] !== null) {
- key = self.initialPreviewConfig[i].key;
- $frame = $(".kv-file-remove[data-key='" + key + "']").closest($h.FRAMES);
- $frame.attr('data-fileindex', 'init_' + i).attr('data-fileindex', 'init_' + i);
- }
- }
- self._raise('filesorted', {
- previewId: $(e.item).attr('id'),
- 'oldIndex': oldIndex,
- 'newIndex': newIndex,
- stack: self.initialPreviewConfig
- });
- }
- };
- if ($el.data('kvsortable')) {
- $el.kvsortable('destroy');
- }
- $.extend(true, settings, self.fileActionSettings.dragSettings);
- $el.kvsortable(settings);
- },
- _initPreview: function (isInit) {
- var self = this, cap = self.initialCaption || '', out;
- if (!self.previewCache.count()) {
- self._clearPreview();
- if (isInit) {
- self._setCaption(cap);
- } else {
- self._initCaption();
- }
- return;
- }
- out = self.previewCache.out();
- cap = isInit && self.initialCaption ? self.initialCaption : out.caption;
- self.$preview.html(out.content);
- self._setInitThumbAttr();
- self._setCaption(cap);
- self._initSortable();
- if (!$h.isEmpty(out.content)) {
- self.$container.removeClass('file-input-new');
- }
- },
- _getZoomButton: function (type) {
- var self = this, label = self.previewZoomButtonIcons[type], css = self.previewZoomButtonClasses[type],
- title = ' title="' + (self.previewZoomButtonTitles[type] || '') + '" ',
- params = title + (type === 'close' ? ' data-dismiss="modal" aria-hidden="true"' : '');
- if (type === 'fullscreen' || type === 'borderless' || type === 'toggleheader') {
- params += ' data-toggle="button" aria-pressed="false" autocomplete="off"';
- }
- return '<button type="button" class="' + css + ' btn-' + type + '"' + params + '>' + label + '</button>';
- },
- _getModalContent: function () {
- var self = this;
- return self._getLayoutTemplate('modal').setTokens({
- 'rtl': self.rtl ? ' kv-rtl' : '',
- 'zoomFrameClass': self.frameClass,
- 'heading': self.msgZoomModalHeading,
- 'prev': self._getZoomButton('prev'),
- 'next': self._getZoomButton('next'),
- 'toggleheader': self._getZoomButton('toggleheader'),
- 'fullscreen': self._getZoomButton('fullscreen'),
- 'borderless': self._getZoomButton('borderless'),
- 'close': self._getZoomButton('close')
- });
- },
- _listenModalEvent: function (event) {
- var self = this, $modal = self.$modal, getParams = function (e) {
- return {
- sourceEvent: e,
- previewId: $modal.data('previewId'),
- modal: $modal
- };
- };
- $modal.on(event + '.bs.modal', function (e) {
- var $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless');
- self._raise('filezoom' + event, getParams(e));
- if (event === 'shown') {
- $btnBord.removeClass('active').attr('aria-pressed', 'false');
- $btnFull.removeClass('active').attr('aria-pressed', 'false');
- if ($modal.hasClass('file-zoom-fullscreen')) {
- self._maximizeZoomDialog();
- if ($h.checkFullScreen()) {
- $btnFull.addClass('active').attr('aria-pressed', 'true');
- } else {
- $btnBord.addClass('active').attr('aria-pressed', 'true');
- }
- }
- }
- });
- },
- _initZoom: function () {
- var self = this, $dialog, modalMain = self._getLayoutTemplate('modalMain'), modalId = '#' + $h.MODAL_ID;
- if (!self.showPreview) {
- return;
- }
- self.$modal = $(modalId);
- if (!self.$modal || !self.$modal.length) {
- $dialog = $(document.createElement('div')).html(modalMain).insertAfter(self.$container);
- self.$modal = $(modalId).insertBefore($dialog);
- $dialog.remove();
- }
- $h.initModal(self.$modal);
- self.$modal.html(self._getModalContent());
- $.each($h.MODAL_EVENTS, function (key, event) {
- self._listenModalEvent(event);
- });
- },
- _initZoomButtons: function () {
- var self = this, previewId = self.$modal.data('previewId') || '', $first, $last,
- thumbs = self.getFrames().toArray(), len = thumbs.length, $prev = self.$modal.find('.btn-prev'),
- $next = self.$modal.find('.btn-next');
- if (thumbs.length < 2) {
- $prev.hide();
- $next.hide();
- return;
- } else {
- $prev.show();
- $next.show();
- }
- if (!len) {
- return;
- }
- $first = $(thumbs[0]);
- $last = $(thumbs[len - 1]);
- $prev.removeAttr('disabled');
- $next.removeAttr('disabled');
- if ($first.length && $first.attr('id') === previewId) {
- $prev.attr('disabled', true);
- }
- if ($last.length && $last.attr('id') === previewId) {
- $next.attr('disabled', true);
- }
- },
- _maximizeZoomDialog: function () {
- var self = this, $modal = self.$modal, $head = $modal.find('.modal-header:visible'),
- $foot = $modal.find('.modal-footer:visible'), $body = $modal.find('.modal-body'),
- h = $(window).height(), diff = 0;
- $modal.addClass('file-zoom-fullscreen');
- if ($head && $head.length) {
- h -= $head.outerHeight(true);
- }
- if ($foot && $foot.length) {
- h -= $foot.outerHeight(true);
- }
- if ($body && $body.length) {
- diff = $body.outerHeight(true) - $body.height();
- h -= diff;
- }
- $modal.find('.kv-zoom-body').height(h);
- },
- _resizeZoomDialog: function (fullScreen) {
- var self = this, $modal = self.$modal, $btnFull = $modal.find('.btn-fullscreen'),
- $btnBord = $modal.find('.btn-borderless');
- if ($modal.hasClass('file-zoom-fullscreen')) {
- $h.toggleFullScreen(false);
- if (!fullScreen) {
- if (!$btnFull.hasClass('active')) {
- $modal.removeClass('file-zoom-fullscreen');
- self.$modal.find('.kv-zoom-body').css('height', self.zoomModalHeight);
- } else {
- $btnFull.removeClass('active').attr('aria-pressed', 'false');
- }
- } else {
- if (!$btnFull.hasClass('active')) {
- $modal.removeClass('file-zoom-fullscreen');
- self._resizeZoomDialog(true);
- if ($btnBord.hasClass('active')) {
- $btnBord.removeClass('active').attr('aria-pressed', 'false');
- }
- }
- }
- } else {
- if (!fullScreen) {
- self._maximizeZoomDialog();
- return;
- }
- $h.toggleFullScreen(true);
- }
- $modal.focus();
- },
- _setZoomContent: function ($frame, animate) {
- var self = this, $content, tmplt, body, title, $body, $dataEl, config, pid = $frame.attr('id'),
- $modal = self.$modal, $prev = $modal.find('.btn-prev'), $next = $modal.find('.btn-next'), $tmp,
- $btnFull = $modal.find('.btn-fullscreen'), $btnBord = $modal.find('.btn-borderless'), cap, size,
- $btnTogh = $modal.find('.btn-toggleheader'), $zoomPreview = self.$preview.find('#zoom-' + pid);
- tmplt = $zoomPreview.attr('data-template') || 'generic';
- $content = $zoomPreview.find('.kv-file-content');
- body = $content.length ? $content.html() : '';
- cap = $frame.data('caption') || '';
- size = $frame.data('size') || '';
- title = cap + ' ' + size;
- $modal.find('.kv-zoom-title').html(title);
- $body = $modal.find('.kv-zoom-body');
- $modal.removeClass('kv-single-content');
- if (animate) {
- $tmp = $body.addClass('file-thumb-loading').clone().insertAfter($body);
- $body.html(body).hide();
- $tmp.fadeOut('fast', function () {
- $body.fadeIn('fast', function () {
- $body.removeClass('file-thumb-loading');
- });
- $tmp.remove();
- });
- } else {
- $body.html(body);
- }
- config = self.previewZoomSettings[tmplt];
- if (config) {
- $dataEl = $body.find('.kv-preview-data');
- $h.addCss($dataEl, 'file-zoom-detail');
- $.each(config, function (key, value) {
- $dataEl.css(key, value);
- if (($dataEl.attr('width') && key === 'width') || ($dataEl.attr('height') && key === 'height')) {
- $dataEl.removeAttr(key);
- }
- });
- }
- $modal.data('previewId', pid);
- var $img = $body.find('img');
- if ($img.length) {
- $h.adjustOrientedImage($img, true);
- }
- self._handler($prev, 'click', function () {
- self._zoomSlideShow('prev', pid);
- });
- self._handler($next, 'click', function () {
- self._zoomSlideShow('next', pid);
- });
- self._handler($btnFull, 'click', function () {
- self._resizeZoomDialog(true);
- });
- self._handler($btnBord, 'click', function () {
- self._resizeZoomDialog(false);
- });
- self._handler($btnTogh, 'click', function () {
- var $header = $modal.find('.modal-header'), $floatBar = $modal.find('.modal-body .floating-buttons'),
- ht, $actions = $header.find('.kv-zoom-actions'), resize = function (height) {
- var $body = self.$modal.find('.kv-zoom-body'), h = self.zoomModalHeight;
- if ($modal.hasClass('file-zoom-fullscreen')) {
- h = $body.outerHeight(true);
- if (!height) {
- h = h - $header.outerHeight(true);
- }
- }
- $body.css('height', height ? h + height : h);
- };
- if ($header.is(':visible')) {
- ht = $header.outerHeight(true);
- $header.slideUp('slow', function () {
- $actions.find('.btn').appendTo($floatBar);
- resize(ht);
- });
- } else {
- $floatBar.find('.btn').appendTo($actions);
- $header.slideDown('slow', function () {
- resize();
- });
- }
- $modal.focus();
- });
- self._handler($modal, 'keydown', function (e) {
- var key = e.which || e.keyCode;
- if (key === 37 && !$prev.attr('disabled')) {
- self._zoomSlideShow('prev', pid);
- }
- if (key === 39 && !$next.attr('disabled')) {
- self._zoomSlideShow('next', pid);
- }
- });
- },
- _zoomPreview: function ($btn) {
- var self = this, $frame, $modal = self.$modal;
- if (!$btn.length) {
- throw 'Cannot zoom to detailed preview!';
- }
- $h.initModal($modal);
- $modal.html(self._getModalContent());
- $frame = $btn.closest($h.FRAMES);
- self._setZoomContent($frame);
- $modal.modal('show');
- self._initZoomButtons();
- },
- _zoomSlideShow: function (dir, previewId) {
- var self = this, $btn = self.$modal.find('.kv-zoom-actions .btn-' + dir), $targFrame, i,
- thumbs = self.getFrames().toArray(), len = thumbs.length, out;
- if ($btn.attr('disabled')) {
- return;
- }
- for (i = 0; i < len; i++) {
- if ($(thumbs[i]).attr('id') === previewId) {
- out = dir === 'prev' ? i - 1 : i + 1;
- break;
- }
- }
- if (out < 0 || out >= len || !thumbs[out]) {
- return;
- }
- $targFrame = $(thumbs[out]);
- if ($targFrame.length) {
- self._setZoomContent($targFrame, true);
- }
- self._initZoomButtons();
- self._raise('filezoom' + dir, {'previewId': previewId, modal: self.$modal});
- },
- _initZoomButton: function () {
- var self = this;
- self.$preview.find('.kv-file-zoom').each(function () {
- var $el = $(this);
- self._handler($el, 'click', function () {
- self._zoomPreview($el);
- });
- });
- },
- _clearObjects: function ($el) {
- $el.find('video audio').each(function () {
- this.pause();
- $(this).remove();
- });
- $el.find('img object div').each(function () {
- $(this).remove();
- });
- },
- _clearFileInput: function () {
- var self = this, $el = self.$element, $srcFrm, $tmpFrm, $tmpEl;
- self.fileInputCleared = true;
- if ($h.isEmpty($el.val())) {
- return;
- }
- // Fix for IE ver < 11, that does not clear file inputs. Requires a sequence of steps to prevent IE
- // crashing but still allow clearing of the file input.
- if (self.isIE9 || self.isIE10) {
- $srcFrm = $el.closest('form');
- $tmpFrm = $(document.createElement('form'));
- $tmpEl = $(document.createElement('div'));
- $el.before($tmpEl);
- if ($srcFrm.length) {
- $srcFrm.after($tmpFrm);
- } else {
- $tmpEl.after($tmpFrm);
- }
- $tmpFrm.append($el).trigger('reset');
- $tmpEl.before($el).remove();
- $tmpFrm.remove();
- } else { // normal input clear behavior for other sane browsers
- $el.val('');
- }
- },
- _resetUpload: function () {
- var self = this;
- self.uploadCache = {content: [], config: [], tags: [], append: true};
- self.uploadCount = 0;
- self.uploadStatus = {};
- self.uploadLog = [];
- self.uploadAsyncCount = 0;
- self.loadedImages = [];
- self.totalImagesCount = 0;
- self.$btnUpload.removeAttr('disabled');
- self._setProgress(0);
- $h.addCss(self.$progress, 'hide');
- self._resetErrors(false);
- self.ajaxAborted = false;
- self.ajaxRequests = [];
- self._resetCanvas();
- self.cacheInitialPreview = {};
- if (self.overwriteInitial) {
- self.initialPreview = [];
- self.initialPreviewConfig = [];
- self.initialPreviewThumbTags = [];
- self.previewCache.data = {
- content: [],
- config: [],
- tags: []
- };
- }
- },
- _resetCanvas: function () {
- var self = this;
- if (self.canvas && self.imageCanvasContext) {
- self.imageCanvasContext.clearRect(0, 0, self.canvas.width, self.canvas.height);
- }
- },
- _hasInitialPreview: function () {
- var self = this;
- return !self.overwriteInitial && self.previewCache.count();
- },
- _resetPreview: function () {
- var self = this, out, cap;
- if (self.previewCache.count()) {
- out = self.previewCache.out();
- self.$preview.html(out.content);
- self._setInitThumbAttr();
- cap = self.initialCaption ? self.initialCaption : out.caption;
- self._setCaption(cap);
- } else {
- self._clearPreview();
- self._initCaption();
- }
- if (self.showPreview) {
- self._initZoom();
- self._initSortable();
- }
- },
- _clearDefaultPreview: function () {
- var self = this;
- self.$preview.find('.file-default-preview').remove();
- },
- _validateDefaultPreview: function () {
- var self = this;
- if (!self.showPreview || $h.isEmpty(self.defaultPreviewContent)) {
- return;
- }
- self.$preview.html('<div class="file-default-preview">' + self.defaultPreviewContent + '</div>');
- self.$container.removeClass('file-input-new');
- self._initClickable();
- },
- _resetPreviewThumbs: function (isAjax) {
- var self = this, out;
- if (isAjax) {
- self._clearPreview();
- self.clearStack();
- return;
- }
- if (self._hasInitialPreview()) {
- out = self.previewCache.out();
- self.$preview.html(out.content);
- self._setInitThumbAttr();
- self._setCaption(out.caption);
- self._initPreviewActions();
- } else {
- self._clearPreview();
- }
- },
- _getLayoutTemplate: function (t) {
- var self = this, template = self.layoutTemplates[t];
- if ($h.isEmpty(self.customLayoutTags)) {
- return template;
- }
- return $h.replaceTags(template, self.customLayoutTags);
- },
- _getPreviewTemplate: function (t) {
- var self = this, template = self.previewTemplates[t];
- if ($h.isEmpty(self.customPreviewTags)) {
- return template;
- }
- return $h.replaceTags(template, self.customPreviewTags);
- },
- _getOutData: function (jqXHR, responseData, filesData) {
- var self = this;
- jqXHR = jqXHR || {};
- responseData = responseData || {};
- filesData = filesData || self.filestack.slice(0) || {};
- return {
- form: self.formdata,
- files: filesData,
- filenames: self.filenames,
- filescount: self.getFilesCount(),
- extra: self._getExtraData(),
- response: responseData,
- reader: self.reader,
- jqXHR: jqXHR
- };
- },
- _getMsgSelected: function (n) {
- var self = this, strFiles = n === 1 ? self.fileSingle : self.filePlural;
- return n > 0 ? self.msgSelected.replace('{n}', n).replace('{files}', strFiles) : self.msgNoFilesSelected;
- },
- _getFrame: function (id) {
- var self = this, $frame = $('#' + id);
- if (!$frame.length) {
- self._log('Invalid thumb frame with id: "' + id + '".');
- return null;
- }
- return $frame;
- },
- _getThumbs: function (css) {
- css = css || '';
- return this.getFrames(':not(.file-preview-initial)' + css);
- },
- _getExtraData: function (previewId, index) {
- var self = this, data = self.uploadExtraData;
- if (typeof self.uploadExtraData === "function") {
- data = self.uploadExtraData(previewId, index);
- }
- return data;
- },
- _initXhr: function (xhrobj, previewId, fileCount) {
- var self = this;
- if (xhrobj.upload) {
- xhrobj.upload.addEventListener('progress', function (event) {
- var pct = 0, total = event.total, position = event.loaded || event.position;
- /** @namespace event.lengthComputable */
- if (event.lengthComputable) {
- pct = Math.floor(position / total * 100);
- }
- if (previewId) {
- self._setAsyncUploadStatus(previewId, pct, fileCount);
- } else {
- self._setProgress(pct);
- }
- }, false);
- }
- return xhrobj;
- },
- _ajaxSubmit: function (fnBefore, fnSuccess, fnComplete, fnError, previewId, index) {
- var self = this, settings;
- if (!self._raise('filepreajax', [previewId, index])) {
- return;
- }
- self._uploadExtra(previewId, index);
- settings = $.extend(true, {}, {
- xhr: function () {
- var xhrobj = $.ajaxSettings.xhr();
- return self._initXhr(xhrobj, previewId, self.getFileStack().length);
- },
- url: self.uploadUrl,
- type: 'POST',
- dataType: 'json',
- data: self.formdata,
- cache: false,
- processData: false,
- contentType: false,
- beforeSend: fnBefore,
- success: fnSuccess,
- complete: fnComplete,
- error: fnError
- }, self.ajaxSettings);
- self.ajaxRequests.push($.ajax(settings));
- },
- _mergeArray: function (prop, content) {
- var self = this, arr1 = $h.cleanArray(self[prop]), arr2 = $h.cleanArray(content);
- self[prop] = arr1.concat(arr2);
- },
- _initUploadSuccess: function (out, $thumb, allFiles) {
- var self = this, append, data, index, $div, $newCache, content, config, tags, i;
- if (!self.showPreview || typeof out !== 'object' || $.isEmptyObject(out)) {
- return;
- }
- if (out.initialPreview !== undefined && out.initialPreview.length > 0) {
- self.hasInitData = true;
- content = out.initialPreview || [];
- config = out.initialPreviewConfig || [];
- tags = out.initialPreviewThumbTags || [];
- append = out.append === undefined || out.append ? true : false;
- if (content.length > 0 && !$h.isArray(content)) {
- content = content.split(self.initialPreviewDelimiter);
- }
- self._mergeArray('initialPreview', content);
- self._mergeArray('initialPreviewConfig', config);
- self._mergeArray('initialPreviewThumbTags', tags);
- if ($thumb !== undefined) {
- if (!allFiles) {
- index = self.previewCache.add(content, config[0], tags[0], append);
- data = self.previewCache.get(index, false);
- $div = $(document.createElement('div')).html(data).hide().insertAfter($thumb);
- $newCache = $div.find('.kv-zoom-cache');
- if ($newCache && $newCache.length) {
- $newCache.insertAfter($thumb);
- }
- $thumb.fadeOut('slow', function () {
- var $newThumb = $div.find('.file-preview-frame');
- if ($newThumb && $newThumb.length) {
- $newThumb.insertBefore($thumb).fadeIn('slow').css('display:inline-block');
- }
- self._initPreviewActions();
- self._clearFileInput();
- $h.cleanZoomCache(self.$preview.find('#zoom-' + $thumb.attr('id')));
- $thumb.remove();
- $div.remove();
- self._initSortable();
- });
- } else {
- i = $thumb.attr('data-fileindex');
- self.uploadCache.content[i] = content[0];
- self.uploadCache.config[i] = config[0] || [];
- self.uploadCache.tags[i] = tags[0] || [];
- self.uploadCache.append = append;
- }
- } else {
- self.previewCache.set(content, config, tags, append);
- self._initPreview();
- self._initPreviewActions();
- }
- }
- },
- _initSuccessThumbs: function () {
- var self = this;
- if (!self.showPreview) {
- return;
- }
- self._getThumbs($h.FRAMES + '.file-preview-success').each(function () {
- var $thumb = $(this), $preview = self.$preview, $remove = $thumb.find('.kv-file-remove');
- $remove.removeAttr('disabled');
- self._handler($remove, 'click', function () {
- var id = $thumb.attr('id'),
- out = self._raise('filesuccessremove', [id, $thumb.attr('data-fileindex')]);
- $h.cleanMemory($thumb);
- if (out === false) {
- return;
- }
- $thumb.fadeOut('slow', function () {
- $h.cleanZoomCache($preview.find('#zoom-' + id));
- $thumb.remove();
- if (!self.getFrames().length) {
- self.reset();
- }
- });
- });
- });
- },
- _checkAsyncComplete: function () {
- var self = this, previewId, i;
- for (i = 0; i < self.filestack.length; i++) {
- if (self.filestack[i]) {
- previewId = self.previewInitId + "-" + i;
- if ($.inArray(previewId, self.uploadLog) === -1) {
- return false;
- }
- }
- }
- return (self.uploadAsyncCount === self.uploadLog.length);
- },
- _uploadExtra: function (previewId, index) {
- var self = this, data = self._getExtraData(previewId, index);
- if (data.length === 0) {
- return;
- }
- $.each(data, function (key, value) {
- self.formdata.append(key, value);
- });
- },
- _uploadSingle: function (i, files, allFiles) {
- var self = this, total = self.getFileStack().length, formdata = new FormData(), outData,
- previewId = self.previewInitId + "-" + i, $thumb, chkComplete, $btnUpload, $btnDelete,
- hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
- $prog = $('#' + previewId).find('.file-thumb-progress'),
- fnBefore, fnSuccess, fnComplete, fnError, updateUploadLog, params = {id: previewId, index: i},
- uploadFailed, multiUploadMode = !$h.isEmpty(self.$element.attr('multiple'));
- self.formdata = formdata;
- if (self.showPreview) {
- $thumb = $('#' + previewId + ':not(.file-preview-initial)');
- $btnUpload = $thumb.find('.kv-file-upload');
- $btnDelete = $thumb.find('.kv-file-remove');
- $prog.removeClass('hide');
- }
- if (total === 0 || !hasPostData || ($btnUpload && $btnUpload.hasClass('disabled')) || self._abort(params)) {
- return;
- }
- updateUploadLog = function (i, previewId) {
- if (multiUploadMode || !uploadFailed) {
- self.updateStack(i, undefined);
- }
- self.uploadLog.push(previewId);
- if (self._checkAsyncComplete()) {
- self.fileBatchCompleted = true;
- }
- };
- chkComplete = function () {
- var u = self.uploadCache, $initThumbs, i, j, len = 0, data = self.cacheInitialPreview;
- if (!self.fileBatchCompleted) {
- return;
- }
- if (data && data.content) {
- len = data.content.length;
- }
- setTimeout(function () {
- var triggerReset = multiUploadMode || !uploadFailed;
- if (self.showPreview) {
- self.previewCache.set(u.content, u.config, u.tags, u.append);
- if (len) {
- for (i = 0; i < u.content.length; i++) {
- j = i + len;
- data.content[j] = u.content[i];
- //noinspection JSUnresolvedVariable
- if (data.config.length) {
- data.config[j] = u.config[i];
- }
- if (data.tags.length) {
- data.tags[j] = u.tags[i];
- }
- }
- self.initialPreview = $h.cleanArray(data.content);
- self.initialPreviewConfig = $h.cleanArray(data.config);
- self.initialPreviewThumbTags = $h.cleanArray(data.tags);
- } else {
- self.initialPreview = u.content;
- self.initialPreviewConfig = u.config;
- self.initialPreviewThumbTags = u.tags;
- }
- self.cacheInitialPreview = {};
- if (self.hasInitData) {
- self._initPreview();
- self._initPreviewActions();
- }
- }
- self.unlock(triggerReset);
- if (triggerReset) {
- self._clearFileInput();
- }
- $initThumbs = self.$preview.find('.file-preview-initial');
- if (self.uploadAsync && $initThumbs.length) {
- $h.addCss($initThumbs, $h.SORT_CSS);
- self._initSortable();
- }
- self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
- self.uploadCount = 0;
- self.uploadStatus = {};
- self.uploadLog = [];
- self._setProgress(101);
- }, 100);
- };
- fnBefore = function (jqXHR) {
- outData = self._getOutData(jqXHR);
- self.fileBatchCompleted = false;
- if (self.showPreview) {
- if (!$thumb.hasClass('file-preview-success')) {
- self._setThumbStatus($thumb, 'Loading');
- $h.addCss($thumb, 'file-uploading');
- }
- $btnUpload.attr('disabled', true);
- $btnDelete.attr('disabled', true);
- }
- if (!allFiles) {
- self.lock();
- }
- self._raise('filepreupload', [outData, previewId, i]);
- $.extend(true, params, outData);
- if (self._abort(params)) {
- jqXHR.abort();
- self._setProgressCancelled();
- }
- };
- fnSuccess = function (data, textStatus, jqXHR) {
- var pid = self.showPreview && $thumb.attr('id') ? $thumb.attr('id') : previewId;
- outData = self._getOutData(jqXHR, data);
- $.extend(true, params, outData);
- setTimeout(function () {
- if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
- if (self.showPreview) {
- self._setThumbStatus($thumb, 'Success');
- $btnUpload.hide();
- self._initUploadSuccess(data, $thumb, allFiles);
- self._setProgress(101, $prog);
- }
- self._raise('fileuploaded', [outData, pid, i]);
- if (!allFiles) {
- self.updateStack(i, undefined);
- } else {
- updateUploadLog(i, pid);
- }
- } else {
- uploadFailed = true;
- self._showUploadError(data.error, params);
- self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
- if (allFiles) {
- updateUploadLog(i, pid);
- }
- }
- }, 100);
- };
- fnComplete = function () {
- setTimeout(function () {
- if (self.showPreview) {
- $btnUpload.removeAttr('disabled');
- $btnDelete.removeAttr('disabled');
- $thumb.removeClass('file-uploading');
- }
- if (!allFiles) {
- self.unlock(false);
- self._clearFileInput();
- } else {
- chkComplete();
- }
- self._initSuccessThumbs();
- }, 100);
- };
- fnError = function (jqXHR, textStatus, errorThrown) {
- var op = self.ajaxOperations.uploadThumb,
- errMsg = self._parseError(op, jqXHR, errorThrown, (allFiles ? files[i].name : null));
- uploadFailed = true;
- setTimeout(function () {
- if (allFiles) {
- updateUploadLog(i, previewId);
- }
- self.uploadStatus[previewId] = 100;
- self._setPreviewError($thumb, i, (multiUploadMode ? null : self.filestack[i]));
- $.extend(true, params, self._getOutData(jqXHR));
- self._setProgress(101, $prog, self.msgAjaxProgressError.replace('{operation}', op));
- self._showUploadError(errMsg, params);
- }, 100);
- };
- formdata.append(self.uploadFileAttr, files[i], self.filenames[i]);
- formdata.append('file_id', i);
- self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i);
- },
- _uploadBatch: function () {
- var self = this, files = self.filestack, total = files.length, params = {}, fnBefore, fnSuccess, fnError,
- fnComplete, hasPostData = self.filestack.length > 0 || !$.isEmptyObject(self.uploadExtraData),
- setAllUploaded;
- self.formdata = new FormData();
- if (total === 0 || !hasPostData || self._abort(params)) {
- return;
- }
- setAllUploaded = function () {
- $.each(files, function (key) {
- self.updateStack(key, undefined);
- });
- self._clearFileInput();
- };
- fnBefore = function (jqXHR) {
- self.lock();
- var outData = self._getOutData(jqXHR);
- if (self.showPreview) {
- self._getThumbs().each(function () {
- var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload'),
- $btnDelete = $thumb.find('.kv-file-remove');
- if (!$thumb.hasClass('file-preview-success')) {
- self._setThumbStatus($thumb, 'Loading');
- $h.addCss($thumb, 'file-uploading');
- }
- $btnUpload.attr('disabled', true);
- $btnDelete.attr('disabled', true);
- });
- }
- self._raise('filebatchpreupload', [outData]);
- if (self._abort(outData)) {
- jqXHR.abort();
- self._setProgressCancelled();
- }
- };
- fnSuccess = function (data, textStatus, jqXHR) {
- /** @namespace data.errorkeys */
- var outData = self._getOutData(jqXHR, data), $thumbs = self._getThumbs(':not(.file-preview-error)'),
- key = 0,
- keys = $h.isEmpty(data) || $h.isEmpty(data.errorkeys) ? [] : data.errorkeys;
- if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
- self._raise('filebatchuploadsuccess', [outData]);
- setAllUploaded();
- if (self.showPreview) {
- $thumbs.each(function () {
- var $thumb = $(this), $btnUpload = $thumb.find('.kv-file-upload');
- $thumb.find('.kv-file-upload').hide();
- self._setThumbStatus($thumb, 'Success');
- $thumb.removeClass('file-uploading');
- $btnUpload.removeAttr('disabled');
- });
- self._initUploadSuccess(data);
- } else {
- self.reset();
- }
- self._setProgress(101);
- } else {
- if (self.showPreview) {
- $thumbs.each(function () {
- var $thumb = $(this), $btnDelete = $thumb.find('.kv-file-remove'),
- $btnUpload = $thumb.find('.kv-file-upload');
- $thumb.removeClass('file-uploading');
- $btnUpload.removeAttr('disabled');
- $btnDelete.removeAttr('disabled');
- if (keys.length === 0) {
- self._setPreviewError($thumb);
- return;
- }
- if ($.inArray(key, keys) !== -1) {
- self._setPreviewError($thumb);
- } else {
- $thumb.find('.kv-file-upload').hide();
- self._setThumbStatus($thumb, 'Success');
- self.updateStack(key, undefined);
- }
- key++;
- });
- self._initUploadSuccess(data);
- }
- self._showUploadError(data.error, outData, 'filebatchuploaderror');
- }
- };
- fnComplete = function () {
- self.unlock();
- self._initSuccessThumbs();
- self._clearFileInput();
- self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
- };
- fnError = function (jqXHR, textStatus, errorThrown) {
- var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadBatch,
- errMsg = self._parseError(op, jqXHR, errorThrown);
- self._showUploadError(errMsg, outData, 'filebatchuploaderror');
- self.uploadFileCount = total - 1;
- if (!self.showPreview) {
- return;
- }
- self._getThumbs().each(function () {
- var $thumb = $(this), key = $thumb.attr('data-fileindex');
- $thumb.removeClass('file-uploading');
- if (self.filestack[key] !== undefined) {
- self._setPreviewError($thumb);
- }
- });
- self._getThumbs().removeClass('file-uploading');
- self._getThumbs(' .kv-file-upload').removeAttr('disabled');
- self._getThumbs(' .kv-file-delete').removeAttr('disabled');
- self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
- };
- $.each(files, function (key, data) {
- if (!$h.isEmpty(files[key])) {
- self.formdata.append(self.uploadFileAttr, data, self.filenames[key]);
- }
- });
- self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
- },
- _uploadExtraOnly: function () {
- var self = this, params = {}, fnBefore, fnSuccess, fnComplete, fnError;
- self.formdata = new FormData();
- if (self._abort(params)) {
- return;
- }
- fnBefore = function (jqXHR) {
- self.lock();
- var outData = self._getOutData(jqXHR);
- self._raise('filebatchpreupload', [outData]);
- self._setProgress(50);
- params.data = outData;
- params.xhr = jqXHR;
- if (self._abort(params)) {
- jqXHR.abort();
- self._setProgressCancelled();
- }
- };
- fnSuccess = function (data, textStatus, jqXHR) {
- var outData = self._getOutData(jqXHR, data);
- if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
- self._raise('filebatchuploadsuccess', [outData]);
- self._clearFileInput();
- self._initUploadSuccess(data);
- self._setProgress(101);
- } else {
- self._showUploadError(data.error, outData, 'filebatchuploaderror');
- }
- };
- fnComplete = function () {
- self.unlock();
- self._clearFileInput();
- self._raise('filebatchuploadcomplete', [self.filestack, self._getExtraData()]);
- };
- fnError = function (jqXHR, textStatus, errorThrown) {
- var outData = self._getOutData(jqXHR), op = self.ajaxOperations.uploadExtra,
- errMsg = self._parseError(op, jqXHR, errorThrown);
- params.data = outData;
- self._showUploadError(errMsg, outData, 'filebatchuploaderror');
- self._setProgress(101, self.$progress, self.msgAjaxProgressError.replace('{operation}', op));
- };
- self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError);
- },
- _deleteFileIndex: function ($frame) {
- var self = this, ind = $frame.attr('data-fileindex');
- if (ind.substring(0, 5) === 'init_') {
- ind = parseInt(ind.replace('init_', ''));
- self.initialPreview = $h.spliceArray(self.initialPreview, ind);
- self.initialPreviewConfig = $h.spliceArray(self.initialPreviewConfig, ind);
- self.initialPreviewThumbTags = $h.spliceArray(self.initialPreviewThumbTags, ind);
- self.getFrames().each(function () {
- var $nFrame = $(this), nInd = $nFrame.attr('data-fileindex');
- if (nInd.substring(0, 5) === 'init_') {
- nInd = parseInt(nInd.replace('init_', ''));
- if (nInd > ind) {
- nInd--;
- $nFrame.attr('data-fileindex', 'init_' + nInd);
- }
- }
- });
- if (self.uploadAsync) {
- self.cacheInitialPreview = self.getPreview();
- }
- }
- },
- _initFileActions: function () {
- var self = this, $preview = self.$preview;
- if (!self.showPreview) {
- return;
- }
- self._initZoomButton();
- self.getFrames(' .kv-file-remove').each(function () {
- var $el = $(this), $frame = $el.closest($h.FRAMES), hasError, id = $frame.attr('id'),
- ind = $frame.attr('data-fileindex'), n, cap, status;
- self._handler($el, 'click', function () {
- status = self._raise('filepreremove', [id, ind]);
- if (status === false || !self._validateMinCount()) {
- return false;
- }
- hasError = $frame.hasClass('file-preview-error');
- $h.cleanMemory($frame);
- $frame.fadeOut('slow', function () {
- $h.cleanZoomCache($preview.find('#zoom-' + id));
- self.updateStack(ind, undefined);
- self._clearObjects($frame);
- $frame.remove();
- if (id && hasError) {
- self.$errorContainer.find('li[data-file-id="' + id + '"]').fadeOut('fast', function () {
- $(this).remove();
- if (!self._errorsExist()) {
- self._resetErrors();
- }
- });
- }
- self._clearFileInput();
- var filestack = self.getFileStack(true), chk = self.previewCache.count(),
- len = filestack.length, hasThumb = self.showPreview && self.getFrames().length;
- if (len === 0 && chk === 0 && !hasThumb) {
- self.reset();
- } else {
- n = chk + len;
- cap = n > 1 ? self._getMsgSelected(n) : (filestack[0] ? self._getFileNames()[0] : '');
- self._setCaption(cap);
- }
- self._raise('fileremoved', [id, ind]);
- });
- });
- });
- self.getFrames(' .kv-file-upload').each(function () {
- var $el = $(this);
- self._handler($el, 'click', function () {
- var $frame = $el.closest($h.FRAMES), ind = $frame.attr('data-fileindex');
- if (!$frame.hasClass('file-preview-error')) {
- self._uploadSingle(ind, self.filestack, false);
- }
- });
- });
- },
- _initPreviewActions: function () {
- var self = this, $preview = self.$preview, deleteExtraData = self.deleteExtraData || {},
- btnRemove = $h.FRAMES + ' .kv-file-remove',
- resetProgress = function () {
- var hasFiles = self.isUploadable ? self.previewCache.count() : self.$element.get(0).files.length;
- if ($preview.find(btnRemove).length === 0 && !hasFiles) {
- self.reset();
- self.initialCaption = '';
- }
- };
- self._initZoomButton();
- $preview.find(btnRemove).each(function () {
- var $el = $(this), vUrl = $el.data('url') || self.deleteUrl, vKey = $el.data('key');
- if ($h.isEmpty(vUrl) || vKey === undefined) {
- return;
- }
- var $frame = $el.closest($h.FRAMES), cache = self.previewCache.data,
- settings, params, index = $frame.attr('data-fileindex'), config, extraData;
- index = parseInt(index.replace('init_', ''));
- config = $h.isEmpty(cache.config) && $h.isEmpty(cache.config[index]) ? null : cache.config[index];
- extraData = $h.isEmpty(config) || $h.isEmpty(config.extra) ? deleteExtraData : config.extra;
- if (typeof extraData === "function") {
- extraData = extraData();
- }
- params = {id: $el.attr('id'), key: vKey, extra: extraData};
- settings = $.extend(true, {}, {
- url: vUrl,
- type: 'POST',
- dataType: 'json',
- data: $.extend(true, {}, {key: vKey}, extraData),
- beforeSend: function (jqXHR) {
- self.ajaxAborted = false;
- self._raise('filepredelete', [vKey, jqXHR, extraData]);
- if (self.ajaxAborted) {
- jqXHR.abort();
- } else {
- $h.addCss($frame, 'file-uploading');
- $h.addCss($el, 'disabled');
- }
- },
- success: function (data, textStatus, jqXHR) {
- var n, cap;
- if ($h.isEmpty(data) || $h.isEmpty(data.error)) {
- index = parseInt(($frame.attr('data-fileindex')).replace('init_', ''));
- self.previewCache.unset(index);
- n = self.previewCache.count();
- cap = n > 0 ? self._getMsgSelected(n) : '';
- self._deleteFileIndex($frame);
- self._setCaption(cap);
- self._raise('filedeleted', [vKey, jqXHR, extraData]);
- } else {
- params.jqXHR = jqXHR;
- params.response = data;
- self._showError(data.error, params, 'filedeleteerror');
- $frame.removeClass('file-uploading');
- $el.removeClass('disabled');
- resetProgress();
- return;
- }
- $frame.removeClass('file-uploading').addClass('file-deleted');
- $frame.fadeOut('slow', function () {
- $h.cleanZoomCache($preview.find('#zoom-' + $frame.attr('id')));
- self._clearObjects($frame);
- $frame.remove();
- resetProgress();
- if (!n && self.getFileStack().length === 0) {
- self._setCaption('');
- self.reset();
- }
- });
- },
- error: function (jqXHR, textStatus, errorThrown) {
- var op = self.ajaxOperations.deleteThumb, errMsg = self._parseError(op, jqXHR, errorThrown);
- params.jqXHR = jqXHR;
- params.response = {};
- self._showError(errMsg, params, 'filedeleteerror');
- $frame.removeClass('file-uploading');
- resetProgress();
- }
- }, self.ajaxDeleteSettings);
- self._handler($el, 'click', function () {
- if (!self._validateMinCount()) {
- return false;
- }
- $.ajax(settings);
- });
- });
- },
- _hideFileIcon: function () {
- if (this.overwriteInitial) {
- this.$captionContainer.find('.kv-caption-icon').hide();
- }
- },
- _showFileIcon: function () {
- this.$captionContainer.find('.kv-caption-icon').show();
- },
- _getSize: function (bytes) {
- var self = this, size = parseFloat(bytes), i, func = self.fileSizeGetter, sizes, out;
- if (!$.isNumeric(bytes) || !$.isNumeric(size)) {
- return '';
- }
- if (typeof func === 'function') {
- out = func(size);
- } else {
- if (size === 0) {
- out = '0.00 B';
- } else {
- i = Math.floor(Math.log(size) / Math.log(1024));
- sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
- out = (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + sizes[i];
- }
- }
- return self._getLayoutTemplate('size').replace('{sizeText}', out);
- },
- _generatePreviewTemplate: function (cat, data, fname, ftype, previewId, isError, size, frameClass, foot, ind, templ) {
- var self = this, caption = self.slug(fname), prevContent, zoomContent = '',
- config = self.previewSettings[cat] || self.defaults.previewSettings[cat],
- w = config && config.width ? config.width : '', h = config && config.height ? config.height : '',
- footer = foot || self._renderFileFooter(caption, size, ($h.isEmpty(w) ? 'auto' : w), isError),
- hasIconSetting = self._getPreviewIcon(fname), typeCss = 'type-default',
- forcePrevIcon = hasIconSetting && self.preferIconicPreview,
- forceZoomIcon = hasIconSetting && self.preferIconicZoomPreview,
- getContent = function (c, d, zoom, frameCss) {
- var id = zoom ? 'zoom-' + previewId : previewId, tmplt = self._getPreviewTemplate(c),
- css = (frameClass || '') + ' ' + frameCss;
- if (self.frameClass) {
- css = self.frameClass + ' ' + css;
- }
- if (zoom) {
- css = css.replace(' ' + $h.SORT_CSS, '');
- }
- tmplt = self._parseFilePreviewIcon(tmplt, fname);
- if (c === 'text') {
- d = $h.htmlEncode(d);
- }
- if (cat === 'object' && !ftype) {
- $.each(self.defaults.fileTypeSettings, function (key, func) {
- if (key === 'object' || key === 'other') {
- return;
- }
- if (func(fname, ftype)) {
- typeCss = 'type-' + key;
- }
- });
- }
- return tmplt.setTokens({
- 'previewId': id,
- 'caption': caption,
- 'frameClass': css,
- 'type': ftype,
- 'fileindex': ind,
- 'width': w,
- 'height': h,
- 'typeCss': typeCss,
- 'footer': footer,
- 'data': d,
- 'template': templ || cat
- });
- };
- ind = ind || previewId.slice(previewId.lastIndexOf('-') + 1);
- if (self.fileActionSettings.showZoom) {
- zoomContent = getContent((forceZoomIcon ? 'other' : cat), data, true, 'kv-zoom-thumb');
- }
- zoomContent = '\n' + self._getLayoutTemplate('zoomCache').replace('{zoomContent}', zoomContent);
- prevContent = getContent((forcePrevIcon ? 'other' : cat), data, false, 'kv-preview-thumb');
- return prevContent + zoomContent;
- },
- _previewDefault: function (file, previewId, isDisabled) {
- var self = this, $preview = self.$preview;
- if (!self.showPreview) {
- return;
- }
- var fname = file ? file.name : '', ftype = file ? file.type : '', content, size = file.size || 0,
- caption = self.slug(fname), isError = isDisabled === true && !self.isUploadable,
- data = $h.objUrl.createObjectURL(file);
- self._clearDefaultPreview();
- content = self._generatePreviewTemplate('other', data, fname, ftype, previewId, isError, size);
- $preview.append("\n" + content);
- self._setThumbAttr(previewId, caption, size);
- if (isDisabled === true && self.isUploadable) {
- self._setThumbStatus($('#' + previewId), 'Error');
- }
- },
- _previewFile: function (i, file, theFile, previewId, data) {
- if (!this.showPreview) {
- return;
- }
- var self = this, cat = self._parseFileType(file), fname = file ? file.name : '', caption = self.slug(fname),
- types = self.allowedPreviewTypes, mimes = self.allowedPreviewMimeTypes, $preview = self.$preview,
- chkTypes = types && types.indexOf(cat) >= 0, fsize = file.size || 0, ftype = file.type,
- iData = (cat === 'text' || cat === 'html' || cat === 'image') ? theFile.target.result : data, content,
- chkMimes = mimes && mimes.indexOf(ftype) !== -1;
- /** @namespace window.DOMPurify */
- if (cat === 'html' && self.purifyHtml && window.DOMPurify) {
- iData = window.DOMPurify.sanitize(iData);
- }
- if (chkTypes || chkMimes) {
- content = self._generatePreviewTemplate(cat, iData, fname, ftype, previewId, false, fsize);
- self._clearDefaultPreview();
- $preview.append("\n" + content);
- var $img = $preview.find('#' + previewId + ' img');
- if ($img.length && self.autoOrientImage) {
- $h.validateOrientation(file, function (value) {
- if (value) {
- var $zoomImg = $preview.find('#zoom-' + previewId + ' img'), css = 'rotate-' + value;
- if (value > 4) {
- css += ($img.width() > $img.height() ? ' is-portrait-gt4' : ' is-landscape-gt4');
- }
- $h.addCss($img, css);
- $h.addCss($zoomImg, css);
- self._raise('fileimageoriented', {'$img': $img, 'file': file});
- }
- self._validateImage(previewId, caption, ftype, fsize, iData);
- $h.adjustOrientedImage($img);
- });
- } else {
- self._validateImage(previewId, caption, ftype, fsize, iData);
- }
- } else {
- self._previewDefault(file, previewId);
- }
- self._setThumbAttr(previewId, caption, fsize);
- self._initSortable();
- },
- _setThumbAttr: function (id, caption, size) {
- var self = this, $frame = $('#' + id);
- if ($frame.length) {
- size = size && size > 0 ? self._getSize(size) : '';
- $frame.data({'caption': caption, 'size': size});
- }
- },
- _setInitThumbAttr: function () {
- var self = this, data = self.previewCache.data, len = self.previewCache.count(true), config,
- caption, size, previewId;
- if (len === 0) {
- return;
- }
- for (var i = 0; i < len; i++) {
- config = data.config[i];
- previewId = self.previewInitId + '-' + 'init_' + i;
- caption = $h.ifSet('caption', config, $h.ifSet('filename', config));
- size = $h.ifSet('size', config);
- self._setThumbAttr(previewId, caption, size);
- }
- },
- _slugDefault: function (text) {
- return $h.isEmpty(text) ? '' : String(text).replace(/[\-\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g, '_');
- },
- _readFiles: function (files) {
- this.reader = new FileReader();
- var self = this, $el = self.$element, $preview = self.$preview, reader = self.reader,
- $container = self.$previewContainer, $status = self.$previewStatus, msgLoading = self.msgLoading,
- msgProgress = self.msgProgress, previewInitId = self.previewInitId, numFiles = files.length,
- settings = self.fileTypeSettings, ctr = self.filestack.length, readFile,
- fileTypes = self.allowedFileTypes, typLen = fileTypes ? fileTypes.length : 0,
- fileExt = self.allowedFileExtensions, strExt = $h.isEmpty(fileExt) ? '' : fileExt.join(', '),
- maxPreviewSize = self.maxFilePreviewSize && parseFloat(self.maxFilePreviewSize),
- canPreview = $preview.length && (!maxPreviewSize || isNaN(maxPreviewSize)),
- throwError = function (msg, file, previewId, index) {
- var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
- p2 = {id: previewId, index: index, file: file, files: files};
- self._previewDefault(file, previewId, true);
- if (self.isUploadable) {
- self.addToStack(undefined);
- setTimeout(function () {
- readFile(index + 1);
- }, 100);
- }
- self._initFileActions();
- if (self.removeFromPreviewOnError) {
- $('#' + previewId).remove();
- }
- return self.isUploadable ? self._showUploadError(msg, p1) : self._showError(msg, p2);
- };
- self.loadedImages = [];
- self.totalImagesCount = 0;
- $.each(files, function (key, file) {
- var func = self.fileTypeSettings.image;
- if (func && func(file.type)) {
- self.totalImagesCount++;
- }
- });
- readFile = function (i) {
- if ($h.isEmpty($el.attr('multiple'))) {
- numFiles = 1;
- }
- if (i >= numFiles) {
- if (self.isUploadable && self.filestack.length > 0) {
- self._raise('filebatchselected', [self.getFileStack()]);
- } else {
- self._raise('filebatchselected', [files]);
- }
- $container.removeClass('file-thumb-loading');
- $status.html('');
- return;
- }
- var node = ctr + i, previewId = previewInitId + "-" + node, isText, isImage, file = files[i], fSizeKB,
- caption = file.name ? self.slug(file.name) : '', fileSize = (file.size || 0) / 1000, j, msg,
- fileExtExpr = '', previewData = $h.objUrl.createObjectURL(file), typ, chk, typ1, typ2,
- fileCount = 0, strTypes = '', func;
- if (typLen > 0) {
- for (j = 0; j < typLen; j++) {
- typ1 = fileTypes[j];
- typ2 = self.msgFileTypes[typ1] || typ1;
- strTypes += j === 0 ? typ2 : ', ' + typ2;
- }
- }
- if (caption === false) {
- readFile(i + 1);
- return;
- }
- if (caption.length === 0) {
- msg = self.msgInvalidFileName.replace('{name}', $h.htmlEncode(file.name));
- self.isError = throwError(msg, file, previewId, i);
- return;
- }
- if (!$h.isEmpty(fileExt)) {
- fileExtExpr = new RegExp('\\.(' + fileExt.join('|') + ')$', 'i');
- }
- fSizeKB = fileSize.toFixed(2);
- if (self.maxFileSize > 0 && fileSize > self.maxFileSize) {
- msg = self.msgSizeTooLarge.setTokens({
- 'name': caption,
- 'size': fSizeKB,
- 'maxSize': self.maxFileSize
- });
- self.isError = throwError(msg, file, previewId, i);
- return;
- }
- if (self.minFileSize !== null && fileSize <= $h.getNum(self.minFileSize)) {
- msg = self.msgSizeTooSmall.setTokens({
- 'name': caption,
- 'size': fSizeKB,
- 'minSize': self.minFileSize
- });
- self.isError = throwError(msg, file, previewId, i);
- return;
- }
- if (!$h.isEmpty(fileTypes) && $h.isArray(fileTypes)) {
- for (j = 0; j < fileTypes.length; j += 1) {
- typ = fileTypes[j];
- func = settings[typ];
- fileCount += !func || (typeof func !== 'function') ? 0 : (func(file.type, file.name) ? 1 : 0);
- }
- if (fileCount === 0) {
- msg = self.msgInvalidFileType.setTokens({'name': caption, 'types': strTypes});
- self.isError = throwError(msg, file, previewId, i);
- return;
- }
- }
- if (fileCount === 0 && !$h.isEmpty(fileExt) && $h.isArray(fileExt) && !$h.isEmpty(fileExtExpr)) {
- chk = $h.compare(caption, fileExtExpr);
- fileCount += $h.isEmpty(chk) ? 0 : chk.length;
- if (fileCount === 0) {
- msg = self.msgInvalidFileExtension.setTokens({'name': caption, 'extensions': strExt});
- self.isError = throwError(msg, file, previewId, i);
- return;
- }
- }
- if (!self.showPreview) {
- if (self.isUploadable) {
- self.addToStack(file);
- }
- setTimeout(function () {
- readFile(i + 1);
- self._updateFileDetails(numFiles);
- }, 100);
- self._raise('fileloaded', [file, previewId, i, reader]);
- return;
- }
- if (!canPreview && fileSize > maxPreviewSize) {
- self.addToStack(file);
- $container.addClass('file-thumb-loading');
- self._previewDefault(file, previewId);
- self._initFileActions();
- self._updateFileDetails(numFiles);
- readFile(i + 1);
- return;
- }
- if ($preview.length && FileReader !== undefined) {
- $status.html(msgLoading.replace('{index}', i + 1).replace('{files}', numFiles));
- $container.addClass('file-thumb-loading');
- reader.onerror = function (evt) {
- self._errorHandler(evt, caption);
- };
- reader.onload = function (theFile) {
- self._previewFile(i, file, theFile, previewId, previewData);
- self._initFileActions();
- };
- reader.onloadend = function () {
- msg = msgProgress.setTokens({
- 'index': i + 1,
- 'files': numFiles,
- 'percent': 50,
- 'name': caption
- });
- setTimeout(function () {
- $status.html(msg);
- self._updateFileDetails(numFiles);
- readFile(i + 1);
- }, 100);
- self._raise('fileloaded', [file, previewId, i, reader]);
- };
- reader.onprogress = function (data) {
- if (data.lengthComputable) {
- var fact = (data.loaded / data.total) * 100, progress = Math.ceil(fact);
- msg = msgProgress.setTokens({
- 'index': i + 1,
- 'files': numFiles,
- 'percent': progress,
- 'name': caption
- });
- setTimeout(function () {
- $status.html(msg);
- }, 100);
- }
- };
- isText = settings.text;
- isImage = settings.image;
- if (isText(file.type, caption)) {
- reader.readAsText(file, self.textEncoding);
- } else {
- if (isImage(file.type, caption)) {
- reader.readAsDataURL(file);
- } else {
- reader.readAsArrayBuffer(file);
- }
- }
- } else {
- self._previewDefault(file, previewId);
- setTimeout(function () {
- readFile(i + 1);
- self._updateFileDetails(numFiles);
- }, 100);
- self._raise('fileloaded', [file, previewId, i, reader]);
- }
- self.addToStack(file);
- };
- readFile(0);
- self._updateFileDetails(numFiles, false);
- },
- _updateFileDetails: function (numFiles) {
- var self = this, $el = self.$element, fileStack = self.getFileStack(),
- name = ($h.isIE(9) && $h.findFileName($el.val())) ||
- ($el[0].files[0] && $el[0].files[0].name) || (fileStack.length && fileStack[0].name) || '',
- label = self.slug(name), n = self.isUploadable ? fileStack.length : numFiles,
- nFiles = self.previewCache.count() + n, log = n > 1 ? self._getMsgSelected(nFiles) : label;
- if (self.isError) {
- self.$previewContainer.removeClass('file-thumb-loading');
- self.$previewStatus.html('');
- self.$captionContainer.find('.kv-caption-icon').hide();
- } else {
- self._showFileIcon();
- }
- self._setCaption(log, self.isError);
- self.$container.removeClass('file-input-new file-input-ajax-new');
- if (arguments.length === 1) {
- self._raise('fileselect', [numFiles, label]);
- }
- if (self.previewCache.count()) {
- self._initPreviewActions();
- }
- },
- _setThumbStatus: function ($thumb, status) {
- var self = this;
- if (!self.showPreview) {
- return;
- }
- var icon = 'indicator' + status, msg = icon + 'Title',
- css = 'file-preview-' + status.toLowerCase(),
- $indicator = $thumb.find('.file-upload-indicator'),
- config = self.fileActionSettings;
- $thumb.removeClass('file-preview-success file-preview-error file-preview-loading');
- if (status === 'Error') {
- $thumb.find('.kv-file-upload').attr('disabled', true);
- }
- if (status === 'Success') {
- $thumb.find('.file-drag-handle').remove();
- $indicator.css('margin-left', 0);
- }
- $indicator.html(config[icon]);
- $indicator.attr('title', config[msg]);
- $thumb.addClass(css);
- },
- _setProgressCancelled: function () {
- var self = this;
- self._setProgress(101, self.$progress, self.msgCancelled);
- },
- _setProgress: function (p, $el, error) {
- var self = this, pct = Math.min(p, 100), out, pctLimit = self.progressUploadThreshold,
- t = p <= 100 ? self.progressTemplate : self.progressCompleteTemplate,
- template = pct < 100 ? self.progressTemplate : (error ? self.progressErrorTemplate : t);
- $el = $el || self.$progress;
- if (!$h.isEmpty(template)) {
- if (pctLimit && pct > pctLimit && p <= 100) {
- out = template.setTokens({'percent': pctLimit, 'status': self.msgUploadThreshold});
- } else {
- out = template.setTokens({'percent': pct, 'status': (p > 100 ? self.msgUploadEnd : pct + '%')});
- }
- $el.html(out);
- if (error) {
- $el.find('[role="progressbar"]').html(error);
- }
- }
- },
- _setFileDropZoneTitle: function () {
- var self = this, $zone = self.$container.find('.file-drop-zone'), title = self.dropZoneTitle, strFiles;
- if (self.isClickable) {
- strFiles = $h.isEmpty(self.$element.attr('multiple')) ? self.fileSingle : self.filePlural;
- title += self.dropZoneClickTitle.replace('{files}', strFiles);
- }
- $zone.find('.' + self.dropZoneTitleClass).remove();
- if (!self.isUploadable || !self.showPreview || $zone.length === 0 || self.getFileStack().length > 0 || !self.dropZoneEnabled) {
- return;
- }
- if ($zone.find($h.FRAMES).length === 0 && $h.isEmpty(self.defaultPreviewContent)) {
- $zone.prepend('<div class="' + self.dropZoneTitleClass + '">' + title + '</div>');
- }
- self.$container.removeClass('file-input-new');
- $h.addCss(self.$container, 'file-input-ajax-new');
- },
- _setAsyncUploadStatus: function (previewId, pct, total) {
- var self = this, sum = 0;
- self._setProgress(pct, $('#' + previewId).find('.file-thumb-progress'));
- self.uploadStatus[previewId] = pct;
- $.each(self.uploadStatus, function (key, value) {
- sum += value;
- });
- self._setProgress(Math.floor(sum / total));
- },
- _validateMinCount: function () {
- var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
- if (self.validateInitialCount && self.minFileCount > 0 && self._getFileCount(len - 1) < self.minFileCount) {
- self._noFilesError({});
- return false;
- }
- return true;
- },
- _getFileCount: function (fileCount) {
- var self = this, addCount = 0;
- if (self.validateInitialCount && !self.overwriteInitial) {
- addCount = self.previewCache.count();
- fileCount += addCount;
- }
- return fileCount;
- },
- _getFileId: function (file) {
- var self = this, custom = self.generateFileId, relativePath;
- if (typeof custom === 'function') {
- return custom(file, event);
- }
- if (!file) {
- return null;
- }
- /** @namespace file.webkitRelativePath */
- relativePath = file.webkitRelativePath || file.fileName || file.name || null;
- if (!relativePath) {
- return null;
- }
- return (file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''));
- },
- _getFileName: function (file) {
- return file && file.name ? this.slug(file.name) : undefined;
- },
- _getFileIds: function (skipNull) {
- var self = this;
- return self.fileids.filter(function (n) {
- return (skipNull ? n !== undefined : n !== undefined && n !== null);
- });
- },
- _getFileNames: function (skipNull) {
- var self = this;
- return self.filenames.filter(function (n) {
- return (skipNull ? n !== undefined : n !== undefined && n !== null);
- });
- },
- _setPreviewError: function ($thumb, i, val) {
- var self = this;
- if (i !== undefined) {
- self.updateStack(i, val);
- }
- if (self.removeFromPreviewOnError) {
- $thumb.remove();
- } else {
- self._setThumbStatus($thumb, 'Error');
- }
- },
- _checkDimensions: function (i, chk, $img, $thumb, fname, type, params) {
- var self = this, msg, dim, tag = chk === 'Small' ? 'min' : 'max', limit = self[tag + 'Image' + type],
- $imgEl, isValid;
- if ($h.isEmpty(limit) || !$img.length) {
- return;
- }
- $imgEl = $img[0];
- dim = (type === 'Width') ? $imgEl.naturalWidth || $imgEl.width : $imgEl.naturalHeight || $imgEl.height;
- isValid = chk === 'Small' ? dim >= limit : dim <= limit;
- if (isValid) {
- return;
- }
- msg = self['msgImage' + type + chk].setTokens({'name': fname, 'size': limit});
- self._showUploadError(msg, params);
- self._setPreviewError($thumb, i, null);
- },
- _validateImage: function (previewId, fname, ftype, fsize, iData) {
- var self = this, $preview = self.$preview, params, w1, w2, $thumb = $preview.find("#" + previewId),
- i = $thumb.attr('data-fileindex'), $img = $thumb.find('img'), exifObject;
- fname = fname || 'Untitled';
- $img.one('load', function () {
- w1 = $thumb.width();
- w2 = $preview.width();
- if (w1 > w2) {
- $img.css('width', '100%');
- }
- params = {ind: i, id: previewId};
- self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Width', params);
- self._checkDimensions(i, 'Small', $img, $thumb, fname, 'Height', params);
- if (!self.resizeImage) {
- self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Width', params);
- self._checkDimensions(i, 'Large', $img, $thumb, fname, 'Height', params);
- }
- self._raise('fileimageloaded', [previewId]);
- exifObject = window.piexif ? window.piexif.load(iData) : null;
- self.loadedImages.push({
- ind: i,
- img: $img,
- thumb: $thumb,
- pid: previewId,
- typ: ftype,
- siz: fsize,
- validated: false,
- imgData: iData,
- exifObj: exifObject
- });
- $thumb.data('exif', exifObject);
- self._validateAllImages();
- }).one('error', function () {
- self._raise('fileimageloaderror', [previewId]);
- }).each(function () {
- if (this.complete) {
- $(this).trigger('load');
- } else {
- if (this.error) {
- $(this).trigger('error');
- }
- }
- });
- },
- _validateAllImages: function () {
- var self = this, i, counter = {val: 0}, numImgs = self.loadedImages.length, config,
- fsize, minSize = self.resizeIfSizeMoreThan;
- if (numImgs !== self.totalImagesCount) {
- return;
- }
- self._raise('fileimagesloaded');
- if (!self.resizeImage) {
- return;
- }
- for (i = 0; i < self.loadedImages.length; i++) {
- config = self.loadedImages[i];
- if (config.validated) {
- continue;
- }
- fsize = config.siz;
- if (fsize && fsize > minSize * 1000) {
- self._getResizedImage(config, counter, numImgs);
- }
- self.loadedImages[i].validated = true;
- }
- },
- _getResizedImage: function (config, counter, numImgs) {
- var self = this, img = $(config.img)[0], width = img.naturalWidth, height = img.naturalHeight, blob,
- ratio = 1, maxWidth = self.maxImageWidth || width, maxHeight = self.maxImageHeight || height,
- isValidImage = !!(width && height), chkWidth, chkHeight, canvas = self.imageCanvas, dataURI,
- context = self.imageCanvasContext, type = config.typ, pid = config.pid, ind = config.ind,
- $thumb = config.thumb, throwError, msg, exifObj = config.exifObj, exifStr;
- throwError = function (msg, params, ev) {
- if (self.isUploadable) {
- self._showUploadError(msg, params, ev);
- } else {
- self._showError(msg, params, ev);
- }
- self._setPreviewError($thumb, ind);
- };
- if (!self.filestack[ind] || !isValidImage || (width <= maxWidth && height <= maxHeight)) {
- if (isValidImage && self.filestack[ind]) {
- self._raise('fileimageresized', [pid, ind]);
- }
- counter.val++;
- if (counter.val === numImgs) {
- self._raise('fileimagesresized');
- }
- if (!isValidImage) {
- throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
- return;
- }
- }
- type = type || self.resizeDefaultImageType;
- chkWidth = width > maxWidth;
- chkHeight = height > maxHeight;
- if (self.resizePreference === 'width') {
- ratio = chkWidth ? maxWidth / width : (chkHeight ? maxHeight / height : 1);
- } else {
- ratio = chkHeight ? maxHeight / height : (chkWidth ? maxWidth / width : 1);
- }
- self._resetCanvas();
- width *= ratio;
- height *= ratio;
- canvas.width = width;
- canvas.height = height;
- try {
- context.drawImage(img, 0, 0, width, height);
- dataURI = canvas.toDataURL(type, self.resizeQuality);
- if (exifObj) {
- exifStr = window.piexif.dump(exifObj);
- dataURI = window.piexif.insert(exifStr, dataURI);
- }
- blob = $h.dataURI2Blob(dataURI);
- self.filestack[ind] = blob;
- self._raise('fileimageresized', [pid, ind]);
- counter.val++;
- if (counter.val === numImgs) {
- self._raise('fileimagesresized', [undefined, undefined]);
- }
- if (!(blob instanceof Blob)) {
- throwError(self.msgImageResizeError, {id: pid, 'index': ind}, 'fileimageresizeerror');
- }
- }
- catch (err) {
- counter.val++;
- if (counter.val === numImgs) {
- self._raise('fileimagesresized', [undefined, undefined]);
- }
- msg = self.msgImageResizeException.replace('{errors}', err.message);
- throwError(msg, {id: pid, 'index': ind}, 'fileimageresizeexception');
- }
- },
- _initBrowse: function ($container) {
- var self = this;
- if (self.showBrowse) {
- self.$btnFile = $container.find('.btn-file');
- self.$btnFile.append(self.$element);
- } else {
- self.$element.hide();
- }
- },
- _initCaption: function () {
- var self = this, cap = self.initialCaption || '';
- if (self.overwriteInitial || $h.isEmpty(cap)) {
- self.$caption.html('');
- return false;
- }
- self._setCaption(cap);
- return true;
- },
- _setCaption: function (content, isError) {
- var self = this, title, out, n, cap, stack = self.getFileStack();
- if (!self.$caption.length) {
- return;
- }
- if (isError) {
- title = $('<div>' + self.msgValidationError + '</div>').text();
- n = stack.length;
- if (n) {
- cap = n === 1 && stack[0] ? self._getFileNames()[0] : self._getMsgSelected(n);
- } else {
- cap = self._getMsgSelected(self.msgNo);
- }
- out = '<span class="' + self.msgValidationErrorClass + '">' + self.msgValidationErrorIcon +
- ($h.isEmpty(content) ? cap : content) + '</span>';
- } else {
- if ($h.isEmpty(content)) {
- return;
- }
- title = $('<div>' + content + '</div>').text();
- out = self._getLayoutTemplate('fileIcon') + title;
- }
- self.$caption.html(out);
- self.$caption.attr('title', title);
- self.$captionContainer.find('.file-caption-ellipsis').attr('title', title);
- },
- _createContainer: function () {
- var self = this, attribs = {"class": 'file-input file-input-new' + (self.rtl ? ' kv-rtl' : '')},
- $container = $(document.createElement("div")).attr(attribs).html(self._renderMain());
- self.$element.before($container);
- self._initBrowse($container);
- if (self.theme) {
- $container.addClass('theme-' + self.theme);
- }
- return $container;
- },
- _refreshContainer: function () {
- var self = this, $container = self.$container;
- $container.before(self.$element);
- $container.html(self._renderMain());
- self._initBrowse($container);
- },
- _renderMain: function () {
- var self = this,
- dropCss = (self.isUploadable && self.dropZoneEnabled) ? ' file-drop-zone' : 'file-drop-disabled',
- close = !self.showClose ? '' : self._getLayoutTemplate('close'),
- preview = !self.showPreview ? '' : self._getLayoutTemplate('preview')
- .setTokens({'class': self.previewClass, 'dropClass': dropCss}),
- css = self.isDisabled ? self.captionClass + ' file-caption-disabled' : self.captionClass,
- caption = self.captionTemplate.setTokens({'class': css + ' kv-fileinput-caption'});
- return self.mainTemplate.setTokens({
- 'class': self.mainClass + (!self.showBrowse && self.showCaption ? ' no-browse' : ''),
- 'preview': preview,
- 'close': close,
- 'caption': caption,
- 'upload': self._renderButton('upload'),
- 'remove': self._renderButton('remove'),
- 'cancel': self._renderButton('cancel'),
- 'browse': self._renderButton('browse')
- });
- },
- _renderButton: function (type) {
- var self = this, tmplt = self._getLayoutTemplate('btnDefault'), css = self[type + 'Class'],
- title = self[type + 'Title'], icon = self[type + 'Icon'], label = self[type + 'Label'],
- status = self.isDisabled ? ' disabled' : '', btnType = 'button';
- switch (type) {
- case 'remove':
- if (!self.showRemove) {
- return '';
- }
- break;
- case 'cancel':
- if (!self.showCancel) {
- return '';
- }
- css += ' hide';
- break;
- case 'upload':
- if (!self.showUpload) {
- return '';
- }
- if (self.isUploadable && !self.isDisabled) {
- tmplt = self._getLayoutTemplate('btnLink').replace('{href}', self.uploadUrl);
- } else {
- btnType = 'submit';
- }
- break;
- case 'browse':
- if (!self.showBrowse) {
- return '';
- }
- tmplt = self._getLayoutTemplate('btnBrowse');
- break;
- default:
- return '';
- }
- css += type === 'browse' ? ' btn-file' : ' fileinput-' + type + ' fileinput-' + type + '-button';
- if (!$h.isEmpty(label)) {
- label = ' <span class="' + self.buttonLabelClass + '">' + label + '</span>';
- }
- return tmplt.setTokens({
- 'type': btnType, 'css': css, 'title': title, 'status': status, 'icon': icon, 'label': label
- });
- },
- _renderThumbProgress: function () {
- var self = this;
- return '<div class="file-thumb-progress hide">' +
- self.progressTemplate.setTokens({'percent': '0', 'status': self.msgUploadBegin}) +
- '</div>';
- },
- _renderFileFooter: function (caption, size, width, isError) {
- var self = this, config = self.fileActionSettings, rem = config.showRemove, drg = config.showDrag,
- upl = config.showUpload, zoom = config.showZoom, out, template = self._getLayoutTemplate('footer'),
- ind = isError ? config.indicatorError : config.indicatorNew,
- tInd = self._getLayoutTemplate('indicator'),
- title = isError ? config.indicatorErrorTitle : config.indicatorNewTitle,
- indicator = tInd.setTokens({'indicator': ind, 'indicatorTitle': title});
- size = self._getSize(size);
- if (self.isUploadable) {
- out = template.setTokens({
- 'actions': self._renderFileActions(upl, rem, zoom, drg, false, false, false),
- 'caption': caption,
- 'size': size,
- 'width': width,
- 'progress': self._renderThumbProgress(),
- 'indicator': indicator
- });
- } else {
- out = template.setTokens({
- 'actions': self._renderFileActions(false, false, zoom, drg, false, false, false),
- 'caption': caption,
- 'size': size,
- 'width': width,
- 'progress': '',
- 'indicator': indicator
- });
- }
- out = $h.replaceTags(out, self.previewThumbTags);
- return out;
- },
- _renderFileActions: function (showUpload, showDelete, showZoom, showDrag, disabled, url, key, isInit) {
- if (!showUpload && !showDelete && !showZoom && !showDrag) {
- return '';
- }
- var self = this, vUrl = url === false ? '' : ' data-url="' + url + '"',
- vKey = key === false ? '' : ' data-key="' + key + '"',
- btnDelete = '', btnUpload = '', btnZoom = '', btnDrag = '', css,
- template = self._getLayoutTemplate('actions'), config = self.fileActionSettings,
- otherButtons = self.otherActionButtons.setTokens({'dataKey': vKey}),
- removeClass = disabled ? config.removeClass + ' disabled' : config.removeClass;
- if (showDelete) {
- btnDelete = self._getLayoutTemplate('actionDelete').setTokens({
- 'removeClass': removeClass,
- 'removeIcon': config.removeIcon,
- 'removeTitle': config.removeTitle,
- 'dataUrl': vUrl,
- 'dataKey': vKey
- });
- }
- if (showUpload) {
- btnUpload = self._getLayoutTemplate('actionUpload').setTokens({
- 'uploadClass': config.uploadClass,
- 'uploadIcon': config.uploadIcon,
- 'uploadTitle': config.uploadTitle
- });
- }
- if (showZoom) {
- btnZoom = self._getLayoutTemplate('actionZoom').setTokens({
- 'zoomClass': config.zoomClass,
- 'zoomIcon': config.zoomIcon,
- 'zoomTitle': config.zoomTitle
- });
- }
- if (showDrag && isInit) {
- css = 'drag-handle-init ' + config.dragClass;
- btnDrag = self._getLayoutTemplate('actionDrag').setTokens({
- 'dragClass': css,
- 'dragTitle': config.dragTitle,
- 'dragIcon': config.dragIcon
- });
- }
- return template.setTokens({
- 'delete': btnDelete,
- 'upload': btnUpload,
- 'zoom': btnZoom,
- 'drag': btnDrag,
- 'other': otherButtons
- });
- },
- _browse: function (e) {
- var self = this;
- self._raise('filebrowse');
- if (e && e.isDefaultPrevented()) {
- return;
- }
- if (self.isError && !self.isUploadable) {
- self.clear();
- }
- self.$captionContainer.focus();
- },
- _filterDuplicate: function (file, files, fileIds) {
- var self = this, fileId = self._getFileId(file);
- if (fileId && fileIds && fileIds.indexOf(fileId) > -1) {
- return;
- }
- if (!fileIds) {
- fileIds = [];
- }
- files.push(file);
- fileIds.push(fileId);
- },
- _change: function (e) {
- var self = this, $el = self.$element;
- if (!self.isUploadable && $h.isEmpty($el.val()) && self.fileInputCleared) { // IE 11 fix
- self.fileInputCleared = false;
- return;
- }
- self.fileInputCleared = false;
- var tfiles = [], msg, total, isDragDrop = arguments.length > 1, isAjaxUpload = self.isUploadable, n, len,
- files = isDragDrop ? e.originalEvent.dataTransfer.files : $el.get(0).files, ctr = self.filestack.length,
- isSingleUpload = $h.isEmpty($el.attr('multiple')), flagSingle = (isSingleUpload && ctr > 0),
- folders = 0, fileIds = self._getFileIds(), throwError = function (mesg, file, previewId, index) {
- var p1 = $.extend(true, {}, self._getOutData({}, {}, files), {id: previewId, index: index}),
- p2 = {id: previewId, index: index, file: file, files: files};
- return self.isUploadable ? self._showUploadError(mesg, p1) : self._showError(mesg, p2);
- };
- self.reader = null;
- self._resetUpload();
- self._hideFileIcon();
- if (self.isUploadable) {
- self.$container.find('.file-drop-zone .' + self.dropZoneTitleClass).remove();
- }
- if (isDragDrop) {
- $.each(files, function (i, f) {
- if (f && !f.type && f.size !== undefined && f.size % 4096 === 0) {
- folders++;
- } else {
- self._filterDuplicate(f, tfiles, fileIds);
- }
- });
- } else {
- if (e.target && e.target.files === undefined) {
- files = e.target.value ? [{name: e.target.value.replace(/^.+\\/, '')}] : [];
- } else {
- files = e.target.files || {};
- }
- if (isAjaxUpload) {
- $.each(files, function (i, f) {
- self._filterDuplicate(f, tfiles, fileIds);
- });
- } else {
- tfiles = files;
- }
- }
- if ($h.isEmpty(tfiles) || tfiles.length === 0) {
- if (!isAjaxUpload) {
- self.clear();
- }
- self._showFolderError(folders);
- self._raise('fileselectnone');
- return;
- }
- self._resetErrors();
- len = tfiles.length;
- total = self._getFileCount(self.isUploadable ? (self.getFileStack().length + len) : len);
- if (self.maxFileCount > 0 && total > self.maxFileCount) {
- if (!self.autoReplace || len > self.maxFileCount) {
- n = (self.autoReplace && len > self.maxFileCount) ? len : total;
- msg = self.msgFilesTooMany.replace('{m}', self.maxFileCount).replace('{n}', n);
- self.isError = throwError(msg, null, null, null);
- self.$captionContainer.find('.kv-caption-icon').hide();
- self._setCaption('', true);
- self.$container.removeClass('file-input-new file-input-ajax-new');
- return;
- }
- if (total > self.maxFileCount) {
- self._resetPreviewThumbs(isAjaxUpload);
- }
- } else {
- if (!isAjaxUpload || flagSingle) {
- self._resetPreviewThumbs(false);
- if (flagSingle) {
- self.clearStack();
- }
- } else {
- if (isAjaxUpload && ctr === 0 && (!self.previewCache.count() || self.overwriteInitial)) {
- self._resetPreviewThumbs(true);
- }
- }
- }
- if (self.isPreviewable) {
- self._readFiles(tfiles);
- } else {
- self._updateFileDetails(1);
- }
- self._showFolderError(folders);
- },
- _abort: function (params) {
- var self = this, data;
- if (self.ajaxAborted && typeof self.ajaxAborted === "object" && self.ajaxAborted.message !== undefined) {
- data = $.extend(true, {}, self._getOutData(), params);
- data.abortData = self.ajaxAborted.data || {};
- data.abortMessage = self.ajaxAborted.message;
- self._setProgress(101, self.$progress, self.msgCancelled);
- self._showUploadError(self.ajaxAborted.message, data, 'filecustomerror');
- self.cancel();
- return true;
- }
- return false;
- },
- _resetFileStack: function () {
- var self = this, i = 0, newstack = [], newnames = [], newids = [];
- self._getThumbs().each(function () {
- var $thumb = $(this), ind = $thumb.attr('data-fileindex'), file = self.filestack[ind],
- pid = $thumb.attr('id'), newId;
- if (ind === '-1' || ind === -1) {
- return;
- }
- if (file !== undefined) {
- newstack[i] = file;
- newnames[i] = self._getFileName(file);
- newids[i] = self._getFileId(file);
- $thumb.attr({'id': self.previewInitId + '-' + i, 'data-fileindex': i});
- i++;
- } else {
- newId = 'uploaded-' + $h.uniqId();
- $thumb.attr({'id': newId, 'data-fileindex': '-1'});
- self.$preview.find('#zoom-' + pid).attr('id', 'zoom-' + newId);
- }
- });
- self.filestack = newstack;
- self.filenames = newnames;
- self.fileids = newids;
- },
- _isFileSelectionValid: function (cnt) {
- var self = this;
- cnt = cnt || 0;
- if (self.required && !self.getFilesCount()) {
- self.$errorContainer.html('');
- self._showUploadError(self.msgFileRequired);
- return false;
- }
- if (self.minFileCount > 0 && self._getFileCount(cnt) < self.minFileCount) {
- self._noFilesError({});
- return false;
- }
- return true;
- },
- clearStack: function () {
- var self = this;
- self.filestack = [];
- self.filenames = [];
- self.fileids = [];
- return self.$element;
- },
- updateStack: function (i, file) {
- var self = this;
- self.filestack[i] = file;
- self.filenames[i] = self._getFileName(file);
- self.fileids[i] = file && self._getFileId(file) || null;
- return self.$element;
- },
- addToStack: function (file) {
- var self = this;
- self.filestack.push(file);
- self.filenames.push(self._getFileName(file));
- self.fileids.push(self._getFileId(file));
- return self.$element;
- },
- getFileStack: function (skipNull) {
- var self = this;
- return self.filestack.filter(function (n) {
- return (skipNull ? n !== undefined : n !== undefined && n !== null);
- });
- },
- getFilesCount: function () {
- var self = this, len = self.isUploadable ? self.getFileStack().length : self.$element.get(0).files.length;
- return self._getFileCount(len);
- },
- lock: function () {
- var self = this;
- self._resetErrors();
- self.disable();
- if (self.showRemove) {
- $h.addCss(self.$container.find('.fileinput-remove'), 'hide');
- }
- if (self.showCancel) {
- self.$container.find('.fileinput-cancel').removeClass('hide');
- }
- self._raise('filelock', [self.filestack, self._getExtraData()]);
- return self.$element;
- },
- unlock: function (reset) {
- var self = this;
- if (reset === undefined) {
- reset = true;
- }
- self.enable();
- if (self.showCancel) {
- $h.addCss(self.$container.find('.fileinput-cancel'), 'hide');
- }
- if (self.showRemove) {
- self.$container.find('.fileinput-remove').removeClass('hide');
- }
- if (reset) {
- self._resetFileStack();
- }
- self._raise('fileunlock', [self.filestack, self._getExtraData()]);
- return self.$element;
- },
- cancel: function () {
- var self = this, xhr = self.ajaxRequests, len = xhr.length, i;
- if (len > 0) {
- for (i = 0; i < len; i += 1) {
- self.cancelling = true;
- xhr[i].abort();
- }
- }
- self._setProgressCancelled();
- self._getThumbs().each(function () {
- var $thumb = $(this), ind = $thumb.attr('data-fileindex');
- $thumb.removeClass('file-uploading');
- if (self.filestack[ind] !== undefined) {
- $thumb.find('.kv-file-upload').removeClass('disabled').removeAttr('disabled');
- $thumb.find('.kv-file-remove').removeClass('disabled').removeAttr('disabled');
- }
- self.unlock();
- });
- return self.$element;
- },
- clear: function () {
- var self = this, cap;
- if (!self._raise('fileclear')) {
- return;
- }
- self.$btnUpload.removeAttr('disabled');
- self._getThumbs().find('video,audio,img').each(function () {
- $h.cleanMemory($(this));
- });
- self._resetUpload();
- self.clearStack();
- self._clearFileInput();
- self._resetErrors(true);
- if (self._hasInitialPreview()) {
- self._showFileIcon();
- self._resetPreview();
- self._initPreviewActions();
- self.$container.removeClass('file-input-new');
- } else {
- self._getThumbs().each(function () {
- self._clearObjects($(this));
- });
- if (self.isUploadable) {
- self.previewCache.data = {};
- }
- self.$preview.html('');
- cap = (!self.overwriteInitial && self.initialCaption.length > 0) ? self.initialCaption : '';
- self.$caption.html(cap);
- self.$caption.attr('title', '');
- $h.addCss(self.$container, 'file-input-new');
- self._validateDefaultPreview();
- }
- if (self.$container.find($h.FRAMES).length === 0) {
- if (!self._initCaption()) {
- self.$captionContainer.find('.kv-caption-icon').hide();
- }
- }
- self._hideFileIcon();
- self._raise('filecleared');
- self.$captionContainer.focus();
- self._setFileDropZoneTitle();
- return self.$element;
- },
- reset: function () {
- var self = this;
- if (!self._raise('filereset')) {
- return;
- }
- self._resetPreview();
- self.$container.find('.fileinput-filename').text('');
- $h.addCss(self.$container, 'file-input-new');
- if (self.getFrames().length || self.isUploadable && self.dropZoneEnabled) {
- self.$container.removeClass('file-input-new');
- }
- self._setFileDropZoneTitle();
- self.clearStack();
- self.formdata = {};
- return self.$element;
- },
- disable: function () {
- var self = this;
- self.isDisabled = true;
- self._raise('filedisabled');
- self.$element.attr('disabled', 'disabled');
- self.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled");
- self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
- .attr("disabled", true);
- self._initDragDrop();
- return self.$element;
- },
- enable: function () {
- var self = this;
- self.isDisabled = false;
- self._raise('fileenabled');
- self.$element.removeAttr('disabled');
- self.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled");
- self.$container.find(".btn-file, .fileinput-remove, .fileinput-upload, .file-preview-frame button")
- .removeAttr("disabled");
- self._initDragDrop();
- return self.$element;
- },
- upload: function () {
- var self = this, totLen = self.getFileStack().length, i, outData, len,
- hasExtraData = !$.isEmptyObject(self._getExtraData());
- if (!self.isUploadable || self.isDisabled || !self._isFileSelectionValid(totLen)) {
- return;
- }
- self._resetUpload();
- if (totLen === 0 && !hasExtraData) {
- self._showUploadError(self.msgUploadEmpty);
- return;
- }
- self.$progress.removeClass('hide');
- self.uploadCount = 0;
- self.uploadStatus = {};
- self.uploadLog = [];
- self.lock();
- self._setProgress(2);
- if (totLen === 0 && hasExtraData) {
- self._uploadExtraOnly();
- return;
- }
- len = self.filestack.length;
- self.hasInitData = false;
- if (self.uploadAsync) {
- outData = self._getOutData();
- self._raise('filebatchpreupload', [outData]);
- self.fileBatchCompleted = false;
- self.uploadCache = {content: [], config: [], tags: [], append: true};
- self.uploadAsyncCount = self.getFileStack().length;
- for (i = 0; i < len; i++) {
- self.uploadCache.content[i] = null;
- self.uploadCache.config[i] = null;
- self.uploadCache.tags[i] = null;
- }
- self.$preview.find('.file-preview-initial').removeClass($h.SORT_CSS);
- self._initSortable();
- self.cacheInitialPreview = self.getPreview();
- for (i = 0; i < len; i++) {
- if (self.filestack[i] !== undefined) {
- self._uploadSingle(i, self.filestack, true);
- }
- }
- return;
- }
- self._uploadBatch();
- return self.$element;
- },
- destroy: function () {
- var self = this, $form = self.$form, $cont = self.$container, $el = self.$element, ns = self.namespace;
- $(document).off(ns);
- $(window).off(ns);
- if ($form && $form.length) {
- $form.off(ns);
- }
- if (self.isUploadable) {
- self._clearFileInput();
- }
- self._cleanup();
- self._initPreviewCache();
- $el.insertBefore($cont).off(ns).removeData();
- $cont.off().remove();
- return $el;
- },
- refresh: function (options) {
- var self = this, $el = self.$element;
- options = options ? $.extend(true, {}, self.options, options) : self.options;
- self.destroy();
- $el.fileinput(options);
- self = $el.data('fileinput');
- if (self.isUploadable) {
- self._clearFileInput();
- }
- if ($el.val()) {
- $el.trigger('change.fileinput');
- }
- return $el;
- },
- zoom: function (frameId) {
- var self = this, $frame = self._getFrame(frameId), $modal = self.$modal;
- if (!$frame) {
- return;
- }
- $h.initModal($modal);
- $modal.html(self._getModalContent());
- self._setZoomContent($frame);
- $modal.modal('show');
- self._initZoomButtons();
- },
- getExif: function (frameId) {
- var self = this, $frame = self._getFrame(frameId);
- return $frame && $frame.data('exif') || null;
- },
- getFrames: function (cssFilter) {
- var self = this;
- cssFilter = cssFilter || '';
- return self.$preview.find($h.FRAMES + cssFilter);
- },
- getPreview: function () {
- var self = this;
- return {
- content: self.initialPreview,
- config: self.initialPreviewConfig,
- tags: self.initialPreviewThumbTags
- };
- }
- };
- $.fn.fileinput = function (option) {
- if (!$h.hasFileAPISupport() && !$h.isIE(9)) {
- return;
- }
- var args = Array.apply(null, arguments), retvals = [];
- args.shift();
- this.each(function () {
- var self = $(this), data = self.data('fileinput'), options = typeof option === 'object' && option,
- theme = options.theme || self.data('theme'), l = {}, t = {},
- lang = options.language || self.data('language') || $.fn.fileinput.defaults.language || 'en', opt;
- if (!data) {
- if (theme) {
- t = $.fn.fileinputThemes[theme] || {};
- }
- if (lang !== 'en' && !$h.isEmpty($.fn.fileinputLocales[lang])) {
- l = $.fn.fileinputLocales[lang] || {};
- }
- opt = $.extend(true, {}, $.fn.fileinput.defaults, t, $.fn.fileinputLocales.en, l, options, self.data());
- data = new FileInput(this, opt);
- self.data('fileinput', data);
- }
- if (typeof option === 'string') {
- retvals.push(data[option].apply(data, args));
- }
- });
- switch (retvals.length) {
- case 0:
- return this;
- case 1:
- return retvals[0];
- default:
- return retvals;
- }
- };
- $.fn.fileinput.defaults = {
- language: 'en',
- showCaption: true,
- showBrowse: true,
- showPreview: true,
- showRemove: true,
- showUpload: true,
- showCancel: true,
- showClose: true,
- showUploadedThumbs: true,
- browseOnZoneClick: false,
- autoReplace: false,
- autoOrientImage: true, // for JPEG images based on EXIF orientation tag
- required: false,
- rtl: false,
- hideThumbnailContent: false,
- generateFileId: null,
- previewClass: '',
- captionClass: '',
- frameClass: 'krajee-default',
- mainClass: 'file-caption-main',
- mainTemplate: null,
- purifyHtml: true,
- fileSizeGetter: null,
- initialCaption: '',
- initialPreview: [],
- initialPreviewDelimiter: '*$$*',
- initialPreviewAsData: false,
- initialPreviewFileType: 'image',
- initialPreviewConfig: [],
- initialPreviewThumbTags: [],
- previewThumbTags: {},
- initialPreviewShowDelete: true,
- removeFromPreviewOnError: false,
- deleteUrl: '',
- deleteExtraData: {},
- overwriteInitial: true,
- previewZoomButtonIcons: {
- prev: '<i class="glyphicon glyphicon-triangle-left"></i>',
- next: '<i class="glyphicon glyphicon-triangle-right"></i>',
- toggleheader: '<i class="glyphicon glyphicon-resize-vertical"></i>',
- fullscreen: '<i class="glyphicon glyphicon-fullscreen"></i>',
- borderless: '<i class="glyphicon glyphicon-resize-full"></i>',
- close: '<i class="glyphicon glyphicon-remove"></i>'
- },
- previewZoomButtonClasses: {
- prev: 'btn btn-navigate',
- next: 'btn btn-navigate',
- toggleheader: 'btn btn-default btn-header-toggle',
- fullscreen: 'btn btn-default',
- borderless: 'btn btn-default',
- close: 'btn btn-default'
- },
- preferIconicPreview: false,
- preferIconicZoomPreview: false,
- allowedPreviewTypes: undefined,
- allowedPreviewMimeTypes: null,
- allowedFileTypes: null,
- allowedFileExtensions: null,
- defaultPreviewContent: null,
- customLayoutTags: {},
- customPreviewTags: {},
- previewFileIcon: '<i class="glyphicon glyphicon-file"></i>',
- previewFileIconClass: 'file-other-icon',
- previewFileIconSettings: {},
- previewFileExtSettings: {},
- buttonLabelClass: 'hidden-xs',
- browseIcon: '<i class="glyphicon glyphicon-folder-open"></i> ',
- browseClass: 'btn btn-primary',
- removeIcon: '<i class="glyphicon glyphicon-trash"></i>',
- removeClass: 'btn btn-default',
- cancelIcon: '<i class="glyphicon glyphicon-ban-circle"></i>',
- cancelClass: 'btn btn-default',
- uploadIcon: '<i class="glyphicon glyphicon-upload"></i>',
- uploadClass: 'btn btn-default',
- uploadUrl: null,
- uploadAsync: true,
- uploadExtraData: {},
- zoomModalHeight: 480,
- minImageWidth: null,
- minImageHeight: null,
- maxImageWidth: null,
- maxImageHeight: null,
- resizeImage: false,
- resizePreference: 'width',
- resizeQuality: 0.92,
- resizeDefaultImageType: 'image/jpeg',
- resizeIfSizeMoreThan: 0, // in KB
- minFileSize: 0,
- maxFileSize: 0,
- maxFilePreviewSize: 25600, // 25 MB
- minFileCount: 0,
- maxFileCount: 0,
- validateInitialCount: false,
- msgValidationErrorClass: 'text-danger',
- msgValidationErrorIcon: '<i class="glyphicon glyphicon-exclamation-sign"></i> ',
- msgErrorClass: 'file-error-message',
- progressThumbClass: "progress-bar progress-bar-success progress-bar-striped active",
- progressClass: "progress-bar progress-bar-success progress-bar-striped active",
- progressCompleteClass: "progress-bar progress-bar-success",
- progressErrorClass: "progress-bar progress-bar-danger",
- progressUploadThreshold: 99,
- previewFileType: 'image',
- elCaptionContainer: null,
- elCaptionText: null,
- elPreviewContainer: null,
- elPreviewImage: null,
- elPreviewStatus: null,
- elErrorContainer: null,
- errorCloseButton: '<span class="close kv-error-close">×</span>',
- slugCallback: null,
- dropZoneEnabled: true,
- dropZoneTitleClass: 'file-drop-zone-title',
- fileActionSettings: {},
- otherActionButtons: '',
- textEncoding: 'UTF-8',
- ajaxSettings: {},
- ajaxDeleteSettings: {},
- showAjaxErrorDetails: true
- };
- $.fn.fileinputLocales.en = {
- fileSingle: 'file',
- filePlural: 'files',
- browseLabel: 'Browse …',
- removeLabel: 'Remove',
- removeTitle: 'Clear selected files',
- cancelLabel: 'Cancel',
- cancelTitle: 'Abort ongoing upload',
- uploadLabel: 'Upload',
- uploadTitle: 'Upload selected files',
- msgNo: 'No',
- msgNoFilesSelected: 'No files selected',
- msgCancelled: 'Cancelled',
- msgZoomModalHeading: 'Detailed Preview',
- msgFileRequired: 'You must select a file to upload.',
- msgSizeTooSmall: 'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',
- msgSizeTooLarge: 'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',
- msgFilesTooLess: 'You must select at least <b>{n}</b> {files} to upload.',
- msgFilesTooMany: 'Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.',
- msgFileNotFound: 'File "{name}" not found!',
- msgFileSecured: 'Security restrictions prevent reading the file "{name}".',
- msgFileNotReadable: 'File "{name}" is not readable.',
- msgFilePreviewAborted: 'File preview aborted for "{name}".',
- msgFilePreviewError: 'An error occurred while reading the file "{name}".',
- msgInvalidFileName: 'Invalid or unsupported characters in file name "{name}".',
- msgInvalidFileType: 'Invalid type for file "{name}". Only "{types}" files are supported.',
- msgInvalidFileExtension: 'Invalid extension for file "{name}". Only "{extensions}" files are supported.',
- msgFileTypes: {
- 'image': 'image',
- 'html': 'HTML',
- 'text': 'text',
- 'video': 'video',
- 'audio': 'audio',
- 'flash': 'flash',
- 'pdf': 'PDF',
- 'object': 'object'
- },
- msgUploadAborted: 'The file upload was aborted',
- msgUploadThreshold: 'Processing...',
- msgUploadBegin: 'Initializing...',
- msgUploadEnd: 'Done',
- msgUploadEmpty: 'No valid data available for upload.',
- msgValidationError: 'Validation Error',
- msgLoading: 'Loading file {index} of {files} …',
- msgProgress: 'Loading file {index} of {files} - {name} - {percent}% completed.',
- msgSelected: '{n} {files} selected',
- msgFoldersNotAllowed: 'Drag & drop files only! {n} folder(s) dropped were skipped.',
- msgImageWidthSmall: 'Width of image file "{name}" must be at least {size} px.',
- msgImageHeightSmall: 'Height of image file "{name}" must be at least {size} px.',
- msgImageWidthLarge: 'Width of image file "{name}" cannot exceed {size} px.',
- msgImageHeightLarge: 'Height of image file "{name}" cannot exceed {size} px.',
- msgImageResizeError: 'Could not get the image dimensions to resize.',
- msgImageResizeException: 'Error while resizing the image.<pre>{errors}</pre>',
- msgAjaxError: 'Something went wrong with the {operation} operation. Please try again later!',
- msgAjaxProgressError: '{operation} failed',
- ajaxOperations: {
- deleteThumb: 'file delete',
- uploadThumb: 'file upload',
- uploadBatch: 'batch file upload',
- uploadExtra: 'form data upload'
- },
- dropZoneTitle: 'Drag & drop files here …',
- dropZoneClickTitle: '<br>(or click to select {files})',
- previewZoomButtonTitles: {
- prev: 'View previous file',
- next: 'View next file',
- toggleheader: 'Toggle header',
- fullscreen: 'Toggle full screen',
- borderless: 'Toggle borderless mode',
- close: 'Close detailed preview'
- }
- };
- $.fn.fileinput.Constructor = FileInput;
- /**
- * Convert automatically file inputs with class 'file' into a bootstrap fileinput control.
- */
- $(document).ready(function () {
- var $input = $('input.file[type=file]');
- if ($input.length) {
- $input.fileinput();
- }
- });
- }));
- /***/ }),
- /* 18 */
- /***/ (function(module, exports) {
- // removed by extract-text-webpack-plugin
- /***/ }),
- /* 19 */
- /***/ (function(module, exports) {
- // removed by extract-text-webpack-plugin
- /***/ }),
- /* 20 */
- /***/ (function(module, exports) {
- // removed by extract-text-webpack-plugin
- /***/ }),
- /* 21 */
- /***/ (function(module, exports) {
- // removed by extract-text-webpack-plugin
- /***/ })
- /******/ ]);
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgZjJhMzFjMmJjMGY3ZDkxNzdjYjIiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS9kaXN0L2pxdWVyeS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9kaXN0L2pzL25wbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL3RyYW5zaXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9hbGVydC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2J1dHRvbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2Nhcm91c2VsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvY29sbGFwc2UuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9kcm9wZG93bi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL21vZGFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvdG9vbHRpcC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL3BvcG92ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9zY3JvbGxzcHkuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90YWIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9hZmZpeC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2pzL2Jvb3RzdHJhcC1zZWxlY3QuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC12YWxpZGF0b3IvanMvdmFsaWRhdG9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2pzL2ZpbGVpbnB1dC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvY3NzL2Jvb3RzdHJhcC5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1zZWxlY3QvZGlzdC9jc3MvYm9vdHN0cmFwLXNlbGVjdC5jc3MiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3MiLCJ3ZWJwYWNrOi8vLy4vc3JjL3N0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7OztBQUlBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsWUFBWTs7QUFFcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxTQUFTO0FBQ2xCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyxZQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLFNBQVM7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxnQkFBZ0IsSUFBSTs7QUFFcEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esd0NBQXdDLElBQUk7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSx5QkFBeUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUSw2QkFBNkI7QUFDaEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGdCQUFnQjtBQUMzQixhQUFhLHVCQUF1QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGNBQWM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGVBQWU7O0FBRWYsU0FBUzs7QUFFVDtBQUNBLFFBQVEsaUNBQWlDO0FBQ3pDLFFBQVEsb0JBQW9CO0FBQzVCLFFBQVEsc0NBQXNDO0FBQzlDLFFBQVE7QUFDUixFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYSxFQUFFO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw0REFBNEQ7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEOztBQUU3RDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0VBQWdFOztBQUVoRTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFLFVBQVU7QUFDM0Usc0NBQXNDLDJCQUEyQjtBQUNqRTtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxVQUFVO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsY0FBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFlBQVksdUVBQXVFO0FBQ25GO0FBQ0E7QUFDQSxZQUFZLDRCQUE0QjtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLFNBQVM7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSwyREFBMkQ7O0FBRTNEO0FBQ0E7QUFDQSxvRkFBb0Y7O0FBRXBGO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaURBQWlEO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pELFVBQVUsd0NBQXdDO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsTUFBTTtBQUNqQixXQUFXLE1BQU07QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUEsQ0FBQzs7OztBQUlEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLFFBQVEsR0FBRztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOzs7O0FBSUE7O0FBRUE7O0FBRUE7QUFDQTs7OztBQUlBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLFNBQVM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUEsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVLE9BQU87QUFDakIsMEJBQTBCLHdCQUF3Qjs7QUFFbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsMENBQTBDO0FBQzFDLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxjQUFjO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLHNDQUFzQztBQUM5RSxvQ0FBb0MsdUNBQXVDO0FBQzNFLG9DQUFvQyxzQ0FBc0M7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUixPQUFPO0FBQ1A7QUFDQSxNQUFNO0FBQ04sS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTs7QUFFVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQyxxQ0FBcUM7QUFDckMsb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7Ozs7O0FBS0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxTQUFTO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGFBQWE7QUFDcEMsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsU0FBUztBQUM3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSxnQkFBZ0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsT0FBTztBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLE9BQU87QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRSxnQkFBZ0I7QUFDbEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQVc7O0FBRVg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsY0FBYzs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix1Q0FBdUM7QUFDakU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVEQUF1RDtBQUM5RTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGNBQWM7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixnQkFBZ0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLCtCQUErQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLE9BQU87QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLE9BQU87QUFDL0M7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLHFDQUFxQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBLFNBQVMsOEJBQThCO0FBQ3ZDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxZQUFZLE9BQU87QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLFdBQVc7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7O0FBSUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCLHNCQUFzQixjQUFjO0FBQ3BDLGdCQUFnQixXQUFXLFlBQVk7QUFDdkMsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFVBQVUsU0FBUyxNQUFNLGFBQWE7QUFDM0UsYUFBYSxlQUFlO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0YsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwrREFBK0Q7QUFDM0U7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsUUFBUSxPQUFPOztBQUVmO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGdCQUFnQjtBQUNsQztBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQSxVQUFVLE9BQU87QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQSxRQUFRLE9BQU87QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsZ0JBQWdCO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osaURBQWlELDBCQUEwQjtBQUMzRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsZ0JBQWdCO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0E7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQSxRQUFRLGdCQUFnQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVMsZ0JBQWdCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLGNBQWM7QUFDbEMsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxrQkFBa0I7QUFDNUIsV0FBVyxrQkFBa0I7QUFDN0IsY0FBYztBQUNkLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSxtQkFBbUI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEOzs7QUFHQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBOztBQUVBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQztBQUMzQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsS0FBSztBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQ0FBcUM7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsS0FBSztBQUNMOztBQUVBLFdBQVc7QUFDWCxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEIsZ0RBQWdEO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakIsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0Esc0JBQXNCO0FBQ3RCLDJCQUEyQjs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHVCQUF1QjtBQUNsQyxXQUFXLHlCQUF5QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFEQUFxRDtBQUNyRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CLDREQUE0RCxlQUFlO0FBQzNFO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGNBQWMsc0RBQXNEO0FBQ3BFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0EsY0FBYyxtQ0FBbUM7QUFDakQsZUFBZSw2REFBNkQ7QUFDNUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLEVBQUU7QUFDRixDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQUE7QUFDRjs7Ozs7QUFLQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0EsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzVnVUQ7QUFBQTtBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSxlQUFlO0FBQzlCLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSwrQkFBK0IsMkJBQTJCO0FBQzFELDBDQUEwQyxlQUFlOztBQUV6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixtQkFBbUI7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsdUJBQXVCOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLDRCQUE0QjtBQUMxQztBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSx1QkFBdUIsYUFBYSxHQUFHLFdBQVcsR0FBRyxhQUFhLEdBQUcsY0FBYztBQUNuRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBOztBQUVBLENBQUM7Ozs7Ozs7QUNuSkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUI7Ozs7OztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsZ0JBQWdCO0FBQ2hFLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsQ0FBQzs7Ozs7Ozs7QUMxREQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQzs7Ozs7Ozs7QUM3RkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUwsQ0FBQzs7Ozs7Ozs7QUM1SEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQiwyQkFBMkI7QUFDM0I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxzRkFBc0YsZUFBZTtBQUNyRzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlEQUFpRCxxREFBcUQ7QUFDdEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUgsQ0FBQzs7Ozs7Ozs7QUM1T0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjs7QUFFL0I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDbk5EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCOztBQUUzQjs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0VBQXNFLHNCQUFzQjtBQUM1RjtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7Ozs7Ozs7QUNwS0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLGdDQUFnQzs7QUFFekU7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSx5Q0FBeUMsZ0NBQWdDOztBQUV6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7O0FBRS9CO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLGtDQUFrQzs7QUFFcEc7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0EsR0FBRzs7QUFFSCxDQUFDOzs7Ozs7OztBQ2xWRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxpQ0FBaUMsS0FBSztBQUN0Qzs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MsaUJBQWlCLGtDQUFrQztBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlCQUF5Qjs7QUFFekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsb0NBQW9DO0FBQ2xEO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVFQUF1RTtBQUN2RSwwQkFBMEIsV0FBVyx3RUFBd0U7QUFDN0c7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsa0JBQWtCO0FBQ2hELHFCQUFxQjtBQUNyQiw4QkFBOEIsdURBQXVEOztBQUVyRixzQkFBc0I7QUFDdEI7O0FBRUE7QUFDQSxvQ0FBb0MsZ0ZBQWdGO0FBQ3BILG9DQUFvQyxnRkFBZ0Y7QUFDcEgsb0NBQW9DLGlGQUFpRjtBQUNySCxvQ0FBb0M7O0FBRXBDOztBQUVBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbURBQW1EO0FBQ25EO0FBQ0EsT0FBTyxrRkFBa0Y7QUFDekY7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0EsT0FBTyx1REFBdUQ7QUFDOUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7Ozs7Ozs7O0FDdmdCRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBOztBQUVBLGlDQUFpQzs7QUFFakM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOzs7Ozs7OztBQzNHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCw2QkFBNkIscUJBQXFCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCLEtBQUs7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDM0tEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOzs7Ozs7OztBQzFKRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDaktEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUFBO0FBQ0wsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSyx5QkFBeUI7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyw0QkFBNEI7QUFDbkMsT0FBTyx1QkFBdUI7QUFDOUIsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGNBQWM7QUFDZCxjQUFjO0FBQ2QsZ0JBQWdCO0FBQ2hCLGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFDaEI7O0FBRUE7QUFDQSxVQUFVO0FBQ1YsU0FBUztBQUNULFNBQVM7QUFDVCxXQUFXO0FBQ1gsV0FBVztBQUNYLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxFQUFFO0FBQzVDO0FBQ0Esb0NBQW9DLEVBQUUsb0JBQW9CLEVBQUU7QUFDNUQsS0FBSztBQUNMO0FBQ0E7QUFDQSx5Q0FBeUMsRUFBRSwrQkFBK0IsRUFBRTtBQUM1RSxpREFBaUQsRUFBRSxxQ0FBcUMsRUFBRTtBQUMxRjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtSUFBbUk7QUFDbkk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThEO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7O0FBRXZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxvQ0FBb0M7QUFDcEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLEVBQUUsOENBQThDLEVBQUU7QUFDdkY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDhCQUE4QjtBQUM5Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiw4QkFBOEI7QUFDOUI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsUUFBUTtBQUN2QixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsMERBQTBELEVBQUU7QUFDNUQsNkRBQTZELEVBQUU7QUFDL0Q7QUFDQSx5QkFBeUIsSUFBSTtBQUM3QjtBQUNBO0FBQ0EsOENBQThDLElBQUk7QUFDbEQsb0RBQW9ELElBQUk7QUFDeEQ7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBLG9FQUFvRSxFQUFFO0FBQ3RFO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQSxxQkFBcUIsZUFBZTtBQUNwQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyx5REFBeUQ7QUFDM0YsdUNBQXVDLHdHQUF3RztBQUMvSTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxDQUFDOzs7QUFHRCxDQUFDOzs7Ozs7O0FDLzBERDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLDRCQUE0QjtBQUN2RDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLDhDQUE4QyxzQkFBc0I7QUFDcEU7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDLHNDQUFzQztBQUNuRiwyQ0FBMkMsMENBQTBDOztBQUVyRjtBQUNBOztBQUVBOztBQUVBLCtEQUErRCxzQkFBc0I7QUFDckYsS0FBSztBQUNMOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxrREFBa0Q7QUFDdkcsK0JBQStCLDBCQUEwQjtBQUN6RCxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw2QkFBNkIsd0RBQXdEO0FBQ3JGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw4Q0FBOEMsbUNBQW1DOztBQUVqRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVILENBQUM7Ozs7Ozs7O0FDN1pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBcUQ7QUFDckQ7QUFDQTtBQUFBO0FBQUE7QUFBQSxxR0FBb0M7QUFDcEMsS0FBSyxPQUFPO0FBQ1osMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQSx3REFBd0Q7QUFDeEQsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsYUFBYTtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsT0FBTyxRQUFRLFFBQVE7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIscUJBQXFCLEdBQUcsZ0JBQWdCO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsZ0JBQWdCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLG9CQUFvQjtBQUMzQztBQUNBO0FBQ0Esa0VBQWtFO0FBQ2xFO0FBQ0EsNEZBQTRGLGNBQWM7QUFDMUc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSwyQ0FBMkM7QUFDM0Msb0NBQW9DO0FBQ3BDLG9DQUFvQztBQUNwQyxzQ0FBc0M7QUFDdEMsc0NBQXNDO0FBQ3RDLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsOEJBQThCO0FBQ3hEO0FBQ0EsYUFBYTtBQUNiLDBCQUEwQixxQ0FBcUM7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELE1BQU07QUFDdEQsd0RBQXdELE1BQU07QUFDOUQscURBQXFELE1BQU07QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsUUFBUTtBQUMvQjtBQUNBLDBDQUEwQyxNQUFNO0FBQ2hELHFCQUFxQixRQUFRO0FBQzdCO0FBQ0EseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEMseUJBQXlCLE9BQU87QUFDaEM7QUFDQTtBQUNBLHVCQUF1QixRQUFRLGdEQUFnRCxPQUFPLEdBQUcsT0FBTyxHQUFHLE9BQU8sR0FBRyxPQUFPO0FBQ3BILGtEQUFrRCxNQUFNO0FBQ3hELHNCQUFzQixNQUFNO0FBQzVCLGtDQUFrQyxVQUFVO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0EsOEVBQThFLE1BQU07QUFDcEY7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLEtBQUsseUJBQXlCLE1BQU0sVUFBVSxJQUFJO0FBQzVGLGtCQUFrQixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDeEM7QUFDQSxrQ0FBa0MsS0FBSyx5QkFBeUIsTUFBTSxVQUFVLElBQUksR0FBRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07QUFDN0c7QUFDQSxzREFBc0QsSUFBSSxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTTtBQUNuRjtBQUNBO0FBQ0Esd0RBQXdELElBQUk7QUFDNUQ7QUFDQTtBQUNBLGdFQUFnRSxjQUFjLFlBQVksWUFBWSxNQUFNO0FBQzVHLGdEQUFnRCxRQUFRO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxlQUFlLGdCQUFnQixLQUFLLEVBQUUsS0FBSztBQUM5RztBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxNQUFNO0FBQ3hDLGtDQUFrQyxRQUFRLHNEQUFzRCxRQUFRLEVBQUU7QUFDMUcsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBLDhCQUE4QixTQUFTO0FBQ3ZDO0FBQ0EsOERBQThELFFBQVEsR0FBRyxRQUFRLEtBQUssS0FBSztBQUMzRixzQkFBc0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRO0FBQ3JEO0FBQ0EseUJBQXlCLEtBQUs7QUFDOUI7QUFDQTtBQUNBLDBCQUEwQixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFLFlBQVk7QUFDdEYseUJBQXlCLFlBQVksR0FBRyxTQUFTLFFBQVEsRUFBRSxXQUFXO0FBQ3RFLDBFQUEwRSxZQUFZLFVBQVUsWUFBWTtBQUM1RyxrQkFBa0IsV0FBVztBQUM3QixzRUFBc0UsVUFBVTtBQUNoRix5QkFBeUIsVUFBVSxHQUFHLFNBQVM7QUFDL0MsMERBQTBELFVBQVUsVUFBVSxVQUFVLEdBQUcsU0FBUztBQUNwRyxxRUFBcUUsZUFBZSxHQUFHLFVBQVU7QUFDakcsdURBQXVELFdBQVcsT0FBTyxVQUFVLG1CQUFtQixVQUFVO0FBQ2hILGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0EsMkNBQTJDLFFBQVE7QUFDbkQsOEJBQThCLE9BQU87QUFDckMseUJBQXlCLFFBQVE7QUFDakMsNEVBQTRFLFFBQVE7QUFDcEYsbUJBQW1CLEtBQUs7QUFDeEIsaUNBQWlDLEtBQUsscURBQXFELFFBQVEsUUFBUSxRQUFRO0FBQ25IO0FBQ0EsaUZBQWlGLFFBQVE7QUFDekYsc0NBQXNDLEtBQUs7QUFDM0MsZ0ZBQWdGLE1BQU07QUFDdEYsMEJBQTBCLE9BQU8sZ0NBQWdDLEtBQUssU0FBUyxLQUFLO0FBQ3BGO0FBQ0EsOEdBQThHLEtBQUs7QUFDbkgsd0JBQXdCLEtBQUs7QUFDN0I7QUFDQSx5QkFBeUIsTUFBTSxXQUFXLE9BQU8sU0FBUyxLQUFLO0FBQy9EO0FBQ0EsbUVBQW1FLFFBQVEsU0FBUyxLQUFLLFNBQVMsS0FBSztBQUN2Ryx5QkFBeUIsTUFBTSxXQUFXLE9BQU8scUNBQXFDLFFBQVE7QUFDOUY7QUFDQSx5REFBeUQsS0FBSztBQUM5RCx5QkFBeUIsTUFBTSxXQUFXLE9BQU87QUFDakQ7QUFDQSwyRUFBMkUsWUFBWTtBQUN2RiwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0EsNEJBQTRCLCtCQUErQjtBQUMzRCwyQkFBMkIsZ0NBQWdDO0FBQzNELDJCQUEyQixnQ0FBZ0M7QUFDM0QsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QixtREFBbUQ7QUFDL0UsNkJBQTZCLGVBQWU7QUFDNUMsMEJBQTBCLGdDQUFnQztBQUMxRCw0QkFBNEI7QUFDNUIsaUJBQWlCO0FBQ2pCO0FBQ0EsNEJBQTRCLHlFQUF5RTtBQUNyRztBQUNBO0FBQ0EsNEJBQTRCLG1EQUFtRDtBQUMvRSw0QkFBNEIsOEJBQThCO0FBQzFELDRCQUE0QiwrQkFBK0I7QUFDM0QsNkJBQTZCLDBFQUEwRTtBQUN2RztBQUNBLDRCQUE0QjtBQUM1QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QyxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLHdDQUF3QywyQkFBMkI7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxvQkFBb0I7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsbUJBQW1CO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLGlCQUFpQjtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0EsK0JBQStCLFNBQVM7QUFDeEM7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsOENBQThDLEtBQUs7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxFQUFFO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EscURBQXFELEVBQUUsZ0NBQWdDLE1BQU07QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EscURBQXFELFVBQVU7QUFDL0Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1QkFBdUIsa0JBQWtCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLDhCQUE4QixnQkFBZ0I7QUFDOUMscUNBQXFDLDBFQUEwRTtBQUMvRztBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGtFQUFrRTtBQUNsRSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsc0NBQXNDO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLDJDQUEyQztBQUN0RixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLHNEQUFzRCxFQUFFLGdCQUFnQixNQUFNO0FBQzlFLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLDJCQUEyQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUZBQXFGLHdCQUF3QjtBQUM3RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsc0JBQXNCO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNGQUFzRixVQUFVO0FBQ2hHO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0Esc0ZBQXNGO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkZBQTJGLFVBQVU7QUFDckc7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0EsbUdBQW1HO0FBQ25HO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsR0FBRyxVQUFVO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QixxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsU0FBUztBQUN0RSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLFlBQVk7QUFDNUY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOERBQThELDJCQUEyQjtBQUN6RjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsaUNBQWlDO0FBQzlEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixTQUFTO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLDZFQUE2RSxFQUFFO0FBQy9FLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHFCQUFxQixJQUFJLFdBQVcsNEJBQTRCO0FBQzlHLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLFlBQVk7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsS0FBSztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixzQkFBc0I7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRSxtQ0FBbUM7QUFDcEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxzQ0FBc0M7QUFDNUc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxNQUFNLG9CQUFvQixNQUFNO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsdURBQXVEO0FBQ3JHLGlCQUFpQjtBQUNqQiw4Q0FBOEMsb0VBQW9FO0FBQ2xIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxNQUFNO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCw2QkFBNkI7QUFDeEY7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBLDJDQUEyQyxPQUFPO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsOEJBQThCO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxzQkFBc0I7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsT0FBTztBQUNwRSxpQ0FBaUMsc0JBQXNCO0FBQ3ZEO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QyxtRUFBbUU7QUFDM0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLGlEQUFpRDtBQUNqRjtBQUNBLDBEQUEwRCx1Q0FBdUM7QUFDakc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkVBQTZFLEtBQUs7QUFDbEYscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCw4Q0FBOEM7QUFDL0Y7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLDBDQUEwQztBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLGdCQUFnQjtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSx1RkFBdUY7QUFDdkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxxQkFBcUIsSUFBSSxXQUFXLDRCQUE0QjtBQUM5Ryw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0EsK0NBQStDLDBDQUEwQztBQUN6RixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCxFQUFFLGdDQUFnQyxFQUFFO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUMsd0RBQXdEO0FBQ3pGO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUNBQWlDLG9DQUFvQztBQUNyRTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFNBQVM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSxRQUFRO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkMsa0NBQWtDO0FBQ2xDO0FBQ0EsMEVBQTBFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBLHdCQUF3QjtBQUN4Qiw4QkFBOEI7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxLQUFLLE9BQU8sS0FBSyxrREFBa0QsUUFBUTtBQUM1RyxpQ0FBaUMsS0FBSyxPQUFPLEtBQUssb0RBQW9ELFFBQVE7QUFDOUcsdURBQXVELEVBQUUsTUFBTSxNQUFNO0FBQ3JFLG1FQUFtRSxFQUFFLDJDQUEyQyxFQUFFO0FBQ2xILGlDQUFpQyxLQUFLO0FBQ3RDLDBFQUEwRSxLQUFLO0FBQy9FLG9DQUFvQyxLQUFLO0FBQ3pDLDJEQUEyRCxLQUFLO0FBQ2hFLHlFQUF5RSxLQUFLO0FBQzlFLDhFQUE4RSxLQUFLO0FBQ25GLHFEQUFxRCxLQUFLLFVBQVUsTUFBTTtBQUMxRSwrREFBK0QsS0FBSyxVQUFVLFdBQVc7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxNQUFNLEtBQUssTUFBTSxTQUFTO0FBQzdELG9DQUFvQyxNQUFNLEtBQUssTUFBTSxJQUFJLEtBQUssSUFBSSxRQUFRO0FBQzFFLHVCQUF1QixFQUFFLEVBQUUsTUFBTTtBQUNqQyx3REFBd0QsRUFBRTtBQUMxRCxtREFBbUQsS0FBSyxvQkFBb0IsS0FBSztBQUNqRixxREFBcUQsS0FBSyxvQkFBb0IsS0FBSztBQUNuRixtREFBbUQsS0FBSyxpQkFBaUIsS0FBSztBQUM5RSxxREFBcUQsS0FBSyxpQkFBaUIsS0FBSztBQUNoRjtBQUNBLHVFQUF1RSxPQUFPO0FBQzlFLHNEQUFzRCxVQUFVO0FBQ2hFLGdDQUFnQyxVQUFVO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsdURBQXVEO0FBQ3ZELHNEQUFzRCxNQUFNO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLENBQUMsRzs7Ozs7O0FDMzFIRCx5Qzs7Ozs7O0FDQUEseUM7Ozs7OztBQ0FBLHlDOzs7Ozs7QUNBQSx5QyIsImZpbGUiOiJtYWluLmJ1bmRsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwge1xuIFx0XHRcdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcbiBcdFx0XHRcdGVudW1lcmFibGU6IHRydWUsXG4gXHRcdFx0XHRnZXQ6IGdldHRlclxuIFx0XHRcdH0pO1xuIFx0XHR9XG4gXHR9O1xuXG4gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG4gXHRcdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0TW9kdWxlRXhwb3J0cygpIHsgcmV0dXJuIG1vZHVsZTsgfTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgJ2EnLCBnZXR0ZXIpO1xuIFx0XHRyZXR1cm4gZ2V0dGVyO1xuIFx0fTtcblxuIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7IHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7IH07XG5cbiBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnAgPSBcIlwiO1xuXG4gXHQvLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbiBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDEpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIGYyYTMxYzJiYzBmN2Q5MTc3Y2IyIiwiLyohXG4gKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYzLjIuMVxuICogaHR0cHM6Ly9qcXVlcnkuY29tL1xuICpcbiAqIEluY2x1ZGVzIFNpenpsZS5qc1xuICogaHR0cHM6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IEpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKiBodHRwczovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTctMDMtMjBUMTg6NTlaXG4gKi9cbiggZnVuY3Rpb24oIGdsb2JhbCwgZmFjdG9yeSApIHtcblxuXHRcInVzZSBzdHJpY3RcIjtcblxuXHRpZiAoIHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0Ly8gRm9yIENvbW1vbkpTIGFuZCBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB3aGVyZSBhIHByb3BlciBgd2luZG93YFxuXHRcdC8vIGlzIHByZXNlbnQsIGV4ZWN1dGUgdGhlIGZhY3RvcnkgYW5kIGdldCBqUXVlcnkuXG5cdFx0Ly8gRm9yIGVudmlyb25tZW50cyB0aGF0IGRvIG5vdCBoYXZlIGEgYHdpbmRvd2Agd2l0aCBhIGBkb2N1bWVudGBcblx0XHQvLyAoc3VjaCBhcyBOb2RlLmpzKSwgZXhwb3NlIGEgZmFjdG9yeSBhcyBtb2R1bGUuZXhwb3J0cy5cblx0XHQvLyBUaGlzIGFjY2VudHVhdGVzIHRoZSBuZWVkIGZvciB0aGUgY3JlYXRpb24gb2YgYSByZWFsIGB3aW5kb3dgLlxuXHRcdC8vIGUuZy4gdmFyIGpRdWVyeSA9IHJlcXVpcmUoXCJqcXVlcnlcIikod2luZG93KTtcblx0XHQvLyBTZWUgdGlja2V0ICMxNDU0OSBmb3IgbW9yZSBpbmZvLlxuXHRcdG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsLmRvY3VtZW50ID9cblx0XHRcdGZhY3RvcnkoIGdsb2JhbCwgdHJ1ZSApIDpcblx0XHRcdGZ1bmN0aW9uKCB3ICkge1xuXHRcdFx0XHRpZiAoICF3LmRvY3VtZW50ICkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJqUXVlcnkgcmVxdWlyZXMgYSB3aW5kb3cgd2l0aCBhIGRvY3VtZW50XCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gZmFjdG9yeSggdyApO1xuXHRcdFx0fTtcblx0fSBlbHNlIHtcblx0XHRmYWN0b3J5KCBnbG9iYWwgKTtcblx0fVxuXG4vLyBQYXNzIHRoaXMgaWYgd2luZG93IGlzIG5vdCBkZWZpbmVkIHlldFxufSApKCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oIHdpbmRvdywgbm9HbG9iYWwgKSB7XG5cbi8vIEVkZ2UgPD0gMTIgLSAxMyssIEZpcmVmb3ggPD0xOCAtIDQ1KywgSUUgMTAgLSAxMSwgU2FmYXJpIDUuMSAtIDkrLCBpT1MgNiAtIDkuMVxuLy8gdGhyb3cgZXhjZXB0aW9ucyB3aGVuIG5vbi1zdHJpY3QgY29kZSAoZS5nLiwgQVNQLk5FVCA0LjUpIGFjY2Vzc2VzIHN0cmljdCBtb2RlXG4vLyBhcmd1bWVudHMuY2FsbGVlLmNhbGxlciAodHJhYy0xMzMzNSkuIEJ1dCBhcyBvZiBqUXVlcnkgMy4wICgyMDE2KSwgc3RyaWN0IG1vZGUgc2hvdWxkIGJlIGNvbW1vblxuLy8gZW5vdWdoIHRoYXQgYWxsIHN1Y2ggYXR0ZW1wdHMgYXJlIGd1YXJkZWQgaW4gYSB0cnkgYmxvY2suXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGFyciA9IFtdO1xuXG52YXIgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQ7XG5cbnZhciBnZXRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjtcblxudmFyIHNsaWNlID0gYXJyLnNsaWNlO1xuXG52YXIgY29uY2F0ID0gYXJyLmNvbmNhdDtcblxudmFyIHB1c2ggPSBhcnIucHVzaDtcblxudmFyIGluZGV4T2YgPSBhcnIuaW5kZXhPZjtcblxudmFyIGNsYXNzMnR5cGUgPSB7fTtcblxudmFyIHRvU3RyaW5nID0gY2xhc3MydHlwZS50b1N0cmluZztcblxudmFyIGhhc093biA9IGNsYXNzMnR5cGUuaGFzT3duUHJvcGVydHk7XG5cbnZhciBmblRvU3RyaW5nID0gaGFzT3duLnRvU3RyaW5nO1xuXG52YXIgT2JqZWN0RnVuY3Rpb25TdHJpbmcgPSBmblRvU3RyaW5nLmNhbGwoIE9iamVjdCApO1xuXG52YXIgc3VwcG9ydCA9IHt9O1xuXG5cblxuXHRmdW5jdGlvbiBET01FdmFsKCBjb2RlLCBkb2MgKSB7XG5cdFx0ZG9jID0gZG9jIHx8IGRvY3VtZW50O1xuXG5cdFx0dmFyIHNjcmlwdCA9IGRvYy5jcmVhdGVFbGVtZW50KCBcInNjcmlwdFwiICk7XG5cblx0XHRzY3JpcHQudGV4dCA9IGNvZGU7XG5cdFx0ZG9jLmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdCApLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHNjcmlwdCApO1xuXHR9XG4vKiBnbG9iYWwgU3ltYm9sICovXG4vLyBEZWZpbmluZyB0aGlzIGdsb2JhbCBpbiAuZXNsaW50cmMuanNvbiB3b3VsZCBjcmVhdGUgYSBkYW5nZXIgb2YgdXNpbmcgdGhlIGdsb2JhbFxuLy8gdW5ndWFyZGVkIGluIGFub3RoZXIgcGxhY2UsIGl0IHNlZW1zIHNhZmVyIHRvIGRlZmluZSBnbG9iYWwgb25seSBmb3IgdGhpcyBtb2R1bGVcblxuXG5cbnZhclxuXHR2ZXJzaW9uID0gXCIzLjIuMVwiLFxuXG5cdC8vIERlZmluZSBhIGxvY2FsIGNvcHkgb2YgalF1ZXJ5XG5cdGpRdWVyeSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblxuXHRcdC8vIFRoZSBqUXVlcnkgb2JqZWN0IGlzIGFjdHVhbGx5IGp1c3QgdGhlIGluaXQgY29uc3RydWN0b3IgJ2VuaGFuY2VkJ1xuXHRcdC8vIE5lZWQgaW5pdCBpZiBqUXVlcnkgaXMgY2FsbGVkIChqdXN0IGFsbG93IGVycm9yIHRvIGJlIHRocm93biBpZiBub3QgaW5jbHVkZWQpXG5cdFx0cmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHdlIHRyaW0gQk9NIGFuZCBOQlNQXG5cdHJ0cmltID0gL15bXFxzXFx1RkVGRlxceEEwXSt8W1xcc1xcdUZFRkZcXHhBMF0rJC9nLFxuXG5cdC8vIE1hdGNoZXMgZGFzaGVkIHN0cmluZyBmb3IgY2FtZWxpemluZ1xuXHRybXNQcmVmaXggPSAvXi1tcy0vLFxuXHRyZGFzaEFscGhhID0gLy0oW2Etel0pL2csXG5cblx0Ly8gVXNlZCBieSBqUXVlcnkuY2FtZWxDYXNlIGFzIGNhbGxiYWNrIHRvIHJlcGxhY2UoKVxuXHRmY2FtZWxDYXNlID0gZnVuY3Rpb24oIGFsbCwgbGV0dGVyICkge1xuXHRcdHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTtcblx0fTtcblxualF1ZXJ5LmZuID0galF1ZXJ5LnByb3RvdHlwZSA9IHtcblxuXHQvLyBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIGpRdWVyeSBiZWluZyB1c2VkXG5cdGpxdWVyeTogdmVyc2lvbixcblxuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LFxuXG5cdC8vIFRoZSBkZWZhdWx0IGxlbmd0aCBvZiBhIGpRdWVyeSBvYmplY3QgaXMgMFxuXHRsZW5ndGg6IDAsXG5cblx0dG9BcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SXG5cdC8vIEdldCB0aGUgd2hvbGUgbWF0Y2hlZCBlbGVtZW50IHNldCBhcyBhIGNsZWFuIGFycmF5XG5cdGdldDogZnVuY3Rpb24oIG51bSApIHtcblxuXHRcdC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGluIGEgY2xlYW4gYXJyYXlcblx0XHRpZiAoIG51bSA9PSBudWxsICkge1xuXHRcdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4ganVzdCB0aGUgb25lIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG5cdFx0cmV0dXJuIG51bSA8IDAgPyB0aGlzWyBudW0gKyB0aGlzLmxlbmd0aCBdIDogdGhpc1sgbnVtIF07XG5cdH0sXG5cblx0Ly8gVGFrZSBhbiBhcnJheSBvZiBlbGVtZW50cyBhbmQgcHVzaCBpdCBvbnRvIHRoZSBzdGFja1xuXHQvLyAocmV0dXJuaW5nIHRoZSBuZXcgbWF0Y2hlZCBlbGVtZW50IHNldClcblx0cHVzaFN0YWNrOiBmdW5jdGlvbiggZWxlbXMgKSB7XG5cblx0XHQvLyBCdWlsZCBhIG5ldyBqUXVlcnkgbWF0Y2hlZCBlbGVtZW50IHNldFxuXHRcdHZhciByZXQgPSBqUXVlcnkubWVyZ2UoIHRoaXMuY29uc3RydWN0b3IoKSwgZWxlbXMgKTtcblxuXHRcdC8vIEFkZCB0aGUgb2xkIG9iamVjdCBvbnRvIHRoZSBzdGFjayAoYXMgYSByZWZlcmVuY2UpXG5cdFx0cmV0LnByZXZPYmplY3QgPSB0aGlzO1xuXG5cdFx0Ly8gUmV0dXJuIHRoZSBuZXdseS1mb3JtZWQgZWxlbWVudCBzZXRcblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdC8vIEV4ZWN1dGUgYSBjYWxsYmFjayBmb3IgZXZlcnkgZWxlbWVudCBpbiB0aGUgbWF0Y2hlZCBzZXQuXG5cdGVhY2g6IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmVhY2goIHRoaXMsIGNhbGxiYWNrICk7XG5cdH0sXG5cblx0bWFwOiBmdW5jdGlvbiggY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkubWFwKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKCBlbGVtLCBpLCBlbGVtICk7XG5cdFx0fSApICk7XG5cdH0sXG5cblx0c2xpY2U6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggc2xpY2UuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApICk7XG5cdH0sXG5cblx0Zmlyc3Q6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVxKCAwICk7XG5cdH0sXG5cblx0bGFzdDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZXEoIC0xICk7XG5cdH0sXG5cblx0ZXE6IGZ1bmN0aW9uKCBpICkge1xuXHRcdHZhciBsZW4gPSB0aGlzLmxlbmd0aCxcblx0XHRcdGogPSAraSArICggaSA8IDAgPyBsZW4gOiAwICk7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqID49IDAgJiYgaiA8IGxlbiA/IFsgdGhpc1sgaiBdIF0gOiBbXSApO1xuXHR9LFxuXG5cdGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCk7XG5cdH0sXG5cblx0Ly8gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuXHQvLyBCZWhhdmVzIGxpa2UgYW4gQXJyYXkncyBtZXRob2QsIG5vdCBsaWtlIGEgalF1ZXJ5IG1ldGhvZC5cblx0cHVzaDogcHVzaCxcblx0c29ydDogYXJyLnNvcnQsXG5cdHNwbGljZTogYXJyLnNwbGljZVxufTtcblxualF1ZXJ5LmV4dGVuZCA9IGpRdWVyeS5mbi5leHRlbmQgPSBmdW5jdGlvbigpIHtcblx0dmFyIG9wdGlvbnMsIG5hbWUsIHNyYywgY29weSwgY29weUlzQXJyYXksIGNsb25lLFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgMCBdIHx8IHt9LFxuXHRcdGkgPSAxLFxuXHRcdGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cdFx0ZGVlcCA9IGZhbHNlO1xuXG5cdC8vIEhhbmRsZSBhIGRlZXAgY29weSBzaXR1YXRpb25cblx0aWYgKCB0eXBlb2YgdGFyZ2V0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRkZWVwID0gdGFyZ2V0O1xuXG5cdFx0Ly8gU2tpcCB0aGUgYm9vbGVhbiBhbmQgdGhlIHRhcmdldFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgaSBdIHx8IHt9O1xuXHRcdGkrKztcblx0fVxuXG5cdC8vIEhhbmRsZSBjYXNlIHdoZW4gdGFyZ2V0IGlzIGEgc3RyaW5nIG9yIHNvbWV0aGluZyAocG9zc2libGUgaW4gZGVlcCBjb3B5KVxuXHRpZiAoIHR5cGVvZiB0YXJnZXQgIT09IFwib2JqZWN0XCIgJiYgIWpRdWVyeS5pc0Z1bmN0aW9uKCB0YXJnZXQgKSApIHtcblx0XHR0YXJnZXQgPSB7fTtcblx0fVxuXG5cdC8vIEV4dGVuZCBqUXVlcnkgaXRzZWxmIGlmIG9ubHkgb25lIGFyZ3VtZW50IGlzIHBhc3NlZFxuXHRpZiAoIGkgPT09IGxlbmd0aCApIHtcblx0XHR0YXJnZXQgPSB0aGlzO1xuXHRcdGktLTtcblx0fVxuXG5cdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXG5cdFx0Ly8gT25seSBkZWFsIHdpdGggbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlc1xuXHRcdGlmICggKCBvcHRpb25zID0gYXJndW1lbnRzWyBpIF0gKSAhPSBudWxsICkge1xuXG5cdFx0XHQvLyBFeHRlbmQgdGhlIGJhc2Ugb2JqZWN0XG5cdFx0XHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRcdHNyYyA9IHRhcmdldFsgbmFtZSBdO1xuXHRcdFx0XHRjb3B5ID0gb3B0aW9uc1sgbmFtZSBdO1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbmV2ZXItZW5kaW5nIGxvb3Bcblx0XHRcdFx0aWYgKCB0YXJnZXQgPT09IGNvcHkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZWN1cnNlIGlmIHdlJ3JlIG1lcmdpbmcgcGxhaW4gb2JqZWN0cyBvciBhcnJheXNcblx0XHRcdFx0aWYgKCBkZWVwICYmIGNvcHkgJiYgKCBqUXVlcnkuaXNQbGFpbk9iamVjdCggY29weSApIHx8XG5cdFx0XHRcdFx0KCBjb3B5SXNBcnJheSA9IEFycmF5LmlzQXJyYXkoIGNvcHkgKSApICkgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGNvcHlJc0FycmF5ICkge1xuXHRcdFx0XHRcdFx0Y29weUlzQXJyYXkgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGNsb25lID0gc3JjICYmIEFycmF5LmlzQXJyYXkoIHNyYyApID8gc3JjIDogW107XG5cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIHNyYyApID8gc3JjIDoge307XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gTmV2ZXIgbW92ZSBvcmlnaW5hbCBvYmplY3RzLCBjbG9uZSB0aGVtXG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBqUXVlcnkuZXh0ZW5kKCBkZWVwLCBjbG9uZSwgY29weSApO1xuXG5cdFx0XHRcdC8vIERvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXNcblx0XHRcdFx0fSBlbHNlIGlmICggY29weSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHRhcmdldFsgbmFtZSBdID0gY29weTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbW9kaWZpZWQgb2JqZWN0XG5cdHJldHVybiB0YXJnZXQ7XG59O1xuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gVW5pcXVlIGZvciBlYWNoIGNvcHkgb2YgalF1ZXJ5IG9uIHRoZSBwYWdlXG5cdGV4cGFuZG86IFwialF1ZXJ5XCIgKyAoIHZlcnNpb24gKyBNYXRoLnJhbmRvbSgpICkucmVwbGFjZSggL1xcRC9nLCBcIlwiICksXG5cblx0Ly8gQXNzdW1lIGpRdWVyeSBpcyByZWFkeSB3aXRob3V0IHRoZSByZWFkeSBtb2R1bGVcblx0aXNSZWFkeTogdHJ1ZSxcblxuXHRlcnJvcjogZnVuY3Rpb24oIG1zZyApIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoIG1zZyApO1xuXHR9LFxuXG5cdG5vb3A6IGZ1bmN0aW9uKCkge30sXG5cblx0aXNGdW5jdGlvbjogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LnR5cGUoIG9iaiApID09PSBcImZ1bmN0aW9uXCI7XG5cdH0sXG5cblx0aXNXaW5kb3c6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0cmV0dXJuIG9iaiAhPSBudWxsICYmIG9iaiA9PT0gb2JqLndpbmRvdztcblx0fSxcblxuXHRpc051bWVyaWM6IGZ1bmN0aW9uKCBvYmogKSB7XG5cblx0XHQvLyBBcyBvZiBqUXVlcnkgMy4wLCBpc051bWVyaWMgaXMgbGltaXRlZCB0b1xuXHRcdC8vIHN0cmluZ3MgYW5kIG51bWJlcnMgKHByaW1pdGl2ZXMgb3Igb2JqZWN0cylcblx0XHQvLyB0aGF0IGNhbiBiZSBjb2VyY2VkIHRvIGZpbml0ZSBudW1iZXJzIChnaC0yNjYyKVxuXHRcdHZhciB0eXBlID0galF1ZXJ5LnR5cGUoIG9iaiApO1xuXHRcdHJldHVybiAoIHR5cGUgPT09IFwibnVtYmVyXCIgfHwgdHlwZSA9PT0gXCJzdHJpbmdcIiApICYmXG5cblx0XHRcdC8vIHBhcnNlRmxvYXQgTmFOcyBudW1lcmljLWNhc3QgZmFsc2UgcG9zaXRpdmVzIChcIlwiKVxuXHRcdFx0Ly8gLi4uYnV0IG1pc2ludGVycHJldHMgbGVhZGluZy1udW1iZXIgc3RyaW5ncywgcGFydGljdWxhcmx5IGhleCBsaXRlcmFscyAoXCIweC4uLlwiKVxuXHRcdFx0Ly8gc3VidHJhY3Rpb24gZm9yY2VzIGluZmluaXRpZXMgdG8gTmFOXG5cdFx0XHQhaXNOYU4oIG9iaiAtIHBhcnNlRmxvYXQoIG9iaiApICk7XG5cdH0sXG5cblx0aXNQbGFpbk9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHR2YXIgcHJvdG8sIEN0b3I7XG5cblx0XHQvLyBEZXRlY3Qgb2J2aW91cyBuZWdhdGl2ZXNcblx0XHQvLyBVc2UgdG9TdHJpbmcgaW5zdGVhZCBvZiBqUXVlcnkudHlwZSB0byBjYXRjaCBob3N0IG9iamVjdHNcblx0XHRpZiAoICFvYmogfHwgdG9TdHJpbmcuY2FsbCggb2JqICkgIT09IFwiW29iamVjdCBPYmplY3RdXCIgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cHJvdG8gPSBnZXRQcm90byggb2JqICk7XG5cblx0XHQvLyBPYmplY3RzIHdpdGggbm8gcHJvdG90eXBlIChlLmcuLCBgT2JqZWN0LmNyZWF0ZSggbnVsbCApYCkgYXJlIHBsYWluXG5cdFx0aWYgKCAhcHJvdG8gKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBPYmplY3RzIHdpdGggcHJvdG90eXBlIGFyZSBwbGFpbiBpZmYgdGhleSB3ZXJlIGNvbnN0cnVjdGVkIGJ5IGEgZ2xvYmFsIE9iamVjdCBmdW5jdGlvblxuXHRcdEN0b3IgPSBoYXNPd24uY2FsbCggcHJvdG8sIFwiY29uc3RydWN0b3JcIiApICYmIHByb3RvLmNvbnN0cnVjdG9yO1xuXHRcdHJldHVybiB0eXBlb2YgQ3RvciA9PT0gXCJmdW5jdGlvblwiICYmIGZuVG9TdHJpbmcuY2FsbCggQ3RvciApID09PSBPYmplY3RGdW5jdGlvblN0cmluZztcblx0fSxcblxuXHRpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiggb2JqICkge1xuXG5cdFx0LyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cblx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzbGludC9lc2xpbnQvaXNzdWVzLzYxMjVcblx0XHR2YXIgbmFtZTtcblxuXHRcdGZvciAoIG5hbWUgaW4gb2JqICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSxcblxuXHR0eXBlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdGlmICggb2JqID09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gb2JqICsgXCJcIjtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9Mi4zIG9ubHkgKGZ1bmN0aW9uaXNoIFJlZ0V4cClcblx0XHRyZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgP1xuXHRcdFx0Y2xhc3MydHlwZVsgdG9TdHJpbmcuY2FsbCggb2JqICkgXSB8fCBcIm9iamVjdFwiIDpcblx0XHRcdHR5cGVvZiBvYmo7XG5cdH0sXG5cblx0Ly8gRXZhbHVhdGVzIGEgc2NyaXB0IGluIGEgZ2xvYmFsIGNvbnRleHRcblx0Z2xvYmFsRXZhbDogZnVuY3Rpb24oIGNvZGUgKSB7XG5cdFx0RE9NRXZhbCggY29kZSApO1xuXHR9LFxuXG5cdC8vIENvbnZlcnQgZGFzaGVkIHRvIGNhbWVsQ2FzZTsgdXNlZCBieSB0aGUgY3NzIGFuZCBkYXRhIG1vZHVsZXNcblx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHQvLyBNaWNyb3NvZnQgZm9yZ290IHRvIGh1bXAgdGhlaXIgdmVuZG9yIHByZWZpeCAoIzk1NzIpXG5cdGNhbWVsQ2FzZTogZnVuY3Rpb24oIHN0cmluZyApIHtcblx0XHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoIHJtc1ByZWZpeCwgXCJtcy1cIiApLnJlcGxhY2UoIHJkYXNoQWxwaGEsIGZjYW1lbENhc2UgKTtcblx0fSxcblxuXHRlYWNoOiBmdW5jdGlvbiggb2JqLCBjYWxsYmFjayApIHtcblx0XHR2YXIgbGVuZ3RoLCBpID0gMDtcblxuXHRcdGlmICggaXNBcnJheUxpa2UoIG9iaiApICkge1xuXHRcdFx0bGVuZ3RoID0gb2JqLmxlbmd0aDtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIG9iaiApIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjay5jYWxsKCBvYmpbIGkgXSwgaSwgb2JqWyBpIF0gKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gb2JqO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seVxuXHR0cmltOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRyZXR1cm4gdGV4dCA9PSBudWxsID9cblx0XHRcdFwiXCIgOlxuXHRcdFx0KCB0ZXh0ICsgXCJcIiApLnJlcGxhY2UoIHJ0cmltLCBcIlwiICk7XG5cdH0sXG5cblx0Ly8gcmVzdWx0cyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYWtlQXJyYXk6IGZ1bmN0aW9uKCBhcnIsIHJlc3VsdHMgKSB7XG5cdFx0dmFyIHJldCA9IHJlc3VsdHMgfHwgW107XG5cblx0XHRpZiAoIGFyciAhPSBudWxsICkge1xuXHRcdFx0aWYgKCBpc0FycmF5TGlrZSggT2JqZWN0KCBhcnIgKSApICkge1xuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIHJldCxcblx0XHRcdFx0XHR0eXBlb2YgYXJyID09PSBcInN0cmluZ1wiID9cblx0XHRcdFx0XHRbIGFyciBdIDogYXJyXG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmNhbGwoIHJldCwgYXJyICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldDtcblx0fSxcblxuXHRpbkFycmF5OiBmdW5jdGlvbiggZWxlbSwgYXJyLCBpICkge1xuXHRcdHJldHVybiBhcnIgPT0gbnVsbCA/IC0xIDogaW5kZXhPZi5jYWxsKCBhcnIsIGVsZW0sIGkgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRtZXJnZTogZnVuY3Rpb24oIGZpcnN0LCBzZWNvbmQgKSB7XG5cdFx0dmFyIGxlbiA9ICtzZWNvbmQubGVuZ3RoLFxuXHRcdFx0aiA9IDAsXG5cdFx0XHRpID0gZmlyc3QubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRmaXJzdFsgaSsrIF0gPSBzZWNvbmRbIGogXTtcblx0XHR9XG5cblx0XHRmaXJzdC5sZW5ndGggPSBpO1xuXG5cdFx0cmV0dXJuIGZpcnN0O1xuXHR9LFxuXG5cdGdyZXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGludmVydCApIHtcblx0XHR2YXIgY2FsbGJhY2tJbnZlcnNlLFxuXHRcdFx0bWF0Y2hlcyA9IFtdLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsZW5ndGggPSBlbGVtcy5sZW5ndGgsXG5cdFx0XHRjYWxsYmFja0V4cGVjdCA9ICFpbnZlcnQ7XG5cblx0XHQvLyBHbyB0aHJvdWdoIHRoZSBhcnJheSwgb25seSBzYXZpbmcgdGhlIGl0ZW1zXG5cdFx0Ly8gdGhhdCBwYXNzIHRoZSB2YWxpZGF0b3IgZnVuY3Rpb25cblx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdGNhbGxiYWNrSW52ZXJzZSA9ICFjYWxsYmFjayggZWxlbXNbIGkgXSwgaSApO1xuXHRcdFx0aWYgKCBjYWxsYmFja0ludmVyc2UgIT09IGNhbGxiYWNrRXhwZWN0ICkge1xuXHRcdFx0XHRtYXRjaGVzLnB1c2goIGVsZW1zWyBpIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbWF0Y2hlcztcblx0fSxcblxuXHQvLyBhcmcgaXMgZm9yIGludGVybmFsIHVzYWdlIG9ubHlcblx0bWFwOiBmdW5jdGlvbiggZWxlbXMsIGNhbGxiYWNrLCBhcmcgKSB7XG5cdFx0dmFyIGxlbmd0aCwgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdHJldCA9IFtdO1xuXG5cdFx0Ly8gR28gdGhyb3VnaCB0aGUgYXJyYXksIHRyYW5zbGF0aW5nIGVhY2ggb2YgdGhlIGl0ZW1zIHRvIHRoZWlyIG5ldyB2YWx1ZXNcblx0XHRpZiAoIGlzQXJyYXlMaWtlKCBlbGVtcyApICkge1xuXHRcdFx0bGVuZ3RoID0gZWxlbXMubGVuZ3RoO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhbHVlID0gY2FsbGJhY2soIGVsZW1zWyBpIF0sIGksIGFyZyApO1xuXG5cdFx0XHRcdGlmICggdmFsdWUgIT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXQucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gR28gdGhyb3VnaCBldmVyeSBrZXkgb24gdGhlIG9iamVjdCxcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yICggaSBpbiBlbGVtcyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmxhdHRlbiBhbnkgbmVzdGVkIGFycmF5c1xuXHRcdHJldHVybiBjb25jYXQuYXBwbHkoIFtdLCByZXQgKTtcblx0fSxcblxuXHQvLyBBIGdsb2JhbCBHVUlEIGNvdW50ZXIgZm9yIG9iamVjdHNcblx0Z3VpZDogMSxcblxuXHQvLyBCaW5kIGEgZnVuY3Rpb24gdG8gYSBjb250ZXh0LCBvcHRpb25hbGx5IHBhcnRpYWxseSBhcHBseWluZyBhbnlcblx0Ly8gYXJndW1lbnRzLlxuXHRwcm94eTogZnVuY3Rpb24oIGZuLCBjb250ZXh0ICkge1xuXHRcdHZhciB0bXAsIGFyZ3MsIHByb3h5O1xuXG5cdFx0aWYgKCB0eXBlb2YgY29udGV4dCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRtcCA9IGZuWyBjb250ZXh0IF07XG5cdFx0XHRjb250ZXh0ID0gZm47XG5cdFx0XHRmbiA9IHRtcDtcblx0XHR9XG5cblx0XHQvLyBRdWljayBjaGVjayB0byBkZXRlcm1pbmUgaWYgdGFyZ2V0IGlzIGNhbGxhYmxlLCBpbiB0aGUgc3BlY1xuXHRcdC8vIHRoaXMgdGhyb3dzIGEgVHlwZUVycm9yLCBidXQgd2Ugd2lsbCBqdXN0IHJldHVybiB1bmRlZmluZWQuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIGZuICkgKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIFNpbXVsYXRlZCBiaW5kXG5cdFx0YXJncyA9IHNsaWNlLmNhbGwoIGFyZ3VtZW50cywgMiApO1xuXHRcdHByb3h5ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gZm4uYXBwbHkoIGNvbnRleHQgfHwgdGhpcywgYXJncy5jb25jYXQoIHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApICkgKTtcblx0XHR9O1xuXG5cdFx0Ly8gU2V0IHRoZSBndWlkIG9mIHVuaXF1ZSBoYW5kbGVyIHRvIHRoZSBzYW1lIG9mIG9yaWdpbmFsIGhhbmRsZXIsIHNvIGl0IGNhbiBiZSByZW1vdmVkXG5cdFx0cHJveHkuZ3VpZCA9IGZuLmd1aWQgPSBmbi5ndWlkIHx8IGpRdWVyeS5ndWlkKys7XG5cblx0XHRyZXR1cm4gcHJveHk7XG5cdH0sXG5cblx0bm93OiBEYXRlLm5vdyxcblxuXHQvLyBqUXVlcnkuc3VwcG9ydCBpcyBub3QgdXNlZCBpbiBDb3JlIGJ1dCBvdGhlciBwcm9qZWN0cyBhdHRhY2ggdGhlaXJcblx0Ly8gcHJvcGVydGllcyB0byBpdCBzbyBpdCBuZWVkcyB0byBleGlzdC5cblx0c3VwcG9ydDogc3VwcG9ydFxufSApO1xuXG5pZiAoIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiApIHtcblx0alF1ZXJ5LmZuWyBTeW1ib2wuaXRlcmF0b3IgXSA9IGFyclsgU3ltYm9sLml0ZXJhdG9yIF07XG59XG5cbi8vIFBvcHVsYXRlIHRoZSBjbGFzczJ0eXBlIG1hcFxualF1ZXJ5LmVhY2goIFwiQm9vbGVhbiBOdW1iZXIgU3RyaW5nIEZ1bmN0aW9uIEFycmF5IERhdGUgUmVnRXhwIE9iamVjdCBFcnJvciBTeW1ib2xcIi5zcGxpdCggXCIgXCIgKSxcbmZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRjbGFzczJ0eXBlWyBcIltvYmplY3QgXCIgKyBuYW1lICsgXCJdXCIgXSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbn0gKTtcblxuZnVuY3Rpb24gaXNBcnJheUxpa2UoIG9iaiApIHtcblxuXHQvLyBTdXBwb3J0OiByZWFsIGlPUyA4LjIgb25seSAobm90IHJlcHJvZHVjaWJsZSBpbiBzaW11bGF0b3IpXG5cdC8vIGBpbmAgY2hlY2sgdXNlZCB0byBwcmV2ZW50IEpJVCBlcnJvciAoZ2gtMjE0NSlcblx0Ly8gaGFzT3duIGlzbid0IHVzZWQgaGVyZSBkdWUgdG8gZmFsc2UgbmVnYXRpdmVzXG5cdC8vIHJlZ2FyZGluZyBOb2RlbGlzdCBsZW5ndGggaW4gSUVcblx0dmFyIGxlbmd0aCA9ICEhb2JqICYmIFwibGVuZ3RoXCIgaW4gb2JqICYmIG9iai5sZW5ndGgsXG5cdFx0dHlwZSA9IGpRdWVyeS50eXBlKCBvYmogKTtcblxuXHRpZiAoIHR5cGUgPT09IFwiZnVuY3Rpb25cIiB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHJldHVybiB0eXBlID09PSBcImFycmF5XCIgfHwgbGVuZ3RoID09PSAwIHx8XG5cdFx0dHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIiAmJiBsZW5ndGggPiAwICYmICggbGVuZ3RoIC0gMSApIGluIG9iajtcbn1cbnZhciBTaXp6bGUgPVxuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2Mi4zLjNcbiAqIGh0dHBzOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcbiAqXG4gKiBEYXRlOiAyMDE2LTA4LTA4XG4gKi9cbihmdW5jdGlvbiggd2luZG93ICkge1xuXG52YXIgaSxcblx0c3VwcG9ydCxcblx0RXhwcixcblx0Z2V0VGV4dCxcblx0aXNYTUwsXG5cdHRva2VuaXplLFxuXHRjb21waWxlLFxuXHRzZWxlY3QsXG5cdG91dGVybW9zdENvbnRleHQsXG5cdHNvcnRJbnB1dCxcblx0aGFzRHVwbGljYXRlLFxuXG5cdC8vIExvY2FsIGRvY3VtZW50IHZhcnNcblx0c2V0RG9jdW1lbnQsXG5cdGRvY3VtZW50LFxuXHRkb2NFbGVtLFxuXHRkb2N1bWVudElzSFRNTCxcblx0cmJ1Z2d5UVNBLFxuXHRyYnVnZ3lNYXRjaGVzLFxuXHRtYXRjaGVzLFxuXHRjb250YWlucyxcblxuXHQvLyBJbnN0YW5jZS1zcGVjaWZpYyBkYXRhXG5cdGV4cGFuZG8gPSBcInNpenpsZVwiICsgMSAqIG5ldyBEYXRlKCksXG5cdHByZWZlcnJlZERvYyA9IHdpbmRvdy5kb2N1bWVudCxcblx0ZGlycnVucyA9IDAsXG5cdGRvbmUgPSAwLFxuXHRjbGFzc0NhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0dG9rZW5DYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdGNvbXBpbGVyQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHRzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHtcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gMDtcblx0fSxcblxuXHQvLyBJbnN0YW5jZSBtZXRob2RzXG5cdGhhc093biA9ICh7fSkuaGFzT3duUHJvcGVydHksXG5cdGFyciA9IFtdLFxuXHRwb3AgPSBhcnIucG9wLFxuXHRwdXNoX25hdGl2ZSA9IGFyci5wdXNoLFxuXHRwdXNoID0gYXJyLnB1c2gsXG5cdHNsaWNlID0gYXJyLnNsaWNlLFxuXHQvLyBVc2UgYSBzdHJpcHBlZC1kb3duIGluZGV4T2YgYXMgaXQncyBmYXN0ZXIgdGhhbiBuYXRpdmVcblx0Ly8gaHR0cHM6Ly9qc3BlcmYuY29tL3Rob3ItaW5kZXhvZi12cy1mb3IvNVxuXHRpbmRleE9mID0gZnVuY3Rpb24oIGxpc3QsIGVsZW0gKSB7XG5cdFx0dmFyIGkgPSAwLFxuXHRcdFx0bGVuID0gbGlzdC5sZW5ndGg7XG5cdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRpZiAoIGxpc3RbaV0gPT09IGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gLTE7XG5cdH0sXG5cblx0Ym9vbGVhbnMgPSBcImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkXCIsXG5cblx0Ly8gUmVndWxhciBleHByZXNzaW9uc1xuXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc2VsZWN0b3JzLyN3aGl0ZXNwYWNlXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvQ1NTMjEvc3luZGF0YS5odG1sI3ZhbHVlLWRlZi1pZGVudGlmaWVyXG5cdGlkZW50aWZpZXIgPSBcIig/OlxcXFxcXFxcLnxbXFxcXHctXXxbXlxcMC1cXFxceGEwXSkrXCIsXG5cblx0Ly8gQXR0cmlidXRlIHNlbGVjdG9yczogaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNhdHRyaWJ1dGUtc2VsZWN0b3JzXG5cdGF0dHJpYnV0ZXMgPSBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFwiICsgaWRlbnRpZmllciArIFwiKSg/OlwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gT3BlcmF0b3IgKGNhcHR1cmUgMilcblx0XHRcIiooWypeJHwhfl0/PSlcIiArIHdoaXRlc3BhY2UgK1xuXHRcdC8vIFwiQXR0cmlidXRlIHZhbHVlcyBtdXN0IGJlIENTUyBpZGVudGlmaWVycyBbY2FwdHVyZSA1XSBvciBzdHJpbmdzIFtjYXB0dXJlIDMgb3IgY2FwdHVyZSA0XVwiXG5cdFx0XCIqKD86JygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwifChcIiArIGlkZW50aWZpZXIgKyBcIikpfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKlxcXFxdXCIsXG5cblx0cHNldWRvcyA9IFwiOihcIiArIGlkZW50aWZpZXIgKyBcIikoPzpcXFxcKChcIiArXG5cdFx0Ly8gVG8gcmVkdWNlIHRoZSBudW1iZXIgb2Ygc2VsZWN0b3JzIG5lZWRpbmcgdG9rZW5pemUgaW4gdGhlIHByZUZpbHRlciwgcHJlZmVyIGFyZ3VtZW50czpcblx0XHQvLyAxLiBxdW90ZWQgKGNhcHR1cmUgMzsgY2FwdHVyZSA0IG9yIGNhcHR1cmUgNSlcblx0XHRcIignKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJ10pKiknfFxcXCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFxcXFwiXSkqKVxcXCIpfFwiICtcblx0XHQvLyAyLiBzaW1wbGUgKGNhcHR1cmUgNilcblx0XHRcIigoPzpcXFxcXFxcXC58W15cXFxcXFxcXCgpW1xcXFxdXXxcIiArIGF0dHJpYnV0ZXMgKyBcIikqKXxcIiArXG5cdFx0Ly8gMy4gYW55dGhpbmcgZWxzZSAoY2FwdHVyZSAyKVxuXHRcdFwiLipcIiArXG5cdFx0XCIpXFxcXCl8KVwiLFxuXG5cdC8vIExlYWRpbmcgYW5kIG5vbi1lc2NhcGVkIHRyYWlsaW5nIHdoaXRlc3BhY2UsIGNhcHR1cmluZyBzb21lIG5vbi13aGl0ZXNwYWNlIGNoYXJhY3RlcnMgcHJlY2VkaW5nIHRoZSBsYXR0ZXJcblx0cndoaXRlc3BhY2UgPSBuZXcgUmVnRXhwKCB3aGl0ZXNwYWNlICsgXCIrXCIsIFwiZ1wiICksXG5cdHJ0cmltID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIrfCgoPzpefFteXFxcXFxcXFxdKSg/OlxcXFxcXFxcLikqKVwiICsgd2hpdGVzcGFjZSArIFwiKyRcIiwgXCJnXCIgKSxcblxuXHRyY29tbWEgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiosXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblx0cmNvbWJpbmF0b3JzID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFs+K35dfFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgd2hpdGVzcGFjZSArIFwiKlwiICksXG5cblx0cmF0dHJpYnV0ZVF1b3RlcyA9IG5ldyBSZWdFeHAoIFwiPVwiICsgd2hpdGVzcGFjZSArIFwiKihbXlxcXFxdJ1xcXCJdKj8pXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXF1cIiwgXCJnXCIgKSxcblxuXHRycHNldWRvID0gbmV3IFJlZ0V4cCggcHNldWRvcyApLFxuXHRyaWRlbnRpZmllciA9IG5ldyBSZWdFeHAoIFwiXlwiICsgaWRlbnRpZmllciArIFwiJFwiICksXG5cblx0bWF0Y2hFeHByID0ge1xuXHRcdFwiSURcIjogbmV3IFJlZ0V4cCggXCJeIyhcIiArIGlkZW50aWZpZXIgKyBcIilcIiApLFxuXHRcdFwiQ0xBU1NcIjogbmV3IFJlZ0V4cCggXCJeXFxcXC4oXCIgKyBpZGVudGlmaWVyICsgXCIpXCIgKSxcblx0XHRcIlRBR1wiOiBuZXcgUmVnRXhwKCBcIl4oXCIgKyBpZGVudGlmaWVyICsgXCJ8WypdKVwiICksXG5cdFx0XCJBVFRSXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgYXR0cmlidXRlcyApLFxuXHRcdFwiUFNFVURPXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgcHNldWRvcyApLFxuXHRcdFwiQ0hJTERcIjogbmV3IFJlZ0V4cCggXCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXFxcKFwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooZXZlbnxvZGR8KChbKy1dfCkoXFxcXGQqKW58KVwiICsgd2hpdGVzcGFjZSArIFwiKig/OihbKy1dfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFx0XCIqKFxcXFxkKyl8KSlcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpXCIsIFwiaVwiICksXG5cdFx0XCJib29sXCI6IG5ldyBSZWdFeHAoIFwiXig/OlwiICsgYm9vbGVhbnMgKyBcIikkXCIsIFwiaVwiICksXG5cdFx0Ly8gRm9yIHVzZSBpbiBsaWJyYXJpZXMgaW1wbGVtZW50aW5nIC5pcygpXG5cdFx0Ly8gV2UgdXNlIHRoaXMgZm9yIFBPUyBtYXRjaGluZyBpbiBgc2VsZWN0YFxuXHRcdFwibmVlZHNDb250ZXh0XCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFxcXChcIiArXG5cdFx0XHR3aGl0ZXNwYWNlICsgXCIqKCg/Oi1cXFxcZCk/XFxcXGQqKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfCkoPz1bXi1dfCQpXCIsIFwiaVwiIClcblx0fSxcblxuXHRyaW5wdXRzID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxcblx0cmhlYWRlciA9IC9eaFxcZCQvaSxcblxuXHRybmF0aXZlID0gL15bXntdK1xce1xccypcXFtuYXRpdmUgXFx3LyxcblxuXHQvLyBFYXNpbHktcGFyc2VhYmxlL3JldHJpZXZhYmxlIElEIG9yIFRBRyBvciBDTEFTUyBzZWxlY3RvcnNcblx0cnF1aWNrRXhwciA9IC9eKD86IyhbXFx3LV0rKXwoXFx3Kyl8XFwuKFtcXHctXSspKSQvLFxuXG5cdHJzaWJsaW5nID0gL1srfl0vLFxuXG5cdC8vIENTUyBlc2NhcGVzXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL0NTUzIxL3N5bmRhdGEuaHRtbCNlc2NhcGVkLWNoYXJhY3RlcnNcblx0cnVuZXNjYXBlID0gbmV3IFJlZ0V4cCggXCJcXFxcXFxcXChbXFxcXGRhLWZdezEsNn1cIiArIHdoaXRlc3BhY2UgKyBcIj98KFwiICsgd2hpdGVzcGFjZSArIFwiKXwuKVwiLCBcImlnXCIgKSxcblx0ZnVuZXNjYXBlID0gZnVuY3Rpb24oIF8sIGVzY2FwZWQsIGVzY2FwZWRXaGl0ZXNwYWNlICkge1xuXHRcdHZhciBoaWdoID0gXCIweFwiICsgZXNjYXBlZCAtIDB4MTAwMDA7XG5cdFx0Ly8gTmFOIG1lYW5zIG5vbi1jb2RlcG9pbnRcblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94PDI0XG5cdFx0Ly8gV29ya2Fyb3VuZCBlcnJvbmVvdXMgbnVtZXJpYyBpbnRlcnByZXRhdGlvbiBvZiArXCIweFwiXG5cdFx0cmV0dXJuIGhpZ2ggIT09IGhpZ2ggfHwgZXNjYXBlZFdoaXRlc3BhY2UgP1xuXHRcdFx0ZXNjYXBlZCA6XG5cdFx0XHRoaWdoIDwgMCA/XG5cdFx0XHRcdC8vIEJNUCBjb2RlcG9pbnRcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCArIDB4MTAwMDAgKSA6XG5cdFx0XHRcdC8vIFN1cHBsZW1lbnRhbCBQbGFuZSBjb2RlcG9pbnQgKHN1cnJvZ2F0ZSBwYWlyKVxuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoID4+IDEwIHwgMHhEODAwLCBoaWdoICYgMHgzRkYgfCAweERDMDAgKTtcblx0fSxcblxuXHQvLyBDU1Mgc3RyaW5nL2lkZW50aWZpZXIgc2VyaWFsaXphdGlvblxuXHQvLyBodHRwczovL2RyYWZ0cy5jc3N3Zy5vcmcvY3Nzb20vI2NvbW1vbi1zZXJpYWxpemluZy1pZGlvbXNcblx0cmNzc2VzY2FwZSA9IC8oW1xcMC1cXHgxZlxceDdmXXxeLT9cXGQpfF4tJHxbXlxcMC1cXHgxZlxceDdmLVxcdUZGRkZcXHctXS9nLFxuXHRmY3NzZXNjYXBlID0gZnVuY3Rpb24oIGNoLCBhc0NvZGVQb2ludCApIHtcblx0XHRpZiAoIGFzQ29kZVBvaW50ICkge1xuXG5cdFx0XHQvLyBVKzAwMDAgTlVMTCBiZWNvbWVzIFUrRkZGRCBSRVBMQUNFTUVOVCBDSEFSQUNURVJcblx0XHRcdGlmICggY2ggPT09IFwiXFwwXCIgKSB7XG5cdFx0XHRcdHJldHVybiBcIlxcdUZGRkRcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udHJvbCBjaGFyYWN0ZXJzIGFuZCAoZGVwZW5kZW50IHVwb24gcG9zaXRpb24pIG51bWJlcnMgZ2V0IGVzY2FwZWQgYXMgY29kZSBwb2ludHNcblx0XHRcdHJldHVybiBjaC5zbGljZSggMCwgLTEgKSArIFwiXFxcXFwiICsgY2guY2hhckNvZGVBdCggY2gubGVuZ3RoIC0gMSApLnRvU3RyaW5nKCAxNiApICsgXCIgXCI7XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXIgcG90ZW50aWFsbHktc3BlY2lhbCBBU0NJSSBjaGFyYWN0ZXJzIGdldCBiYWNrc2xhc2gtZXNjYXBlZFxuXHRcdHJldHVybiBcIlxcXFxcIiArIGNoO1xuXHR9LFxuXG5cdC8vIFVzZWQgZm9yIGlmcmFtZXNcblx0Ly8gU2VlIHNldERvY3VtZW50KClcblx0Ly8gUmVtb3ZpbmcgdGhlIGZ1bmN0aW9uIHdyYXBwZXIgY2F1c2VzIGEgXCJQZXJtaXNzaW9uIERlbmllZFwiXG5cdC8vIGVycm9yIGluIElFXG5cdHVubG9hZEhhbmRsZXIgPSBmdW5jdGlvbigpIHtcblx0XHRzZXREb2N1bWVudCgpO1xuXHR9LFxuXG5cdGRpc2FibGVkQW5jZXN0b3IgPSBhZGRDb21iaW5hdG9yKFxuXHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IHRydWUgJiYgKFwiZm9ybVwiIGluIGVsZW0gfHwgXCJsYWJlbFwiIGluIGVsZW0pO1xuXHRcdH0sXG5cdFx0eyBkaXI6IFwicGFyZW50Tm9kZVwiLCBuZXh0OiBcImxlZ2VuZFwiIH1cblx0KTtcblxuLy8gT3B0aW1pemUgZm9yIHB1c2guYXBwbHkoIF8sIE5vZGVMaXN0IClcbnRyeSB7XG5cdHB1c2guYXBwbHkoXG5cdFx0KGFyciA9IHNsaWNlLmNhbGwoIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzICkpLFxuXHRcdHByZWZlcnJlZERvYy5jaGlsZE5vZGVzXG5cdCk7XG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8NC4wXG5cdC8vIERldGVjdCBzaWxlbnRseSBmYWlsaW5nIHB1c2guYXBwbHlcblx0YXJyWyBwcmVmZXJyZWREb2MuY2hpbGROb2Rlcy5sZW5ndGggXS5ub2RlVHlwZTtcbn0gY2F0Y2ggKCBlICkge1xuXHRwdXNoID0geyBhcHBseTogYXJyLmxlbmd0aCA/XG5cblx0XHQvLyBMZXZlcmFnZSBzbGljZSBpZiBwb3NzaWJsZVxuXHRcdGZ1bmN0aW9uKCB0YXJnZXQsIGVscyApIHtcblx0XHRcdHB1c2hfbmF0aXZlLmFwcGx5KCB0YXJnZXQsIHNsaWNlLmNhbGwoZWxzKSApO1xuXHRcdH0gOlxuXG5cdFx0Ly8gU3VwcG9ydDogSUU8OVxuXHRcdC8vIE90aGVyd2lzZSBhcHBlbmQgZGlyZWN0bHlcblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHR2YXIgaiA9IHRhcmdldC5sZW5ndGgsXG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0Ly8gQ2FuJ3QgdHJ1c3QgTm9kZUxpc3QubGVuZ3RoXG5cdFx0XHR3aGlsZSAoICh0YXJnZXRbaisrXSA9IGVsc1tpKytdKSApIHt9XG5cdFx0XHR0YXJnZXQubGVuZ3RoID0gaiAtIDE7XG5cdFx0fVxuXHR9O1xufVxuXG5mdW5jdGlvbiBTaXp6bGUoIHNlbGVjdG9yLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICkge1xuXHR2YXIgbSwgaSwgZWxlbSwgbmlkLCBtYXRjaCwgZ3JvdXBzLCBuZXdTZWxlY3Rvcixcblx0XHRuZXdDb250ZXh0ID0gY29udGV4dCAmJiBjb250ZXh0Lm93bmVyRG9jdW1lbnQsXG5cblx0XHQvLyBub2RlVHlwZSBkZWZhdWx0cyB0byA5LCBzaW5jZSBjb250ZXh0IGRlZmF1bHRzIHRvIGRvY3VtZW50XG5cdFx0bm9kZVR5cGUgPSBjb250ZXh0ID8gY29udGV4dC5ub2RlVHlwZSA6IDk7XG5cblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0Ly8gUmV0dXJuIGVhcmx5IGZyb20gY2FsbHMgd2l0aCBpbnZhbGlkIHNlbGVjdG9yIG9yIGNvbnRleHRcblx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgfHwgIXNlbGVjdG9yIHx8XG5cdFx0bm9kZVR5cGUgIT09IDEgJiYgbm9kZVR5cGUgIT09IDkgJiYgbm9kZVR5cGUgIT09IDExICkge1xuXG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvLyBUcnkgdG8gc2hvcnRjdXQgZmluZCBvcGVyYXRpb25zIChhcyBvcHBvc2VkIHRvIGZpbHRlcnMpIGluIEhUTUwgZG9jdW1lbnRzXG5cdGlmICggIXNlZWQgKSB7XG5cblx0XHRpZiAoICggY29udGV4dCA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogcHJlZmVycmVkRG9jICkgIT09IGRvY3VtZW50ICkge1xuXHRcdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0XHR9XG5cdFx0Y29udGV4dCA9IGNvbnRleHQgfHwgZG9jdW1lbnQ7XG5cblx0XHRpZiAoIGRvY3VtZW50SXNIVE1MICkge1xuXG5cdFx0XHQvLyBJZiB0aGUgc2VsZWN0b3IgaXMgc3VmZmljaWVudGx5IHNpbXBsZSwgdHJ5IHVzaW5nIGEgXCJnZXQqQnkqXCIgRE9NIG1ldGhvZFxuXHRcdFx0Ly8gKGV4Y2VwdGluZyBEb2N1bWVudEZyYWdtZW50IGNvbnRleHQsIHdoZXJlIHRoZSBtZXRob2RzIGRvbid0IGV4aXN0KVxuXHRcdFx0aWYgKCBub2RlVHlwZSAhPT0gMTEgJiYgKG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHQvLyBJRCBzZWxlY3RvclxuXHRcdFx0XHRpZiAoIChtID0gbWF0Y2hbMV0pICkge1xuXG5cdFx0XHRcdFx0Ly8gRG9jdW1lbnQgY29udGV4dFxuXHRcdFx0XHRcdGlmICggbm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApKSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0XHQvLyBUT0RPOiBpZGVudGlmeSB2ZXJzaW9uc1xuXHRcdFx0XHRcdFx0XHQvLyBnZXRFbGVtZW50QnlJZCBjYW4gbWF0Y2ggZWxlbWVudHMgYnkgbmFtZSBpbnN0ZWFkIG9mIElEXG5cdFx0XHRcdFx0XHRcdGlmICggZWxlbS5pZCA9PT0gbSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBFbGVtZW50IGNvbnRleHRcblx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0Ly8gVE9ETzogaWRlbnRpZnkgdmVyc2lvbnNcblx0XHRcdFx0XHRcdC8vIGdldEVsZW1lbnRCeUlkIGNhbiBtYXRjaCBlbGVtZW50cyBieSBuYW1lIGluc3RlYWQgb2YgSURcblx0XHRcdFx0XHRcdGlmICggbmV3Q29udGV4dCAmJiAoZWxlbSA9IG5ld0NvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIG0gKSkgJiZcblx0XHRcdFx0XHRcdFx0Y29udGFpbnMoIGNvbnRleHQsIGVsZW0gKSAmJlxuXHRcdFx0XHRcdFx0XHRlbGVtLmlkID09PSBtICkge1xuXG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHlwZSBzZWxlY3RvclxuXHRcdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFsyXSApIHtcblx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCBzZWxlY3RvciApICk7XG5cdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdFx0Ly8gQ2xhc3Mgc2VsZWN0b3Jcblx0XHRcdFx0fSBlbHNlIGlmICggKG0gPSBtYXRjaFszXSkgJiYgc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmXG5cdFx0XHRcdFx0Y29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICkge1xuXG5cdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCBtICkgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUYWtlIGFkdmFudGFnZSBvZiBxdWVyeVNlbGVjdG9yQWxsXG5cdFx0XHRpZiAoIHN1cHBvcnQucXNhICYmXG5cdFx0XHRcdCFjb21waWxlckNhY2hlWyBzZWxlY3RvciArIFwiIFwiIF0gJiZcblx0XHRcdFx0KCFyYnVnZ3lRU0EgfHwgIXJidWdneVFTQS50ZXN0KCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHRpZiAoIG5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0XHRcdG5ld1NlbGVjdG9yID0gc2VsZWN0b3I7XG5cblx0XHRcdFx0Ly8gcVNBIGxvb2tzIG91dHNpZGUgRWxlbWVudCBjb250ZXh0LCB3aGljaCBpcyBub3Qgd2hhdCB3ZSB3YW50XG5cdFx0XHRcdC8vIFRoYW5rcyB0byBBbmRyZXcgRHVwb250IGZvciB0aGlzIHdvcmthcm91bmQgdGVjaG5pcXVlXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OFxuXHRcdFx0XHQvLyBFeGNsdWRlIG9iamVjdCBlbGVtZW50c1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHRcdFx0XHQvLyBDYXB0dXJlIHRoZSBjb250ZXh0IElELCBzZXR0aW5nIGl0IGZpcnN0IGlmIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdGlmICggKG5pZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKCBcImlkXCIgKSkgKSB7XG5cdFx0XHRcdFx0XHRuaWQgPSBuaWQucmVwbGFjZSggcmNzc2VzY2FwZSwgZmNzc2VzY2FwZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb250ZXh0LnNldEF0dHJpYnV0ZSggXCJpZFwiLCAobmlkID0gZXhwYW5kbykgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBQcmVmaXggZXZlcnkgc2VsZWN0b3IgaW4gdGhlIGxpc3Rcblx0XHRcdFx0XHRncm91cHMgPSB0b2tlbml6ZSggc2VsZWN0b3IgKTtcblx0XHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGdyb3Vwc1tpXSA9IFwiI1wiICsgbmlkICsgXCIgXCIgKyB0b1NlbGVjdG9yKCBncm91cHNbaV0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bmV3U2VsZWN0b3IgPSBncm91cHMuam9pbiggXCIsXCIgKTtcblxuXHRcdFx0XHRcdC8vIEV4cGFuZCBjb250ZXh0IGZvciBzaWJsaW5nIHNlbGVjdG9yc1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSByc2libGluZy50ZXN0KCBzZWxlY3RvciApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fFxuXHRcdFx0XHRcdFx0Y29udGV4dDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggbmV3U2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRcdG5ld0NvbnRleHQucXVlcnlTZWxlY3RvckFsbCggbmV3U2VsZWN0b3IgKVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKCBxc2FFcnJvciApIHtcblx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0aWYgKCBuaWQgPT09IGV4cGFuZG8gKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRleHQucmVtb3ZlQXR0cmlidXRlKCBcImlkXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBBbGwgb3RoZXJzXG5cdHJldHVybiBzZWxlY3QoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBrZXktdmFsdWUgY2FjaGVzIG9mIGxpbWl0ZWQgc2l6ZVxuICogQHJldHVybnMge2Z1bmN0aW9uKHN0cmluZywgb2JqZWN0KX0gUmV0dXJucyB0aGUgT2JqZWN0IGRhdGEgYWZ0ZXIgc3RvcmluZyBpdCBvbiBpdHNlbGYgd2l0aFxuICpcdHByb3BlcnR5IG5hbWUgdGhlIChzcGFjZS1zdWZmaXhlZCkgc3RyaW5nIGFuZCAoaWYgdGhlIGNhY2hlIGlzIGxhcmdlciB0aGFuIEV4cHIuY2FjaGVMZW5ndGgpXG4gKlx0ZGVsZXRpbmcgdGhlIG9sZGVzdCBlbnRyeVxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWNoZSgpIHtcblx0dmFyIGtleXMgPSBbXTtcblxuXHRmdW5jdGlvbiBjYWNoZSgga2V5LCB2YWx1ZSApIHtcblx0XHQvLyBVc2UgKGtleSArIFwiIFwiKSB0byBhdm9pZCBjb2xsaXNpb24gd2l0aCBuYXRpdmUgcHJvdG90eXBlIHByb3BlcnRpZXMgKHNlZSBJc3N1ZSAjMTU3KVxuXHRcdGlmICgga2V5cy5wdXNoKCBrZXkgKyBcIiBcIiApID4gRXhwci5jYWNoZUxlbmd0aCApIHtcblx0XHRcdC8vIE9ubHkga2VlcCB0aGUgbW9zdCByZWNlbnQgZW50cmllc1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBlbGVtZW50IGFuZCByZXR1cm5zIGEgYm9vbGVhbiByZXN1bHRcbiAqL1xuZnVuY3Rpb24gYXNzZXJ0KCBmbiApIHtcblx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImZpZWxkc2V0XCIpO1xuXG5cdHRyeSB7XG5cdFx0cmV0dXJuICEhZm4oIGVsICk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0gZmluYWxseSB7XG5cdFx0Ly8gUmVtb3ZlIGZyb20gaXRzIHBhcmVudCBieSBkZWZhdWx0XG5cdFx0aWYgKCBlbC5wYXJlbnROb2RlICkge1xuXHRcdFx0ZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggZWwgKTtcblx0XHR9XG5cdFx0Ly8gcmVsZWFzZSBtZW1vcnkgaW4gSUVcblx0XHRlbCA9IG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSBzYW1lIGhhbmRsZXIgZm9yIGFsbCBvZiB0aGUgc3BlY2lmaWVkIGF0dHJzXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cnMgUGlwZS1zZXBhcmF0ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIFRoZSBtZXRob2QgdGhhdCB3aWxsIGJlIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gYWRkSGFuZGxlKCBhdHRycywgaGFuZGxlciApIHtcblx0dmFyIGFyciA9IGF0dHJzLnNwbGl0KFwifFwiKSxcblx0XHRpID0gYXJyLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRFeHByLmF0dHJIYW5kbGVbIGFycltpXSBdID0gaGFuZGxlcjtcblx0fVxufVxuXG4vKipcbiAqIENoZWNrcyBkb2N1bWVudCBvcmRlciBvZiB0d28gc2libGluZ3NcbiAqIEBwYXJhbSB7RWxlbWVudH0gYVxuICogQHBhcmFtIHtFbGVtZW50fSBiXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIGxlc3MgdGhhbiAwIGlmIGEgcHJlY2VkZXMgYiwgZ3JlYXRlciB0aGFuIDAgaWYgYSBmb2xsb3dzIGJcbiAqL1xuZnVuY3Rpb24gc2libGluZ0NoZWNrKCBhLCBiICkge1xuXHR2YXIgY3VyID0gYiAmJiBhLFxuXHRcdGRpZmYgPSBjdXIgJiYgYS5ub2RlVHlwZSA9PT0gMSAmJiBiLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRhLnNvdXJjZUluZGV4IC0gYi5zb3VyY2VJbmRleDtcblxuXHQvLyBVc2UgSUUgc291cmNlSW5kZXggaWYgYXZhaWxhYmxlIG9uIGJvdGggbm9kZXNcblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0Ly8gQ2hlY2sgaWYgYiBmb2xsb3dzIGFcblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIDplbmFibGVkLzpkaXNhYmxlZFxuICogQHBhcmFtIHtCb29sZWFufSBkaXNhYmxlZCB0cnVlIGZvciA6ZGlzYWJsZWQ7IGZhbHNlIGZvciA6ZW5hYmxlZFxuICovXG5mdW5jdGlvbiBjcmVhdGVEaXNhYmxlZFBzZXVkbyggZGlzYWJsZWQgKSB7XG5cblx0Ly8gS25vd24gOmRpc2FibGVkIGZhbHNlIHBvc2l0aXZlczogZmllbGRzZXRbZGlzYWJsZWRdID4gbGVnZW5kOm50aC1vZi10eXBlKG4rMikgOmNhbi1kaXNhYmxlXG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE9ubHkgY2VydGFpbiBlbGVtZW50cyBjYW4gbWF0Y2ggOmVuYWJsZWQgb3IgOmRpc2FibGVkXG5cdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc2NyaXB0aW5nLmh0bWwjc2VsZWN0b3ItZW5hYmxlZFxuXHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3NjcmlwdGluZy5odG1sI3NlbGVjdG9yLWRpc2FibGVkXG5cdFx0aWYgKCBcImZvcm1cIiBpbiBlbGVtICkge1xuXG5cdFx0XHQvLyBDaGVjayBmb3IgaW5oZXJpdGVkIGRpc2FibGVkbmVzcyBvbiByZWxldmFudCBub24tZGlzYWJsZWQgZWxlbWVudHM6XG5cdFx0XHQvLyAqIGxpc3RlZCBmb3JtLWFzc29jaWF0ZWQgZWxlbWVudHMgaW4gYSBkaXNhYmxlZCBmaWVsZHNldFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NhdGVnb3J5LWxpc3RlZFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NvbmNlcHQtZmUtZGlzYWJsZWRcblx0XHRcdC8vICogb3B0aW9uIGVsZW1lbnRzIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdC8vICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvZm9ybXMuaHRtbCNjb25jZXB0LW9wdGlvbi1kaXNhYmxlZFxuXHRcdFx0Ly8gQWxsIHN1Y2ggZWxlbWVudHMgaGF2ZSBhIFwiZm9ybVwiIHByb3BlcnR5LlxuXHRcdFx0aWYgKCBlbGVtLnBhcmVudE5vZGUgJiYgZWxlbS5kaXNhYmxlZCA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdFx0Ly8gT3B0aW9uIGVsZW1lbnRzIGRlZmVyIHRvIGEgcGFyZW50IG9wdGdyb3VwIGlmIHByZXNlbnRcblx0XHRcdFx0aWYgKCBcImxhYmVsXCIgaW4gZWxlbSApIHtcblx0XHRcdFx0XHRpZiAoIFwibGFiZWxcIiBpbiBlbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5wYXJlbnROb2RlLmRpc2FibGVkID09PSBkaXNhYmxlZDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDYgLSAxMVxuXHRcdFx0XHQvLyBVc2UgdGhlIGlzRGlzYWJsZWQgc2hvcnRjdXQgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGRpc2FibGVkIGZpZWxkc2V0IGFuY2VzdG9yc1xuXHRcdFx0XHRyZXR1cm4gZWxlbS5pc0Rpc2FibGVkID09PSBkaXNhYmxlZCB8fFxuXG5cdFx0XHRcdFx0Ly8gV2hlcmUgdGhlcmUgaXMgbm8gaXNEaXNhYmxlZCwgY2hlY2sgbWFudWFsbHlcblx0XHRcdFx0XHQvKiBqc2hpbnQgLVcwMTggKi9cblx0XHRcdFx0XHRlbGVtLmlzRGlzYWJsZWQgIT09ICFkaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0ZGlzYWJsZWRBbmNlc3RvciggZWxlbSApID09PSBkaXNhYmxlZDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXG5cdFx0Ly8gVHJ5IHRvIHdpbm5vdyBvdXQgZWxlbWVudHMgdGhhdCBjYW4ndCBiZSBkaXNhYmxlZCBiZWZvcmUgdHJ1c3RpbmcgdGhlIGRpc2FibGVkIHByb3BlcnR5LlxuXHRcdC8vIFNvbWUgdmljdGltcyBnZXQgY2F1Z2h0IGluIG91ciBuZXQgKGxhYmVsLCBsZWdlbmQsIG1lbnUsIHRyYWNrKSwgYnV0IGl0IHNob3VsZG4ndFxuXHRcdC8vIGV2ZW4gZXhpc3Qgb24gdGhlbSwgbGV0IGFsb25lIGhhdmUgYSBib29sZWFuIHZhbHVlLlxuXHRcdH0gZWxzZSBpZiAoIFwibGFiZWxcIiBpbiBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdH1cblxuXHRcdC8vIFJlbWFpbmluZyBlbGVtZW50cyBhcmUgbmVpdGhlciA6ZW5hYmxlZCBub3IgOmRpc2FibGVkXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgcG9zaXRpb25hbHNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oIGZuICkge1xuXHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBhcmd1bWVudCApIHtcblx0XHRhcmd1bWVudCA9ICthcmd1bWVudDtcblx0XHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0dmFyIGosXG5cdFx0XHRcdG1hdGNoSW5kZXhlcyA9IGZuKCBbXSwgc2VlZC5sZW5ndGgsIGFyZ3VtZW50ICksXG5cdFx0XHRcdGkgPSBtYXRjaEluZGV4ZXMubGVuZ3RoO1xuXG5cdFx0XHQvLyBNYXRjaCBlbGVtZW50cyBmb3VuZCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4ZXNcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoIHNlZWRbIChqID0gbWF0Y2hJbmRleGVzW2ldKSBdICkge1xuXHRcdFx0XHRcdHNlZWRbal0gPSAhKG1hdGNoZXNbal0gPSBzZWVkW2pdKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBub2RlIGZvciB2YWxpZGl0eSBhcyBhIFNpenpsZSBjb250ZXh0XG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0PX0gY29udGV4dFxuICogQHJldHVybnMge0VsZW1lbnR8T2JqZWN0fEJvb2xlYW59IFRoZSBpbnB1dCBub2RlIGlmIGFjY2VwdGFibGUsIG90aGVyd2lzZSBhIGZhbHN5IHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHRlc3RDb250ZXh0KCBjb250ZXh0ICkge1xuXHRyZXR1cm4gY29udGV4dCAmJiB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjb250ZXh0O1xufVxuXG4vLyBFeHBvc2Ugc3VwcG9ydCB2YXJzIGZvciBjb252ZW5pZW5jZVxuc3VwcG9ydCA9IFNpenpsZS5zdXBwb3J0ID0ge307XG5cbi8qKlxuICogRGV0ZWN0cyBYTUwgbm9kZXNcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IGVsZW0gQW4gZWxlbWVudCBvciBhIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZmYgZWxlbSBpcyBhIG5vbi1IVE1MIFhNTCBub2RlXG4gKi9cbmlzWE1MID0gU2l6emxlLmlzWE1MID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdC8vIGRvY3VtZW50RWxlbWVudCBpcyB2ZXJpZmllZCBmb3IgY2FzZXMgd2hlcmUgaXQgZG9lc24ndCB5ZXQgZXhpc3Rcblx0Ly8gKHN1Y2ggYXMgbG9hZGluZyBpZnJhbWVzIGluIElFIC0gIzQ4MzMpXG5cdHZhciBkb2N1bWVudEVsZW1lbnQgPSBlbGVtICYmIChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSkuZG9jdW1lbnRFbGVtZW50O1xuXHRyZXR1cm4gZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lICE9PSBcIkhUTUxcIiA6IGZhbHNlO1xufTtcblxuLyoqXG4gKiBTZXRzIGRvY3VtZW50LXJlbGF0ZWQgdmFyaWFibGVzIG9uY2UgYmFzZWQgb24gdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IFtkb2NdIEFuIGVsZW1lbnQgb3IgZG9jdW1lbnQgb2JqZWN0IHRvIHVzZSB0byBzZXQgdGhlIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKi9cbnNldERvY3VtZW50ID0gU2l6emxlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oIG5vZGUgKSB7XG5cdHZhciBoYXNDb21wYXJlLCBzdWJXaW5kb3csXG5cdFx0ZG9jID0gbm9kZSA/IG5vZGUub3duZXJEb2N1bWVudCB8fCBub2RlIDogcHJlZmVycmVkRG9jO1xuXG5cdC8vIFJldHVybiBlYXJseSBpZiBkb2MgaXMgaW52YWxpZCBvciBhbHJlYWR5IHNlbGVjdGVkXG5cdGlmICggZG9jID09PSBkb2N1bWVudCB8fCBkb2Mubm9kZVR5cGUgIT09IDkgfHwgIWRvYy5kb2N1bWVudEVsZW1lbnQgKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50O1xuXHR9XG5cblx0Ly8gVXBkYXRlIGdsb2JhbCB2YXJpYWJsZXNcblx0ZG9jdW1lbnQgPSBkb2M7XG5cdGRvY0VsZW0gPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdGRvY3VtZW50SXNIVE1MID0gIWlzWE1MKCBkb2N1bWVudCApO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDktMTEsIEVkZ2Vcblx0Ly8gQWNjZXNzaW5nIGlmcmFtZSBkb2N1bWVudHMgYWZ0ZXIgdW5sb2FkIHRocm93cyBcInBlcm1pc3Npb24gZGVuaWVkXCIgZXJyb3JzIChqUXVlcnkgIzEzOTM2KVxuXHRpZiAoIHByZWZlcnJlZERvYyAhPT0gZG9jdW1lbnQgJiZcblx0XHQoc3ViV2luZG93ID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcpICYmIHN1YldpbmRvdy50b3AgIT09IHN1YldpbmRvdyApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDExLCBFZGdlXG5cdFx0aWYgKCBzdWJXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lciApIHtcblx0XHRcdHN1YldpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcInVubG9hZFwiLCB1bmxvYWRIYW5kbGVyLCBmYWxzZSApO1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgOSAtIDEwIG9ubHlcblx0XHR9IGVsc2UgaWYgKCBzdWJXaW5kb3cuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRzdWJXaW5kb3cuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgdW5sb2FkSGFuZGxlciApO1xuXHRcdH1cblx0fVxuXG5cdC8qIEF0dHJpYnV0ZXNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIFN1cHBvcnQ6IElFPDhcblx0Ly8gVmVyaWZ5IHRoYXQgZ2V0QXR0cmlidXRlIHJlYWxseSByZXR1cm5zIGF0dHJpYnV0ZXMgYW5kIG5vdCBwcm9wZXJ0aWVzXG5cdC8vIChleGNlcHRpbmcgSUU4IGJvb2xlYW5zKVxuXHRzdXBwb3J0LmF0dHJpYnV0ZXMgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmNsYXNzTmFtZSA9IFwiaVwiO1xuXHRcdHJldHVybiAhZWwuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpO1xuXHR9KTtcblxuXHQvKiBnZXRFbGVtZW50KHMpQnkqXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBDaGVjayBpZiBnZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikgcmV0dXJucyBvbmx5IGVsZW1lbnRzXG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVDb21tZW50KFwiXCIpICk7XG5cdFx0cmV0dXJuICFlbC5nZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBTdXBwb3J0OiBJRTw5XG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApO1xuXG5cdC8vIFN1cHBvcnQ6IElFPDEwXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRCeUlkIHJldHVybnMgZWxlbWVudHMgYnkgbmFtZVxuXHQvLyBUaGUgYnJva2VuIGdldEVsZW1lbnRCeUlkIG1ldGhvZHMgZG9uJ3QgcGljayB1cCBwcm9ncmFtbWF0aWNhbGx5LXNldCBuYW1lcyxcblx0Ly8gc28gdXNlIGEgcm91bmRhYm91dCBnZXRFbGVtZW50c0J5TmFtZSB0ZXN0XG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pZCA9IGV4cGFuZG87XG5cdFx0cmV0dXJuICFkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoIGV4cGFuZG8gKS5sZW5ndGg7XG5cdH0pO1xuXG5cdC8vIElEIGZpbHRlciBhbmQgZmluZFxuXHRpZiAoIHN1cHBvcnQuZ2V0QnlJZCApIHtcblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmdldEF0dHJpYnV0ZShcImlkXCIpID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cdFx0XHRcdHJldHVybiBlbGVtID8gWyBlbGVtIF0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSAgZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBub2RlID0gdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlTm9kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuXHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRyZXR1cm4gbm9kZSAmJiBub2RlLnZhbHVlID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA2IC0gNyBvbmx5XG5cdFx0Ly8gZ2V0RWxlbWVudEJ5SWQgaXMgbm90IHJlbGlhYmxlIGFzIGEgZmluZCBzaG9ydGN1dFxuXHRcdEV4cHIuZmluZFtcIklEXCJdID0gZnVuY3Rpb24oIGlkLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50QnlJZCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdFx0dmFyIG5vZGUsIGksIGVsZW1zLFxuXHRcdFx0XHRcdGVsZW0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBpZCApO1xuXG5cdFx0XHRcdGlmICggZWxlbSApIHtcblxuXHRcdFx0XHRcdC8vIFZlcmlmeSB0aGUgaWQgYXR0cmlidXRlXG5cdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdGlmICggbm9kZSAmJiBub2RlLnZhbHVlID09PSBpZCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBbIGVsZW0gXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBGYWxsIGJhY2sgb24gZ2V0RWxlbWVudHNCeU5hbWVcblx0XHRcdFx0XHRlbGVtcyA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeU5hbWUoIGlkICk7XG5cdFx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1zW2krK10pICkge1xuXHRcdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdFx0aWYgKCBub2RlICYmIG5vZGUudmFsdWUgPT09IGlkICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gWyBlbGVtIF07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvLyBUYWdcblx0RXhwci5maW5kW1wiVEFHXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/XG5cdFx0ZnVuY3Rpb24oIHRhZywgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRG9jdW1lbnRGcmFnbWVudCBub2RlcyBkb24ndCBoYXZlIGdFQlROXG5cdFx0XHR9IGVsc2UgaWYgKCBzdXBwb3J0LnFzYSApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCggdGFnICk7XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdHRtcCA9IFtdLFxuXHRcdFx0XHRpID0gMCxcblx0XHRcdFx0Ly8gQnkgaGFwcHkgY29pbmNpZGVuY2UsIGEgKGJyb2tlbikgZ0VCVE4gYXBwZWFycyBvbiBEb2N1bWVudEZyYWdtZW50IG5vZGVzIHRvb1xuXHRcdFx0XHRyZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnICk7XG5cblx0XHRcdC8vIEZpbHRlciBvdXQgcG9zc2libGUgY29tbWVudHNcblx0XHRcdGlmICggdGFnID09PSBcIipcIiApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRcdFx0dG1wLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdG1wO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0fTtcblxuXHQvLyBDbGFzc1xuXHRFeHByLmZpbmRbXCJDTEFTU1wiXSA9IHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBmdW5jdGlvbiggY2xhc3NOYW1lLCBjb250ZXh0ICkge1xuXHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIGNsYXNzTmFtZSApO1xuXHRcdH1cblx0fTtcblxuXHQvKiBRU0EvbWF0Y2hlc1NlbGVjdG9yXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBRU0EgYW5kIG1hdGNoZXNTZWxlY3RvciBzdXBwb3J0XG5cblx0Ly8gbWF0Y2hlc1NlbGVjdG9yKDphY3RpdmUpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChJRTkvT3BlcmEgMTEuNSlcblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdC8vIHFTYSg6Zm9jdXMpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChDaHJvbWUgMjEpXG5cdC8vIFdlIGFsbG93IHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBJRTgvOSB0aGF0IHRocm93cyBhbiBlcnJvclxuXHQvLyB3aGVuZXZlciBgZG9jdW1lbnQuYWN0aXZlRWxlbWVudGAgaXMgYWNjZXNzZWQgb24gYW4gaWZyYW1lXG5cdC8vIFNvLCB3ZSBhbGxvdyA6Zm9jdXMgdG8gcGFzcyB0aHJvdWdoIFFTQSBhbGwgdGhlIHRpbWUgdG8gYXZvaWQgdGhlIElFIGVycm9yXG5cdC8vIFNlZSBodHRwczovL2J1Z3MuanF1ZXJ5LmNvbS90aWNrZXQvMTMzNzhcblx0cmJ1Z2d5UVNBID0gW107XG5cblx0aWYgKCAoc3VwcG9ydC5xc2EgPSBybmF0aXZlLnRlc3QoIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwgKSkgKSB7XG5cdFx0Ly8gQnVpbGQgUVNBIHJlZ2V4XG5cdFx0Ly8gUmVnZXggc3RyYXRlZ3kgYWRvcHRlZCBmcm9tIERpZWdvIFBlcmluaVxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBTZWxlY3QgaXMgc2V0IHRvIGVtcHR5IHN0cmluZyBvbiBwdXJwb3NlXG5cdFx0XHQvLyBUaGlzIGlzIHRvIHRlc3QgSUUncyB0cmVhdG1lbnQgb2Ygbm90IGV4cGxpY2l0bHlcblx0XHRcdC8vIHNldHRpbmcgYSBib29sZWFuIGNvbnRlbnQgYXR0cmlidXRlLFxuXHRcdFx0Ly8gc2luY2UgaXRzIHByZXNlbmNlIHNob3VsZCBiZSBlbm91Z2hcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjM1OVxuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pbm5lckhUTUwgPSBcIjxhIGlkPSdcIiArIGV4cGFuZG8gKyBcIic+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGlkPSdcIiArIGV4cGFuZG8gKyBcIi1cXHJcXFxcJyBtc2FsbG93Y2FwdHVyZT0nJz5cIiArXG5cdFx0XHRcdFwiPG9wdGlvbiBzZWxlY3RlZD0nJz48L29wdGlvbj48L3NlbGVjdD5cIjtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4LCBPcGVyYSAxMS0xMi4xNlxuXHRcdFx0Ly8gTm90aGluZyBzaG91bGQgYmUgc2VsZWN0ZWQgd2hlbiBlbXB0eSBzdHJpbmdzIGZvbGxvdyBePSBvciAkPSBvciAqPVxuXHRcdFx0Ly8gVGhlIHRlc3QgYXR0cmlidXRlIG11c3QgYmUgdW5rbm93biBpbiBPcGVyYSBidXQgXCJzYWZlXCIgZm9yIFdpblJUXG5cdFx0XHQvLyBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2hoNDY1Mzg4LmFzcHgjYXR0cmlidXRlX3NlY3Rpb25cblx0XHRcdGlmICggZWwucXVlcnlTZWxlY3RvckFsbChcIlttc2FsbG93Y2FwdHVyZV49JyddXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiWypeJF09XCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86Jyd8XFxcIlxcXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4XG5cdFx0XHQvLyBCb29sZWFuIGF0dHJpYnV0ZXMgYW5kIFwidmFsdWVcIiBhcmUgbm90IHRyZWF0ZWQgY29ycmVjdGx5XG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW3NlbGVjdGVkXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86dmFsdWV8XCIgKyBib29sZWFucyArIFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IENocm9tZTwyOSwgQW5kcm9pZDw0LjQsIFNhZmFyaTw3LjArLCBpT1M8Ny4wKywgUGhhbnRvbUpTPDEuOS44K1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbCggXCJbaWR+PVwiICsgZXhwYW5kbyArIFwiLV1cIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCJ+PVwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gV2Via2l0L09wZXJhIC0gOmNoZWNrZWQgc2hvdWxkIHJldHVybiBzZWxlY3RlZCBvcHRpb24gZWxlbWVudHNcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMTEvUkVDLWNzczMtc2VsZWN0b3JzLTIwMTEwOTI5LyNjaGVja2VkXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbChcIjpjaGVja2VkXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCI6Y2hlY2tlZFwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogU2FmYXJpIDgrLCBpT1MgOCtcblx0XHRcdC8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzY4NTFcblx0XHRcdC8vIEluLXBhZ2UgYHNlbGVjdG9yI2lkIHNpYmxpbmctY29tYmluYXRvciBzZWxlY3RvcmAgZmFpbHNcblx0XHRcdGlmICggIWVsLnF1ZXJ5U2VsZWN0b3JBbGwoIFwiYSNcIiArIGV4cGFuZG8gKyBcIisqXCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKFwiLiMuK1srfl1cIik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdFx0ZWwuaW5uZXJIVE1MID0gXCI8YSBocmVmPScnIGRpc2FibGVkPSdkaXNhYmxlZCc+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGRpc2FibGVkPSdkaXNhYmxlZCc+PG9wdGlvbi8+PC9zZWxlY3Q+XCI7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IFdpbmRvd3MgOCBOYXRpdmUgQXBwc1xuXHRcdFx0Ly8gVGhlIHR5cGUgYW5kIG5hbWUgYXR0cmlidXRlcyBhcmUgcmVzdHJpY3RlZCBkdXJpbmcgLmlubmVySFRNTCBhc3NpZ25tZW50XG5cdFx0XHR2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG5cdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwidHlwZVwiLCBcImhpZGRlblwiICk7XG5cdFx0XHRlbC5hcHBlbmRDaGlsZCggaW5wdXQgKS5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcIkRcIiApO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRThcblx0XHRcdC8vIEVuZm9yY2UgY2FzZS1zZW5zaXRpdml0eSBvZiBuYW1lIGF0dHJpYnV0ZVxuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW25hbWU9ZF1cIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCJuYW1lXCIgKyB3aGl0ZXNwYWNlICsgXCIqWypeJHwhfl0/PVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZGIDMuNSAtIDplbmFibGVkLzpkaXNhYmxlZCBhbmQgaGlkZGVuIGVsZW1lbnRzIChoaWRkZW4gZWxlbWVudHMgYXJlIHN0aWxsIGVuYWJsZWQpXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiOmVuYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOS0xMStcblx0XHRcdC8vIElFJ3MgOmRpc2FibGVkIHNlbGVjdG9yIGRvZXMgbm90IHBpY2sgdXAgdGhlIGNoaWxkcmVuIG9mIGRpc2FibGVkIGZpZWxkc2V0c1xuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZGlzYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9wZXJhIDEwLTExIGRvZXMgbm90IHRocm93IG9uIHBvc3QtY29tbWEgaW52YWxpZCBwc2V1ZG9zXG5cdFx0XHRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiKiw6eFwiKTtcblx0XHRcdHJidWdneVFTQS5wdXNoKFwiLC4qOlwiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmICggKHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yID0gcm5hdGl2ZS50ZXN0KCAobWF0Y2hlcyA9IGRvY0VsZW0ubWF0Y2hlcyB8fFxuXHRcdGRvY0VsZW0ud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0ZG9jRWxlbS5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm9NYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1zTWF0Y2hlc1NlbGVjdG9yKSApKSApIHtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBDaGVjayB0byBzZWUgaWYgaXQncyBwb3NzaWJsZSB0byBkbyBtYXRjaGVzU2VsZWN0b3Jcblx0XHRcdC8vIG9uIGEgZGlzY29ubmVjdGVkIG5vZGUgKElFIDkpXG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBlbCwgXCIqXCIgKTtcblxuXHRcdFx0Ly8gVGhpcyBzaG91bGQgZmFpbCB3aXRoIGFuIGV4Y2VwdGlvblxuXHRcdFx0Ly8gR2Vja28gZG9lcyBub3QgZXJyb3IsIHJldHVybnMgZmFsc2UgaW5zdGVhZFxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBlbCwgXCJbcyE9JyddOnhcIiApO1xuXHRcdFx0cmJ1Z2d5TWF0Y2hlcy5wdXNoKCBcIiE9XCIsIHBzZXVkb3MgKTtcblx0XHR9KTtcblx0fVxuXG5cdHJidWdneVFTQSA9IHJidWdneVFTQS5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5UVNBLmpvaW4oXCJ8XCIpICk7XG5cdHJidWdneU1hdGNoZXMgPSByYnVnZ3lNYXRjaGVzLmxlbmd0aCAmJiBuZXcgUmVnRXhwKCByYnVnZ3lNYXRjaGVzLmpvaW4oXCJ8XCIpICk7XG5cblx0LyogQ29udGFpbnNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXHRoYXNDb21wYXJlID0gcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICk7XG5cblx0Ly8gRWxlbWVudCBjb250YWlucyBhbm90aGVyXG5cdC8vIFB1cnBvc2VmdWxseSBzZWxmLWV4Y2x1c2l2ZVxuXHQvLyBBcyBpbiwgYW4gZWxlbWVudCBkb2VzIG5vdCBjb250YWluIGl0c2VsZlxuXHRjb250YWlucyA9IGhhc0NvbXBhcmUgfHwgcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbnRhaW5zICkgP1xuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0dmFyIGFkb3duID0gYS5ub2RlVHlwZSA9PT0gOSA/IGEuZG9jdW1lbnRFbGVtZW50IDogYSxcblx0XHRcdFx0YnVwID0gYiAmJiBiLnBhcmVudE5vZGU7XG5cdFx0XHRyZXR1cm4gYSA9PT0gYnVwIHx8ICEhKCBidXAgJiYgYnVwLm5vZGVUeXBlID09PSAxICYmIChcblx0XHRcdFx0YWRvd24uY29udGFpbnMgP1xuXHRcdFx0XHRcdGFkb3duLmNvbnRhaW5zKCBidXAgKSA6XG5cdFx0XHRcdFx0YS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBidXAgKSAmIDE2XG5cdFx0XHQpKTtcblx0XHR9IDpcblx0XHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHRcdGlmICggYiApIHtcblx0XHRcdFx0d2hpbGUgKCAoYiA9IGIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBiID09PSBhICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcblxuXHQvKiBTb3J0aW5nXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBEb2N1bWVudCBvcmRlciBzb3J0aW5nXG5cdHNvcnRPcmRlciA9IGhhc0NvbXBhcmUgP1xuXHRmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdC8vIEZsYWcgZm9yIGR1cGxpY2F0ZSByZW1vdmFsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdC8vIFNvcnQgb24gbWV0aG9kIGV4aXN0ZW5jZSBpZiBvbmx5IG9uZSBpbnB1dCBoYXMgY29tcGFyZURvY3VtZW50UG9zaXRpb25cblx0XHR2YXIgY29tcGFyZSA9ICFhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uIC0gIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247XG5cdFx0aWYgKCBjb21wYXJlICkge1xuXHRcdFx0cmV0dXJuIGNvbXBhcmU7XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsY3VsYXRlIHBvc2l0aW9uIGlmIGJvdGggaW5wdXRzIGJlbG9uZyB0byB0aGUgc2FtZSBkb2N1bWVudFxuXHRcdGNvbXBhcmUgPSAoIGEub3duZXJEb2N1bWVudCB8fCBhICkgPT09ICggYi5vd25lckRvY3VtZW50IHx8IGIgKSA/XG5cdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBiICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugd2Uga25vdyB0aGV5IGFyZSBkaXNjb25uZWN0ZWRcblx0XHRcdDE7XG5cblx0XHQvLyBEaXNjb25uZWN0ZWQgbm9kZXNcblx0XHRpZiAoIGNvbXBhcmUgJiAxIHx8XG5cdFx0XHQoIXN1cHBvcnQuc29ydERldGFjaGVkICYmIGIuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGEgKSA9PT0gY29tcGFyZSkgKSB7XG5cblx0XHRcdC8vIENob29zZSB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IGlzIHJlbGF0ZWQgdG8gb3VyIHByZWZlcnJlZCBkb2N1bWVudFxuXHRcdFx0aWYgKCBhID09PSBkb2N1bWVudCB8fCBhLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGEpICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGIgPT09IGRvY3VtZW50IHx8IGIub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYikgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWludGFpbiBvcmlnaW5hbCBvcmRlclxuXHRcdFx0cmV0dXJuIHNvcnRJbnB1dCA/XG5cdFx0XHRcdCggaW5kZXhPZiggc29ydElucHV0LCBhICkgLSBpbmRleE9mKCBzb3J0SW5wdXQsIGIgKSApIDpcblx0XHRcdFx0MDtcblx0XHR9XG5cblx0XHRyZXR1cm4gY29tcGFyZSAmIDQgPyAtMSA6IDE7XG5cdH0gOlxuXHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHQvLyBFeGl0IGVhcmx5IGlmIHRoZSBub2RlcyBhcmUgaWRlbnRpY2FsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHZhciBjdXIsXG5cdFx0XHRpID0gMCxcblx0XHRcdGF1cCA9IGEucGFyZW50Tm9kZSxcblx0XHRcdGJ1cCA9IGIucGFyZW50Tm9kZSxcblx0XHRcdGFwID0gWyBhIF0sXG5cdFx0XHRicCA9IFsgYiBdO1xuXG5cdFx0Ly8gUGFyZW50bGVzcyBub2RlcyBhcmUgZWl0aGVyIGRvY3VtZW50cyBvciBkaXNjb25uZWN0ZWRcblx0XHRpZiAoICFhdXAgfHwgIWJ1cCApIHtcblx0XHRcdHJldHVybiBhID09PSBkb2N1bWVudCA/IC0xIDpcblx0XHRcdFx0YiA9PT0gZG9jdW1lbnQgPyAxIDpcblx0XHRcdFx0YXVwID8gLTEgOlxuXHRcdFx0XHRidXAgPyAxIDpcblx0XHRcdFx0c29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0Ly8gSWYgdGhlIG5vZGVzIGFyZSBzaWJsaW5ncywgd2UgY2FuIGRvIGEgcXVpY2sgY2hlY2tcblx0XHR9IGVsc2UgaWYgKCBhdXAgPT09IGJ1cCApIHtcblx0XHRcdHJldHVybiBzaWJsaW5nQ2hlY2soIGEsIGIgKTtcblx0XHR9XG5cblx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCBmdWxsIGxpc3RzIG9mIHRoZWlyIGFuY2VzdG9ycyBmb3IgY29tcGFyaXNvblxuXHRcdGN1ciA9IGE7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YXAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXHRcdGN1ciA9IGI7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YnAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXG5cdFx0Ly8gV2FsayBkb3duIHRoZSB0cmVlIGxvb2tpbmcgZm9yIGEgZGlzY3JlcGFuY3lcblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHQvLyBEbyBhIHNpYmxpbmcgY2hlY2sgaWYgdGhlIG5vZGVzIGhhdmUgYSBjb21tb24gYW5jZXN0b3Jcblx0XHRcdHNpYmxpbmdDaGVjayggYXBbaV0sIGJwW2ldICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugbm9kZXMgaW4gb3VyIGRvY3VtZW50IHNvcnQgZmlyc3Rcblx0XHRcdGFwW2ldID09PSBwcmVmZXJyZWREb2MgPyAtMSA6XG5cdFx0XHRicFtpXSA9PT0gcHJlZmVycmVkRG9jID8gMSA6XG5cdFx0XHQwO1xuXHR9O1xuXG5cdHJldHVybiBkb2N1bWVudDtcbn07XG5cblNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1lbnRzICkge1xuXHRyZXR1cm4gU2l6emxlKCBleHByLCBudWxsLCBudWxsLCBlbGVtZW50cyApO1xufTtcblxuU2l6emxlLm1hdGNoZXNTZWxlY3RvciA9IGZ1bmN0aW9uKCBlbGVtLCBleHByICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHQvLyBNYWtlIHN1cmUgdGhhdCBhdHRyaWJ1dGUgc2VsZWN0b3JzIGFyZSBxdW90ZWRcblx0ZXhwciA9IGV4cHIucmVwbGFjZSggcmF0dHJpYnV0ZVF1b3RlcywgXCI9JyQxJ11cIiApO1xuXG5cdGlmICggc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgJiYgZG9jdW1lbnRJc0hUTUwgJiZcblx0XHQhY29tcGlsZXJDYWNoZVsgZXhwciArIFwiIFwiIF0gJiZcblx0XHQoICFyYnVnZ3lNYXRjaGVzIHx8ICFyYnVnZ3lNYXRjaGVzLnRlc3QoIGV4cHIgKSApICYmXG5cdFx0KCAhcmJ1Z2d5UVNBICAgICB8fCAhcmJ1Z2d5UVNBLnRlc3QoIGV4cHIgKSApICkge1xuXG5cdFx0dHJ5IHtcblx0XHRcdHZhciByZXQgPSBtYXRjaGVzLmNhbGwoIGVsZW0sIGV4cHIgKTtcblxuXHRcdFx0Ly8gSUUgOSdzIG1hdGNoZXNTZWxlY3RvciByZXR1cm5zIGZhbHNlIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdFx0aWYgKCByZXQgfHwgc3VwcG9ydC5kaXNjb25uZWN0ZWRNYXRjaCB8fFxuXHRcdFx0XHRcdC8vIEFzIHdlbGwsIGRpc2Nvbm5lY3RlZCBub2RlcyBhcmUgc2FpZCB0byBiZSBpbiBhIGRvY3VtZW50XG5cdFx0XHRcdFx0Ly8gZnJhZ21lbnQgaW4gSUUgOVxuXHRcdFx0XHRcdGVsZW0uZG9jdW1lbnQgJiYgZWxlbS5kb2N1bWVudC5ub2RlVHlwZSAhPT0gMTEgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge31cblx0fVxuXG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIGRvY3VtZW50LCBudWxsLCBbIGVsZW0gXSApLmxlbmd0aCA+IDA7XG59O1xuXG5TaXp6bGUuY29udGFpbnMgPSBmdW5jdGlvbiggY29udGV4dCwgZWxlbSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgfHwgY29udGV4dCApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHR9XG5cdHJldHVybiBjb250YWlucyggY29udGV4dCwgZWxlbSApO1xufTtcblxuU2l6emxlLmF0dHIgPSBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHR9XG5cblx0dmFyIGZuID0gRXhwci5hdHRySGFuZGxlWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSxcblx0XHQvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IE9iamVjdC5wcm90b3R5cGUgcHJvcGVydGllcyAoalF1ZXJ5ICMxMzgwNylcblx0XHR2YWwgPSBmbiAmJiBoYXNPd24uY2FsbCggRXhwci5hdHRySGFuZGxlLCBuYW1lLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRmbiggZWxlbSwgbmFtZSwgIWRvY3VtZW50SXNIVE1MICkgOlxuXHRcdFx0dW5kZWZpbmVkO1xuXG5cdHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/XG5cdFx0dmFsIDpcblx0XHRzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWRvY3VtZW50SXNIVE1MID9cblx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICkgOlxuXHRcdFx0KHZhbCA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShuYW1lKSkgJiYgdmFsLnNwZWNpZmllZCA/XG5cdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG59O1xuXG5TaXp6bGUuZXNjYXBlID0gZnVuY3Rpb24oIHNlbCApIHtcblx0cmV0dXJuIChzZWwgKyBcIlwiKS5yZXBsYWNlKCByY3NzZXNjYXBlLCBmY3NzZXNjYXBlICk7XG59O1xuXG5TaXp6bGUuZXJyb3IgPSBmdW5jdGlvbiggbXNnICkge1xuXHR0aHJvdyBuZXcgRXJyb3IoIFwiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogXCIgKyBtc2cgKTtcbn07XG5cbi8qKlxuICogRG9jdW1lbnQgc29ydGluZyBhbmQgcmVtb3ZpbmcgZHVwbGljYXRlc1xuICogQHBhcmFtIHtBcnJheUxpa2V9IHJlc3VsdHNcbiAqL1xuU2l6emxlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbiggcmVzdWx0cyApIHtcblx0dmFyIGVsZW0sXG5cdFx0ZHVwbGljYXRlcyA9IFtdLFxuXHRcdGogPSAwLFxuXHRcdGkgPSAwO1xuXG5cdC8vIFVubGVzcyB3ZSAqa25vdyogd2UgY2FuIGRldGVjdCBkdXBsaWNhdGVzLCBhc3N1bWUgdGhlaXIgcHJlc2VuY2Vcblx0aGFzRHVwbGljYXRlID0gIXN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcztcblx0c29ydElucHV0ID0gIXN1cHBvcnQuc29ydFN0YWJsZSAmJiByZXN1bHRzLnNsaWNlKCAwICk7XG5cdHJlc3VsdHMuc29ydCggc29ydE9yZGVyICk7XG5cblx0aWYgKCBoYXNEdXBsaWNhdGUgKSB7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRpZiAoIGVsZW0gPT09IHJlc3VsdHNbIGkgXSApIHtcblx0XHRcdFx0aiA9IGR1cGxpY2F0ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdHJlc3VsdHMuc3BsaWNlKCBkdXBsaWNhdGVzWyBqIF0sIDEgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDbGVhciBpbnB1dCBhZnRlciBzb3J0aW5nIHRvIHJlbGVhc2Ugb2JqZWN0c1xuXHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9zaXp6bGUvcHVsbC8yMjVcblx0c29ydElucHV0ID0gbnVsbDtcblxuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiBmb3IgcmV0cmlldmluZyB0aGUgdGV4dCB2YWx1ZSBvZiBhbiBhcnJheSBvZiBET00gbm9kZXNcbiAqIEBwYXJhbSB7QXJyYXl8RWxlbWVudH0gZWxlbVxuICovXG5nZXRUZXh0ID0gU2l6emxlLmdldFRleHQgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0dmFyIG5vZGUsXG5cdFx0cmV0ID0gXCJcIixcblx0XHRpID0gMCxcblx0XHRub2RlVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0aWYgKCAhbm9kZVR5cGUgKSB7XG5cdFx0Ly8gSWYgbm8gbm9kZVR5cGUsIHRoaXMgaXMgZXhwZWN0ZWQgdG8gYmUgYW4gYXJyYXlcblx0XHR3aGlsZSAoIChub2RlID0gZWxlbVtpKytdKSApIHtcblx0XHRcdC8vIERvIG5vdCB0cmF2ZXJzZSBjb21tZW50IG5vZGVzXG5cdFx0XHRyZXQgKz0gZ2V0VGV4dCggbm9kZSApO1xuXHRcdH1cblx0fSBlbHNlIGlmICggbm9kZVR5cGUgPT09IDEgfHwgbm9kZVR5cGUgPT09IDkgfHwgbm9kZVR5cGUgPT09IDExICkge1xuXHRcdC8vIFVzZSB0ZXh0Q29udGVudCBmb3IgZWxlbWVudHNcblx0XHQvLyBpbm5lclRleHQgdXNhZ2UgcmVtb3ZlZCBmb3IgY29uc2lzdGVuY3kgb2YgbmV3IGxpbmVzIChqUXVlcnkgIzExMTUzKVxuXHRcdGlmICggdHlwZW9mIGVsZW0udGV4dENvbnRlbnQgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS50ZXh0Q29udGVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gVHJhdmVyc2UgaXRzIGNoaWxkcmVuXG5cdFx0XHRmb3IgKCBlbGVtID0gZWxlbS5maXJzdENoaWxkOyBlbGVtOyBlbGVtID0gZWxlbS5uZXh0U2libGluZyApIHtcblx0XHRcdFx0cmV0ICs9IGdldFRleHQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAzIHx8IG5vZGVUeXBlID09PSA0ICkge1xuXHRcdHJldHVybiBlbGVtLm5vZGVWYWx1ZTtcblx0fVxuXHQvLyBEbyBub3QgaW5jbHVkZSBjb21tZW50IG9yIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gbm9kZXNcblxuXHRyZXR1cm4gcmV0O1xufTtcblxuRXhwciA9IFNpenpsZS5zZWxlY3RvcnMgPSB7XG5cblx0Ly8gQ2FuIGJlIGFkanVzdGVkIGJ5IHRoZSB1c2VyXG5cdGNhY2hlTGVuZ3RoOiA1MCxcblxuXHRjcmVhdGVQc2V1ZG86IG1hcmtGdW5jdGlvbixcblxuXHRtYXRjaDogbWF0Y2hFeHByLFxuXG5cdGF0dHJIYW5kbGU6IHt9LFxuXG5cdGZpbmQ6IHt9LFxuXG5cdHJlbGF0aXZlOiB7XG5cdFx0XCI+XCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIiBcIjogeyBkaXI6IFwicGFyZW50Tm9kZVwiIH0sXG5cdFx0XCIrXCI6IHsgZGlyOiBcInByZXZpb3VzU2libGluZ1wiLCBmaXJzdDogdHJ1ZSB9LFxuXHRcdFwiflwiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiB9XG5cdH0sXG5cblx0cHJlRmlsdGVyOiB7XG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0Ly8gTW92ZSB0aGUgZ2l2ZW4gdmFsdWUgdG8gbWF0Y2hbM10gd2hldGhlciBxdW90ZWQgb3IgdW5xdW90ZWRcblx0XHRcdG1hdGNoWzNdID0gKCBtYXRjaFszXSB8fCBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiICkucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsyXSA9PT0gXCJ+PVwiICkge1xuXHRcdFx0XHRtYXRjaFszXSA9IFwiIFwiICsgbWF0Y2hbM10gKyBcIiBcIjtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCA0ICk7XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0LyogbWF0Y2hlcyBmcm9tIG1hdGNoRXhwcltcIkNISUxEXCJdXG5cdFx0XHRcdDEgdHlwZSAob25seXxudGh8Li4uKVxuXHRcdFx0XHQyIHdoYXQgKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdDMgYXJndW1lbnQgKGV2ZW58b2RkfFxcZCp8XFxkKm4oWystXVxcZCspP3wuLi4pXG5cdFx0XHRcdDQgeG4tY29tcG9uZW50IG9mIHhuK3kgYXJndW1lbnQgKFsrLV0/XFxkKm58KVxuXHRcdFx0XHQ1IHNpZ24gb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDYgeCBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NyBzaWduIG9mIHktY29tcG9uZW50XG5cdFx0XHRcdDggeSBvZiB5LWNvbXBvbmVudFxuXHRcdFx0Ki9cblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsxXS5zbGljZSggMCwgMyApID09PSBcIm50aFwiICkge1xuXHRcdFx0XHQvLyBudGgtKiByZXF1aXJlcyBhcmd1bWVudFxuXHRcdFx0XHRpZiAoICFtYXRjaFszXSApIHtcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBudW1lcmljIHggYW5kIHkgcGFyYW1ldGVycyBmb3IgRXhwci5maWx0ZXIuQ0hJTERcblx0XHRcdFx0Ly8gcmVtZW1iZXIgdGhhdCBmYWxzZS90cnVlIGNhc3QgcmVzcGVjdGl2ZWx5IHRvIDAvMVxuXHRcdFx0XHRtYXRjaFs0XSA9ICsoIG1hdGNoWzRdID8gbWF0Y2hbNV0gKyAobWF0Y2hbNl0gfHwgMSkgOiAyICogKCBtYXRjaFszXSA9PT0gXCJldmVuXCIgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKSApO1xuXHRcdFx0XHRtYXRjaFs1XSA9ICsoICggbWF0Y2hbN10gKyBtYXRjaFs4XSApIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICk7XG5cblx0XHRcdC8vIG90aGVyIHR5cGVzIHByb2hpYml0IGFyZ3VtZW50c1xuXHRcdFx0fSBlbHNlIGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdFNpenpsZS5lcnJvciggbWF0Y2hbMF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoO1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHR2YXIgZXhjZXNzLFxuXHRcdFx0XHR1bnF1b3RlZCA9ICFtYXRjaFs2XSAmJiBtYXRjaFsyXTtcblxuXHRcdFx0aWYgKCBtYXRjaEV4cHJbXCJDSElMRFwiXS50ZXN0KCBtYXRjaFswXSApICkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWNjZXB0IHF1b3RlZCBhcmd1bWVudHMgYXMtaXNcblx0XHRcdGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdG1hdGNoWzJdID0gbWF0Y2hbNF0gfHwgbWF0Y2hbNV0gfHwgXCJcIjtcblxuXHRcdFx0Ly8gU3RyaXAgZXhjZXNzIGNoYXJhY3RlcnMgZnJvbSB1bnF1b3RlZCBhcmd1bWVudHNcblx0XHRcdH0gZWxzZSBpZiAoIHVucXVvdGVkICYmIHJwc2V1ZG8udGVzdCggdW5xdW90ZWQgKSAmJlxuXHRcdFx0XHQvLyBHZXQgZXhjZXNzIGZyb20gdG9rZW5pemUgKHJlY3Vyc2l2ZWx5KVxuXHRcdFx0XHQoZXhjZXNzID0gdG9rZW5pemUoIHVucXVvdGVkLCB0cnVlICkpICYmXG5cdFx0XHRcdC8vIGFkdmFuY2UgdG8gdGhlIG5leHQgY2xvc2luZyBwYXJlbnRoZXNpc1xuXHRcdFx0XHQoZXhjZXNzID0gdW5xdW90ZWQuaW5kZXhPZiggXCIpXCIsIHVucXVvdGVkLmxlbmd0aCAtIGV4Y2VzcyApIC0gdW5xdW90ZWQubGVuZ3RoKSApIHtcblxuXHRcdFx0XHQvLyBleGNlc3MgaXMgYSBuZWdhdGl2ZSBpbmRleFxuXHRcdFx0XHRtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwLCBleGNlc3MgKTtcblx0XHRcdFx0bWF0Y2hbMl0gPSB1bnF1b3RlZC5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldHVybiBvbmx5IGNhcHR1cmVzIG5lZWRlZCBieSB0aGUgcHNldWRvIGZpbHRlciBtZXRob2QgKHR5cGUgYW5kIGFyZ3VtZW50KVxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCAzICk7XG5cdFx0fVxuXHR9LFxuXG5cdGZpbHRlcjoge1xuXG5cdFx0XCJUQUdcIjogZnVuY3Rpb24oIG5vZGVOYW1lU2VsZWN0b3IgKSB7XG5cdFx0XHR2YXIgbm9kZU5hbWUgPSBub2RlTmFtZVNlbGVjdG9yLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICkudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBub2RlTmFtZVNlbGVjdG9yID09PSBcIipcIiA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfSA6XG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbm9kZU5hbWU7XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0xBU1NcIjogZnVuY3Rpb24oIGNsYXNzTmFtZSApIHtcblx0XHRcdHZhciBwYXR0ZXJuID0gY2xhc3NDYWNoZVsgY2xhc3NOYW1lICsgXCIgXCIgXTtcblxuXHRcdFx0cmV0dXJuIHBhdHRlcm4gfHxcblx0XHRcdFx0KHBhdHRlcm4gPSBuZXcgUmVnRXhwKCBcIihefFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgY2xhc3NOYW1lICsgXCIoXCIgKyB3aGl0ZXNwYWNlICsgXCJ8JClcIiApKSAmJlxuXHRcdFx0XHRjbGFzc0NhY2hlKCBjbGFzc05hbWUsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXR0ZXJuLnRlc3QoIHR5cGVvZiBlbGVtLmNsYXNzTmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBlbGVtLmNsYXNzTmFtZSB8fCB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGUgIT09IFwidW5kZWZpbmVkXCIgJiYgZWxlbS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKSB8fCBcIlwiICk7XG5cdFx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRcIkFUVFJcIjogZnVuY3Rpb24oIG5hbWUsIG9wZXJhdG9yLCBjaGVjayApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IFNpenpsZS5hdHRyKCBlbGVtLCBuYW1lICk7XG5cblx0XHRcdFx0aWYgKCByZXN1bHQgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiIT1cIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoICFvcGVyYXRvciApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlc3VsdCArPSBcIlwiO1xuXG5cdFx0XHRcdHJldHVybiBvcGVyYXRvciA9PT0gXCI9XCIgPyByZXN1bHQgPT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIhPVwiID8gcmVzdWx0ICE9PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiXj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID09PSAwIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIqPVwiID8gY2hlY2sgJiYgcmVzdWx0LmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiJD1cIiA/IGNoZWNrICYmIHJlc3VsdC5zbGljZSggLWNoZWNrLmxlbmd0aCApID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifj1cIiA/ICggXCIgXCIgKyByZXN1bHQucmVwbGFjZSggcndoaXRlc3BhY2UsIFwiIFwiICkgKyBcIiBcIiApLmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifD1cIiA/IHJlc3VsdCA9PT0gY2hlY2sgfHwgcmVzdWx0LnNsaWNlKCAwLCBjaGVjay5sZW5ndGggKyAxICkgPT09IGNoZWNrICsgXCItXCIgOlxuXHRcdFx0XHRcdGZhbHNlO1xuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDSElMRFwiOiBmdW5jdGlvbiggdHlwZSwgd2hhdCwgYXJndW1lbnQsIGZpcnN0LCBsYXN0ICkge1xuXHRcdFx0dmFyIHNpbXBsZSA9IHR5cGUuc2xpY2UoIDAsIDMgKSAhPT0gXCJudGhcIixcblx0XHRcdFx0Zm9yd2FyZCA9IHR5cGUuc2xpY2UoIC00ICkgIT09IFwibGFzdFwiLFxuXHRcdFx0XHRvZlR5cGUgPSB3aGF0ID09PSBcIm9mLXR5cGVcIjtcblxuXHRcdFx0cmV0dXJuIGZpcnN0ID09PSAxICYmIGxhc3QgPT09IDAgP1xuXG5cdFx0XHRcdC8vIFNob3J0Y3V0IGZvciA6bnRoLSoobilcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuICEhZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0XHR9IDpcblxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBjYWNoZSwgdW5pcXVlQ2FjaGUsIG91dGVyQ2FjaGUsIG5vZGUsIG5vZGVJbmRleCwgc3RhcnQsXG5cdFx0XHRcdFx0XHRkaXIgPSBzaW1wbGUgIT09IGZvcndhcmQgPyBcIm5leHRTaWJsaW5nXCIgOiBcInByZXZpb3VzU2libGluZ1wiLFxuXHRcdFx0XHRcdFx0cGFyZW50ID0gZWxlbS5wYXJlbnROb2RlLFxuXHRcdFx0XHRcdFx0bmFtZSA9IG9mVHlwZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRcdFx0XHR1c2VDYWNoZSA9ICF4bWwgJiYgIW9mVHlwZSxcblx0XHRcdFx0XHRcdGRpZmYgPSBmYWxzZTtcblxuXHRcdFx0XHRcdGlmICggcGFyZW50ICkge1xuXG5cdFx0XHRcdFx0XHQvLyA6KGZpcnN0fGxhc3R8b25seSktKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdFx0XHRpZiAoIHNpbXBsZSApIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCBkaXIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW07XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9IG5vZGVbIGRpciBdKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggb2ZUeXBlID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDpcblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vIFJldmVyc2UgZGlyZWN0aW9uIGZvciA6b25seS0qIChpZiB3ZSBoYXZlbid0IHlldCBkb25lIHNvKVxuXHRcdFx0XHRcdFx0XHRcdHN0YXJ0ID0gZGlyID0gdHlwZSA9PT0gXCJvbmx5XCIgJiYgIXN0YXJ0ICYmIFwibmV4dFNpYmxpbmdcIjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0c3RhcnQgPSBbIGZvcndhcmQgPyBwYXJlbnQuZmlyc3RDaGlsZCA6IHBhcmVudC5sYXN0Q2hpbGQgXTtcblxuXHRcdFx0XHRcdFx0Ly8gbm9uLXhtbCA6bnRoLWNoaWxkKC4uLikgc3RvcmVzIGNhY2hlIGRhdGEgb24gYHBhcmVudGBcblx0XHRcdFx0XHRcdGlmICggZm9yd2FyZCAmJiB1c2VDYWNoZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTZWVrIGBlbGVtYCBmcm9tIGEgcHJldmlvdXNseS1jYWNoZWQgaW5kZXhcblxuXHRcdFx0XHRcdFx0XHQvLyAuLi5pbiBhIGd6aXAtZnJpZW5kbHkgd2F5XG5cdFx0XHRcdFx0XHRcdG5vZGUgPSBwYXJlbnQ7XG5cdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0Y2FjaGUgPSB1bmlxdWVDYWNoZVsgdHlwZSBdIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVsgMCBdID09PSBkaXJydW5zICYmIGNhY2hlWyAxIF07XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXggJiYgY2FjaGVbIDIgXTtcblx0XHRcdFx0XHRcdFx0bm9kZSA9IG5vZGVJbmRleCAmJiBwYXJlbnQuY2hpbGROb2Rlc1sgbm9kZUluZGV4IF07XG5cblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIHNlZWtpbmcgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBXaGVuIGZvdW5kLCBjYWNoZSBpbmRleGVzIG9uIGBwYXJlbnRgIGFuZCBicmVha1xuXHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSAmJiArK2RpZmYgJiYgbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIG5vZGVJbmRleCwgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFVzZSBwcmV2aW91c2x5LWNhY2hlZCBlbGVtZW50IGluZGV4IGlmIGF2YWlsYWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLmluIGEgZ3ppcC1mcmllbmRseSB3YXlcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gZWxlbTtcblx0XHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gbm9kZVsgZXhwYW5kbyBdIHx8IChub2RlWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHRjYWNoZSA9IHVuaXF1ZUNhY2hlWyB0eXBlIF0gfHwgW107XG5cdFx0XHRcdFx0XHRcdFx0bm9kZUluZGV4ID0gY2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBjYWNoZVsgMSBdO1xuXHRcdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXg7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvLyB4bWwgOm50aC1jaGlsZCguLi4pXG5cdFx0XHRcdFx0XHRcdC8vIG9yIDpudGgtbGFzdC1jaGlsZCguLi4pIG9yIDpudGgoLWxhc3QpPy1vZi10eXBlKC4uLilcblx0XHRcdFx0XHRcdFx0aWYgKCBkaWZmID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBVc2UgdGhlIHNhbWUgbG9vcCBhcyBhYm92ZSB0byBzZWVrIGBlbGVtYCBmcm9tIHRoZSBzdGFydFxuXHRcdFx0XHRcdFx0XHRcdHdoaWxlICggKG5vZGUgPSArK25vZGVJbmRleCAmJiBub2RlICYmIG5vZGVbIGRpciBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCAoIG9mVHlwZSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZSA6XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZVR5cGUgPT09IDEgKSAmJlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQrK2RpZmYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FjaGUgdGhlIGluZGV4IG9mIGVhY2ggZW5jb3VudGVyZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZlbmQgYWdhaW5zdCBjbG9uZWQgYXR0cm9wZXJ0aWVzIChqUXVlcnkgZ2gtMTcwOSlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIGRpZmYgXTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQvLyBJbmNvcnBvcmF0ZSB0aGUgb2Zmc2V0LCB0aGVuIGNoZWNrIGFnYWluc3QgY3ljbGUgc2l6ZVxuXHRcdFx0XHRcdFx0ZGlmZiAtPSBsYXN0O1xuXHRcdFx0XHRcdFx0cmV0dXJuIGRpZmYgPT09IGZpcnN0IHx8ICggZGlmZiAlIGZpcnN0ID09PSAwICYmIGRpZmYgLyBmaXJzdCA+PSAwICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggcHNldWRvLCBhcmd1bWVudCApIHtcblx0XHRcdC8vIHBzZXVkby1jbGFzcyBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZVxuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNwc2V1ZG8tY2xhc3Nlc1xuXHRcdFx0Ly8gUHJpb3JpdGl6ZSBieSBjYXNlIHNlbnNpdGl2aXR5IGluIGNhc2UgY3VzdG9tIHBzZXVkb3MgYXJlIGFkZGVkIHdpdGggdXBwZXJjYXNlIGxldHRlcnNcblx0XHRcdC8vIFJlbWVtYmVyIHRoYXQgc2V0RmlsdGVycyBpbmhlcml0cyBmcm9tIHBzZXVkb3Ncblx0XHRcdHZhciBhcmdzLFxuXHRcdFx0XHRmbiA9IEV4cHIucHNldWRvc1sgcHNldWRvIF0gfHwgRXhwci5zZXRGaWx0ZXJzWyBwc2V1ZG8udG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIHBzZXVkbzogXCIgKyBwc2V1ZG8gKTtcblxuXHRcdFx0Ly8gVGhlIHVzZXIgbWF5IHVzZSBjcmVhdGVQc2V1ZG8gdG8gaW5kaWNhdGUgdGhhdFxuXHRcdFx0Ly8gYXJndW1lbnRzIGFyZSBuZWVkZWQgdG8gY3JlYXRlIHRoZSBmaWx0ZXIgZnVuY3Rpb25cblx0XHRcdC8vIGp1c3QgYXMgU2l6emxlIGRvZXNcblx0XHRcdGlmICggZm5bIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZuKCBhcmd1bWVudCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBCdXQgbWFpbnRhaW4gc3VwcG9ydCBmb3Igb2xkIHNpZ25hdHVyZXNcblx0XHRcdGlmICggZm4ubGVuZ3RoID4gMSApIHtcblx0XHRcdFx0YXJncyA9IFsgcHNldWRvLCBwc2V1ZG8sIFwiXCIsIGFyZ3VtZW50IF07XG5cdFx0XHRcdHJldHVybiBFeHByLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoIHBzZXVkby50b0xvd2VyQ2FzZSgpICkgP1xuXHRcdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdFx0XHRcdHZhciBpZHgsXG5cdFx0XHRcdFx0XHRcdG1hdGNoZWQgPSBmbiggc2VlZCwgYXJndW1lbnQgKSxcblx0XHRcdFx0XHRcdFx0aSA9IG1hdGNoZWQubGVuZ3RoO1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlkeCA9IGluZGV4T2YoIHNlZWQsIG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdFx0c2VlZFsgaWR4IF0gPSAhKCBtYXRjaGVzWyBpZHggXSA9IG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZm4oIGVsZW0sIDAsIGFyZ3MgKTtcblx0XHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZm47XG5cdFx0fVxuXHR9LFxuXG5cdHBzZXVkb3M6IHtcblx0XHQvLyBQb3RlbnRpYWxseSBjb21wbGV4IHBzZXVkb3Ncblx0XHRcIm5vdFwiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0Ly8gVHJpbSB0aGUgc2VsZWN0b3IgcGFzc2VkIHRvIGNvbXBpbGVcblx0XHRcdC8vIHRvIGF2b2lkIHRyZWF0aW5nIGxlYWRpbmcgYW5kIHRyYWlsaW5nXG5cdFx0XHQvLyBzcGFjZXMgYXMgY29tYmluYXRvcnNcblx0XHRcdHZhciBpbnB1dCA9IFtdLFxuXHRcdFx0XHRyZXN1bHRzID0gW10sXG5cdFx0XHRcdG1hdGNoZXIgPSBjb21waWxlKCBzZWxlY3Rvci5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICkgKTtcblxuXHRcdFx0cmV0dXJuIG1hdGNoZXJbIGV4cGFuZG8gXSA/XG5cdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcywgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBlbGVtLFxuXHRcdFx0XHRcdFx0dW5tYXRjaGVkID0gbWF0Y2hlciggc2VlZCwgbnVsbCwgeG1sLCBbXSApLFxuXHRcdFx0XHRcdFx0aSA9IHNlZWQubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Ly8gTWF0Y2ggZWxlbWVudHMgdW5tYXRjaGVkIGJ5IGBtYXRjaGVyYFxuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdHNlZWRbaV0gPSAhKG1hdGNoZXNbaV0gPSBlbGVtKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pIDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdFx0XHRpbnB1dFswXSA9IGVsZW07XG5cdFx0XHRcdFx0bWF0Y2hlciggaW5wdXQsIG51bGwsIHhtbCwgcmVzdWx0cyApO1xuXHRcdFx0XHRcdC8vIERvbid0IGtlZXAgdGhlIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRcdFx0aW5wdXRbMF0gPSBudWxsO1xuXHRcdFx0XHRcdHJldHVybiAhcmVzdWx0cy5wb3AoKTtcblx0XHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiaGFzXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBTaXp6bGUoIHNlbGVjdG9yLCBlbGVtICkubGVuZ3RoID4gMDtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHRcImNvbnRhaW5zXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdHRleHQgPSB0ZXh0LnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lclRleHQgfHwgZ2V0VGV4dCggZWxlbSApICkuaW5kZXhPZiggdGV4dCApID4gLTE7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gXCJXaGV0aGVyIGFuIGVsZW1lbnQgaXMgcmVwcmVzZW50ZWQgYnkgYSA6bGFuZygpIHNlbGVjdG9yXG5cdFx0Ly8gaXMgYmFzZWQgc29sZWx5IG9uIHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWVcblx0XHQvLyBiZWluZyBlcXVhbCB0byB0aGUgaWRlbnRpZmllciBDLFxuXHRcdC8vIG9yIGJlZ2lubmluZyB3aXRoIHRoZSBpZGVudGlmaWVyIEMgaW1tZWRpYXRlbHkgZm9sbG93ZWQgYnkgXCItXCIuXG5cdFx0Ly8gVGhlIG1hdGNoaW5nIG9mIEMgYWdhaW5zdCB0aGUgZWxlbWVudCdzIGxhbmd1YWdlIHZhbHVlIGlzIHBlcmZvcm1lZCBjYXNlLWluc2Vuc2l0aXZlbHkuXG5cdFx0Ly8gVGhlIGlkZW50aWZpZXIgQyBkb2VzIG5vdCBoYXZlIHRvIGJlIGEgdmFsaWQgbGFuZ3VhZ2UgbmFtZS5cIlxuXHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jbGFuZy1wc2V1ZG9cblx0XHRcImxhbmdcIjogbWFya0Z1bmN0aW9uKCBmdW5jdGlvbiggbGFuZyApIHtcblx0XHRcdC8vIGxhbmcgdmFsdWUgbXVzdCBiZSBhIHZhbGlkIGlkZW50aWZpZXJcblx0XHRcdGlmICggIXJpZGVudGlmaWVyLnRlc3QobGFuZyB8fCBcIlwiKSApIHtcblx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIGxhbmc6IFwiICsgbGFuZyApO1xuXHRcdFx0fVxuXHRcdFx0bGFuZyA9IGxhbmcucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgZWxlbUxhbmc7XG5cdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtTGFuZyA9IGRvY3VtZW50SXNIVE1MID9cblx0XHRcdFx0XHRcdGVsZW0ubGFuZyA6XG5cdFx0XHRcdFx0XHRlbGVtLmdldEF0dHJpYnV0ZShcInhtbDpsYW5nXCIpIHx8IGVsZW0uZ2V0QXR0cmlidXRlKFwibGFuZ1wiKSkgKSB7XG5cblx0XHRcdFx0XHRcdGVsZW1MYW5nID0gZWxlbUxhbmcudG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtTGFuZyA9PT0gbGFuZyB8fCBlbGVtTGFuZy5pbmRleE9mKCBsYW5nICsgXCItXCIgKSA9PT0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gd2hpbGUgKCAoZWxlbSA9IGVsZW0ucGFyZW50Tm9kZSkgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gTWlzY2VsbGFuZW91c1xuXHRcdFwidGFyZ2V0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGhhc2ggPSB3aW5kb3cubG9jYXRpb24gJiYgd2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0XHRyZXR1cm4gaGFzaCAmJiBoYXNoLnNsaWNlKCAxICkgPT09IGVsZW0uaWQ7XG5cdFx0fSxcblxuXHRcdFwicm9vdFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBkb2NFbGVtO1xuXHRcdH0sXG5cblx0XHRcImZvY3VzXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKCFkb2N1bWVudC5oYXNGb2N1cyB8fCBkb2N1bWVudC5oYXNGb2N1cygpKSAmJiAhIShlbGVtLnR5cGUgfHwgZWxlbS5ocmVmIHx8IH5lbGVtLnRhYkluZGV4KTtcblx0XHR9LFxuXG5cdFx0Ly8gQm9vbGVhbiBwcm9wZXJ0aWVzXG5cdFx0XCJlbmFibGVkXCI6IGNyZWF0ZURpc2FibGVkUHNldWRvKCBmYWxzZSApLFxuXHRcdFwiZGlzYWJsZWRcIjogY3JlYXRlRGlzYWJsZWRQc2V1ZG8oIHRydWUgKSxcblxuXHRcdFwiY2hlY2tlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEluIENTUzMsIDpjaGVja2VkIHNob3VsZCByZXR1cm4gYm90aCBjaGVja2VkIGFuZCBzZWxlY3RlZCBlbGVtZW50c1xuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvMjAxMS9SRUMtY3NzMy1zZWxlY3RvcnMtMjAxMTA5MjkvI2NoZWNrZWRcblx0XHRcdHZhciBub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiAobm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiAhIWVsZW0uY2hlY2tlZCkgfHwgKG5vZGVOYW1lID09PSBcIm9wdGlvblwiICYmICEhZWxlbS5zZWxlY3RlZCk7XG5cdFx0fSxcblxuXHRcdFwic2VsZWN0ZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBBY2Nlc3NpbmcgdGhpcyBwcm9wZXJ0eSBtYWtlcyBzZWxlY3RlZC1ieS1kZWZhdWx0XG5cdFx0XHQvLyBvcHRpb25zIGluIFNhZmFyaSB3b3JrIHByb3Blcmx5XG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBlbGVtLnNlbGVjdGVkID09PSB0cnVlO1xuXHRcdH0sXG5cblx0XHQvLyBDb250ZW50c1xuXHRcdFwiZW1wdHlcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2VtcHR5LXBzZXVkb1xuXHRcdFx0Ly8gOmVtcHR5IGlzIG5lZ2F0ZWQgYnkgZWxlbWVudCAoMSkgb3IgY29udGVudCBub2RlcyAodGV4dDogMzsgY2RhdGE6IDQ7IGVudGl0eSByZWY6IDUpLFxuXHRcdFx0Ly8gICBidXQgbm90IGJ5IG90aGVycyAoY29tbWVudDogODsgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbjogNzsgZXRjLilcblx0XHRcdC8vIG5vZGVUeXBlIDwgNiB3b3JrcyBiZWNhdXNlIGF0dHJpYnV0ZXMgKDIpIGRvIG5vdCBhcHBlYXIgYXMgY2hpbGRyZW5cblx0XHRcdGZvciAoIGVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7IGVsZW07IGVsZW0gPSBlbGVtLm5leHRTaWJsaW5nICkge1xuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPCA2ICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblxuXHRcdFwicGFyZW50XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICFFeHByLnBzZXVkb3NbXCJlbXB0eVwiXSggZWxlbSApO1xuXHRcdH0sXG5cblx0XHQvLyBFbGVtZW50L2lucHV0IHR5cGVzXG5cdFx0XCJoZWFkZXJcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmhlYWRlci50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiaW5wdXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmlucHV0cy50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiYnV0dG9uXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIG5hbWUgPSBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gXCJidXR0b25cIiB8fCBuYW1lID09PSBcImJ1dHRvblwiO1xuXHRcdH0sXG5cblx0XHRcInRleHRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgYXR0cjtcblx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaW5wdXRcIiAmJlxuXHRcdFx0XHRlbGVtLnR5cGUgPT09IFwidGV4dFwiICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUU8OFxuXHRcdFx0XHQvLyBOZXcgSFRNTDUgYXR0cmlidXRlIHZhbHVlcyAoZS5nLiwgXCJzZWFyY2hcIikgYXBwZWFyIHdpdGggZWxlbS50eXBlID09PSBcInRleHRcIlxuXHRcdFx0XHQoIChhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpKSA9PSBudWxsIHx8IGF0dHIudG9Mb3dlckNhc2UoKSA9PT0gXCJ0ZXh0XCIgKTtcblx0XHR9LFxuXG5cdFx0Ly8gUG9zaXRpb24taW4tY29sbGVjdGlvblxuXHRcdFwiZmlyc3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBbIDAgXTtcblx0XHR9KSxcblxuXHRcdFwibGFzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHJldHVybiBbIGxlbmd0aCAtIDEgXTtcblx0XHR9KSxcblxuXHRcdFwiZXFcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0cmV0dXJuIFsgYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJldmVuXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0dmFyIGkgPSAwO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpICs9IDIgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJvZGRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDE7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcImx0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHZhciBpID0gYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudDtcblx0XHRcdGZvciAoIDsgLS1pID49IDA7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwiZ3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyArK2kgPCBsZW5ndGg7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KVxuXHR9XG59O1xuXG5FeHByLnBzZXVkb3NbXCJudGhcIl0gPSBFeHByLnBzZXVkb3NbXCJlcVwiXTtcblxuLy8gQWRkIGJ1dHRvbi9pbnB1dCB0eXBlIHBzZXVkb3NcbmZvciAoIGkgaW4geyByYWRpbzogdHJ1ZSwgY2hlY2tib3g6IHRydWUsIGZpbGU6IHRydWUsIHBhc3N3b3JkOiB0cnVlLCBpbWFnZTogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUlucHV0UHNldWRvKCBpICk7XG59XG5mb3IgKCBpIGluIHsgc3VibWl0OiB0cnVlLCByZXNldDogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUJ1dHRvblBzZXVkbyggaSApO1xufVxuXG4vLyBFYXN5IEFQSSBmb3IgY3JlYXRpbmcgbmV3IHNldEZpbHRlcnNcbmZ1bmN0aW9uIHNldEZpbHRlcnMoKSB7fVxuc2V0RmlsdGVycy5wcm90b3R5cGUgPSBFeHByLmZpbHRlcnMgPSBFeHByLnBzZXVkb3M7XG5FeHByLnNldEZpbHRlcnMgPSBuZXcgc2V0RmlsdGVycygpO1xuXG50b2tlbml6ZSA9IFNpenpsZS50b2tlbml6ZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgcGFyc2VPbmx5ICkge1xuXHR2YXIgbWF0Y2hlZCwgbWF0Y2gsIHRva2VucywgdHlwZSxcblx0XHRzb0ZhciwgZ3JvdXBzLCBwcmVGaWx0ZXJzLFxuXHRcdGNhY2hlZCA9IHRva2VuQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXTtcblxuXHRpZiAoIGNhY2hlZCApIHtcblx0XHRyZXR1cm4gcGFyc2VPbmx5ID8gMCA6IGNhY2hlZC5zbGljZSggMCApO1xuXHR9XG5cblx0c29GYXIgPSBzZWxlY3Rvcjtcblx0Z3JvdXBzID0gW107XG5cdHByZUZpbHRlcnMgPSBFeHByLnByZUZpbHRlcjtcblxuXHR3aGlsZSAoIHNvRmFyICkge1xuXG5cdFx0Ly8gQ29tbWEgYW5kIGZpcnN0IHJ1blxuXHRcdGlmICggIW1hdGNoZWQgfHwgKG1hdGNoID0gcmNvbW1hLmV4ZWMoIHNvRmFyICkpICkge1xuXHRcdFx0aWYgKCBtYXRjaCApIHtcblx0XHRcdFx0Ly8gRG9uJ3QgY29uc3VtZSB0cmFpbGluZyBjb21tYXMgYXMgdmFsaWRcblx0XHRcdFx0c29GYXIgPSBzb0Zhci5zbGljZSggbWF0Y2hbMF0ubGVuZ3RoICkgfHwgc29GYXI7XG5cdFx0XHR9XG5cdFx0XHRncm91cHMucHVzaCggKHRva2VucyA9IFtdKSApO1xuXHRcdH1cblxuXHRcdG1hdGNoZWQgPSBmYWxzZTtcblxuXHRcdC8vIENvbWJpbmF0b3JzXG5cdFx0aWYgKCAobWF0Y2ggPSByY29tYmluYXRvcnMuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0dmFsdWU6IG1hdGNoZWQsXG5cdFx0XHRcdC8vIENhc3QgZGVzY2VuZGFudCBjb21iaW5hdG9ycyB0byBzcGFjZVxuXHRcdFx0XHR0eXBlOiBtYXRjaFswXS5yZXBsYWNlKCBydHJpbSwgXCIgXCIgKVxuXHRcdFx0fSk7XG5cdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdH1cblxuXHRcdC8vIEZpbHRlcnNcblx0XHRmb3IgKCB0eXBlIGluIEV4cHIuZmlsdGVyICkge1xuXHRcdFx0aWYgKCAobWF0Y2ggPSBtYXRjaEV4cHJbIHR5cGUgXS5leGVjKCBzb0ZhciApKSAmJiAoIXByZUZpbHRlcnNbIHR5cGUgXSB8fFxuXHRcdFx0XHQobWF0Y2ggPSBwcmVGaWx0ZXJzWyB0eXBlIF0oIG1hdGNoICkpKSApIHtcblx0XHRcdFx0bWF0Y2hlZCA9IG1hdGNoLnNoaWZ0KCk7XG5cdFx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRcdG1hdGNoZXM6IG1hdGNoXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIW1hdGNoZWQgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHQvLyBSZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgaW52YWxpZCBleGNlc3Ncblx0Ly8gaWYgd2UncmUganVzdCBwYXJzaW5nXG5cdC8vIE90aGVyd2lzZSwgdGhyb3cgYW4gZXJyb3Igb3IgcmV0dXJuIHRva2Vuc1xuXHRyZXR1cm4gcGFyc2VPbmx5ID9cblx0XHRzb0Zhci5sZW5ndGggOlxuXHRcdHNvRmFyID9cblx0XHRcdFNpenpsZS5lcnJvciggc2VsZWN0b3IgKSA6XG5cdFx0XHQvLyBDYWNoZSB0aGUgdG9rZW5zXG5cdFx0XHR0b2tlbkNhY2hlKCBzZWxlY3RvciwgZ3JvdXBzICkuc2xpY2UoIDAgKTtcbn07XG5cbmZ1bmN0aW9uIHRvU2VsZWN0b3IoIHRva2VucyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGxlbiA9IHRva2Vucy5sZW5ndGgsXG5cdFx0c2VsZWN0b3IgPSBcIlwiO1xuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRzZWxlY3RvciArPSB0b2tlbnNbaV0udmFsdWU7XG5cdH1cblx0cmV0dXJuIHNlbGVjdG9yO1xufVxuXG5mdW5jdGlvbiBhZGRDb21iaW5hdG9yKCBtYXRjaGVyLCBjb21iaW5hdG9yLCBiYXNlICkge1xuXHR2YXIgZGlyID0gY29tYmluYXRvci5kaXIsXG5cdFx0c2tpcCA9IGNvbWJpbmF0b3IubmV4dCxcblx0XHRrZXkgPSBza2lwIHx8IGRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBrZXkgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGNsb3Nlc3QgYW5jZXN0b3IvcHJlY2VkaW5nIGVsZW1lbnRcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSA6XG5cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGFsbCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudHNcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCB1bmlxdWVDYWNoZSwgb3V0ZXJDYWNoZSxcblx0XHRcdFx0bmV3Q2FjaGUgPSBbIGRpcnJ1bnMsIGRvbmVOYW1lIF07XG5cblx0XHRcdC8vIFdlIGNhbid0IHNldCBhcmJpdHJhcnkgZGF0YSBvbiBYTUwgbm9kZXMsIHNvIHRoZXkgZG9uJ3QgYmVuZWZpdCBmcm9tIGNvbWJpbmF0b3IgY2FjaGluZ1xuXHRcdFx0aWYgKCB4bWwgKSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBlbGVtLnVuaXF1ZUlEIF0gfHwgKG91dGVyQ2FjaGVbIGVsZW0udW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0aWYgKCBza2lwICYmIHNraXAgPT09IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSApIHtcblx0XHRcdFx0XHRcdFx0ZWxlbSA9IGVsZW1bIGRpciBdIHx8IGVsZW07XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCAob2xkQ2FjaGUgPSB1bmlxdWVDYWNoZVsga2V5IF0pICYmXG5cdFx0XHRcdFx0XHRcdG9sZENhY2hlWyAwIF0gPT09IGRpcnJ1bnMgJiYgb2xkQ2FjaGVbIDEgXSA9PT0gZG9uZU5hbWUgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQXNzaWduIHRvIG5ld0NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0cmV0dXJuIChuZXdDYWNoZVsgMiBdID0gb2xkQ2FjaGVbIDIgXSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXVzZSBuZXdjYWNoZSBzbyByZXN1bHRzIGJhY2stcHJvcGFnYXRlIHRvIHByZXZpb3VzIGVsZW1lbnRzXG5cdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyBrZXkgXSA9IG5ld0NhY2hlO1xuXG5cdFx0XHRcdFx0XHRcdC8vIEEgbWF0Y2ggbWVhbnMgd2UncmUgZG9uZTsgYSBmYWlsIG1lYW5zIHdlIGhhdmUgdG8ga2VlcCBjaGVja2luZ1xuXHRcdFx0XHRcdFx0XHRpZiAoIChuZXdDYWNoZVsgMiBdID0gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkpICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcbn1cblxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICkge1xuXHRyZXR1cm4gbWF0Y2hlcnMubGVuZ3RoID4gMSA/XG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciBpID0gbWF0Y2hlcnMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggIW1hdGNoZXJzW2ldKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gOlxuXHRcdG1hdGNoZXJzWzBdO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciwgY29udGV4dHMsIHJlc3VsdHMgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBjb250ZXh0cy5sZW5ndGg7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHRzW2ldLCByZXN1bHRzICk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdHM7XG59XG5cbmZ1bmN0aW9uIGNvbmRlbnNlKCB1bm1hdGNoZWQsIG1hcCwgZmlsdGVyLCBjb250ZXh0LCB4bWwgKSB7XG5cdHZhciBlbGVtLFxuXHRcdG5ld1VubWF0Y2hlZCA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGxlbiA9IHVubWF0Y2hlZC5sZW5ndGgsXG5cdFx0bWFwcGVkID0gbWFwICE9IG51bGw7XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRpZiAoICFmaWx0ZXIgfHwgZmlsdGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0bmV3VW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0aWYgKCBtYXBwZWQgKSB7XG5cdFx0XHRcdFx0bWFwLnB1c2goIGkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBuZXdVbm1hdGNoZWQ7XG59XG5cbmZ1bmN0aW9uIHNldE1hdGNoZXIoIHByZUZpbHRlciwgc2VsZWN0b3IsIG1hdGNoZXIsIHBvc3RGaWx0ZXIsIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApIHtcblx0aWYgKCBwb3N0RmlsdGVyICYmICFwb3N0RmlsdGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbHRlciA9IHNldE1hdGNoZXIoIHBvc3RGaWx0ZXIgKTtcblx0fVxuXHRpZiAoIHBvc3RGaW5kZXIgJiYgIXBvc3RGaW5kZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmluZGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICk7XG5cdH1cblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgcmVzdWx0cywgY29udGV4dCwgeG1sICkge1xuXHRcdHZhciB0ZW1wLCBpLCBlbGVtLFxuXHRcdFx0cHJlTWFwID0gW10sXG5cdFx0XHRwb3N0TWFwID0gW10sXG5cdFx0XHRwcmVleGlzdGluZyA9IHJlc3VsdHMubGVuZ3RoLFxuXG5cdFx0XHQvLyBHZXQgaW5pdGlhbCBlbGVtZW50cyBmcm9tIHNlZWQgb3IgY29udGV4dFxuXHRcdFx0ZWxlbXMgPSBzZWVkIHx8IG11bHRpcGxlQ29udGV4dHMoIHNlbGVjdG9yIHx8IFwiKlwiLCBjb250ZXh0Lm5vZGVUeXBlID8gWyBjb250ZXh0IF0gOiBjb250ZXh0LCBbXSApLFxuXG5cdFx0XHQvLyBQcmVmaWx0ZXIgdG8gZ2V0IG1hdGNoZXIgaW5wdXQsIHByZXNlcnZpbmcgYSBtYXAgZm9yIHNlZWQtcmVzdWx0cyBzeW5jaHJvbml6YXRpb25cblx0XHRcdG1hdGNoZXJJbiA9IHByZUZpbHRlciAmJiAoIHNlZWQgfHwgIXNlbGVjdG9yICkgP1xuXHRcdFx0XHRjb25kZW5zZSggZWxlbXMsIHByZU1hcCwgcHJlRmlsdGVyLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdGVsZW1zLFxuXG5cdFx0XHRtYXRjaGVyT3V0ID0gbWF0Y2hlciA/XG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgYSBwb3N0RmluZGVyLCBvciBmaWx0ZXJlZCBzZWVkLCBvciBub24tc2VlZCBwb3N0RmlsdGVyIG9yIHByZWV4aXN0aW5nIHJlc3VsdHMsXG5cdFx0XHRcdHBvc3RGaW5kZXIgfHwgKCBzZWVkID8gcHJlRmlsdGVyIDogcHJlZXhpc3RpbmcgfHwgcG9zdEZpbHRlciApID9cblxuXHRcdFx0XHRcdC8vIC4uLmludGVybWVkaWF0ZSBwcm9jZXNzaW5nIGlzIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdFtdIDpcblxuXHRcdFx0XHRcdC8vIC4uLm90aGVyd2lzZSB1c2UgcmVzdWx0cyBkaXJlY3RseVxuXHRcdFx0XHRcdHJlc3VsdHMgOlxuXHRcdFx0XHRtYXRjaGVySW47XG5cblx0XHQvLyBGaW5kIHByaW1hcnkgbWF0Y2hlc1xuXHRcdGlmICggbWF0Y2hlciApIHtcblx0XHRcdG1hdGNoZXIoIG1hdGNoZXJJbiwgbWF0Y2hlck91dCwgY29udGV4dCwgeG1sICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgcG9zdEZpbHRlclxuXHRcdGlmICggcG9zdEZpbHRlciApIHtcblx0XHRcdHRlbXAgPSBjb25kZW5zZSggbWF0Y2hlck91dCwgcG9zdE1hcCApO1xuXHRcdFx0cG9zdEZpbHRlciggdGVtcCwgW10sIGNvbnRleHQsIHhtbCApO1xuXG5cdFx0XHQvLyBVbi1tYXRjaCBmYWlsaW5nIGVsZW1lbnRzIGJ5IG1vdmluZyB0aGVtIGJhY2sgdG8gbWF0Y2hlckluXG5cdFx0XHRpID0gdGVtcC5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAoZWxlbSA9IHRlbXBbaV0pICkge1xuXHRcdFx0XHRcdG1hdGNoZXJPdXRbIHBvc3RNYXBbaV0gXSA9ICEobWF0Y2hlckluWyBwb3N0TWFwW2ldIF0gPSBlbGVtKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggc2VlZCApIHtcblx0XHRcdGlmICggcG9zdEZpbmRlciB8fCBwcmVGaWx0ZXIgKSB7XG5cdFx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIGZpbmFsIG1hdGNoZXJPdXQgYnkgY29uZGVuc2luZyB0aGlzIGludGVybWVkaWF0ZSBpbnRvIHBvc3RGaW5kZXIgY29udGV4dHNcblx0XHRcdFx0XHR0ZW1wID0gW107XG5cdFx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIG1hdGNoZXJJbiBzaW5jZSBlbGVtIGlzIG5vdCB5ZXQgYSBmaW5hbCBtYXRjaFxuXHRcdFx0XHRcdFx0XHR0ZW1wLnB1c2goIChtYXRjaGVySW5baV0gPSBlbGVtKSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCAobWF0Y2hlck91dCA9IFtdKSwgdGVtcCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBNb3ZlIG1hdGNoZWQgZWxlbWVudHMgZnJvbSBzZWVkIHRvIHJlc3VsdHMgdG8ga2VlcCB0aGVtIHN5bmNocm9uaXplZFxuXHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSAmJlxuXHRcdFx0XHRcdFx0KHRlbXAgPSBwb3N0RmluZGVyID8gaW5kZXhPZiggc2VlZCwgZWxlbSApIDogcHJlTWFwW2ldKSA+IC0xICkge1xuXG5cdFx0XHRcdFx0XHRzZWVkW3RlbXBdID0gIShyZXN1bHRzW3RlbXBdID0gZWxlbSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBBZGQgZWxlbWVudHMgdG8gcmVzdWx0cywgdGhyb3VnaCBwb3N0RmluZGVyIGlmIGRlZmluZWRcblx0XHR9IGVsc2Uge1xuXHRcdFx0bWF0Y2hlck91dCA9IGNvbmRlbnNlKFxuXHRcdFx0XHRtYXRjaGVyT3V0ID09PSByZXN1bHRzID9cblx0XHRcdFx0XHRtYXRjaGVyT3V0LnNwbGljZSggcHJlZXhpc3RpbmcsIG1hdGNoZXJPdXQubGVuZ3RoICkgOlxuXHRcdFx0XHRcdG1hdGNoZXJPdXRcblx0XHRcdCk7XG5cdFx0XHRpZiAoIHBvc3RGaW5kZXIgKSB7XG5cdFx0XHRcdHBvc3RGaW5kZXIoIG51bGwsIHJlc3VsdHMsIG1hdGNoZXJPdXQsIHhtbCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgbWF0Y2hlck91dCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMgKSB7XG5cdHZhciBjaGVja0NvbnRleHQsIG1hdGNoZXIsIGosXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRsZWFkaW5nUmVsYXRpdmUgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbMF0udHlwZSBdLFxuXHRcdGltcGxpY2l0UmVsYXRpdmUgPSBsZWFkaW5nUmVsYXRpdmUgfHwgRXhwci5yZWxhdGl2ZVtcIiBcIl0sXG5cdFx0aSA9IGxlYWRpbmdSZWxhdGl2ZSA/IDEgOiAwLFxuXG5cdFx0Ly8gVGhlIGZvdW5kYXRpb25hbCBtYXRjaGVyIGVuc3VyZXMgdGhhdCBlbGVtZW50cyBhcmUgcmVhY2hhYmxlIGZyb20gdG9wLWxldmVsIGNvbnRleHQocylcblx0XHRtYXRjaENvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBjaGVja0NvbnRleHQ7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoQW55Q29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YoIGNoZWNrQ29udGV4dCwgZWxlbSApID4gLTE7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoZXJzID0gWyBmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIHJldCA9ICggIWxlYWRpbmdSZWxhdGl2ZSAmJiAoIHhtbCB8fCBjb250ZXh0ICE9PSBvdXRlcm1vc3RDb250ZXh0ICkgKSB8fCAoXG5cdFx0XHRcdChjaGVja0NvbnRleHQgPSBjb250ZXh0KS5ub2RlVHlwZSA/XG5cdFx0XHRcdFx0bWF0Y2hDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdFx0bWF0Y2hBbnlDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSApO1xuXHRcdFx0Ly8gQXZvaWQgaGFuZ2luZyBvbnRvIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRjaGVja0NvbnRleHQgPSBudWxsO1xuXHRcdFx0cmV0dXJuIHJldDtcblx0XHR9IF07XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAobWF0Y2hlciA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1tpXS50eXBlIF0pICkge1xuXHRcdFx0bWF0Y2hlcnMgPSBbIGFkZENvbWJpbmF0b3IoZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksIG1hdGNoZXIpIF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hdGNoZXIgPSBFeHByLmZpbHRlclsgdG9rZW5zW2ldLnR5cGUgXS5hcHBseSggbnVsbCwgdG9rZW5zW2ldLm1hdGNoZXMgKTtcblxuXHRcdFx0Ly8gUmV0dXJuIHNwZWNpYWwgdXBvbiBzZWVpbmcgYSBwb3NpdGlvbmFsIG1hdGNoZXJcblx0XHRcdGlmICggbWF0Y2hlclsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHQvLyBGaW5kIHRoZSBuZXh0IHJlbGF0aXZlIG9wZXJhdG9yIChpZiBhbnkpIGZvciBwcm9wZXIgaGFuZGxpbmdcblx0XHRcdFx0aiA9ICsraTtcblx0XHRcdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyB0b2tlbnNbal0udHlwZSBdICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBzZXRNYXRjaGVyKFxuXHRcdFx0XHRcdGkgPiAxICYmIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLFxuXHRcdFx0XHRcdGkgPiAxICYmIHRvU2VsZWN0b3IoXG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgcHJlY2VkaW5nIHRva2VuIHdhcyBhIGRlc2NlbmRhbnQgY29tYmluYXRvciwgaW5zZXJ0IGFuIGltcGxpY2l0IGFueS1lbGVtZW50IGAqYFxuXHRcdFx0XHRcdFx0dG9rZW5zLnNsaWNlKCAwLCBpIC0gMSApLmNvbmNhdCh7IHZhbHVlOiB0b2tlbnNbIGkgLSAyIF0udHlwZSA9PT0gXCIgXCIgPyBcIipcIiA6IFwiXCIgfSlcblx0XHRcdFx0XHQpLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSxcblx0XHRcdFx0XHRtYXRjaGVyLFxuXHRcdFx0XHRcdGkgPCBqICYmIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMuc2xpY2UoIGksIGogKSApLFxuXHRcdFx0XHRcdGogPCBsZW4gJiYgbWF0Y2hlckZyb21Ub2tlbnMoICh0b2tlbnMgPSB0b2tlbnMuc2xpY2UoIGogKSkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIHRvU2VsZWN0b3IoIHRva2VucyApXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVycy5wdXNoKCBtYXRjaGVyICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSB7XG5cdHZhciBieVNldCA9IHNldE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0YnlFbGVtZW50ID0gZWxlbWVudE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0c3VwZXJNYXRjaGVyID0gZnVuY3Rpb24oIHNlZWQsIGNvbnRleHQsIHhtbCwgcmVzdWx0cywgb3V0ZXJtb3N0ICkge1xuXHRcdFx0dmFyIGVsZW0sIGosIG1hdGNoZXIsXG5cdFx0XHRcdG1hdGNoZWRDb3VudCA9IDAsXG5cdFx0XHRcdGkgPSBcIjBcIixcblx0XHRcdFx0dW5tYXRjaGVkID0gc2VlZCAmJiBbXSxcblx0XHRcdFx0c2V0TWF0Y2hlZCA9IFtdLFxuXHRcdFx0XHRjb250ZXh0QmFja3VwID0gb3V0ZXJtb3N0Q29udGV4dCxcblx0XHRcdFx0Ly8gV2UgbXVzdCBhbHdheXMgaGF2ZSBlaXRoZXIgc2VlZCBlbGVtZW50cyBvciBvdXRlcm1vc3QgY29udGV4dFxuXHRcdFx0XHRlbGVtcyA9IHNlZWQgfHwgYnlFbGVtZW50ICYmIEV4cHIuZmluZFtcIlRBR1wiXSggXCIqXCIsIG91dGVybW9zdCApLFxuXHRcdFx0XHQvLyBVc2UgaW50ZWdlciBkaXJydW5zIGlmZiB0aGlzIGlzIHRoZSBvdXRlcm1vc3QgbWF0Y2hlclxuXHRcdFx0XHRkaXJydW5zVW5pcXVlID0gKGRpcnJ1bnMgKz0gY29udGV4dEJhY2t1cCA9PSBudWxsID8gMSA6IE1hdGgucmFuZG9tKCkgfHwgMC4xKSxcblx0XHRcdFx0bGVuID0gZWxlbXMubGVuZ3RoO1xuXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0b3V0ZXJtb3N0Q29udGV4dCA9IGNvbnRleHQgPT09IGRvY3VtZW50IHx8IGNvbnRleHQgfHwgb3V0ZXJtb3N0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgZWxlbWVudHMgcGFzc2luZyBlbGVtZW50TWF0Y2hlcnMgZGlyZWN0bHkgdG8gcmVzdWx0c1xuXHRcdFx0Ly8gU3VwcG9ydDogSUU8OSwgU2FmYXJpXG5cdFx0XHQvLyBUb2xlcmF0ZSBOb2RlTGlzdCBwcm9wZXJ0aWVzIChJRTogXCJsZW5ndGhcIjsgU2FmYXJpOiA8bnVtYmVyPikgbWF0Y2hpbmcgZWxlbWVudHMgYnkgaWRcblx0XHRcdGZvciAoIDsgaSAhPT0gbGVuICYmIChlbGVtID0gZWxlbXNbaV0pICE9IG51bGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBieUVsZW1lbnQgJiYgZWxlbSApIHtcblx0XHRcdFx0XHRqID0gMDtcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0ICYmIGVsZW0ub3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHRcdFx0XHRcdFx0eG1sID0gIWRvY3VtZW50SXNIVE1MO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR3aGlsZSAoIChtYXRjaGVyID0gZWxlbWVudE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVyKCBlbGVtLCBjb250ZXh0IHx8IGRvY3VtZW50LCB4bWwpICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHJhY2sgdW5tYXRjaGVkIGVsZW1lbnRzIGZvciBzZXQgZmlsdGVyc1xuXHRcdFx0XHRpZiAoIGJ5U2V0ICkge1xuXHRcdFx0XHRcdC8vIFRoZXkgd2lsbCBoYXZlIGdvbmUgdGhyb3VnaCBhbGwgcG9zc2libGUgbWF0Y2hlcnNcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBMZW5ndGhlbiB0aGUgYXJyYXkgZm9yIGV2ZXJ5IGVsZW1lbnQsIG1hdGNoZWQgb3Igbm90XG5cdFx0XHRcdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0XHRcdFx0dW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYGlgIGlzIG5vdyB0aGUgY291bnQgb2YgZWxlbWVudHMgdmlzaXRlZCBhYm92ZSwgYW5kIGFkZGluZyBpdCB0byBgbWF0Y2hlZENvdW50YFxuXHRcdFx0Ly8gbWFrZXMgdGhlIGxhdHRlciBub25uZWdhdGl2ZS5cblx0XHRcdG1hdGNoZWRDb3VudCArPSBpO1xuXG5cdFx0XHQvLyBBcHBseSBzZXQgZmlsdGVycyB0byB1bm1hdGNoZWQgZWxlbWVudHNcblx0XHRcdC8vIE5PVEU6IFRoaXMgY2FuIGJlIHNraXBwZWQgaWYgdGhlcmUgYXJlIG5vIHVubWF0Y2hlZCBlbGVtZW50cyAoaS5lLiwgYG1hdGNoZWRDb3VudGBcblx0XHRcdC8vIGVxdWFscyBgaWApLCB1bmxlc3Mgd2UgZGlkbid0IHZpc2l0IF9hbnlfIGVsZW1lbnRzIGluIHRoZSBhYm92ZSBsb29wIGJlY2F1c2Ugd2UgaGF2ZVxuXHRcdFx0Ly8gbm8gZWxlbWVudCBtYXRjaGVycyBhbmQgbm8gc2VlZC5cblx0XHRcdC8vIEluY3JlbWVudGluZyBhbiBpbml0aWFsbHktc3RyaW5nIFwiMFwiIGBpYCBhbGxvd3MgYGlgIHRvIHJlbWFpbiBhIHN0cmluZyBvbmx5IGluIHRoYXRcblx0XHRcdC8vIGNhc2UsIHdoaWNoIHdpbGwgcmVzdWx0IGluIGEgXCIwMFwiIGBtYXRjaGVkQ291bnRgIHRoYXQgZGlmZmVycyBmcm9tIGBpYCBidXQgaXMgYWxzb1xuXHRcdFx0Ly8gbnVtZXJpY2FsbHkgemVyby5cblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0Ly8gUmVpbnRlZ3JhdGUgZWxlbWVudCBtYXRjaGVzIHRvIGVsaW1pbmF0ZSB0aGUgbmVlZCBmb3Igc29ydGluZ1xuXHRcdFx0XHRcdGlmICggbWF0Y2hlZENvdW50ID4gMCApIHtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoICEodW5tYXRjaGVkW2ldIHx8IHNldE1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRcdHNldE1hdGNoZWRbaV0gPSBwb3AuY2FsbCggcmVzdWx0cyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRGlzY2FyZCBpbmRleCBwbGFjZWhvbGRlciB2YWx1ZXMgdG8gZ2V0IG9ubHkgYWN0dWFsIG1hdGNoZXNcblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBtYXRjaGVzIHRvIHJlc3VsdHNcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2V0TWF0Y2hlZCApO1xuXG5cdFx0XHRcdC8vIFNlZWRsZXNzIHNldCBtYXRjaGVzIHN1Y2NlZWRpbmcgbXVsdGlwbGUgc3VjY2Vzc2Z1bCBtYXRjaGVycyBzdGlwdWxhdGUgc29ydGluZ1xuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gT3ZlcnJpZGUgbWFuaXB1bGF0aW9uIG9mIGdsb2JhbHMgYnkgbmVzdGVkIG1hdGNoZXJzXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0QmFja3VwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdW5tYXRjaGVkO1xuXHRcdH07XG5cblx0cmV0dXJuIGJ5U2V0ID9cblx0XHRtYXJrRnVuY3Rpb24oIHN1cGVyTWF0Y2hlciApIDpcblx0XHRzdXBlck1hdGNoZXI7XG59XG5cbmNvbXBpbGUgPSBTaXp6bGUuY29tcGlsZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgbWF0Y2ggLyogSW50ZXJuYWwgVXNlIE9ubHkgKi8gKSB7XG5cdHZhciBpLFxuXHRcdHNldE1hdGNoZXJzID0gW10sXG5cdFx0ZWxlbWVudE1hdGNoZXJzID0gW10sXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggIWNhY2hlZCApIHtcblx0XHQvLyBHZW5lcmF0ZSBhIGZ1bmN0aW9uIG9mIHJlY3Vyc2l2ZSBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBjaGVjayBlYWNoIGVsZW1lbnRcblx0XHRpZiAoICFtYXRjaCApIHtcblx0XHRcdG1hdGNoID0gdG9rZW5pemUoIHNlbGVjdG9yICk7XG5cdFx0fVxuXHRcdGkgPSBtYXRjaC5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRjYWNoZWQgPSBtYXRjaGVyRnJvbVRva2VucyggbWF0Y2hbaV0gKTtcblx0XHRcdGlmICggY2FjaGVkWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdHNldE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENhY2hlIHRoZSBjb21waWxlZCBmdW5jdGlvblxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGUoIHNlbGVjdG9yLCBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSApO1xuXG5cdFx0Ly8gU2F2ZSBzZWxlY3RvciBhbmQgdG9rZW5pemF0aW9uXG5cdFx0Y2FjaGVkLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdH1cblx0cmV0dXJuIGNhY2hlZDtcbn07XG5cbi8qKlxuICogQSBsb3ctbGV2ZWwgc2VsZWN0aW9uIGZ1bmN0aW9uIHRoYXQgd29ya3Mgd2l0aCBTaXp6bGUncyBjb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHNlbGVjdG9yIEEgc2VsZWN0b3Igb3IgYSBwcmUtY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbiBidWlsdCB3aXRoIFNpenpsZS5jb21waWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHRzXVxuICogQHBhcmFtIHtBcnJheX0gW3NlZWRdIEEgc2V0IG9mIGVsZW1lbnRzIHRvIG1hdGNoIGFnYWluc3RcbiAqL1xuc2VsZWN0ID0gU2l6emxlLnNlbGVjdCA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIGksIHRva2VucywgdG9rZW4sIHR5cGUsIGZpbmQsXG5cdFx0Y29tcGlsZWQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiAmJiBzZWxlY3Rvcixcblx0XHRtYXRjaCA9ICFzZWVkICYmIHRva2VuaXplKCAoc2VsZWN0b3IgPSBjb21waWxlZC5zZWxlY3RvciB8fCBzZWxlY3RvcikgKTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBUcnkgdG8gbWluaW1pemUgb3BlcmF0aW9ucyBpZiB0aGVyZSBpcyBvbmx5IG9uZSBzZWxlY3RvciBpbiB0aGUgbGlzdCBhbmQgbm8gc2VlZFxuXHQvLyAodGhlIGxhdHRlciBvZiB3aGljaCBndWFyYW50ZWVzIHVzIGNvbnRleHQpXG5cdGlmICggbWF0Y2gubGVuZ3RoID09PSAxICkge1xuXG5cdFx0Ly8gUmVkdWNlIGNvbnRleHQgaWYgdGhlIGxlYWRpbmcgY29tcG91bmQgc2VsZWN0b3IgaXMgYW4gSURcblx0XHR0b2tlbnMgPSBtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwICk7XG5cdFx0aWYgKCB0b2tlbnMubGVuZ3RoID4gMiAmJiAodG9rZW4gPSB0b2tlbnNbMF0pLnR5cGUgPT09IFwiSURcIiAmJlxuXHRcdFx0XHRjb250ZXh0Lm5vZGVUeXBlID09PSA5ICYmIGRvY3VtZW50SXNIVE1MICYmIEV4cHIucmVsYXRpdmVbIHRva2Vuc1sxXS50eXBlIF0gKSB7XG5cblx0XHRcdGNvbnRleHQgPSAoIEV4cHIuZmluZFtcIklEXCJdKCB0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UocnVuZXNjYXBlLCBmdW5lc2NhcGUpLCBjb250ZXh0ICkgfHwgW10gKVswXTtcblx0XHRcdGlmICggIWNvbnRleHQgKSB7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXG5cdFx0XHQvLyBQcmVjb21waWxlZCBtYXRjaGVycyB3aWxsIHN0aWxsIHZlcmlmeSBhbmNlc3RyeSwgc28gc3RlcCB1cCBhIGxldmVsXG5cdFx0XHR9IGVsc2UgaWYgKCBjb21waWxlZCApIHtcblx0XHRcdFx0Y29udGV4dCA9IGNvbnRleHQucGFyZW50Tm9kZTtcblx0XHRcdH1cblxuXHRcdFx0c2VsZWN0b3IgPSBzZWxlY3Rvci5zbGljZSggdG9rZW5zLnNoaWZ0KCkudmFsdWUubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmV0Y2ggYSBzZWVkIHNldCBmb3IgcmlnaHQtdG8tbGVmdCBtYXRjaGluZ1xuXHRcdGkgPSBtYXRjaEV4cHJbXCJuZWVkc0NvbnRleHRcIl0udGVzdCggc2VsZWN0b3IgKSA/IDAgOiB0b2tlbnMubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG9rZW4gPSB0b2tlbnNbaV07XG5cblx0XHRcdC8vIEFib3J0IGlmIHdlIGhpdCBhIGNvbWJpbmF0b3Jcblx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgKHR5cGUgPSB0b2tlbi50eXBlKSBdICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggKGZpbmQgPSBFeHByLmZpbmRbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdC8vIFNlYXJjaCwgZXhwYW5kaW5nIGNvbnRleHQgZm9yIGxlYWRpbmcgc2libGluZyBjb21iaW5hdG9yc1xuXHRcdFx0XHRpZiAoIChzZWVkID0gZmluZChcblx0XHRcdFx0XHR0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICksXG5cdFx0XHRcdFx0cnNpYmxpbmcudGVzdCggdG9rZW5zWzBdLnR5cGUgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHRcdFx0XHQpKSApIHtcblxuXHRcdFx0XHRcdC8vIElmIHNlZWQgaXMgZW1wdHkgb3Igbm8gdG9rZW5zIHJlbWFpbiwgd2UgY2FuIHJldHVybiBlYXJseVxuXHRcdFx0XHRcdHRva2Vucy5zcGxpY2UoIGksIDEgKTtcblx0XHRcdFx0XHRzZWxlY3RvciA9IHNlZWQubGVuZ3RoICYmIHRvU2VsZWN0b3IoIHRva2VucyApO1xuXHRcdFx0XHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2VlZCApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDb21waWxlIGFuZCBleGVjdXRlIGEgZmlsdGVyaW5nIGZ1bmN0aW9uIGlmIG9uZSBpcyBub3QgcHJvdmlkZWRcblx0Ly8gUHJvdmlkZSBgbWF0Y2hgIHRvIGF2b2lkIHJldG9rZW5pemF0aW9uIGlmIHdlIG1vZGlmaWVkIHRoZSBzZWxlY3RvciBhYm92ZVxuXHQoIGNvbXBpbGVkIHx8IGNvbXBpbGUoIHNlbGVjdG9yLCBtYXRjaCApICkoXG5cdFx0c2VlZCxcblx0XHRjb250ZXh0LFxuXHRcdCFkb2N1bWVudElzSFRNTCxcblx0XHRyZXN1bHRzLFxuXHRcdCFjb250ZXh0IHx8IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHRcblx0KTtcblx0cmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vLyBPbmUtdGltZSBhc3NpZ25tZW50c1xuXG4vLyBTb3J0IHN0YWJpbGl0eVxuc3VwcG9ydC5zb3J0U3RhYmxlID0gZXhwYW5kby5zcGxpdChcIlwiKS5zb3J0KCBzb3J0T3JkZXIgKS5qb2luKFwiXCIpID09PSBleHBhbmRvO1xuXG4vLyBTdXBwb3J0OiBDaHJvbWUgMTQtMzUrXG4vLyBBbHdheXMgYXNzdW1lIGR1cGxpY2F0ZXMgaWYgdGhleSBhcmVuJ3QgcGFzc2VkIHRvIHRoZSBjb21wYXJpc29uIGZ1bmN0aW9uXG5zdXBwb3J0LmRldGVjdER1cGxpY2F0ZXMgPSAhIWhhc0R1cGxpY2F0ZTtcblxuLy8gSW5pdGlhbGl6ZSBhZ2FpbnN0IHRoZSBkZWZhdWx0IGRvY3VtZW50XG5zZXREb2N1bWVudCgpO1xuXG4vLyBTdXBwb3J0OiBXZWJraXQ8NTM3LjMyIC0gU2FmYXJpIDYuMC4zL0Nocm9tZSAyNSAoZml4ZWQgaW4gQ2hyb21lIDI3KVxuLy8gRGV0YWNoZWQgbm9kZXMgY29uZm91bmRpbmdseSBmb2xsb3cgKmVhY2ggb3RoZXIqXG5zdXBwb3J0LnNvcnREZXRhY2hlZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdC8vIFNob3VsZCByZXR1cm4gMSwgYnV0IHJldHVybnMgNCAoZm9sbG93aW5nKVxuXHRyZXR1cm4gZWwuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJmaWVsZHNldFwiKSApICYgMTtcbn0pO1xuXG4vLyBTdXBwb3J0OiBJRTw4XG4vLyBQcmV2ZW50IGF0dHJpYnV0ZS9wcm9wZXJ0eSBcImludGVycG9sYXRpb25cIlxuLy8gaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNjQyOSUyOFZTLjg1JTI5LmFzcHhcbmlmICggIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGEgaHJlZj0nIyc+PC9hPlwiO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZGVmYXVsdFZhbHVlIGluIHBsYWNlIG9mIGdldEF0dHJpYnV0ZShcInZhbHVlXCIpXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGlucHV0Lz5cIjtcblx0ZWwuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiApID09PSBcIlwiO1xufSkgKSB7XG5cdGFkZEhhbmRsZSggXCJ2YWx1ZVwiLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0aWYgKCAhaXNYTUwgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlucHV0XCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kZWZhdWx0VmFsdWU7XG5cdFx0fVxuXHR9KTtcbn1cblxuLy8gU3VwcG9ydDogSUU8OVxuLy8gVXNlIGdldEF0dHJpYnV0ZU5vZGUgdG8gZmV0Y2ggYm9vbGVhbnMgd2hlbiBnZXRBdHRyaWJ1dGUgbGllc1xuaWYgKCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0cmV0dXJuIGVsLmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxucmV0dXJuIFNpenpsZTtcblxufSkoIHdpbmRvdyApO1xuXG5cblxualF1ZXJ5LmZpbmQgPSBTaXp6bGU7XG5qUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7XG5cbi8vIERlcHJlY2F0ZWRcbmpRdWVyeS5leHByWyBcIjpcIiBdID0galF1ZXJ5LmV4cHIucHNldWRvcztcbmpRdWVyeS51bmlxdWVTb3J0ID0galF1ZXJ5LnVuaXF1ZSA9IFNpenpsZS51bmlxdWVTb3J0O1xualF1ZXJ5LnRleHQgPSBTaXp6bGUuZ2V0VGV4dDtcbmpRdWVyeS5pc1hNTERvYyA9IFNpenpsZS5pc1hNTDtcbmpRdWVyeS5jb250YWlucyA9IFNpenpsZS5jb250YWlucztcbmpRdWVyeS5lc2NhcGVTZWxlY3RvciA9IFNpenpsZS5lc2NhcGU7XG5cblxuXG5cbnZhciBkaXIgPSBmdW5jdGlvbiggZWxlbSwgZGlyLCB1bnRpbCApIHtcblx0dmFyIG1hdGNoZWQgPSBbXSxcblx0XHR0cnVuY2F0ZSA9IHVudGlsICE9PSB1bmRlZmluZWQ7XG5cblx0d2hpbGUgKCAoIGVsZW0gPSBlbGVtWyBkaXIgXSApICYmIGVsZW0ubm9kZVR5cGUgIT09IDkgKSB7XG5cdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0aWYgKCB0cnVuY2F0ZSAmJiBqUXVlcnkoIGVsZW0gKS5pcyggdW50aWwgKSApIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG1hdGNoZWQ7XG59O1xuXG5cbnZhciBzaWJsaW5ncyA9IGZ1bmN0aW9uKCBuLCBlbGVtICkge1xuXHR2YXIgbWF0Y2hlZCA9IFtdO1xuXG5cdGZvciAoIDsgbjsgbiA9IG4ubmV4dFNpYmxpbmcgKSB7XG5cdFx0aWYgKCBuLm5vZGVUeXBlID09PSAxICYmIG4gIT09IGVsZW0gKSB7XG5cdFx0XHRtYXRjaGVkLnB1c2goIG4gKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbWF0Y2hlZDtcbn07XG5cblxudmFyIHJuZWVkc0NvbnRleHQgPSBqUXVlcnkuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQ7XG5cblxuXG5mdW5jdGlvbiBub2RlTmFtZSggZWxlbSwgbmFtZSApIHtcblxuICByZXR1cm4gZWxlbS5ub2RlTmFtZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUudG9Mb3dlckNhc2UoKTtcblxufTtcbnZhciByc2luZ2xlVGFnID0gKCAvXjwoW2Etel1bXlxcL1xcMD46XFx4MjBcXHRcXHJcXG5cXGZdKilbXFx4MjBcXHRcXHJcXG5cXGZdKlxcLz8+KD86PFxcL1xcMT58KSQvaSApO1xuXG5cblxudmFyIHJpc1NpbXBsZSA9IC9eLlteOiNcXFtcXC4sXSokLztcblxuLy8gSW1wbGVtZW50IHRoZSBpZGVudGljYWwgZnVuY3Rpb25hbGl0eSBmb3IgZmlsdGVyIGFuZCBub3RcbmZ1bmN0aW9uIHdpbm5vdyggZWxlbWVudHMsIHF1YWxpZmllciwgbm90ICkge1xuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiAhIXF1YWxpZmllci5jYWxsKCBlbGVtLCBpLCBlbGVtICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBTaW5nbGUgZWxlbWVudFxuXHRpZiAoIHF1YWxpZmllci5ub2RlVHlwZSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGVsZW0gPT09IHF1YWxpZmllciApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gQXJyYXlsaWtlIG9mIGVsZW1lbnRzIChqUXVlcnksIGFyZ3VtZW50cywgQXJyYXkpXG5cdGlmICggdHlwZW9mIHF1YWxpZmllciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gU2ltcGxlIHNlbGVjdG9yIHRoYXQgY2FuIGJlIGZpbHRlcmVkIGRpcmVjdGx5LCByZW1vdmluZyBub24tRWxlbWVudHNcblx0aWYgKCByaXNTaW1wbGUudGVzdCggcXVhbGlmaWVyICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5maWx0ZXIoIHF1YWxpZmllciwgZWxlbWVudHMsIG5vdCApO1xuXHR9XG5cblx0Ly8gQ29tcGxleCBzZWxlY3RvciwgY29tcGFyZSB0aGUgdHdvIHNldHMsIHJlbW92aW5nIG5vbi1FbGVtZW50c1xuXHRxdWFsaWZpZXIgPSBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzICk7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3QgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMTtcblx0fSApO1xufVxuXG5qUXVlcnkuZmlsdGVyID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1zLCBub3QgKSB7XG5cdHZhciBlbGVtID0gZWxlbXNbIDAgXTtcblxuXHRpZiAoIG5vdCApIHtcblx0XHRleHByID0gXCI6bm90KFwiICsgZXhwciArIFwiKVwiO1xuXHR9XG5cblx0aWYgKCBlbGVtcy5sZW5ndGggPT09IDEgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBlbGVtLCBleHByICkgPyBbIGVsZW0gXSA6IFtdO1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeS5maW5kLm1hdGNoZXMoIGV4cHIsIGpRdWVyeS5ncmVwKCBlbGVtcywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7XG5cdH0gKSApO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmaW5kOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dmFyIGksIHJldCxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0c2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5KCBzZWxlY3RvciApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHNlbGZbIGkgXSwgdGhpcyApICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICkgKTtcblx0XHR9XG5cblx0XHRyZXQgPSB0aGlzLnB1c2hTdGFjayggW10gKTtcblxuXHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRqUXVlcnkuZmluZCggc2VsZWN0b3IsIHNlbGZbIGkgXSwgcmV0ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGxlbiA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggcmV0ICkgOiByZXQ7XG5cdH0sXG5cdGZpbHRlcjogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KCB0aGlzLCBzZWxlY3RvciB8fCBbXSwgZmFsc2UgKSApO1xuXHR9LFxuXHRub3Q6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHdpbm5vdyggdGhpcywgc2VsZWN0b3IgfHwgW10sIHRydWUgKSApO1xuXHR9LFxuXHRpczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiAhIXdpbm5vdyhcblx0XHRcdHRoaXMsXG5cblx0XHRcdC8vIElmIHRoaXMgaXMgYSBwb3NpdGlvbmFsL3JlbGF0aXZlIHNlbGVjdG9yLCBjaGVjayBtZW1iZXJzaGlwIGluIHRoZSByZXR1cm5lZCBzZXRcblx0XHRcdC8vIHNvICQoXCJwOmZpcnN0XCIpLmlzKFwicDpsYXN0XCIpIHdvbid0IHJldHVybiB0cnVlIGZvciBhIGRvYyB3aXRoIHR3byBcInBcIi5cblx0XHRcdHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiAmJiBybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICkgP1xuXHRcdFx0XHRqUXVlcnkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHRzZWxlY3RvciB8fCBbXSxcblx0XHRcdGZhbHNlXG5cdFx0KS5sZW5ndGg7XG5cdH1cbn0gKTtcblxuXG4vLyBJbml0aWFsaXplIGEgalF1ZXJ5IG9iamVjdFxuXG5cbi8vIEEgY2VudHJhbCByZWZlcmVuY2UgdG8gdGhlIHJvb3QgalF1ZXJ5KGRvY3VtZW50KVxudmFyIHJvb3RqUXVlcnksXG5cblx0Ly8gQSBzaW1wbGUgd2F5IHRvIGNoZWNrIGZvciBIVE1MIHN0cmluZ3Ncblx0Ly8gUHJpb3JpdGl6ZSAjaWQgb3ZlciA8dGFnPiB0byBhdm9pZCBYU1MgdmlhIGxvY2F0aW9uLmhhc2ggKCM5NTIxKVxuXHQvLyBTdHJpY3QgSFRNTCByZWNvZ25pdGlvbiAoIzExMjkwOiBtdXN0IHN0YXJ0IHdpdGggPClcblx0Ly8gU2hvcnRjdXQgc2ltcGxlICNpZCBjYXNlIGZvciBzcGVlZFxuXHRycXVpY2tFeHByID0gL14oPzpcXHMqKDxbXFx3XFxXXSs+KVtePl0qfCMoW1xcdy1dKykpJC8sXG5cblx0aW5pdCA9IGpRdWVyeS5mbi5pbml0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0LCByb290ICkge1xuXHRcdHZhciBtYXRjaCwgZWxlbTtcblxuXHRcdC8vIEhBTkRMRTogJChcIlwiKSwgJChudWxsKSwgJCh1bmRlZmluZWQpLCAkKGZhbHNlKVxuXHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Ly8gTWV0aG9kIGluaXQoKSBhY2NlcHRzIGFuIGFsdGVybmF0ZSByb290alF1ZXJ5XG5cdFx0Ly8gc28gbWlncmF0ZSBjYW4gc3VwcG9ydCBqUXVlcnkuc3ViIChnaC0yMTAxKVxuXHRcdHJvb3QgPSByb290IHx8IHJvb3RqUXVlcnk7XG5cblx0XHQvLyBIYW5kbGUgSFRNTCBzdHJpbmdzXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRpZiAoIHNlbGVjdG9yWyAwIF0gPT09IFwiPFwiICYmXG5cdFx0XHRcdHNlbGVjdG9yWyBzZWxlY3Rvci5sZW5ndGggLSAxIF0gPT09IFwiPlwiICYmXG5cdFx0XHRcdHNlbGVjdG9yLmxlbmd0aCA+PSAzICkge1xuXG5cdFx0XHRcdC8vIEFzc3VtZSB0aGF0IHN0cmluZ3MgdGhhdCBzdGFydCBhbmQgZW5kIHdpdGggPD4gYXJlIEhUTUwgYW5kIHNraXAgdGhlIHJlZ2V4IGNoZWNrXG5cdFx0XHRcdG1hdGNoID0gWyBudWxsLCBzZWxlY3RvciwgbnVsbCBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXRjaCA9IHJxdWlja0V4cHIuZXhlYyggc2VsZWN0b3IgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWF0Y2ggaHRtbCBvciBtYWtlIHN1cmUgbm8gY29udGV4dCBpcyBzcGVjaWZpZWQgZm9yICNpZFxuXHRcdFx0aWYgKCBtYXRjaCAmJiAoIG1hdGNoWyAxIF0gfHwgIWNvbnRleHQgKSApIHtcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCkgLT4gJChhcnJheSlcblx0XHRcdFx0aWYgKCBtYXRjaFsgMSBdICkge1xuXHRcdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgalF1ZXJ5ID8gY29udGV4dFsgMCBdIDogY29udGV4dDtcblxuXHRcdFx0XHRcdC8vIE9wdGlvbiB0byBydW4gc2NyaXB0cyBpcyB0cnVlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRcdC8vIEludGVudGlvbmFsbHkgbGV0IHRoZSBlcnJvciBiZSB0aHJvd24gaWYgcGFyc2VIVE1MIGlzIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLCBqUXVlcnkucGFyc2VIVE1MKFxuXHRcdFx0XHRcdFx0bWF0Y2hbIDEgXSxcblx0XHRcdFx0XHRcdGNvbnRleHQgJiYgY29udGV4dC5ub2RlVHlwZSA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogZG9jdW1lbnQsXG5cdFx0XHRcdFx0XHR0cnVlXG5cdFx0XHRcdFx0KSApO1xuXG5cdFx0XHRcdFx0Ly8gSEFORExFOiAkKGh0bWwsIHByb3BzKVxuXHRcdFx0XHRcdGlmICggcnNpbmdsZVRhZy50ZXN0KCBtYXRjaFsgMSBdICkgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGNvbnRleHQgKSApIHtcblx0XHRcdFx0XHRcdGZvciAoIG1hdGNoIGluIGNvbnRleHQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gUHJvcGVydGllcyBvZiBjb250ZXh0IGFyZSBjYWxsZWQgYXMgbWV0aG9kcyBpZiBwb3NzaWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB0aGlzWyBtYXRjaCBdICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpc1sgbWF0Y2ggXSggY29udGV4dFsgbWF0Y2ggXSApO1xuXG5cdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBvdGhlcndpc2Ugc2V0IGFzIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmF0dHIoIG1hdGNoLCBjb250ZXh0WyBtYXRjaCBdICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoI2lkKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggbWF0Y2hbIDIgXSApO1xuXG5cdFx0XHRcdFx0aWYgKCBlbGVtICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJbmplY3QgdGhlIGVsZW1lbnQgZGlyZWN0bHkgaW50byB0aGUgalF1ZXJ5IG9iamVjdFxuXHRcdFx0XHRcdFx0dGhpc1sgMCBdID0gZWxlbTtcblx0XHRcdFx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gSEFORExFOiAkKGV4cHIsICQoLi4uKSlcblx0XHRcdH0gZWxzZSBpZiAoICFjb250ZXh0IHx8IGNvbnRleHQuanF1ZXJ5ICkge1xuXHRcdFx0XHRyZXR1cm4gKCBjb250ZXh0IHx8IHJvb3QgKS5maW5kKCBzZWxlY3RvciApO1xuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgY29udGV4dClcblx0XHRcdC8vICh3aGljaCBpcyBqdXN0IGVxdWl2YWxlbnQgdG86ICQoY29udGV4dCkuZmluZChleHByKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29uc3RydWN0b3IoIGNvbnRleHQgKS5maW5kKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0Ly8gSEFORExFOiAkKERPTUVsZW1lbnQpXG5cdFx0fSBlbHNlIGlmICggc2VsZWN0b3Iubm9kZVR5cGUgKSB7XG5cdFx0XHR0aGlzWyAwIF0gPSBzZWxlY3Rvcjtcblx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0Ly8gSEFORExFOiAkKGZ1bmN0aW9uKVxuXHRcdC8vIFNob3J0Y3V0IGZvciBkb2N1bWVudCByZWFkeVxuXHRcdH0gZWxzZSBpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBzZWxlY3RvciApICkge1xuXHRcdFx0cmV0dXJuIHJvb3QucmVhZHkgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdHJvb3QucmVhZHkoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIEV4ZWN1dGUgaW1tZWRpYXRlbHkgaWYgcmVhZHkgaXMgbm90IHByZXNlbnRcblx0XHRcdFx0c2VsZWN0b3IoIGpRdWVyeSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciwgdGhpcyApO1xuXHR9O1xuXG4vLyBHaXZlIHRoZSBpbml0IGZ1bmN0aW9uIHRoZSBqUXVlcnkgcHJvdG90eXBlIGZvciBsYXRlciBpbnN0YW50aWF0aW9uXG5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjtcblxuLy8gSW5pdGlhbGl6ZSBjZW50cmFsIHJlZmVyZW5jZVxucm9vdGpRdWVyeSA9IGpRdWVyeSggZG9jdW1lbnQgKTtcblxuXG52YXIgcnBhcmVudHNwcmV2ID0gL14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sXG5cblx0Ly8gTWV0aG9kcyBndWFyYW50ZWVkIHRvIHByb2R1Y2UgYSB1bmlxdWUgc2V0IHdoZW4gc3RhcnRpbmcgZnJvbSBhIHVuaXF1ZSBzZXRcblx0Z3VhcmFudGVlZFVuaXF1ZSA9IHtcblx0XHRjaGlsZHJlbjogdHJ1ZSxcblx0XHRjb250ZW50czogdHJ1ZSxcblx0XHRuZXh0OiB0cnVlLFxuXHRcdHByZXY6IHRydWVcblx0fTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRoYXM6IGZ1bmN0aW9uKCB0YXJnZXQgKSB7XG5cdFx0dmFyIHRhcmdldHMgPSBqUXVlcnkoIHRhcmdldCwgdGhpcyApLFxuXHRcdFx0bCA9IHRhcmdldHMubGVuZ3RoO1xuXG5cdFx0cmV0dXJuIHRoaXMuZmlsdGVyKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpID0gMDtcblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHRoaXMsIHRhcmdldHNbIGkgXSApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGNsb3Nlc3Q6IGZ1bmN0aW9uKCBzZWxlY3RvcnMsIGNvbnRleHQgKSB7XG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0bWF0Y2hlZCA9IFtdLFxuXHRcdFx0dGFyZ2V0cyA9IHR5cGVvZiBzZWxlY3RvcnMgIT09IFwic3RyaW5nXCIgJiYgalF1ZXJ5KCBzZWxlY3RvcnMgKTtcblxuXHRcdC8vIFBvc2l0aW9uYWwgc2VsZWN0b3JzIG5ldmVyIG1hdGNoLCBzaW5jZSB0aGVyZSdzIG5vIF9zZWxlY3Rpb25fIGNvbnRleHRcblx0XHRpZiAoICFybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9ycyApICkge1xuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRmb3IgKCBjdXIgPSB0aGlzWyBpIF07IGN1ciAmJiBjdXIgIT09IGNvbnRleHQ7IGN1ciA9IGN1ci5wYXJlbnROb2RlICkge1xuXG5cdFx0XHRcdFx0Ly8gQWx3YXlzIHNraXAgZG9jdW1lbnQgZnJhZ21lbnRzXG5cdFx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPCAxMSAmJiAoIHRhcmdldHMgP1xuXHRcdFx0XHRcdFx0dGFyZ2V0cy5pbmRleCggY3VyICkgPiAtMSA6XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IHBhc3Mgbm9uLWVsZW1lbnRzIHRvIFNpenpsZVxuXHRcdFx0XHRcdFx0Y3VyLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kLm1hdGNoZXNTZWxlY3RvciggY3VyLCBzZWxlY3RvcnMgKSApICkge1xuXG5cdFx0XHRcdFx0XHRtYXRjaGVkLnB1c2goIGN1ciApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBtYXRjaGVkLmxlbmd0aCA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApIDogbWF0Y2hlZCApO1xuXHR9LFxuXG5cdC8vIERldGVybWluZSB0aGUgcG9zaXRpb24gb2YgYW4gZWxlbWVudCB3aXRoaW4gdGhlIHNldFxuXHRpbmRleDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHQvLyBObyBhcmd1bWVudCwgcmV0dXJuIGluZGV4IGluIHBhcmVudFxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gKCB0aGlzWyAwIF0gJiYgdGhpc1sgMCBdLnBhcmVudE5vZGUgKSA/IHRoaXMuZmlyc3QoKS5wcmV2QWxsKCkubGVuZ3RoIDogLTE7XG5cdFx0fVxuXG5cdFx0Ly8gSW5kZXggaW4gc2VsZWN0b3Jcblx0XHRpZiAoIHR5cGVvZiBlbGVtID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggalF1ZXJ5KCBlbGVtICksIHRoaXNbIDAgXSApO1xuXHRcdH1cblxuXHRcdC8vIExvY2F0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGRlc2lyZWQgZWxlbWVudFxuXHRcdHJldHVybiBpbmRleE9mLmNhbGwoIHRoaXMsXG5cblx0XHRcdC8vIElmIGl0IHJlY2VpdmVzIGEgalF1ZXJ5IG9iamVjdCwgdGhlIGZpcnN0IGVsZW1lbnQgaXMgdXNlZFxuXHRcdFx0ZWxlbS5qcXVlcnkgPyBlbGVtWyAwIF0gOiBlbGVtXG5cdFx0KTtcblx0fSxcblxuXHRhZGQ6IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soXG5cdFx0XHRqUXVlcnkudW5pcXVlU29ydChcblx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLmdldCgpLCBqUXVlcnkoIHNlbGVjdG9yLCBjb250ZXh0ICkgKVxuXHRcdFx0KVxuXHRcdCk7XG5cdH0sXG5cblx0YWRkQmFjazogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLmFkZCggc2VsZWN0b3IgPT0gbnVsbCA/XG5cdFx0XHR0aGlzLnByZXZPYmplY3QgOiB0aGlzLnByZXZPYmplY3QuZmlsdGVyKCBzZWxlY3RvciApXG5cdFx0KTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBzaWJsaW5nKCBjdXIsIGRpciApIHtcblx0d2hpbGUgKCAoIGN1ciA9IGN1clsgZGlyIF0gKSAmJiBjdXIubm9kZVR5cGUgIT09IDEgKSB7fVxuXHRyZXR1cm4gY3VyO1xufVxuXG5qUXVlcnkuZWFjaCgge1xuXHRwYXJlbnQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGU7XG5cdFx0cmV0dXJuIHBhcmVudCAmJiBwYXJlbnQubm9kZVR5cGUgIT09IDExID8gcGFyZW50IDogbnVsbDtcblx0fSxcblx0cGFyZW50czogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIgKTtcblx0fSxcblx0cGFyZW50c1VudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIsIHVudGlsICk7XG5cdH0sXG5cdG5leHQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5nKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmcoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dEFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiICk7XG5cdH0sXG5cdHByZXZBbGw6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBkaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dFVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRwcmV2VW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInByZXZpb3VzU2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRzaWJsaW5nczogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmdzKCAoIGVsZW0ucGFyZW50Tm9kZSB8fCB7fSApLmZpcnN0Q2hpbGQsIGVsZW0gKTtcblx0fSxcblx0Y2hpbGRyZW46IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5ncyggZWxlbS5maXJzdENoaWxkICk7XG5cdH0sXG5cdGNvbnRlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAgICAgaWYgKCBub2RlTmFtZSggZWxlbSwgXCJpZnJhbWVcIiApICkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0uY29udGVudERvY3VtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHksIGlPUyA3IG9ubHksIEFuZHJvaWQgQnJvd3NlciA8PTQuMyBvbmx5XG4gICAgICAgIC8vIFRyZWF0IHRoZSB0ZW1wbGF0ZSBlbGVtZW50IGFzIGEgcmVndWxhciBvbmUgaW4gYnJvd3NlcnMgdGhhdFxuICAgICAgICAvLyBkb24ndCBzdXBwb3J0IGl0LlxuICAgICAgICBpZiAoIG5vZGVOYW1lKCBlbGVtLCBcInRlbXBsYXRlXCIgKSApIHtcbiAgICAgICAgICAgIGVsZW0gPSBlbGVtLmNvbnRlbnQgfHwgZWxlbTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBlbGVtLmNoaWxkTm9kZXMgKTtcblx0fVxufSwgZnVuY3Rpb24oIG5hbWUsIGZuICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCB1bnRpbCwgc2VsZWN0b3IgKSB7XG5cdFx0dmFyIG1hdGNoZWQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiwgdW50aWwgKTtcblxuXHRcdGlmICggbmFtZS5zbGljZSggLTUgKSAhPT0gXCJVbnRpbFwiICkge1xuXHRcdFx0c2VsZWN0b3IgPSB1bnRpbDtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG1hdGNoZWQgPSBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgbWF0Y2hlZCApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sZW5ndGggPiAxICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgZHVwbGljYXRlc1xuXHRcdFx0aWYgKCAhZ3VhcmFudGVlZFVuaXF1ZVsgbmFtZSBdICkge1xuXHRcdFx0XHRqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXZlcnNlIG9yZGVyIGZvciBwYXJlbnRzKiBhbmQgcHJldi1kZXJpdmF0aXZlc1xuXHRcdFx0aWYgKCBycGFyZW50c3ByZXYudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRtYXRjaGVkLnJldmVyc2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQgKTtcblx0fTtcbn0gKTtcbnZhciBybm90aHRtbHdoaXRlID0gKCAvW15cXHgyMFxcdFxcclxcblxcZl0rL2cgKTtcblxuXG5cbi8vIENvbnZlcnQgU3RyaW5nLWZvcm1hdHRlZCBvcHRpb25zIGludG8gT2JqZWN0LWZvcm1hdHRlZCBvbmVzXG5mdW5jdGlvbiBjcmVhdGVPcHRpb25zKCBvcHRpb25zICkge1xuXHR2YXIgb2JqZWN0ID0ge307XG5cdGpRdWVyeS5lYWNoKCBvcHRpb25zLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10sIGZ1bmN0aW9uKCBfLCBmbGFnICkge1xuXHRcdG9iamVjdFsgZmxhZyBdID0gdHJ1ZTtcblx0fSApO1xuXHRyZXR1cm4gb2JqZWN0O1xufVxuXG4vKlxuICogQ3JlYXRlIGEgY2FsbGJhY2sgbGlzdCB1c2luZyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gKlxuICpcdG9wdGlvbnM6IGFuIG9wdGlvbmFsIGxpc3Qgb2Ygc3BhY2Utc2VwYXJhdGVkIG9wdGlvbnMgdGhhdCB3aWxsIGNoYW5nZSBob3dcbiAqXHRcdFx0dGhlIGNhbGxiYWNrIGxpc3QgYmVoYXZlcyBvciBhIG1vcmUgdHJhZGl0aW9uYWwgb3B0aW9uIG9iamVjdFxuICpcbiAqIEJ5IGRlZmF1bHQgYSBjYWxsYmFjayBsaXN0IHdpbGwgYWN0IGxpa2UgYW4gZXZlbnQgY2FsbGJhY2sgbGlzdCBhbmQgY2FuIGJlXG4gKiBcImZpcmVkXCIgbXVsdGlwbGUgdGltZXMuXG4gKlxuICogUG9zc2libGUgb3B0aW9uczpcbiAqXG4gKlx0b25jZTpcdFx0XHR3aWxsIGVuc3VyZSB0aGUgY2FsbGJhY2sgbGlzdCBjYW4gb25seSBiZSBmaXJlZCBvbmNlIChsaWtlIGEgRGVmZXJyZWQpXG4gKlxuICpcdG1lbW9yeTpcdFx0XHR3aWxsIGtlZXAgdHJhY2sgb2YgcHJldmlvdXMgdmFsdWVzIGFuZCB3aWxsIGNhbGwgYW55IGNhbGxiYWNrIGFkZGVkXG4gKlx0XHRcdFx0XHRhZnRlciB0aGUgbGlzdCBoYXMgYmVlbiBmaXJlZCByaWdodCBhd2F5IHdpdGggdGhlIGxhdGVzdCBcIm1lbW9yaXplZFwiXG4gKlx0XHRcdFx0XHR2YWx1ZXMgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0dW5pcXVlOlx0XHRcdHdpbGwgZW5zdXJlIGEgY2FsbGJhY2sgY2FuIG9ubHkgYmUgYWRkZWQgb25jZSAobm8gZHVwbGljYXRlIGluIHRoZSBsaXN0KVxuICpcbiAqXHRzdG9wT25GYWxzZTpcdGludGVycnVwdCBjYWxsaW5ncyB3aGVuIGEgY2FsbGJhY2sgcmV0dXJucyBmYWxzZVxuICpcbiAqL1xualF1ZXJ5LkNhbGxiYWNrcyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdC8vIENvbnZlcnQgb3B0aW9ucyBmcm9tIFN0cmluZy1mb3JtYXR0ZWQgdG8gT2JqZWN0LWZvcm1hdHRlZCBpZiBuZWVkZWRcblx0Ly8gKHdlIGNoZWNrIGluIGNhY2hlIGZpcnN0KVxuXHRvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIgP1xuXHRcdGNyZWF0ZU9wdGlvbnMoIG9wdGlvbnMgKSA6XG5cdFx0alF1ZXJ5LmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgLy8gRmxhZyB0byBrbm93IGlmIGxpc3QgaXMgY3VycmVudGx5IGZpcmluZ1xuXHRcdGZpcmluZyxcblxuXHRcdC8vIExhc3QgZmlyZSB2YWx1ZSBmb3Igbm9uLWZvcmdldHRhYmxlIGxpc3RzXG5cdFx0bWVtb3J5LFxuXG5cdFx0Ly8gRmxhZyB0byBrbm93IGlmIGxpc3Qgd2FzIGFscmVhZHkgZmlyZWRcblx0XHRmaXJlZCxcblxuXHRcdC8vIEZsYWcgdG8gcHJldmVudCBmaXJpbmdcblx0XHRsb2NrZWQsXG5cblx0XHQvLyBBY3R1YWwgY2FsbGJhY2sgbGlzdFxuXHRcdGxpc3QgPSBbXSxcblxuXHRcdC8vIFF1ZXVlIG9mIGV4ZWN1dGlvbiBkYXRhIGZvciByZXBlYXRhYmxlIGxpc3RzXG5cdFx0cXVldWUgPSBbXSxcblxuXHRcdC8vIEluZGV4IG9mIGN1cnJlbnRseSBmaXJpbmcgY2FsbGJhY2sgKG1vZGlmaWVkIGJ5IGFkZC9yZW1vdmUgYXMgbmVlZGVkKVxuXHRcdGZpcmluZ0luZGV4ID0gLTEsXG5cblx0XHQvLyBGaXJlIGNhbGxiYWNrc1xuXHRcdGZpcmUgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRW5mb3JjZSBzaW5nbGUtZmlyaW5nXG5cdFx0XHRsb2NrZWQgPSBsb2NrZWQgfHwgb3B0aW9ucy5vbmNlO1xuXG5cdFx0XHQvLyBFeGVjdXRlIGNhbGxiYWNrcyBmb3IgYWxsIHBlbmRpbmcgZXhlY3V0aW9ucyxcblx0XHRcdC8vIHJlc3BlY3RpbmcgZmlyaW5nSW5kZXggb3ZlcnJpZGVzIGFuZCBydW50aW1lIGNoYW5nZXNcblx0XHRcdGZpcmVkID0gZmlyaW5nID0gdHJ1ZTtcblx0XHRcdGZvciAoIDsgcXVldWUubGVuZ3RoOyBmaXJpbmdJbmRleCA9IC0xICkge1xuXHRcdFx0XHRtZW1vcnkgPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHR3aGlsZSAoICsrZmlyaW5nSW5kZXggPCBsaXN0Lmxlbmd0aCApIHtcblxuXHRcdFx0XHRcdC8vIFJ1biBjYWxsYmFjayBhbmQgY2hlY2sgZm9yIGVhcmx5IHRlcm1pbmF0aW9uXG5cdFx0XHRcdFx0aWYgKCBsaXN0WyBmaXJpbmdJbmRleCBdLmFwcGx5KCBtZW1vcnlbIDAgXSwgbWVtb3J5WyAxIF0gKSA9PT0gZmFsc2UgJiZcblx0XHRcdFx0XHRcdG9wdGlvbnMuc3RvcE9uRmFsc2UgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEp1bXAgdG8gZW5kIGFuZCBmb3JnZXQgdGhlIGRhdGEgc28gLmFkZCBkb2Vzbid0IHJlLWZpcmVcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRcdFx0XHRtZW1vcnkgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gRm9yZ2V0IHRoZSBkYXRhIGlmIHdlJ3JlIGRvbmUgd2l0aCBpdFxuXHRcdFx0aWYgKCAhb3B0aW9ucy5tZW1vcnkgKSB7XG5cdFx0XHRcdG1lbW9yeSA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRmaXJpbmcgPSBmYWxzZTtcblxuXHRcdFx0Ly8gQ2xlYW4gdXAgaWYgd2UncmUgZG9uZSBmaXJpbmcgZm9yIGdvb2Rcblx0XHRcdGlmICggbG9ja2VkICkge1xuXG5cdFx0XHRcdC8vIEtlZXAgYW4gZW1wdHkgbGlzdCBpZiB3ZSBoYXZlIGRhdGEgZm9yIGZ1dHVyZSBhZGQgY2FsbHNcblx0XHRcdFx0aWYgKCBtZW1vcnkgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IFtdO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSwgdGhpcyBvYmplY3QgaXMgc3BlbnRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsaXN0ID0gXCJcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvLyBBY3R1YWwgQ2FsbGJhY2tzIG9iamVjdFxuXHRcdHNlbGYgPSB7XG5cblx0XHRcdC8vIEFkZCBhIGNhbGxiYWNrIG9yIGEgY29sbGVjdGlvbiBvZiBjYWxsYmFja3MgdG8gdGhlIGxpc3Rcblx0XHRcdGFkZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblxuXHRcdFx0XHRcdC8vIElmIHdlIGhhdmUgbWVtb3J5IGZyb20gYSBwYXN0IHJ1biwgd2Ugc2hvdWxkIGZpcmUgYWZ0ZXIgYWRkaW5nXG5cdFx0XHRcdFx0aWYgKCBtZW1vcnkgJiYgIWZpcmluZyApIHtcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGggLSAxO1xuXHRcdFx0XHRcdFx0cXVldWUucHVzaCggbWVtb3J5ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0KCBmdW5jdGlvbiBhZGQoIGFyZ3MgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZWFjaCggYXJncywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYXJnICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhb3B0aW9ucy51bmlxdWUgfHwgIXNlbGYuaGFzKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGxpc3QucHVzaCggYXJnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBhcmcgJiYgYXJnLmxlbmd0aCAmJiBqUXVlcnkudHlwZSggYXJnICkgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBJbnNwZWN0IHJlY3Vyc2l2ZWx5XG5cdFx0XHRcdFx0XHRcdFx0YWRkKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gKSggYXJndW1lbnRzICk7XG5cblx0XHRcdFx0XHRpZiAoIG1lbW9yeSAmJiAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIFJlbW92ZSBhIGNhbGxiYWNrIGZyb20gdGhlIGxpc3Rcblx0XHRcdHJlbW92ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBfLCBhcmcgKSB7XG5cdFx0XHRcdFx0dmFyIGluZGV4O1xuXHRcdFx0XHRcdHdoaWxlICggKCBpbmRleCA9IGpRdWVyeS5pbkFycmF5KCBhcmcsIGxpc3QsIGluZGV4ICkgKSA+IC0xICkge1xuXHRcdFx0XHRcdFx0bGlzdC5zcGxpY2UoIGluZGV4LCAxICk7XG5cblx0XHRcdFx0XHRcdC8vIEhhbmRsZSBmaXJpbmcgaW5kZXhlc1xuXHRcdFx0XHRcdFx0aWYgKCBpbmRleCA8PSBmaXJpbmdJbmRleCApIHtcblx0XHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXgtLTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDaGVjayBpZiBhIGdpdmVuIGNhbGxiYWNrIGlzIGluIHRoZSBsaXN0LlxuXHRcdFx0Ly8gSWYgbm8gYXJndW1lbnQgaXMgZ2l2ZW4sIHJldHVybiB3aGV0aGVyIG9yIG5vdCBsaXN0IGhhcyBjYWxsYmFja3MgYXR0YWNoZWQuXG5cdFx0XHRoYXM6IGZ1bmN0aW9uKCBmbiApIHtcblx0XHRcdFx0cmV0dXJuIGZuID9cblx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggZm4sIGxpc3QgKSA+IC0xIDpcblx0XHRcdFx0XHRsaXN0Lmxlbmd0aCA+IDA7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBSZW1vdmUgYWxsIGNhbGxiYWNrcyBmcm9tIHRoZSBsaXN0XG5cdFx0XHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblx0XHRcdFx0XHRsaXN0ID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBEaXNhYmxlIC5maXJlIGFuZCAuYWRkXG5cdFx0XHQvLyBBYm9ydCBhbnkgY3VycmVudC9wZW5kaW5nIGV4ZWN1dGlvbnNcblx0XHRcdC8vIENsZWFyIGFsbCBjYWxsYmFja3MgYW5kIHZhbHVlc1xuXHRcdFx0ZGlzYWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGxvY2tlZCA9IHF1ZXVlID0gW107XG5cdFx0XHRcdGxpc3QgPSBtZW1vcnkgPSBcIlwiO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHRkaXNhYmxlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhbGlzdDtcblx0XHRcdH0sXG5cblx0XHRcdC8vIERpc2FibGUgLmZpcmVcblx0XHRcdC8vIEFsc28gZGlzYWJsZSAuYWRkIHVubGVzcyB3ZSBoYXZlIG1lbW9yeSAoc2luY2UgaXQgd291bGQgaGF2ZSBubyBlZmZlY3QpXG5cdFx0XHQvLyBBYm9ydCBhbnkgcGVuZGluZyBleGVjdXRpb25zXG5cdFx0XHRsb2NrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0bG9ja2VkID0gcXVldWUgPSBbXTtcblx0XHRcdFx0aWYgKCAhbWVtb3J5ICYmICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IG1lbW9yeSA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0bG9ja2VkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICEhbG9ja2VkO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhbGwgY2FsbGJhY2tzIHdpdGggdGhlIGdpdmVuIGNvbnRleHQgYW5kIGFyZ3VtZW50c1xuXHRcdFx0ZmlyZVdpdGg6IGZ1bmN0aW9uKCBjb250ZXh0LCBhcmdzICkge1xuXHRcdFx0XHRpZiAoICFsb2NrZWQgKSB7XG5cdFx0XHRcdFx0YXJncyA9IGFyZ3MgfHwgW107XG5cdFx0XHRcdFx0YXJncyA9IFsgY29udGV4dCwgYXJncy5zbGljZSA/IGFyZ3Muc2xpY2UoKSA6IGFyZ3MgXTtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBhcmdzICk7XG5cdFx0XHRcdFx0aWYgKCAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIENhbGwgYWxsIHRoZSBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gYXJndW1lbnRzXG5cdFx0XHRmaXJlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0c2VsZi5maXJlV2l0aCggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gVG8ga25vdyBpZiB0aGUgY2FsbGJhY2tzIGhhdmUgYWxyZWFkeSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlXG5cdFx0XHRmaXJlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhIWZpcmVkO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0cmV0dXJuIHNlbGY7XG59O1xuXG5cbmZ1bmN0aW9uIElkZW50aXR5KCB2ICkge1xuXHRyZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIFRocm93ZXIoIGV4ICkge1xuXHR0aHJvdyBleDtcbn1cblxuZnVuY3Rpb24gYWRvcHRWYWx1ZSggdmFsdWUsIHJlc29sdmUsIHJlamVjdCwgbm9WYWx1ZSApIHtcblx0dmFyIG1ldGhvZDtcblxuXHR0cnkge1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIHByb21pc2UgYXNwZWN0IGZpcnN0IHRvIHByaXZpbGVnZSBzeW5jaHJvbm91cyBiZWhhdmlvclxuXHRcdGlmICggdmFsdWUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oICggbWV0aG9kID0gdmFsdWUucHJvbWlzZSApICkgKSB7XG5cdFx0XHRtZXRob2QuY2FsbCggdmFsdWUgKS5kb25lKCByZXNvbHZlICkuZmFpbCggcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciB0aGVuYWJsZXNcblx0XHR9IGVsc2UgaWYgKCB2YWx1ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggKCBtZXRob2QgPSB2YWx1ZS50aGVuICkgKSApIHtcblx0XHRcdG1ldGhvZC5jYWxsKCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciBub24tdGhlbmFibGVzXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQ29udHJvbCBgcmVzb2x2ZWAgYXJndW1lbnRzIGJ5IGxldHRpbmcgQXJyYXkjc2xpY2UgY2FzdCBib29sZWFuIGBub1ZhbHVlYCB0byBpbnRlZ2VyOlxuXHRcdFx0Ly8gKiBmYWxzZTogWyB2YWx1ZSBdLnNsaWNlKCAwICkgPT4gcmVzb2x2ZSggdmFsdWUgKVxuXHRcdFx0Ly8gKiB0cnVlOiBbIHZhbHVlIF0uc2xpY2UoIDEgKSA9PiByZXNvbHZlKClcblx0XHRcdHJlc29sdmUuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdLnNsaWNlKCBub1ZhbHVlICkgKTtcblx0XHR9XG5cblx0Ly8gRm9yIFByb21pc2VzL0ErLCBjb252ZXJ0IGV4Y2VwdGlvbnMgaW50byByZWplY3Rpb25zXG5cdC8vIFNpbmNlIGpRdWVyeS53aGVuIGRvZXNuJ3QgdW53cmFwIHRoZW5hYmxlcywgd2UgY2FuIHNraXAgdGhlIGV4dHJhIGNoZWNrcyBhcHBlYXJpbmcgaW5cblx0Ly8gRGVmZXJyZWQjdGhlbiB0byBjb25kaXRpb25hbGx5IHN1cHByZXNzIHJlamVjdGlvbi5cblx0fSBjYXRjaCAoIHZhbHVlICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgb25seVxuXHRcdC8vIFN0cmljdCBtb2RlIGZ1bmN0aW9ucyBpbnZva2VkIHdpdGhvdXQgLmNhbGwvLmFwcGx5IGdldCBnbG9iYWwtb2JqZWN0IGNvbnRleHRcblx0XHRyZWplY3QuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdICk7XG5cdH1cbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdERlZmVycmVkOiBmdW5jdGlvbiggZnVuYyApIHtcblx0XHR2YXIgdHVwbGVzID0gW1xuXG5cdFx0XHRcdC8vIGFjdGlvbiwgYWRkIGxpc3RlbmVyLCBjYWxsYmFja3MsXG5cdFx0XHRcdC8vIC4uLiAudGhlbiBoYW5kbGVycywgYXJndW1lbnQgaW5kZXgsIFtmaW5hbCBzdGF0ZV1cblx0XHRcdFx0WyBcIm5vdGlmeVwiLCBcInByb2dyZXNzXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwibWVtb3J5XCIgKSxcblx0XHRcdFx0XHRqUXVlcnkuQ2FsbGJhY2tzKCBcIm1lbW9yeVwiICksIDIgXSxcblx0XHRcdFx0WyBcInJlc29sdmVcIiwgXCJkb25lXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXHRcdFx0XHRcdGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLCAwLCBcInJlc29sdmVkXCIgXSxcblx0XHRcdFx0WyBcInJlamVjdFwiLCBcImZhaWxcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cdFx0XHRcdFx0alF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksIDEsIFwicmVqZWN0ZWRcIiBdXG5cdFx0XHRdLFxuXHRcdFx0c3RhdGUgPSBcInBlbmRpbmdcIixcblx0XHRcdHByb21pc2UgPSB7XG5cdFx0XHRcdHN0YXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gc3RhdGU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGFsd2F5czogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQuZG9uZSggYXJndW1lbnRzICkuZmFpbCggYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFwiY2F0Y2hcIjogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlLnRoZW4oIG51bGwsIGZuICk7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gS2VlcCBwaXBlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRwaXBlOiBmdW5jdGlvbiggLyogZm5Eb25lLCBmbkZhaWwsIGZuUHJvZ3Jlc3MgKi8gKSB7XG5cdFx0XHRcdFx0dmFyIGZucyA9IGFyZ3VtZW50cztcblxuXHRcdFx0XHRcdHJldHVybiBqUXVlcnkuRGVmZXJyZWQoIGZ1bmN0aW9uKCBuZXdEZWZlciApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCB0dXBsZXMsIGZ1bmN0aW9uKCBpLCB0dXBsZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBNYXAgdHVwbGVzIChwcm9ncmVzcywgZG9uZSwgZmFpbCkgdG8gYXJndW1lbnRzIChkb25lLCBmYWlsLCBwcm9ncmVzcylcblx0XHRcdFx0XHRcdFx0dmFyIGZuID0galF1ZXJ5LmlzRnVuY3Rpb24oIGZuc1sgdHVwbGVbIDQgXSBdICkgJiYgZm5zWyB0dXBsZVsgNCBdIF07XG5cblx0XHRcdFx0XHRcdFx0Ly8gZGVmZXJyZWQucHJvZ3Jlc3MoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIubm90aWZ5IH0pXG5cdFx0XHRcdFx0XHRcdC8vIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIucmVzb2x2ZSB9KVxuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZC5mYWlsKGZ1bmN0aW9uKCkgeyBiaW5kIHRvIG5ld0RlZmVyIG9yIG5ld0RlZmVyLnJlamVjdCB9KVxuXHRcdFx0XHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDEgXSBdKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmV0dXJuZWQgPSBmbiAmJiBmbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCAmJiBqUXVlcnkuaXNGdW5jdGlvbiggcmV0dXJuZWQucHJvbWlzZSApICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQucHJvbWlzZSgpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5wcm9ncmVzcyggbmV3RGVmZXIubm90aWZ5IClcblx0XHRcdFx0XHRcdFx0XHRcdFx0LmRvbmUoIG5ld0RlZmVyLnJlc29sdmUgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZmFpbCggbmV3RGVmZXIucmVqZWN0ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyWyB0dXBsZVsgMCBdICsgXCJXaXRoXCIgXShcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm4gPyBbIHJldHVybmVkIF0gOiBhcmd1bWVudHNcblx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRmbnMgPSBudWxsO1xuXHRcdFx0XHRcdH0gKS5wcm9taXNlKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRoZW46IGZ1bmN0aW9uKCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb25Qcm9ncmVzcyApIHtcblx0XHRcdFx0XHR2YXIgbWF4RGVwdGggPSAwO1xuXHRcdFx0XHRcdGZ1bmN0aW9uIHJlc29sdmUoIGRlcHRoLCBkZWZlcnJlZCwgaGFuZGxlciwgc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHRoYXQgPSB0aGlzLFxuXHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBhcmd1bWVudHMsXG5cdFx0XHRcdFx0XHRcdFx0bWlnaHRUaHJvdyA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIHJldHVybmVkLCB0aGVuO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4zLjMuM1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBkb3VibGUtcmVzb2x1dGlvbiBhdHRlbXB0c1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCA8IG1heERlcHRoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkID0gaGFuZGxlci5hcHBseSggdGhhdCwgYXJncyApO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4xXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC00OFxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCA9PT0gZGVmZXJyZWQucHJvbWlzZSgpICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCBcIlRoZW5hYmxlIHNlbGYtcmVzb2x1dGlvblwiICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb25zIDIuMy4zLjEsIDMuNVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTRcblx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTc1XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBSZXRyaWV2ZSBgdGhlbmAgb25seSBvbmNlXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGVuID0gcmV0dXJuZWQgJiZcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy40XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTY0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgY2hlY2sgb2JqZWN0cyBhbmQgZnVuY3Rpb25zIGZvciB0aGVuYWJpbGl0eVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHR5cGVvZiByZXR1cm5lZCA9PT0gXCJvYmplY3RcIiB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHR5cGVvZiByZXR1cm5lZCA9PT0gXCJmdW5jdGlvblwiICkgJiZcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQudGhlbjtcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGEgcmV0dXJuZWQgdGhlbmFibGVcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHRoZW4gKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTcGVjaWFsIHByb2Nlc3NvcnMgKG5vdGlmeSkganVzdCB3YWl0IGZvciByZXNvbHV0aW9uXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGVuLmNhbGwoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgVGhyb3dlciwgc3BlY2lhbCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBOb3JtYWwgcHJvY2Vzc29ycyAocmVzb2x2ZSkgYWxzbyBob29rIGludG8gcHJvZ3Jlc3Ncblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBkaXNyZWdhcmQgb2xkZXIgcmVzb2x1dGlvbiB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtYXhEZXB0aCsrO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhlbi5jYWxsKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIElkZW50aXR5LCBzcGVjaWFsICksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIFRocm93ZXIsIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGFsbCBvdGhlciByZXR1cm5lZCB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gT25seSBzdWJzdGl0dXRlIGhhbmRsZXJzIHBhc3Mgb24gY29udGV4dFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBoYW5kbGVyICE9PSBJZGVudGl0eSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGF0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBbIHJldHVybmVkIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBQcm9jZXNzIHRoZSB2YWx1ZShzKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZhdWx0IHByb2Nlc3MgaXMgcmVzb2x2ZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHNwZWNpYWwgfHwgZGVmZXJyZWQucmVzb2x2ZVdpdGggKSggdGhhdCwgYXJncyApO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IG5vcm1hbCBwcm9jZXNzb3JzIChyZXNvbHZlKSBjYXRjaCBhbmQgcmVqZWN0IGV4Y2VwdGlvbnNcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzID0gc3BlY2lhbCA/XG5cdFx0XHRcdFx0XHRcdFx0XHRtaWdodFRocm93IDpcblx0XHRcdFx0XHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1pZ2h0VGhyb3coKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5leGNlcHRpb25Ib29rICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LkRlZmVycmVkLmV4Y2VwdGlvbkhvb2soIGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb2Nlc3Muc3RhY2tUcmFjZSApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy40LjFcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC02MVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBwb3N0LXJlc29sdXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggZGVwdGggKyAxID49IG1heERlcHRoICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IHN1YnN0aXR1dGUgaGFuZGxlcnMgcGFzcyBvbiBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggaGFuZGxlciAhPT0gVGhyb3dlciApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhhdCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YXJncyA9IFsgZSBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy4xXG5cdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTU3XG5cdFx0XHRcdFx0XHRcdC8vIFJlLXJlc29sdmUgcHJvbWlzZXMgaW1tZWRpYXRlbHkgdG8gZG9kZ2UgZmFsc2UgcmVqZWN0aW9uIGZyb21cblx0XHRcdFx0XHRcdFx0Ly8gc3Vic2VxdWVudCBlcnJvcnNcblx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCApIHtcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDYWxsIGFuIG9wdGlvbmFsIGhvb2sgdG8gcmVjb3JkIHRoZSBzdGFjaywgaW4gY2FzZSBvZiBleGNlcHRpb25cblx0XHRcdFx0XHRcdFx0XHQvLyBzaW5jZSBpdCdzIG90aGVyd2lzZSBsb3N0IHdoZW4gZXhlY3V0aW9uIGdvZXMgYXN5bmNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5nZXRTdGFja0hvb2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzLnN0YWNrVHJhY2UgPSBqUXVlcnkuRGVmZXJyZWQuZ2V0U3RhY2tIb29rKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBwcm9jZXNzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZCggZnVuY3Rpb24oIG5ld0RlZmVyICkge1xuXG5cdFx0XHRcdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDAgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvblByb2dyZXNzICkgP1xuXHRcdFx0XHRcdFx0XHRcdFx0b25Qcm9ncmVzcyA6XG5cdFx0XHRcdFx0XHRcdFx0XHRJZGVudGl0eSxcblx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlci5ub3RpZnlXaXRoXG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDEgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvbkZ1bGZpbGxlZCApID9cblx0XHRcdFx0XHRcdFx0XHRcdG9uRnVsZmlsbGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdElkZW50aXR5XG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIHJlamVjdGVkX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMiBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uUmVqZWN0ZWQgKSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRvblJlamVjdGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdFRocm93ZXJcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9ICkucHJvbWlzZSgpO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIEdldCBhIHByb21pc2UgZm9yIHRoaXMgZGVmZXJyZWRcblx0XHRcdFx0Ly8gSWYgb2JqIGlzIHByb3ZpZGVkLCB0aGUgcHJvbWlzZSBhc3BlY3QgaXMgYWRkZWQgdG8gdGhlIG9iamVjdFxuXHRcdFx0XHRwcm9taXNlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdFx0XHRcdHJldHVybiBvYmogIT0gbnVsbCA/IGpRdWVyeS5leHRlbmQoIG9iaiwgcHJvbWlzZSApIDogcHJvbWlzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlZmVycmVkID0ge307XG5cblx0XHQvLyBBZGQgbGlzdC1zcGVjaWZpYyBtZXRob2RzXG5cdFx0alF1ZXJ5LmVhY2goIHR1cGxlcywgZnVuY3Rpb24oIGksIHR1cGxlICkge1xuXHRcdFx0dmFyIGxpc3QgPSB0dXBsZVsgMiBdLFxuXHRcdFx0XHRzdGF0ZVN0cmluZyA9IHR1cGxlWyA1IF07XG5cblx0XHRcdC8vIHByb21pc2UucHJvZ3Jlc3MgPSBsaXN0LmFkZFxuXHRcdFx0Ly8gcHJvbWlzZS5kb25lID0gbGlzdC5hZGRcblx0XHRcdC8vIHByb21pc2UuZmFpbCA9IGxpc3QuYWRkXG5cdFx0XHRwcm9taXNlWyB0dXBsZVsgMSBdIF0gPSBsaXN0LmFkZDtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0YXRlXG5cdFx0XHRpZiAoIHN0YXRlU3RyaW5nICkge1xuXHRcdFx0XHRsaXN0LmFkZChcblx0XHRcdFx0XHRmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gc3RhdGUgPSBcInJlc29sdmVkXCIgKGkuZS4sIGZ1bGZpbGxlZClcblx0XHRcdFx0XHRcdC8vIHN0YXRlID0gXCJyZWplY3RlZFwiXG5cdFx0XHRcdFx0XHRzdGF0ZSA9IHN0YXRlU3RyaW5nO1xuXHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHQvLyByZWplY3RlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdHR1cGxlc1sgMyAtIGkgXVsgMiBdLmRpc2FibGUsXG5cblx0XHRcdFx0XHQvLyBwcm9ncmVzc19jYWxsYmFja3MubG9ja1xuXHRcdFx0XHRcdHR1cGxlc1sgMCBdWyAyIF0ubG9ja1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5maXJlXG5cdFx0XHQvLyBmdWxmaWxsZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0Ly8gcmVqZWN0ZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0bGlzdC5hZGQoIHR1cGxlWyAzIF0uZmlyZSApO1xuXG5cdFx0XHQvLyBkZWZlcnJlZC5ub3RpZnkgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQubm90aWZ5V2l0aCguLi4pIH1cblx0XHRcdC8vIGRlZmVycmVkLnJlc29sdmUgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVzb2x2ZVdpdGgoLi4uKSB9XG5cdFx0XHQvLyBkZWZlcnJlZC5yZWplY3QgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVqZWN0V2l0aCguLi4pIH1cblx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMCBdIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGVmZXJyZWRbIHR1cGxlWyAwIF0gKyBcIldpdGhcIiBdKCB0aGlzID09PSBkZWZlcnJlZCA/IHVuZGVmaW5lZCA6IHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH07XG5cblx0XHRcdC8vIGRlZmVycmVkLm5vdGlmeVdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHQvLyBkZWZlcnJlZC5yZXNvbHZlV2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdC8vIGRlZmVycmVkLnJlamVjdFdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0gPSBsaXN0LmZpcmVXaXRoO1xuXHRcdH0gKTtcblxuXHRcdC8vIE1ha2UgdGhlIGRlZmVycmVkIGEgcHJvbWlzZVxuXHRcdHByb21pc2UucHJvbWlzZSggZGVmZXJyZWQgKTtcblxuXHRcdC8vIENhbGwgZ2l2ZW4gZnVuYyBpZiBhbnlcblx0XHRpZiAoIGZ1bmMgKSB7XG5cdFx0XHRmdW5jLmNhbGwoIGRlZmVycmVkLCBkZWZlcnJlZCApO1xuXHRcdH1cblxuXHRcdC8vIEFsbCBkb25lIVxuXHRcdHJldHVybiBkZWZlcnJlZDtcblx0fSxcblxuXHQvLyBEZWZlcnJlZCBoZWxwZXJcblx0d2hlbjogZnVuY3Rpb24oIHNpbmdsZVZhbHVlICkge1xuXHRcdHZhclxuXG5cdFx0XHQvLyBjb3VudCBvZiB1bmNvbXBsZXRlZCBzdWJvcmRpbmF0ZXNcblx0XHRcdHJlbWFpbmluZyA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cblx0XHRcdC8vIGNvdW50IG9mIHVucHJvY2Vzc2VkIGFyZ3VtZW50c1xuXHRcdFx0aSA9IHJlbWFpbmluZyxcblxuXHRcdFx0Ly8gc3Vib3JkaW5hdGUgZnVsZmlsbG1lbnQgZGF0YVxuXHRcdFx0cmVzb2x2ZUNvbnRleHRzID0gQXJyYXkoIGkgKSxcblx0XHRcdHJlc29sdmVWYWx1ZXMgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSxcblxuXHRcdFx0Ly8gdGhlIG1hc3RlciBEZWZlcnJlZFxuXHRcdFx0bWFzdGVyID0galF1ZXJ5LkRlZmVycmVkKCksXG5cblx0XHRcdC8vIHN1Ym9yZGluYXRlIGNhbGxiYWNrIGZhY3Rvcnlcblx0XHRcdHVwZGF0ZUZ1bmMgPSBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXNvbHZlQ29udGV4dHNbIGkgXSA9IHRoaXM7XG5cdFx0XHRcdFx0cmVzb2x2ZVZhbHVlc1sgaSBdID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSA6IHZhbHVlO1xuXHRcdFx0XHRcdGlmICggISggLS1yZW1haW5pbmcgKSApIHtcblx0XHRcdFx0XHRcdG1hc3Rlci5yZXNvbHZlV2l0aCggcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fTtcblxuXHRcdC8vIFNpbmdsZS0gYW5kIGVtcHR5IGFyZ3VtZW50cyBhcmUgYWRvcHRlZCBsaWtlIFByb21pc2UucmVzb2x2ZVxuXHRcdGlmICggcmVtYWluaW5nIDw9IDEgKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCBzaW5nbGVWYWx1ZSwgbWFzdGVyLmRvbmUoIHVwZGF0ZUZ1bmMoIGkgKSApLnJlc29sdmUsIG1hc3Rlci5yZWplY3QsXG5cdFx0XHRcdCFyZW1haW5pbmcgKTtcblxuXHRcdFx0Ly8gVXNlIC50aGVuKCkgdG8gdW53cmFwIHNlY29uZGFyeSB0aGVuYWJsZXMgKGNmLiBnaC0zMDAwKVxuXHRcdFx0aWYgKCBtYXN0ZXIuc3RhdGUoKSA9PT0gXCJwZW5kaW5nXCIgfHxcblx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHJlc29sdmVWYWx1ZXNbIGkgXSAmJiByZXNvbHZlVmFsdWVzWyBpIF0udGhlbiApICkge1xuXG5cdFx0XHRcdHJldHVybiBtYXN0ZXIudGhlbigpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE11bHRpcGxlIGFyZ3VtZW50cyBhcmUgYWdncmVnYXRlZCBsaWtlIFByb21pc2UuYWxsIGFycmF5IGVsZW1lbnRzXG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCByZXNvbHZlVmFsdWVzWyBpIF0sIHVwZGF0ZUZ1bmMoIGkgKSwgbWFzdGVyLnJlamVjdCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBtYXN0ZXIucHJvbWlzZSgpO1xuXHR9XG59ICk7XG5cblxuLy8gVGhlc2UgdXN1YWxseSBpbmRpY2F0ZSBhIHByb2dyYW1tZXIgbWlzdGFrZSBkdXJpbmcgZGV2ZWxvcG1lbnQsXG4vLyB3YXJuIGFib3V0IHRoZW0gQVNBUCByYXRoZXIgdGhhbiBzd2FsbG93aW5nIHRoZW0gYnkgZGVmYXVsdC5cbnZhciByZXJyb3JOYW1lcyA9IC9eKEV2YWx8SW50ZXJuYWx8UmFuZ2V8UmVmZXJlbmNlfFN5bnRheHxUeXBlfFVSSSlFcnJvciQvO1xuXG5qUXVlcnkuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayA9IGZ1bmN0aW9uKCBlcnJvciwgc3RhY2sgKSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgOCAtIDkgb25seVxuXHQvLyBDb25zb2xlIGV4aXN0cyB3aGVuIGRldiB0b29scyBhcmUgb3Blbiwgd2hpY2ggY2FuIGhhcHBlbiBhdCBhbnkgdGltZVxuXHRpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLndhcm4gJiYgZXJyb3IgJiYgcmVycm9yTmFtZXMudGVzdCggZXJyb3IubmFtZSApICkge1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4oIFwialF1ZXJ5LkRlZmVycmVkIGV4Y2VwdGlvbjogXCIgKyBlcnJvci5tZXNzYWdlLCBlcnJvci5zdGFjaywgc3RhY2sgKTtcblx0fVxufTtcblxuXG5cblxualF1ZXJ5LnJlYWR5RXhjZXB0aW9uID0gZnVuY3Rpb24oIGVycm9yICkge1xuXHR3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXJyb3I7XG5cdH0gKTtcbn07XG5cblxuXG5cbi8vIFRoZSBkZWZlcnJlZCB1c2VkIG9uIERPTSByZWFkeVxudmFyIHJlYWR5TGlzdCA9IGpRdWVyeS5EZWZlcnJlZCgpO1xuXG5qUXVlcnkuZm4ucmVhZHkgPSBmdW5jdGlvbiggZm4gKSB7XG5cblx0cmVhZHlMaXN0XG5cdFx0LnRoZW4oIGZuIClcblxuXHRcdC8vIFdyYXAgalF1ZXJ5LnJlYWR5RXhjZXB0aW9uIGluIGEgZnVuY3Rpb24gc28gdGhhdCB0aGUgbG9va3VwXG5cdFx0Ly8gaGFwcGVucyBhdCB0aGUgdGltZSBvZiBlcnJvciBoYW5kbGluZyBpbnN0ZWFkIG9mIGNhbGxiYWNrXG5cdFx0Ly8gcmVnaXN0cmF0aW9uLlxuXHRcdC5jYXRjaCggZnVuY3Rpb24oIGVycm9yICkge1xuXHRcdFx0alF1ZXJ5LnJlYWR5RXhjZXB0aW9uKCBlcnJvciApO1xuXHRcdH0gKTtcblxuXHRyZXR1cm4gdGhpcztcbn07XG5cbmpRdWVyeS5leHRlbmQoIHtcblxuXHQvLyBJcyB0aGUgRE9NIHJlYWR5IHRvIGJlIHVzZWQ/IFNldCB0byB0cnVlIG9uY2UgaXQgb2NjdXJzLlxuXHRpc1JlYWR5OiBmYWxzZSxcblxuXHQvLyBBIGNvdW50ZXIgdG8gdHJhY2sgaG93IG1hbnkgaXRlbXMgdG8gd2FpdCBmb3IgYmVmb3JlXG5cdC8vIHRoZSByZWFkeSBldmVudCBmaXJlcy4gU2VlICM2NzgxXG5cdHJlYWR5V2FpdDogMSxcblxuXHQvLyBIYW5kbGUgd2hlbiB0aGUgRE9NIGlzIHJlYWR5XG5cdHJlYWR5OiBmdW5jdGlvbiggd2FpdCApIHtcblxuXHRcdC8vIEFib3J0IGlmIHRoZXJlIGFyZSBwZW5kaW5nIGhvbGRzIG9yIHdlJ3JlIGFscmVhZHkgcmVhZHlcblx0XHRpZiAoIHdhaXQgPT09IHRydWUgPyAtLWpRdWVyeS5yZWFkeVdhaXQgOiBqUXVlcnkuaXNSZWFkeSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBSZW1lbWJlciB0aGF0IHRoZSBET00gaXMgcmVhZHlcblx0XHRqUXVlcnkuaXNSZWFkeSA9IHRydWU7XG5cblx0XHQvLyBJZiBhIG5vcm1hbCBET00gUmVhZHkgZXZlbnQgZmlyZWQsIGRlY3JlbWVudCwgYW5kIHdhaXQgaWYgbmVlZCBiZVxuXHRcdGlmICggd2FpdCAhPT0gdHJ1ZSAmJiAtLWpRdWVyeS5yZWFkeVdhaXQgPiAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIElmIHRoZXJlIGFyZSBmdW5jdGlvbnMgYm91bmQsIHRvIGV4ZWN1dGVcblx0XHRyZWFkeUxpc3QucmVzb2x2ZVdpdGgoIGRvY3VtZW50LCBbIGpRdWVyeSBdICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LnJlYWR5LnRoZW4gPSByZWFkeUxpc3QudGhlbjtcblxuLy8gVGhlIHJlYWR5IGV2ZW50IGhhbmRsZXIgYW5kIHNlbGYgY2xlYW51cCBtZXRob2RcbmZ1bmN0aW9uIGNvbXBsZXRlZCgpIHtcblx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJsb2FkXCIsIGNvbXBsZXRlZCApO1xuXHRqUXVlcnkucmVhZHkoKTtcbn1cblxuLy8gQ2F0Y2ggY2FzZXMgd2hlcmUgJChkb2N1bWVudCkucmVhZHkoKSBpcyBjYWxsZWRcbi8vIGFmdGVyIHRoZSBicm93c2VyIGV2ZW50IGhhcyBhbHJlYWR5IG9jY3VycmVkLlxuLy8gU3VwcG9ydDogSUUgPD05IC0gMTAgb25seVxuLy8gT2xkZXIgSUUgc29tZXRpbWVzIHNpZ25hbHMgXCJpbnRlcmFjdGl2ZVwiIHRvbyBzb29uXG5pZiAoIGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIiB8fFxuXHQoIGRvY3VtZW50LnJlYWR5U3RhdGUgIT09IFwibG9hZGluZ1wiICYmICFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGwgKSApIHtcblxuXHQvLyBIYW5kbGUgaXQgYXN5bmNocm9ub3VzbHkgdG8gYWxsb3cgc2NyaXB0cyB0aGUgb3Bwb3J0dW5pdHkgdG8gZGVsYXkgcmVhZHlcblx0d2luZG93LnNldFRpbWVvdXQoIGpRdWVyeS5yZWFkeSApO1xuXG59IGVsc2Uge1xuXG5cdC8vIFVzZSB0aGUgaGFuZHkgZXZlbnQgY2FsbGJhY2tcblx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXG5cdC8vIEEgZmFsbGJhY2sgdG8gd2luZG93Lm9ubG9hZCwgdGhhdCB3aWxsIGFsd2F5cyB3b3JrXG5cdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkICk7XG59XG5cblxuXG5cbi8vIE11bHRpZnVuY3Rpb25hbCBtZXRob2QgdG8gZ2V0IGFuZCBzZXQgdmFsdWVzIG9mIGEgY29sbGVjdGlvblxuLy8gVGhlIHZhbHVlL3MgY2FuIG9wdGlvbmFsbHkgYmUgZXhlY3V0ZWQgaWYgaXQncyBhIGZ1bmN0aW9uXG52YXIgYWNjZXNzID0gZnVuY3Rpb24oIGVsZW1zLCBmbiwga2V5LCB2YWx1ZSwgY2hhaW5hYmxlLCBlbXB0eUdldCwgcmF3ICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gZWxlbXMubGVuZ3RoLFxuXHRcdGJ1bGsgPSBrZXkgPT0gbnVsbDtcblxuXHQvLyBTZXRzIG1hbnkgdmFsdWVzXG5cdGlmICggalF1ZXJ5LnR5cGUoIGtleSApID09PSBcIm9iamVjdFwiICkge1xuXHRcdGNoYWluYWJsZSA9IHRydWU7XG5cdFx0Zm9yICggaSBpbiBrZXkgKSB7XG5cdFx0XHRhY2Nlc3MoIGVsZW1zLCBmbiwgaSwga2V5WyBpIF0sIHRydWUsIGVtcHR5R2V0LCByYXcgKTtcblx0XHR9XG5cblx0Ly8gU2V0cyBvbmUgdmFsdWVcblx0fSBlbHNlIGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRjaGFpbmFibGUgPSB0cnVlO1xuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyYXcgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggYnVsayApIHtcblxuXHRcdFx0Ly8gQnVsayBvcGVyYXRpb25zIHJ1biBhZ2FpbnN0IHRoZSBlbnRpcmUgc2V0XG5cdFx0XHRpZiAoIHJhdyApIHtcblx0XHRcdFx0Zm4uY2FsbCggZWxlbXMsIHZhbHVlICk7XG5cdFx0XHRcdGZuID0gbnVsbDtcblxuXHRcdFx0Ly8gLi4uZXhjZXB0IHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uIHZhbHVlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YnVsayA9IGZuO1xuXHRcdFx0XHRmbiA9IGZ1bmN0aW9uKCBlbGVtLCBrZXksIHZhbHVlICkge1xuXHRcdFx0XHRcdHJldHVybiBidWxrLmNhbGwoIGpRdWVyeSggZWxlbSApLCB2YWx1ZSApO1xuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggZm4gKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0Zm4oXG5cdFx0XHRcdFx0ZWxlbXNbIGkgXSwga2V5LCByYXcgP1xuXHRcdFx0XHRcdHZhbHVlIDpcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCBlbGVtc1sgaSBdLCBpLCBmbiggZWxlbXNbIGkgXSwga2V5ICkgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggY2hhaW5hYmxlICkge1xuXHRcdHJldHVybiBlbGVtcztcblx0fVxuXG5cdC8vIEdldHNcblx0aWYgKCBidWxrICkge1xuXHRcdHJldHVybiBmbi5jYWxsKCBlbGVtcyApO1xuXHR9XG5cblx0cmV0dXJuIGxlbiA/IGZuKCBlbGVtc1sgMCBdLCBrZXkgKSA6IGVtcHR5R2V0O1xufTtcbnZhciBhY2NlcHREYXRhID0gZnVuY3Rpb24oIG93bmVyICkge1xuXG5cdC8vIEFjY2VwdHMgb25seTpcblx0Ly8gIC0gTm9kZVxuXHQvLyAgICAtIE5vZGUuRUxFTUVOVF9OT0RFXG5cdC8vICAgIC0gTm9kZS5ET0NVTUVOVF9OT0RFXG5cdC8vICAtIE9iamVjdFxuXHQvLyAgICAtIEFueVxuXHRyZXR1cm4gb3duZXIubm9kZVR5cGUgPT09IDEgfHwgb3duZXIubm9kZVR5cGUgPT09IDkgfHwgISggK293bmVyLm5vZGVUeXBlICk7XG59O1xuXG5cblxuXG5mdW5jdGlvbiBEYXRhKCkge1xuXHR0aGlzLmV4cGFuZG8gPSBqUXVlcnkuZXhwYW5kbyArIERhdGEudWlkKys7XG59XG5cbkRhdGEudWlkID0gMTtcblxuRGF0YS5wcm90b3R5cGUgPSB7XG5cblx0Y2FjaGU6IGZ1bmN0aW9uKCBvd25lciApIHtcblxuXHRcdC8vIENoZWNrIGlmIHRoZSBvd25lciBvYmplY3QgYWxyZWFkeSBoYXMgYSBjYWNoZVxuXHRcdHZhciB2YWx1ZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdC8vIElmIG5vdCwgY3JlYXRlIG9uZVxuXHRcdGlmICggIXZhbHVlICkge1xuXHRcdFx0dmFsdWUgPSB7fTtcblxuXHRcdFx0Ly8gV2UgY2FuIGFjY2VwdCBkYXRhIGZvciBub24tZWxlbWVudCBub2RlcyBpbiBtb2Rlcm4gYnJvd3NlcnMsXG5cdFx0XHQvLyBidXQgd2Ugc2hvdWxkIG5vdCwgc2VlICM4MzM1LlxuXHRcdFx0Ly8gQWx3YXlzIHJldHVybiBhbiBlbXB0eSBvYmplY3QuXG5cdFx0XHRpZiAoIGFjY2VwdERhdGEoIG93bmVyICkgKSB7XG5cblx0XHRcdFx0Ly8gSWYgaXQgaXMgYSBub2RlIHVubGlrZWx5IHRvIGJlIHN0cmluZ2lmeS1lZCBvciBsb29wZWQgb3ZlclxuXHRcdFx0XHQvLyB1c2UgcGxhaW4gYXNzaWdubWVudFxuXHRcdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSA9IHZhbHVlO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBzZWN1cmUgaXQgaW4gYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eVxuXHRcdFx0XHQvLyBjb25maWd1cmFibGUgbXVzdCBiZSB0cnVlIHRvIGFsbG93IHRoZSBwcm9wZXJ0eSB0byBiZVxuXHRcdFx0XHQvLyBkZWxldGVkIHdoZW4gZGF0YSBpcyByZW1vdmVkXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KCBvd25lciwgdGhpcy5leHBhbmRvLCB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogdmFsdWUsXG5cdFx0XHRcdFx0XHRjb25maWd1cmFibGU6IHRydWVcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdmFsdWU7XG5cdH0sXG5cdHNldDogZnVuY3Rpb24oIG93bmVyLCBkYXRhLCB2YWx1ZSApIHtcblx0XHR2YXIgcHJvcCxcblx0XHRcdGNhY2hlID0gdGhpcy5jYWNoZSggb3duZXIgKTtcblxuXHRcdC8vIEhhbmRsZTogWyBvd25lciwga2V5LCB2YWx1ZSBdIGFyZ3Ncblx0XHQvLyBBbHdheXMgdXNlIGNhbWVsQ2FzZSBrZXkgKGdoLTIyNTcpXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGNhY2hlWyBqUXVlcnkuY2FtZWxDYXNlKCBkYXRhICkgXSA9IHZhbHVlO1xuXG5cdFx0Ly8gSGFuZGxlOiBbIG93bmVyLCB7IHByb3BlcnRpZXMgfSBdIGFyZ3Ncblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBDb3B5IHRoZSBwcm9wZXJ0aWVzIG9uZS1ieS1vbmUgdG8gdGhlIGNhY2hlIG9iamVjdFxuXHRcdFx0Zm9yICggcHJvcCBpbiBkYXRhICkge1xuXHRcdFx0XHRjYWNoZVsgalF1ZXJ5LmNhbWVsQ2FzZSggcHJvcCApIF0gPSBkYXRhWyBwcm9wIF07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZTtcblx0fSxcblx0Z2V0OiBmdW5jdGlvbiggb3duZXIsIGtleSApIHtcblx0XHRyZXR1cm4ga2V5ID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcy5jYWNoZSggb3duZXIgKSA6XG5cblx0XHRcdC8vIEFsd2F5cyB1c2UgY2FtZWxDYXNlIGtleSAoZ2gtMjI1Nylcblx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSAmJiBvd25lclsgdGhpcy5leHBhbmRvIF1bIGpRdWVyeS5jYW1lbENhc2UoIGtleSApIF07XG5cdH0sXG5cdGFjY2VzczogZnVuY3Rpb24oIG93bmVyLCBrZXksIHZhbHVlICkge1xuXG5cdFx0Ly8gSW4gY2FzZXMgd2hlcmUgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBObyBrZXkgd2FzIHNwZWNpZmllZFxuXHRcdC8vICAgMi4gQSBzdHJpbmcga2V5IHdhcyBzcGVjaWZpZWQsIGJ1dCBubyB2YWx1ZSBwcm92aWRlZFxuXHRcdC8vXG5cdFx0Ly8gVGFrZSB0aGUgXCJyZWFkXCIgcGF0aCBhbmQgYWxsb3cgdGhlIGdldCBtZXRob2QgdG8gZGV0ZXJtaW5lXG5cdFx0Ly8gd2hpY2ggdmFsdWUgdG8gcmV0dXJuLCByZXNwZWN0aXZlbHkgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBUaGUgZW50aXJlIGNhY2hlIG9iamVjdFxuXHRcdC8vICAgMi4gVGhlIGRhdGEgc3RvcmVkIGF0IHRoZSBrZXlcblx0XHQvL1xuXHRcdGlmICgga2V5ID09PSB1bmRlZmluZWQgfHxcblx0XHRcdFx0KCAoIGtleSAmJiB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICkgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApICkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoIG93bmVyLCBrZXkgKTtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHRoZSBrZXkgaXMgbm90IGEgc3RyaW5nLCBvciBib3RoIGEga2V5IGFuZCB2YWx1ZVxuXHRcdC8vIGFyZSBzcGVjaWZpZWQsIHNldCBvciBleHRlbmQgKGV4aXN0aW5nIG9iamVjdHMpIHdpdGggZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBBbiBvYmplY3Qgb2YgcHJvcGVydGllc1xuXHRcdC8vICAgMi4gQSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly9cblx0XHR0aGlzLnNldCggb3duZXIsIGtleSwgdmFsdWUgKTtcblxuXHRcdC8vIFNpbmNlIHRoZSBcInNldFwiIHBhdGggY2FuIGhhdmUgdHdvIHBvc3NpYmxlIGVudHJ5IHBvaW50c1xuXHRcdC8vIHJldHVybiB0aGUgZXhwZWN0ZWQgZGF0YSBiYXNlZCBvbiB3aGljaCBwYXRoIHdhcyB0YWtlblsqXVxuXHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiBrZXk7XG5cdH0sXG5cdHJlbW92ZTogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0dmFyIGksXG5cdFx0XHRjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdGlmICggY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGtleSAhPT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHQvLyBTdXBwb3J0IGFycmF5IG9yIHNwYWNlIHNlcGFyYXRlZCBzdHJpbmcgb2Yga2V5c1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBrZXkgKSApIHtcblxuXHRcdFx0XHQvLyBJZiBrZXkgaXMgYW4gYXJyYXkgb2Yga2V5cy4uLlxuXHRcdFx0XHQvLyBXZSBhbHdheXMgc2V0IGNhbWVsQ2FzZSBrZXlzLCBzbyByZW1vdmUgdGhhdC5cblx0XHRcdFx0a2V5ID0ga2V5Lm1hcCggalF1ZXJ5LmNhbWVsQ2FzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0a2V5ID0galF1ZXJ5LmNhbWVsQ2FzZSgga2V5ICk7XG5cblx0XHRcdFx0Ly8gSWYgYSBrZXkgd2l0aCB0aGUgc3BhY2VzIGV4aXN0cywgdXNlIGl0LlxuXHRcdFx0XHQvLyBPdGhlcndpc2UsIGNyZWF0ZSBhbiBhcnJheSBieSBtYXRjaGluZyBub24td2hpdGVzcGFjZVxuXHRcdFx0XHRrZXkgPSBrZXkgaW4gY2FjaGUgP1xuXHRcdFx0XHRcdFsga2V5IF0gOlxuXHRcdFx0XHRcdCgga2V5Lm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10gKTtcblx0XHRcdH1cblxuXHRcdFx0aSA9IGtleS5sZW5ndGg7XG5cblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRkZWxldGUgY2FjaGVbIGtleVsgaSBdIF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIHRoZSBleHBhbmRvIGlmIHRoZXJlJ3Mgbm8gbW9yZSBkYXRhXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fCBqUXVlcnkuaXNFbXB0eU9iamVjdCggY2FjaGUgKSApIHtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NVxuXHRcdFx0Ly8gV2Via2l0ICYgQmxpbmsgcGVyZm9ybWFuY2Ugc3VmZmVycyB3aGVuIGRlbGV0aW5nIHByb3BlcnRpZXNcblx0XHRcdC8vIGZyb20gRE9NIG5vZGVzLCBzbyBzZXQgdG8gdW5kZWZpbmVkIGluc3RlYWRcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTM3ODYwNyAoYnVnIHJlc3RyaWN0ZWQpXG5cdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRvd25lclsgdGhpcy5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWxldGUgb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0aGFzRGF0YTogZnVuY3Rpb24oIG93bmVyICkge1xuXHRcdHZhciBjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblx0XHRyZXR1cm4gY2FjaGUgIT09IHVuZGVmaW5lZCAmJiAhalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGNhY2hlICk7XG5cdH1cbn07XG52YXIgZGF0YVByaXYgPSBuZXcgRGF0YSgpO1xuXG52YXIgZGF0YVVzZXIgPSBuZXcgRGF0YSgpO1xuXG5cblxuLy9cdEltcGxlbWVudGF0aW9uIFN1bW1hcnlcbi8vXG4vL1x0MS4gRW5mb3JjZSBBUEkgc3VyZmFjZSBhbmQgc2VtYW50aWMgY29tcGF0aWJpbGl0eSB3aXRoIDEuOS54IGJyYW5jaFxuLy9cdDIuIEltcHJvdmUgdGhlIG1vZHVsZSdzIG1haW50YWluYWJpbGl0eSBieSByZWR1Y2luZyB0aGUgc3RvcmFnZVxuLy9cdFx0cGF0aHMgdG8gYSBzaW5nbGUgbWVjaGFuaXNtLlxuLy9cdDMuIFVzZSB0aGUgc2FtZSBzaW5nbGUgbWVjaGFuaXNtIHRvIHN1cHBvcnQgXCJwcml2YXRlXCIgYW5kIFwidXNlclwiIGRhdGEuXG4vL1x0NC4gX05ldmVyXyBleHBvc2UgXCJwcml2YXRlXCIgZGF0YSB0byB1c2VyIGNvZGUgKFRPRE86IERyb3AgX2RhdGEsIF9yZW1vdmVEYXRhKVxuLy9cdDUuIEF2b2lkIGV4cG9zaW5nIGltcGxlbWVudGF0aW9uIGRldGFpbHMgb24gdXNlciBvYmplY3RzIChlZy4gZXhwYW5kbyBwcm9wZXJ0aWVzKVxuLy9cdDYuIFByb3ZpZGUgYSBjbGVhciBwYXRoIGZvciBpbXBsZW1lbnRhdGlvbiB1cGdyYWRlIHRvIFdlYWtNYXAgaW4gMjAxNFxuXG52YXIgcmJyYWNlID0gL14oPzpcXHtbXFx3XFxXXSpcXH18XFxbW1xcd1xcV10qXFxdKSQvLFxuXHRybXVsdGlEYXNoID0gL1tBLVpdL2c7XG5cbmZ1bmN0aW9uIGdldERhdGEoIGRhdGEgKSB7XG5cdGlmICggZGF0YSA9PT0gXCJ0cnVlXCIgKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwiZmFsc2VcIiApIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwibnVsbFwiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gT25seSBjb252ZXJ0IHRvIGEgbnVtYmVyIGlmIGl0IGRvZXNuJ3QgY2hhbmdlIHRoZSBzdHJpbmdcblx0aWYgKCBkYXRhID09PSArZGF0YSArIFwiXCIgKSB7XG5cdFx0cmV0dXJuICtkYXRhO1xuXHR9XG5cblx0aWYgKCByYnJhY2UudGVzdCggZGF0YSApICkge1xuXHRcdHJldHVybiBKU09OLnBhcnNlKCBkYXRhICk7XG5cdH1cblxuXHRyZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gZGF0YUF0dHIoIGVsZW0sIGtleSwgZGF0YSApIHtcblx0dmFyIG5hbWU7XG5cblx0Ly8gSWYgbm90aGluZyB3YXMgZm91bmQgaW50ZXJuYWxseSwgdHJ5IHRvIGZldGNoIGFueVxuXHQvLyBkYXRhIGZyb20gdGhlIEhUTUw1IGRhdGEtKiBhdHRyaWJ1dGVcblx0aWYgKCBkYXRhID09PSB1bmRlZmluZWQgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRuYW1lID0gXCJkYXRhLVwiICsga2V5LnJlcGxhY2UoIHJtdWx0aURhc2gsIFwiLSQmXCIgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGRhdGEgPSBlbGVtLmdldEF0dHJpYnV0ZSggbmFtZSApO1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBnZXREYXRhKCBkYXRhICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHt9XG5cblx0XHRcdC8vIE1ha2Ugc3VyZSB3ZSBzZXQgdGhlIGRhdGEgc28gaXQgaXNuJ3QgY2hhbmdlZCBsYXRlclxuXHRcdFx0ZGF0YVVzZXIuc2V0KCBlbGVtLCBrZXksIGRhdGEgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aGFzRGF0YTogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmhhc0RhdGEoIGVsZW0gKSB8fCBkYXRhUHJpdi5oYXNEYXRhKCBlbGVtICk7XG5cdH0sXG5cblx0ZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdHJlbW92ZURhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHRcdGRhdGFVc2VyLnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9LFxuXG5cdC8vIFRPRE86IE5vdyB0aGF0IGFsbCBjYWxscyB0byBfZGF0YSBhbmQgX3JlbW92ZURhdGEgaGF2ZSBiZWVuIHJlcGxhY2VkXG5cdC8vIHdpdGggZGlyZWN0IGNhbGxzIHRvIGRhdGFQcml2IG1ldGhvZHMsIHRoZXNlIGNhbiBiZSBkZXByZWNhdGVkLlxuXHRfZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFQcml2LmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdF9yZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIG5hbWUgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRhdGE6IGZ1bmN0aW9uKCBrZXksIHZhbHVlICkge1xuXHRcdHZhciBpLCBuYW1lLCBkYXRhLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGF0dHJzID0gZWxlbSAmJiBlbGVtLmF0dHJpYnV0ZXM7XG5cblx0XHQvLyBHZXRzIGFsbCB2YWx1ZXNcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdFx0ZGF0YSA9IGRhdGFVc2VyLmdldCggZWxlbSApO1xuXG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAhZGF0YVByaXYuZ2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiICkgKSB7XG5cdFx0XHRcdFx0aSA9IGF0dHJzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0XHRcdFx0Ly8gVGhlIGF0dHJzIGVsZW1lbnRzIGNhbiBiZSBudWxsICgjMTQ4OTQpXG5cdFx0XHRcdFx0XHRpZiAoIGF0dHJzWyBpIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG5hbWUgPSBhdHRyc1sgaSBdLm5hbWU7XG5cdFx0XHRcdFx0XHRcdGlmICggbmFtZS5pbmRleE9mKCBcImRhdGEtXCIgKSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZS5zbGljZSggNSApICk7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUF0dHIoIGVsZW0sIG5hbWUsIGRhdGFbIG5hbWUgXSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFQcml2LnNldCggZWxlbSwgXCJoYXNEYXRhQXR0cnNcIiwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdH1cblxuXHRcdC8vIFNldHMgbXVsdGlwbGUgdmFsdWVzXG5cdFx0aWYgKCB0eXBlb2Yga2V5ID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFVc2VyLnNldCggdGhpcywga2V5ICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGRhdGE7XG5cblx0XHRcdC8vIFRoZSBjYWxsaW5nIGpRdWVyeSBvYmplY3QgKGVsZW1lbnQgbWF0Y2hlcykgaXMgbm90IGVtcHR5XG5cdFx0XHQvLyAoYW5kIHRoZXJlZm9yZSBoYXMgYW4gZWxlbWVudCBhcHBlYXJzIGF0IHRoaXNbIDAgXSkgYW5kIHRoZVxuXHRcdFx0Ly8gYHZhbHVlYCBwYXJhbWV0ZXIgd2FzIG5vdCB1bmRlZmluZWQuIEFuIGVtcHR5IGpRdWVyeSBvYmplY3Rcblx0XHRcdC8vIHdpbGwgcmVzdWx0IGluIGB1bmRlZmluZWRgIGZvciBlbGVtID0gdGhpc1sgMCBdIHdoaWNoIHdpbGxcblx0XHRcdC8vIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBhbiBhdHRlbXB0IHRvIHJlYWQgYSBkYXRhIGNhY2hlIGlzIG1hZGUuXG5cdFx0XHRpZiAoIGVsZW0gJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHQvLyBBdHRlbXB0IHRvIGdldCBkYXRhIGZyb20gdGhlIGNhY2hlXG5cdFx0XHRcdC8vIFRoZSBrZXkgd2lsbCBhbHdheXMgYmUgY2FtZWxDYXNlZCBpbiBEYXRhXG5cdFx0XHRcdGRhdGEgPSBkYXRhVXNlci5nZXQoIGVsZW0sIGtleSApO1xuXHRcdFx0XHRpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gXCJkaXNjb3ZlclwiIHRoZSBkYXRhIGluXG5cdFx0XHRcdC8vIEhUTUw1IGN1c3RvbSBkYXRhLSogYXR0cnNcblx0XHRcdFx0ZGF0YSA9IGRhdGFBdHRyKCBlbGVtLCBrZXkgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB0cmllZCByZWFsbHkgaGFyZCwgYnV0IHRoZSBkYXRhIGRvZXNuJ3QgZXhpc3QuXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IHRoZSBkYXRhLi4uXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdC8vIFdlIGFsd2F5cyBzdG9yZSB0aGUgY2FtZWxDYXNlZCBrZXlcblx0XHRcdFx0ZGF0YVVzZXIuc2V0KCB0aGlzLCBrZXksIHZhbHVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fSwgbnVsbCwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxLCBudWxsLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlRGF0YTogZnVuY3Rpb24oIGtleSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGRhdGFVc2VyLnJlbW92ZSggdGhpcywga2V5ICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHF1ZXVlO1xuXG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0dHlwZSA9ICggdHlwZSB8fCBcImZ4XCIgKSArIFwicXVldWVcIjtcblx0XHRcdHF1ZXVlID0gZGF0YVByaXYuZ2V0KCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdC8vIFNwZWVkIHVwIGRlcXVldWUgYnkgZ2V0dGluZyBvdXQgcXVpY2tseSBpZiB0aGlzIGlzIGp1c3QgYSBsb29rdXBcblx0XHRcdGlmICggZGF0YSApIHtcblx0XHRcdFx0aWYgKCAhcXVldWUgfHwgQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdHF1ZXVlID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCB0eXBlLCBqUXVlcnkubWFrZUFycmF5KCBkYXRhICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBxdWV1ZSB8fCBbXTtcblx0XHR9XG5cdH0sXG5cblx0ZGVxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0dmFyIHF1ZXVlID0galF1ZXJ5LnF1ZXVlKCBlbGVtLCB0eXBlICksXG5cdFx0XHRzdGFydExlbmd0aCA9IHF1ZXVlLmxlbmd0aCxcblx0XHRcdGZuID0gcXVldWUuc2hpZnQoKSxcblx0XHRcdGhvb2tzID0galF1ZXJ5Ll9xdWV1ZUhvb2tzKCBlbGVtLCB0eXBlICksXG5cdFx0XHRuZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCBlbGVtLCB0eXBlICk7XG5cdFx0XHR9O1xuXG5cdFx0Ly8gSWYgdGhlIGZ4IHF1ZXVlIGlzIGRlcXVldWVkLCBhbHdheXMgcmVtb3ZlIHRoZSBwcm9ncmVzcyBzZW50aW5lbFxuXHRcdGlmICggZm4gPT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0c3RhcnRMZW5ndGgtLTtcblx0XHR9XG5cblx0XHRpZiAoIGZuICkge1xuXG5cdFx0XHQvLyBBZGQgYSBwcm9ncmVzcyBzZW50aW5lbCB0byBwcmV2ZW50IHRoZSBmeCBxdWV1ZSBmcm9tIGJlaW5nXG5cdFx0XHQvLyBhdXRvbWF0aWNhbGx5IGRlcXVldWVkXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiApIHtcblx0XHRcdFx0cXVldWUudW5zaGlmdCggXCJpbnByb2dyZXNzXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2xlYXIgdXAgdGhlIGxhc3QgcXVldWUgc3RvcCBmdW5jdGlvblxuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRmbi5jYWxsKCBlbGVtLCBuZXh0LCBob29rcyApO1xuXHRcdH1cblxuXHRcdGlmICggIXN0YXJ0TGVuZ3RoICYmIGhvb2tzICkge1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBOb3QgcHVibGljIC0gZ2VuZXJhdGUgYSBxdWV1ZUhvb2tzIG9iamVjdCwgb3IgcmV0dXJuIHRoZSBjdXJyZW50IG9uZVxuXHRfcXVldWVIb29rczogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dmFyIGtleSA9IHR5cGUgKyBcInF1ZXVlSG9va3NcIjtcblx0XHRyZXR1cm4gZGF0YVByaXYuZ2V0KCBlbGVtLCBrZXkgKSB8fCBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIGtleSwge1xuXHRcdFx0ZW1wdHk6IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLmFkZCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgWyB0eXBlICsgXCJxdWV1ZVwiLCBrZXkgXSApO1xuXHRcdFx0fSApXG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0cXVldWU6IGZ1bmN0aW9uKCB0eXBlLCBkYXRhICkge1xuXHRcdHZhciBzZXR0ZXIgPSAyO1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGRhdGEgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IFwiZnhcIjtcblx0XHRcdHNldHRlci0tO1xuXHRcdH1cblxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCA8IHNldHRlciApIHtcblx0XHRcdHJldHVybiBqUXVlcnkucXVldWUoIHRoaXNbIDAgXSwgdHlwZSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRhID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcyA6XG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIHRoaXMsIHR5cGUsIGRhdGEgKTtcblxuXHRcdFx0XHQvLyBFbnN1cmUgYSBob29rcyBmb3IgdGhpcyBxdWV1ZVxuXHRcdFx0XHRqUXVlcnkuX3F1ZXVlSG9va3MoIHRoaXMsIHR5cGUgKTtcblxuXHRcdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiAmJiBxdWV1ZVsgMCBdICE9PSBcImlucHJvZ3Jlc3NcIiApIHtcblx0XHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdH0sXG5cdGRlcXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIHR5cGUgKTtcblx0XHR9ICk7XG5cdH0sXG5cdGNsZWFyUXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0fSxcblxuXHQvLyBHZXQgYSBwcm9taXNlIHJlc29sdmVkIHdoZW4gcXVldWVzIG9mIGEgY2VydGFpbiB0eXBlXG5cdC8vIGFyZSBlbXB0aWVkIChmeCBpcyB0aGUgdHlwZSBieSBkZWZhdWx0KVxuXHRwcm9taXNlOiBmdW5jdGlvbiggdHlwZSwgb2JqICkge1xuXHRcdHZhciB0bXAsXG5cdFx0XHRjb3VudCA9IDEsXG5cdFx0XHRkZWZlciA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0ZWxlbWVudHMgPSB0aGlzLFxuXHRcdFx0aSA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0cmVzb2x2ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICEoIC0tY291bnQgKSApIHtcblx0XHRcdFx0XHRkZWZlci5yZXNvbHZlV2l0aCggZWxlbWVudHMsIFsgZWxlbWVudHMgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG9iaiA9IHR5cGU7XG5cdFx0XHR0eXBlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdHRtcCA9IGRhdGFQcml2LmdldCggZWxlbWVudHNbIGkgXSwgdHlwZSArIFwicXVldWVIb29rc1wiICk7XG5cdFx0XHRpZiAoIHRtcCAmJiB0bXAuZW1wdHkgKSB7XG5cdFx0XHRcdGNvdW50Kys7XG5cdFx0XHRcdHRtcC5lbXB0eS5hZGQoIHJlc29sdmUgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVzb2x2ZSgpO1xuXHRcdHJldHVybiBkZWZlci5wcm9taXNlKCBvYmogKTtcblx0fVxufSApO1xudmFyIHBudW0gPSAoIC9bKy1dPyg/OlxcZCpcXC58KVxcZCsoPzpbZUVdWystXT9cXGQrfCkvICkuc291cmNlO1xuXG52YXIgcmNzc051bSA9IG5ldyBSZWdFeHAoIFwiXig/OihbKy1dKT18KShcIiArIHBudW0gKyBcIikoW2EteiVdKikkXCIsIFwiaVwiICk7XG5cblxudmFyIGNzc0V4cGFuZCA9IFsgXCJUb3BcIiwgXCJSaWdodFwiLCBcIkJvdHRvbVwiLCBcIkxlZnRcIiBdO1xuXG52YXIgaXNIaWRkZW5XaXRoaW5UcmVlID0gZnVuY3Rpb24oIGVsZW0sIGVsICkge1xuXG5cdFx0Ly8gaXNIaWRkZW5XaXRoaW5UcmVlIG1pZ2h0IGJlIGNhbGxlZCBmcm9tIGpRdWVyeSNmaWx0ZXIgZnVuY3Rpb247XG5cdFx0Ly8gaW4gdGhhdCBjYXNlLCBlbGVtZW50IHdpbGwgYmUgc2Vjb25kIGFyZ3VtZW50XG5cdFx0ZWxlbSA9IGVsIHx8IGVsZW07XG5cblx0XHQvLyBJbmxpbmUgc3R5bGUgdHJ1bXBzIGFsbFxuXHRcdHJldHVybiBlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwibm9uZVwiIHx8XG5cdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwiXCIgJiZcblxuXHRcdFx0Ly8gT3RoZXJ3aXNlLCBjaGVjayBjb21wdXRlZCBzdHlsZVxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCA8PTQzIC0gNDVcblx0XHRcdC8vIERpc2Nvbm5lY3RlZCBlbGVtZW50cyBjYW4gaGF2ZSBjb21wdXRlZCBkaXNwbGF5OiBub25lLCBzbyBmaXJzdCBjb25maXJtIHRoYXQgZWxlbSBpc1xuXHRcdFx0Ly8gaW4gdGhlIGRvY3VtZW50LlxuXHRcdFx0alF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKSAmJlxuXG5cdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApID09PSBcIm5vbmVcIjtcblx0fTtcblxudmFyIHN3YXAgPSBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgY2FsbGJhY2ssIGFyZ3MgKSB7XG5cdHZhciByZXQsIG5hbWUsXG5cdFx0b2xkID0ge307XG5cblx0Ly8gUmVtZW1iZXIgdGhlIG9sZCB2YWx1ZXMsIGFuZCBpbnNlcnQgdGhlIG5ldyBvbmVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRvbGRbIG5hbWUgXSA9IGVsZW0uc3R5bGVbIG5hbWUgXTtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvcHRpb25zWyBuYW1lIF07XG5cdH1cblxuXHRyZXQgPSBjYWxsYmFjay5hcHBseSggZWxlbSwgYXJncyB8fCBbXSApO1xuXG5cdC8vIFJldmVydCB0aGUgb2xkIHZhbHVlc1xuXHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0ZWxlbS5zdHlsZVsgbmFtZSBdID0gb2xkWyBuYW1lIF07XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufTtcblxuXG5cblxuZnVuY3Rpb24gYWRqdXN0Q1NTKCBlbGVtLCBwcm9wLCB2YWx1ZVBhcnRzLCB0d2VlbiApIHtcblx0dmFyIGFkanVzdGVkLFxuXHRcdHNjYWxlID0gMSxcblx0XHRtYXhJdGVyYXRpb25zID0gMjAsXG5cdFx0Y3VycmVudFZhbHVlID0gdHdlZW4gP1xuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiB0d2Vlbi5jdXIoKTtcblx0XHRcdH0gOlxuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wLCBcIlwiICk7XG5cdFx0XHR9LFxuXHRcdGluaXRpYWwgPSBjdXJyZW50VmFsdWUoKSxcblx0XHR1bml0ID0gdmFsdWVQYXJ0cyAmJiB2YWx1ZVBhcnRzWyAzIF0gfHwgKCBqUXVlcnkuY3NzTnVtYmVyWyBwcm9wIF0gPyBcIlwiIDogXCJweFwiICksXG5cblx0XHQvLyBTdGFydGluZyB2YWx1ZSBjb21wdXRhdGlvbiBpcyByZXF1aXJlZCBmb3IgcG90ZW50aWFsIHVuaXQgbWlzbWF0Y2hlc1xuXHRcdGluaXRpYWxJblVuaXQgPSAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSB8fCB1bml0ICE9PSBcInB4XCIgJiYgK2luaXRpYWwgKSAmJlxuXHRcdFx0cmNzc051bS5leGVjKCBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wICkgKTtcblxuXHRpZiAoIGluaXRpYWxJblVuaXQgJiYgaW5pdGlhbEluVW5pdFsgMyBdICE9PSB1bml0ICkge1xuXG5cdFx0Ly8gVHJ1c3QgdW5pdHMgcmVwb3J0ZWQgYnkgalF1ZXJ5LmNzc1xuXHRcdHVuaXQgPSB1bml0IHx8IGluaXRpYWxJblVuaXRbIDMgXTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB3ZSB1cGRhdGUgdGhlIHR3ZWVuIHByb3BlcnRpZXMgbGF0ZXIgb25cblx0XHR2YWx1ZVBhcnRzID0gdmFsdWVQYXJ0cyB8fCBbXTtcblxuXHRcdC8vIEl0ZXJhdGl2ZWx5IGFwcHJveGltYXRlIGZyb20gYSBub256ZXJvIHN0YXJ0aW5nIHBvaW50XG5cdFx0aW5pdGlhbEluVW5pdCA9ICtpbml0aWFsIHx8IDE7XG5cblx0XHRkbyB7XG5cblx0XHRcdC8vIElmIHByZXZpb3VzIGl0ZXJhdGlvbiB6ZXJvZWQgb3V0LCBkb3VibGUgdW50aWwgd2UgZ2V0ICpzb21ldGhpbmcqLlxuXHRcdFx0Ly8gVXNlIHN0cmluZyBmb3IgZG91Ymxpbmcgc28gd2UgZG9uJ3QgYWNjaWRlbnRhbGx5IHNlZSBzY2FsZSBhcyB1bmNoYW5nZWQgYmVsb3dcblx0XHRcdHNjYWxlID0gc2NhbGUgfHwgXCIuNVwiO1xuXG5cdFx0XHQvLyBBZGp1c3QgYW5kIGFwcGx5XG5cdFx0XHRpbml0aWFsSW5Vbml0ID0gaW5pdGlhbEluVW5pdCAvIHNjYWxlO1xuXHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wLCBpbml0aWFsSW5Vbml0ICsgdW5pdCApO1xuXG5cdFx0Ly8gVXBkYXRlIHNjYWxlLCB0b2xlcmF0aW5nIHplcm8gb3IgTmFOIGZyb20gdHdlZW4uY3VyKClcblx0XHQvLyBCcmVhayB0aGUgbG9vcCBpZiBzY2FsZSBpcyB1bmNoYW5nZWQgb3IgcGVyZmVjdCwgb3IgaWYgd2UndmUganVzdCBoYWQgZW5vdWdoLlxuXHRcdH0gd2hpbGUgKFxuXHRcdFx0c2NhbGUgIT09ICggc2NhbGUgPSBjdXJyZW50VmFsdWUoKSAvIGluaXRpYWwgKSAmJiBzY2FsZSAhPT0gMSAmJiAtLW1heEl0ZXJhdGlvbnNcblx0XHQpO1xuXHR9XG5cblx0aWYgKCB2YWx1ZVBhcnRzICkge1xuXHRcdGluaXRpYWxJblVuaXQgPSAraW5pdGlhbEluVW5pdCB8fCAraW5pdGlhbCB8fCAwO1xuXG5cdFx0Ly8gQXBwbHkgcmVsYXRpdmUgb2Zmc2V0ICgrPS8tPSkgaWYgc3BlY2lmaWVkXG5cdFx0YWRqdXN0ZWQgPSB2YWx1ZVBhcnRzWyAxIF0gP1xuXHRcdFx0aW5pdGlhbEluVW5pdCArICggdmFsdWVQYXJ0c1sgMSBdICsgMSApICogdmFsdWVQYXJ0c1sgMiBdIDpcblx0XHRcdCt2YWx1ZVBhcnRzWyAyIF07XG5cdFx0aWYgKCB0d2VlbiApIHtcblx0XHRcdHR3ZWVuLnVuaXQgPSB1bml0O1xuXHRcdFx0dHdlZW4uc3RhcnQgPSBpbml0aWFsSW5Vbml0O1xuXHRcdFx0dHdlZW4uZW5kID0gYWRqdXN0ZWQ7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBhZGp1c3RlZDtcbn1cblxuXG52YXIgZGVmYXVsdERpc3BsYXlNYXAgPSB7fTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKSB7XG5cdHZhciB0ZW1wLFxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudCxcblx0XHRub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUsXG5cdFx0ZGlzcGxheSA9IGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdO1xuXG5cdGlmICggZGlzcGxheSApIHtcblx0XHRyZXR1cm4gZGlzcGxheTtcblx0fVxuXG5cdHRlbXAgPSBkb2MuYm9keS5hcHBlbmRDaGlsZCggZG9jLmNyZWF0ZUVsZW1lbnQoIG5vZGVOYW1lICkgKTtcblx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIHRlbXAsIFwiZGlzcGxheVwiICk7XG5cblx0dGVtcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCB0ZW1wICk7XG5cblx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRkaXNwbGF5ID0gXCJibG9ja1wiO1xuXHR9XG5cdGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdID0gZGlzcGxheTtcblxuXHRyZXR1cm4gZGlzcGxheTtcbn1cblxuZnVuY3Rpb24gc2hvd0hpZGUoIGVsZW1lbnRzLCBzaG93ICkge1xuXHR2YXIgZGlzcGxheSwgZWxlbSxcblx0XHR2YWx1ZXMgPSBbXSxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoO1xuXG5cdC8vIERldGVybWluZSBuZXcgZGlzcGxheSB2YWx1ZSBmb3IgZWxlbWVudHMgdGhhdCBuZWVkIHRvIGNoYW5nZVxuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGVsZW0gPSBlbGVtZW50c1sgaW5kZXggXTtcblx0XHRpZiAoICFlbGVtLnN0eWxlICkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0ZGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheTtcblx0XHRpZiAoIHNob3cgKSB7XG5cblx0XHRcdC8vIFNpbmNlIHdlIGZvcmNlIHZpc2liaWxpdHkgdXBvbiBjYXNjYWRlLWhpZGRlbiBlbGVtZW50cywgYW4gaW1tZWRpYXRlIChhbmQgc2xvdylcblx0XHRcdC8vIGNoZWNrIGlzIHJlcXVpcmVkIGluIHRoaXMgZmlyc3QgbG9vcCB1bmxlc3Mgd2UgaGF2ZSBhIG5vbmVtcHR5IGRpc3BsYXkgdmFsdWUgKGVpdGhlclxuXHRcdFx0Ly8gaW5saW5lIG9yIGFib3V0LXRvLWJlLXJlc3RvcmVkKVxuXHRcdFx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApIHx8IG51bGw7XG5cdFx0XHRcdGlmICggIXZhbHVlc1sgaW5kZXggXSApIHtcblx0XHRcdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJcIiAmJiBpc0hpZGRlbldpdGhpblRyZWUoIGVsZW0gKSApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBkaXNwbGF5ICE9PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gXCJub25lXCI7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgd2hhdCB3ZSdyZSBvdmVyd3JpdGluZ1xuXHRcdFx0XHRkYXRhUHJpdi5zZXQoIGVsZW0sIFwiZGlzcGxheVwiLCBkaXNwbGF5ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gU2V0IHRoZSBkaXNwbGF5IG9mIHRoZSBlbGVtZW50cyBpbiBhIHNlY29uZCBsb29wIHRvIGF2b2lkIGNvbnN0YW50IHJlZmxvd1xuXHRmb3IgKCBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGlmICggdmFsdWVzWyBpbmRleCBdICE9IG51bGwgKSB7XG5cdFx0XHRlbGVtZW50c1sgaW5kZXggXS5zdHlsZS5kaXNwbGF5ID0gdmFsdWVzWyBpbmRleCBdO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50cztcbn1cblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRzaG93OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMsIHRydWUgKTtcblx0fSxcblx0aGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNob3dIaWRlKCB0aGlzICk7XG5cdH0sXG5cdHRvZ2dsZTogZnVuY3Rpb24oIHN0YXRlICkge1xuXHRcdGlmICggdHlwZW9mIHN0YXRlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdHJldHVybiBzdGF0ZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGlzSGlkZGVuV2l0aGluVHJlZSggdGhpcyApICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5zaG93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG52YXIgcmNoZWNrYWJsZVR5cGUgPSAoIC9eKD86Y2hlY2tib3h8cmFkaW8pJC9pICk7XG5cbnZhciBydGFnTmFtZSA9ICggLzwoW2Etel1bXlxcL1xcMD5cXHgyMFxcdFxcclxcblxcZl0rKS9pICk7XG5cbnZhciByc2NyaXB0VHlwZSA9ICggL14kfFxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSApO1xuXG5cblxuLy8gV2UgaGF2ZSB0byBjbG9zZSB0aGVzZSB0YWdzIHRvIHN1cHBvcnQgWEhUTUwgKCMxMzIwMClcbnZhciB3cmFwTWFwID0ge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdG9wdGlvbjogWyAxLCBcIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz5cIiwgXCI8L3NlbGVjdD5cIiBdLFxuXG5cdC8vIFhIVE1MIHBhcnNlcnMgZG8gbm90IG1hZ2ljYWxseSBpbnNlcnQgZWxlbWVudHMgaW4gdGhlXG5cdC8vIHNhbWUgd2F5IHRoYXQgdGFnIHNvdXAgcGFyc2VycyBkby4gU28gd2UgY2Fubm90IHNob3J0ZW5cblx0Ly8gdGhpcyBieSBvbWl0dGluZyA8dGJvZHk+IG9yIG90aGVyIHJlcXVpcmVkIGVsZW1lbnRzLlxuXHR0aGVhZDogWyAxLCBcIjx0YWJsZT5cIiwgXCI8L3RhYmxlPlwiIF0sXG5cdGNvbDogWyAyLCBcIjx0YWJsZT48Y29sZ3JvdXA+XCIsIFwiPC9jb2xncm91cD48L3RhYmxlPlwiIF0sXG5cdHRyOiBbIDIsIFwiPHRhYmxlPjx0Ym9keT5cIiwgXCI8L3Rib2R5PjwvdGFibGU+XCIgXSxcblx0dGQ6IFsgMywgXCI8dGFibGU+PHRib2R5Pjx0cj5cIiwgXCI8L3RyPjwvdGJvZHk+PC90YWJsZT5cIiBdLFxuXG5cdF9kZWZhdWx0OiBbIDAsIFwiXCIsIFwiXCIgXVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbndyYXBNYXAub3B0Z3JvdXAgPSB3cmFwTWFwLm9wdGlvbjtcblxud3JhcE1hcC50Ym9keSA9IHdyYXBNYXAudGZvb3QgPSB3cmFwTWFwLmNvbGdyb3VwID0gd3JhcE1hcC5jYXB0aW9uID0gd3JhcE1hcC50aGVhZDtcbndyYXBNYXAudGggPSB3cmFwTWFwLnRkO1xuXG5cbmZ1bmN0aW9uIGdldEFsbCggY29udGV4dCwgdGFnICkge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0Ly8gVXNlIHR5cGVvZiB0byBhdm9pZCB6ZXJvLWFyZ3VtZW50IG1ldGhvZCBpbnZvY2F0aW9uIG9uIGhvc3Qgb2JqZWN0cyAoIzE1MTUxKVxuXHR2YXIgcmV0O1xuXG5cdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0cmV0ID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnIHx8IFwiKlwiICk7XG5cblx0fSBlbHNlIGlmICggdHlwZW9mIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRyZXQgPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIHRhZyB8fCBcIipcIiApO1xuXG5cdH0gZWxzZSB7XG5cdFx0cmV0ID0gW107XG5cdH1cblxuXHRpZiAoIHRhZyA9PT0gdW5kZWZpbmVkIHx8IHRhZyAmJiBub2RlTmFtZSggY29udGV4dCwgdGFnICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5tZXJnZSggWyBjb250ZXh0IF0sIHJldCApO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuXG4vLyBNYXJrIHNjcmlwdHMgYXMgaGF2aW5nIGFscmVhZHkgYmVlbiBldmFsdWF0ZWRcbmZ1bmN0aW9uIHNldEdsb2JhbEV2YWwoIGVsZW1zLCByZWZFbGVtZW50cyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdGRhdGFQcml2LnNldChcblx0XHRcdGVsZW1zWyBpIF0sXG5cdFx0XHRcImdsb2JhbEV2YWxcIixcblx0XHRcdCFyZWZFbGVtZW50cyB8fCBkYXRhUHJpdi5nZXQoIHJlZkVsZW1lbnRzWyBpIF0sIFwiZ2xvYmFsRXZhbFwiIClcblx0XHQpO1xuXHR9XG59XG5cblxudmFyIHJodG1sID0gLzx8JiM/XFx3KzsvO1xuXG5mdW5jdGlvbiBidWlsZEZyYWdtZW50KCBlbGVtcywgY29udGV4dCwgc2NyaXB0cywgc2VsZWN0aW9uLCBpZ25vcmVkICkge1xuXHR2YXIgZWxlbSwgdG1wLCB0YWcsIHdyYXAsIGNvbnRhaW5zLCBqLFxuXHRcdGZyYWdtZW50ID0gY29udGV4dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksXG5cdFx0bm9kZXMgPSBbXSxcblx0XHRpID0gMCxcblx0XHRsID0gZWxlbXMubGVuZ3RoO1xuXG5cdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRlbGVtID0gZWxlbXNbIGkgXTtcblxuXHRcdGlmICggZWxlbSB8fCBlbGVtID09PSAwICkge1xuXG5cdFx0XHQvLyBBZGQgbm9kZXMgZGlyZWN0bHlcblx0XHRcdGlmICggalF1ZXJ5LnR5cGUoIGVsZW0gKSA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0XHRcdFx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIG5vZGVzLCBlbGVtLm5vZGVUeXBlID8gWyBlbGVtIF0gOiBlbGVtICk7XG5cblx0XHRcdC8vIENvbnZlcnQgbm9uLWh0bWwgaW50byBhIHRleHQgbm9kZVxuXHRcdFx0fSBlbHNlIGlmICggIXJodG1sLnRlc3QoIGVsZW0gKSApIHtcblx0XHRcdFx0bm9kZXMucHVzaCggY29udGV4dC5jcmVhdGVUZXh0Tm9kZSggZWxlbSApICk7XG5cblx0XHRcdC8vIENvbnZlcnQgaHRtbCBpbnRvIERPTSBub2Rlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dG1wID0gdG1wIHx8IGZyYWdtZW50LmFwcGVuZENoaWxkKCBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSApO1xuXG5cdFx0XHRcdC8vIERlc2VyaWFsaXplIGEgc3RhbmRhcmQgcmVwcmVzZW50YXRpb25cblx0XHRcdFx0dGFnID0gKCBydGFnTmFtZS5leGVjKCBlbGVtICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdHdyYXAgPSB3cmFwTWFwWyB0YWcgXSB8fCB3cmFwTWFwLl9kZWZhdWx0O1xuXHRcdFx0XHR0bXAuaW5uZXJIVE1MID0gd3JhcFsgMSBdICsgalF1ZXJ5Lmh0bWxQcmVmaWx0ZXIoIGVsZW0gKSArIHdyYXBbIDIgXTtcblxuXHRcdFx0XHQvLyBEZXNjZW5kIHRocm91Z2ggd3JhcHBlcnMgdG8gdGhlIHJpZ2h0IGNvbnRlbnRcblx0XHRcdFx0aiA9IHdyYXBbIDAgXTtcblx0XHRcdFx0d2hpbGUgKCBqLS0gKSB7XG5cdFx0XHRcdFx0dG1wID0gdG1wLmxhc3RDaGlsZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIHRtcC5jaGlsZE5vZGVzICk7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgdGhlIHRvcC1sZXZlbCBjb250YWluZXJcblx0XHRcdFx0dG1wID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuXHRcdFx0XHQvLyBFbnN1cmUgdGhlIGNyZWF0ZWQgbm9kZXMgYXJlIG9ycGhhbmVkICgjMTIzOTIpXG5cdFx0XHRcdHRtcC50ZXh0Q29udGVudCA9IFwiXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmVtb3ZlIHdyYXBwZXIgZnJvbSBmcmFnbWVudFxuXHRmcmFnbWVudC50ZXh0Q29udGVudCA9IFwiXCI7XG5cblx0aSA9IDA7XG5cdHdoaWxlICggKCBlbGVtID0gbm9kZXNbIGkrKyBdICkgKSB7XG5cblx0XHQvLyBTa2lwIGVsZW1lbnRzIGFscmVhZHkgaW4gdGhlIGNvbnRleHQgY29sbGVjdGlvbiAodHJhYy00MDg3KVxuXHRcdGlmICggc2VsZWN0aW9uICYmIGpRdWVyeS5pbkFycmF5KCBlbGVtLCBzZWxlY3Rpb24gKSA+IC0xICkge1xuXHRcdFx0aWYgKCBpZ25vcmVkICkge1xuXHRcdFx0XHRpZ25vcmVkLnB1c2goIGVsZW0gKTtcblx0XHRcdH1cblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblxuXHRcdGNvbnRhaW5zID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdC8vIEFwcGVuZCB0byBmcmFnbWVudFxuXHRcdHRtcCA9IGdldEFsbCggZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGVsZW0gKSwgXCJzY3JpcHRcIiApO1xuXG5cdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdGlmICggY29udGFpbnMgKSB7XG5cdFx0XHRzZXRHbG9iYWxFdmFsKCB0bXAgKTtcblx0XHR9XG5cblx0XHQvLyBDYXB0dXJlIGV4ZWN1dGFibGVzXG5cdFx0aWYgKCBzY3JpcHRzICkge1xuXHRcdFx0aiA9IDA7XG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRtcFsgaisrIF0gKSApIHtcblx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBlbGVtLnR5cGUgfHwgXCJcIiApICkge1xuXHRcdFx0XHRcdHNjcmlwdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGZyYWdtZW50O1xufVxuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRkaXYgPSBmcmFnbWVudC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApICksXG5cdFx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCAtIDQuMyBvbmx5XG5cdC8vIENoZWNrIHN0YXRlIGxvc3QgaWYgdGhlIG5hbWUgaXMgc2V0ICgjMTEyMTcpXG5cdC8vIFN1cHBvcnQ6IFdpbmRvd3MgV2ViIEFwcHMgKFdXQSlcblx0Ly8gYG5hbWVgIGFuZCBgdHlwZWAgbXVzdCB1c2UgLnNldEF0dHJpYnV0ZSBmb3IgV1dBICgjMTQ5MDEpXG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIFwicmFkaW9cIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwiY2hlY2tlZFwiLCBcImNoZWNrZWRcIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcInRcIiApO1xuXG5cdGRpdi5hcHBlbmRDaGlsZCggaW5wdXQgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4xIG9ubHlcblx0Ly8gT2xkZXIgV2ViS2l0IGRvZXNuJ3QgY2xvbmUgY2hlY2tlZCBzdGF0ZSBjb3JyZWN0bHkgaW4gZnJhZ21lbnRzXG5cdHN1cHBvcnQuY2hlY2tDbG9uZSA9IGRpdi5jbG9uZU5vZGUoIHRydWUgKS5jbG9uZU5vZGUoIHRydWUgKS5sYXN0Q2hpbGQuY2hlY2tlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHRleHRhcmVhIChhbmQgY2hlY2tib3gpIGRlZmF1bHRWYWx1ZSBpcyBwcm9wZXJseSBjbG9uZWRcblx0ZGl2LmlubmVySFRNTCA9IFwiPHRleHRhcmVhPng8L3RleHRhcmVhPlwiO1xuXHRzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkID0gISFkaXYuY2xvbmVOb2RlKCB0cnVlICkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZTtcbn0gKSgpO1xudmFyIGRvY3VtZW50RWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuXG5cbnZhclxuXHRya2V5RXZlbnQgPSAvXmtleS8sXG5cdHJtb3VzZUV2ZW50ID0gL14oPzptb3VzZXxwb2ludGVyfGNvbnRleHRtZW51fGRyYWd8ZHJvcCl8Y2xpY2svLFxuXHRydHlwZW5hbWVzcGFjZSA9IC9eKFteLl0qKSg/OlxcLiguKyl8KS87XG5cbmZ1bmN0aW9uIHJldHVyblRydWUoKSB7XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZXR1cm5GYWxzZSgpIHtcblx0cmV0dXJuIGZhbHNlO1xufVxuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuLy8gU2VlICMxMzM5MyBmb3IgbW9yZSBpbmZvXG5mdW5jdGlvbiBzYWZlQWN0aXZlRWxlbWVudCgpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblx0fSBjYXRjaCAoIGVyciApIHsgfVxufVxuXG5mdW5jdGlvbiBvbiggZWxlbSwgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgb25lICkge1xuXHR2YXIgb3JpZ0ZuLCB0eXBlO1xuXG5cdC8vIFR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xuXHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdC8vICggdHlwZXMtT2JqZWN0LCBzZWxlY3RvciwgZGF0YSApXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMtT2JqZWN0LCBkYXRhIClcblx0XHRcdGRhdGEgPSBkYXRhIHx8IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRvbiggZWxlbSwgdHlwZSwgc2VsZWN0b3IsIGRhdGEsIHR5cGVzWyB0eXBlIF0sIG9uZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbTtcblx0fVxuXG5cdGlmICggZGF0YSA9PSBudWxsICYmIGZuID09IG51bGwgKSB7XG5cblx0XHQvLyAoIHR5cGVzLCBmbiApXG5cdFx0Zm4gPSBzZWxlY3Rvcjtcblx0XHRkYXRhID0gc2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdH0gZWxzZSBpZiAoIGZuID09IG51bGwgKSB7XG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMsIHNlbGVjdG9yLCBmbiApXG5cdFx0XHRmbiA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vICggdHlwZXMsIGRhdGEsIGZuIClcblx0XHRcdGZuID0gZGF0YTtcblx0XHRcdGRhdGEgPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRpZiAoIGZuID09PSBmYWxzZSApIHtcblx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHR9IGVsc2UgaWYgKCAhZm4gKSB7XG5cdFx0cmV0dXJuIGVsZW07XG5cdH1cblxuXHRpZiAoIG9uZSA9PT0gMSApIHtcblx0XHRvcmlnRm4gPSBmbjtcblx0XHRmbiA9IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0Ly8gQ2FuIHVzZSBhbiBlbXB0eSBzZXQsIHNpbmNlIGV2ZW50IGNvbnRhaW5zIHRoZSBpbmZvXG5cdFx0XHRqUXVlcnkoKS5vZmYoIGV2ZW50ICk7XG5cdFx0XHRyZXR1cm4gb3JpZ0ZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9O1xuXG5cdFx0Ly8gVXNlIHNhbWUgZ3VpZCBzbyBjYWxsZXIgY2FuIHJlbW92ZSB1c2luZyBvcmlnRm5cblx0XHRmbi5ndWlkID0gb3JpZ0ZuLmd1aWQgfHwgKCBvcmlnRm4uZ3VpZCA9IGpRdWVyeS5ndWlkKysgKTtcblx0fVxuXHRyZXR1cm4gZWxlbS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRqUXVlcnkuZXZlbnQuYWRkKCB0aGlzLCB0eXBlcywgZm4sIGRhdGEsIHNlbGVjdG9yICk7XG5cdH0gKTtcbn1cblxuLypcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIG1hbmFnaW5nIGV2ZW50cyAtLSBub3QgcGFydCBvZiB0aGUgcHVibGljIGludGVyZmFjZS5cbiAqIFByb3BzIHRvIERlYW4gRWR3YXJkcycgYWRkRXZlbnQgbGlicmFyeSBmb3IgbWFueSBvZiB0aGUgaWRlYXMuXG4gKi9cbmpRdWVyeS5ldmVudCA9IHtcblxuXHRnbG9iYWw6IHt9LFxuXG5cdGFkZDogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBkYXRhLCBzZWxlY3RvciApIHtcblxuXHRcdHZhciBoYW5kbGVPYmpJbiwgZXZlbnRIYW5kbGUsIHRtcCxcblx0XHRcdGV2ZW50cywgdCwgaGFuZGxlT2JqLFxuXHRcdFx0c3BlY2lhbCwgaGFuZGxlcnMsIHR5cGUsIG5hbWVzcGFjZXMsIG9yaWdUeXBlLFxuXHRcdFx0ZWxlbURhdGEgPSBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdC8vIERvbid0IGF0dGFjaCBldmVudHMgdG8gbm9EYXRhIG9yIHRleHQvY29tbWVudCBub2RlcyAoYnV0IGFsbG93IHBsYWluIG9iamVjdHMpXG5cdFx0aWYgKCAhZWxlbURhdGEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGVyIGNhbiBwYXNzIGluIGFuIG9iamVjdCBvZiBjdXN0b20gZGF0YSBpbiBsaWV1IG9mIHRoZSBoYW5kbGVyXG5cdFx0aWYgKCBoYW5kbGVyLmhhbmRsZXIgKSB7XG5cdFx0XHRoYW5kbGVPYmpJbiA9IGhhbmRsZXI7XG5cdFx0XHRoYW5kbGVyID0gaGFuZGxlT2JqSW4uaGFuZGxlcjtcblx0XHRcdHNlbGVjdG9yID0gaGFuZGxlT2JqSW4uc2VsZWN0b3I7XG5cdFx0fVxuXG5cdFx0Ly8gRW5zdXJlIHRoYXQgaW52YWxpZCBzZWxlY3RvcnMgdGhyb3cgZXhjZXB0aW9ucyBhdCBhdHRhY2ggdGltZVxuXHRcdC8vIEV2YWx1YXRlIGFnYWluc3QgZG9jdW1lbnRFbGVtZW50IGluIGNhc2UgZWxlbSBpcyBhIG5vbi1lbGVtZW50IG5vZGUgKGUuZy4sIGRvY3VtZW50KVxuXHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRqUXVlcnkuZmluZC5tYXRjaGVzU2VsZWN0b3IoIGRvY3VtZW50RWxlbWVudCwgc2VsZWN0b3IgKTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB0aGUgaGFuZGxlciBoYXMgYSB1bmlxdWUgSUQsIHVzZWQgdG8gZmluZC9yZW1vdmUgaXQgbGF0ZXJcblx0XHRpZiAoICFoYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRoYW5kbGVyLmd1aWQgPSBqUXVlcnkuZ3VpZCsrO1xuXHRcdH1cblxuXHRcdC8vIEluaXQgdGhlIGVsZW1lbnQncyBldmVudCBzdHJ1Y3R1cmUgYW5kIG1haW4gaGFuZGxlciwgaWYgdGhpcyBpcyB0aGUgZmlyc3Rcblx0XHRpZiAoICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0ZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzID0ge307XG5cdFx0fVxuXHRcdGlmICggISggZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgKSApIHtcblx0XHRcdGV2ZW50SGFuZGxlID0gZWxlbURhdGEuaGFuZGxlID0gZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdFx0Ly8gRGlzY2FyZCB0aGUgc2Vjb25kIGV2ZW50IG9mIGEgalF1ZXJ5LmV2ZW50LnRyaWdnZXIoKSBhbmRcblx0XHRcdFx0Ly8gd2hlbiBhbiBldmVudCBpcyBjYWxsZWQgYWZ0ZXIgYSBwYWdlIGhhcyB1bmxvYWRlZFxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICE9PSBlLnR5cGUgP1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5kaXNwYXRjaC5hcHBseSggZWxlbSwgYXJndW1lbnRzICkgOiB1bmRlZmluZWQ7XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIEhhbmRsZSBtdWx0aXBsZSBldmVudHMgc2VwYXJhdGVkIGJ5IGEgc3BhY2Vcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVGhlcmUgKm11c3QqIGJlIGEgdHlwZSwgbm8gYXR0YWNoaW5nIG5hbWVzcGFjZS1vbmx5IGhhbmRsZXJzXG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgZXZlbnQgY2hhbmdlcyBpdHMgdHlwZSwgdXNlIHRoZSBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgY2hhbmdlZCB0eXBlXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblxuXHRcdFx0Ly8gSWYgc2VsZWN0b3IgZGVmaW5lZCwgZGV0ZXJtaW5lIHNwZWNpYWwgZXZlbnQgYXBpIHR5cGUsIG90aGVyd2lzZSBnaXZlbiB0eXBlXG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cblx0XHRcdC8vIFVwZGF0ZSBzcGVjaWFsIGJhc2VkIG9uIG5ld2x5IHJlc2V0IHR5cGVcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXG5cdFx0XHQvLyBoYW5kbGVPYmogaXMgcGFzc2VkIHRvIGFsbCBldmVudCBoYW5kbGVyc1xuXHRcdFx0aGFuZGxlT2JqID0galF1ZXJ5LmV4dGVuZCgge1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRvcmlnVHlwZTogb3JpZ1R5cGUsXG5cdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdGhhbmRsZXI6IGhhbmRsZXIsXG5cdFx0XHRcdGd1aWQ6IGhhbmRsZXIuZ3VpZCxcblx0XHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0XHRuZWVkc0NvbnRleHQ6IHNlbGVjdG9yICYmIGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KCBzZWxlY3RvciApLFxuXHRcdFx0XHRuYW1lc3BhY2U6IG5hbWVzcGFjZXMuam9pbiggXCIuXCIgKVxuXHRcdFx0fSwgaGFuZGxlT2JqSW4gKTtcblxuXHRcdFx0Ly8gSW5pdCB0aGUgZXZlbnQgaGFuZGxlciBxdWV1ZSBpZiB3ZSdyZSB0aGUgZmlyc3Rcblx0XHRcdGlmICggISggaGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSApICkge1xuXHRcdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdID0gW107XG5cdFx0XHRcdGhhbmRsZXJzLmRlbGVnYXRlQ291bnQgPSAwO1xuXG5cdFx0XHRcdC8vIE9ubHkgdXNlIGFkZEV2ZW50TGlzdGVuZXIgaWYgdGhlIHNwZWNpYWwgZXZlbnRzIGhhbmRsZXIgcmV0dXJucyBmYWxzZVxuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnNldHVwIHx8XG5cdFx0XHRcdFx0c3BlY2lhbC5zZXR1cC5jYWxsKCBlbGVtLCBkYXRhLCBuYW1lc3BhY2VzLCBldmVudEhhbmRsZSApID09PSBmYWxzZSApIHtcblxuXHRcdFx0XHRcdGlmICggZWxlbS5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5hZGRFdmVudExpc3RlbmVyKCB0eXBlLCBldmVudEhhbmRsZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHNwZWNpYWwuYWRkICkge1xuXHRcdFx0XHRzcGVjaWFsLmFkZC5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblxuXHRcdFx0XHRpZiAoICFoYW5kbGVPYmouaGFuZGxlci5ndWlkICkge1xuXHRcdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyLmd1aWQgPSBoYW5kbGVyLmd1aWQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIHRvIHRoZSBlbGVtZW50J3MgaGFuZGxlciBsaXN0LCBkZWxlZ2F0ZXMgaW4gZnJvbnRcblx0XHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaGFuZGxlcnMuZGVsZWdhdGVDb3VudCsrLCAwLCBoYW5kbGVPYmogKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGhhbmRsZXJzLnB1c2goIGhhbmRsZU9iaiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBLZWVwIHRyYWNrIG9mIHdoaWNoIGV2ZW50cyBoYXZlIGV2ZXIgYmVlbiB1c2VkLCBmb3IgZXZlbnQgb3B0aW1pemF0aW9uXG5cdFx0XHRqUXVlcnkuZXZlbnQuZ2xvYmFsWyB0eXBlIF0gPSB0cnVlO1xuXHRcdH1cblxuXHR9LFxuXG5cdC8vIERldGFjaCBhbiBldmVudCBvciBzZXQgb2YgZXZlbnRzIGZyb20gYW4gZWxlbWVudFxuXHRyZW1vdmU6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlcywgaGFuZGxlciwgc2VsZWN0b3IsIG1hcHBlZFR5cGVzICkge1xuXG5cdFx0dmFyIGosIG9yaWdDb3VudCwgdG1wLFxuXHRcdFx0ZXZlbnRzLCB0LCBoYW5kbGVPYmosXG5cdFx0XHRzcGVjaWFsLCBoYW5kbGVycywgdHlwZSwgbmFtZXNwYWNlcywgb3JpZ1R5cGUsXG5cdFx0XHRlbGVtRGF0YSA9IGRhdGFQcml2Lmhhc0RhdGEoIGVsZW0gKSAmJiBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdGlmICggIWVsZW1EYXRhIHx8ICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIE9uY2UgZm9yIGVhY2ggdHlwZS5uYW1lc3BhY2UgaW4gdHlwZXM7IHR5cGUgbWF5IGJlIG9taXR0ZWRcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVW5iaW5kIGFsbCBldmVudHMgKG9uIHRoaXMgbmFtZXNwYWNlLCBpZiBwcm92aWRlZCkgZm9yIHRoZSBlbGVtZW50XG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCBlbGVtLCB0eXBlICsgdHlwZXNbIHQgXSwgaGFuZGxlciwgc2VsZWN0b3IsIHRydWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdIHx8IFtdO1xuXHRcdFx0dG1wID0gdG1wWyAyIF0gJiZcblx0XHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICk7XG5cblx0XHRcdC8vIFJlbW92ZSBtYXRjaGluZyBldmVudHNcblx0XHRcdG9yaWdDb3VudCA9IGogPSBoYW5kbGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGogXTtcblxuXHRcdFx0XHRpZiAoICggbWFwcGVkVHlwZXMgfHwgb3JpZ1R5cGUgPT09IGhhbmRsZU9iai5vcmlnVHlwZSApICYmXG5cdFx0XHRcdFx0KCAhaGFuZGxlciB8fCBoYW5kbGVyLmd1aWQgPT09IGhhbmRsZU9iai5ndWlkICkgJiZcblx0XHRcdFx0XHQoICF0bXAgfHwgdG1wLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApICYmXG5cdFx0XHRcdFx0KCAhc2VsZWN0b3IgfHwgc2VsZWN0b3IgPT09IGhhbmRsZU9iai5zZWxlY3RvciB8fFxuXHRcdFx0XHRcdFx0c2VsZWN0b3IgPT09IFwiKipcIiAmJiBoYW5kbGVPYmouc2VsZWN0b3IgKSApIHtcblx0XHRcdFx0XHRoYW5kbGVycy5zcGxpY2UoIGosIDEgKTtcblxuXHRcdFx0XHRcdGlmICggaGFuZGxlT2JqLnNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudC0tO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIHNwZWNpYWwucmVtb3ZlICkge1xuXHRcdFx0XHRcdFx0c3BlY2lhbC5yZW1vdmUuY2FsbCggZWxlbSwgaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlbW92ZSBnZW5lcmljIGV2ZW50IGhhbmRsZXIgaWYgd2UgcmVtb3ZlZCBzb21ldGhpbmcgYW5kIG5vIG1vcmUgaGFuZGxlcnMgZXhpc3Rcblx0XHRcdC8vIChhdm9pZHMgcG90ZW50aWFsIGZvciBlbmRsZXNzIHJlY3Vyc2lvbiBkdXJpbmcgcmVtb3ZhbCBvZiBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzKVxuXHRcdFx0aWYgKCBvcmlnQ291bnQgJiYgIWhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0aWYgKCAhc3BlY2lhbC50ZWFyZG93biB8fFxuXHRcdFx0XHRcdHNwZWNpYWwudGVhcmRvd24uY2FsbCggZWxlbSwgbmFtZXNwYWNlcywgZWxlbURhdGEuaGFuZGxlICkgPT09IGZhbHNlICkge1xuXG5cdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBlbGVtRGF0YS5oYW5kbGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlbGV0ZSBldmVudHNbIHR5cGUgXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgZGF0YSBhbmQgdGhlIGV4cGFuZG8gaWYgaXQncyBubyBsb25nZXIgdXNlZFxuXHRcdGlmICggalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGV2ZW50cyApICkge1xuXHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBlbGVtLCBcImhhbmRsZSBldmVudHNcIiApO1xuXHRcdH1cblx0fSxcblxuXHRkaXNwYXRjaDogZnVuY3Rpb24oIG5hdGl2ZUV2ZW50ICkge1xuXG5cdFx0Ly8gTWFrZSBhIHdyaXRhYmxlIGpRdWVyeS5FdmVudCBmcm9tIHRoZSBuYXRpdmUgZXZlbnQgb2JqZWN0XG5cdFx0dmFyIGV2ZW50ID0galF1ZXJ5LmV2ZW50LmZpeCggbmF0aXZlRXZlbnQgKTtcblxuXHRcdHZhciBpLCBqLCByZXQsIG1hdGNoZWQsIGhhbmRsZU9iaiwgaGFuZGxlclF1ZXVlLFxuXHRcdFx0YXJncyA9IG5ldyBBcnJheSggYXJndW1lbnRzLmxlbmd0aCApLFxuXHRcdFx0aGFuZGxlcnMgPSAoIGRhdGFQcml2LmdldCggdGhpcywgXCJldmVudHNcIiApIHx8IHt9IClbIGV2ZW50LnR5cGUgXSB8fCBbXSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZXZlbnQudHlwZSBdIHx8IHt9O1xuXG5cdFx0Ly8gVXNlIHRoZSBmaXgtZWQgalF1ZXJ5LkV2ZW50IHJhdGhlciB0aGFuIHRoZSAocmVhZC1vbmx5KSBuYXRpdmUgZXZlbnRcblx0XHRhcmdzWyAwIF0gPSBldmVudDtcblxuXHRcdGZvciAoIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0YXJnc1sgaSBdID0gYXJndW1lbnRzWyBpIF07XG5cdFx0fVxuXG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSB0aGlzO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgcHJlRGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlLCBhbmQgbGV0IGl0IGJhaWwgaWYgZGVzaXJlZFxuXHRcdGlmICggc3BlY2lhbC5wcmVEaXNwYXRjaCAmJiBzcGVjaWFsLnByZURpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBoYW5kbGVyc1xuXHRcdGhhbmRsZXJRdWV1ZSA9IGpRdWVyeS5ldmVudC5oYW5kbGVycy5jYWxsKCB0aGlzLCBldmVudCwgaGFuZGxlcnMgKTtcblxuXHRcdC8vIFJ1biBkZWxlZ2F0ZXMgZmlyc3Q7IHRoZXkgbWF5IHdhbnQgdG8gc3RvcCBwcm9wYWdhdGlvbiBiZW5lYXRoIHVzXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoIG1hdGNoZWQgPSBoYW5kbGVyUXVldWVbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cdFx0XHRldmVudC5jdXJyZW50VGFyZ2V0ID0gbWF0Y2hlZC5lbGVtO1xuXG5cdFx0XHRqID0gMDtcblx0XHRcdHdoaWxlICggKCBoYW5kbGVPYmogPSBtYXRjaGVkLmhhbmRsZXJzWyBqKysgXSApICYmXG5cdFx0XHRcdCFldmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpICkge1xuXG5cdFx0XHRcdC8vIFRyaWdnZXJlZCBldmVudCBtdXN0IGVpdGhlciAxKSBoYXZlIG5vIG5hbWVzcGFjZSwgb3IgMikgaGF2ZSBuYW1lc3BhY2Uocylcblx0XHRcdFx0Ly8gYSBzdWJzZXQgb3IgZXF1YWwgdG8gdGhvc2UgaW4gdGhlIGJvdW5kIGV2ZW50IChib3RoIGNhbiBoYXZlIG5vIG5hbWVzcGFjZSkuXG5cdFx0XHRcdGlmICggIWV2ZW50LnJuYW1lc3BhY2UgfHwgZXZlbnQucm5hbWVzcGFjZS50ZXN0KCBoYW5kbGVPYmoubmFtZXNwYWNlICkgKSB7XG5cblx0XHRcdFx0XHRldmVudC5oYW5kbGVPYmogPSBoYW5kbGVPYmo7XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSA9IGhhbmRsZU9iai5kYXRhO1xuXG5cdFx0XHRcdFx0cmV0ID0gKCAoIGpRdWVyeS5ldmVudC5zcGVjaWFsWyBoYW5kbGVPYmoub3JpZ1R5cGUgXSB8fCB7fSApLmhhbmRsZSB8fFxuXHRcdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIgKS5hcHBseSggbWF0Y2hlZC5lbGVtLCBhcmdzICk7XG5cblx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoIGV2ZW50LnJlc3VsdCA9IHJldCApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbCB0aGUgcG9zdERpc3BhdGNoIGhvb2sgZm9yIHRoZSBtYXBwZWQgdHlwZVxuXHRcdGlmICggc3BlY2lhbC5wb3N0RGlzcGF0Y2ggKSB7XG5cdFx0XHRzcGVjaWFsLnBvc3REaXNwYXRjaC5jYWxsKCB0aGlzLCBldmVudCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBldmVudC5yZXN1bHQ7XG5cdH0sXG5cblx0aGFuZGxlcnM6IGZ1bmN0aW9uKCBldmVudCwgaGFuZGxlcnMgKSB7XG5cdFx0dmFyIGksIGhhbmRsZU9iaiwgc2VsLCBtYXRjaGVkSGFuZGxlcnMsIG1hdGNoZWRTZWxlY3RvcnMsXG5cdFx0XHRoYW5kbGVyUXVldWUgPSBbXSxcblx0XHRcdGRlbGVnYXRlQ291bnQgPSBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LFxuXHRcdFx0Y3VyID0gZXZlbnQudGFyZ2V0O1xuXG5cdFx0Ly8gRmluZCBkZWxlZ2F0ZSBoYW5kbGVyc1xuXHRcdGlmICggZGVsZWdhdGVDb3VudCAmJlxuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTlcblx0XHRcdC8vIEJsYWNrLWhvbGUgU1ZHIDx1c2U+IGluc3RhbmNlIHRyZWVzICh0cmFjLTEzMTgwKVxuXHRcdFx0Y3VyLm5vZGVUeXBlICYmXG5cblx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggPD00MlxuXHRcdFx0Ly8gU3VwcHJlc3Mgc3BlYy12aW9sYXRpbmcgY2xpY2tzIGluZGljYXRpbmcgYSBub24tcHJpbWFyeSBwb2ludGVyIGJ1dHRvbiAodHJhYy0zODYxKVxuXHRcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnQtdHlwZS1jbGlja1xuXHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0Ly8gLi4uYnV0IG5vdCBhcnJvdyBrZXkgXCJjbGlja3NcIiBvZiByYWRpbyBpbnB1dHMsIHdoaWNoIGNhbiBoYXZlIGBidXR0b25gIC0xIChnaC0yMzQzKVxuXHRcdFx0ISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGV2ZW50LmJ1dHRvbiA+PSAxICkgKSB7XG5cblx0XHRcdGZvciAoIDsgY3VyICE9PSB0aGlzOyBjdXIgPSBjdXIucGFyZW50Tm9kZSB8fCB0aGlzICkge1xuXG5cdFx0XHRcdC8vIERvbid0IGNoZWNrIG5vbi1lbGVtZW50cyAoIzEzMjA4KVxuXHRcdFx0XHQvLyBEb24ndCBwcm9jZXNzIGNsaWNrcyBvbiBkaXNhYmxlZCBlbGVtZW50cyAoIzY5MTEsICM4MTY1LCAjMTEzODIsICMxMTc2NClcblx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPT09IDEgJiYgISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGN1ci5kaXNhYmxlZCA9PT0gdHJ1ZSApICkge1xuXHRcdFx0XHRcdG1hdGNoZWRIYW5kbGVycyA9IFtdO1xuXHRcdFx0XHRcdG1hdGNoZWRTZWxlY3RvcnMgPSB7fTtcblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGRlbGVnYXRlQ291bnQ7IGkrKyApIHtcblx0XHRcdFx0XHRcdGhhbmRsZU9iaiA9IGhhbmRsZXJzWyBpIF07XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IGNvbmZsaWN0IHdpdGggT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzICgjMTMyMDMpXG5cdFx0XHRcdFx0XHRzZWwgPSBoYW5kbGVPYmouc2VsZWN0b3IgKyBcIiBcIjtcblxuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9IGhhbmRsZU9iai5uZWVkc0NvbnRleHQgP1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggc2VsLCB0aGlzICkuaW5kZXgoIGN1ciApID4gLTEgOlxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kKCBzZWwsIHRoaXMsIG51bGwsIFsgY3VyIF0gKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkSGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggbWF0Y2hlZEhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdGhhbmRsZXJRdWV1ZS5wdXNoKCB7IGVsZW06IGN1ciwgaGFuZGxlcnM6IG1hdGNoZWRIYW5kbGVycyB9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIHRoZSByZW1haW5pbmcgKGRpcmVjdGx5LWJvdW5kKSBoYW5kbGVyc1xuXHRcdGN1ciA9IHRoaXM7XG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50IDwgaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goIHsgZWxlbTogY3VyLCBoYW5kbGVyczogaGFuZGxlcnMuc2xpY2UoIGRlbGVnYXRlQ291bnQgKSB9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGhhbmRsZXJRdWV1ZTtcblx0fSxcblxuXHRhZGRQcm9wOiBmdW5jdGlvbiggbmFtZSwgaG9vayApIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIGpRdWVyeS5FdmVudC5wcm90b3R5cGUsIG5hbWUsIHtcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cblx0XHRcdGdldDogalF1ZXJ5LmlzRnVuY3Rpb24oIGhvb2sgKSA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaG9vayggdGhpcy5vcmlnaW5hbEV2ZW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IDpcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnRbIG5hbWUgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cblx0XHRcdHNldDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIHRoaXMsIG5hbWUsIHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRmaXg6IGZ1bmN0aW9uKCBvcmlnaW5hbEV2ZW50ICkge1xuXHRcdHJldHVybiBvcmlnaW5hbEV2ZW50WyBqUXVlcnkuZXhwYW5kbyBdID9cblx0XHRcdG9yaWdpbmFsRXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggb3JpZ2luYWxFdmVudCApO1xuXHR9LFxuXG5cdHNwZWNpYWw6IHtcblx0XHRsb2FkOiB7XG5cblx0XHRcdC8vIFByZXZlbnQgdHJpZ2dlcmVkIGltYWdlLmxvYWQgZXZlbnRzIGZyb20gYnViYmxpbmcgdG8gd2luZG93LmxvYWRcblx0XHRcdG5vQnViYmxlOiB0cnVlXG5cdFx0fSxcblx0XHRmb2N1czoge1xuXG5cdFx0XHQvLyBGaXJlIG5hdGl2ZSBldmVudCBpZiBwb3NzaWJsZSBzbyBibHVyL2ZvY3VzIHNlcXVlbmNlIGlzIGNvcnJlY3Rcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMgIT09IHNhZmVBY3RpdmVFbGVtZW50KCkgJiYgdGhpcy5mb2N1cyApIHtcblx0XHRcdFx0XHR0aGlzLmZvY3VzKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3VzaW5cIlxuXHRcdH0sXG5cdFx0Ymx1cjoge1xuXHRcdFx0dHJpZ2dlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdGhpcyA9PT0gc2FmZUFjdGl2ZUVsZW1lbnQoKSAmJiB0aGlzLmJsdXIgKSB7XG5cdFx0XHRcdFx0dGhpcy5ibHVyKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3Vzb3V0XCJcblx0XHR9LFxuXHRcdGNsaWNrOiB7XG5cblx0XHRcdC8vIEZvciBjaGVja2JveCwgZmlyZSBuYXRpdmUgZXZlbnQgc28gY2hlY2tlZCBzdGF0ZSB3aWxsIGJlIHJpZ2h0XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzLnR5cGUgPT09IFwiY2hlY2tib3hcIiAmJiB0aGlzLmNsaWNrICYmIG5vZGVOYW1lKCB0aGlzLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR0aGlzLmNsaWNrKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGb3IgY3Jvc3MtYnJvd3NlciBjb25zaXN0ZW5jeSwgZG9uJ3QgZmlyZSBuYXRpdmUgLmNsaWNrKCkgb24gbGlua3Ncblx0XHRcdF9kZWZhdWx0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHJldHVybiBub2RlTmFtZSggZXZlbnQudGFyZ2V0LCBcImFcIiApO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRiZWZvcmV1bmxvYWQ6IHtcblx0XHRcdHBvc3REaXNwYXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggMjArXG5cdFx0XHRcdC8vIEZpcmVmb3ggZG9lc24ndCBhbGVydCBpZiB0aGUgcmV0dXJuVmFsdWUgZmllbGQgaXMgbm90IHNldC5cblx0XHRcdFx0aWYgKCBldmVudC5yZXN1bHQgIT09IHVuZGVmaW5lZCAmJiBldmVudC5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdGV2ZW50Lm9yaWdpbmFsRXZlbnQucmV0dXJuVmFsdWUgPSBldmVudC5yZXN1bHQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn07XG5cbmpRdWVyeS5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCBoYW5kbGUgKSB7XG5cblx0Ly8gVGhpcyBcImlmXCIgaXMgbmVlZGVkIGZvciBwbGFpbiBvYmplY3RzXG5cdGlmICggZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyICkge1xuXHRcdGVsZW0ucmVtb3ZlRXZlbnRMaXN0ZW5lciggdHlwZSwgaGFuZGxlICk7XG5cdH1cbn07XG5cbmpRdWVyeS5FdmVudCA9IGZ1bmN0aW9uKCBzcmMsIHByb3BzICkge1xuXG5cdC8vIEFsbG93IGluc3RhbnRpYXRpb24gd2l0aG91dCB0aGUgJ25ldycga2V5d29yZFxuXHRpZiAoICEoIHRoaXMgaW5zdGFuY2VvZiBqUXVlcnkuRXZlbnQgKSApIHtcblx0XHRyZXR1cm4gbmV3IGpRdWVyeS5FdmVudCggc3JjLCBwcm9wcyApO1xuXHR9XG5cblx0Ly8gRXZlbnQgb2JqZWN0XG5cdGlmICggc3JjICYmIHNyYy50eXBlICkge1xuXHRcdHRoaXMub3JpZ2luYWxFdmVudCA9IHNyYztcblx0XHR0aGlzLnR5cGUgPSBzcmMudHlwZTtcblxuXHRcdC8vIEV2ZW50cyBidWJibGluZyB1cCB0aGUgZG9jdW1lbnQgbWF5IGhhdmUgYmVlbiBtYXJrZWQgYXMgcHJldmVudGVkXG5cdFx0Ly8gYnkgYSBoYW5kbGVyIGxvd2VyIGRvd24gdGhlIHRyZWU7IHJlZmxlY3QgdGhlIGNvcnJlY3QgdmFsdWUuXG5cdFx0dGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBzcmMuZGVmYXVsdFByZXZlbnRlZCB8fFxuXHRcdFx0XHRzcmMuZGVmYXVsdFByZXZlbnRlZCA9PT0gdW5kZWZpbmVkICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTIuMyBvbmx5XG5cdFx0XHRcdHNyYy5yZXR1cm5WYWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0cmV0dXJuVHJ1ZSA6XG5cdFx0XHRyZXR1cm5GYWxzZTtcblxuXHRcdC8vIENyZWF0ZSB0YXJnZXQgcHJvcGVydGllc1xuXHRcdC8vIFN1cHBvcnQ6IFNhZmFyaSA8PTYgLSA3IG9ubHlcblx0XHQvLyBUYXJnZXQgc2hvdWxkIG5vdCBiZSBhIHRleHQgbm9kZSAoIzUwNCwgIzEzMTQzKVxuXHRcdHRoaXMudGFyZ2V0ID0gKCBzcmMudGFyZ2V0ICYmIHNyYy50YXJnZXQubm9kZVR5cGUgPT09IDMgKSA/XG5cdFx0XHRzcmMudGFyZ2V0LnBhcmVudE5vZGUgOlxuXHRcdFx0c3JjLnRhcmdldDtcblxuXHRcdHRoaXMuY3VycmVudFRhcmdldCA9IHNyYy5jdXJyZW50VGFyZ2V0O1xuXHRcdHRoaXMucmVsYXRlZFRhcmdldCA9IHNyYy5yZWxhdGVkVGFyZ2V0O1xuXG5cdC8vIEV2ZW50IHR5cGVcblx0fSBlbHNlIHtcblx0XHR0aGlzLnR5cGUgPSBzcmM7XG5cdH1cblxuXHQvLyBQdXQgZXhwbGljaXRseSBwcm92aWRlZCBwcm9wZXJ0aWVzIG9udG8gdGhlIGV2ZW50IG9iamVjdFxuXHRpZiAoIHByb3BzICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRoaXMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSB0aW1lc3RhbXAgaWYgaW5jb21pbmcgZXZlbnQgZG9lc24ndCBoYXZlIG9uZVxuXHR0aGlzLnRpbWVTdGFtcCA9IHNyYyAmJiBzcmMudGltZVN0YW1wIHx8IGpRdWVyeS5ub3coKTtcblxuXHQvLyBNYXJrIGl0IGFzIGZpeGVkXG5cdHRoaXNbIGpRdWVyeS5leHBhbmRvIF0gPSB0cnVlO1xufTtcblxuLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nXG4vLyBodHRwczovL3d3dy53My5vcmcvVFIvMjAwMy9XRC1ET00tTGV2ZWwtMy1FdmVudHMtMjAwMzAzMzEvZWNtYS1zY3JpcHQtYmluZGluZy5odG1sXG5qUXVlcnkuRXZlbnQucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LkV2ZW50LFxuXHRpc0RlZmF1bHRQcmV2ZW50ZWQ6IHJldHVybkZhbHNlLFxuXHRpc1Byb3BhZ2F0aW9uU3RvcHBlZDogcmV0dXJuRmFsc2UsXG5cdGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNTaW11bGF0ZWQ6IGZhbHNlLFxuXG5cdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9LFxuXHRzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0dGhpcy5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9IHJldHVyblRydWU7XG5cblx0XHRpZiAoIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgKSB7XG5cdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdH1cblxuXHRcdHRoaXMuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdH1cbn07XG5cbi8vIEluY2x1ZGVzIGFsbCBjb21tb24gZXZlbnQgcHJvcHMgaW5jbHVkaW5nIEtleUV2ZW50IGFuZCBNb3VzZUV2ZW50IHNwZWNpZmljIHByb3BzXG5qUXVlcnkuZWFjaCgge1xuXHRhbHRLZXk6IHRydWUsXG5cdGJ1YmJsZXM6IHRydWUsXG5cdGNhbmNlbGFibGU6IHRydWUsXG5cdGNoYW5nZWRUb3VjaGVzOiB0cnVlLFxuXHRjdHJsS2V5OiB0cnVlLFxuXHRkZXRhaWw6IHRydWUsXG5cdGV2ZW50UGhhc2U6IHRydWUsXG5cdG1ldGFLZXk6IHRydWUsXG5cdHBhZ2VYOiB0cnVlLFxuXHRwYWdlWTogdHJ1ZSxcblx0c2hpZnRLZXk6IHRydWUsXG5cdHZpZXc6IHRydWUsXG5cdFwiY2hhclwiOiB0cnVlLFxuXHRjaGFyQ29kZTogdHJ1ZSxcblx0a2V5OiB0cnVlLFxuXHRrZXlDb2RlOiB0cnVlLFxuXHRidXR0b246IHRydWUsXG5cdGJ1dHRvbnM6IHRydWUsXG5cdGNsaWVudFg6IHRydWUsXG5cdGNsaWVudFk6IHRydWUsXG5cdG9mZnNldFg6IHRydWUsXG5cdG9mZnNldFk6IHRydWUsXG5cdHBvaW50ZXJJZDogdHJ1ZSxcblx0cG9pbnRlclR5cGU6IHRydWUsXG5cdHNjcmVlblg6IHRydWUsXG5cdHNjcmVlblk6IHRydWUsXG5cdHRhcmdldFRvdWNoZXM6IHRydWUsXG5cdHRvRWxlbWVudDogdHJ1ZSxcblx0dG91Y2hlczogdHJ1ZSxcblxuXHR3aGljaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdHZhciBidXR0b24gPSBldmVudC5idXR0b247XG5cblx0XHQvLyBBZGQgd2hpY2ggZm9yIGtleSBldmVudHNcblx0XHRpZiAoIGV2ZW50LndoaWNoID09IG51bGwgJiYgcmtleUV2ZW50LnRlc3QoIGV2ZW50LnR5cGUgKSApIHtcblx0XHRcdHJldHVybiBldmVudC5jaGFyQ29kZSAhPSBudWxsID8gZXZlbnQuY2hhckNvZGUgOiBldmVudC5rZXlDb2RlO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB3aGljaCBmb3IgY2xpY2s6IDEgPT09IGxlZnQ7IDIgPT09IG1pZGRsZTsgMyA9PT0gcmlnaHRcblx0XHRpZiAoICFldmVudC53aGljaCAmJiBidXR0b24gIT09IHVuZGVmaW5lZCAmJiBybW91c2VFdmVudC50ZXN0KCBldmVudC50eXBlICkgKSB7XG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDEgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDIgKSB7XG5cdFx0XHRcdHJldHVybiAzO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDQgKSB7XG5cdFx0XHRcdHJldHVybiAyO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnQud2hpY2g7XG5cdH1cbn0sIGpRdWVyeS5ldmVudC5hZGRQcm9wICk7XG5cbi8vIENyZWF0ZSBtb3VzZWVudGVyL2xlYXZlIGV2ZW50cyB1c2luZyBtb3VzZW92ZXIvb3V0IGFuZCBldmVudC10aW1lIGNoZWNrc1xuLy8gc28gdGhhdCBldmVudCBkZWxlZ2F0aW9uIHdvcmtzIGluIGpRdWVyeS5cbi8vIERvIHRoZSBzYW1lIGZvciBwb2ludGVyZW50ZXIvcG9pbnRlcmxlYXZlIGFuZCBwb2ludGVyb3Zlci9wb2ludGVyb3V0XG4vL1xuLy8gU3VwcG9ydDogU2FmYXJpIDcgb25seVxuLy8gU2FmYXJpIHNlbmRzIG1vdXNlZW50ZXIgdG9vIG9mdGVuOyBzZWU6XG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NzAyNThcbi8vIGZvciB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGJ1ZyAoaXQgZXhpc3RlZCBpbiBvbGRlciBDaHJvbWUgdmVyc2lvbnMgYXMgd2VsbCkuXG5qUXVlcnkuZWFjaCgge1xuXHRtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuXHRtb3VzZWxlYXZlOiBcIm1vdXNlb3V0XCIsXG5cdHBvaW50ZXJlbnRlcjogXCJwb2ludGVyb3ZlclwiLFxuXHRwb2ludGVybGVhdmU6IFwicG9pbnRlcm91dFwiXG59LCBmdW5jdGlvbiggb3JpZywgZml4ICkge1xuXHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgb3JpZyBdID0ge1xuXHRcdGRlbGVnYXRlVHlwZTogZml4LFxuXHRcdGJpbmRUeXBlOiBmaXgsXG5cblx0XHRoYW5kbGU6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdHZhciByZXQsXG5cdFx0XHRcdHRhcmdldCA9IHRoaXMsXG5cdFx0XHRcdHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0LFxuXHRcdFx0XHRoYW5kbGVPYmogPSBldmVudC5oYW5kbGVPYmo7XG5cblx0XHRcdC8vIEZvciBtb3VzZWVudGVyL2xlYXZlIGNhbGwgdGhlIGhhbmRsZXIgaWYgcmVsYXRlZCBpcyBvdXRzaWRlIHRoZSB0YXJnZXQuXG5cdFx0XHQvLyBOQjogTm8gcmVsYXRlZFRhcmdldCBpZiB0aGUgbW91c2UgbGVmdC9lbnRlcmVkIHRoZSBicm93c2VyIHdpbmRvd1xuXHRcdFx0aWYgKCAhcmVsYXRlZCB8fCAoIHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhalF1ZXJ5LmNvbnRhaW5zKCB0YXJnZXQsIHJlbGF0ZWQgKSApICkge1xuXHRcdFx0XHRldmVudC50eXBlID0gaGFuZGxlT2JqLm9yaWdUeXBlO1xuXHRcdFx0XHRyZXQgPSBoYW5kbGVPYmouaGFuZGxlci5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBmaXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXG5cdG9uOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4gKTtcblx0fSxcblx0b25lOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4sIDEgKTtcblx0fSxcblx0b2ZmOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBmbiApIHtcblx0XHR2YXIgaGFuZGxlT2JqLCB0eXBlO1xuXHRcdGlmICggdHlwZXMgJiYgdHlwZXMucHJldmVudERlZmF1bHQgJiYgdHlwZXMuaGFuZGxlT2JqICkge1xuXG5cdFx0XHQvLyAoIGV2ZW50ICkgIGRpc3BhdGNoZWQgalF1ZXJ5LkV2ZW50XG5cdFx0XHRoYW5kbGVPYmogPSB0eXBlcy5oYW5kbGVPYmo7XG5cdFx0XHRqUXVlcnkoIHR5cGVzLmRlbGVnYXRlVGFyZ2V0ICkub2ZmKFxuXHRcdFx0XHRoYW5kbGVPYmoubmFtZXNwYWNlID9cblx0XHRcdFx0XHRoYW5kbGVPYmoub3JpZ1R5cGUgKyBcIi5cIiArIGhhbmRsZU9iai5uYW1lc3BhY2UgOlxuXHRcdFx0XHRcdGhhbmRsZU9iai5vcmlnVHlwZSxcblx0XHRcdFx0aGFuZGxlT2JqLnNlbGVjdG9yLFxuXHRcdFx0XHRoYW5kbGVPYmouaGFuZGxlclxuXHRcdFx0KTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcy1vYmplY3QgWywgc2VsZWN0b3JdIClcblx0XHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRcdHRoaXMub2ZmKCB0eXBlLCBzZWxlY3RvciwgdHlwZXNbIHR5cGUgXSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggc2VsZWN0b3IgPT09IGZhbHNlIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICkge1xuXG5cdFx0XHQvLyAoIHR5cGVzIFssIGZuXSApXG5cdFx0XHRmbiA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGlmICggZm4gPT09IGZhbHNlICkge1xuXHRcdFx0Zm4gPSByZXR1cm5GYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCB0aGlzLCB0eXBlcywgZm4sIHNlbGVjdG9yICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxudmFyXG5cblx0LyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuXG5cdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZXNsaW50L2VzbGludC9pc3N1ZXMvMzIyOVxuXHRyeGh0bWxUYWcgPSAvPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbYS16XVteXFwvXFwwPlxceDIwXFx0XFxyXFxuXFxmXSopW14+XSopXFwvPi9naSxcblxuXHQvKiBlc2xpbnQtZW5hYmxlICovXG5cblx0Ly8gU3VwcG9ydDogSUUgPD0xMCAtIDExLCBFZGdlIDEyIC0gMTNcblx0Ly8gSW4gSUUvRWRnZSB1c2luZyByZWdleCBncm91cHMgaGVyZSBjYXVzZXMgc2V2ZXJlIHNsb3dkb3ducy5cblx0Ly8gU2VlIGh0dHBzOi8vY29ubmVjdC5taWNyb3NvZnQuY29tL0lFL2ZlZWRiYWNrL2RldGFpbHMvMTczNjUxMi9cblx0cm5vSW5uZXJodG1sID0gLzxzY3JpcHR8PHN0eWxlfDxsaW5rL2ksXG5cblx0Ly8gY2hlY2tlZD1cImNoZWNrZWRcIiBvciBjaGVja2VkXG5cdHJjaGVja2VkID0gL2NoZWNrZWRcXHMqKD86W149XXw9XFxzKi5jaGVja2VkLikvaSxcblx0cnNjcmlwdFR5cGVNYXNrZWQgPSAvXnRydWVcXC8oLiopLyxcblx0cmNsZWFuU2NyaXB0ID0gL15cXHMqPCEoPzpcXFtDREFUQVxcW3wtLSl8KD86XFxdXFxdfC0tKT5cXHMqJC9nO1xuXG4vLyBQcmVmZXIgYSB0Ym9keSBvdmVyIGl0cyBwYXJlbnQgdGFibGUgZm9yIGNvbnRhaW5pbmcgbmV3IHJvd3NcbmZ1bmN0aW9uIG1hbmlwdWxhdGlvblRhcmdldCggZWxlbSwgY29udGVudCApIHtcblx0aWYgKCBub2RlTmFtZSggZWxlbSwgXCJ0YWJsZVwiICkgJiZcblx0XHRub2RlTmFtZSggY29udGVudC5ub2RlVHlwZSAhPT0gMTEgPyBjb250ZW50IDogY29udGVudC5maXJzdENoaWxkLCBcInRyXCIgKSApIHtcblxuXHRcdHJldHVybiBqUXVlcnkoIFwiPnRib2R5XCIsIGVsZW0gKVsgMCBdIHx8IGVsZW07XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxuLy8gUmVwbGFjZS9yZXN0b3JlIHRoZSB0eXBlIGF0dHJpYnV0ZSBvZiBzY3JpcHQgZWxlbWVudHMgZm9yIHNhZmUgRE9NIG1hbmlwdWxhdGlvblxuZnVuY3Rpb24gZGlzYWJsZVNjcmlwdCggZWxlbSApIHtcblx0ZWxlbS50eXBlID0gKCBlbGVtLmdldEF0dHJpYnV0ZSggXCJ0eXBlXCIgKSAhPT0gbnVsbCApICsgXCIvXCIgKyBlbGVtLnR5cGU7XG5cdHJldHVybiBlbGVtO1xufVxuZnVuY3Rpb24gcmVzdG9yZVNjcmlwdCggZWxlbSApIHtcblx0dmFyIG1hdGNoID0gcnNjcmlwdFR5cGVNYXNrZWQuZXhlYyggZWxlbS50eXBlICk7XG5cblx0aWYgKCBtYXRjaCApIHtcblx0XHRlbGVtLnR5cGUgPSBtYXRjaFsgMSBdO1xuXHR9IGVsc2Uge1xuXHRcdGVsZW0ucmVtb3ZlQXR0cmlidXRlKCBcInR5cGVcIiApO1xuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmZ1bmN0aW9uIGNsb25lQ29weUV2ZW50KCBzcmMsIGRlc3QgKSB7XG5cdHZhciBpLCBsLCB0eXBlLCBwZGF0YU9sZCwgcGRhdGFDdXIsIHVkYXRhT2xkLCB1ZGF0YUN1ciwgZXZlbnRzO1xuXG5cdGlmICggZGVzdC5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyAxLiBDb3B5IHByaXZhdGUgZGF0YTogZXZlbnRzLCBoYW5kbGVycywgZXRjLlxuXHRpZiAoIGRhdGFQcml2Lmhhc0RhdGEoIHNyYyApICkge1xuXHRcdHBkYXRhT2xkID0gZGF0YVByaXYuYWNjZXNzKCBzcmMgKTtcblx0XHRwZGF0YUN1ciA9IGRhdGFQcml2LnNldCggZGVzdCwgcGRhdGFPbGQgKTtcblx0XHRldmVudHMgPSBwZGF0YU9sZC5ldmVudHM7XG5cblx0XHRpZiAoIGV2ZW50cyApIHtcblx0XHRcdGRlbGV0ZSBwZGF0YUN1ci5oYW5kbGU7XG5cdFx0XHRwZGF0YUN1ci5ldmVudHMgPSB7fTtcblxuXHRcdFx0Zm9yICggdHlwZSBpbiBldmVudHMgKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwLCBsID0gZXZlbnRzWyB0eXBlIF0ubGVuZ3RoOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5hZGQoIGRlc3QsIHR5cGUsIGV2ZW50c1sgdHlwZSBdWyBpIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIDIuIENvcHkgdXNlciBkYXRhXG5cdGlmICggZGF0YVVzZXIuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0dWRhdGFPbGQgPSBkYXRhVXNlci5hY2Nlc3MoIHNyYyApO1xuXHRcdHVkYXRhQ3VyID0galF1ZXJ5LmV4dGVuZCgge30sIHVkYXRhT2xkICk7XG5cblx0XHRkYXRhVXNlci5zZXQoIGRlc3QsIHVkYXRhQ3VyICk7XG5cdH1cbn1cblxuLy8gRml4IElFIGJ1Z3MsIHNlZSBzdXBwb3J0IHRlc3RzXG5mdW5jdGlvbiBmaXhJbnB1dCggc3JjLCBkZXN0ICkge1xuXHR2YXIgbm9kZU5hbWUgPSBkZXN0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0Ly8gRmFpbHMgdG8gcGVyc2lzdCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiBhIGNsb25lZCBjaGVja2JveCBvciByYWRpbyBidXR0b24uXG5cdGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiByY2hlY2thYmxlVHlwZS50ZXN0KCBzcmMudHlwZSApICkge1xuXHRcdGRlc3QuY2hlY2tlZCA9IHNyYy5jaGVja2VkO1xuXG5cdC8vIEZhaWxzIHRvIHJldHVybiB0aGUgc2VsZWN0ZWQgb3B0aW9uIHRvIHRoZSBkZWZhdWx0IHNlbGVjdGVkIHN0YXRlIHdoZW4gY2xvbmluZyBvcHRpb25zXG5cdH0gZWxzZSBpZiAoIG5vZGVOYW1lID09PSBcImlucHV0XCIgfHwgbm9kZU5hbWUgPT09IFwidGV4dGFyZWFcIiApIHtcblx0XHRkZXN0LmRlZmF1bHRWYWx1ZSA9IHNyYy5kZWZhdWx0VmFsdWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gZG9tTWFuaXAoIGNvbGxlY3Rpb24sIGFyZ3MsIGNhbGxiYWNrLCBpZ25vcmVkICkge1xuXG5cdC8vIEZsYXR0ZW4gYW55IG5lc3RlZCBhcnJheXNcblx0YXJncyA9IGNvbmNhdC5hcHBseSggW10sIGFyZ3MgKTtcblxuXHR2YXIgZnJhZ21lbnQsIGZpcnN0LCBzY3JpcHRzLCBoYXNTY3JpcHRzLCBub2RlLCBkb2MsXG5cdFx0aSA9IDAsXG5cdFx0bCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuXHRcdGlOb0Nsb25lID0gbCAtIDEsXG5cdFx0dmFsdWUgPSBhcmdzWyAwIF0sXG5cdFx0aXNGdW5jdGlvbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApO1xuXG5cdC8vIFdlIGNhbid0IGNsb25lTm9kZSBmcmFnbWVudHMgdGhhdCBjb250YWluIGNoZWNrZWQsIGluIFdlYktpdFxuXHRpZiAoIGlzRnVuY3Rpb24gfHxcblx0XHRcdCggbCA+IDEgJiYgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmXG5cdFx0XHRcdCFzdXBwb3J0LmNoZWNrQ2xvbmUgJiYgcmNoZWNrZWQudGVzdCggdmFsdWUgKSApICkge1xuXHRcdHJldHVybiBjb2xsZWN0aW9uLmVhY2goIGZ1bmN0aW9uKCBpbmRleCApIHtcblx0XHRcdHZhciBzZWxmID0gY29sbGVjdGlvbi5lcSggaW5kZXggKTtcblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0YXJnc1sgMCBdID0gdmFsdWUuY2FsbCggdGhpcywgaW5kZXgsIHNlbGYuaHRtbCgpICk7XG5cdFx0XHR9XG5cdFx0XHRkb21NYW5pcCggc2VsZiwgYXJncywgY2FsbGJhY2ssIGlnbm9yZWQgKTtcblx0XHR9ICk7XG5cdH1cblxuXHRpZiAoIGwgKSB7XG5cdFx0ZnJhZ21lbnQgPSBidWlsZEZyYWdtZW50KCBhcmdzLCBjb2xsZWN0aW9uWyAwIF0ub3duZXJEb2N1bWVudCwgZmFsc2UsIGNvbGxlY3Rpb24sIGlnbm9yZWQgKTtcblx0XHRmaXJzdCA9IGZyYWdtZW50LmZpcnN0Q2hpbGQ7XG5cblx0XHRpZiAoIGZyYWdtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAxICkge1xuXHRcdFx0ZnJhZ21lbnQgPSBmaXJzdDtcblx0XHR9XG5cblx0XHQvLyBSZXF1aXJlIGVpdGhlciBuZXcgY29udGVudCBvciBhbiBpbnRlcmVzdCBpbiBpZ25vcmVkIGVsZW1lbnRzIHRvIGludm9rZSB0aGUgY2FsbGJhY2tcblx0XHRpZiAoIGZpcnN0IHx8IGlnbm9yZWQgKSB7XG5cdFx0XHRzY3JpcHRzID0galF1ZXJ5Lm1hcCggZ2V0QWxsKCBmcmFnbWVudCwgXCJzY3JpcHRcIiApLCBkaXNhYmxlU2NyaXB0ICk7XG5cdFx0XHRoYXNTY3JpcHRzID0gc2NyaXB0cy5sZW5ndGg7XG5cblx0XHRcdC8vIFVzZSB0aGUgb3JpZ2luYWwgZnJhZ21lbnQgZm9yIHRoZSBsYXN0IGl0ZW1cblx0XHRcdC8vIGluc3RlYWQgb2YgdGhlIGZpcnN0IGJlY2F1c2UgaXQgY2FuIGVuZCB1cFxuXHRcdFx0Ly8gYmVpbmcgZW1wdGllZCBpbmNvcnJlY3RseSBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgKCM4MDcwKS5cblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0bm9kZSA9IGZyYWdtZW50O1xuXG5cdFx0XHRcdGlmICggaSAhPT0gaU5vQ2xvbmUgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IGpRdWVyeS5jbG9uZSggbm9kZSwgdHJ1ZSwgdHJ1ZSApO1xuXG5cdFx0XHRcdFx0Ly8gS2VlcCByZWZlcmVuY2VzIHRvIGNsb25lZCBzY3JpcHRzIGZvciBsYXRlciByZXN0b3JhdGlvblxuXHRcdFx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIHNjcmlwdHMsIGdldEFsbCggbm9kZSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FsbGJhY2suY2FsbCggY29sbGVjdGlvblsgaSBdLCBub2RlLCBpICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblx0XHRcdFx0ZG9jID0gc2NyaXB0c1sgc2NyaXB0cy5sZW5ndGggLSAxIF0ub3duZXJEb2N1bWVudDtcblxuXHRcdFx0XHQvLyBSZWVuYWJsZSBzY3JpcHRzXG5cdFx0XHRcdGpRdWVyeS5tYXAoIHNjcmlwdHMsIHJlc3RvcmVTY3JpcHQgKTtcblxuXHRcdFx0XHQvLyBFdmFsdWF0ZSBleGVjdXRhYmxlIHNjcmlwdHMgb24gZmlyc3QgZG9jdW1lbnQgaW5zZXJ0aW9uXG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgaGFzU2NyaXB0czsgaSsrICkge1xuXHRcdFx0XHRcdG5vZGUgPSBzY3JpcHRzWyBpIF07XG5cdFx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBub2RlLnR5cGUgfHwgXCJcIiApICYmXG5cdFx0XHRcdFx0XHQhZGF0YVByaXYuYWNjZXNzKCBub2RlLCBcImdsb2JhbEV2YWxcIiApICYmXG5cdFx0XHRcdFx0XHRqUXVlcnkuY29udGFpbnMoIGRvYywgbm9kZSApICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIG5vZGUuc3JjICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIE9wdGlvbmFsIEFKQVggZGVwZW5kZW5jeSwgYnV0IHdvbid0IHJ1biBzY3JpcHRzIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5Ll9ldmFsVXJsICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5fZXZhbFVybCggbm9kZS5zcmMgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0RE9NRXZhbCggbm9kZS50ZXh0Q29udGVudC5yZXBsYWNlKCByY2xlYW5TY3JpcHQsIFwiXCIgKSwgZG9jICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGNvbGxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSggZWxlbSwgc2VsZWN0b3IsIGtlZXBEYXRhICkge1xuXHR2YXIgbm9kZSxcblx0XHRub2RlcyA9IHNlbGVjdG9yID8galF1ZXJ5LmZpbHRlciggc2VsZWN0b3IsIGVsZW0gKSA6IGVsZW0sXG5cdFx0aSA9IDA7XG5cblx0Zm9yICggOyAoIG5vZGUgPSBub2Rlc1sgaSBdICkgIT0gbnVsbDsgaSsrICkge1xuXHRcdGlmICggIWtlZXBEYXRhICYmIG5vZGUubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIG5vZGUgKSApO1xuXHRcdH1cblxuXHRcdGlmICggbm9kZS5wYXJlbnROb2RlICkge1xuXHRcdFx0aWYgKCBrZWVwRGF0YSAmJiBqUXVlcnkuY29udGFpbnMoIG5vZGUub3duZXJEb2N1bWVudCwgbm9kZSApICkge1xuXHRcdFx0XHRzZXRHbG9iYWxFdmFsKCBnZXRBbGwoIG5vZGUsIFwic2NyaXB0XCIgKSApO1xuXHRcdFx0fVxuXHRcdFx0bm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBub2RlICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aHRtbFByZWZpbHRlcjogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0cmV0dXJuIGh0bWwucmVwbGFjZSggcnhodG1sVGFnLCBcIjwkMT48LyQyPlwiICk7XG5cdH0sXG5cblx0Y2xvbmU6IGZ1bmN0aW9uKCBlbGVtLCBkYXRhQW5kRXZlbnRzLCBkZWVwRGF0YUFuZEV2ZW50cyApIHtcblx0XHR2YXIgaSwgbCwgc3JjRWxlbWVudHMsIGRlc3RFbGVtZW50cyxcblx0XHRcdGNsb25lID0gZWxlbS5jbG9uZU5vZGUoIHRydWUgKSxcblx0XHRcdGluUGFnZSA9IGpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICk7XG5cblx0XHQvLyBGaXggSUUgY2xvbmluZyBpc3N1ZXNcblx0XHRpZiAoICFzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkICYmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBlbGVtLm5vZGVUeXBlID09PSAxMSApICYmXG5cdFx0XHRcdCFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblxuXHRcdFx0Ly8gV2UgZXNjaGV3IFNpenpsZSBoZXJlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zOiBodHRwczovL2pzcGVyZi5jb20vZ2V0YWxsLXZzLXNpenpsZS8yXG5cdFx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lICk7XG5cdFx0XHRzcmNFbGVtZW50cyA9IGdldEFsbCggZWxlbSApO1xuXG5cdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0Zml4SW5wdXQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ29weSB0aGUgZXZlbnRzIGZyb20gdGhlIG9yaWdpbmFsIHRvIHRoZSBjbG9uZVxuXHRcdGlmICggZGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdGlmICggZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0XHRcdHNyY0VsZW1lbnRzID0gc3JjRWxlbWVudHMgfHwgZ2V0QWxsKCBlbGVtICk7XG5cdFx0XHRcdGRlc3RFbGVtZW50cyA9IGRlc3RFbGVtZW50cyB8fCBnZXRBbGwoIGNsb25lICk7XG5cblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBzcmNFbGVtZW50cy5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNsb25lQ29weUV2ZW50KCBlbGVtLCBjbG9uZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIHNjcmlwdCBldmFsdWF0aW9uIGhpc3Rvcnlcblx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lLCBcInNjcmlwdFwiICk7XG5cdFx0aWYgKCBkZXN0RWxlbWVudHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIGRlc3RFbGVtZW50cywgIWluUGFnZSAmJiBnZXRBbGwoIGVsZW0sIFwic2NyaXB0XCIgKSApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0aGUgY2xvbmVkIHNldFxuXHRcdHJldHVybiBjbG9uZTtcblx0fSxcblxuXHRjbGVhbkRhdGE6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblx0XHR2YXIgZGF0YSwgZWxlbSwgdHlwZSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbCxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoIGVsZW0gPSBlbGVtc1sgaSBdICkgIT09IHVuZGVmaW5lZDsgaSsrICkge1xuXHRcdFx0aWYgKCBhY2NlcHREYXRhKCBlbGVtICkgKSB7XG5cdFx0XHRcdGlmICggKCBkYXRhID0gZWxlbVsgZGF0YVByaXYuZXhwYW5kbyBdICkgKSB7XG5cdFx0XHRcdFx0aWYgKCBkYXRhLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdGZvciAoIHR5cGUgaW4gZGF0YS5ldmVudHMgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbFsgdHlwZSBdICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIGVsZW0sIHR5cGUgKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYXZvaWQgalF1ZXJ5LmV2ZW50LnJlbW92ZSdzIG92ZXJoZWFkXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBkYXRhLmhhbmRsZSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NStcblx0XHRcdFx0XHQvLyBBc3NpZ24gdW5kZWZpbmVkIGluc3RlYWQgb2YgdXNpbmcgZGVsZXRlLCBzZWUgRGF0YSNyZW1vdmVcblx0XHRcdFx0XHRlbGVtWyBkYXRhUHJpdi5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBlbGVtWyBkYXRhVXNlci5leHBhbmRvIF0gKSB7XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1K1xuXHRcdFx0XHRcdC8vIEFzc2lnbiB1bmRlZmluZWQgaW5zdGVhZCBvZiB1c2luZyBkZWxldGUsIHNlZSBEYXRhI3JlbW92ZVxuXHRcdFx0XHRcdGVsZW1bIGRhdGFVc2VyLmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRldGFjaDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiByZW1vdmUoIHRoaXMsIHNlbGVjdG9yLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHJlbW92ZSggdGhpcywgc2VsZWN0b3IgKTtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkudGV4dCggdGhpcyApIDpcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdFx0dGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0YXBwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0dmFyIHRhcmdldCA9IG1hbmlwdWxhdGlvblRhcmdldCggdGhpcywgZWxlbSApO1xuXHRcdFx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0cHJlcGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBtYW5pcHVsYXRpb25UYXJnZXQoIHRoaXMsIGVsZW0gKTtcblx0XHRcdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSggZWxlbSwgdGFyZ2V0LmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0YmVmb3JlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRhZnRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoIGVsZW0sIHRoaXMubmV4dFNpYmxpbmcgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0ZW1wdHk6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7ICggZWxlbSA9IHRoaXNbIGkgXSApICE9IG51bGw7IGkrKyApIHtcblx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHQvLyBQcmV2ZW50IG1lbW9yeSBsZWFrc1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIGVsZW0sIGZhbHNlICkgKTtcblxuXHRcdFx0XHQvLyBSZW1vdmUgYW55IHJlbWFpbmluZyBub2Rlc1xuXHRcdFx0XHRlbGVtLnRleHRDb250ZW50ID0gXCJcIjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRjbG9uZTogZnVuY3Rpb24oIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICkge1xuXHRcdGRhdGFBbmRFdmVudHMgPSBkYXRhQW5kRXZlbnRzID09IG51bGwgPyBmYWxzZSA6IGRhdGFBbmRFdmVudHM7XG5cdFx0ZGVlcERhdGFBbmRFdmVudHMgPSBkZWVwRGF0YUFuZEV2ZW50cyA9PSBudWxsID8gZGF0YUFuZEV2ZW50cyA6IGRlZXBEYXRhQW5kRXZlbnRzO1xuXG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBqUXVlcnkuY2xvbmUoIHRoaXMsIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdGh0bWw6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXSB8fCB7fSxcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdGwgPSB0aGlzLmxlbmd0aDtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmlubmVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2VlIGlmIHdlIGNhbiB0YWtlIGEgc2hvcnRjdXQgYW5kIGp1c3QgdXNlIGlubmVySFRNTFxuXHRcdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgIXJub0lubmVyaHRtbC50ZXN0KCB2YWx1ZSApICYmXG5cdFx0XHRcdCF3cmFwTWFwWyAoIHJ0YWdOYW1lLmV4ZWMoIHZhbHVlICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCkgXSApIHtcblxuXHRcdFx0XHR2YWx1ZSA9IGpRdWVyeS5odG1sUHJlZmlsdGVyKCB2YWx1ZSApO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdFx0ZWxlbSA9IHRoaXNbIGkgXSB8fCB7fTtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXHRcdFx0XHRcdFx0XHRlbGVtLmlubmVySFRNTCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsZW0gPSAwO1xuXG5cdFx0XHRcdC8vIElmIHVzaW5nIGlubmVySFRNTCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB1c2UgdGhlIGZhbGxiYWNrIG1ldGhvZFxuXHRcdFx0XHR9IGNhdGNoICggZSApIHt9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZWxlbSApIHtcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmFwcGVuZCggdmFsdWUgKTtcblx0XHRcdH1cblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCApO1xuXHR9LFxuXG5cdHJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaWdub3JlZCA9IFtdO1xuXG5cdFx0Ly8gTWFrZSB0aGUgY2hhbmdlcywgcmVwbGFjaW5nIGVhY2ggbm9uLWlnbm9yZWQgY29udGV4dCBlbGVtZW50IHdpdGggdGhlIG5ldyBjb250ZW50XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIHBhcmVudCA9IHRoaXMucGFyZW50Tm9kZTtcblxuXHRcdFx0aWYgKCBqUXVlcnkuaW5BcnJheSggdGhpcywgaWdub3JlZCApIDwgMCApIHtcblx0XHRcdFx0alF1ZXJ5LmNsZWFuRGF0YSggZ2V0QWxsKCB0aGlzICkgKTtcblx0XHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cdFx0XHRcdFx0cGFyZW50LnJlcGxhY2VDaGlsZCggZWxlbSwgdGhpcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBGb3JjZSBjYWxsYmFjayBpbnZvY2F0aW9uXG5cdFx0fSwgaWdub3JlZCApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCB7XG5cdGFwcGVuZFRvOiBcImFwcGVuZFwiLFxuXHRwcmVwZW5kVG86IFwicHJlcGVuZFwiLFxuXHRpbnNlcnRCZWZvcmU6IFwiYmVmb3JlXCIsXG5cdGluc2VydEFmdGVyOiBcImFmdGVyXCIsXG5cdHJlcGxhY2VBbGw6IFwicmVwbGFjZVdpdGhcIlxufSwgZnVuY3Rpb24oIG5hbWUsIG9yaWdpbmFsICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgZWxlbXMsXG5cdFx0XHRyZXQgPSBbXSxcblx0XHRcdGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKSxcblx0XHRcdGxhc3QgPSBpbnNlcnQubGVuZ3RoIC0gMSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyBpIDw9IGxhc3Q7IGkrKyApIHtcblx0XHRcdGVsZW1zID0gaSA9PT0gbGFzdCA/IHRoaXMgOiB0aGlzLmNsb25lKCB0cnVlICk7XG5cdFx0XHRqUXVlcnkoIGluc2VydFsgaSBdIClbIG9yaWdpbmFsIF0oIGVsZW1zICk7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0Ly8gLmdldCgpIGJlY2F1c2UgcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0cHVzaC5hcHBseSggcmV0LCBlbGVtcy5nZXQoKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggcmV0ICk7XG5cdH07XG59ICk7XG52YXIgcm1hcmdpbiA9ICggL15tYXJnaW4vICk7XG5cbnZhciBybnVtbm9ucHggPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBwbnVtICsgXCIpKD8hcHgpW2EteiVdKyRcIiwgXCJpXCIgKTtcblxudmFyIGdldFN0eWxlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5LCBGaXJlZm94IDw9MzAgKCMxNTA5OCwgIzE0MTUwKVxuXHRcdC8vIElFIHRocm93cyBvbiBlbGVtZW50cyBjcmVhdGVkIGluIHBvcHVwc1xuXHRcdC8vIEZGIG1lYW53aGlsZSB0aHJvd3Mgb24gZnJhbWUgZWxlbWVudHMgdGhyb3VnaCBcImRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGVcIlxuXHRcdHZhciB2aWV3ID0gZWxlbS5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3O1xuXG5cdFx0aWYgKCAhdmlldyB8fCAhdmlldy5vcGVuZXIgKSB7XG5cdFx0XHR2aWV3ID0gd2luZG93O1xuXHRcdH1cblxuXHRcdHJldHVybiB2aWV3LmdldENvbXB1dGVkU3R5bGUoIGVsZW0gKTtcblx0fTtcblxuXG5cbiggZnVuY3Rpb24oKSB7XG5cblx0Ly8gRXhlY3V0aW5nIGJvdGggcGl4ZWxQb3NpdGlvbiAmIGJveFNpemluZ1JlbGlhYmxlIHRlc3RzIHJlcXVpcmUgb25seSBvbmUgbGF5b3V0XG5cdC8vIHNvIHRoZXkncmUgZXhlY3V0ZWQgYXQgdGhlIHNhbWUgdGltZSB0byBzYXZlIHRoZSBzZWNvbmQgY29tcHV0YXRpb24uXG5cdGZ1bmN0aW9uIGNvbXB1dGVTdHlsZVRlc3RzKCkge1xuXG5cdFx0Ly8gVGhpcyBpcyBhIHNpbmdsZXRvbiwgd2UgbmVlZCB0byBleGVjdXRlIGl0IG9ubHkgb25jZVxuXHRcdGlmICggIWRpdiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRkaXYuc3R5bGUuY3NzVGV4dCA9XG5cdFx0XHRcImJveC1zaXppbmc6Ym9yZGVyLWJveDtcIiArXG5cdFx0XHRcInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7XCIgK1xuXHRcdFx0XCJtYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O1wiICtcblx0XHRcdFwidG9wOjElO3dpZHRoOjUwJVwiO1xuXHRcdGRpdi5pbm5lckhUTUwgPSBcIlwiO1xuXHRcdGRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHR2YXIgZGl2U3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSggZGl2ICk7XG5cdFx0cGl4ZWxQb3NpdGlvblZhbCA9IGRpdlN0eWxlLnRvcCAhPT0gXCIxJVwiO1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgLSA0LjMgb25seSwgRmlyZWZveCA8PTMgLSA0NFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdFZhbCA9IGRpdlN0eWxlLm1hcmdpbkxlZnQgPT09IFwiMnB4XCI7XG5cdFx0Ym94U2l6aW5nUmVsaWFibGVWYWwgPSBkaXZTdHlsZS53aWR0aCA9PT0gXCI0cHhcIjtcblxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgNC4wIC0gNC4zIG9ubHlcblx0XHQvLyBTb21lIHN0eWxlcyBjb21lIGJhY2sgd2l0aCBwZXJjZW50YWdlIHZhbHVlcywgZXZlbiB0aG91Z2ggdGhleSBzaG91bGRuJ3Rcblx0XHRkaXYuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjUwJVwiO1xuXHRcdHBpeGVsTWFyZ2luUmlnaHRWYWwgPSBkaXZTdHlsZS5tYXJnaW5SaWdodCA9PT0gXCI0cHhcIjtcblxuXHRcdGRvY3VtZW50RWxlbWVudC5yZW1vdmVDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHQvLyBOdWxsaWZ5IHRoZSBkaXYgc28gaXQgd291bGRuJ3QgYmUgc3RvcmVkIGluIHRoZSBtZW1vcnkgYW5kXG5cdFx0Ly8gaXQgd2lsbCBhbHNvIGJlIGEgc2lnbiB0aGF0IGNoZWNrcyBhbHJlYWR5IHBlcmZvcm1lZFxuXHRcdGRpdiA9IG51bGw7XG5cdH1cblxuXHR2YXIgcGl4ZWxQb3NpdGlvblZhbCwgYm94U2l6aW5nUmVsaWFibGVWYWwsIHBpeGVsTWFyZ2luUmlnaHRWYWwsIHJlbGlhYmxlTWFyZ2luTGVmdFZhbCxcblx0XHRjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICksXG5cdFx0ZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApO1xuXG5cdC8vIEZpbmlzaCBlYXJseSBpbiBsaW1pdGVkIChub24tYnJvd3NlcikgZW52aXJvbm1lbnRzXG5cdGlmICggIWRpdi5zdHlsZSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSBvbmx5XG5cdC8vIFN0eWxlIG9mIGNsb25lZCBlbGVtZW50IGFmZmVjdHMgc291cmNlIGVsZW1lbnQgY2xvbmVkICgjODkwOClcblx0ZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID0gXCJjb250ZW50LWJveFwiO1xuXHRkaXYuY2xvbmVOb2RlKCB0cnVlICkuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcIlwiO1xuXHRzdXBwb3J0LmNsZWFyQ2xvbmVTdHlsZSA9IGRpdi5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9PT0gXCJjb250ZW50LWJveFwiO1xuXG5cdGNvbnRhaW5lci5zdHlsZS5jc3NUZXh0ID0gXCJib3JkZXI6MDt3aWR0aDo4cHg7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4O1wiICtcblx0XHRcInBhZGRpbmc6MDttYXJnaW4tdG9wOjFweDtwb3NpdGlvbjphYnNvbHV0ZVwiO1xuXHRjb250YWluZXIuYXBwZW5kQ2hpbGQoIGRpdiApO1xuXG5cdGpRdWVyeS5leHRlbmQoIHN1cHBvcnQsIHtcblx0XHRwaXhlbFBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxQb3NpdGlvblZhbDtcblx0XHR9LFxuXHRcdGJveFNpemluZ1JlbGlhYmxlOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gYm94U2l6aW5nUmVsaWFibGVWYWw7XG5cdFx0fSxcblx0XHRwaXhlbE1hcmdpblJpZ2h0OiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxNYXJnaW5SaWdodFZhbDtcblx0XHR9LFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRjb21wdXRlU3R5bGVUZXN0cygpO1xuXHRcdFx0cmV0dXJuIHJlbGlhYmxlTWFyZ2luTGVmdFZhbDtcblx0XHR9XG5cdH0gKTtcbn0gKSgpO1xuXG5cbmZ1bmN0aW9uIGN1ckNTUyggZWxlbSwgbmFtZSwgY29tcHV0ZWQgKSB7XG5cdHZhciB3aWR0aCwgbWluV2lkdGgsIG1heFdpZHRoLCByZXQsXG5cblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDUxK1xuXHRcdC8vIFJldHJpZXZpbmcgc3R5bGUgYmVmb3JlIGNvbXB1dGVkIHNvbWVob3dcblx0XHQvLyBmaXhlcyBhbiBpc3N1ZSB3aXRoIGdldHRpbmcgd3JvbmcgdmFsdWVzXG5cdFx0Ly8gb24gZGV0YWNoZWQgZWxlbWVudHNcblx0XHRzdHlsZSA9IGVsZW0uc3R5bGU7XG5cblx0Y29tcHV0ZWQgPSBjb21wdXRlZCB8fCBnZXRTdHlsZXMoIGVsZW0gKTtcblxuXHQvLyBnZXRQcm9wZXJ0eVZhbHVlIGlzIG5lZWRlZCBmb3I6XG5cdC8vICAgLmNzcygnZmlsdGVyJykgKElFIDkgb25seSwgIzEyNTM3KVxuXHQvLyAgIC5jc3MoJy0tY3VzdG9tUHJvcGVydHkpICgjMzE0NClcblx0aWYgKCBjb21wdXRlZCApIHtcblx0XHRyZXQgPSBjb21wdXRlZC5nZXRQcm9wZXJ0eVZhbHVlKCBuYW1lICkgfHwgY29tcHV0ZWRbIG5hbWUgXTtcblxuXHRcdGlmICggcmV0ID09PSBcIlwiICYmICFqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICkge1xuXHRcdFx0cmV0ID0galF1ZXJ5LnN0eWxlKCBlbGVtLCBuYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gQSB0cmlidXRlIHRvIHRoZSBcImF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHNcIlxuXHRcdC8vIEFuZHJvaWQgQnJvd3NlciByZXR1cm5zIHBlcmNlbnRhZ2UgZm9yIHNvbWUgdmFsdWVzLFxuXHRcdC8vIGJ1dCB3aWR0aCBzZWVtcyB0byBiZSByZWxpYWJseSBwaXhlbHMuXG5cdFx0Ly8gVGhpcyBpcyBhZ2FpbnN0IHRoZSBDU1NPTSBkcmFmdCBzcGVjOlxuXHRcdC8vIGh0dHBzOi8vZHJhZnRzLmNzc3dnLm9yZy9jc3NvbS8jcmVzb2x2ZWQtdmFsdWVzXG5cdFx0aWYgKCAhc3VwcG9ydC5waXhlbE1hcmdpblJpZ2h0KCkgJiYgcm51bW5vbnB4LnRlc3QoIHJldCApICYmIHJtYXJnaW4udGVzdCggbmFtZSApICkge1xuXG5cdFx0XHQvLyBSZW1lbWJlciB0aGUgb3JpZ2luYWwgdmFsdWVzXG5cdFx0XHR3aWR0aCA9IHN0eWxlLndpZHRoO1xuXHRcdFx0bWluV2lkdGggPSBzdHlsZS5taW5XaWR0aDtcblx0XHRcdG1heFdpZHRoID0gc3R5bGUubWF4V2lkdGg7XG5cblx0XHRcdC8vIFB1dCBpbiB0aGUgbmV3IHZhbHVlcyB0byBnZXQgYSBjb21wdXRlZCB2YWx1ZSBvdXRcblx0XHRcdHN0eWxlLm1pbldpZHRoID0gc3R5bGUubWF4V2lkdGggPSBzdHlsZS53aWR0aCA9IHJldDtcblx0XHRcdHJldCA9IGNvbXB1dGVkLndpZHRoO1xuXG5cdFx0XHQvLyBSZXZlcnQgdGhlIGNoYW5nZWQgdmFsdWVzXG5cdFx0XHRzdHlsZS53aWR0aCA9IHdpZHRoO1xuXHRcdFx0c3R5bGUubWluV2lkdGggPSBtaW5XaWR0aDtcblx0XHRcdHN0eWxlLm1heFdpZHRoID0gbWF4V2lkdGg7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHJldCAhPT0gdW5kZWZpbmVkID9cblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0XHQvLyBJRSByZXR1cm5zIHpJbmRleCB2YWx1ZSBhcyBhbiBpbnRlZ2VyLlxuXHRcdHJldCArIFwiXCIgOlxuXHRcdHJldDtcbn1cblxuXG5mdW5jdGlvbiBhZGRHZXRIb29rSWYoIGNvbmRpdGlvbkZuLCBob29rRm4gKSB7XG5cblx0Ly8gRGVmaW5lIHRoZSBob29rLCB3ZSdsbCBjaGVjayBvbiB0aGUgZmlyc3QgcnVuIGlmIGl0J3MgcmVhbGx5IG5lZWRlZC5cblx0cmV0dXJuIHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCBjb25kaXRpb25GbigpICkge1xuXG5cdFx0XHRcdC8vIEhvb2sgbm90IG5lZWRlZCAob3IgaXQncyBub3QgcG9zc2libGUgdG8gdXNlIGl0IGR1ZVxuXHRcdFx0XHQvLyB0byBtaXNzaW5nIGRlcGVuZGVuY3kpLCByZW1vdmUgaXQuXG5cdFx0XHRcdGRlbGV0ZSB0aGlzLmdldDtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBIb29rIG5lZWRlZDsgcmVkZWZpbmUgaXQgc28gdGhhdCB0aGUgc3VwcG9ydCB0ZXN0IGlzIG5vdCBleGVjdXRlZCBhZ2Fpbi5cblx0XHRcdHJldHVybiAoIHRoaXMuZ2V0ID0gaG9va0ZuICkuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0fTtcbn1cblxuXG52YXJcblxuXHQvLyBTd2FwcGFibGUgaWYgZGlzcGxheSBpcyBub25lIG9yIHN0YXJ0cyB3aXRoIHRhYmxlXG5cdC8vIGV4Y2VwdCBcInRhYmxlXCIsIFwidGFibGUtY2VsbFwiLCBvciBcInRhYmxlLWNhcHRpb25cIlxuXHQvLyBTZWUgaGVyZSBmb3IgZGlzcGxheSB2YWx1ZXM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvQ1NTL2Rpc3BsYXlcblx0cmRpc3BsYXlzd2FwID0gL14obm9uZXx0YWJsZSg/IS1jW2VhXSkuKykvLFxuXHRyY3VzdG9tUHJvcCA9IC9eLS0vLFxuXHRjc3NTaG93ID0geyBwb3NpdGlvbjogXCJhYnNvbHV0ZVwiLCB2aXNpYmlsaXR5OiBcImhpZGRlblwiLCBkaXNwbGF5OiBcImJsb2NrXCIgfSxcblx0Y3NzTm9ybWFsVHJhbnNmb3JtID0ge1xuXHRcdGxldHRlclNwYWNpbmc6IFwiMFwiLFxuXHRcdGZvbnRXZWlnaHQ6IFwiNDAwXCJcblx0fSxcblxuXHRjc3NQcmVmaXhlcyA9IFsgXCJXZWJraXRcIiwgXCJNb3pcIiwgXCJtc1wiIF0sXG5cdGVtcHR5U3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkuc3R5bGU7XG5cbi8vIFJldHVybiBhIGNzcyBwcm9wZXJ0eSBtYXBwZWQgdG8gYSBwb3RlbnRpYWxseSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHlcbmZ1bmN0aW9uIHZlbmRvclByb3BOYW1lKCBuYW1lICkge1xuXG5cdC8vIFNob3J0Y3V0IGZvciBuYW1lcyB0aGF0IGFyZSBub3QgdmVuZG9yIHByZWZpeGVkXG5cdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdHJldHVybiBuYW1lO1xuXHR9XG5cblx0Ly8gQ2hlY2sgZm9yIHZlbmRvciBwcmVmaXhlZCBuYW1lc1xuXHR2YXIgY2FwTmFtZSA9IG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApLFxuXHRcdGkgPSBjc3NQcmVmaXhlcy5sZW5ndGg7XG5cblx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0bmFtZSA9IGNzc1ByZWZpeGVzWyBpIF0gKyBjYXBOYW1lO1xuXHRcdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdFx0cmV0dXJuIG5hbWU7XG5cdFx0fVxuXHR9XG59XG5cbi8vIFJldHVybiBhIHByb3BlcnR5IG1hcHBlZCBhbG9uZyB3aGF0IGpRdWVyeS5jc3NQcm9wcyBzdWdnZXN0cyBvciB0b1xuLy8gYSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHkuXG5mdW5jdGlvbiBmaW5hbFByb3BOYW1lKCBuYW1lICkge1xuXHR2YXIgcmV0ID0galF1ZXJ5LmNzc1Byb3BzWyBuYW1lIF07XG5cdGlmICggIXJldCApIHtcblx0XHRyZXQgPSBqUXVlcnkuY3NzUHJvcHNbIG5hbWUgXSA9IHZlbmRvclByb3BOYW1lKCBuYW1lICkgfHwgbmFtZTtcblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICkge1xuXG5cdC8vIEFueSByZWxhdGl2ZSAoKy8tKSB2YWx1ZXMgaGF2ZSBhbHJlYWR5IGJlZW5cblx0Ly8gbm9ybWFsaXplZCBhdCB0aGlzIHBvaW50XG5cdHZhciBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApO1xuXHRyZXR1cm4gbWF0Y2hlcyA/XG5cblx0XHQvLyBHdWFyZCBhZ2FpbnN0IHVuZGVmaW5lZCBcInN1YnRyYWN0XCIsIGUuZy4sIHdoZW4gdXNlZCBhcyBpbiBjc3NIb29rc1xuXHRcdE1hdGgubWF4KCAwLCBtYXRjaGVzWyAyIF0gLSAoIHN1YnRyYWN0IHx8IDAgKSApICsgKCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgOlxuXHRcdHZhbHVlO1xufVxuXG5mdW5jdGlvbiBhdWdtZW50V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEsIGlzQm9yZGVyQm94LCBzdHlsZXMgKSB7XG5cdHZhciBpLFxuXHRcdHZhbCA9IDA7XG5cblx0Ly8gSWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBtZWFzdXJlbWVudCwgYXZvaWQgYXVnbWVudGF0aW9uXG5cdGlmICggZXh0cmEgPT09ICggaXNCb3JkZXJCb3ggPyBcImJvcmRlclwiIDogXCJjb250ZW50XCIgKSApIHtcblx0XHRpID0gNDtcblxuXHQvLyBPdGhlcndpc2UgaW5pdGlhbGl6ZSBmb3IgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBwcm9wZXJ0aWVzXG5cdH0gZWxzZSB7XG5cdFx0aSA9IG5hbWUgPT09IFwid2lkdGhcIiA/IDEgOiAwO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgNDsgaSArPSAyICkge1xuXG5cdFx0Ly8gQm90aCBib3ggbW9kZWxzIGV4Y2x1ZGUgbWFyZ2luLCBzbyBhZGQgaXQgaWYgd2Ugd2FudCBpdFxuXHRcdGlmICggZXh0cmEgPT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHR2YWwgKz0galF1ZXJ5LmNzcyggZWxlbSwgZXh0cmEgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpc0JvcmRlckJveCApIHtcblxuXHRcdFx0Ly8gYm9yZGVyLWJveCBpbmNsdWRlcyBwYWRkaW5nLCBzbyByZW1vdmUgaXQgaWYgd2Ugd2FudCBjb250ZW50XG5cdFx0XHRpZiAoIGV4dHJhID09PSBcImNvbnRlbnRcIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBib3JkZXIgbm9yIG1hcmdpbiwgc28gcmVtb3ZlIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJtYXJnaW5cIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCwgc28gYWRkIHBhZGRpbmdcblx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBhZGRpbmdcIiArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCBub3IgcGFkZGluZywgc28gYWRkIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJwYWRkaW5nXCIgKSB7XG5cdFx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcImJvcmRlclwiICsgY3NzRXhwYW5kWyBpIF0gKyBcIldpZHRoXCIsIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICkge1xuXG5cdC8vIFN0YXJ0IHdpdGggY29tcHV0ZWQgc3R5bGVcblx0dmFyIHZhbHVlSXNCb3JkZXJCb3gsXG5cdFx0c3R5bGVzID0gZ2V0U3R5bGVzKCBlbGVtICksXG5cdFx0dmFsID0gY3VyQ1NTKCBlbGVtLCBuYW1lLCBzdHlsZXMgKSxcblx0XHRpc0JvcmRlckJveCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm94U2l6aW5nXCIsIGZhbHNlLCBzdHlsZXMgKSA9PT0gXCJib3JkZXItYm94XCI7XG5cblx0Ly8gQ29tcHV0ZWQgdW5pdCBpcyBub3QgcGl4ZWxzLiBTdG9wIGhlcmUgYW5kIHJldHVybi5cblx0aWYgKCBybnVtbm9ucHgudGVzdCggdmFsICkgKSB7XG5cdFx0cmV0dXJuIHZhbDtcblx0fVxuXG5cdC8vIENoZWNrIGZvciBzdHlsZSBpbiBjYXNlIGEgYnJvd3NlciB3aGljaCByZXR1cm5zIHVucmVsaWFibGUgdmFsdWVzXG5cdC8vIGZvciBnZXRDb21wdXRlZFN0eWxlIHNpbGVudGx5IGZhbGxzIGJhY2sgdG8gdGhlIHJlbGlhYmxlIGVsZW0uc3R5bGVcblx0dmFsdWVJc0JvcmRlckJveCA9IGlzQm9yZGVyQm94ICYmXG5cdFx0KCBzdXBwb3J0LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgdmFsID09PSBlbGVtLnN0eWxlWyBuYW1lIF0gKTtcblxuXHQvLyBGYWxsIGJhY2sgdG8gb2Zmc2V0V2lkdGgvSGVpZ2h0IHdoZW4gdmFsdWUgaXMgXCJhdXRvXCJcblx0Ly8gVGhpcyBoYXBwZW5zIGZvciBpbmxpbmUgZWxlbWVudHMgd2l0aCBubyBleHBsaWNpdCBzZXR0aW5nIChnaC0zNTcxKVxuXHRpZiAoIHZhbCA9PT0gXCJhdXRvXCIgKSB7XG5cdFx0dmFsID0gZWxlbVsgXCJvZmZzZXRcIiArIG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApIF07XG5cdH1cblxuXHQvLyBOb3JtYWxpemUgXCJcIiwgYXV0bywgYW5kIHByZXBhcmUgZm9yIGV4dHJhXG5cdHZhbCA9IHBhcnNlRmxvYXQoIHZhbCApIHx8IDA7XG5cblx0Ly8gVXNlIHRoZSBhY3RpdmUgYm94LXNpemluZyBtb2RlbCB0byBhZGQvc3VidHJhY3QgaXJyZWxldmFudCBzdHlsZXNcblx0cmV0dXJuICggdmFsICtcblx0XHRhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdGVsZW0sXG5cdFx0XHRuYW1lLFxuXHRcdFx0ZXh0cmEgfHwgKCBpc0JvcmRlckJveCA/IFwiYm9yZGVyXCIgOiBcImNvbnRlbnRcIiApLFxuXHRcdFx0dmFsdWVJc0JvcmRlckJveCxcblx0XHRcdHN0eWxlc1xuXHRcdClcblx0KSArIFwicHhcIjtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIEFkZCBpbiBzdHlsZSBwcm9wZXJ0eSBob29rcyBmb3Igb3ZlcnJpZGluZyB0aGUgZGVmYXVsdFxuXHQvLyBiZWhhdmlvciBvZiBnZXR0aW5nIGFuZCBzZXR0aW5nIGEgc3R5bGUgcHJvcGVydHlcblx0Y3NzSG9va3M6IHtcblx0XHRvcGFjaXR5OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblxuXHRcdFx0XHRcdC8vIFdlIHNob3VsZCBhbHdheXMgZ2V0IGEgbnVtYmVyIGJhY2sgZnJvbSBvcGFjaXR5XG5cdFx0XHRcdFx0dmFyIHJldCA9IGN1ckNTUyggZWxlbSwgXCJvcGFjaXR5XCIgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmV0ID09PSBcIlwiID8gXCIxXCIgOiByZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0Ly8gRG9uJ3QgYXV0b21hdGljYWxseSBhZGQgXCJweFwiIHRvIHRoZXNlIHBvc3NpYmx5LXVuaXRsZXNzIHByb3BlcnRpZXNcblx0Y3NzTnVtYmVyOiB7XG5cdFx0XCJhbmltYXRpb25JdGVyYXRpb25Db3VudFwiOiB0cnVlLFxuXHRcdFwiY29sdW1uQ291bnRcIjogdHJ1ZSxcblx0XHRcImZpbGxPcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJmbGV4R3Jvd1wiOiB0cnVlLFxuXHRcdFwiZmxleFNocmlua1wiOiB0cnVlLFxuXHRcdFwiZm9udFdlaWdodFwiOiB0cnVlLFxuXHRcdFwibGluZUhlaWdodFwiOiB0cnVlLFxuXHRcdFwib3BhY2l0eVwiOiB0cnVlLFxuXHRcdFwib3JkZXJcIjogdHJ1ZSxcblx0XHRcIm9ycGhhbnNcIjogdHJ1ZSxcblx0XHRcIndpZG93c1wiOiB0cnVlLFxuXHRcdFwiekluZGV4XCI6IHRydWUsXG5cdFx0XCJ6b29tXCI6IHRydWVcblx0fSxcblxuXHQvLyBBZGQgaW4gcHJvcGVydGllcyB3aG9zZSBuYW1lcyB5b3Ugd2lzaCB0byBmaXggYmVmb3JlXG5cdC8vIHNldHRpbmcgb3IgZ2V0dGluZyB0aGUgdmFsdWVcblx0Y3NzUHJvcHM6IHtcblx0XHRcImZsb2F0XCI6IFwiY3NzRmxvYXRcIlxuXHR9LFxuXG5cdC8vIEdldCBhbmQgc2V0IHRoZSBzdHlsZSBwcm9wZXJ0eSBvbiBhIERPTSBOb2RlXG5cdHN0eWxlOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUsIGV4dHJhICkge1xuXG5cdFx0Ly8gRG9uJ3Qgc2V0IHN0eWxlcyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBlbGVtLm5vZGVUeXBlID09PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT09IDggfHwgIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lXG5cdFx0dmFyIHJldCwgdHlwZSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKSxcblx0XHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIHF1ZXJ5IHRoZSB2YWx1ZSBpZiBpdCBpcyBhIENTUyBjdXN0b20gcHJvcGVydHlcblx0XHQvLyBzaW5jZSB0aGV5IGFyZSB1c2VyLWRlZmluZWQuXG5cdFx0aWYgKCAhaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0bmFtZSA9IGZpbmFsUHJvcE5hbWUoIG9yaWdOYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0cyBob29rIGZvciB0aGUgcHJlZml4ZWQgdmVyc2lvbiwgdGhlbiB1bnByZWZpeGVkIHZlcnNpb25cblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIENoZWNrIGlmIHdlJ3JlIHNldHRpbmcgYSB2YWx1ZVxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cblx0XHRcdC8vIENvbnZlcnQgXCIrPVwiIG9yIFwiLT1cIiB0byByZWxhdGl2ZSBudW1iZXJzICgjNzM0NSlcblx0XHRcdGlmICggdHlwZSA9PT0gXCJzdHJpbmdcIiAmJiAoIHJldCA9IHJjc3NOdW0uZXhlYyggdmFsdWUgKSApICYmIHJldFsgMSBdICkge1xuXHRcdFx0XHR2YWx1ZSA9IGFkanVzdENTUyggZWxlbSwgbmFtZSwgcmV0ICk7XG5cblx0XHRcdFx0Ly8gRml4ZXMgYnVnICM5MjM3XG5cdFx0XHRcdHR5cGUgPSBcIm51bWJlclwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgdGhhdCBudWxsIGFuZCBOYU4gdmFsdWVzIGFyZW4ndCBzZXQgKCM3MTE2KVxuXHRcdFx0aWYgKCB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBhIG51bWJlciB3YXMgcGFzc2VkIGluLCBhZGQgdGhlIHVuaXQgKGV4Y2VwdCBmb3IgY2VydGFpbiBDU1MgcHJvcGVydGllcylcblx0XHRcdGlmICggdHlwZSA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsdWUgKz0gcmV0ICYmIHJldFsgMyBdIHx8ICggalF1ZXJ5LmNzc051bWJlclsgb3JpZ05hbWUgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gYmFja2dyb3VuZC0qIHByb3BzIGFmZmVjdCBvcmlnaW5hbCBjbG9uZSdzIHZhbHVlc1xuXHRcdFx0aWYgKCAhc3VwcG9ydC5jbGVhckNsb25lU3R5bGUgJiYgdmFsdWUgPT09IFwiXCIgJiYgbmFtZS5pbmRleE9mKCBcImJhY2tncm91bmRcIiApID09PSAwICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gXCJpbmhlcml0XCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0IHZhbHVlLCBvdGhlcndpc2UganVzdCBzZXQgdGhlIHNwZWNpZmllZCB2YWx1ZVxuXHRcdFx0aWYgKCAhaG9va3MgfHwgISggXCJzZXRcIiBpbiBob29rcyApIHx8XG5cdFx0XHRcdCggdmFsdWUgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBleHRyYSApICkgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHRpZiAoIGlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdFx0XHRzdHlsZS5zZXRQcm9wZXJ0eSggbmFtZSwgdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBub24tY29tcHV0ZWQgdmFsdWUgZnJvbSB0aGVyZVxuXHRcdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBmYWxzZSwgZXh0cmEgKSApICE9PSB1bmRlZmluZWQgKSB7XG5cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gT3RoZXJ3aXNlIGp1c3QgZ2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBzdHlsZSBvYmplY3Rcblx0XHRcdHJldHVybiBzdHlsZVsgbmFtZSBdO1xuXHRcdH1cblx0fSxcblxuXHRjc3M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBleHRyYSwgc3R5bGVzICkge1xuXHRcdHZhciB2YWwsIG51bSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIG1vZGlmeSB0aGUgdmFsdWUgaWYgaXQgaXMgYSBDU1MgY3VzdG9tIHByb3BlcnR5XG5cdFx0Ly8gc2luY2UgdGhleSBhcmUgdXNlci1kZWZpbmVkLlxuXHRcdGlmICggIWlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdG5hbWUgPSBmaW5hbFByb3BOYW1lKCBvcmlnTmFtZSApO1xuXHRcdH1cblxuXHRcdC8vIFRyeSBwcmVmaXhlZCBuYW1lIGZvbGxvd2VkIGJ5IHRoZSB1bnByZWZpeGVkIG5hbWVcblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsID0gaG9va3MuZ2V0KCBlbGVtLCB0cnVlLCBleHRyYSApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSwgaWYgYSB3YXkgdG8gZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbCA9IGN1ckNTUyggZWxlbSwgbmFtZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udmVydCBcIm5vcm1hbFwiIHRvIGNvbXB1dGVkIHZhbHVlXG5cdFx0aWYgKCB2YWwgPT09IFwibm9ybWFsXCIgJiYgbmFtZSBpbiBjc3NOb3JtYWxUcmFuc2Zvcm0gKSB7XG5cdFx0XHR2YWwgPSBjc3NOb3JtYWxUcmFuc2Zvcm1bIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIG51bWVyaWMgaWYgZm9yY2VkIG9yIGEgcXVhbGlmaWVyIHdhcyBwcm92aWRlZCBhbmQgdmFsIGxvb2tzIG51bWVyaWNcblx0XHRpZiAoIGV4dHJhID09PSBcIlwiIHx8IGV4dHJhICkge1xuXHRcdFx0bnVtID0gcGFyc2VGbG9hdCggdmFsICk7XG5cdFx0XHRyZXR1cm4gZXh0cmEgPT09IHRydWUgfHwgaXNGaW5pdGUoIG51bSApID8gbnVtIHx8IDAgOiB2YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbDtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImhlaWdodFwiLCBcIndpZHRoXCIgXSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdID0ge1xuXHRcdGdldDogZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkLCBleHRyYSApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cblx0XHRcdFx0Ly8gQ2VydGFpbiBlbGVtZW50cyBjYW4gaGF2ZSBkaW1lbnNpb24gaW5mbyBpZiB3ZSBpbnZpc2libHkgc2hvdyB0aGVtXG5cdFx0XHRcdC8vIGJ1dCBpdCBtdXN0IGhhdmUgYSBjdXJyZW50IGRpc3BsYXkgc3R5bGUgdGhhdCB3b3VsZCBiZW5lZml0XG5cdFx0XHRcdHJldHVybiByZGlzcGxheXN3YXAudGVzdCggalF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKSApICYmXG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCtcblx0XHRcdFx0XHQvLyBUYWJsZSBjb2x1bW5zIGluIFNhZmFyaSBoYXZlIG5vbi16ZXJvIG9mZnNldFdpZHRoICYgemVyb1xuXHRcdFx0XHRcdC8vIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIHVubGVzcyBkaXNwbGF5IGlzIGNoYW5nZWQuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0XHRcdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYSBkaXNjb25uZWN0ZWQgbm9kZVxuXHRcdFx0XHRcdC8vIGluIElFIHRocm93cyBhbiBlcnJvci5cblx0XHRcdFx0XHQoICFlbGVtLmdldENsaWVudFJlY3RzKCkubGVuZ3RoIHx8ICFlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoICkgP1xuXHRcdFx0XHRcdFx0c3dhcCggZWxlbSwgY3NzU2hvdywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBnZXRXaWR0aE9ySGVpZ2h0KCBlbGVtLCBuYW1lLCBleHRyYSApO1xuXHRcdFx0XHRcdFx0fSApIDpcblx0XHRcdFx0XHRcdGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBleHRyYSApIHtcblx0XHRcdHZhciBtYXRjaGVzLFxuXHRcdFx0XHRzdHlsZXMgPSBleHRyYSAmJiBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHRcdFx0c3VidHJhY3QgPSBleHRyYSAmJiBhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdFx0XHRlbGVtLFxuXHRcdFx0XHRcdG5hbWUsXG5cdFx0XHRcdFx0ZXh0cmEsXG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIixcblx0XHRcdFx0XHRzdHlsZXNcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gQ29udmVydCB0byBwaXhlbHMgaWYgdmFsdWUgYWRqdXN0bWVudCBpcyBuZWVkZWRcblx0XHRcdGlmICggc3VidHJhY3QgJiYgKCBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApICkgJiZcblx0XHRcdFx0KCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgIT09IFwicHhcIiApIHtcblxuXHRcdFx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdFx0dmFsdWUgPSBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICk7XG5cdFx0fVxuXHR9O1xufSApO1xuXG5qUXVlcnkuY3NzSG9va3MubWFyZ2luTGVmdCA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5yZWxpYWJsZU1hcmdpbkxlZnQsXG5cdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRpZiAoIGNvbXB1dGVkICkge1xuXHRcdFx0cmV0dXJuICggcGFyc2VGbG9hdCggY3VyQ1NTKCBlbGVtLCBcIm1hcmdpbkxlZnRcIiApICkgfHxcblx0XHRcdFx0ZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC1cblx0XHRcdFx0XHRzd2FwKCBlbGVtLCB7IG1hcmdpbkxlZnQ6IDAgfSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuXHRcdFx0XHRcdH0gKVxuXHRcdFx0XHQpICsgXCJweFwiO1xuXHRcdH1cblx0fVxuKTtcblxuLy8gVGhlc2UgaG9va3MgYXJlIHVzZWQgYnkgYW5pbWF0ZSB0byBleHBhbmQgcHJvcGVydGllc1xualF1ZXJ5LmVhY2goIHtcblx0bWFyZ2luOiBcIlwiLFxuXHRwYWRkaW5nOiBcIlwiLFxuXHRib3JkZXI6IFwiV2lkdGhcIlxufSwgZnVuY3Rpb24oIHByZWZpeCwgc3VmZml4ICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdID0ge1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGkgPSAwLFxuXHRcdFx0XHRleHBhbmRlZCA9IHt9LFxuXG5cdFx0XHRcdC8vIEFzc3VtZXMgYSBzaW5nbGUgbnVtYmVyIGlmIG5vdCBhIHN0cmluZ1xuXHRcdFx0XHRwYXJ0cyA9IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlLnNwbGl0KCBcIiBcIiApIDogWyB2YWx1ZSBdO1xuXG5cdFx0XHRmb3IgKCA7IGkgPCA0OyBpKysgKSB7XG5cdFx0XHRcdGV4cGFuZGVkWyBwcmVmaXggKyBjc3NFeHBhbmRbIGkgXSArIHN1ZmZpeCBdID1cblx0XHRcdFx0XHRwYXJ0c1sgaSBdIHx8IHBhcnRzWyBpIC0gMiBdIHx8IHBhcnRzWyAwIF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBleHBhbmRlZDtcblx0XHR9XG5cdH07XG5cblx0aWYgKCAhcm1hcmdpbi50ZXN0KCBwcmVmaXggKSApIHtcblx0XHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdLnNldCA9IHNldFBvc2l0aXZlTnVtYmVyO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0Y3NzOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0dmFyIHN0eWxlcywgbGVuLFxuXHRcdFx0XHRtYXAgPSB7fSxcblx0XHRcdFx0aSA9IDA7XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggbmFtZSApICkge1xuXHRcdFx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKTtcblx0XHRcdFx0bGVuID0gbmFtZS5sZW5ndGg7XG5cblx0XHRcdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0bWFwWyBuYW1lWyBpIF0gXSA9IGpRdWVyeS5jc3MoIGVsZW0sIG5hbWVbIGkgXSwgZmFsc2UsIHN0eWxlcyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIG1hcDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUsIHZhbHVlICkgOlxuXHRcdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0fSwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH1cbn0gKTtcblxuXG5mdW5jdGlvbiBUd2VlbiggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKSB7XG5cdHJldHVybiBuZXcgVHdlZW4ucHJvdG90eXBlLmluaXQoIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nICk7XG59XG5qUXVlcnkuVHdlZW4gPSBUd2VlbjtcblxuVHdlZW4ucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogVHdlZW4sXG5cdGluaXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZywgdW5pdCApIHtcblx0XHR0aGlzLmVsZW0gPSBlbGVtO1xuXHRcdHRoaXMucHJvcCA9IHByb3A7XG5cdFx0dGhpcy5lYXNpbmcgPSBlYXNpbmcgfHwgalF1ZXJ5LmVhc2luZy5fZGVmYXVsdDtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHRcdHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCk7XG5cdFx0dGhpcy5lbmQgPSBlbmQ7XG5cdFx0dGhpcy51bml0ID0gdW5pdCB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0fSxcblx0Y3VyOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0cmV0dXJuIGhvb2tzICYmIGhvb2tzLmdldCA/XG5cdFx0XHRob29rcy5nZXQoIHRoaXMgKSA6XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuZ2V0KCB0aGlzICk7XG5cdH0sXG5cdHJ1bjogZnVuY3Rpb24oIHBlcmNlbnQgKSB7XG5cdFx0dmFyIGVhc2VkLFxuXHRcdFx0aG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0galF1ZXJ5LmVhc2luZ1sgdGhpcy5lYXNpbmcgXShcblx0XHRcdFx0cGVyY2VudCwgdGhpcy5vcHRpb25zLmR1cmF0aW9uICogcGVyY2VudCwgMCwgMSwgdGhpcy5vcHRpb25zLmR1cmF0aW9uXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0gcGVyY2VudDtcblx0XHR9XG5cdFx0dGhpcy5ub3cgPSAoIHRoaXMuZW5kIC0gdGhpcy5zdGFydCApICogZWFzZWQgKyB0aGlzLnN0YXJ0O1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc3RlcCApIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zdGVwLmNhbGwoIHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMgKTtcblx0XHR9XG5cblx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnNldCApIHtcblx0XHRcdGhvb2tzLnNldCggdGhpcyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KCB0aGlzICk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59O1xuXG5Ud2Vlbi5wcm90b3R5cGUuaW5pdC5wcm90b3R5cGUgPSBUd2Vlbi5wcm90b3R5cGU7XG5cblR3ZWVuLnByb3BIb29rcyA9IHtcblx0X2RlZmF1bHQ6IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRcdHZhciByZXN1bHQ7XG5cblx0XHRcdC8vIFVzZSBhIHByb3BlcnR5IG9uIHRoZSBlbGVtZW50IGRpcmVjdGx5IHdoZW4gaXQgaXMgbm90IGEgRE9NIGVsZW1lbnQsXG5cdFx0XHQvLyBvciB3aGVuIHRoZXJlIGlzIG5vIG1hdGNoaW5nIHN0eWxlIHByb3BlcnR5IHRoYXQgZXhpc3RzLlxuXHRcdFx0aWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlICE9PSAxIHx8XG5cdFx0XHRcdHR3ZWVuLmVsZW1bIHR3ZWVuLnByb3AgXSAhPSBudWxsICYmIHR3ZWVuLmVsZW0uc3R5bGVbIHR3ZWVuLnByb3AgXSA9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gdHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQYXNzaW5nIGFuIGVtcHR5IHN0cmluZyBhcyBhIDNyZCBwYXJhbWV0ZXIgdG8gLmNzcyB3aWxsIGF1dG9tYXRpY2FsbHlcblx0XHRcdC8vIGF0dGVtcHQgYSBwYXJzZUZsb2F0IGFuZCBmYWxsYmFjayB0byBhIHN0cmluZyBpZiB0aGUgcGFyc2UgZmFpbHMuXG5cdFx0XHQvLyBTaW1wbGUgdmFsdWVzIHN1Y2ggYXMgXCIxMHB4XCIgYXJlIHBhcnNlZCB0byBGbG9hdDtcblx0XHRcdC8vIGNvbXBsZXggdmFsdWVzIHN1Y2ggYXMgXCJyb3RhdGUoMXJhZClcIiBhcmUgcmV0dXJuZWQgYXMtaXMuXG5cdFx0XHRyZXN1bHQgPSBqUXVlcnkuY3NzKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCBcIlwiICk7XG5cblx0XHRcdC8vIEVtcHR5IHN0cmluZ3MsIG51bGwsIHVuZGVmaW5lZCBhbmQgXCJhdXRvXCIgYXJlIGNvbnZlcnRlZCB0byAwLlxuXHRcdFx0cmV0dXJuICFyZXN1bHQgfHwgcmVzdWx0ID09PSBcImF1dG9cIiA/IDAgOiByZXN1bHQ7XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblxuXHRcdFx0Ly8gVXNlIHN0ZXAgaG9vayBmb3IgYmFjayBjb21wYXQuXG5cdFx0XHQvLyBVc2UgY3NzSG9vayBpZiBpdHMgdGhlcmUuXG5cdFx0XHQvLyBVc2UgLnN0eWxlIGlmIGF2YWlsYWJsZSBhbmQgdXNlIHBsYWluIHByb3BlcnRpZXMgd2hlcmUgYXZhaWxhYmxlLlxuXHRcdFx0aWYgKCBqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdICkge1xuXHRcdFx0XHRqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdKCB0d2VlbiApO1xuXHRcdFx0fSBlbHNlIGlmICggdHdlZW4uZWxlbS5ub2RlVHlwZSA9PT0gMSAmJlxuXHRcdFx0XHQoIHR3ZWVuLmVsZW0uc3R5bGVbIGpRdWVyeS5jc3NQcm9wc1sgdHdlZW4ucHJvcCBdIF0gIT0gbnVsbCB8fFxuXHRcdFx0XHRcdGpRdWVyeS5jc3NIb29rc1sgdHdlZW4ucHJvcCBdICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgdHdlZW4ucHJvcCwgdHdlZW4ubm93ICsgdHdlZW4udW5pdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbi8vIFBhbmljIGJhc2VkIGFwcHJvYWNoIHRvIHNldHRpbmcgdGhpbmdzIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuVHdlZW4ucHJvcEhvb2tzLnNjcm9sbFRvcCA9IFR3ZWVuLnByb3BIb29rcy5zY3JvbGxMZWZ0ID0ge1xuXHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRpZiAoIHR3ZWVuLmVsZW0ubm9kZVR5cGUgJiYgdHdlZW4uZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmVhc2luZyA9IHtcblx0bGluZWFyOiBmdW5jdGlvbiggcCApIHtcblx0XHRyZXR1cm4gcDtcblx0fSxcblx0c3dpbmc6IGZ1bmN0aW9uKCBwICkge1xuXHRcdHJldHVybiAwLjUgLSBNYXRoLmNvcyggcCAqIE1hdGguUEkgKSAvIDI7XG5cdH0sXG5cdF9kZWZhdWx0OiBcInN3aW5nXCJcbn07XG5cbmpRdWVyeS5meCA9IFR3ZWVuLnByb3RvdHlwZS5pbml0O1xuXG4vLyBCYWNrIGNvbXBhdCA8MS44IGV4dGVuc2lvbiBwb2ludFxualF1ZXJ5LmZ4LnN0ZXAgPSB7fTtcblxuXG5cblxudmFyXG5cdGZ4Tm93LCBpblByb2dyZXNzLFxuXHRyZnh0eXBlcyA9IC9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxcblx0cnJ1biA9IC9xdWV1ZUhvb2tzJC87XG5cbmZ1bmN0aW9uIHNjaGVkdWxlKCkge1xuXHRpZiAoIGluUHJvZ3Jlc3MgKSB7XG5cdFx0aWYgKCBkb2N1bWVudC5oaWRkZW4gPT09IGZhbHNlICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgKSB7XG5cdFx0XHR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBzY2hlZHVsZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCggc2NoZWR1bGUsIGpRdWVyeS5meC5pbnRlcnZhbCApO1xuXHRcdH1cblxuXHRcdGpRdWVyeS5meC50aWNrKCk7XG5cdH1cbn1cblxuLy8gQW5pbWF0aW9ucyBjcmVhdGVkIHN5bmNocm9ub3VzbHkgd2lsbCBydW4gc3luY2hyb25vdXNseVxuZnVuY3Rpb24gY3JlYXRlRnhOb3coKSB7XG5cdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRmeE5vdyA9IHVuZGVmaW5lZDtcblx0fSApO1xuXHRyZXR1cm4gKCBmeE5vdyA9IGpRdWVyeS5ub3coKSApO1xufVxuXG4vLyBHZW5lcmF0ZSBwYXJhbWV0ZXJzIHRvIGNyZWF0ZSBhIHN0YW5kYXJkIGFuaW1hdGlvblxuZnVuY3Rpb24gZ2VuRngoIHR5cGUsIGluY2x1ZGVXaWR0aCApIHtcblx0dmFyIHdoaWNoLFxuXHRcdGkgPSAwLFxuXHRcdGF0dHJzID0geyBoZWlnaHQ6IHR5cGUgfTtcblxuXHQvLyBJZiB3ZSBpbmNsdWRlIHdpZHRoLCBzdGVwIHZhbHVlIGlzIDEgdG8gZG8gYWxsIGNzc0V4cGFuZCB2YWx1ZXMsXG5cdC8vIG90aGVyd2lzZSBzdGVwIHZhbHVlIGlzIDIgdG8gc2tpcCBvdmVyIExlZnQgYW5kIFJpZ2h0XG5cdGluY2x1ZGVXaWR0aCA9IGluY2x1ZGVXaWR0aCA/IDEgOiAwO1xuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgLSBpbmNsdWRlV2lkdGggKSB7XG5cdFx0d2hpY2ggPSBjc3NFeHBhbmRbIGkgXTtcblx0XHRhdHRyc1sgXCJtYXJnaW5cIiArIHdoaWNoIF0gPSBhdHRyc1sgXCJwYWRkaW5nXCIgKyB3aGljaCBdID0gdHlwZTtcblx0fVxuXG5cdGlmICggaW5jbHVkZVdpZHRoICkge1xuXHRcdGF0dHJzLm9wYWNpdHkgPSBhdHRycy53aWR0aCA9IHR5cGU7XG5cdH1cblxuXHRyZXR1cm4gYXR0cnM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR3ZWVuKCB2YWx1ZSwgcHJvcCwgYW5pbWF0aW9uICkge1xuXHR2YXIgdHdlZW4sXG5cdFx0Y29sbGVjdGlvbiA9ICggQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW10gKS5jb25jYXQoIEFuaW1hdGlvbi50d2VlbmVyc1sgXCIqXCIgXSApLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRpZiAoICggdHdlZW4gPSBjb2xsZWN0aW9uWyBpbmRleCBdLmNhbGwoIGFuaW1hdGlvbiwgcHJvcCwgdmFsdWUgKSApICkge1xuXG5cdFx0XHQvLyBXZSdyZSBkb25lIHdpdGggdGhpcyBwcm9wZXJ0eVxuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBkZWZhdWx0UHJlZmlsdGVyKCBlbGVtLCBwcm9wcywgb3B0cyApIHtcblx0dmFyIHByb3AsIHZhbHVlLCB0b2dnbGUsIGhvb2tzLCBvbGRmaXJlLCBwcm9wVHdlZW4sIHJlc3RvcmVEaXNwbGF5LCBkaXNwbGF5LFxuXHRcdGlzQm94ID0gXCJ3aWR0aFwiIGluIHByb3BzIHx8IFwiaGVpZ2h0XCIgaW4gcHJvcHMsXG5cdFx0YW5pbSA9IHRoaXMsXG5cdFx0b3JpZyA9IHt9LFxuXHRcdHN0eWxlID0gZWxlbS5zdHlsZSxcblx0XHRoaWRkZW4gPSBlbGVtLm5vZGVUeXBlICYmIGlzSGlkZGVuV2l0aGluVHJlZSggZWxlbSApLFxuXHRcdGRhdGFTaG93ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImZ4c2hvd1wiICk7XG5cblx0Ly8gUXVldWUtc2tpcHBpbmcgYW5pbWF0aW9ucyBoaWphY2sgdGhlIGZ4IGhvb2tzXG5cdGlmICggIW9wdHMucXVldWUgKSB7XG5cdFx0aG9va3MgPSBqUXVlcnkuX3F1ZXVlSG9va3MoIGVsZW0sIFwiZnhcIiApO1xuXHRcdGlmICggaG9va3MudW5xdWV1ZWQgPT0gbnVsbCApIHtcblx0XHRcdGhvb2tzLnVucXVldWVkID0gMDtcblx0XHRcdG9sZGZpcmUgPSBob29rcy5lbXB0eS5maXJlO1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICFob29rcy51bnF1ZXVlZCApIHtcblx0XHRcdFx0XHRvbGRmaXJlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fVxuXHRcdGhvb2tzLnVucXVldWVkKys7XG5cblx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIEVuc3VyZSB0aGUgY29tcGxldGUgaGFuZGxlciBpcyBjYWxsZWQgYmVmb3JlIHRoaXMgY29tcGxldGVzXG5cdFx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGhvb2tzLnVucXVldWVkLS07XG5cdFx0XHRcdGlmICggIWpRdWVyeS5xdWV1ZSggZWxlbSwgXCJmeFwiICkubGVuZ3RoICkge1xuXHRcdFx0XHRcdGhvb2tzLmVtcHR5LmZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIERldGVjdCBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRmb3IgKCBwcm9wIGluIHByb3BzICkge1xuXHRcdHZhbHVlID0gcHJvcHNbIHByb3AgXTtcblx0XHRpZiAoIHJmeHR5cGVzLnRlc3QoIHZhbHVlICkgKSB7XG5cdFx0XHRkZWxldGUgcHJvcHNbIHByb3AgXTtcblx0XHRcdHRvZ2dsZSA9IHRvZ2dsZSB8fCB2YWx1ZSA9PT0gXCJ0b2dnbGVcIjtcblx0XHRcdGlmICggdmFsdWUgPT09ICggaGlkZGVuID8gXCJoaWRlXCIgOiBcInNob3dcIiApICkge1xuXG5cdFx0XHRcdC8vIFByZXRlbmQgdG8gYmUgaGlkZGVuIGlmIHRoaXMgaXMgYSBcInNob3dcIiBhbmRcblx0XHRcdFx0Ly8gdGhlcmUgaXMgc3RpbGwgZGF0YSBmcm9tIGEgc3RvcHBlZCBzaG93L2hpZGVcblx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gXCJzaG93XCIgJiYgZGF0YVNob3cgJiYgZGF0YVNob3dbIHByb3AgXSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdGhpZGRlbiA9IHRydWU7XG5cblx0XHRcdFx0Ly8gSWdub3JlIGFsbCBvdGhlciBuby1vcCBzaG93L2hpZGUgZGF0YVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvcmlnWyBwcm9wIF0gPSBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdIHx8IGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIEJhaWwgb3V0IGlmIHRoaXMgaXMgYSBuby1vcCBsaWtlIC5oaWRlKCkuaGlkZSgpXG5cdHByb3BUd2VlbiA9ICFqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcHMgKTtcblx0aWYgKCAhcHJvcFR3ZWVuICYmIGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBvcmlnICkgKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Ly8gUmVzdHJpY3QgXCJvdmVyZmxvd1wiIGFuZCBcImRpc3BsYXlcIiBzdHlsZXMgZHVyaW5nIGJveCBhbmltYXRpb25zXG5cdGlmICggaXNCb3ggJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExLCBFZGdlIDEyIC0gMTNcblx0XHQvLyBSZWNvcmQgYWxsIDMgb3ZlcmZsb3cgYXR0cmlidXRlcyBiZWNhdXNlIElFIGRvZXMgbm90IGluZmVyIHRoZSBzaG9ydGhhbmRcblx0XHQvLyBmcm9tIGlkZW50aWNhbGx5LXZhbHVlZCBvdmVyZmxvd1ggYW5kIG92ZXJmbG93WVxuXHRcdG9wdHMub3ZlcmZsb3cgPSBbIHN0eWxlLm92ZXJmbG93LCBzdHlsZS5vdmVyZmxvd1gsIHN0eWxlLm92ZXJmbG93WSBdO1xuXG5cdFx0Ly8gSWRlbnRpZnkgYSBkaXNwbGF5IHR5cGUsIHByZWZlcnJpbmcgb2xkIHNob3cvaGlkZSBkYXRhIG92ZXIgdGhlIENTUyBjYXNjYWRlXG5cdFx0cmVzdG9yZURpc3BsYXkgPSBkYXRhU2hvdyAmJiBkYXRhU2hvdy5kaXNwbGF5O1xuXHRcdGlmICggcmVzdG9yZURpc3BsYXkgPT0gbnVsbCApIHtcblx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApO1xuXHRcdH1cblx0XHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKTtcblx0XHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSApIHtcblx0XHRcdFx0ZGlzcGxheSA9IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHQvLyBHZXQgbm9uZW1wdHkgdmFsdWUocykgYnkgdGVtcG9yYXJpbHkgZm9yY2luZyB2aXNpYmlsaXR5XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSwgdHJ1ZSApO1xuXHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheSB8fCByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFuaW1hdGUgaW5saW5lIGVsZW1lbnRzIGFzIGlubGluZS1ibG9ja1xuXHRcdGlmICggZGlzcGxheSA9PT0gXCJpbmxpbmVcIiB8fCBkaXNwbGF5ID09PSBcImlubGluZS1ibG9ja1wiICYmIHJlc3RvcmVEaXNwbGF5ICE9IG51bGwgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwiZmxvYXRcIiApID09PSBcIm5vbmVcIiApIHtcblxuXHRcdFx0XHQvLyBSZXN0b3JlIHRoZSBvcmlnaW5hbCBkaXNwbGF5IHZhbHVlIGF0IHRoZSBlbmQgb2YgcHVyZSBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRcdFx0XHRpZiAoICFwcm9wVHdlZW4gKSB7XG5cdFx0XHRcdFx0YW5pbS5kb25lKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0ZGlzcGxheSA9IHN0eWxlLmRpc3BsYXk7XG5cdFx0XHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGRpc3BsYXkgPT09IFwibm9uZVwiID8gXCJcIiA6IGRpc3BsYXk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggb3B0cy5vdmVyZmxvdyApIHtcblx0XHRzdHlsZS5vdmVyZmxvdyA9IFwiaGlkZGVuXCI7XG5cdFx0YW5pbS5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0c3R5bGUub3ZlcmZsb3cgPSBvcHRzLm92ZXJmbG93WyAwIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1ggPSBvcHRzLm92ZXJmbG93WyAxIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1kgPSBvcHRzLm92ZXJmbG93WyAyIF07XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50IHNob3cvaGlkZSBhbmltYXRpb25zXG5cdHByb3BUd2VlbiA9IGZhbHNlO1xuXHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cblx0XHQvLyBHZW5lcmFsIHNob3cvaGlkZSBzZXR1cCBmb3IgdGhpcyBlbGVtZW50IGFuaW1hdGlvblxuXHRcdGlmICggIXByb3BUd2VlbiApIHtcblx0XHRcdGlmICggZGF0YVNob3cgKSB7XG5cdFx0XHRcdGlmICggXCJoaWRkZW5cIiBpbiBkYXRhU2hvdyApIHtcblx0XHRcdFx0XHRoaWRkZW4gPSBkYXRhU2hvdy5oaWRkZW47XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFTaG93ID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCBcImZ4c2hvd1wiLCB7IGRpc3BsYXk6IHJlc3RvcmVEaXNwbGF5IH0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RvcmUgaGlkZGVuL3Zpc2libGUgZm9yIHRvZ2dsZSBzbyBgLnN0b3AoKS50b2dnbGUoKWAgXCJyZXZlcnNlc1wiXG5cdFx0XHRpZiAoIHRvZ2dsZSApIHtcblx0XHRcdFx0ZGF0YVNob3cuaGlkZGVuID0gIWhpZGRlbjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2hvdyBlbGVtZW50cyBiZWZvcmUgYW5pbWF0aW5nIHRoZW1cblx0XHRcdGlmICggaGlkZGVuICkge1xuXHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0sIHRydWUgKTtcblx0XHRcdH1cblxuXHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdGFuaW0uZG9uZSggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdFx0Ly8gVGhlIGZpbmFsIHN0ZXAgb2YgYSBcImhpZGVcIiBhbmltYXRpb24gaXMgYWN0dWFsbHkgaGlkaW5nIHRoZSBlbGVtZW50XG5cdFx0XHRcdGlmICggIWhpZGRlbiApIHtcblx0XHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIFwiZnhzaG93XCIgKTtcblx0XHRcdFx0Zm9yICggcHJvcCBpbiBvcmlnICkge1xuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCwgb3JpZ1sgcHJvcCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHQvLyBQZXItcHJvcGVydHkgc2V0dXBcblx0XHRwcm9wVHdlZW4gPSBjcmVhdGVUd2VlbiggaGlkZGVuID8gZGF0YVNob3dbIHByb3AgXSA6IDAsIHByb3AsIGFuaW0gKTtcblx0XHRpZiAoICEoIHByb3AgaW4gZGF0YVNob3cgKSApIHtcblx0XHRcdGRhdGFTaG93WyBwcm9wIF0gPSBwcm9wVHdlZW4uc3RhcnQ7XG5cdFx0XHRpZiAoIGhpZGRlbiApIHtcblx0XHRcdFx0cHJvcFR3ZWVuLmVuZCA9IHByb3BUd2Vlbi5zdGFydDtcblx0XHRcdFx0cHJvcFR3ZWVuLnN0YXJ0ID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJvcEZpbHRlciggcHJvcHMsIHNwZWNpYWxFYXNpbmcgKSB7XG5cdHZhciBpbmRleCwgbmFtZSwgZWFzaW5nLCB2YWx1ZSwgaG9va3M7XG5cblx0Ly8gY2FtZWxDYXNlLCBzcGVjaWFsRWFzaW5nIGFuZCBleHBhbmQgY3NzSG9vayBwYXNzXG5cdGZvciAoIGluZGV4IGluIHByb3BzICkge1xuXHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBpbmRleCApO1xuXHRcdGVhc2luZyA9IHNwZWNpYWxFYXNpbmdbIG5hbWUgXTtcblx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdO1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsdWUgKSApIHtcblx0XHRcdGVhc2luZyA9IHZhbHVlWyAxIF07XG5cdFx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdID0gdmFsdWVbIDAgXTtcblx0XHR9XG5cblx0XHRpZiAoIGluZGV4ICE9PSBuYW1lICkge1xuXHRcdFx0cHJvcHNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0ZGVsZXRlIHByb3BzWyBpbmRleCBdO1xuXHRcdH1cblxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF07XG5cdFx0aWYgKCBob29rcyAmJiBcImV4cGFuZFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsdWUgPSBob29rcy5leHBhbmQoIHZhbHVlICk7XG5cdFx0XHRkZWxldGUgcHJvcHNbIG5hbWUgXTtcblxuXHRcdFx0Ly8gTm90IHF1aXRlICQuZXh0ZW5kLCB0aGlzIHdvbid0IG92ZXJ3cml0ZSBleGlzdGluZyBrZXlzLlxuXHRcdFx0Ly8gUmV1c2luZyAnaW5kZXgnIGJlY2F1c2Ugd2UgaGF2ZSB0aGUgY29ycmVjdCBcIm5hbWVcIlxuXHRcdFx0Zm9yICggaW5kZXggaW4gdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggISggaW5kZXggaW4gcHJvcHMgKSApIHtcblx0XHRcdFx0XHRwcm9wc1sgaW5kZXggXSA9IHZhbHVlWyBpbmRleCBdO1xuXHRcdFx0XHRcdHNwZWNpYWxFYXNpbmdbIGluZGV4IF0gPSBlYXNpbmc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0c3BlY2lhbEVhc2luZ1sgbmFtZSBdID0gZWFzaW5nO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBBbmltYXRpb24oIGVsZW0sIHByb3BlcnRpZXMsIG9wdGlvbnMgKSB7XG5cdHZhciByZXN1bHQsXG5cdFx0c3RvcHBlZCxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gQW5pbWF0aW9uLnByZWZpbHRlcnMubGVuZ3RoLFxuXHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCkuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRG9uJ3QgbWF0Y2ggZWxlbSBpbiB0aGUgOmFuaW1hdGVkIHNlbGVjdG9yXG5cdFx0XHRkZWxldGUgdGljay5lbGVtO1xuXHRcdH0gKSxcblx0XHR0aWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50VGltZSA9IGZ4Tm93IHx8IGNyZWF0ZUZ4Tm93KCksXG5cdFx0XHRcdHJlbWFpbmluZyA9IE1hdGgubWF4KCAwLCBhbmltYXRpb24uc3RhcnRUaW1lICsgYW5pbWF0aW9uLmR1cmF0aW9uIC0gY3VycmVudFRpbWUgKSxcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDIuMyBvbmx5XG5cdFx0XHRcdC8vIEFyY2hhaWMgY3Jhc2ggYnVnIHdvbid0IGFsbG93IHVzIHRvIHVzZSBgMSAtICggMC41IHx8IDAgKWAgKCMxMjQ5Nylcblx0XHRcdFx0dGVtcCA9IHJlbWFpbmluZyAvIGFuaW1hdGlvbi5kdXJhdGlvbiB8fCAwLFxuXHRcdFx0XHRwZXJjZW50ID0gMSAtIHRlbXAsXG5cdFx0XHRcdGluZGV4ID0gMCxcblx0XHRcdFx0bGVuZ3RoID0gYW5pbWF0aW9uLnR3ZWVucy5sZW5ndGg7XG5cblx0XHRcdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCBwZXJjZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBwZXJjZW50LCByZW1haW5pbmcgXSApO1xuXG5cdFx0XHQvLyBJZiB0aGVyZSdzIG1vcmUgdG8gZG8sIHlpZWxkXG5cdFx0XHRpZiAoIHBlcmNlbnQgPCAxICYmIGxlbmd0aCApIHtcblx0XHRcdFx0cmV0dXJuIHJlbWFpbmluZztcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgdGhpcyB3YXMgYW4gZW1wdHkgYW5pbWF0aW9uLCBzeW50aGVzaXplIGEgZmluYWwgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uXG5cdFx0XHRpZiAoICFsZW5ndGggKSB7XG5cdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCAxLCAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVzb2x2ZSB0aGUgYW5pbWF0aW9uIGFuZCByZXBvcnQgaXRzIGNvbmNsdXNpb25cblx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiBdICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSxcblx0XHRhbmltYXRpb24gPSBkZWZlcnJlZC5wcm9taXNlKCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0cHJvcHM6IGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wZXJ0aWVzICksXG5cdFx0XHRvcHRzOiBqUXVlcnkuZXh0ZW5kKCB0cnVlLCB7XG5cdFx0XHRcdHNwZWNpYWxFYXNpbmc6IHt9LFxuXHRcdFx0XHRlYXNpbmc6IGpRdWVyeS5lYXNpbmcuX2RlZmF1bHRcblx0XHRcdH0sIG9wdGlvbnMgKSxcblx0XHRcdG9yaWdpbmFsUHJvcGVydGllczogcHJvcGVydGllcyxcblx0XHRcdG9yaWdpbmFsT3B0aW9uczogb3B0aW9ucyxcblx0XHRcdHN0YXJ0VGltZTogZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuXHRcdFx0dHdlZW5zOiBbXSxcblx0XHRcdGNyZWF0ZVR3ZWVuOiBmdW5jdGlvbiggcHJvcCwgZW5kICkge1xuXHRcdFx0XHR2YXIgdHdlZW4gPSBqUXVlcnkuVHdlZW4oIGVsZW0sIGFuaW1hdGlvbi5vcHRzLCBwcm9wLCBlbmQsXG5cdFx0XHRcdFx0XHRhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nWyBwcm9wIF0gfHwgYW5pbWF0aW9uLm9wdHMuZWFzaW5nICk7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnMucHVzaCggdHdlZW4gKTtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdFx0fSxcblx0XHRcdHN0b3A6IGZ1bmN0aW9uKCBnb3RvRW5kICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwLFxuXG5cdFx0XHRcdFx0Ly8gSWYgd2UgYXJlIGdvaW5nIHRvIHRoZSBlbmQsIHdlIHdhbnQgdG8gcnVuIGFsbCB0aGUgdHdlZW5zXG5cdFx0XHRcdFx0Ly8gb3RoZXJ3aXNlIHdlIHNraXAgdGhpcyBwYXJ0XG5cdFx0XHRcdFx0bGVuZ3RoID0gZ290b0VuZCA/IGFuaW1hdGlvbi50d2VlbnMubGVuZ3RoIDogMDtcblx0XHRcdFx0aWYgKCBzdG9wcGVkICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCAxICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZXNvbHZlIHdoZW4gd2UgcGxheWVkIHRoZSBsYXN0IGZyYW1lOyBvdGhlcndpc2UsIHJlamVjdFxuXHRcdFx0XHRpZiAoIGdvdG9FbmQgKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIDEsIDAgXSApO1xuXHRcdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgZ290b0VuZCBdICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIGdvdG9FbmQgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH0gKSxcblx0XHRwcm9wcyA9IGFuaW1hdGlvbi5wcm9wcztcblxuXHRwcm9wRmlsdGVyKCBwcm9wcywgYW5pbWF0aW9uLm9wdHMuc3BlY2lhbEVhc2luZyApO1xuXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0cmVzdWx0ID0gQW5pbWF0aW9uLnByZWZpbHRlcnNbIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBlbGVtLCBwcm9wcywgYW5pbWF0aW9uLm9wdHMgKTtcblx0XHRpZiAoIHJlc3VsdCApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHJlc3VsdC5zdG9wICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggYW5pbWF0aW9uLmVsZW0sIGFuaW1hdGlvbi5vcHRzLnF1ZXVlICkuc3RvcCA9XG5cdFx0XHRcdFx0alF1ZXJ5LnByb3h5KCByZXN1bHQuc3RvcCwgcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblx0fVxuXG5cdGpRdWVyeS5tYXAoIHByb3BzLCBjcmVhdGVUd2VlbiwgYW5pbWF0aW9uICk7XG5cblx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYW5pbWF0aW9uLm9wdHMuc3RhcnQgKSApIHtcblx0XHRhbmltYXRpb24ub3B0cy5zdGFydC5jYWxsKCBlbGVtLCBhbmltYXRpb24gKTtcblx0fVxuXG5cdC8vIEF0dGFjaCBjYWxsYmFja3MgZnJvbSBvcHRpb25zXG5cdGFuaW1hdGlvblxuXHRcdC5wcm9ncmVzcyggYW5pbWF0aW9uLm9wdHMucHJvZ3Jlc3MgKVxuXHRcdC5kb25lKCBhbmltYXRpb24ub3B0cy5kb25lLCBhbmltYXRpb24ub3B0cy5jb21wbGV0ZSApXG5cdFx0LmZhaWwoIGFuaW1hdGlvbi5vcHRzLmZhaWwgKVxuXHRcdC5hbHdheXMoIGFuaW1hdGlvbi5vcHRzLmFsd2F5cyApO1xuXG5cdGpRdWVyeS5meC50aW1lcihcblx0XHRqUXVlcnkuZXh0ZW5kKCB0aWNrLCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0YW5pbTogYW5pbWF0aW9uLFxuXHRcdFx0cXVldWU6IGFuaW1hdGlvbi5vcHRzLnF1ZXVlXG5cdFx0fSApXG5cdCk7XG5cblx0cmV0dXJuIGFuaW1hdGlvbjtcbn1cblxualF1ZXJ5LkFuaW1hdGlvbiA9IGpRdWVyeS5leHRlbmQoIEFuaW1hdGlvbiwge1xuXG5cdHR3ZWVuZXJzOiB7XG5cdFx0XCIqXCI6IFsgZnVuY3Rpb24oIHByb3AsIHZhbHVlICkge1xuXHRcdFx0dmFyIHR3ZWVuID0gdGhpcy5jcmVhdGVUd2VlbiggcHJvcCwgdmFsdWUgKTtcblx0XHRcdGFkanVzdENTUyggdHdlZW4uZWxlbSwgcHJvcCwgcmNzc051bS5leGVjKCB2YWx1ZSApLCB0d2VlbiApO1xuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH0gXVxuXHR9LFxuXG5cdHR3ZWVuZXI6IGZ1bmN0aW9uKCBwcm9wcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcHJvcHMgKSApIHtcblx0XHRcdGNhbGxiYWNrID0gcHJvcHM7XG5cdFx0XHRwcm9wcyA9IFsgXCIqXCIgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvcHMgPSBwcm9wcy5tYXRjaCggcm5vdGh0bWx3aGl0ZSApO1xuXHRcdH1cblxuXHRcdHZhciBwcm9wLFxuXHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0bGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdHByb3AgPSBwcm9wc1sgaW5kZXggXTtcblx0XHRcdEFuaW1hdGlvbi50d2VlbmVyc1sgcHJvcCBdID0gQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW107XG5cdFx0XHRBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXS51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH1cblx0fSxcblxuXHRwcmVmaWx0ZXJzOiBbIGRlZmF1bHRQcmVmaWx0ZXIgXSxcblxuXHRwcmVmaWx0ZXI6IGZ1bmN0aW9uKCBjYWxsYmFjaywgcHJlcGVuZCApIHtcblx0XHRpZiAoIHByZXBlbmQgKSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy5wdXNoKCBjYWxsYmFjayApO1xuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuc3BlZWQgPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgZm4gKSB7XG5cdHZhciBvcHQgPSBzcGVlZCAmJiB0eXBlb2Ygc3BlZWQgPT09IFwib2JqZWN0XCIgPyBqUXVlcnkuZXh0ZW5kKCB7fSwgc3BlZWQgKSA6IHtcblx0XHRjb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fFxuXHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHNwZWVkICkgJiYgc3BlZWQsXG5cdFx0ZHVyYXRpb246IHNwZWVkLFxuXHRcdGVhc2luZzogZm4gJiYgZWFzaW5nIHx8IGVhc2luZyAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIGVhc2luZyApICYmIGVhc2luZ1xuXHR9O1xuXG5cdC8vIEdvIHRvIHRoZSBlbmQgc3RhdGUgaWYgZnggYXJlIG9mZlxuXHRpZiAoIGpRdWVyeS5meC5vZmYgKSB7XG5cdFx0b3B0LmR1cmF0aW9uID0gMDtcblxuXHR9IGVsc2Uge1xuXHRcdGlmICggdHlwZW9mIG9wdC5kdXJhdGlvbiAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdGlmICggb3B0LmR1cmF0aW9uIGluIGpRdWVyeS5meC5zcGVlZHMgKSB7XG5cdFx0XHRcdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5zcGVlZHNbIG9wdC5kdXJhdGlvbiBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvcHQuZHVyYXRpb24gPSBqUXVlcnkuZnguc3BlZWRzLl9kZWZhdWx0O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBvcHQucXVldWUgLSB0cnVlL3VuZGVmaW5lZC9udWxsIC0+IFwiZnhcIlxuXHRpZiAoIG9wdC5xdWV1ZSA9PSBudWxsIHx8IG9wdC5xdWV1ZSA9PT0gdHJ1ZSApIHtcblx0XHRvcHQucXVldWUgPSBcImZ4XCI7XG5cdH1cblxuXHQvLyBRdWV1ZWluZ1xuXHRvcHQub2xkID0gb3B0LmNvbXBsZXRlO1xuXG5cdG9wdC5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIG9wdC5vbGQgKSApIHtcblx0XHRcdG9wdC5vbGQuY2FsbCggdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0LnF1ZXVlICkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIG9wdC5xdWV1ZSApO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gb3B0O1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmYWRlVG86IGZ1bmN0aW9uKCBzcGVlZCwgdG8sIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cblx0XHQvLyBTaG93IGFueSBoaWRkZW4gZWxlbWVudHMgYWZ0ZXIgc2V0dGluZyBvcGFjaXR5IHRvIDBcblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGlzSGlkZGVuV2l0aGluVHJlZSApLmNzcyggXCJvcGFjaXR5XCIsIDAgKS5zaG93KClcblxuXHRcdFx0Ly8gQW5pbWF0ZSB0byB0aGUgdmFsdWUgc3BlY2lmaWVkXG5cdFx0XHQuZW5kKCkuYW5pbWF0ZSggeyBvcGFjaXR5OiB0byB9LCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9LFxuXHRhbmltYXRlOiBmdW5jdGlvbiggcHJvcCwgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0dmFyIGVtcHR5ID0galF1ZXJ5LmlzRW1wdHlPYmplY3QoIHByb3AgKSxcblx0XHRcdG9wdGFsbCA9IGpRdWVyeS5zcGVlZCggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSxcblx0XHRcdGRvQW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0Ly8gT3BlcmF0ZSBvbiBhIGNvcHkgb2YgcHJvcCBzbyBwZXItcHJvcGVydHkgZWFzaW5nIHdvbid0IGJlIGxvc3Rcblx0XHRcdFx0dmFyIGFuaW0gPSBBbmltYXRpb24oIHRoaXMsIGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wICksIG9wdGFsbCApO1xuXG5cdFx0XHRcdC8vIEVtcHR5IGFuaW1hdGlvbnMsIG9yIGZpbmlzaGluZyByZXNvbHZlcyBpbW1lZGlhdGVseVxuXHRcdFx0XHRpZiAoIGVtcHR5IHx8IGRhdGFQcml2LmdldCggdGhpcywgXCJmaW5pc2hcIiApICkge1xuXHRcdFx0XHRcdGFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0ZG9BbmltYXRpb24uZmluaXNoID0gZG9BbmltYXRpb247XG5cblx0XHRyZXR1cm4gZW1wdHkgfHwgb3B0YWxsLnF1ZXVlID09PSBmYWxzZSA/XG5cdFx0XHR0aGlzLmVhY2goIGRvQW5pbWF0aW9uICkgOlxuXHRcdFx0dGhpcy5xdWV1ZSggb3B0YWxsLnF1ZXVlLCBkb0FuaW1hdGlvbiApO1xuXHR9LFxuXHRzdG9wOiBmdW5jdGlvbiggdHlwZSwgY2xlYXJRdWV1ZSwgZ290b0VuZCApIHtcblx0XHR2YXIgc3RvcFF1ZXVlID0gZnVuY3Rpb24oIGhvb2tzICkge1xuXHRcdFx0dmFyIHN0b3AgPSBob29rcy5zdG9wO1xuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRzdG9wKCBnb3RvRW5kICk7XG5cdFx0fTtcblxuXHRcdGlmICggdHlwZW9mIHR5cGUgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRnb3RvRW5kID0gY2xlYXJRdWV1ZTtcblx0XHRcdGNsZWFyUXVldWUgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKCBjbGVhclF1ZXVlICYmIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dGhpcy5xdWV1ZSggdHlwZSB8fCBcImZ4XCIsIFtdICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgZGVxdWV1ZSA9IHRydWUsXG5cdFx0XHRcdGluZGV4ID0gdHlwZSAhPSBudWxsICYmIHR5cGUgKyBcInF1ZXVlSG9va3NcIixcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApO1xuXG5cdFx0XHRpZiAoIGluZGV4ICkge1xuXHRcdFx0XHRpZiAoIGRhdGFbIGluZGV4IF0gJiYgZGF0YVsgaW5kZXggXS5zdG9wICkge1xuXHRcdFx0XHRcdHN0b3BRdWV1ZSggZGF0YVsgaW5kZXggXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCBpbmRleCBpbiBkYXRhICkge1xuXHRcdFx0XHRcdGlmICggZGF0YVsgaW5kZXggXSAmJiBkYXRhWyBpbmRleCBdLnN0b3AgJiYgcnJ1bi50ZXN0KCBpbmRleCApICkge1xuXHRcdFx0XHRcdFx0c3RvcFF1ZXVlKCBkYXRhWyBpbmRleCBdICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGluZGV4ID0gdGltZXJzLmxlbmd0aDsgaW5kZXgtLTsgKSB7XG5cdFx0XHRcdGlmICggdGltZXJzWyBpbmRleCBdLmVsZW0gPT09IHRoaXMgJiZcblx0XHRcdFx0XHQoIHR5cGUgPT0gbnVsbCB8fCB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSApIHtcblxuXHRcdFx0XHRcdHRpbWVyc1sgaW5kZXggXS5hbmltLnN0b3AoIGdvdG9FbmQgKTtcblx0XHRcdFx0XHRkZXF1ZXVlID0gZmFsc2U7XG5cdFx0XHRcdFx0dGltZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFydCB0aGUgbmV4dCBpbiB0aGUgcXVldWUgaWYgdGhlIGxhc3Qgc3RlcCB3YXNuJ3QgZm9yY2VkLlxuXHRcdFx0Ly8gVGltZXJzIGN1cnJlbnRseSB3aWxsIGNhbGwgdGhlaXIgY29tcGxldGUgY2FsbGJhY2tzLCB3aGljaFxuXHRcdFx0Ly8gd2lsbCBkZXF1ZXVlIGJ1dCBvbmx5IGlmIHRoZXkgd2VyZSBnb3RvRW5kLlxuXHRcdFx0aWYgKCBkZXF1ZXVlIHx8ICFnb3RvRW5kICkge1xuXHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblx0ZmluaXNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRpZiAoIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpbmRleCxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApLFxuXHRcdFx0XHRxdWV1ZSA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlXCIgXSxcblx0XHRcdFx0aG9va3MgPSBkYXRhWyB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgXSxcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0bGVuZ3RoID0gcXVldWUgPyBxdWV1ZS5sZW5ndGggOiAwO1xuXG5cdFx0XHQvLyBFbmFibGUgZmluaXNoaW5nIGZsYWcgb24gcHJpdmF0ZSBkYXRhXG5cdFx0XHRkYXRhLmZpbmlzaCA9IHRydWU7XG5cblx0XHRcdC8vIEVtcHR5IHRoZSBxdWV1ZSBmaXJzdFxuXHRcdFx0alF1ZXJ5LnF1ZXVlKCB0aGlzLCB0eXBlLCBbXSApO1xuXG5cdFx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnN0b3AgKSB7XG5cdFx0XHRcdGhvb2tzLnN0b3AuY2FsbCggdGhpcywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYWN0aXZlIGFuaW1hdGlvbnMsIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJiB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSB7XG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTG9vayBmb3IgYW55IGFuaW1hdGlvbnMgaW4gdGhlIG9sZCBxdWV1ZSBhbmQgZmluaXNoIHRoZW1cblx0XHRcdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGlmICggcXVldWVbIGluZGV4IF0gJiYgcXVldWVbIGluZGV4IF0uZmluaXNoICkge1xuXHRcdFx0XHRcdHF1ZXVlWyBpbmRleCBdLmZpbmlzaC5jYWxsKCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVHVybiBvZmYgZmluaXNoaW5nIGZsYWdcblx0XHRcdGRlbGV0ZSBkYXRhLmZpbmlzaDtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmVhY2goIFsgXCJ0b2dnbGVcIiwgXCJzaG93XCIsIFwiaGlkZVwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgY3NzRm4gPSBqUXVlcnkuZm5bIG5hbWUgXTtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHNwZWVkID09IG51bGwgfHwgdHlwZW9mIHNwZWVkID09PSBcImJvb2xlYW5cIiA/XG5cdFx0XHRjc3NGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOlxuXHRcdFx0dGhpcy5hbmltYXRlKCBnZW5GeCggbmFtZSwgdHJ1ZSApLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG4vLyBHZW5lcmF0ZSBzaG9ydGN1dHMgZm9yIGN1c3RvbSBhbmltYXRpb25zXG5qUXVlcnkuZWFjaCgge1xuXHRzbGlkZURvd246IGdlbkZ4KCBcInNob3dcIiApLFxuXHRzbGlkZVVwOiBnZW5GeCggXCJoaWRlXCIgKSxcblx0c2xpZGVUb2dnbGU6IGdlbkZ4KCBcInRvZ2dsZVwiICksXG5cdGZhZGVJbjogeyBvcGFjaXR5OiBcInNob3dcIiB9LFxuXHRmYWRlT3V0OiB7IG9wYWNpdHk6IFwiaGlkZVwiIH0sXG5cdGZhZGVUb2dnbGU6IHsgb3BhY2l0eTogXCJ0b2dnbGVcIiB9XG59LCBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLmFuaW1hdGUoIHByb3BzLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG5qUXVlcnkudGltZXJzID0gW107XG5qUXVlcnkuZngudGljayA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgdGltZXIsXG5cdFx0aSA9IDAsXG5cdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycztcblxuXHRmeE5vdyA9IGpRdWVyeS5ub3coKTtcblxuXHRmb3IgKCA7IGkgPCB0aW1lcnMubGVuZ3RoOyBpKysgKSB7XG5cdFx0dGltZXIgPSB0aW1lcnNbIGkgXTtcblxuXHRcdC8vIFJ1biB0aGUgdGltZXIgYW5kIHNhZmVseSByZW1vdmUgaXQgd2hlbiBkb25lIChhbGxvd2luZyBmb3IgZXh0ZXJuYWwgcmVtb3ZhbClcblx0XHRpZiAoICF0aW1lcigpICYmIHRpbWVyc1sgaSBdID09PSB0aW1lciApIHtcblx0XHRcdHRpbWVycy5zcGxpY2UoIGktLSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIXRpbWVycy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0b3AoKTtcblx0fVxuXHRmeE5vdyA9IHVuZGVmaW5lZDtcbn07XG5cbmpRdWVyeS5meC50aW1lciA9IGZ1bmN0aW9uKCB0aW1lciApIHtcblx0alF1ZXJ5LnRpbWVycy5wdXNoKCB0aW1lciApO1xuXHRqUXVlcnkuZnguc3RhcnQoKTtcbn07XG5cbmpRdWVyeS5meC5pbnRlcnZhbCA9IDEzO1xualF1ZXJ5LmZ4LnN0YXJ0ID0gZnVuY3Rpb24oKSB7XG5cdGlmICggaW5Qcm9ncmVzcyApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpblByb2dyZXNzID0gdHJ1ZTtcblx0c2NoZWR1bGUoKTtcbn07XG5cbmpRdWVyeS5meC5zdG9wID0gZnVuY3Rpb24oKSB7XG5cdGluUHJvZ3Jlc3MgPSBudWxsO1xufTtcblxualF1ZXJ5LmZ4LnNwZWVkcyA9IHtcblx0c2xvdzogNjAwLFxuXHRmYXN0OiAyMDAsXG5cblx0Ly8gRGVmYXVsdCBzcGVlZFxuXHRfZGVmYXVsdDogNDAwXG59O1xuXG5cbi8vIEJhc2VkIG9mZiBvZiB0aGUgcGx1Z2luIGJ5IENsaW50IEhlbGZlcnMsIHdpdGggcGVybWlzc2lvbi5cbi8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDEwMDMyNDAxNDc0Ny9odHRwOi8vYmxpbmRzaWduYWxzLmNvbS9pbmRleC5waHAvMjAwOS8wNy9qcXVlcnktZGVsYXkvXG5qUXVlcnkuZm4uZGVsYXkgPSBmdW5jdGlvbiggdGltZSwgdHlwZSApIHtcblx0dGltZSA9IGpRdWVyeS5meCA/IGpRdWVyeS5meC5zcGVlZHNbIHRpbWUgXSB8fCB0aW1lIDogdGltZTtcblx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlLCBmdW5jdGlvbiggbmV4dCwgaG9va3MgKSB7XG5cdFx0dmFyIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCggbmV4dCwgdGltZSApO1xuXHRcdGhvb2tzLnN0b3AgPSBmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5jbGVhclRpbWVvdXQoIHRpbWVvdXQgKTtcblx0XHR9O1xuXHR9ICk7XG59O1xuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApLFxuXHRcdHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwic2VsZWN0XCIgKSxcblx0XHRvcHQgPSBzZWxlY3QuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwib3B0aW9uXCIgKSApO1xuXG5cdGlucHV0LnR5cGUgPSBcImNoZWNrYm94XCI7XG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMyBvbmx5XG5cdC8vIERlZmF1bHQgdmFsdWUgZm9yIGEgY2hlY2tib3ggc2hvdWxkIGJlIFwib25cIlxuXHRzdXBwb3J0LmNoZWNrT24gPSBpbnB1dC52YWx1ZSAhPT0gXCJcIjtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTXVzdCBhY2Nlc3Mgc2VsZWN0ZWRJbmRleCB0byBtYWtlIGRlZmF1bHQgb3B0aW9ucyBzZWxlY3Rcblx0c3VwcG9ydC5vcHRTZWxlY3RlZCA9IG9wdC5zZWxlY3RlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gQW4gaW5wdXQgbG9zZXMgaXRzIHZhbHVlIGFmdGVyIGJlY29taW5nIGEgcmFkaW9cblx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblx0aW5wdXQudmFsdWUgPSBcInRcIjtcblx0aW5wdXQudHlwZSA9IFwicmFkaW9cIjtcblx0c3VwcG9ydC5yYWRpb1ZhbHVlID0gaW5wdXQudmFsdWUgPT09IFwidFwiO1xufSApKCk7XG5cblxudmFyIGJvb2xIb29rLFxuXHRhdHRySGFuZGxlID0galF1ZXJ5LmV4cHIuYXR0ckhhbmRsZTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgalF1ZXJ5LmF0dHIsIG5hbWUsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoID4gMSApO1xuXHR9LFxuXG5cdHJlbW92ZUF0dHI6IGZ1bmN0aW9uKCBuYW1lICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIHRoaXMsIG5hbWUgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBEb24ndCBnZXQvc2V0IGF0dHJpYnV0ZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBGYWxsYmFjayB0byBwcm9wIHdoZW4gYXR0cmlidXRlcyBhcmUgbm90IHN1cHBvcnRlZFxuXHRcdGlmICggdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlID09PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5wcm9wKCBlbGVtLCBuYW1lLCB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdC8vIEF0dHJpYnV0ZSBob29rcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgbG93ZXJjYXNlIHZlcnNpb25cblx0XHQvLyBHcmFiIG5lY2Vzc2FyeSBob29rIGlmIG9uZSBpcyBkZWZpbmVkXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5hdHRySG9va3NbIG5hbWUudG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdCggalF1ZXJ5LmV4cHIubWF0Y2guYm9vbC50ZXN0KCBuYW1lICkgPyBib29sSG9vayA6IHVuZGVmaW5lZCApO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGlmICggdmFsdWUgPT09IG51bGwgKSB7XG5cdFx0XHRcdGpRdWVyeS5yZW1vdmVBdHRyKCBlbGVtLCBuYW1lICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBob29rcyAmJiBcInNldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3Muc2V0KCBlbGVtLCB2YWx1ZSwgbmFtZSApICkgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIG5hbWUsIHZhbHVlICsgXCJcIiApO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdC8vIE5vbi1leGlzdGVudCBhdHRyaWJ1dGVzIHJldHVybiBudWxsLCB3ZSBub3JtYWxpemUgdG8gdW5kZWZpbmVkXG5cdFx0cmV0dXJuIHJldCA9PSBudWxsID8gdW5kZWZpbmVkIDogcmV0O1xuXHR9LFxuXG5cdGF0dHJIb29rczoge1xuXHRcdHR5cGU6IHtcblx0XHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0XHRpZiAoICFzdXBwb3J0LnJhZGlvVmFsdWUgJiYgdmFsdWUgPT09IFwicmFkaW9cIiAmJlxuXHRcdFx0XHRcdG5vZGVOYW1lKCBlbGVtLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsID0gZWxlbS52YWx1ZTtcblx0XHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLnZhbHVlID0gdmFsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cmVtb3ZlQXR0cjogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdHZhciBuYW1lLFxuXHRcdFx0aSA9IDAsXG5cblx0XHRcdC8vIEF0dHJpYnV0ZSBuYW1lcyBjYW4gY29udGFpbiBub24tSFRNTCB3aGl0ZXNwYWNlIGNoYXJhY3RlcnNcblx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3N5bnRheC5odG1sI2F0dHJpYnV0ZXMtMlxuXHRcdFx0YXR0ck5hbWVzID0gdmFsdWUgJiYgdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKTtcblxuXHRcdGlmICggYXR0ck5hbWVzICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHR3aGlsZSAoICggbmFtZSA9IGF0dHJOYW1lc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIG5hbWUgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSG9va3MgZm9yIGJvb2xlYW4gYXR0cmlidXRlc1xuYm9vbEhvb2sgPSB7XG5cdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBuYW1lICkge1xuXHRcdGlmICggdmFsdWUgPT09IGZhbHNlICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgYm9vbGVhbiBhdHRyaWJ1dGVzIHdoZW4gc2V0IHRvIGZhbHNlXG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggZWxlbSwgbmFtZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgbmFtZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxufTtcblxualF1ZXJ5LmVhY2goIGpRdWVyeS5leHByLm1hdGNoLmJvb2wuc291cmNlLm1hdGNoKCAvXFx3Ky9nICksIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgZ2V0dGVyID0gYXR0ckhhbmRsZVsgbmFtZSBdIHx8IGpRdWVyeS5maW5kLmF0dHI7XG5cblx0YXR0ckhhbmRsZVsgbmFtZSBdID0gZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciByZXQsIGhhbmRsZSxcblx0XHRcdGxvd2VyY2FzZU5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAoICFpc1hNTCApIHtcblxuXHRcdFx0Ly8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcCBieSB0ZW1wb3JhcmlseSByZW1vdmluZyB0aGlzIGZ1bmN0aW9uIGZyb20gdGhlIGdldHRlclxuXHRcdFx0aGFuZGxlID0gYXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdO1xuXHRcdFx0YXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdID0gcmV0O1xuXHRcdFx0cmV0ID0gZ2V0dGVyKCBlbGVtLCBuYW1lLCBpc1hNTCApICE9IG51bGwgP1xuXHRcdFx0XHRsb3dlcmNhc2VOYW1lIDpcblx0XHRcdFx0bnVsbDtcblx0XHRcdGF0dHJIYW5kbGVbIGxvd2VyY2FzZU5hbWUgXSA9IGhhbmRsZTtcblx0XHR9XG5cdFx0cmV0dXJuIHJldDtcblx0fTtcbn0gKTtcblxuXG5cblxudmFyIHJmb2N1c2FibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFxuXHRyY2xpY2thYmxlID0gL14oPzphfGFyZWEpJC9pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHByb3A6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBqUXVlcnkucHJvcCwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH0sXG5cblx0cmVtb3ZlUHJvcDogZnVuY3Rpb24oIG5hbWUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRkZWxldGUgdGhpc1sgalF1ZXJ5LnByb3BGaXhbIG5hbWUgXSB8fCBuYW1lIF07XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0cHJvcDogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdHZhciByZXQsIGhvb2tzLFxuXHRcdFx0blR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuXG5cdFx0Ly8gRG9uJ3QgZ2V0L3NldCBwcm9wZXJ0aWVzIG9uIHRleHQsIGNvbW1lbnQgYW5kIGF0dHJpYnV0ZSBub2Rlc1xuXHRcdGlmICggblR5cGUgPT09IDMgfHwgblR5cGUgPT09IDggfHwgblR5cGUgPT09IDIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cblx0XHRcdC8vIEZpeCBuYW1lIGFuZCBhdHRhY2ggaG9va3Ncblx0XHRcdG5hbWUgPSBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWU7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5wcm9wSG9va3NbIG5hbWUgXTtcblx0XHR9XG5cblx0XHRpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIGhvb2tzICYmIFwic2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gKCBlbGVtWyBuYW1lIF0gPSB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldHVybiBlbGVtWyBuYW1lIF07XG5cdH0sXG5cblx0cHJvcEhvb2tzOiB7XG5cdFx0dGFiSW5kZXg6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHRcdFx0XHQvLyBlbGVtLnRhYkluZGV4IGRvZXNuJ3QgYWx3YXlzIHJldHVybiB0aGVcblx0XHRcdFx0Ly8gY29ycmVjdCB2YWx1ZSB3aGVuIGl0IGhhc24ndCBiZWVuIGV4cGxpY2l0bHkgc2V0XG5cdFx0XHRcdC8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDE0MTExNjIzMzM0Ny9odHRwOi8vZmx1aWRwcm9qZWN0Lm9yZy9ibG9nLzIwMDgvMDEvMDkvZ2V0dGluZy1zZXR0aW5nLWFuZC1yZW1vdmluZy10YWJpbmRleC12YWx1ZXMtd2l0aC1qYXZhc2NyaXB0L1xuXHRcdFx0XHQvLyBVc2UgcHJvcGVyIGF0dHJpYnV0ZSByZXRyaWV2YWwoIzEyMDcyKVxuXHRcdFx0XHR2YXIgdGFiaW5kZXggPSBqUXVlcnkuZmluZC5hdHRyKCBlbGVtLCBcInRhYmluZGV4XCIgKTtcblxuXHRcdFx0XHRpZiAoIHRhYmluZGV4ICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXJzZUludCggdGFiaW5kZXgsIDEwICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0cmZvY3VzYWJsZS50ZXN0KCBlbGVtLm5vZGVOYW1lICkgfHxcblx0XHRcdFx0XHRyY2xpY2thYmxlLnRlc3QoIGVsZW0ubm9kZU5hbWUgKSAmJlxuXHRcdFx0XHRcdGVsZW0uaHJlZlxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cHJvcEZpeDoge1xuXHRcdFwiZm9yXCI6IFwiaHRtbEZvclwiLFxuXHRcdFwiY2xhc3NcIjogXCJjbGFzc05hbWVcIlxuXHR9XG59ICk7XG5cbi8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuLy8gQWNjZXNzaW5nIHRoZSBzZWxlY3RlZEluZGV4IHByb3BlcnR5XG4vLyBmb3JjZXMgdGhlIGJyb3dzZXIgdG8gcmVzcGVjdCBzZXR0aW5nIHNlbGVjdGVkXG4vLyBvbiB0aGUgb3B0aW9uXG4vLyBUaGUgZ2V0dGVyIGVuc3VyZXMgYSBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZFxuLy8gd2hlbiBpbiBhbiBvcHRncm91cFxuLy8gZXNsaW50IHJ1bGUgXCJuby11bnVzZWQtZXhwcmVzc2lvbnNcIiBpcyBkaXNhYmxlZCBmb3IgdGhpcyBjb2RlXG4vLyBzaW5jZSBpdCBjb25zaWRlcnMgc3VjaCBhY2Nlc3Npb25zIG5vb3BcbmlmICggIXN1cHBvcnQub3B0U2VsZWN0ZWQgKSB7XG5cdGpRdWVyeS5wcm9wSG9va3Muc2VsZWN0ZWQgPSB7XG5cdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0LyogZXNsaW50IG5vLXVudXNlZC1leHByZXNzaW9uczogXCJvZmZcIiAqL1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgJiYgcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9LFxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdC8qIGVzbGludCBuby11bnVzZWQtZXhwcmVzc2lvbnM6IFwib2ZmXCIgKi9cblxuXHRcdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRcdGlmICggcGFyZW50ICkge1xuXHRcdFx0XHRwYXJlbnQuc2VsZWN0ZWRJbmRleDtcblxuXHRcdFx0XHRpZiAoIHBhcmVudC5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbmpRdWVyeS5lYWNoKCBbXG5cdFwidGFiSW5kZXhcIixcblx0XCJyZWFkT25seVwiLFxuXHRcIm1heExlbmd0aFwiLFxuXHRcImNlbGxTcGFjaW5nXCIsXG5cdFwiY2VsbFBhZGRpbmdcIixcblx0XCJyb3dTcGFuXCIsXG5cdFwiY29sU3BhblwiLFxuXHRcInVzZU1hcFwiLFxuXHRcImZyYW1lQm9yZGVyXCIsXG5cdFwiY29udGVudEVkaXRhYmxlXCJcbl0sIGZ1bmN0aW9uKCkge1xuXHRqUXVlcnkucHJvcEZpeFsgdGhpcy50b0xvd2VyQ2FzZSgpIF0gPSB0aGlzO1xufSApO1xuXG5cblxuXG5cdC8vIFN0cmlwIGFuZCBjb2xsYXBzZSB3aGl0ZXNwYWNlIGFjY29yZGluZyB0byBIVE1MIHNwZWNcblx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvaW5mcmFzdHJ1Y3R1cmUuaHRtbCNzdHJpcC1hbmQtY29sbGFwc2Utd2hpdGVzcGFjZVxuXHRmdW5jdGlvbiBzdHJpcEFuZENvbGxhcHNlKCB2YWx1ZSApIHtcblx0XHR2YXIgdG9rZW5zID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblx0XHRyZXR1cm4gdG9rZW5zLmpvaW4oIFwiIFwiICk7XG5cdH1cblxuXG5mdW5jdGlvbiBnZXRDbGFzcyggZWxlbSApIHtcblx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlICYmIGVsZW0uZ2V0QXR0cmlidXRlKCBcImNsYXNzXCIgKSB8fCBcIlwiO1xufVxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGFkZENsYXNzOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGNsYXNzZXMsIGVsZW0sIGN1ciwgY3VyVmFsdWUsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmFkZENsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCBnZXRDbGFzcyggdGhpcyApICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZSApIHtcblx0XHRcdGNsYXNzZXMgPSB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRoaXNbIGkrKyBdICkgKSB7XG5cdFx0XHRcdGN1clZhbHVlID0gZ2V0Q2xhc3MoIGVsZW0gKTtcblx0XHRcdFx0Y3VyID0gZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAoIFwiIFwiICsgc3RyaXBBbmRDb2xsYXBzZSggY3VyVmFsdWUgKSArIFwiIFwiICk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGNsYXp6ID0gY2xhc3Nlc1sgaisrIF0gKSApIHtcblx0XHRcdFx0XHRcdGlmICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApIDwgMCApIHtcblx0XHRcdFx0XHRcdFx0Y3VyICs9IGNsYXp6ICsgXCIgXCI7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVDbGFzczogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBjbGFzc2VzLCBlbGVtLCBjdXIsIGN1clZhbHVlLCBjbGF6eiwgaiwgZmluYWxWYWx1ZSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBqICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZW1vdmVDbGFzcyggdmFsdWUuY2FsbCggdGhpcywgaiwgZ2V0Q2xhc3MoIHRoaXMgKSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiB0aGlzLmF0dHIoIFwiY2xhc3NcIiwgXCJcIiApO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlICkge1xuXHRcdFx0Y2xhc3NlcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdHdoaWxlICggKCBlbGVtID0gdGhpc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0Y3VyVmFsdWUgPSBnZXRDbGFzcyggZWxlbSApO1xuXG5cdFx0XHRcdC8vIFRoaXMgZXhwcmVzc2lvbiBpcyBoZXJlIGZvciBiZXR0ZXIgY29tcHJlc3NpYmlsaXR5IChzZWUgYWRkQ2xhc3MpXG5cdFx0XHRcdGN1ciA9IGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgKCBcIiBcIiArIHN0cmlwQW5kQ29sbGFwc2UoIGN1clZhbHVlICkgKyBcIiBcIiApO1xuXG5cdFx0XHRcdGlmICggY3VyICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKCBjbGF6eiA9IGNsYXNzZXNbIGorKyBdICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIFJlbW92ZSAqYWxsKiBpbnN0YW5jZXNcblx0XHRcdFx0XHRcdHdoaWxlICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApID4gLTEgKSB7XG5cdFx0XHRcdFx0XHRcdGN1ciA9IGN1ci5yZXBsYWNlKCBcIiBcIiArIGNsYXp6ICsgXCIgXCIsIFwiIFwiICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR0b2dnbGVDbGFzczogZnVuY3Rpb24oIHZhbHVlLCBzdGF0ZVZhbCApIHtcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdGlmICggdHlwZW9mIHN0YXRlVmFsID09PSBcImJvb2xlYW5cIiAmJiB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlVmFsID8gdGhpcy5hZGRDbGFzcyggdmFsdWUgKSA6IHRoaXMucmVtb3ZlQ2xhc3MoIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS50b2dnbGVDbGFzcyhcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCB0aGlzLCBpLCBnZXRDbGFzcyggdGhpcyApLCBzdGF0ZVZhbCApLFxuXHRcdFx0XHRcdHN0YXRlVmFsXG5cdFx0XHRcdCk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2xhc3NOYW1lLCBpLCBzZWxmLCBjbGFzc05hbWVzO1xuXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0Ly8gVG9nZ2xlIGluZGl2aWR1YWwgY2xhc3MgbmFtZXNcblx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdHNlbGYgPSBqUXVlcnkoIHRoaXMgKTtcblx0XHRcdFx0Y2xhc3NOYW1lcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdFx0d2hpbGUgKCAoIGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbIGkrKyBdICkgKSB7XG5cblx0XHRcdFx0XHQvLyBDaGVjayBlYWNoIGNsYXNzTmFtZSBnaXZlbiwgc3BhY2Ugc2VwYXJhdGVkIGxpc3Rcblx0XHRcdFx0XHRpZiAoIHNlbGYuaGFzQ2xhc3MoIGNsYXNzTmFtZSApICkge1xuXHRcdFx0XHRcdFx0c2VsZi5yZW1vdmVDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuYWRkQ2xhc3MoIGNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb2dnbGUgd2hvbGUgY2xhc3MgbmFtZVxuXHRcdFx0fSBlbHNlIGlmICggdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdFx0Y2xhc3NOYW1lID0gZ2V0Q2xhc3MoIHRoaXMgKTtcblx0XHRcdFx0aWYgKCBjbGFzc05hbWUgKSB7XG5cblx0XHRcdFx0XHQvLyBTdG9yZSBjbGFzc05hbWUgaWYgc2V0XG5cdFx0XHRcdFx0ZGF0YVByaXYuc2V0KCB0aGlzLCBcIl9fY2xhc3NOYW1lX19cIiwgY2xhc3NOYW1lICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBJZiB0aGUgZWxlbWVudCBoYXMgYSBjbGFzcyBuYW1lIG9yIGlmIHdlJ3JlIHBhc3NlZCBgZmFsc2VgLFxuXHRcdFx0XHQvLyB0aGVuIHJlbW92ZSB0aGUgd2hvbGUgY2xhc3NuYW1lIChpZiB0aGVyZSB3YXMgb25lLCB0aGUgYWJvdmUgc2F2ZWQgaXQpLlxuXHRcdFx0XHQvLyBPdGhlcndpc2UgYnJpbmcgYmFjayB3aGF0ZXZlciB3YXMgcHJldmlvdXNseSBzYXZlZCAoaWYgYW55dGhpbmcpLFxuXHRcdFx0XHQvLyBmYWxsaW5nIGJhY2sgdG8gdGhlIGVtcHR5IHN0cmluZyBpZiBub3RoaW5nIHdhcyBzdG9yZWQuXG5cdFx0XHRcdGlmICggdGhpcy5zZXRBdHRyaWJ1dGUgKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIixcblx0XHRcdFx0XHRcdGNsYXNzTmFtZSB8fCB2YWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0XHRcdFx0XCJcIiA6XG5cdFx0XHRcdFx0XHRkYXRhUHJpdi5nZXQoIHRoaXMsIFwiX19jbGFzc05hbWVfX1wiICkgfHwgXCJcIlxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0aGFzQ2xhc3M6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgY2xhc3NOYW1lLCBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRjbGFzc05hbWUgPSBcIiBcIiArIHNlbGVjdG9yICsgXCIgXCI7XG5cdFx0d2hpbGUgKCAoIGVsZW0gPSB0aGlzWyBpKysgXSApICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdCggXCIgXCIgKyBzdHJpcEFuZENvbGxhcHNlKCBnZXRDbGFzcyggZWxlbSApICkgKyBcIiBcIiApLmluZGV4T2YoIGNsYXNzTmFtZSApID4gLTEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBycmV0dXJuID0gL1xcci9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHZhbDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBob29rcywgcmV0LCBpc0Z1bmN0aW9uLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRcdGhvb2tzID0galF1ZXJ5LnZhbEhvb2tzWyBlbGVtLnR5cGUgXSB8fFxuXHRcdFx0XHRcdGpRdWVyeS52YWxIb29rc1sgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdFx0aWYgKCBob29rcyAmJlxuXHRcdFx0XHRcdFwiZ2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0XHQoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgXCJ2YWx1ZVwiICkgKSAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXQgPSBlbGVtLnZhbHVlO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSBtb3N0IGNvbW1vbiBzdHJpbmcgY2FzZXNcblx0XHRcdFx0aWYgKCB0eXBlb2YgcmV0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHRcdHJldHVybiByZXQucmVwbGFjZSggcnJldHVybiwgXCJcIiApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gSGFuZGxlIGNhc2VzIHdoZXJlIHZhbHVlIGlzIG51bGwvdW5kZWYgb3IgbnVtYmVyXG5cdFx0XHRcdHJldHVybiByZXQgPT0gbnVsbCA/IFwiXCIgOiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdHZhciB2YWw7XG5cblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGlzRnVuY3Rpb24gKSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlLmNhbGwoIHRoaXMsIGksIGpRdWVyeSggdGhpcyApLnZhbCgpICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVHJlYXQgbnVsbC91bmRlZmluZWQgYXMgXCJcIjsgY29udmVydCBudW1iZXJzIHRvIHN0cmluZ1xuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0dmFsID0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggdHlwZW9mIHZhbCA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsICs9IFwiXCI7XG5cblx0XHRcdH0gZWxzZSBpZiAoIEFycmF5LmlzQXJyYXkoIHZhbCApICkge1xuXHRcdFx0XHR2YWwgPSBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSArIFwiXCI7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0aG9va3MgPSBqUXVlcnkudmFsSG9va3NbIHRoaXMudHlwZSBdIHx8IGpRdWVyeS52YWxIb29rc1sgdGhpcy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdC8vIElmIHNldCByZXR1cm5zIHVuZGVmaW5lZCwgZmFsbCBiYWNrIHRvIG5vcm1hbCBzZXR0aW5nXG5cdFx0XHRpZiAoICFob29rcyB8fCAhKCBcInNldFwiIGluIGhvb2tzICkgfHwgaG9va3Muc2V0KCB0aGlzLCB2YWwsIFwidmFsdWVcIiApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMudmFsdWUgPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0dmFsSG9va3M6IHtcblx0XHRvcHRpb246IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0dmFyIHZhbCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIFwidmFsdWVcIiApO1xuXHRcdFx0XHRyZXR1cm4gdmFsICE9IG51bGwgP1xuXHRcdFx0XHRcdHZhbCA6XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTEwIC0gMTEgb25seVxuXHRcdFx0XHRcdC8vIG9wdGlvbi50ZXh0IHRocm93cyBleGNlcHRpb25zICgjMTQ2ODYsICMxNDg1OClcblx0XHRcdFx0XHQvLyBTdHJpcCBhbmQgY29sbGFwc2Ugd2hpdGVzcGFjZVxuXHRcdFx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvI3N0cmlwLWFuZC1jb2xsYXBzZS13aGl0ZXNwYWNlXG5cdFx0XHRcdFx0c3RyaXBBbmRDb2xsYXBzZSggalF1ZXJ5LnRleHQoIGVsZW0gKSApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c2VsZWN0OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgdmFsdWUsIG9wdGlvbiwgaSxcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdGluZGV4ID0gZWxlbS5zZWxlY3RlZEluZGV4LFxuXHRcdFx0XHRcdG9uZSA9IGVsZW0udHlwZSA9PT0gXCJzZWxlY3Qtb25lXCIsXG5cdFx0XHRcdFx0dmFsdWVzID0gb25lID8gbnVsbCA6IFtdLFxuXHRcdFx0XHRcdG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdGlmICggaW5kZXggPCAwICkge1xuXHRcdFx0XHRcdGkgPSBtYXg7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpID0gb25lID8gaW5kZXggOiAwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTG9vcCB0aHJvdWdoIGFsbCB0aGUgc2VsZWN0ZWQgb3B0aW9uc1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBtYXg7IGkrKyApIHtcblx0XHRcdFx0XHRvcHRpb24gPSBvcHRpb25zWyBpIF07XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuXHRcdFx0XHRcdC8vIElFOC05IGRvZXNuJ3QgdXBkYXRlIHNlbGVjdGVkIGFmdGVyIGZvcm0gcmVzZXQgKCMyNTUxKVxuXHRcdFx0XHRcdGlmICggKCBvcHRpb24uc2VsZWN0ZWQgfHwgaSA9PT0gaW5kZXggKSAmJlxuXG5cdFx0XHRcdFx0XHRcdC8vIERvbid0IHJldHVybiBvcHRpb25zIHRoYXQgYXJlIGRpc2FibGVkIG9yIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdFx0XHRcdFx0IW9wdGlvbi5kaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0XHQoICFvcHRpb24ucGFyZW50Tm9kZS5kaXNhYmxlZCB8fFxuXHRcdFx0XHRcdFx0XHRcdCFub2RlTmFtZSggb3B0aW9uLnBhcmVudE5vZGUsIFwib3B0Z3JvdXBcIiApICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEdldCB0aGUgc3BlY2lmaWMgdmFsdWUgZm9yIHRoZSBvcHRpb25cblx0XHRcdFx0XHRcdHZhbHVlID0galF1ZXJ5KCBvcHRpb24gKS52YWwoKTtcblxuXHRcdFx0XHRcdFx0Ly8gV2UgZG9uJ3QgbmVlZCBhbiBhcnJheSBmb3Igb25lIHNlbGVjdHNcblx0XHRcdFx0XHRcdGlmICggb25lICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIE11bHRpLVNlbGVjdHMgcmV0dXJuIGFuIGFycmF5XG5cdFx0XHRcdFx0XHR2YWx1ZXMucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fSxcblxuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBvcHRpb25TZXQsIG9wdGlvbixcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdHZhbHVlcyA9IGpRdWVyeS5tYWtlQXJyYXkoIHZhbHVlICksXG5cdFx0XHRcdFx0aSA9IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG5cblx0XHRcdFx0XHRpZiAoIG9wdGlvbi5zZWxlY3RlZCA9XG5cdFx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggalF1ZXJ5LnZhbEhvb2tzLm9wdGlvbi5nZXQoIG9wdGlvbiApLCB2YWx1ZXMgKSA+IC0xXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRvcHRpb25TZXQgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tY29uZC1hc3NpZ24gKi9cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcmNlIGJyb3dzZXJzIHRvIGJlaGF2ZSBjb25zaXN0ZW50bHkgd2hlbiBub24tbWF0Y2hpbmcgdmFsdWUgaXMgc2V0XG5cdFx0XHRcdGlmICggIW9wdGlvblNldCApIHtcblx0XHRcdFx0XHRlbGVtLnNlbGVjdGVkSW5kZXggPSAtMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG4vLyBSYWRpb3MgYW5kIGNoZWNrYm94ZXMgZ2V0dGVyL3NldHRlclxualF1ZXJ5LmVhY2goIFsgXCJyYWRpb1wiLCBcImNoZWNrYm94XCIgXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdID0ge1xuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWx1ZSApICkge1xuXHRcdFx0XHRyZXR1cm4gKCBlbGVtLmNoZWNrZWQgPSBqUXVlcnkuaW5BcnJheSggalF1ZXJ5KCBlbGVtICkudmFsKCksIHZhbHVlICkgPiAtMSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0aWYgKCAhc3VwcG9ydC5jaGVja09uICkge1xuXHRcdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdLmdldCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gbnVsbCA/IFwib25cIiA6IGVsZW0udmFsdWU7XG5cdFx0fTtcblx0fVxufSApO1xuXG5cblxuXG4vLyBSZXR1cm4galF1ZXJ5IGZvciBhdHRyaWJ1dGVzLW9ubHkgaW5jbHVzaW9uXG5cblxudmFyIHJmb2N1c01vcnBoID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvO1xuXG5qUXVlcnkuZXh0ZW5kKCBqUXVlcnkuZXZlbnQsIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggZXZlbnQsIGRhdGEsIGVsZW0sIG9ubHlIYW5kbGVycyApIHtcblxuXHRcdHZhciBpLCBjdXIsIHRtcCwgYnViYmxlVHlwZSwgb250eXBlLCBoYW5kbGUsIHNwZWNpYWwsXG5cdFx0XHRldmVudFBhdGggPSBbIGVsZW0gfHwgZG9jdW1lbnQgXSxcblx0XHRcdHR5cGUgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwidHlwZVwiICkgPyBldmVudC50eXBlIDogZXZlbnQsXG5cdFx0XHRuYW1lc3BhY2VzID0gaGFzT3duLmNhbGwoIGV2ZW50LCBcIm5hbWVzcGFjZVwiICkgPyBldmVudC5uYW1lc3BhY2Uuc3BsaXQoIFwiLlwiICkgOiBbXTtcblxuXHRcdGN1ciA9IHRtcCA9IGVsZW0gPSBlbGVtIHx8IGRvY3VtZW50O1xuXG5cdFx0Ly8gRG9uJ3QgZG8gZXZlbnRzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBmb2N1cy9ibHVyIG1vcnBocyB0byBmb2N1c2luL291dDsgZW5zdXJlIHdlJ3JlIG5vdCBmaXJpbmcgdGhlbSByaWdodCBub3dcblx0XHRpZiAoIHJmb2N1c01vcnBoLnRlc3QoIHR5cGUgKyBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlLmluZGV4T2YoIFwiLlwiICkgPiAtMSApIHtcblxuXHRcdFx0Ly8gTmFtZXNwYWNlZCB0cmlnZ2VyOyBjcmVhdGUgYSByZWdleHAgdG8gbWF0Y2ggZXZlbnQgdHlwZSBpbiBoYW5kbGUoKVxuXHRcdFx0bmFtZXNwYWNlcyA9IHR5cGUuc3BsaXQoIFwiLlwiICk7XG5cdFx0XHR0eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpO1xuXHRcdFx0bmFtZXNwYWNlcy5zb3J0KCk7XG5cdFx0fVxuXHRcdG9udHlwZSA9IHR5cGUuaW5kZXhPZiggXCI6XCIgKSA8IDAgJiYgXCJvblwiICsgdHlwZTtcblxuXHRcdC8vIENhbGxlciBjYW4gcGFzcyBpbiBhIGpRdWVyeS5FdmVudCBvYmplY3QsIE9iamVjdCwgb3IganVzdCBhbiBldmVudCB0eXBlIHN0cmluZ1xuXHRcdGV2ZW50ID0gZXZlbnRbIGpRdWVyeS5leHBhbmRvIF0gP1xuXHRcdFx0ZXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggdHlwZSwgdHlwZW9mIGV2ZW50ID09PSBcIm9iamVjdFwiICYmIGV2ZW50ICk7XG5cblx0XHQvLyBUcmlnZ2VyIGJpdG1hc2s6ICYgMSBmb3IgbmF0aXZlIGhhbmRsZXJzOyAmIDIgZm9yIGpRdWVyeSAoYWx3YXlzIHRydWUpXG5cdFx0ZXZlbnQuaXNUcmlnZ2VyID0gb25seUhhbmRsZXJzID8gMiA6IDM7XG5cdFx0ZXZlbnQubmFtZXNwYWNlID0gbmFtZXNwYWNlcy5qb2luKCBcIi5cIiApO1xuXHRcdGV2ZW50LnJuYW1lc3BhY2UgPSBldmVudC5uYW1lc3BhY2UgP1xuXHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICkgOlxuXHRcdFx0bnVsbDtcblxuXHRcdC8vIENsZWFuIHVwIHRoZSBldmVudCBpbiBjYXNlIGl0IGlzIGJlaW5nIHJldXNlZFxuXHRcdGV2ZW50LnJlc3VsdCA9IHVuZGVmaW5lZDtcblx0XHRpZiAoICFldmVudC50YXJnZXQgKSB7XG5cdFx0XHRldmVudC50YXJnZXQgPSBlbGVtO1xuXHRcdH1cblxuXHRcdC8vIENsb25lIGFueSBpbmNvbWluZyBkYXRhIGFuZCBwcmVwZW5kIHRoZSBldmVudCwgY3JlYXRpbmcgdGhlIGhhbmRsZXIgYXJnIGxpc3Rcblx0XHRkYXRhID0gZGF0YSA9PSBudWxsID9cblx0XHRcdFsgZXZlbnQgXSA6XG5cdFx0XHRqUXVlcnkubWFrZUFycmF5KCBkYXRhLCBbIGV2ZW50IF0gKTtcblxuXHRcdC8vIEFsbG93IHNwZWNpYWwgZXZlbnRzIHRvIGRyYXcgb3V0c2lkZSB0aGUgbGluZXNcblx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgc3BlY2lhbC50cmlnZ2VyICYmIHNwZWNpYWwudHJpZ2dlci5hcHBseSggZWxlbSwgZGF0YSApID09PSBmYWxzZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgZXZlbnQgcHJvcGFnYXRpb24gcGF0aCBpbiBhZHZhbmNlLCBwZXIgVzNDIGV2ZW50cyBzcGVjICgjOTk1MSlcblx0XHQvLyBCdWJibGUgdXAgdG8gZG9jdW1lbnQsIHRoZW4gdG8gd2luZG93OyB3YXRjaCBmb3IgYSBnbG9iYWwgb3duZXJEb2N1bWVudCB2YXIgKCM5NzI0KVxuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhc3BlY2lhbC5ub0J1YmJsZSAmJiAhalF1ZXJ5LmlzV2luZG93KCBlbGVtICkgKSB7XG5cblx0XHRcdGJ1YmJsZVR5cGUgPSBzcGVjaWFsLmRlbGVnYXRlVHlwZSB8fCB0eXBlO1xuXHRcdFx0aWYgKCAhcmZvY3VzTW9ycGgudGVzdCggYnViYmxlVHlwZSArIHR5cGUgKSApIHtcblx0XHRcdFx0Y3VyID0gY3VyLnBhcmVudE5vZGU7XG5cdFx0XHR9XG5cdFx0XHRmb3IgKCA7IGN1cjsgY3VyID0gY3VyLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdGV2ZW50UGF0aC5wdXNoKCBjdXIgKTtcblx0XHRcdFx0dG1wID0gY3VyO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPbmx5IGFkZCB3aW5kb3cgaWYgd2UgZ290IHRvIGRvY3VtZW50IChlLmcuLCBub3QgcGxhaW4gb2JqIG9yIGRldGFjaGVkIERPTSlcblx0XHRcdGlmICggdG1wID09PSAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudCApICkge1xuXHRcdFx0XHRldmVudFBhdGgucHVzaCggdG1wLmRlZmF1bHRWaWV3IHx8IHRtcC5wYXJlbnRXaW5kb3cgfHwgd2luZG93ICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZSBoYW5kbGVycyBvbiB0aGUgZXZlbnQgcGF0aFxuXHRcdGkgPSAwO1xuXHRcdHdoaWxlICggKCBjdXIgPSBldmVudFBhdGhbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdGV2ZW50LnR5cGUgPSBpID4gMSA/XG5cdFx0XHRcdGJ1YmJsZVR5cGUgOlxuXHRcdFx0XHRzcGVjaWFsLmJpbmRUeXBlIHx8IHR5cGU7XG5cblx0XHRcdC8vIGpRdWVyeSBoYW5kbGVyXG5cdFx0XHRoYW5kbGUgPSAoIGRhdGFQcml2LmdldCggY3VyLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdICYmXG5cdFx0XHRcdGRhdGFQcml2LmdldCggY3VyLCBcImhhbmRsZVwiICk7XG5cdFx0XHRpZiAoIGhhbmRsZSApIHtcblx0XHRcdFx0aGFuZGxlLmFwcGx5KCBjdXIsIGRhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTmF0aXZlIGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9IG9udHlwZSAmJiBjdXJbIG9udHlwZSBdO1xuXHRcdFx0aWYgKCBoYW5kbGUgJiYgaGFuZGxlLmFwcGx5ICYmIGFjY2VwdERhdGEoIGN1ciApICkge1xuXHRcdFx0XHRldmVudC5yZXN1bHQgPSBoYW5kbGUuYXBwbHkoIGN1ciwgZGF0YSApO1xuXHRcdFx0XHRpZiAoIGV2ZW50LnJlc3VsdCA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRldmVudC50eXBlID0gdHlwZTtcblxuXHRcdC8vIElmIG5vYm9keSBwcmV2ZW50ZWQgdGhlIGRlZmF1bHQgYWN0aW9uLCBkbyBpdCBub3dcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgIWV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpICkge1xuXG5cdFx0XHRpZiAoICggIXNwZWNpYWwuX2RlZmF1bHQgfHxcblx0XHRcdFx0c3BlY2lhbC5fZGVmYXVsdC5hcHBseSggZXZlbnRQYXRoLnBvcCgpLCBkYXRhICkgPT09IGZhbHNlICkgJiZcblx0XHRcdFx0YWNjZXB0RGF0YSggZWxlbSApICkge1xuXG5cdFx0XHRcdC8vIENhbGwgYSBuYXRpdmUgRE9NIG1ldGhvZCBvbiB0aGUgdGFyZ2V0IHdpdGggdGhlIHNhbWUgbmFtZSBhcyB0aGUgZXZlbnQuXG5cdFx0XHRcdC8vIERvbid0IGRvIGRlZmF1bHQgYWN0aW9ucyBvbiB3aW5kb3csIHRoYXQncyB3aGVyZSBnbG9iYWwgdmFyaWFibGVzIGJlICgjNjE3MClcblx0XHRcdFx0aWYgKCBvbnR5cGUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIGVsZW1bIHR5cGUgXSApICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vIERvbid0IHJlLXRyaWdnZXIgYW4gb25GT08gZXZlbnQgd2hlbiB3ZSBjYWxsIGl0cyBGT08oKSBtZXRob2Rcblx0XHRcdFx0XHR0bXAgPSBlbGVtWyBvbnR5cGUgXTtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSBudWxsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZXZlbnQgcmUtdHJpZ2dlcmluZyBvZiB0aGUgc2FtZSBldmVudCwgc2luY2Ugd2UgYWxyZWFkeSBidWJibGVkIGl0IGFib3ZlXG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHR5cGU7XG5cdFx0XHRcdFx0ZWxlbVsgdHlwZSBdKCk7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSB0bXA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHQvLyBQaWdneWJhY2sgb24gYSBkb25vciBldmVudCB0byBzaW11bGF0ZSBhIGRpZmZlcmVudCBvbmVcblx0Ly8gVXNlZCBvbmx5IGZvciBgZm9jdXMoaW4gfCBvdXQpYCBldmVudHNcblx0c2ltdWxhdGU6IGZ1bmN0aW9uKCB0eXBlLCBlbGVtLCBldmVudCApIHtcblx0XHR2YXIgZSA9IGpRdWVyeS5leHRlbmQoXG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCksXG5cdFx0XHRldmVudCxcblx0XHRcdHtcblx0XHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdFx0aXNTaW11bGF0ZWQ6IHRydWVcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIGUsIG51bGwsIGVsZW0gKTtcblx0fVxuXG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7XG5cdFx0fSApO1xuXHR9LFxuXHR0cmlnZ2VySGFuZGxlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIGVsZW0gPSB0aGlzWyAwIF07XG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCBlbGVtLCB0cnVlICk7XG5cdFx0fVxuXHR9XG59ICk7XG5cblxualF1ZXJ5LmVhY2goICggXCJibHVyIGZvY3VzIGZvY3VzaW4gZm9jdXNvdXQgcmVzaXplIHNjcm9sbCBjbGljayBkYmxjbGljayBcIiArXG5cdFwibW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgXCIgK1xuXHRcImNoYW5nZSBzZWxlY3Qgc3VibWl0IGtleWRvd24ga2V5cHJlc3Mga2V5dXAgY29udGV4dG1lbnVcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRmdW5jdGlvbiggaSwgbmFtZSApIHtcblxuXHQvLyBIYW5kbGUgZXZlbnQgYmluZGluZ1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDAgP1xuXHRcdFx0dGhpcy5vbiggbmFtZSwgbnVsbCwgZGF0YSwgZm4gKSA6XG5cdFx0XHR0aGlzLnRyaWdnZXIoIG5hbWUgKTtcblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRob3ZlcjogZnVuY3Rpb24oIGZuT3ZlciwgZm5PdXQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubW91c2VlbnRlciggZm5PdmVyICkubW91c2VsZWF2ZSggZm5PdXQgfHwgZm5PdmVyICk7XG5cdH1cbn0gKTtcblxuXG5cblxuc3VwcG9ydC5mb2N1c2luID0gXCJvbmZvY3VzaW5cIiBpbiB3aW5kb3c7XG5cblxuLy8gU3VwcG9ydDogRmlyZWZveCA8PTQ0XG4vLyBGaXJlZm94IGRvZXNuJ3QgaGF2ZSBmb2N1cyhpbiB8IG91dCkgZXZlbnRzXG4vLyBSZWxhdGVkIHRpY2tldCAtIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY4Nzc4N1xuLy9cbi8vIFN1cHBvcnQ6IENocm9tZSA8PTQ4IC0gNDksIFNhZmFyaSA8PTkuMCAtIDkuMVxuLy8gZm9jdXMoaW4gfCBvdXQpIGV2ZW50cyBmaXJlIGFmdGVyIGZvY3VzICYgYmx1ciBldmVudHMsXG4vLyB3aGljaCBpcyBzcGVjIHZpb2xhdGlvbiAtIGh0dHA6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnRzLWZvY3VzZXZlbnQtZXZlbnQtb3JkZXJcbi8vIFJlbGF0ZWQgdGlja2V0IC0gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQ5ODU3XG5pZiAoICFzdXBwb3J0LmZvY3VzaW4gKSB7XG5cdGpRdWVyeS5lYWNoKCB7IGZvY3VzOiBcImZvY3VzaW5cIiwgYmx1cjogXCJmb2N1c291dFwiIH0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cblx0XHQvLyBBdHRhY2ggYSBzaW5nbGUgY2FwdHVyaW5nIGhhbmRsZXIgb24gdGhlIGRvY3VtZW50IHdoaWxlIHNvbWVvbmUgd2FudHMgZm9jdXNpbi9mb2N1c291dFxuXHRcdHZhciBoYW5kbGVyID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnNpbXVsYXRlKCBmaXgsIGV2ZW50LnRhcmdldCwgalF1ZXJ5LmV2ZW50LmZpeCggZXZlbnQgKSApO1xuXHRcdH07XG5cblx0XHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZml4IF0gPSB7XG5cdFx0XHRzZXR1cDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBkb2MgPSB0aGlzLm93bmVyRG9jdW1lbnQgfHwgdGhpcyxcblx0XHRcdFx0XHRhdHRhY2hlcyA9IGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXggKTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MuYWRkRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsICggYXR0YWNoZXMgfHwgMCApICsgMSApO1xuXHRcdFx0fSxcblx0XHRcdHRlYXJkb3duOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCApIC0gMTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZG9jLCBmaXggKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsIGF0dGFjaGVzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9ICk7XG59XG52YXIgbG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb247XG5cbnZhciBub25jZSA9IGpRdWVyeS5ub3coKTtcblxudmFyIHJxdWVyeSA9ICggL1xcPy8gKTtcblxuXG5cbi8vIENyb3NzLWJyb3dzZXIgeG1sIHBhcnNpbmdcbmpRdWVyeS5wYXJzZVhNTCA9IGZ1bmN0aW9uKCBkYXRhICkge1xuXHR2YXIgeG1sO1xuXHRpZiAoICFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHlcblx0Ly8gSUUgdGhyb3dzIG9uIHBhcnNlRnJvbVN0cmluZyB3aXRoIGludmFsaWQgaW5wdXQuXG5cdHRyeSB7XG5cdFx0eG1sID0gKCBuZXcgd2luZG93LkRPTVBhcnNlcigpICkucGFyc2VGcm9tU3RyaW5nKCBkYXRhLCBcInRleHQveG1sXCIgKTtcblx0fSBjYXRjaCAoIGUgKSB7XG5cdFx0eG1sID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0aWYgKCAheG1sIHx8IHhtbC5nZXRFbGVtZW50c0J5VGFnTmFtZSggXCJwYXJzZXJlcnJvclwiICkubGVuZ3RoICkge1xuXHRcdGpRdWVyeS5lcnJvciggXCJJbnZhbGlkIFhNTDogXCIgKyBkYXRhICk7XG5cdH1cblx0cmV0dXJuIHhtbDtcbn07XG5cblxudmFyXG5cdHJicmFja2V0ID0gL1xcW1xcXSQvLFxuXHRyQ1JMRiA9IC9cXHI/XFxuL2csXG5cdHJzdWJtaXR0ZXJUeXBlcyA9IC9eKD86c3VibWl0fGJ1dHRvbnxpbWFnZXxyZXNldHxmaWxlKSQvaSxcblx0cnN1Ym1pdHRhYmxlID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pO1xuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyggcHJlZml4LCBvYmosIHRyYWRpdGlvbmFsLCBhZGQgKSB7XG5cdHZhciBuYW1lO1xuXG5cdGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgYXJyYXkgaXRlbS5cblx0XHRqUXVlcnkuZWFjaCggb2JqLCBmdW5jdGlvbiggaSwgdiApIHtcblx0XHRcdGlmICggdHJhZGl0aW9uYWwgfHwgcmJyYWNrZXQudGVzdCggcHJlZml4ICkgKSB7XG5cblx0XHRcdFx0Ly8gVHJlYXQgZWFjaCBhcnJheSBpdGVtIGFzIGEgc2NhbGFyLlxuXHRcdFx0XHRhZGQoIHByZWZpeCwgdiApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIEl0ZW0gaXMgbm9uLXNjYWxhciAoYXJyYXkgb3Igb2JqZWN0KSwgZW5jb2RlIGl0cyBudW1lcmljIGluZGV4LlxuXHRcdFx0XHRidWlsZFBhcmFtcyhcblx0XHRcdFx0XHRwcmVmaXggKyBcIltcIiArICggdHlwZW9mIHYgPT09IFwib2JqZWN0XCIgJiYgdiAhPSBudWxsID8gaSA6IFwiXCIgKSArIFwiXVwiLFxuXHRcdFx0XHRcdHYsXG5cdFx0XHRcdFx0dHJhZGl0aW9uYWwsXG5cdFx0XHRcdFx0YWRkXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdH0gZWxzZSBpZiAoICF0cmFkaXRpb25hbCAmJiBqUXVlcnkudHlwZSggb2JqICkgPT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgb2JqZWN0IGl0ZW0uXG5cdFx0Zm9yICggbmFtZSBpbiBvYmogKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4ICsgXCJbXCIgKyBuYW1lICsgXCJdXCIsIG9ialsgbmFtZSBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXG5cdH0gZWxzZSB7XG5cblx0XHQvLyBTZXJpYWxpemUgc2NhbGFyIGl0ZW0uXG5cdFx0YWRkKCBwcmVmaXgsIG9iaiApO1xuXHR9XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzIG9yIGEgc2V0IG9mXG4vLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmdcbmpRdWVyeS5wYXJhbSA9IGZ1bmN0aW9uKCBhLCB0cmFkaXRpb25hbCApIHtcblx0dmFyIHByZWZpeCxcblx0XHRzID0gW10sXG5cdFx0YWRkID0gZnVuY3Rpb24oIGtleSwgdmFsdWVPckZ1bmN0aW9uICkge1xuXG5cdFx0XHQvLyBJZiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCBpbnZva2UgaXQgYW5kIHVzZSBpdHMgcmV0dXJuIHZhbHVlXG5cdFx0XHR2YXIgdmFsdWUgPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWVPckZ1bmN0aW9uICkgP1xuXHRcdFx0XHR2YWx1ZU9yRnVuY3Rpb24oKSA6XG5cdFx0XHRcdHZhbHVlT3JGdW5jdGlvbjtcblxuXHRcdFx0c1sgcy5sZW5ndGggXSA9IGVuY29kZVVSSUNvbXBvbmVudCgga2V5ICkgKyBcIj1cIiArXG5cdFx0XHRcdGVuY29kZVVSSUNvbXBvbmVudCggdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSApO1xuXHRcdH07XG5cblx0Ly8gSWYgYW4gYXJyYXkgd2FzIHBhc3NlZCBpbiwgYXNzdW1lIHRoYXQgaXQgaXMgYW4gYXJyYXkgb2YgZm9ybSBlbGVtZW50cy5cblx0aWYgKCBBcnJheS5pc0FycmF5KCBhICkgfHwgKCBhLmpxdWVyeSAmJiAhalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGEgKSApICkge1xuXG5cdFx0Ly8gU2VyaWFsaXplIHRoZSBmb3JtIGVsZW1lbnRzXG5cdFx0alF1ZXJ5LmVhY2goIGEsIGZ1bmN0aW9uKCkge1xuXHRcdFx0YWRkKCB0aGlzLm5hbWUsIHRoaXMudmFsdWUgKTtcblx0XHR9ICk7XG5cblx0fSBlbHNlIHtcblxuXHRcdC8vIElmIHRyYWRpdGlvbmFsLCBlbmNvZGUgdGhlIFwib2xkXCIgd2F5ICh0aGUgd2F5IDEuMy4yIG9yIG9sZGVyXG5cdFx0Ly8gZGlkIGl0KSwgb3RoZXJ3aXNlIGVuY29kZSBwYXJhbXMgcmVjdXJzaXZlbHkuXG5cdFx0Zm9yICggcHJlZml4IGluIGEgKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4LCBhWyBwcmVmaXggXSwgdHJhZGl0aW9uYWwsIGFkZCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgcmVzdWx0aW5nIHNlcmlhbGl6YXRpb25cblx0cmV0dXJuIHMuam9pbiggXCImXCIgKTtcbn07XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0c2VyaWFsaXplOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4galF1ZXJ5LnBhcmFtKCB0aGlzLnNlcmlhbGl6ZUFycmF5KCkgKTtcblx0fSxcblx0c2VyaWFsaXplQXJyYXk6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIENhbiBhZGQgcHJvcEhvb2sgZm9yIFwiZWxlbWVudHNcIiB0byBmaWx0ZXIgb3IgYWRkIGZvcm0gZWxlbWVudHNcblx0XHRcdHZhciBlbGVtZW50cyA9IGpRdWVyeS5wcm9wKCB0aGlzLCBcImVsZW1lbnRzXCIgKTtcblx0XHRcdHJldHVybiBlbGVtZW50cyA/IGpRdWVyeS5tYWtlQXJyYXkoIGVsZW1lbnRzICkgOiB0aGlzO1xuXHRcdH0gKVxuXHRcdC5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLnR5cGU7XG5cblx0XHRcdC8vIFVzZSAuaXMoIFwiOmRpc2FibGVkXCIgKSBzbyB0aGF0IGZpZWxkc2V0W2Rpc2FibGVkXSB3b3Jrc1xuXHRcdFx0cmV0dXJuIHRoaXMubmFtZSAmJiAhalF1ZXJ5KCB0aGlzICkuaXMoIFwiOmRpc2FibGVkXCIgKSAmJlxuXHRcdFx0XHRyc3VibWl0dGFibGUudGVzdCggdGhpcy5ub2RlTmFtZSApICYmICFyc3VibWl0dGVyVHlwZXMudGVzdCggdHlwZSApICYmXG5cdFx0XHRcdCggdGhpcy5jaGVja2VkIHx8ICFyY2hlY2thYmxlVHlwZS50ZXN0KCB0eXBlICkgKTtcblx0XHR9IClcblx0XHQubWFwKCBmdW5jdGlvbiggaSwgZWxlbSApIHtcblx0XHRcdHZhciB2YWwgPSBqUXVlcnkoIHRoaXMgKS52YWwoKTtcblxuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsICkgKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHsgbmFtZTogZWxlbS5uYW1lLCB2YWx1ZTogdmFsLnJlcGxhY2UoIHJDUkxGLCBcIlxcclxcblwiICkgfTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4geyBuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWwucmVwbGFjZSggckNSTEYsIFwiXFxyXFxuXCIgKSB9O1xuXHRcdH0gKS5nZXQoKTtcblx0fVxufSApO1xuXG5cbnZhclxuXHRyMjAgPSAvJTIwL2csXG5cdHJoYXNoID0gLyMuKiQvLFxuXHRyYW50aUNhY2hlID0gLyhbPyZdKV89W14mXSovLFxuXHRyaGVhZGVycyA9IC9eKC4qPyk6WyBcXHRdKihbXlxcclxcbl0qKSQvbWcsXG5cblx0Ly8gIzc2NTMsICM4MTI1LCAjODE1MjogbG9jYWwgcHJvdG9jb2wgZGV0ZWN0aW9uXG5cdHJsb2NhbFByb3RvY29sID0gL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8sXG5cdHJub0NvbnRlbnQgPSAvXig/OkdFVHxIRUFEKSQvLFxuXHRycHJvdG9jb2wgPSAvXlxcL1xcLy8sXG5cblx0LyogUHJlZmlsdGVyc1xuXHQgKiAxKSBUaGV5IGFyZSB1c2VmdWwgdG8gaW50cm9kdWNlIGN1c3RvbSBkYXRhVHlwZXMgKHNlZSBhamF4L2pzb25wLmpzIGZvciBhbiBleGFtcGxlKVxuXHQgKiAyKSBUaGVzZSBhcmUgY2FsbGVkOlxuXHQgKiAgICAtIEJFRk9SRSBhc2tpbmcgZm9yIGEgdHJhbnNwb3J0XG5cdCAqICAgIC0gQUZURVIgcGFyYW0gc2VyaWFsaXphdGlvbiAocy5kYXRhIGlzIGEgc3RyaW5nIGlmIHMucHJvY2Vzc0RhdGEgaXMgdHJ1ZSlcblx0ICogMykga2V5IGlzIHRoZSBkYXRhVHlwZVxuXHQgKiA0KSB0aGUgY2F0Y2hhbGwgc3ltYm9sIFwiKlwiIGNhbiBiZSB1c2VkXG5cdCAqIDUpIGV4ZWN1dGlvbiB3aWxsIHN0YXJ0IHdpdGggdHJhbnNwb3J0IGRhdGFUeXBlIGFuZCBUSEVOIGNvbnRpbnVlIGRvd24gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHRwcmVmaWx0ZXJzID0ge30sXG5cblx0LyogVHJhbnNwb3J0cyBiaW5kaW5nc1xuXHQgKiAxKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDIpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogMykgc2VsZWN0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gZ28gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHR0cmFuc3BvcnRzID0ge30sXG5cblx0Ly8gQXZvaWQgY29tbWVudC1wcm9sb2cgY2hhciBzZXF1ZW5jZSAoIzEwMDk4KTsgbXVzdCBhcHBlYXNlIGxpbnQgYW5kIGV2YWRlIGNvbXByZXNzaW9uXG5cdGFsbFR5cGVzID0gXCIqL1wiLmNvbmNhdCggXCIqXCIgKSxcblxuXHQvLyBBbmNob3IgdGFnIGZvciBwYXJzaW5nIHRoZSBkb2N1bWVudCBvcmlnaW5cblx0b3JpZ2luQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblx0b3JpZ2luQW5jaG9yLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXG4vLyBCYXNlIFwiY29uc3RydWN0b3JcIiBmb3IgalF1ZXJ5LmFqYXhQcmVmaWx0ZXIgYW5kIGpRdWVyeS5hamF4VHJhbnNwb3J0XG5mdW5jdGlvbiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHN0cnVjdHVyZSApIHtcblxuXHQvLyBkYXRhVHlwZUV4cHJlc3Npb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIFwiKlwiXG5cdHJldHVybiBmdW5jdGlvbiggZGF0YVR5cGVFeHByZXNzaW9uLCBmdW5jICkge1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVFeHByZXNzaW9uICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZnVuYyA9IGRhdGFUeXBlRXhwcmVzc2lvbjtcblx0XHRcdGRhdGFUeXBlRXhwcmVzc2lvbiA9IFwiKlwiO1xuXHRcdH1cblxuXHRcdHZhciBkYXRhVHlwZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0ZGF0YVR5cGVzID0gZGF0YVR5cGVFeHByZXNzaW9uLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGZ1bmMgKSApIHtcblxuXHRcdFx0Ly8gRm9yIGVhY2ggZGF0YVR5cGUgaW4gdGhlIGRhdGFUeXBlRXhwcmVzc2lvblxuXHRcdFx0d2hpbGUgKCAoIGRhdGFUeXBlID0gZGF0YVR5cGVzWyBpKysgXSApICkge1xuXG5cdFx0XHRcdC8vIFByZXBlbmQgaWYgcmVxdWVzdGVkXG5cdFx0XHRcdGlmICggZGF0YVR5cGVbIDAgXSA9PT0gXCIrXCIgKSB7XG5cdFx0XHRcdFx0ZGF0YVR5cGUgPSBkYXRhVHlwZS5zbGljZSggMSApIHx8IFwiKlwiO1xuXHRcdFx0XHRcdCggc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdICkudW5zaGlmdCggZnVuYyApO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBhcHBlbmRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQoIHN0cnVjdHVyZVsgZGF0YVR5cGUgXSA9IHN0cnVjdHVyZVsgZGF0YVR5cGUgXSB8fCBbXSApLnB1c2goIGZ1bmMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxuLy8gQmFzZSBpbnNwZWN0aW9uIGZ1bmN0aW9uIGZvciBwcmVmaWx0ZXJzIGFuZCB0cmFuc3BvcnRzXG5mdW5jdGlvbiBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlLCBvcHRpb25zLCBvcmlnaW5hbE9wdGlvbnMsIGpxWEhSICkge1xuXG5cdHZhciBpbnNwZWN0ZWQgPSB7fSxcblx0XHRzZWVraW5nVHJhbnNwb3J0ID0gKCBzdHJ1Y3R1cmUgPT09IHRyYW5zcG9ydHMgKTtcblxuXHRmdW5jdGlvbiBpbnNwZWN0KCBkYXRhVHlwZSApIHtcblx0XHR2YXIgc2VsZWN0ZWQ7XG5cdFx0aW5zcGVjdGVkWyBkYXRhVHlwZSBdID0gdHJ1ZTtcblx0XHRqUXVlcnkuZWFjaCggc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdLCBmdW5jdGlvbiggXywgcHJlZmlsdGVyT3JGYWN0b3J5ICkge1xuXHRcdFx0dmFyIGRhdGFUeXBlT3JUcmFuc3BvcnQgPSBwcmVmaWx0ZXJPckZhY3RvcnkoIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKTtcblx0XHRcdGlmICggdHlwZW9mIGRhdGFUeXBlT3JUcmFuc3BvcnQgPT09IFwic3RyaW5nXCIgJiZcblx0XHRcdFx0IXNlZWtpbmdUcmFuc3BvcnQgJiYgIWluc3BlY3RlZFsgZGF0YVR5cGVPclRyYW5zcG9ydCBdICkge1xuXG5cdFx0XHRcdG9wdGlvbnMuZGF0YVR5cGVzLnVuc2hpZnQoIGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdFx0aW5zcGVjdCggZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCBzZWVraW5nVHJhbnNwb3J0ICkge1xuXHRcdFx0XHRyZXR1cm4gISggc2VsZWN0ZWQgPSBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcdHJldHVybiBzZWxlY3RlZDtcblx0fVxuXG5cdHJldHVybiBpbnNwZWN0KCBvcHRpb25zLmRhdGFUeXBlc1sgMCBdICkgfHwgIWluc3BlY3RlZFsgXCIqXCIgXSAmJiBpbnNwZWN0KCBcIipcIiApO1xufVxuXG4vLyBBIHNwZWNpYWwgZXh0ZW5kIGZvciBhamF4IG9wdGlvbnNcbi8vIHRoYXQgdGFrZXMgXCJmbGF0XCIgb3B0aW9ucyAobm90IHRvIGJlIGRlZXAgZXh0ZW5kZWQpXG4vLyBGaXhlcyAjOTg4N1xuZnVuY3Rpb24gYWpheEV4dGVuZCggdGFyZ2V0LCBzcmMgKSB7XG5cdHZhciBrZXksIGRlZXAsXG5cdFx0ZmxhdE9wdGlvbnMgPSBqUXVlcnkuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zIHx8IHt9O1xuXG5cdGZvciAoIGtleSBpbiBzcmMgKSB7XG5cdFx0aWYgKCBzcmNbIGtleSBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHQoIGZsYXRPcHRpb25zWyBrZXkgXSA/IHRhcmdldCA6ICggZGVlcCB8fCAoIGRlZXAgPSB7fSApICkgKVsga2V5IF0gPSBzcmNbIGtleSBdO1xuXHRcdH1cblx0fVxuXHRpZiAoIGRlZXAgKSB7XG5cdFx0alF1ZXJ5LmV4dGVuZCggdHJ1ZSwgdGFyZ2V0LCBkZWVwICk7XG5cdH1cblxuXHRyZXR1cm4gdGFyZ2V0O1xufVxuXG4vKiBIYW5kbGVzIHJlc3BvbnNlcyB0byBhbiBhamF4IHJlcXVlc3Q6XG4gKiAtIGZpbmRzIHRoZSByaWdodCBkYXRhVHlwZSAobWVkaWF0ZXMgYmV0d2VlbiBjb250ZW50LXR5cGUgYW5kIGV4cGVjdGVkIGRhdGFUeXBlKVxuICogLSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG4gKi9cbmZ1bmN0aW9uIGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKSB7XG5cblx0dmFyIGN0LCB0eXBlLCBmaW5hbERhdGFUeXBlLCBmaXJzdERhdGFUeXBlLFxuXHRcdGNvbnRlbnRzID0gcy5jb250ZW50cyxcblx0XHRkYXRhVHlwZXMgPSBzLmRhdGFUeXBlcztcblxuXHQvLyBSZW1vdmUgYXV0byBkYXRhVHlwZSBhbmQgZ2V0IGNvbnRlbnQtdHlwZSBpbiB0aGUgcHJvY2Vzc1xuXHR3aGlsZSAoIGRhdGFUeXBlc1sgMCBdID09PSBcIipcIiApIHtcblx0XHRkYXRhVHlwZXMuc2hpZnQoKTtcblx0XHRpZiAoIGN0ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRjdCA9IHMubWltZVR5cGUgfHwganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiQ29udGVudC1UeXBlXCIgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayBpZiB3ZSdyZSBkZWFsaW5nIHdpdGggYSBrbm93biBjb250ZW50LXR5cGVcblx0aWYgKCBjdCApIHtcblx0XHRmb3IgKCB0eXBlIGluIGNvbnRlbnRzICkge1xuXHRcdFx0aWYgKCBjb250ZW50c1sgdHlwZSBdICYmIGNvbnRlbnRzWyB0eXBlIF0udGVzdCggY3QgKSApIHtcblx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHR5cGUgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSByZXNwb25zZSBmb3IgdGhlIGV4cGVjdGVkIGRhdGFUeXBlXG5cdGlmICggZGF0YVR5cGVzWyAwIF0gaW4gcmVzcG9uc2VzICkge1xuXHRcdGZpbmFsRGF0YVR5cGUgPSBkYXRhVHlwZXNbIDAgXTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIFRyeSBjb252ZXJ0aWJsZSBkYXRhVHlwZXNcblx0XHRmb3IgKCB0eXBlIGluIHJlc3BvbnNlcyApIHtcblx0XHRcdGlmICggIWRhdGFUeXBlc1sgMCBdIHx8IHMuY29udmVydGVyc1sgdHlwZSArIFwiIFwiICsgZGF0YVR5cGVzWyAwIF0gXSApIHtcblx0XHRcdFx0ZmluYWxEYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAhZmlyc3REYXRhVHlwZSApIHtcblx0XHRcdFx0Zmlyc3REYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gT3IganVzdCB1c2UgZmlyc3Qgb25lXG5cdFx0ZmluYWxEYXRhVHlwZSA9IGZpbmFsRGF0YVR5cGUgfHwgZmlyc3REYXRhVHlwZTtcblx0fVxuXG5cdC8vIElmIHdlIGZvdW5kIGEgZGF0YVR5cGVcblx0Ly8gV2UgYWRkIHRoZSBkYXRhVHlwZSB0byB0aGUgbGlzdCBpZiBuZWVkZWRcblx0Ly8gYW5kIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyByZXNwb25zZVxuXHRpZiAoIGZpbmFsRGF0YVR5cGUgKSB7XG5cdFx0aWYgKCBmaW5hbERhdGFUeXBlICE9PSBkYXRhVHlwZXNbIDAgXSApIHtcblx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCBmaW5hbERhdGFUeXBlICk7XG5cdFx0fVxuXHRcdHJldHVybiByZXNwb25zZXNbIGZpbmFsRGF0YVR5cGUgXTtcblx0fVxufVxuXG4vKiBDaGFpbiBjb252ZXJzaW9ucyBnaXZlbiB0aGUgcmVxdWVzdCBhbmQgdGhlIG9yaWdpbmFsIHJlc3BvbnNlXG4gKiBBbHNvIHNldHMgdGhlIHJlc3BvbnNlWFhYIGZpZWxkcyBvbiB0aGUganFYSFIgaW5zdGFuY2VcbiAqL1xuZnVuY3Rpb24gYWpheENvbnZlcnQoIHMsIHJlc3BvbnNlLCBqcVhIUiwgaXNTdWNjZXNzICkge1xuXHR2YXIgY29udjIsIGN1cnJlbnQsIGNvbnYsIHRtcCwgcHJldixcblx0XHRjb252ZXJ0ZXJzID0ge30sXG5cblx0XHQvLyBXb3JrIHdpdGggYSBjb3B5IG9mIGRhdGFUeXBlcyBpbiBjYXNlIHdlIG5lZWQgdG8gbW9kaWZ5IGl0IGZvciBjb252ZXJzaW9uXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXMuc2xpY2UoKTtcblxuXHQvLyBDcmVhdGUgY29udmVydGVycyBtYXAgd2l0aCBsb3dlcmNhc2VkIGtleXNcblx0aWYgKCBkYXRhVHlwZXNbIDEgXSApIHtcblx0XHRmb3IgKCBjb252IGluIHMuY29udmVydGVycyApIHtcblx0XHRcdGNvbnZlcnRlcnNbIGNvbnYudG9Mb3dlckNhc2UoKSBdID0gcy5jb252ZXJ0ZXJzWyBjb252IF07XG5cdFx0fVxuXHR9XG5cblx0Y3VycmVudCA9IGRhdGFUeXBlcy5zaGlmdCgpO1xuXG5cdC8vIENvbnZlcnQgdG8gZWFjaCBzZXF1ZW50aWFsIGRhdGFUeXBlXG5cdHdoaWxlICggY3VycmVudCApIHtcblxuXHRcdGlmICggcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdICkge1xuXHRcdFx0anFYSFJbIHMucmVzcG9uc2VGaWVsZHNbIGN1cnJlbnQgXSBdID0gcmVzcG9uc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgdGhlIGRhdGFGaWx0ZXIgaWYgcHJvdmlkZWRcblx0XHRpZiAoICFwcmV2ICYmIGlzU3VjY2VzcyAmJiBzLmRhdGFGaWx0ZXIgKSB7XG5cdFx0XHRyZXNwb25zZSA9IHMuZGF0YUZpbHRlciggcmVzcG9uc2UsIHMuZGF0YVR5cGUgKTtcblx0XHR9XG5cblx0XHRwcmV2ID0gY3VycmVudDtcblx0XHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0XHRpZiAoIGN1cnJlbnQgKSB7XG5cblx0XHRcdC8vIFRoZXJlJ3Mgb25seSB3b3JrIHRvIGRvIGlmIGN1cnJlbnQgZGF0YVR5cGUgaXMgbm9uLWF1dG9cblx0XHRcdGlmICggY3VycmVudCA9PT0gXCIqXCIgKSB7XG5cblx0XHRcdFx0Y3VycmVudCA9IHByZXY7XG5cblx0XHRcdC8vIENvbnZlcnQgcmVzcG9uc2UgaWYgcHJldiBkYXRhVHlwZSBpcyBub24tYXV0byBhbmQgZGlmZmVycyBmcm9tIGN1cnJlbnRcblx0XHRcdH0gZWxzZSBpZiAoIHByZXYgIT09IFwiKlwiICYmIHByZXYgIT09IGN1cnJlbnQgKSB7XG5cblx0XHRcdFx0Ly8gU2VlayBhIGRpcmVjdCBjb252ZXJ0ZXJcblx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIGN1cnJlbnQgXSB8fCBjb252ZXJ0ZXJzWyBcIiogXCIgKyBjdXJyZW50IF07XG5cblx0XHRcdFx0Ly8gSWYgbm9uZSBmb3VuZCwgc2VlayBhIHBhaXJcblx0XHRcdFx0aWYgKCAhY29udiApIHtcblx0XHRcdFx0XHRmb3IgKCBjb252MiBpbiBjb252ZXJ0ZXJzICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJZiBjb252MiBvdXRwdXRzIGN1cnJlbnRcblx0XHRcdFx0XHRcdHRtcCA9IGNvbnYyLnNwbGl0KCBcIiBcIiApO1xuXHRcdFx0XHRcdFx0aWYgKCB0bXBbIDEgXSA9PT0gY3VycmVudCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBJZiBwcmV2IGNhbiBiZSBjb252ZXJ0ZWQgdG8gYWNjZXB0ZWQgaW5wdXRcblx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIHRtcFsgMCBdIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRjb252ZXJ0ZXJzWyBcIiogXCIgKyB0bXBbIDAgXSBdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDb25kZW5zZSBlcXVpdmFsZW5jZSBjb252ZXJ0ZXJzXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBjb252ID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIGNvbnYyIF07XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPdGhlcndpc2UsIGluc2VydCB0aGUgaW50ZXJtZWRpYXRlIGRhdGFUeXBlXG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udmVydGVyc1sgY29udjIgXSAhPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGN1cnJlbnQgPSB0bXBbIDAgXTtcblx0XHRcdFx0XHRcdFx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCB0bXBbIDEgXSApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFwcGx5IGNvbnZlcnRlciAoaWYgbm90IGFuIGVxdWl2YWxlbmNlKVxuXHRcdFx0XHRpZiAoIGNvbnYgIT09IHRydWUgKSB7XG5cblx0XHRcdFx0XHQvLyBVbmxlc3MgZXJyb3JzIGFyZSBhbGxvd2VkIHRvIGJ1YmJsZSwgY2F0Y2ggYW5kIHJldHVybiB0aGVtXG5cdFx0XHRcdFx0aWYgKCBjb252ICYmIHMudGhyb3dzICkge1xuXHRcdFx0XHRcdFx0cmVzcG9uc2UgPSBjb252KCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdFx0XHRzdGF0ZTogXCJwYXJzZXJlcnJvclwiLFxuXHRcdFx0XHRcdFx0XHRcdGVycm9yOiBjb252ID8gZSA6IFwiTm8gY29udmVyc2lvbiBmcm9tIFwiICsgcHJldiArIFwiIHRvIFwiICsgY3VycmVudFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7IHN0YXRlOiBcInN1Y2Nlc3NcIiwgZGF0YTogcmVzcG9uc2UgfTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIENvdW50ZXIgZm9yIGhvbGRpbmcgdGhlIG51bWJlciBvZiBhY3RpdmUgcXVlcmllc1xuXHRhY3RpdmU6IDAsXG5cblx0Ly8gTGFzdC1Nb2RpZmllZCBoZWFkZXIgY2FjaGUgZm9yIG5leHQgcmVxdWVzdFxuXHRsYXN0TW9kaWZpZWQ6IHt9LFxuXHRldGFnOiB7fSxcblxuXHRhamF4U2V0dGluZ3M6IHtcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYsXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRpc0xvY2FsOiBybG9jYWxQcm90b2NvbC50ZXN0KCBsb2NhdGlvbi5wcm90b2NvbCApLFxuXHRcdGdsb2JhbDogdHJ1ZSxcblx0XHRwcm9jZXNzRGF0YTogdHJ1ZSxcblx0XHRhc3luYzogdHJ1ZSxcblx0XHRjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIixcblxuXHRcdC8qXG5cdFx0dGltZW91dDogMCxcblx0XHRkYXRhOiBudWxsLFxuXHRcdGRhdGFUeXBlOiBudWxsLFxuXHRcdHVzZXJuYW1lOiBudWxsLFxuXHRcdHBhc3N3b3JkOiBudWxsLFxuXHRcdGNhY2hlOiBudWxsLFxuXHRcdHRocm93czogZmFsc2UsXG5cdFx0dHJhZGl0aW9uYWw6IGZhbHNlLFxuXHRcdGhlYWRlcnM6IHt9LFxuXHRcdCovXG5cblx0XHRhY2NlcHRzOiB7XG5cdFx0XHRcIipcIjogYWxsVHlwZXMsXG5cdFx0XHR0ZXh0OiBcInRleHQvcGxhaW5cIixcblx0XHRcdGh0bWw6IFwidGV4dC9odG1sXCIsXG5cdFx0XHR4bWw6IFwiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbFwiLFxuXHRcdFx0anNvbjogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIlxuXHRcdH0sXG5cblx0XHRjb250ZW50czoge1xuXHRcdFx0eG1sOiAvXFxieG1sXFxiLyxcblx0XHRcdGh0bWw6IC9cXGJodG1sLyxcblx0XHRcdGpzb246IC9cXGJqc29uXFxiL1xuXHRcdH0sXG5cblx0XHRyZXNwb25zZUZpZWxkczoge1xuXHRcdFx0eG1sOiBcInJlc3BvbnNlWE1MXCIsXG5cdFx0XHR0ZXh0OiBcInJlc3BvbnNlVGV4dFwiLFxuXHRcdFx0anNvbjogXCJyZXNwb25zZUpTT05cIlxuXHRcdH0sXG5cblx0XHQvLyBEYXRhIGNvbnZlcnRlcnNcblx0XHQvLyBLZXlzIHNlcGFyYXRlIHNvdXJjZSAob3IgY2F0Y2hhbGwgXCIqXCIpIGFuZCBkZXN0aW5hdGlvbiB0eXBlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG5cdFx0Y29udmVydGVyczoge1xuXG5cdFx0XHQvLyBDb252ZXJ0IGFueXRoaW5nIHRvIHRleHRcblx0XHRcdFwiKiB0ZXh0XCI6IFN0cmluZyxcblxuXHRcdFx0Ly8gVGV4dCB0byBodG1sICh0cnVlID0gbm8gdHJhbnNmb3JtYXRpb24pXG5cdFx0XHRcInRleHQgaHRtbFwiOiB0cnVlLFxuXG5cdFx0XHQvLyBFdmFsdWF0ZSB0ZXh0IGFzIGEganNvbiBleHByZXNzaW9uXG5cdFx0XHRcInRleHQganNvblwiOiBKU09OLnBhcnNlLFxuXG5cdFx0XHQvLyBQYXJzZSB0ZXh0IGFzIHhtbFxuXHRcdFx0XCJ0ZXh0IHhtbFwiOiBqUXVlcnkucGFyc2VYTUxcblx0XHR9LFxuXG5cdFx0Ly8gRm9yIG9wdGlvbnMgdGhhdCBzaG91bGRuJ3QgYmUgZGVlcCBleHRlbmRlZDpcblx0XHQvLyB5b3UgY2FuIGFkZCB5b3VyIG93biBjdXN0b20gb3B0aW9ucyBoZXJlIGlmXG5cdFx0Ly8gYW5kIHdoZW4geW91IGNyZWF0ZSBvbmUgdGhhdCBzaG91bGRuJ3QgYmVcblx0XHQvLyBkZWVwIGV4dGVuZGVkIChzZWUgYWpheEV4dGVuZClcblx0XHRmbGF0T3B0aW9uczoge1xuXHRcdFx0dXJsOiB0cnVlLFxuXHRcdFx0Y29udGV4dDogdHJ1ZVxuXHRcdH1cblx0fSxcblxuXHQvLyBDcmVhdGVzIGEgZnVsbCBmbGVkZ2VkIHNldHRpbmdzIG9iamVjdCBpbnRvIHRhcmdldFxuXHQvLyB3aXRoIGJvdGggYWpheFNldHRpbmdzIGFuZCBzZXR0aW5ncyBmaWVsZHMuXG5cdC8vIElmIHRhcmdldCBpcyBvbWl0dGVkLCB3cml0ZXMgaW50byBhamF4U2V0dGluZ3MuXG5cdGFqYXhTZXR1cDogZnVuY3Rpb24oIHRhcmdldCwgc2V0dGluZ3MgKSB7XG5cdFx0cmV0dXJuIHNldHRpbmdzID9cblxuXHRcdFx0Ly8gQnVpbGRpbmcgYSBzZXR0aW5ncyBvYmplY3Rcblx0XHRcdGFqYXhFeHRlbmQoIGFqYXhFeHRlbmQoIHRhcmdldCwgalF1ZXJ5LmFqYXhTZXR0aW5ncyApLCBzZXR0aW5ncyApIDpcblxuXHRcdFx0Ly8gRXh0ZW5kaW5nIGFqYXhTZXR0aW5nc1xuXHRcdFx0YWpheEV4dGVuZCggalF1ZXJ5LmFqYXhTZXR0aW5ncywgdGFyZ2V0ICk7XG5cdH0sXG5cblx0YWpheFByZWZpbHRlcjogYWRkVG9QcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBwcmVmaWx0ZXJzICksXG5cdGFqYXhUcmFuc3BvcnQ6IGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cyApLFxuXG5cdC8vIE1haW4gbWV0aG9kXG5cdGFqYXg6IGZ1bmN0aW9uKCB1cmwsIG9wdGlvbnMgKSB7XG5cblx0XHQvLyBJZiB1cmwgaXMgYW4gb2JqZWN0LCBzaW11bGF0ZSBwcmUtMS41IHNpZ25hdHVyZVxuXHRcdGlmICggdHlwZW9mIHVybCA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdG9wdGlvbnMgPSB1cmw7XG5cdFx0XHR1cmwgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gRm9yY2Ugb3B0aW9ucyB0byBiZSBhbiBvYmplY3Rcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdHZhciB0cmFuc3BvcnQsXG5cblx0XHRcdC8vIFVSTCB3aXRob3V0IGFudGktY2FjaGUgcGFyYW1cblx0XHRcdGNhY2hlVVJMLFxuXG5cdFx0XHQvLyBSZXNwb25zZSBoZWFkZXJzXG5cdFx0XHRyZXNwb25zZUhlYWRlcnNTdHJpbmcsXG5cdFx0XHRyZXNwb25zZUhlYWRlcnMsXG5cblx0XHRcdC8vIHRpbWVvdXQgaGFuZGxlXG5cdFx0XHR0aW1lb3V0VGltZXIsXG5cblx0XHRcdC8vIFVybCBjbGVhbnVwIHZhclxuXHRcdFx0dXJsQW5jaG9yLFxuXG5cdFx0XHQvLyBSZXF1ZXN0IHN0YXRlIChiZWNvbWVzIGZhbHNlIHVwb24gc2VuZCBhbmQgdHJ1ZSB1cG9uIGNvbXBsZXRpb24pXG5cdFx0XHRjb21wbGV0ZWQsXG5cblx0XHRcdC8vIFRvIGtub3cgaWYgZ2xvYmFsIGV2ZW50cyBhcmUgdG8gYmUgZGlzcGF0Y2hlZFxuXHRcdFx0ZmlyZUdsb2JhbHMsXG5cblx0XHRcdC8vIExvb3AgdmFyaWFibGVcblx0XHRcdGksXG5cblx0XHRcdC8vIHVuY2FjaGVkIHBhcnQgb2YgdGhlIHVybFxuXHRcdFx0dW5jYWNoZWQsXG5cblx0XHRcdC8vIENyZWF0ZSB0aGUgZmluYWwgb3B0aW9ucyBvYmplY3Rcblx0XHRcdHMgPSBqUXVlcnkuYWpheFNldHVwKCB7fSwgb3B0aW9ucyApLFxuXG5cdFx0XHQvLyBDYWxsYmFja3MgY29udGV4dFxuXHRcdFx0Y2FsbGJhY2tDb250ZXh0ID0gcy5jb250ZXh0IHx8IHMsXG5cblx0XHRcdC8vIENvbnRleHQgZm9yIGdsb2JhbCBldmVudHMgaXMgY2FsbGJhY2tDb250ZXh0IGlmIGl0IGlzIGEgRE9NIG5vZGUgb3IgalF1ZXJ5IGNvbGxlY3Rpb25cblx0XHRcdGdsb2JhbEV2ZW50Q29udGV4dCA9IHMuY29udGV4dCAmJlxuXHRcdFx0XHQoIGNhbGxiYWNrQ29udGV4dC5ub2RlVHlwZSB8fCBjYWxsYmFja0NvbnRleHQuanF1ZXJ5ICkgP1xuXHRcdFx0XHRcdGpRdWVyeSggY2FsbGJhY2tDb250ZXh0ICkgOlxuXHRcdFx0XHRcdGpRdWVyeS5ldmVudCxcblxuXHRcdFx0Ly8gRGVmZXJyZWRzXG5cdFx0XHRkZWZlcnJlZCA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZCA9IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXG5cdFx0XHQvLyBTdGF0dXMtZGVwZW5kZW50IGNhbGxiYWNrc1xuXHRcdFx0c3RhdHVzQ29kZSA9IHMuc3RhdHVzQ29kZSB8fCB7fSxcblxuXHRcdFx0Ly8gSGVhZGVycyAodGhleSBhcmUgc2VudCBhbGwgYXQgb25jZSlcblx0XHRcdHJlcXVlc3RIZWFkZXJzID0ge30sXG5cdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzID0ge30sXG5cblx0XHRcdC8vIERlZmF1bHQgYWJvcnQgbWVzc2FnZVxuXHRcdFx0c3RyQWJvcnQgPSBcImNhbmNlbGVkXCIsXG5cblx0XHRcdC8vIEZha2UgeGhyXG5cdFx0XHRqcVhIUiA9IHtcblx0XHRcdFx0cmVhZHlTdGF0ZTogMCxcblxuXHRcdFx0XHQvLyBCdWlsZHMgaGVhZGVycyBoYXNodGFibGUgaWYgbmVlZGVkXG5cdFx0XHRcdGdldFJlc3BvbnNlSGVhZGVyOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdFx0XHRcdHZhciBtYXRjaDtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHRcdGlmICggIXJlc3BvbnNlSGVhZGVycyApIHtcblx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzID0ge307XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggKCBtYXRjaCA9IHJoZWFkZXJzLmV4ZWMoIHJlc3BvbnNlSGVhZGVyc1N0cmluZyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzWyBtYXRjaFsgMSBdLnRvTG93ZXJDYXNlKCkgXSA9IG1hdGNoWyAyIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1hdGNoID0gcmVzcG9uc2VIZWFkZXJzWyBrZXkudG9Mb3dlckNhc2UoKSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2ggPT0gbnVsbCA/IG51bGwgOiBtYXRjaDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBSYXcgc3RyaW5nXG5cdFx0XHRcdGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNvbXBsZXRlZCA/IHJlc3BvbnNlSGVhZGVyc1N0cmluZyA6IG51bGw7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gQ2FjaGVzIHRoZSBoZWFkZXJcblx0XHRcdFx0c2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRuYW1lID0gcmVxdWVzdEhlYWRlcnNOYW1lc1sgbmFtZS50b0xvd2VyQ2FzZSgpIF0gPVxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSB8fCBuYW1lO1xuXHRcdFx0XHRcdFx0cmVxdWVzdEhlYWRlcnNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBPdmVycmlkZXMgcmVzcG9uc2UgY29udGVudC10eXBlIGhlYWRlclxuXHRcdFx0XHRvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0cy5taW1lVHlwZSA9IHR5cGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRcdHN0YXR1c0NvZGU6IGZ1bmN0aW9uKCBtYXAgKSB7XG5cdFx0XHRcdFx0dmFyIGNvZGU7XG5cdFx0XHRcdFx0aWYgKCBtYXAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBFeGVjdXRlIHRoZSBhcHByb3ByaWF0ZSBjYWxsYmFja3Ncblx0XHRcdFx0XHRcdFx0anFYSFIuYWx3YXlzKCBtYXBbIGpxWEhSLnN0YXR1cyBdICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdC8vIExhenktYWRkIHRoZSBuZXcgY2FsbGJhY2tzIGluIGEgd2F5IHRoYXQgcHJlc2VydmVzIG9sZCBvbmVzXG5cdFx0XHRcdFx0XHRcdGZvciAoIGNvZGUgaW4gbWFwICkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0NvZGVbIGNvZGUgXSA9IFsgc3RhdHVzQ29kZVsgY29kZSBdLCBtYXBbIGNvZGUgXSBdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIENhbmNlbCB0aGUgcmVxdWVzdFxuXHRcdFx0XHRhYm9ydDogZnVuY3Rpb24oIHN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0dmFyIGZpbmFsVGV4dCA9IHN0YXR1c1RleHQgfHwgc3RyQWJvcnQ7XG5cdFx0XHRcdFx0aWYgKCB0cmFuc3BvcnQgKSB7XG5cdFx0XHRcdFx0XHR0cmFuc3BvcnQuYWJvcnQoIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkb25lKCAwLCBmaW5hbFRleHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdC8vIEF0dGFjaCBkZWZlcnJlZHNcblx0XHRkZWZlcnJlZC5wcm9taXNlKCBqcVhIUiApO1xuXG5cdFx0Ly8gQWRkIHByb3RvY29sIGlmIG5vdCBwcm92aWRlZCAocHJlZmlsdGVycyBtaWdodCBleHBlY3QgaXQpXG5cdFx0Ly8gSGFuZGxlIGZhbHN5IHVybCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0ICgjMTAwOTM6IGNvbnNpc3RlbmN5IHdpdGggb2xkIHNpZ25hdHVyZSlcblx0XHQvLyBXZSBhbHNvIHVzZSB0aGUgdXJsIHBhcmFtZXRlciBpZiBhdmFpbGFibGVcblx0XHRzLnVybCA9ICggKCB1cmwgfHwgcy51cmwgfHwgbG9jYXRpb24uaHJlZiApICsgXCJcIiApXG5cdFx0XHQucmVwbGFjZSggcnByb3RvY29sLCBsb2NhdGlvbi5wcm90b2NvbCArIFwiLy9cIiApO1xuXG5cdFx0Ly8gQWxpYXMgbWV0aG9kIG9wdGlvbiB0byB0eXBlIGFzIHBlciB0aWNrZXQgIzEyMDA0XG5cdFx0cy50eXBlID0gb3B0aW9ucy5tZXRob2QgfHwgb3B0aW9ucy50eXBlIHx8IHMubWV0aG9kIHx8IHMudHlwZTtcblxuXHRcdC8vIEV4dHJhY3QgZGF0YVR5cGVzIGxpc3Rcblx0XHRzLmRhdGFUeXBlcyA9ICggcy5kYXRhVHlwZSB8fCBcIipcIiApLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblxuXHRcdC8vIEEgY3Jvc3MtZG9tYWluIHJlcXVlc3QgaXMgaW4gb3JkZXIgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgb3JpZ2luLlxuXHRcdGlmICggcy5jcm9zc0RvbWFpbiA9PSBudWxsICkge1xuXHRcdFx0dXJsQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHRcdFx0Ly8gSUUgdGhyb3dzIGV4Y2VwdGlvbiBvbiBhY2Nlc3NpbmcgdGhlIGhyZWYgcHJvcGVydHkgaWYgdXJsIGlzIG1hbGZvcm1lZCxcblx0XHRcdC8vIGUuZy4gaHR0cDovL2V4YW1wbGUuY29tOjgweC9cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHVybEFuY2hvci5ocmVmID0gcy51cmw7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEgb25seVxuXHRcdFx0XHQvLyBBbmNob3IncyBob3N0IHByb3BlcnR5IGlzbid0IGNvcnJlY3RseSBzZXQgd2hlbiBzLnVybCBpcyByZWxhdGl2ZVxuXHRcdFx0XHR1cmxBbmNob3IuaHJlZiA9IHVybEFuY2hvci5ocmVmO1xuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gb3JpZ2luQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgb3JpZ2luQW5jaG9yLmhvc3QgIT09XG5cdFx0XHRcdFx0dXJsQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgdXJsQW5jaG9yLmhvc3Q7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhbiBlcnJvciBwYXJzaW5nIHRoZSBVUkwsIGFzc3VtZSBpdCBpcyBjcm9zc0RvbWFpbixcblx0XHRcdFx0Ly8gaXQgY2FuIGJlIHJlamVjdGVkIGJ5IHRoZSB0cmFuc3BvcnQgaWYgaXQgaXMgaW52YWxpZFxuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcblx0XHRpZiAoIHMuZGF0YSAmJiBzLnByb2Nlc3NEYXRhICYmIHR5cGVvZiBzLmRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRzLmRhdGEgPSBqUXVlcnkucGFyYW0oIHMuZGF0YSwgcy50cmFkaXRpb25hbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHByZWZpbHRlcnNcblx0XHRpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGEgcHJlZmlsdGVyLCBzdG9wIHRoZXJlXG5cdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4ganFYSFI7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgY2FuIGZpcmUgZ2xvYmFsIGV2ZW50cyBhcyBvZiBub3cgaWYgYXNrZWQgdG9cblx0XHQvLyBEb24ndCBmaXJlIGV2ZW50cyBpZiBqUXVlcnkuZXZlbnQgaXMgdW5kZWZpbmVkIGluIGFuIEFNRC11c2FnZSBzY2VuYXJpbyAoIzE1MTE4KVxuXHRcdGZpcmVHbG9iYWxzID0galF1ZXJ5LmV2ZW50ICYmIHMuZ2xvYmFsO1xuXG5cdFx0Ly8gV2F0Y2ggZm9yIGEgbmV3IHNldCBvZiByZXF1ZXN0c1xuXHRcdGlmICggZmlyZUdsb2JhbHMgJiYgalF1ZXJ5LmFjdGl2ZSsrID09PSAwICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIFwiYWpheFN0YXJ0XCIgKTtcblx0XHR9XG5cblx0XHQvLyBVcHBlcmNhc2UgdGhlIHR5cGVcblx0XHRzLnR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTtcblxuXHRcdC8vIERldGVybWluZSBpZiByZXF1ZXN0IGhhcyBjb250ZW50XG5cdFx0cy5oYXNDb250ZW50ID0gIXJub0NvbnRlbnQudGVzdCggcy50eXBlICk7XG5cblx0XHQvLyBTYXZlIHRoZSBVUkwgaW4gY2FzZSB3ZSdyZSB0b3lpbmcgd2l0aCB0aGUgSWYtTW9kaWZpZWQtU2luY2Vcblx0XHQvLyBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIgbGF0ZXIgb25cblx0XHQvLyBSZW1vdmUgaGFzaCB0byBzaW1wbGlmeSB1cmwgbWFuaXB1bGF0aW9uXG5cdFx0Y2FjaGVVUkwgPSBzLnVybC5yZXBsYWNlKCByaGFzaCwgXCJcIiApO1xuXG5cdFx0Ly8gTW9yZSBvcHRpb25zIGhhbmRsaW5nIGZvciByZXF1ZXN0cyB3aXRoIG5vIGNvbnRlbnRcblx0XHRpZiAoICFzLmhhc0NvbnRlbnQgKSB7XG5cblx0XHRcdC8vIFJlbWVtYmVyIHRoZSBoYXNoIHNvIHdlIGNhbiBwdXQgaXQgYmFja1xuXHRcdFx0dW5jYWNoZWQgPSBzLnVybC5zbGljZSggY2FjaGVVUkwubGVuZ3RoICk7XG5cblx0XHRcdC8vIElmIGRhdGEgaXMgYXZhaWxhYmxlLCBhcHBlbmQgZGF0YSB0byB1cmxcblx0XHRcdGlmICggcy5kYXRhICkge1xuXHRcdFx0XHRjYWNoZVVSTCArPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgcy5kYXRhO1xuXG5cdFx0XHRcdC8vICM5NjgyOiByZW1vdmUgZGF0YSBzbyB0aGF0IGl0J3Mgbm90IHVzZWQgaW4gYW4gZXZlbnR1YWwgcmV0cnlcblx0XHRcdFx0ZGVsZXRlIHMuZGF0YTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9yIHVwZGF0ZSBhbnRpLWNhY2hlIHBhcmFtIGlmIG5lZWRlZFxuXHRcdFx0aWYgKCBzLmNhY2hlID09PSBmYWxzZSApIHtcblx0XHRcdFx0Y2FjaGVVUkwgPSBjYWNoZVVSTC5yZXBsYWNlKCByYW50aUNhY2hlLCBcIiQxXCIgKTtcblx0XHRcdFx0dW5jYWNoZWQgPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgXCJfPVwiICsgKCBub25jZSsrICkgKyB1bmNhY2hlZDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUHV0IGhhc2ggYW5kIGFudGktY2FjaGUgb24gdGhlIFVSTCB0aGF0IHdpbGwgYmUgcmVxdWVzdGVkIChnaC0xNzMyKVxuXHRcdFx0cy51cmwgPSBjYWNoZVVSTCArIHVuY2FjaGVkO1xuXG5cdFx0Ly8gQ2hhbmdlICclMjAnIHRvICcrJyBpZiB0aGlzIGlzIGVuY29kZWQgZm9ybSBib2R5IGNvbnRlbnQgKGdoLTI2NTgpXG5cdFx0fSBlbHNlIGlmICggcy5kYXRhICYmIHMucHJvY2Vzc0RhdGEgJiZcblx0XHRcdCggcy5jb250ZW50VHlwZSB8fCBcIlwiICkuaW5kZXhPZiggXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiApID09PSAwICkge1xuXHRcdFx0cy5kYXRhID0gcy5kYXRhLnJlcGxhY2UoIHIyMCwgXCIrXCIgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdGhlIElmLU1vZGlmaWVkLVNpbmNlIGFuZC9vciBJZi1Ob25lLU1hdGNoIGhlYWRlciwgaWYgaW4gaWZNb2RpZmllZCBtb2RlLlxuXHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0aWYgKCBqUXVlcnkubGFzdE1vZGlmaWVkWyBjYWNoZVVSTCBdICkge1xuXHRcdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIklmLU1vZGlmaWVkLVNpbmNlXCIsIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKTtcblx0XHRcdH1cblx0XHRcdGlmICggalF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTm9uZS1NYXRjaFwiLCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgY29ycmVjdCBoZWFkZXIsIGlmIGRhdGEgaXMgYmVpbmcgc2VudFxuXHRcdGlmICggcy5kYXRhICYmIHMuaGFzQ29udGVudCAmJiBzLmNvbnRlbnRUeXBlICE9PSBmYWxzZSB8fCBvcHRpb25zLmNvbnRlbnRUeXBlICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJDb250ZW50LVR5cGVcIiwgcy5jb250ZW50VHlwZSApO1xuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgQWNjZXB0cyBoZWFkZXIgZm9yIHRoZSBzZXJ2ZXIsIGRlcGVuZGluZyBvbiB0aGUgZGF0YVR5cGVcblx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKFxuXHRcdFx0XCJBY2NlcHRcIixcblx0XHRcdHMuZGF0YVR5cGVzWyAwIF0gJiYgcy5hY2NlcHRzWyBzLmRhdGFUeXBlc1sgMCBdIF0gP1xuXHRcdFx0XHRzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWyAwIF0gXSArXG5cdFx0XHRcdFx0KCBzLmRhdGFUeXBlc1sgMCBdICE9PSBcIipcIiA/IFwiLCBcIiArIGFsbFR5cGVzICsgXCI7IHE9MC4wMVwiIDogXCJcIiApIDpcblx0XHRcdFx0cy5hY2NlcHRzWyBcIipcIiBdXG5cdFx0KTtcblxuXHRcdC8vIENoZWNrIGZvciBoZWFkZXJzIG9wdGlvblxuXHRcdGZvciAoIGkgaW4gcy5oZWFkZXJzICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggaSwgcy5oZWFkZXJzWyBpIF0gKTtcblx0XHR9XG5cblx0XHQvLyBBbGxvdyBjdXN0b20gaGVhZGVycy9taW1ldHlwZXMgYW5kIGVhcmx5IGFib3J0XG5cdFx0aWYgKCBzLmJlZm9yZVNlbmQgJiZcblx0XHRcdCggcy5iZWZvcmVTZW5kLmNhbGwoIGNhbGxiYWNrQ29udGV4dCwganFYSFIsIHMgKSA9PT0gZmFsc2UgfHwgY29tcGxldGVkICkgKSB7XG5cblx0XHRcdC8vIEFib3J0IGlmIG5vdCBkb25lIGFscmVhZHkgYW5kIHJldHVyblxuXHRcdFx0cmV0dXJuIGpxWEhSLmFib3J0KCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWJvcnRpbmcgaXMgbm8gbG9uZ2VyIGEgY2FuY2VsbGF0aW9uXG5cdFx0c3RyQWJvcnQgPSBcImFib3J0XCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrcyBvbiBkZWZlcnJlZHNcblx0XHRjb21wbGV0ZURlZmVycmVkLmFkZCggcy5jb21wbGV0ZSApO1xuXHRcdGpxWEhSLmRvbmUoIHMuc3VjY2VzcyApO1xuXHRcdGpxWEhSLmZhaWwoIHMuZXJyb3IgKTtcblxuXHRcdC8vIEdldCB0cmFuc3BvcnRcblx0XHR0cmFuc3BvcnQgPSBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIG5vIHRyYW5zcG9ydCwgd2UgYXV0by1hYm9ydFxuXHRcdGlmICggIXRyYW5zcG9ydCApIHtcblx0XHRcdGRvbmUoIC0xLCBcIk5vIFRyYW5zcG9ydFwiICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSAxO1xuXG5cdFx0XHQvLyBTZW5kIGdsb2JhbCBldmVudFxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheFNlbmRcIiwgWyBqcVhIUiwgcyBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGFqYXhTZW5kLCBzdG9wIHRoZXJlXG5cdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0cmV0dXJuIGpxWEhSO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaW1lb3V0XG5cdFx0XHRpZiAoIHMuYXN5bmMgJiYgcy50aW1lb3V0ID4gMCApIHtcblx0XHRcdFx0dGltZW91dFRpbWVyID0gd2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGpxWEhSLmFib3J0KCBcInRpbWVvdXRcIiApO1xuXHRcdFx0XHR9LCBzLnRpbWVvdXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29tcGxldGVkID0gZmFsc2U7XG5cdFx0XHRcdHRyYW5zcG9ydC5zZW5kKCByZXF1ZXN0SGVhZGVycywgZG9uZSApO1xuXHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0Ly8gUmV0aHJvdyBwb3N0LWNvbXBsZXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHR0aHJvdyBlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUHJvcGFnYXRlIG90aGVycyBhcyByZXN1bHRzXG5cdFx0XHRcdGRvbmUoIC0xLCBlICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGJhY2sgZm9yIHdoZW4gZXZlcnl0aGluZyBpcyBkb25lXG5cdFx0ZnVuY3Rpb24gZG9uZSggc3RhdHVzLCBuYXRpdmVTdGF0dXNUZXh0LCByZXNwb25zZXMsIGhlYWRlcnMgKSB7XG5cdFx0XHR2YXIgaXNTdWNjZXNzLCBzdWNjZXNzLCBlcnJvciwgcmVzcG9uc2UsIG1vZGlmaWVkLFxuXHRcdFx0XHRzdGF0dXNUZXh0ID0gbmF0aXZlU3RhdHVzVGV4dDtcblxuXHRcdFx0Ly8gSWdub3JlIHJlcGVhdCBpbnZvY2F0aW9uc1xuXHRcdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gQ2xlYXIgdGltZW91dCBpZiBpdCBleGlzdHNcblx0XHRcdGlmICggdGltZW91dFRpbWVyICkge1xuXHRcdFx0XHR3aW5kb3cuY2xlYXJUaW1lb3V0KCB0aW1lb3V0VGltZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRGVyZWZlcmVuY2UgdHJhbnNwb3J0IGZvciBlYXJseSBnYXJiYWdlIGNvbGxlY3Rpb25cblx0XHRcdC8vIChubyBtYXR0ZXIgaG93IGxvbmcgdGhlIGpxWEhSIG9iamVjdCB3aWxsIGJlIHVzZWQpXG5cdFx0XHR0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHRcdC8vIENhY2hlIHJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyA9IGhlYWRlcnMgfHwgXCJcIjtcblxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGVcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSBzdGF0dXMgPiAwID8gNCA6IDA7XG5cblx0XHRcdC8vIERldGVybWluZSBpZiBzdWNjZXNzZnVsXG5cdFx0XHRpc1N1Y2Nlc3MgPSBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDtcblxuXHRcdFx0Ly8gR2V0IHJlc3BvbnNlIGRhdGFcblx0XHRcdGlmICggcmVzcG9uc2VzICkge1xuXHRcdFx0XHRyZXNwb25zZSA9IGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udmVydCBubyBtYXR0ZXIgd2hhdCAodGhhdCB3YXkgcmVzcG9uc2VYWFggZmllbGRzIGFyZSBhbHdheXMgc2V0KVxuXHRcdFx0cmVzcG9uc2UgPSBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKTtcblxuXHRcdFx0Ly8gSWYgc3VjY2Vzc2Z1bCwgaGFuZGxlIHR5cGUgY2hhaW5pbmdcblx0XHRcdGlmICggaXNTdWNjZXNzICkge1xuXG5cdFx0XHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0XHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiTGFzdC1Nb2RpZmllZFwiICk7XG5cdFx0XHRcdFx0aWYgKCBtb2RpZmllZCApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bW9kaWZpZWQgPSBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJldGFnXCIgKTtcblx0XHRcdFx0XHRpZiAoIG1vZGlmaWVkICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpZiBubyBjb250ZW50XG5cdFx0XHRcdGlmICggc3RhdHVzID09PSAyMDQgfHwgcy50eXBlID09PSBcIkhFQURcIiApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub2NvbnRlbnRcIjtcblxuXHRcdFx0XHQvLyBpZiBub3QgbW9kaWZpZWRcblx0XHRcdFx0fSBlbHNlIGlmICggc3RhdHVzID09PSAzMDQgKSB7XG5cdFx0XHRcdFx0c3RhdHVzVGV4dCA9IFwibm90bW9kaWZpZWRcIjtcblxuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGRhdGEsIGxldCdzIGNvbnZlcnQgaXRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gcmVzcG9uc2Uuc3RhdGU7XG5cdFx0XHRcdFx0c3VjY2VzcyA9IHJlc3BvbnNlLmRhdGE7XG5cdFx0XHRcdFx0ZXJyb3IgPSByZXNwb25zZS5lcnJvcjtcblx0XHRcdFx0XHRpc1N1Y2Nlc3MgPSAhZXJyb3I7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gRXh0cmFjdCBlcnJvciBmcm9tIHN0YXR1c1RleHQgYW5kIG5vcm1hbGl6ZSBmb3Igbm9uLWFib3J0c1xuXHRcdFx0XHRlcnJvciA9IHN0YXR1c1RleHQ7XG5cdFx0XHRcdGlmICggc3RhdHVzIHx8ICFzdGF0dXNUZXh0ICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcImVycm9yXCI7XG5cdFx0XHRcdFx0aWYgKCBzdGF0dXMgPCAwICkge1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGRhdGEgZm9yIHRoZSBmYWtlIHhociBvYmplY3Rcblx0XHRcdGpxWEhSLnN0YXR1cyA9IHN0YXR1cztcblx0XHRcdGpxWEhSLnN0YXR1c1RleHQgPSAoIG5hdGl2ZVN0YXR1c1RleHQgfHwgc3RhdHVzVGV4dCApICsgXCJcIjtcblxuXHRcdFx0Ly8gU3VjY2Vzcy9FcnJvclxuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsgc3VjY2Vzcywgc3RhdHVzVGV4dCwganFYSFIgXSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0LCBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRqcVhIUi5zdGF0dXNDb2RlKCBzdGF0dXNDb2RlICk7XG5cdFx0XHRzdGF0dXNDb2RlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggaXNTdWNjZXNzID8gXCJhamF4U3VjY2Vzc1wiIDogXCJhamF4RXJyb3JcIixcblx0XHRcdFx0XHRbIGpxWEhSLCBzLCBpc1N1Y2Nlc3MgPyBzdWNjZXNzIDogZXJyb3IgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb21wbGV0ZVxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZC5maXJlV2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0IF0gKTtcblxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheENvbXBsZXRlXCIsIFsganFYSFIsIHMgXSApO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSB0aGUgZ2xvYmFsIEFKQVggY291bnRlclxuXHRcdFx0XHRpZiAoICEoIC0talF1ZXJ5LmFjdGl2ZSApICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCBcImFqYXhTdG9wXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBqcVhIUjtcblx0fSxcblxuXHRnZXRKU09OOiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdldCggdXJsLCBkYXRhLCBjYWxsYmFjaywgXCJqc29uXCIgKTtcblx0fSxcblxuXHRnZXRTY3JpcHQ6IGZ1bmN0aW9uKCB1cmwsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIHVuZGVmaW5lZCwgY2FsbGJhY2ssIFwic2NyaXB0XCIgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImdldFwiLCBcInBvc3RcIiBdLCBmdW5jdGlvbiggaSwgbWV0aG9kICkge1xuXHRqUXVlcnlbIG1ldGhvZCBdID0gZnVuY3Rpb24oIHVybCwgZGF0YSwgY2FsbGJhY2ssIHR5cGUgKSB7XG5cblx0XHQvLyBTaGlmdCBhcmd1bWVudHMgaWYgZGF0YSBhcmd1bWVudCB3YXMgb21pdHRlZFxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGRhdGEgKSApIHtcblx0XHRcdHR5cGUgPSB0eXBlIHx8IGNhbGxiYWNrO1xuXHRcdFx0Y2FsbGJhY2sgPSBkYXRhO1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBUaGUgdXJsIGNhbiBiZSBhbiBvcHRpb25zIG9iamVjdCAod2hpY2ggdGhlbiBtdXN0IGhhdmUgLnVybClcblx0XHRyZXR1cm4galF1ZXJ5LmFqYXgoIGpRdWVyeS5leHRlbmQoIHtcblx0XHRcdHVybDogdXJsLFxuXHRcdFx0dHlwZTogbWV0aG9kLFxuXHRcdFx0ZGF0YVR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhOiBkYXRhLFxuXHRcdFx0c3VjY2VzczogY2FsbGJhY2tcblx0XHR9LCBqUXVlcnkuaXNQbGFpbk9iamVjdCggdXJsICkgJiYgdXJsICkgKTtcblx0fTtcbn0gKTtcblxuXG5qUXVlcnkuX2V2YWxVcmwgPSBmdW5jdGlvbiggdXJsICkge1xuXHRyZXR1cm4galF1ZXJ5LmFqYXgoIHtcblx0XHR1cmw6IHVybCxcblxuXHRcdC8vIE1ha2UgdGhpcyBleHBsaWNpdCwgc2luY2UgdXNlciBjYW4gb3ZlcnJpZGUgdGhpcyB0aHJvdWdoIGFqYXhTZXR1cCAoIzExMjY0KVxuXHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0ZGF0YVR5cGU6IFwic2NyaXB0XCIsXG5cdFx0Y2FjaGU6IHRydWUsXG5cdFx0YXN5bmM6IGZhbHNlLFxuXHRcdGdsb2JhbDogZmFsc2UsXG5cdFx0XCJ0aHJvd3NcIjogdHJ1ZVxuXHR9ICk7XG59O1xuXG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0d3JhcEFsbDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIHdyYXA7XG5cblx0XHRpZiAoIHRoaXNbIDAgXSApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdFx0aHRtbCA9IGh0bWwuY2FsbCggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoZSBlbGVtZW50cyB0byB3cmFwIHRoZSB0YXJnZXQgYXJvdW5kXG5cdFx0XHR3cmFwID0galF1ZXJ5KCBodG1sLCB0aGlzWyAwIF0ub3duZXJEb2N1bWVudCApLmVxKCAwICkuY2xvbmUoIHRydWUgKTtcblxuXHRcdFx0aWYgKCB0aGlzWyAwIF0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0d3JhcC5pbnNlcnRCZWZvcmUoIHRoaXNbIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHR3cmFwLm1hcCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBlbGVtID0gdGhpcztcblxuXHRcdFx0XHR3aGlsZSAoIGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQgKSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gZWxlbTtcblx0XHRcdH0gKS5hcHBlbmQoIHRoaXMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwSW5uZXIoIGh0bWwuY2FsbCggdGhpcywgaSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgc2VsZiA9IGpRdWVyeSggdGhpcyApLFxuXHRcdFx0XHRjb250ZW50cyA9IHNlbGYuY29udGVudHMoKTtcblxuXHRcdFx0aWYgKCBjb250ZW50cy5sZW5ndGggKSB7XG5cdFx0XHRcdGNvbnRlbnRzLndyYXBBbGwoIGh0bWwgKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi5hcHBlbmQoIGh0bWwgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0d3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwQWxsKCBpc0Z1bmN0aW9uID8gaHRtbC5jYWxsKCB0aGlzLCBpICkgOiBodG1sICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdHVud3JhcDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHRoaXMucGFyZW50KCBzZWxlY3RvciApLm5vdCggXCJib2R5XCIgKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLnJlcGxhY2VXaXRoKCB0aGlzLmNoaWxkTm9kZXMgKTtcblx0XHR9ICk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gIWpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSggZWxlbSApO1xufTtcbmpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gISEoIGVsZW0ub2Zmc2V0V2lkdGggfHwgZWxlbS5vZmZzZXRIZWlnaHQgfHwgZWxlbS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCApO1xufTtcblxuXG5cblxualF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIgPSBmdW5jdGlvbigpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbmV3IHdpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuXHR9IGNhdGNoICggZSApIHt9XG59O1xuXG52YXIgeGhyU3VjY2Vzc1N0YXR1cyA9IHtcblxuXHRcdC8vIEZpbGUgcHJvdG9jb2wgYWx3YXlzIHlpZWxkcyBzdGF0dXMgY29kZSAwLCBhc3N1bWUgMjAwXG5cdFx0MDogMjAwLFxuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHQvLyAjMTQ1MDogc29tZXRpbWVzIElFIHJldHVybnMgMTIyMyB3aGVuIGl0IHNob3VsZCBiZSAyMDRcblx0XHQxMjIzOiAyMDRcblx0fSxcblx0eGhyU3VwcG9ydGVkID0galF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIoKTtcblxuc3VwcG9ydC5jb3JzID0gISF4aHJTdXBwb3J0ZWQgJiYgKCBcIndpdGhDcmVkZW50aWFsc1wiIGluIHhoclN1cHBvcnRlZCApO1xuc3VwcG9ydC5hamF4ID0geGhyU3VwcG9ydGVkID0gISF4aHJTdXBwb3J0ZWQ7XG5cbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0dmFyIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrO1xuXG5cdC8vIENyb3NzIGRvbWFpbiBvbmx5IGFsbG93ZWQgaWYgc3VwcG9ydGVkIHRocm91Z2ggWE1MSHR0cFJlcXVlc3Rcblx0aWYgKCBzdXBwb3J0LmNvcnMgfHwgeGhyU3VwcG9ydGVkICYmICFvcHRpb25zLmNyb3NzRG9tYWluICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRzZW5kOiBmdW5jdGlvbiggaGVhZGVycywgY29tcGxldGUgKSB7XG5cdFx0XHRcdHZhciBpLFxuXHRcdFx0XHRcdHhociA9IG9wdGlvbnMueGhyKCk7XG5cblx0XHRcdFx0eGhyLm9wZW4oXG5cdFx0XHRcdFx0b3B0aW9ucy50eXBlLFxuXHRcdFx0XHRcdG9wdGlvbnMudXJsLFxuXHRcdFx0XHRcdG9wdGlvbnMuYXN5bmMsXG5cdFx0XHRcdFx0b3B0aW9ucy51c2VybmFtZSxcblx0XHRcdFx0XHRvcHRpb25zLnBhc3N3b3JkXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gQXBwbHkgY3VzdG9tIGZpZWxkcyBpZiBwcm92aWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMueGhyRmllbGRzICkge1xuXHRcdFx0XHRcdGZvciAoIGkgaW4gb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0XHR4aHJbIGkgXSA9IG9wdGlvbnMueGhyRmllbGRzWyBpIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gT3ZlcnJpZGUgbWltZSB0eXBlIGlmIG5lZWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMubWltZVR5cGUgJiYgeGhyLm92ZXJyaWRlTWltZVR5cGUgKSB7XG5cdFx0XHRcdFx0eGhyLm92ZXJyaWRlTWltZVR5cGUoIG9wdGlvbnMubWltZVR5cGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFgtUmVxdWVzdGVkLVdpdGggaGVhZGVyXG5cdFx0XHRcdC8vIEZvciBjcm9zcy1kb21haW4gcmVxdWVzdHMsIHNlZWluZyBhcyBjb25kaXRpb25zIGZvciBhIHByZWZsaWdodCBhcmVcblx0XHRcdFx0Ly8gYWtpbiB0byBhIGppZ3NhdyBwdXp6bGUsIHdlIHNpbXBseSBuZXZlciBzZXQgaXQgdG8gYmUgc3VyZS5cblx0XHRcdFx0Ly8gKGl0IGNhbiBhbHdheXMgYmUgc2V0IG9uIGEgcGVyLXJlcXVlc3QgYmFzaXMgb3IgZXZlbiB1c2luZyBhamF4U2V0dXApXG5cdFx0XHRcdC8vIEZvciBzYW1lLWRvbWFpbiByZXF1ZXN0cywgd29uJ3QgY2hhbmdlIGhlYWRlciBpZiBhbHJlYWR5IHByb3ZpZGVkLlxuXHRcdFx0XHRpZiAoICFvcHRpb25zLmNyb3NzRG9tYWluICYmICFoZWFkZXJzWyBcIlgtUmVxdWVzdGVkLVdpdGhcIiBdICkge1xuXHRcdFx0XHRcdGhlYWRlcnNbIFwiWC1SZXF1ZXN0ZWQtV2l0aFwiIF0gPSBcIlhNTEh0dHBSZXF1ZXN0XCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBTZXQgaGVhZGVyc1xuXHRcdFx0XHRmb3IgKCBpIGluIGhlYWRlcnMgKSB7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoIGksIGhlYWRlcnNbIGkgXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQ2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRjYWxsYmFjayA9IGVycm9yQ2FsbGJhY2sgPSB4aHIub25sb2FkID1cblx0XHRcdFx0XHRcdFx0XHR4aHIub25lcnJvciA9IHhoci5vbmFib3J0ID0geGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSBcImFib3J0XCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0eGhyLmFib3J0KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHR5cGUgPT09IFwiZXJyb3JcIiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gT24gYSBtYW51YWwgbmF0aXZlIGFib3J0LCBJRTkgdGhyb3dzXG5cdFx0XHRcdFx0XHRcdFx0Ly8gZXJyb3JzIG9uIGFueSBwcm9wZXJ0eSBhY2Nlc3MgdGhhdCBpcyBub3QgcmVhZHlTdGF0ZVxuXHRcdFx0XHRcdFx0XHRcdGlmICggdHlwZW9mIHhoci5zdGF0dXMgIT09IFwibnVtYmVyXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggMCwgXCJlcnJvclwiICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKFxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEZpbGU6IHByb3RvY29sIGFsd2F5cyB5aWVsZHMgc3RhdHVzIDA7IHNlZSAjODYwNSwgIzE0MjA3XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXMsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXNUZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZShcblx0XHRcdFx0XHRcdFx0XHRcdHhoclN1Y2Nlc3NTdGF0dXNbIHhoci5zdGF0dXMgXSB8fCB4aHIuc3RhdHVzLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHQsXG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBJRTkgaGFzIG5vIFhIUjIgYnV0IHRocm93cyBvbiBiaW5hcnkgKHRyYWMtMTE0MjYpXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBGb3IgWEhSMiBub24tdGV4dCwgbGV0IHRoZSBjYWxsZXIgaGFuZGxlIGl0IChnaC0yNDk4KVxuXHRcdFx0XHRcdFx0XHRcdFx0KCB4aHIucmVzcG9uc2VUeXBlIHx8IFwidGV4dFwiICkgIT09IFwidGV4dFwiICB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0dHlwZW9mIHhoci5yZXNwb25zZVRleHQgIT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IGJpbmFyeTogeGhyLnJlc3BvbnNlIH0gOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IHRleHQ6IHhoci5yZXNwb25zZVRleHQgfSxcblx0XHRcdFx0XHRcdFx0XHRcdHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKVxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIExpc3RlbiB0byBldmVudHNcblx0XHRcdFx0eGhyLm9ubG9hZCA9IGNhbGxiYWNrKCk7XG5cdFx0XHRcdGVycm9yQ2FsbGJhY2sgPSB4aHIub25lcnJvciA9IGNhbGxiYWNrKCBcImVycm9yXCIgKTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA5IG9ubHlcblx0XHRcdFx0Ly8gVXNlIG9ucmVhZHlzdGF0ZWNoYW5nZSB0byByZXBsYWNlIG9uYWJvcnRcblx0XHRcdFx0Ly8gdG8gaGFuZGxlIHVuY2F1Z2h0IGFib3J0c1xuXHRcdFx0XHRpZiAoIHhoci5vbmFib3J0ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0eGhyLm9uYWJvcnQgPSBlcnJvckNhbGxiYWNrO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgcmVhZHlTdGF0ZSBiZWZvcmUgdGltZW91dCBhcyBpdCBjaGFuZ2VzXG5cdFx0XHRcdFx0XHRpZiAoIHhoci5yZWFkeVN0YXRlID09PSA0ICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIEFsbG93IG9uZXJyb3IgdG8gYmUgY2FsbGVkIGZpcnN0LFxuXHRcdFx0XHRcdFx0XHQvLyBidXQgdGhhdCB3aWxsIG5vdCBoYW5kbGUgYSBuYXRpdmUgYWJvcnRcblx0XHRcdFx0XHRcdFx0Ly8gQWxzbywgc2F2ZSBlcnJvckNhbGxiYWNrIHRvIGEgdmFyaWFibGVcblx0XHRcdFx0XHRcdFx0Ly8gYXMgeGhyLm9uZXJyb3IgY2Fubm90IGJlIGFjY2Vzc2VkXG5cdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JDYWxsYmFjaygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDcmVhdGUgdGhlIGFib3J0IGNhbGxiYWNrXG5cdFx0XHRcdGNhbGxiYWNrID0gY2FsbGJhY2soIFwiYWJvcnRcIiApO1xuXG5cdFx0XHRcdHRyeSB7XG5cblx0XHRcdFx0XHQvLyBEbyBzZW5kIHRoZSByZXF1ZXN0ICh0aGlzIG1heSByYWlzZSBhbiBleGNlcHRpb24pXG5cdFx0XHRcdFx0eGhyLnNlbmQoIG9wdGlvbnMuaGFzQ29udGVudCAmJiBvcHRpb25zLmRhdGEgfHwgbnVsbCApO1xuXHRcdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHRcdC8vICMxNDY4MzogT25seSByZXRocm93IGlmIHRoaXMgaGFzbid0IGJlZW4gbm90aWZpZWQgYXMgYW4gZXJyb3IgeWV0XG5cdFx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRcdHRocm93IGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0gKTtcblxuXG5cblxuLy8gUHJldmVudCBhdXRvLWV4ZWN1dGlvbiBvZiBzY3JpcHRzIHdoZW4gbm8gZXhwbGljaXQgZGF0YVR5cGUgd2FzIHByb3ZpZGVkIChTZWUgZ2gtMjQzMilcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBmdW5jdGlvbiggcyApIHtcblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMuY29udGVudHMuc2NyaXB0ID0gZmFsc2U7XG5cdH1cbn0gKTtcblxuLy8gSW5zdGFsbCBzY3JpcHQgZGF0YVR5cGVcbmpRdWVyeS5hamF4U2V0dXAoIHtcblx0YWNjZXB0czoge1xuXHRcdHNjcmlwdDogXCJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIFwiICtcblx0XHRcdFwiYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0XCJcblx0fSxcblx0Y29udGVudHM6IHtcblx0XHRzY3JpcHQ6IC9cXGIoPzpqYXZhfGVjbWEpc2NyaXB0XFxiL1xuXHR9LFxuXHRjb252ZXJ0ZXJzOiB7XG5cdFx0XCJ0ZXh0IHNjcmlwdFwiOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdGpRdWVyeS5nbG9iYWxFdmFsKCB0ZXh0ICk7XG5cdFx0XHRyZXR1cm4gdGV4dDtcblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSGFuZGxlIGNhY2hlJ3Mgc3BlY2lhbCBjYXNlIGFuZCBjcm9zc0RvbWFpblxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIFwic2NyaXB0XCIsIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzLmNhY2hlID0gZmFsc2U7XG5cdH1cblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMudHlwZSA9IFwiR0VUXCI7XG5cdH1cbn0gKTtcblxuLy8gQmluZCBzY3JpcHQgdGFnIGhhY2sgdHJhbnNwb3J0XG5qUXVlcnkuYWpheFRyYW5zcG9ydCggXCJzY3JpcHRcIiwgZnVuY3Rpb24oIHMgKSB7XG5cblx0Ly8gVGhpcyB0cmFuc3BvcnQgb25seSBkZWFscyB3aXRoIGNyb3NzIGRvbWFpbiByZXF1ZXN0c1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0dmFyIHNjcmlwdCwgY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBfLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0c2NyaXB0ID0galF1ZXJ5KCBcIjxzY3JpcHQ+XCIgKS5wcm9wKCB7XG5cdFx0XHRcdFx0Y2hhcnNldDogcy5zY3JpcHRDaGFyc2V0LFxuXHRcdFx0XHRcdHNyYzogcy51cmxcblx0XHRcdFx0fSApLm9uKFxuXHRcdFx0XHRcdFwibG9hZCBlcnJvclwiLFxuXHRcdFx0XHRcdGNhbGxiYWNrID0gZnVuY3Rpb24oIGV2dCApIHtcblx0XHRcdFx0XHRcdHNjcmlwdC5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdGNhbGxiYWNrID0gbnVsbDtcblx0XHRcdFx0XHRcdGlmICggZXZ0ICkge1xuXHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggZXZ0LnR5cGUgPT09IFwiZXJyb3JcIiA/IDQwNCA6IDIwMCwgZXZ0LnR5cGUgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gVXNlIG5hdGl2ZSBET00gbWFuaXB1bGF0aW9uIHRvIGF2b2lkIG91ciBkb21NYW5pcCBBSkFYIHRyaWNrZXJ5XG5cdFx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdFsgMCBdICk7XG5cdFx0XHR9LFxuXHRcdFx0YWJvcnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBvbGRDYWxsYmFja3MgPSBbXSxcblx0cmpzb25wID0gLyg9KVxcPyg/PSZ8JCl8XFw/XFw/LztcblxuLy8gRGVmYXVsdCBqc29ucCBzZXR0aW5nc1xualF1ZXJ5LmFqYXhTZXR1cCgge1xuXHRqc29ucDogXCJjYWxsYmFja1wiLFxuXHRqc29ucENhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgY2FsbGJhY2sgPSBvbGRDYWxsYmFja3MucG9wKCkgfHwgKCBqUXVlcnkuZXhwYW5kbyArIFwiX1wiICsgKCBub25jZSsrICkgKTtcblx0XHR0aGlzWyBjYWxsYmFjayBdID0gdHJ1ZTtcblx0XHRyZXR1cm4gY2FsbGJhY2s7XG5cdH1cbn0gKTtcblxuLy8gRGV0ZWN0LCBub3JtYWxpemUgb3B0aW9ucyBhbmQgaW5zdGFsbCBjYWxsYmFja3MgZm9yIGpzb25wIHJlcXVlc3RzXG5qUXVlcnkuYWpheFByZWZpbHRlciggXCJqc29uIGpzb25wXCIsIGZ1bmN0aW9uKCBzLCBvcmlnaW5hbFNldHRpbmdzLCBqcVhIUiApIHtcblxuXHR2YXIgY2FsbGJhY2tOYW1lLCBvdmVyd3JpdHRlbiwgcmVzcG9uc2VDb250YWluZXIsXG5cdFx0anNvblByb3AgPSBzLmpzb25wICE9PSBmYWxzZSAmJiAoIHJqc29ucC50ZXN0KCBzLnVybCApID9cblx0XHRcdFwidXJsXCIgOlxuXHRcdFx0dHlwZW9mIHMuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHQoIHMuY29udGVudFR5cGUgfHwgXCJcIiApXG5cdFx0XHRcdFx0LmluZGV4T2YoIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgKSA9PT0gMCAmJlxuXHRcdFx0XHRyanNvbnAudGVzdCggcy5kYXRhICkgJiYgXCJkYXRhXCJcblx0XHQpO1xuXG5cdC8vIEhhbmRsZSBpZmYgdGhlIGV4cGVjdGVkIGRhdGEgdHlwZSBpcyBcImpzb25wXCIgb3Igd2UgaGF2ZSBhIHBhcmFtZXRlciB0byBzZXRcblx0aWYgKCBqc29uUHJvcCB8fCBzLmRhdGFUeXBlc1sgMCBdID09PSBcImpzb25wXCIgKSB7XG5cblx0XHQvLyBHZXQgY2FsbGJhY2sgbmFtZSwgcmVtZW1iZXJpbmcgcHJlZXhpc3RpbmcgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGl0XG5cdFx0Y2FsbGJhY2tOYW1lID0gcy5qc29ucENhbGxiYWNrID0galF1ZXJ5LmlzRnVuY3Rpb24oIHMuanNvbnBDYWxsYmFjayApID9cblx0XHRcdHMuanNvbnBDYWxsYmFjaygpIDpcblx0XHRcdHMuanNvbnBDYWxsYmFjaztcblxuXHRcdC8vIEluc2VydCBjYWxsYmFjayBpbnRvIHVybCBvciBmb3JtIGRhdGFcblx0XHRpZiAoIGpzb25Qcm9wICkge1xuXHRcdFx0c1sganNvblByb3AgXSA9IHNbIGpzb25Qcm9wIF0ucmVwbGFjZSggcmpzb25wLCBcIiQxXCIgKyBjYWxsYmFja05hbWUgKTtcblx0XHR9IGVsc2UgaWYgKCBzLmpzb25wICE9PSBmYWxzZSApIHtcblx0XHRcdHMudXJsICs9ICggcnF1ZXJ5LnRlc3QoIHMudXJsICkgPyBcIiZcIiA6IFwiP1wiICkgKyBzLmpzb25wICsgXCI9XCIgKyBjYWxsYmFja05hbWU7XG5cdFx0fVxuXG5cdFx0Ly8gVXNlIGRhdGEgY29udmVydGVyIHRvIHJldHJpZXZlIGpzb24gYWZ0ZXIgc2NyaXB0IGV4ZWN1dGlvblxuXHRcdHMuY29udmVydGVyc1sgXCJzY3JpcHQganNvblwiIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggIXJlc3BvbnNlQ29udGFpbmVyICkge1xuXHRcdFx0XHRqUXVlcnkuZXJyb3IoIGNhbGxiYWNrTmFtZSArIFwiIHdhcyBub3QgY2FsbGVkXCIgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXNwb25zZUNvbnRhaW5lclsgMCBdO1xuXHRcdH07XG5cblx0XHQvLyBGb3JjZSBqc29uIGRhdGFUeXBlXG5cdFx0cy5kYXRhVHlwZXNbIDAgXSA9IFwianNvblwiO1xuXG5cdFx0Ly8gSW5zdGFsbCBjYWxsYmFja1xuXHRcdG92ZXJ3cml0dGVuID0gd2luZG93WyBjYWxsYmFja05hbWUgXTtcblx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXNwb25zZUNvbnRhaW5lciA9IGFyZ3VtZW50cztcblx0XHR9O1xuXG5cdFx0Ly8gQ2xlYW4tdXAgZnVuY3Rpb24gKGZpcmVzIGFmdGVyIGNvbnZlcnRlcnMpXG5cdFx0anFYSFIuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gSWYgcHJldmlvdXMgdmFsdWUgZGlkbid0IGV4aXN0IC0gcmVtb3ZlIGl0XG5cdFx0XHRpZiAoIG92ZXJ3cml0dGVuID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpRdWVyeSggd2luZG93ICkucmVtb3ZlUHJvcCggY2FsbGJhY2tOYW1lICk7XG5cblx0XHRcdC8vIE90aGVyd2lzZSByZXN0b3JlIHByZWV4aXN0aW5nIHZhbHVlXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gb3ZlcndyaXR0ZW47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNhdmUgYmFjayBhcyBmcmVlXG5cdFx0XHRpZiAoIHNbIGNhbGxiYWNrTmFtZSBdICkge1xuXG5cdFx0XHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHJlLXVzaW5nIHRoZSBvcHRpb25zIGRvZXNuJ3Qgc2NyZXcgdGhpbmdzIGFyb3VuZFxuXHRcdFx0XHRzLmpzb25wQ2FsbGJhY2sgPSBvcmlnaW5hbFNldHRpbmdzLmpzb25wQ2FsbGJhY2s7XG5cblx0XHRcdFx0Ly8gU2F2ZSB0aGUgY2FsbGJhY2sgbmFtZSBmb3IgZnV0dXJlIHVzZVxuXHRcdFx0XHRvbGRDYWxsYmFja3MucHVzaCggY2FsbGJhY2tOYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENhbGwgaWYgaXQgd2FzIGEgZnVuY3Rpb24gYW5kIHdlIGhhdmUgYSByZXNwb25zZVxuXHRcdFx0aWYgKCByZXNwb25zZUNvbnRhaW5lciAmJiBqUXVlcnkuaXNGdW5jdGlvbiggb3ZlcndyaXR0ZW4gKSApIHtcblx0XHRcdFx0b3ZlcndyaXR0ZW4oIHJlc3BvbnNlQ29udGFpbmVyWyAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmVzcG9uc2VDb250YWluZXIgPSBvdmVyd3JpdHRlbiA9IHVuZGVmaW5lZDtcblx0XHR9ICk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBzY3JpcHRcblx0XHRyZXR1cm4gXCJzY3JpcHRcIjtcblx0fVxufSApO1xuXG5cblxuXG4vLyBTdXBwb3J0OiBTYWZhcmkgOCBvbmx5XG4vLyBJbiBTYWZhcmkgOCBkb2N1bWVudHMgY3JlYXRlZCB2aWEgZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50XG4vLyBjb2xsYXBzZSBzaWJsaW5nIGZvcm1zOiB0aGUgc2Vjb25kIG9uZSBiZWNvbWVzIGEgY2hpbGQgb2YgdGhlIGZpcnN0IG9uZS5cbi8vIEJlY2F1c2Ugb2YgdGhhdCwgdGhpcyBzZWN1cml0eSBtZWFzdXJlIGhhcyB0byBiZSBkaXNhYmxlZCBpbiBTYWZhcmkgOC5cbi8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzczMzdcbnN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ID0gKCBmdW5jdGlvbigpIHtcblx0dmFyIGJvZHkgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoIFwiXCIgKS5ib2R5O1xuXHRib2R5LmlubmVySFRNTCA9IFwiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT5cIjtcblx0cmV0dXJuIGJvZHkuY2hpbGROb2Rlcy5sZW5ndGggPT09IDI7XG59ICkoKTtcblxuXG4vLyBBcmd1bWVudCBcImRhdGFcIiBzaG91bGQgYmUgc3RyaW5nIG9mIGh0bWxcbi8vIGNvbnRleHQgKG9wdGlvbmFsKTogSWYgc3BlY2lmaWVkLCB0aGUgZnJhZ21lbnQgd2lsbCBiZSBjcmVhdGVkIGluIHRoaXMgY29udGV4dCxcbi8vIGRlZmF1bHRzIHRvIGRvY3VtZW50XG4vLyBrZWVwU2NyaXB0cyAob3B0aW9uYWwpOiBJZiB0cnVlLCB3aWxsIGluY2x1ZGUgc2NyaXB0cyBwYXNzZWQgaW4gdGhlIGh0bWwgc3RyaW5nXG5qUXVlcnkucGFyc2VIVE1MID0gZnVuY3Rpb24oIGRhdGEsIGNvbnRleHQsIGtlZXBTY3JpcHRzICkge1xuXHRpZiAoIHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBbXTtcblx0fVxuXHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRrZWVwU2NyaXB0cyA9IGNvbnRleHQ7XG5cdFx0Y29udGV4dCA9IGZhbHNlO1xuXHR9XG5cblx0dmFyIGJhc2UsIHBhcnNlZCwgc2NyaXB0cztcblxuXHRpZiAoICFjb250ZXh0ICkge1xuXG5cdFx0Ly8gU3RvcCBzY3JpcHRzIG9yIGlubGluZSBldmVudCBoYW5kbGVycyBmcm9tIGJlaW5nIGV4ZWN1dGVkIGltbWVkaWF0ZWx5XG5cdFx0Ly8gYnkgdXNpbmcgZG9jdW1lbnQuaW1wbGVtZW50YXRpb25cblx0XHRpZiAoIHN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ICkge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCggXCJcIiApO1xuXG5cdFx0XHQvLyBTZXQgdGhlIGJhc2UgaHJlZiBmb3IgdGhlIGNyZWF0ZWQgZG9jdW1lbnRcblx0XHRcdC8vIHNvIGFueSBwYXJzZWQgZWxlbWVudHMgd2l0aCBVUkxzXG5cdFx0XHQvLyBhcmUgYmFzZWQgb24gdGhlIGRvY3VtZW50J3MgVVJMIChnaC0yOTY1KVxuXHRcdFx0YmFzZSA9IGNvbnRleHQuY3JlYXRlRWxlbWVudCggXCJiYXNlXCIgKTtcblx0XHRcdGJhc2UuaHJlZiA9IGRvY3VtZW50LmxvY2F0aW9uLmhyZWY7XG5cdFx0XHRjb250ZXh0LmhlYWQuYXBwZW5kQ2hpbGQoIGJhc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50O1xuXHRcdH1cblx0fVxuXG5cdHBhcnNlZCA9IHJzaW5nbGVUYWcuZXhlYyggZGF0YSApO1xuXHRzY3JpcHRzID0gIWtlZXBTY3JpcHRzICYmIFtdO1xuXG5cdC8vIFNpbmdsZSB0YWdcblx0aWYgKCBwYXJzZWQgKSB7XG5cdFx0cmV0dXJuIFsgY29udGV4dC5jcmVhdGVFbGVtZW50KCBwYXJzZWRbIDEgXSApIF07XG5cdH1cblxuXHRwYXJzZWQgPSBidWlsZEZyYWdtZW50KCBbIGRhdGEgXSwgY29udGV4dCwgc2NyaXB0cyApO1xuXG5cdGlmICggc2NyaXB0cyAmJiBzY3JpcHRzLmxlbmd0aCApIHtcblx0XHRqUXVlcnkoIHNjcmlwdHMgKS5yZW1vdmUoKTtcblx0fVxuXG5cdHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBwYXJzZWQuY2hpbGROb2RlcyApO1xufTtcblxuXG4vKipcbiAqIExvYWQgYSB1cmwgaW50byBhIHBhZ2VcbiAqL1xualF1ZXJ5LmZuLmxvYWQgPSBmdW5jdGlvbiggdXJsLCBwYXJhbXMsIGNhbGxiYWNrICkge1xuXHR2YXIgc2VsZWN0b3IsIHR5cGUsIHJlc3BvbnNlLFxuXHRcdHNlbGYgPSB0aGlzLFxuXHRcdG9mZiA9IHVybC5pbmRleE9mKCBcIiBcIiApO1xuXG5cdGlmICggb2ZmID4gLTEgKSB7XG5cdFx0c2VsZWN0b3IgPSBzdHJpcEFuZENvbGxhcHNlKCB1cmwuc2xpY2UoIG9mZiApICk7XG5cdFx0dXJsID0gdXJsLnNsaWNlKCAwLCBvZmYgKTtcblx0fVxuXG5cdC8vIElmIGl0J3MgYSBmdW5jdGlvblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwYXJhbXMgKSApIHtcblxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2sgPSBwYXJhbXM7XG5cdFx0cGFyYW1zID0gdW5kZWZpbmVkO1xuXG5cdC8vIE90aGVyd2lzZSwgYnVpbGQgYSBwYXJhbSBzdHJpbmdcblx0fSBlbHNlIGlmICggcGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0dHlwZSA9IFwiUE9TVFwiO1xuXHR9XG5cblx0Ly8gSWYgd2UgaGF2ZSBlbGVtZW50cyB0byBtb2RpZnksIG1ha2UgdGhlIHJlcXVlc3Rcblx0aWYgKCBzZWxmLmxlbmd0aCA+IDAgKSB7XG5cdFx0alF1ZXJ5LmFqYXgoIHtcblx0XHRcdHVybDogdXJsLFxuXG5cdFx0XHQvLyBJZiBcInR5cGVcIiB2YXJpYWJsZSBpcyB1bmRlZmluZWQsIHRoZW4gXCJHRVRcIiBtZXRob2Qgd2lsbCBiZSB1c2VkLlxuXHRcdFx0Ly8gTWFrZSB2YWx1ZSBvZiB0aGlzIGZpZWxkIGV4cGxpY2l0IHNpbmNlXG5cdFx0XHQvLyB1c2VyIGNhbiBvdmVycmlkZSBpdCB0aHJvdWdoIGFqYXhTZXR1cCBtZXRob2Rcblx0XHRcdHR5cGU6IHR5cGUgfHwgXCJHRVRcIixcblx0XHRcdGRhdGFUeXBlOiBcImh0bWxcIixcblx0XHRcdGRhdGE6IHBhcmFtc1xuXHRcdH0gKS5kb25lKCBmdW5jdGlvbiggcmVzcG9uc2VUZXh0ICkge1xuXG5cdFx0XHQvLyBTYXZlIHJlc3BvbnNlIGZvciB1c2UgaW4gY29tcGxldGUgY2FsbGJhY2tcblx0XHRcdHJlc3BvbnNlID0gYXJndW1lbnRzO1xuXG5cdFx0XHRzZWxmLmh0bWwoIHNlbGVjdG9yID9cblxuXHRcdFx0XHQvLyBJZiBhIHNlbGVjdG9yIHdhcyBzcGVjaWZpZWQsIGxvY2F0ZSB0aGUgcmlnaHQgZWxlbWVudHMgaW4gYSBkdW1teSBkaXZcblx0XHRcdFx0Ly8gRXhjbHVkZSBzY3JpcHRzIHRvIGF2b2lkIElFICdQZXJtaXNzaW9uIERlbmllZCcgZXJyb3JzXG5cdFx0XHRcdGpRdWVyeSggXCI8ZGl2PlwiICkuYXBwZW5kKCBqUXVlcnkucGFyc2VIVE1MKCByZXNwb25zZVRleHQgKSApLmZpbmQoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSB1c2UgdGhlIGZ1bGwgcmVzdWx0XG5cdFx0XHRcdHJlc3BvbnNlVGV4dCApO1xuXG5cdFx0Ly8gSWYgdGhlIHJlcXVlc3Qgc3VjY2VlZHMsIHRoaXMgZnVuY3Rpb24gZ2V0cyBcImRhdGFcIiwgXCJzdGF0dXNcIiwgXCJqcVhIUlwiXG5cdFx0Ly8gYnV0IHRoZXkgYXJlIGlnbm9yZWQgYmVjYXVzZSByZXNwb25zZSB3YXMgc2V0IGFib3ZlLlxuXHRcdC8vIElmIGl0IGZhaWxzLCB0aGlzIGZ1bmN0aW9uIGdldHMgXCJqcVhIUlwiLCBcInN0YXR1c1wiLCBcImVycm9yXCJcblx0XHR9ICkuYWx3YXlzKCBjYWxsYmFjayAmJiBmdW5jdGlvbigganFYSFIsIHN0YXR1cyApIHtcblx0XHRcdHNlbGYuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNhbGxiYWNrLmFwcGx5KCB0aGlzLCByZXNwb25zZSB8fCBbIGpxWEhSLnJlc3BvbnNlVGV4dCwgc3RhdHVzLCBqcVhIUiBdICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXM7XG59O1xuXG5cblxuXG4vLyBBdHRhY2ggYSBidW5jaCBvZiBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIGNvbW1vbiBBSkFYIGV2ZW50c1xualF1ZXJ5LmVhY2goIFtcblx0XCJhamF4U3RhcnRcIixcblx0XCJhamF4U3RvcFwiLFxuXHRcImFqYXhDb21wbGV0ZVwiLFxuXHRcImFqYXhFcnJvclwiLFxuXHRcImFqYXhTdWNjZXNzXCIsXG5cdFwiYWpheFNlbmRcIlxuXSwgZnVuY3Rpb24oIGksIHR5cGUgKSB7XG5cdGpRdWVyeS5mblsgdHlwZSBdID0gZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlLCBmbiApO1xuXHR9O1xufSApO1xuXG5cblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggalF1ZXJ5LnRpbWVycywgZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiBlbGVtID09PSBmbi5lbGVtO1xuXHR9ICkubGVuZ3RoO1xufTtcblxuXG5cblxualF1ZXJ5Lm9mZnNldCA9IHtcblx0c2V0T2Zmc2V0OiBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgaSApIHtcblx0XHR2YXIgY3VyUG9zaXRpb24sIGN1ckxlZnQsIGN1ckNTU1RvcCwgY3VyVG9wLCBjdXJPZmZzZXQsIGN1ckNTU0xlZnQsIGNhbGN1bGF0ZVBvc2l0aW9uLFxuXHRcdFx0cG9zaXRpb24gPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBvc2l0aW9uXCIgKSxcblx0XHRcdGN1ckVsZW0gPSBqUXVlcnkoIGVsZW0gKSxcblx0XHRcdHByb3BzID0ge307XG5cblx0XHQvLyBTZXQgcG9zaXRpb24gZmlyc3QsIGluLWNhc2UgdG9wL2xlZnQgYXJlIHNldCBldmVuIG9uIHN0YXRpYyBlbGVtXG5cdFx0aWYgKCBwb3NpdGlvbiA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdGVsZW0uc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cdFx0fVxuXG5cdFx0Y3VyT2Zmc2V0ID0gY3VyRWxlbS5vZmZzZXQoKTtcblx0XHRjdXJDU1NUb3AgPSBqUXVlcnkuY3NzKCBlbGVtLCBcInRvcFwiICk7XG5cdFx0Y3VyQ1NTTGVmdCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwibGVmdFwiICk7XG5cdFx0Y2FsY3VsYXRlUG9zaXRpb24gPSAoIHBvc2l0aW9uID09PSBcImFic29sdXRlXCIgfHwgcG9zaXRpb24gPT09IFwiZml4ZWRcIiApICYmXG5cdFx0XHQoIGN1ckNTU1RvcCArIGN1ckNTU0xlZnQgKS5pbmRleE9mKCBcImF1dG9cIiApID4gLTE7XG5cblx0XHQvLyBOZWVkIHRvIGJlIGFibGUgdG8gY2FsY3VsYXRlIHBvc2l0aW9uIGlmIGVpdGhlclxuXHRcdC8vIHRvcCBvciBsZWZ0IGlzIGF1dG8gYW5kIHBvc2l0aW9uIGlzIGVpdGhlciBhYnNvbHV0ZSBvciBmaXhlZFxuXHRcdGlmICggY2FsY3VsYXRlUG9zaXRpb24gKSB7XG5cdFx0XHRjdXJQb3NpdGlvbiA9IGN1ckVsZW0ucG9zaXRpb24oKTtcblx0XHRcdGN1clRvcCA9IGN1clBvc2l0aW9uLnRvcDtcblx0XHRcdGN1ckxlZnQgPSBjdXJQb3NpdGlvbi5sZWZ0O1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1clRvcCA9IHBhcnNlRmxvYXQoIGN1ckNTU1RvcCApIHx8IDA7XG5cdFx0XHRjdXJMZWZ0ID0gcGFyc2VGbG9hdCggY3VyQ1NTTGVmdCApIHx8IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0aW9ucyApICkge1xuXG5cdFx0XHQvLyBVc2UgalF1ZXJ5LmV4dGVuZCBoZXJlIHRvIGFsbG93IG1vZGlmaWNhdGlvbiBvZiBjb29yZGluYXRlcyBhcmd1bWVudCAoZ2gtMTg0OClcblx0XHRcdG9wdGlvbnMgPSBvcHRpb25zLmNhbGwoIGVsZW0sIGksIGpRdWVyeS5leHRlbmQoIHt9LCBjdXJPZmZzZXQgKSApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0aW9ucy50b3AgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLnRvcCA9ICggb3B0aW9ucy50b3AgLSBjdXJPZmZzZXQudG9wICkgKyBjdXJUb3A7XG5cdFx0fVxuXHRcdGlmICggb3B0aW9ucy5sZWZ0ICE9IG51bGwgKSB7XG5cdFx0XHRwcm9wcy5sZWZ0ID0gKCBvcHRpb25zLmxlZnQgLSBjdXJPZmZzZXQubGVmdCApICsgY3VyTGVmdDtcblx0XHR9XG5cblx0XHRpZiAoIFwidXNpbmdcIiBpbiBvcHRpb25zICkge1xuXHRcdFx0b3B0aW9ucy51c2luZy5jYWxsKCBlbGVtLCBwcm9wcyApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1ckVsZW0uY3NzKCBwcm9wcyApO1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRvZmZzZXQ6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdFx0Ly8gUHJlc2VydmUgY2hhaW5pbmcgZm9yIHNldHRlclxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiBvcHRpb25zID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHR0aGlzIDpcblx0XHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0XHRqUXVlcnkub2Zmc2V0LnNldE9mZnNldCggdGhpcywgb3B0aW9ucywgaSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRvYywgZG9jRWxlbSwgcmVjdCwgd2luLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHplcm9zIGZvciBkaXNjb25uZWN0ZWQgYW5kIGhpZGRlbiAoZGlzcGxheTogbm9uZSkgZWxlbWVudHMgKGdoLTIzMTApXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYVxuXHRcdC8vIGRpc2Nvbm5lY3RlZCBub2RlIGluIElFIHRocm93cyBhbiBlcnJvclxuXHRcdGlmICggIWVsZW0uZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblx0XHR9XG5cblx0XHRyZWN0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudDtcblx0XHRkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudDtcblx0XHR3aW4gPSBkb2MuZGVmYXVsdFZpZXc7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiByZWN0LnRvcCArIHdpbi5wYWdlWU9mZnNldCAtIGRvY0VsZW0uY2xpZW50VG9wLFxuXHRcdFx0bGVmdDogcmVjdC5sZWZ0ICsgd2luLnBhZ2VYT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRMZWZ0XG5cdFx0fTtcblx0fSxcblxuXHRwb3NpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCAhdGhpc1sgMCBdICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBvZmZzZXRQYXJlbnQsIG9mZnNldCxcblx0XHRcdGVsZW0gPSB0aGlzWyAwIF0sXG5cdFx0XHRwYXJlbnRPZmZzZXQgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xuXG5cdFx0Ly8gRml4ZWQgZWxlbWVudHMgYXJlIG9mZnNldCBmcm9tIHdpbmRvdyAocGFyZW50T2Zmc2V0ID0ge3RvcDowLCBsZWZ0OiAwfSxcblx0XHQvLyBiZWNhdXNlIGl0IGlzIGl0cyBvbmx5IG9mZnNldCBwYXJlbnRcblx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApID09PSBcImZpeGVkXCIgKSB7XG5cblx0XHRcdC8vIEFzc3VtZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgaXMgdGhlcmUgd2hlbiBjb21wdXRlZCBwb3NpdGlvbiBpcyBmaXhlZFxuXHRcdFx0b2Zmc2V0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIEdldCAqcmVhbCogb2Zmc2V0UGFyZW50XG5cdFx0XHRvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudCgpO1xuXG5cdFx0XHQvLyBHZXQgY29ycmVjdCBvZmZzZXRzXG5cdFx0XHRvZmZzZXQgPSB0aGlzLm9mZnNldCgpO1xuXHRcdFx0aWYgKCAhbm9kZU5hbWUoIG9mZnNldFBhcmVudFsgMCBdLCBcImh0bWxcIiApICkge1xuXHRcdFx0XHRwYXJlbnRPZmZzZXQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBvZmZzZXRQYXJlbnQgYm9yZGVyc1xuXHRcdFx0cGFyZW50T2Zmc2V0ID0ge1xuXHRcdFx0XHR0b3A6IHBhcmVudE9mZnNldC50b3AgKyBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnRbIDAgXSwgXCJib3JkZXJUb3BXaWR0aFwiLCB0cnVlICksXG5cdFx0XHRcdGxlZnQ6IHBhcmVudE9mZnNldC5sZWZ0ICsgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50WyAwIF0sIFwiYm9yZGVyTGVmdFdpZHRoXCIsIHRydWUgKVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHQvLyBTdWJ0cmFjdCBwYXJlbnQgb2Zmc2V0cyBhbmQgZWxlbWVudCBtYXJnaW5zXG5cdFx0cmV0dXJuIHtcblx0XHRcdHRvcDogb2Zmc2V0LnRvcCAtIHBhcmVudE9mZnNldC50b3AgLSBqUXVlcnkuY3NzKCBlbGVtLCBcIm1hcmdpblRvcFwiLCB0cnVlICksXG5cdFx0XHRsZWZ0OiBvZmZzZXQubGVmdCAtIHBhcmVudE9mZnNldC5sZWZ0IC0galF1ZXJ5LmNzcyggZWxlbSwgXCJtYXJnaW5MZWZ0XCIsIHRydWUgKVxuXHRcdH07XG5cdH0sXG5cblx0Ly8gVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gZG9jdW1lbnRFbGVtZW50IGluIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG5cdC8vIDEpIEZvciB0aGUgZWxlbWVudCBpbnNpZGUgdGhlIGlmcmFtZSB3aXRob3V0IG9mZnNldFBhcmVudCwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm5cblx0Ly8gICAgZG9jdW1lbnRFbGVtZW50IG9mIHRoZSBwYXJlbnQgd2luZG93XG5cdC8vIDIpIEZvciB0aGUgaGlkZGVuIG9yIGRldGFjaGVkIGVsZW1lbnRcblx0Ly8gMykgRm9yIGJvZHkgb3IgaHRtbCBlbGVtZW50LCBpLmUuIGluIGNhc2Ugb2YgdGhlIGh0bWwgbm9kZSAtIGl0IHdpbGwgcmV0dXJuIGl0c2VsZlxuXHQvL1xuXHQvLyBidXQgdGhvc2UgZXhjZXB0aW9ucyB3ZXJlIG5ldmVyIHByZXNlbnRlZCBhcyBhIHJlYWwgbGlmZSB1c2UtY2FzZXNcblx0Ly8gYW5kIG1pZ2h0IGJlIGNvbnNpZGVyZWQgYXMgbW9yZSBwcmVmZXJhYmxlIHJlc3VsdHMuXG5cdC8vXG5cdC8vIFRoaXMgbG9naWMsIGhvd2V2ZXIsIGlzIG5vdCBndWFyYW50ZWVkIGFuZCBjYW4gY2hhbmdlIGF0IGFueSBwb2ludCBpbiB0aGUgZnV0dXJlXG5cdG9mZnNldFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudDtcblxuXHRcdFx0d2hpbGUgKCBvZmZzZXRQYXJlbnQgJiYgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50LCBcInBvc2l0aW9uXCIgKSA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdFx0b2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG9mZnNldFBhcmVudCB8fCBkb2N1bWVudEVsZW1lbnQ7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbi8vIENyZWF0ZSBzY3JvbGxMZWZ0IGFuZCBzY3JvbGxUb3AgbWV0aG9kc1xualF1ZXJ5LmVhY2goIHsgc2Nyb2xsTGVmdDogXCJwYWdlWE9mZnNldFwiLCBzY3JvbGxUb3A6IFwicGFnZVlPZmZzZXRcIiB9LCBmdW5jdGlvbiggbWV0aG9kLCBwcm9wICkge1xuXHR2YXIgdG9wID0gXCJwYWdlWU9mZnNldFwiID09PSBwcm9wO1xuXG5cdGpRdWVyeS5mblsgbWV0aG9kIF0gPSBmdW5jdGlvbiggdmFsICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCBtZXRob2QsIHZhbCApIHtcblxuXHRcdFx0Ly8gQ29hbGVzY2UgZG9jdW1lbnRzIGFuZCB3aW5kb3dzXG5cdFx0XHR2YXIgd2luO1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblx0XHRcdFx0d2luID0gZWxlbTtcblx0XHRcdH0gZWxzZSBpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHdpbiA9IGVsZW0uZGVmYXVsdFZpZXc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdmFsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiB3aW4gPyB3aW5bIHByb3AgXSA6IGVsZW1bIG1ldGhvZCBdO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHdpbiApIHtcblx0XHRcdFx0d2luLnNjcm9sbFRvKFxuXHRcdFx0XHRcdCF0b3AgPyB2YWwgOiB3aW4ucGFnZVhPZmZzZXQsXG5cdFx0XHRcdFx0dG9wID8gdmFsIDogd2luLnBhZ2VZT2Zmc2V0XG5cdFx0XHRcdCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVsZW1bIG1ldGhvZCBdID0gdmFsO1xuXHRcdFx0fVxuXHRcdH0sIG1ldGhvZCwgdmFsLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH07XG59ICk7XG5cbi8vIFN1cHBvcnQ6IFNhZmFyaSA8PTcgLSA5LjEsIENocm9tZSA8PTM3IC0gNDlcbi8vIEFkZCB0aGUgdG9wL2xlZnQgY3NzSG9va3MgdXNpbmcgalF1ZXJ5LmZuLnBvc2l0aW9uXG4vLyBXZWJraXQgYnVnOiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkwODRcbi8vIEJsaW5rIGJ1ZzogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NTg5MzQ3XG4vLyBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgcGVyY2VudCB3aGVuIHNwZWNpZmllZCBmb3IgdG9wL2xlZnQvYm90dG9tL3JpZ2h0O1xuLy8gcmF0aGVyIHRoYW4gbWFrZSB0aGUgY3NzIG1vZHVsZSBkZXBlbmQgb24gdGhlIG9mZnNldCBtb2R1bGUsIGp1c3QgY2hlY2sgZm9yIGl0IGhlcmVcbmpRdWVyeS5lYWNoKCBbIFwidG9wXCIsIFwibGVmdFwiIF0sIGZ1bmN0aW9uKCBpLCBwcm9wICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByb3AgXSA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5waXhlbFBvc2l0aW9uLFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGNvbXB1dGVkID0gY3VyQ1NTKCBlbGVtLCBwcm9wICk7XG5cblx0XHRcdFx0Ly8gSWYgY3VyQ1NTIHJldHVybnMgcGVyY2VudGFnZSwgZmFsbGJhY2sgdG8gb2Zmc2V0XG5cdFx0XHRcdHJldHVybiBybnVtbm9ucHgudGVzdCggY29tcHV0ZWQgKSA/XG5cdFx0XHRcdFx0alF1ZXJ5KCBlbGVtICkucG9zaXRpb24oKVsgcHJvcCBdICsgXCJweFwiIDpcblx0XHRcdFx0XHRjb21wdXRlZDtcblx0XHRcdH1cblx0XHR9XG5cdCk7XG59ICk7XG5cblxuLy8gQ3JlYXRlIGlubmVySGVpZ2h0LCBpbm5lcldpZHRoLCBoZWlnaHQsIHdpZHRoLCBvdXRlckhlaWdodCBhbmQgb3V0ZXJXaWR0aCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBIZWlnaHQ6IFwiaGVpZ2h0XCIsIFdpZHRoOiBcIndpZHRoXCIgfSwgZnVuY3Rpb24oIG5hbWUsIHR5cGUgKSB7XG5cdGpRdWVyeS5lYWNoKCB7IHBhZGRpbmc6IFwiaW5uZXJcIiArIG5hbWUsIGNvbnRlbnQ6IHR5cGUsIFwiXCI6IFwib3V0ZXJcIiArIG5hbWUgfSxcblx0XHRmdW5jdGlvbiggZGVmYXVsdEV4dHJhLCBmdW5jTmFtZSApIHtcblxuXHRcdC8vIE1hcmdpbiBpcyBvbmx5IGZvciBvdXRlckhlaWdodCwgb3V0ZXJXaWR0aFxuXHRcdGpRdWVyeS5mblsgZnVuY05hbWUgXSA9IGZ1bmN0aW9uKCBtYXJnaW4sIHZhbHVlICkge1xuXHRcdFx0dmFyIGNoYWluYWJsZSA9IGFyZ3VtZW50cy5sZW5ndGggJiYgKCBkZWZhdWx0RXh0cmEgfHwgdHlwZW9mIG1hcmdpbiAhPT0gXCJib29sZWFuXCIgKSxcblx0XHRcdFx0ZXh0cmEgPSBkZWZhdWx0RXh0cmEgfHwgKCBtYXJnaW4gPT09IHRydWUgfHwgdmFsdWUgPT09IHRydWUgPyBcIm1hcmdpblwiIDogXCJib3JkZXJcIiApO1xuXG5cdFx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgdHlwZSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBkb2M7XG5cblx0XHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vICQoIHdpbmRvdyApLm91dGVyV2lkdGgvSGVpZ2h0IHJldHVybiB3L2ggaW5jbHVkaW5nIHNjcm9sbGJhcnMgKGdoLTE3MjkpXG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmNOYW1lLmluZGV4T2YoIFwib3V0ZXJcIiApID09PSAwID9cblx0XHRcdFx0XHRcdGVsZW1bIFwiaW5uZXJcIiArIG5hbWUgXSA6XG5cdFx0XHRcdFx0XHRlbGVtLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsgXCJjbGllbnRcIiArIG5hbWUgXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEdldCBkb2N1bWVudCB3aWR0aCBvciBoZWlnaHRcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdGRvYyA9IGVsZW0uZG9jdW1lbnRFbGVtZW50O1xuXG5cdFx0XHRcdFx0Ly8gRWl0aGVyIHNjcm9sbFtXaWR0aC9IZWlnaHRdIG9yIG9mZnNldFtXaWR0aC9IZWlnaHRdIG9yIGNsaWVudFtXaWR0aC9IZWlnaHRdLFxuXHRcdFx0XHRcdC8vIHdoaWNoZXZlciBpcyBncmVhdGVzdFxuXHRcdFx0XHRcdHJldHVybiBNYXRoLm1heChcblx0XHRcdFx0XHRcdGVsZW0uYm9keVsgXCJzY3JvbGxcIiArIG5hbWUgXSwgZG9jWyBcInNjcm9sbFwiICsgbmFtZSBdLFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcIm9mZnNldFwiICsgbmFtZSBdLCBkb2NbIFwib2Zmc2V0XCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRkb2NbIFwiY2xpZW50XCIgKyBuYW1lIF1cblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXG5cdFx0XHRcdFx0Ly8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudCwgcmVxdWVzdGluZyBidXQgbm90IGZvcmNpbmcgcGFyc2VGbG9hdFxuXHRcdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIHR5cGUsIGV4dHJhICkgOlxuXG5cdFx0XHRcdFx0Ly8gU2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudFxuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgdHlwZSwgdmFsdWUsIGV4dHJhICk7XG5cdFx0XHR9LCB0eXBlLCBjaGFpbmFibGUgPyBtYXJnaW4gOiB1bmRlZmluZWQsIGNoYWluYWJsZSApO1xuXHRcdH07XG5cdH0gKTtcbn0gKTtcblxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cblx0YmluZDogZnVuY3Rpb24oIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIG51bGwsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuYmluZDogZnVuY3Rpb24oIHR5cGVzLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYoIHR5cGVzLCBudWxsLCBmbiApO1xuXHR9LFxuXG5cdGRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHR1bmRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBmbiApIHtcblxuXHRcdC8vICggbmFtZXNwYWNlICkgb3IgKCBzZWxlY3RvciwgdHlwZXMgWywgZm5dIClcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/XG5cdFx0XHR0aGlzLm9mZiggc2VsZWN0b3IsIFwiKipcIiApIDpcblx0XHRcdHRoaXMub2ZmKCB0eXBlcywgc2VsZWN0b3IgfHwgXCIqKlwiLCBmbiApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5ob2xkUmVhZHkgPSBmdW5jdGlvbiggaG9sZCApIHtcblx0aWYgKCBob2xkICkge1xuXHRcdGpRdWVyeS5yZWFkeVdhaXQrKztcblx0fSBlbHNlIHtcblx0XHRqUXVlcnkucmVhZHkoIHRydWUgKTtcblx0fVxufTtcbmpRdWVyeS5pc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbmpRdWVyeS5wYXJzZUpTT04gPSBKU09OLnBhcnNlO1xualF1ZXJ5Lm5vZGVOYW1lID0gbm9kZU5hbWU7XG5cblxuXG5cbi8vIFJlZ2lzdGVyIGFzIGEgbmFtZWQgQU1EIG1vZHVsZSwgc2luY2UgalF1ZXJ5IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBvdGhlclxuLy8gZmlsZXMgdGhhdCBtYXkgdXNlIGRlZmluZSwgYnV0IG5vdCB2aWEgYSBwcm9wZXIgY29uY2F0ZW5hdGlvbiBzY3JpcHQgdGhhdFxuLy8gdW5kZXJzdGFuZHMgYW5vbnltb3VzIEFNRCBtb2R1bGVzLiBBIG5hbWVkIEFNRCBpcyBzYWZlc3QgYW5kIG1vc3Qgcm9idXN0XG4vLyB3YXkgdG8gcmVnaXN0ZXIuIExvd2VyY2FzZSBqcXVlcnkgaXMgdXNlZCBiZWNhdXNlIEFNRCBtb2R1bGUgbmFtZXMgYXJlXG4vLyBkZXJpdmVkIGZyb20gZmlsZSBuYW1lcywgYW5kIGpRdWVyeSBpcyBub3JtYWxseSBkZWxpdmVyZWQgaW4gYSBsb3dlcmNhc2Vcbi8vIGZpbGUgbmFtZS4gRG8gdGhpcyBhZnRlciBjcmVhdGluZyB0aGUgZ2xvYmFsIHNvIHRoYXQgaWYgYW4gQU1EIG1vZHVsZSB3YW50c1xuLy8gdG8gY2FsbCBub0NvbmZsaWN0IHRvIGhpZGUgdGhpcyB2ZXJzaW9uIG9mIGpRdWVyeSwgaXQgd2lsbCB3b3JrLlxuXG4vLyBOb3RlIHRoYXQgZm9yIG1heGltdW0gcG9ydGFiaWxpdHksIGxpYnJhcmllcyB0aGF0IGFyZSBub3QgalF1ZXJ5IHNob3VsZFxuLy8gZGVjbGFyZSB0aGVtc2VsdmVzIGFzIGFub255bW91cyBtb2R1bGVzLCBhbmQgYXZvaWQgc2V0dGluZyBhIGdsb2JhbCBpZiBhblxuLy8gQU1EIGxvYWRlciBpcyBwcmVzZW50LiBqUXVlcnkgaXMgYSBzcGVjaWFsIGNhc2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcmJ1cmtlL3JlcXVpcmVqcy93aWtpL1VwZGF0aW5nLWV4aXN0aW5nLWxpYnJhcmllcyN3aWtpLWFub25cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKCBcImpxdWVyeVwiLCBbXSwgZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGpRdWVyeTtcblx0fSApO1xufVxuXG5cblxuXG52YXJcblxuXHQvLyBNYXAgb3ZlciBqUXVlcnkgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0X2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksXG5cblx0Ly8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0XyQgPSB3aW5kb3cuJDtcblxualF1ZXJ5Lm5vQ29uZmxpY3QgPSBmdW5jdGlvbiggZGVlcCApIHtcblx0aWYgKCB3aW5kb3cuJCA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy4kID0gXyQ7XG5cdH1cblxuXHRpZiAoIGRlZXAgJiYgd2luZG93LmpRdWVyeSA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5O1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeTtcbn07XG5cbi8vIEV4cG9zZSBqUXVlcnkgYW5kICQgaWRlbnRpZmllcnMsIGV2ZW4gaW4gQU1EXG4vLyAoIzcxMDIjY29tbWVudDoxMCwgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvcHVsbC81NTcpXG4vLyBhbmQgQ29tbW9uSlMgZm9yIGJyb3dzZXIgZW11bGF0b3JzICgjMTM1NjYpXG5pZiAoICFub0dsb2JhbCApIHtcblx0d2luZG93LmpRdWVyeSA9IHdpbmRvdy4kID0galF1ZXJ5O1xufVxuXG5cblxuXG5yZXR1cm4galF1ZXJ5O1xufSApO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvanF1ZXJ5L2Rpc3QvanF1ZXJ5LmpzXG4vLyBtb2R1bGUgaWQgPSAwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIEphdmFzY3JpcHRcblxuaW1wb3J0ICQgZnJvbSAnanF1ZXJ5J1xuaW1wb3J0ICdib290c3RyYXAnO1xuaW1wb3J0ICdib290c3RyYXAtc2VsZWN0JztcbmltcG9ydCAnYm9vdHN0cmFwLXZhbGlkYXRvcic7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQnO1xuXG5cbi8vIENTU1xuXG5pbXBvcnQgJ2Jvb3RzdHJhcC9kaXN0L2Nzcy9ib290c3RyYXAuY3NzJztcbmltcG9ydCAnYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2Nzcy9ib290c3RyYXAtc2VsZWN0LmNzcyc7XG5pbXBvcnQgJ2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3MnO1xuaW1wb3J0ICcuL3N0eWxlLmNzcydcblxuJChmdW5jdGlvbiAoKSB7XG4gIFxuICAkKFwiI215SW5wdXRcIikub24oXCJrZXl1cFwiLCBmdW5jdGlvbihldmVudE9iamVjdCkge1xuICAgIFxuICAgIHZhciBpbnB1dCwgZmlsdGVyLCB1bCwgbGksIGEsIGk7XG5cbiAgICBpbnB1dCA9IGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQ7XG4gICAgZmlsdGVyID0gaW5wdXQudmFsdWUudG9VcHBlckNhc2UoKTtcbiAgICB1bCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXlVTFwiKTtcbiAgICBsaSA9IHVsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdhJyk7XG5cbiAgICAvLyBMb29wIHRocm91Z2ggYWxsIGxpc3QgaXRlbXMsIGFuZCBoaWRlIHRob3NlIHdobyBkb24ndCBtYXRjaCB0aGUgc2VhcmNoIHF1ZXJ5XG4gICAgZm9yIChpID0gMDsgaSA8IGxpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhID0gbGlbaV07IC8vbGlbaV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJhXCIpWzBdO1xuICAgICAgaWYgKGEuaW5uZXJIVE1MLnRvVXBwZXJDYXNlKCkuaW5kZXhPZihmaWx0ZXIpID4gLTEpIHtcblx0bGlbaV0uc3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICB9IGVsc2Uge1xuXHRsaVtpXS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICB9XG4gICAgfVxuXG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNoZWNrVXNlcm5hbWVJbnB1dEhhbmRsZXIoZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgaW5wdXRfZWwgPSAkKGV2ZW50T2JqZWN0LmN1cnJlbnRUYXJnZXQpO1xuICAgIHZhciBkYXRhID0gSlNPTi5zdHJpbmdpZnkoe1widXNlcm5hbWVcIjogaW5wdXRfZWwudmFsKCl9KTtcbiAgICB2YXIgdXJsID0gYC90ZWFjaGVycy9jaGVja191c2VybmFtZS8ke2lucHV0X2VsLnZhbCgpfWBcbiAgICAgICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHRpZiAocmVzdWx0LmV4aXN0cykge1xuXHQgIGNvbnNvbGUubG9nKFwiVXNlcm5hbWUgZXhpc3RzXCIpO1xuXHR9XG4gICAgICB9LFxuICAgICAgXCJqc29uXCJcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gdXNlcm5hbWVHZW5lcmF0b3IoZXZlbnRPYmplY3QsIGZpcnN0bmFtZSwgc3VybmFtZSkge1xuICAgIHZhciBpbnB1dF9lbCA9ICQoZXZlbnRPYmplY3QuY3VycmVudFRhcmdldCk7XG4gICAgaW5wdXRfZWwudmFsKGZpcnN0bmFtZStcIi5cIitzdXJuYW1lKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlbGV0ZVJlbGF0aW9uSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgXG4gICAgICAkLmFqYXgoe1xuXHR1cmw6IHVybCxcblx0dHlwZTogJ0RFTEVURScsXG5cdHN1Y2Nlc3M6IGZ1bmN0aW9uKHJlc3VsdCkge1xuXHQgIGVsLmNsb3Nlc3QoXCIubGlzdC1ncm91cC1pdGVtXCIpLnJlbW92ZSgpO1xuXHQgIG1vZGFsRWwubW9kYWwoJ2hpZGUnKTtcblx0fVxuICAgICAgfSk7XG4gICAgICBcbiAgICB9KTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZnVuY3Rpb24gZGVsZXRlSGFuZGxlcihldmVudE9iamVjdCkge1xuICAgIHZhciB1cmwgPSB0aGlzLmRhdGFzZXQudXJsO1xuICAgIHZhciBtb2RhbEVsID0gJCgnI2thcm1lbi1tb2RhbC1yZW1vdmUnKTtcbiAgICBcbiAgICB2YXIgZWwgPSAkKHRoaXMpO1xuXG4gICAgbW9kYWxFbC5tb2RhbCh7YmFja2Ryb3A6ICdzdGF0aWMnfSkub25lKCdjbGljaycsICcja2FybWVuLW1vZGFsLWJ0bi1jb25maXJtJywgZnVuY3Rpb24oKSB7XG4gICAgICBcbiAgICAgICQuYWpheCh7XG5cdHVybDogdXJsLFxuXHR0eXBlOiAnREVMRVRFJyxcblx0c3VjY2VzczogZnVuY3Rpb24ocmVzdWx0KSB7XG5cdCAgbW9kYWxFbC5tb2RhbCgnaGlkZScpO1xuXHQgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKHJlc3VsdC5yZWRpcmVjdF91cmwpO1xuXHR9XG4gICAgICB9KTtcbiAgICAgIFxuICAgIH0pO1xuICAgIFxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgXG4gICQoXCIuYWpheC1wb3N0XCIpLm9uKFwiY2xpY2tcIiwgZnVuY3Rpb24oZXZlbnRPYmplY3QpIHtcbiAgICB2YXIgc2VsZWN0X2VsID0gJChcIiNcIit0aGlzLmRhdGFzZXQuc2VsZWN0KS5maXJzdCgpO1xuICAgIHZhciBsaXN0Z3JvdXBfZWwgPSAkKFwiI1wiK3RoaXMuZGF0YXNldC5saXN0Z3JvdXApLmZpcnN0KCk7XG4gICAgdmFyIHVybCA9IHRoaXMuZGF0YXNldC51cmw7XG4gICAgdmFyIGRhdGEgPSBKU09OLnN0cmluZ2lmeSh7XCJpZHNcIjogc2VsZWN0X2VsLnZhbCgpfSk7XG4gICAgXG4gICAgJC5wb3N0KFxuICAgICAgdXJsLFxuICAgICAgZGF0YSxcbiAgICAgIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHR2YXIgaTtcblx0aWYgKHJlc3VsdC5lbGVtZW50cyAhPSBudWxsKSB7XG5cdCAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5lbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXHQgICAgdmFyIG5ld0l0ZW0gPSBgXG5cdFx0PGEgaHJlZj1cIiNcIiBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBjbGVhcmZpeFwiPlxuXHRcdDxzcGFuIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1ib29rXCI+PC9zcGFuPlxuXHRcdCR7cmVzdWx0LmVsZW1lbnRzW2ldLk5hbWV9XG5cdFx0PHNwYW4gY2xhc3M9XCJwdWxsLXJpZ2h0XCI+XG5cdFx0PGJ1dHRvbiBkYXRhLXVybD1cIi8ke3Jlc3VsdC5uYW1lMX0vJHtyZXN1bHQuaWQxfS8ke3Jlc3VsdC5uYW1lMn0vJHtyZXN1bHQuaWQyW2ldfS9kZWxldGVcIiBjbGFzcz1cImJ0biBidG4teHMgYnRuLXdhcm5pbmcga2FybWVuLWFqYXgtZGVsZXRlXCI+XG5cdFx0PHNwYW4gY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXRyYXNoXCI+PC9zcGFuPlxuXHRcdDwvYnV0dG9uPlxuXHQgICAgICA8L3NwYW4+XG5cdCAgICAgIGA7XG5cdCAgICAkKGxpc3Rncm91cF9lbCkuYXBwZW5kKG5ld0l0ZW0pO1xuXHQgICAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblx0ICB9XG5cdH1cbiAgICAgIFxuICAgICAgfSxcbiAgICAgIFwianNvblwiXG4gICAgKTtcblxuICAgIHNlbGVjdF9lbC52YWwoJ2RlZmF1bHQnKTtcbiAgICBzZWxlY3RfZWwuc2VsZWN0cGlja2VyKFwicmVmcmVzaFwiKTtcbiAgICBcbiAgICByZXR1cm4gZmFsc2U7XG4gICAgXG4gIH0pO1xuXG4gICQoXCIua2FybWVuLWFqYXgtZGVsZXRlLXJlbGF0aW9uXCIpLm9uKFwiY2xpY2tcIiwgZGVsZXRlUmVsYXRpb25IYW5kbGVyKTtcbiAgJChcIi5rYXJtZW4tYWpheC1kZWxldGVcIikub24oXCJjbGlja1wiLCBkZWxldGVIYW5kbGVyKTtcblxufSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBUaGlzIGZpbGUgaXMgYXV0b2dlbmVyYXRlZCB2aWEgdGhlIGBjb21tb25qc2AgR3J1bnQgdGFzay4gWW91IGNhbiByZXF1aXJlKCkgdGhpcyBmaWxlIGluIGEgQ29tbW9uSlMgZW52aXJvbm1lbnQuXG5yZXF1aXJlKCcuLi8uLi9qcy90cmFuc2l0aW9uLmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL2FsZXJ0LmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL2J1dHRvbi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9jYXJvdXNlbC5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9jb2xsYXBzZS5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9kcm9wZG93bi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9tb2RhbC5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy90b29sdGlwLmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL3BvcG92ZXIuanMnKVxucmVxdWlyZSgnLi4vLi4vanMvc2Nyb2xsc3B5LmpzJylcbnJlcXVpcmUoJy4uLy4uL2pzL3RhYi5qcycpXG5yZXF1aXJlKCcuLi8uLi9qcy9hZmZpeC5qcycpXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvanMvbnBtLmpzXG4vLyBtb2R1bGUgaWQgPSAyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiB0cmFuc2l0aW9uLmpzIHYzLjMuN1xuICogaHR0cDovL2dldGJvb3RzdHJhcC5jb20vamF2YXNjcmlwdC8jdHJhbnNpdGlvbnNcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTEtMjAxNiBUd2l0dGVyLCBJbmMuXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cblxuK2Z1bmN0aW9uICgkKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBDU1MgVFJBTlNJVElPTiBTVVBQT1JUIChTaG91dG91dDogaHR0cDovL3d3dy5tb2Rlcm5penIuY29tLylcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gdHJhbnNpdGlvbkVuZCgpIHtcbiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdib290c3RyYXAnKVxuXG4gICAgdmFyIHRyYW5zRW5kRXZlbnROYW1lcyA9IHtcbiAgICAgIFdlYmtpdFRyYW5zaXRpb24gOiAnd2Via2l0VHJhbnNpdGlvbkVuZCcsXG4gICAgICBNb3pUcmFuc2l0aW9uICAgIDogJ3RyYW5zaXRpb25lbmQnLFxuICAgICAgT1RyYW5zaXRpb24gICAgICA6ICdvVHJhbnNpdGlvbkVuZCBvdHJhbnNpdGlvbmVuZCcsXG4gICAgICB0cmFuc2l0aW9uICAgICAgIDogJ3RyYW5zaXRpb25lbmQnXG4gICAgfVxuXG4gICAgZm9yICh2YXIgbmFtZSBpbiB0cmFuc0VuZEV2ZW50TmFtZXMpIHtcbiAgICAgIGlmIChlbC5zdHlsZVtuYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB7IGVuZDogdHJhbnNFbmRFdmVudE5hbWVzW25hbWVdIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2UgLy8gZXhwbGljaXQgZm9yIGllOCAoICAuXy4pXG4gIH1cblxuICAvLyBodHRwOi8vYmxvZy5hbGV4bWFjY2F3LmNvbS9jc3MtdHJhbnNpdGlvbnNcbiAgJC5mbi5lbXVsYXRlVHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uIChkdXJhdGlvbikge1xuICAgIHZhciBjYWxsZWQgPSBmYWxzZVxuICAgIHZhciAkZWwgPSB0aGlzXG4gICAgJCh0aGlzKS5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGZ1bmN0aW9uICgpIHsgY2FsbGVkID0gdHJ1ZSB9KVxuICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHsgaWYgKCFjYWxsZWQpICQoJGVsKS50cmlnZ2VyKCQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZCkgfVxuICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIGR1cmF0aW9uKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAkKGZ1bmN0aW9uICgpIHtcbiAgICAkLnN1cHBvcnQudHJhbnNpdGlvbiA9IHRyYW5zaXRpb25FbmQoKVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuXG5cbiAgICAkLmV2ZW50LnNwZWNpYWwuYnNUcmFuc2l0aW9uRW5kID0ge1xuICAgICAgYmluZFR5cGU6ICQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZCxcbiAgICAgIGRlbGVnYXRlVHlwZTogJC5zdXBwb3J0LnRyYW5zaXRpb24uZW5kLFxuICAgICAgaGFuZGxlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoJChlLnRhcmdldCkuaXModGhpcykpIHJldHVybiBlLmhhbmRsZU9iai5oYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90cmFuc2l0aW9uLmpzXG4vLyBtb2R1bGUgaWQgPSAzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBhbGVydC5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI2FsZXJ0c1xuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIEFMRVJUIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBkaXNtaXNzID0gJ1tkYXRhLWRpc21pc3M9XCJhbGVydFwiXSdcbiAgdmFyIEFsZXJ0ICAgPSBmdW5jdGlvbiAoZWwpIHtcbiAgICAkKGVsKS5vbignY2xpY2snLCBkaXNtaXNzLCB0aGlzLmNsb3NlKVxuICB9XG5cbiAgQWxlcnQuVkVSU0lPTiA9ICczLjMuNydcblxuICBBbGVydC5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwXG5cbiAgQWxlcnQucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgJHRoaXMgICAgPSAkKHRoaXMpXG4gICAgdmFyIHNlbGVjdG9yID0gJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKVxuXG4gICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgc2VsZWN0b3IgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICAgIHNlbGVjdG9yID0gc2VsZWN0b3IgJiYgc2VsZWN0b3IucmVwbGFjZSgvLiooPz0jW15cXHNdKiQpLywgJycpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB9XG5cbiAgICB2YXIgJHBhcmVudCA9ICQoc2VsZWN0b3IgPT09ICcjJyA/IFtdIDogc2VsZWN0b3IpXG5cbiAgICBpZiAoZSkgZS5wcmV2ZW50RGVmYXVsdCgpXG5cbiAgICBpZiAoISRwYXJlbnQubGVuZ3RoKSB7XG4gICAgICAkcGFyZW50ID0gJHRoaXMuY2xvc2VzdCgnLmFsZXJ0JylcbiAgICB9XG5cbiAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ2Nsb3NlLmJzLmFsZXJ0JykpXG5cbiAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICAkcGFyZW50LnJlbW92ZUNsYXNzKCdpbicpXG5cbiAgICBmdW5jdGlvbiByZW1vdmVFbGVtZW50KCkge1xuICAgICAgLy8gZGV0YWNoIGZyb20gcGFyZW50LCBmaXJlIGV2ZW50IHRoZW4gY2xlYW4gdXAgZGF0YVxuICAgICAgJHBhcmVudC5kZXRhY2goKS50cmlnZ2VyKCdjbG9zZWQuYnMuYWxlcnQnKS5yZW1vdmUoKVxuICAgIH1cblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmICRwYXJlbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAkcGFyZW50XG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIHJlbW92ZUVsZW1lbnQpXG4gICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChBbGVydC5UUkFOU0lUSU9OX0RVUkFUSU9OKSA6XG4gICAgICByZW1vdmVFbGVtZW50KClcbiAgfVxuXG5cbiAgLy8gQUxFUlQgUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgPSAkdGhpcy5kYXRhKCdicy5hbGVydCcpXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMuYWxlcnQnLCAoZGF0YSA9IG5ldyBBbGVydCh0aGlzKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dLmNhbGwoJHRoaXMpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmFsZXJ0XG5cbiAgJC5mbi5hbGVydCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmFsZXJ0LkNvbnN0cnVjdG9yID0gQWxlcnRcblxuXG4gIC8vIEFMRVJUIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5hbGVydC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYWxlcnQgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBBTEVSVCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5hbGVydC5kYXRhLWFwaScsIGRpc21pc3MsIEFsZXJ0LnByb3RvdHlwZS5jbG9zZSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2FsZXJ0LmpzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBidXR0b24uanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNidXR0b25zXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQlVUVE9OIFBVQkxJQyBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBCdXR0b24gPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGVsZW1lbnQgID0gJChlbGVtZW50KVxuICAgIHRoaXMub3B0aW9ucyAgID0gJC5leHRlbmQoe30sIEJ1dHRvbi5ERUZBVUxUUywgb3B0aW9ucylcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlXG4gIH1cblxuICBCdXR0b24uVkVSU0lPTiAgPSAnMy4zLjcnXG5cbiAgQnV0dG9uLkRFRkFVTFRTID0ge1xuICAgIGxvYWRpbmdUZXh0OiAnbG9hZGluZy4uLidcbiAgfVxuXG4gIEJ1dHRvbi5wcm90b3R5cGUuc2V0U3RhdGUgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICB2YXIgZCAgICA9ICdkaXNhYmxlZCdcbiAgICB2YXIgJGVsICA9IHRoaXMuJGVsZW1lbnRcbiAgICB2YXIgdmFsICA9ICRlbC5pcygnaW5wdXQnKSA/ICd2YWwnIDogJ2h0bWwnXG4gICAgdmFyIGRhdGEgPSAkZWwuZGF0YSgpXG5cbiAgICBzdGF0ZSArPSAnVGV4dCdcblxuICAgIGlmIChkYXRhLnJlc2V0VGV4dCA9PSBudWxsKSAkZWwuZGF0YSgncmVzZXRUZXh0JywgJGVsW3ZhbF0oKSlcblxuICAgIC8vIHB1c2ggdG8gZXZlbnQgbG9vcCB0byBhbGxvdyBmb3JtcyB0byBzdWJtaXRcbiAgICBzZXRUaW1lb3V0KCQucHJveHkoZnVuY3Rpb24gKCkge1xuICAgICAgJGVsW3ZhbF0oZGF0YVtzdGF0ZV0gPT0gbnVsbCA/IHRoaXMub3B0aW9uc1tzdGF0ZV0gOiBkYXRhW3N0YXRlXSlcblxuICAgICAgaWYgKHN0YXRlID09ICdsb2FkaW5nVGV4dCcpIHtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlXG4gICAgICAgICRlbC5hZGRDbGFzcyhkKS5hdHRyKGQsIGQpLnByb3AoZCwgdHJ1ZSlcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0xvYWRpbmcpIHtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZVxuICAgICAgICAkZWwucmVtb3ZlQ2xhc3MoZCkucmVtb3ZlQXR0cihkKS5wcm9wKGQsIGZhbHNlKVxuICAgICAgfVxuICAgIH0sIHRoaXMpLCAwKVxuICB9XG5cbiAgQnV0dG9uLnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNoYW5nZWQgPSB0cnVlXG4gICAgdmFyICRwYXJlbnQgPSB0aGlzLiRlbGVtZW50LmNsb3Nlc3QoJ1tkYXRhLXRvZ2dsZT1cImJ1dHRvbnNcIl0nKVxuXG4gICAgaWYgKCRwYXJlbnQubGVuZ3RoKSB7XG4gICAgICB2YXIgJGlucHV0ID0gdGhpcy4kZWxlbWVudC5maW5kKCdpbnB1dCcpXG4gICAgICBpZiAoJGlucHV0LnByb3AoJ3R5cGUnKSA9PSAncmFkaW8nKSB7XG4gICAgICAgIGlmICgkaW5wdXQucHJvcCgnY2hlY2tlZCcpKSBjaGFuZ2VkID0gZmFsc2VcbiAgICAgICAgJHBhcmVudC5maW5kKCcuYWN0aXZlJykucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICB9IGVsc2UgaWYgKCRpbnB1dC5wcm9wKCd0eXBlJykgPT0gJ2NoZWNrYm94Jykge1xuICAgICAgICBpZiAoKCRpbnB1dC5wcm9wKCdjaGVja2VkJykpICE9PSB0aGlzLiRlbGVtZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSkgY2hhbmdlZCA9IGZhbHNlXG4gICAgICAgIHRoaXMuJGVsZW1lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICB9XG4gICAgICAkaW5wdXQucHJvcCgnY2hlY2tlZCcsIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2FjdGl2ZScpKVxuICAgICAgaWYgKGNoYW5nZWQpICRpbnB1dC50cmlnZ2VyKCdjaGFuZ2UnKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLiRlbGVtZW50LmF0dHIoJ2FyaWEtcHJlc3NlZCcsICF0aGlzLiRlbGVtZW50Lmhhc0NsYXNzKCdhY3RpdmUnKSlcbiAgICAgIHRoaXMuJGVsZW1lbnQudG9nZ2xlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgfVxuICB9XG5cblxuICAvLyBCVVRUT04gUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmJ1dHRvbicpXG4gICAgICB2YXIgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMuYnV0dG9uJywgKGRhdGEgPSBuZXcgQnV0dG9uKHRoaXMsIG9wdGlvbnMpKSlcblxuICAgICAgaWYgKG9wdGlvbiA9PSAndG9nZ2xlJykgZGF0YS50b2dnbGUoKVxuICAgICAgZWxzZSBpZiAob3B0aW9uKSBkYXRhLnNldFN0YXRlKG9wdGlvbilcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uYnV0dG9uXG5cbiAgJC5mbi5idXR0b24gICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5idXR0b24uQ29uc3RydWN0b3IgPSBCdXR0b25cblxuXG4gIC8vIEJVVFRPTiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLmJ1dHRvbi5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYnV0dG9uID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gQlVUVE9OIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpXG4gICAgLm9uKCdjbGljay5icy5idXR0b24uZGF0YS1hcGknLCAnW2RhdGEtdG9nZ2xlXj1cImJ1dHRvblwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgJGJ0biA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJy5idG4nKVxuICAgICAgUGx1Z2luLmNhbGwoJGJ0biwgJ3RvZ2dsZScpXG4gICAgICBpZiAoISgkKGUudGFyZ2V0KS5pcygnaW5wdXRbdHlwZT1cInJhZGlvXCJdLCBpbnB1dFt0eXBlPVwiY2hlY2tib3hcIl0nKSkpIHtcbiAgICAgICAgLy8gUHJldmVudCBkb3VibGUgY2xpY2sgb24gcmFkaW9zLCBhbmQgdGhlIGRvdWJsZSBzZWxlY3Rpb25zIChzbyBjYW5jZWxsYXRpb24pIG9uIGNoZWNrYm94ZXNcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIC8vIFRoZSB0YXJnZXQgY29tcG9uZW50IHN0aWxsIHJlY2VpdmUgdGhlIGZvY3VzXG4gICAgICAgIGlmICgkYnRuLmlzKCdpbnB1dCxidXR0b24nKSkgJGJ0bi50cmlnZ2VyKCdmb2N1cycpXG4gICAgICAgIGVsc2UgJGJ0bi5maW5kKCdpbnB1dDp2aXNpYmxlLGJ1dHRvbjp2aXNpYmxlJykuZmlyc3QoKS50cmlnZ2VyKCdmb2N1cycpXG4gICAgICB9XG4gICAgfSlcbiAgICAub24oJ2ZvY3VzLmJzLmJ1dHRvbi5kYXRhLWFwaSBibHVyLmJzLmJ1dHRvbi5kYXRhLWFwaScsICdbZGF0YS10b2dnbGVePVwiYnV0dG9uXCJdJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICQoZS50YXJnZXQpLmNsb3Nlc3QoJy5idG4nKS50b2dnbGVDbGFzcygnZm9jdXMnLCAvXmZvY3VzKGluKT8kLy50ZXN0KGUudHlwZSkpXG4gICAgfSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2pzL2J1dHRvbi5qc1xuLy8gbW9kdWxlIGlkID0gNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogY2Fyb3VzZWwuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNjYXJvdXNlbFxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIENBUk9VU0VMIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBDYXJvdXNlbCA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy4kZWxlbWVudCAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLiRpbmRpY2F0b3JzID0gdGhpcy4kZWxlbWVudC5maW5kKCcuY2Fyb3VzZWwtaW5kaWNhdG9ycycpXG4gICAgdGhpcy5vcHRpb25zICAgICA9IG9wdGlvbnNcbiAgICB0aGlzLnBhdXNlZCAgICAgID0gbnVsbFxuICAgIHRoaXMuc2xpZGluZyAgICAgPSBudWxsXG4gICAgdGhpcy5pbnRlcnZhbCAgICA9IG51bGxcbiAgICB0aGlzLiRhY3RpdmUgICAgID0gbnVsbFxuICAgIHRoaXMuJGl0ZW1zICAgICAgPSBudWxsXG5cbiAgICB0aGlzLm9wdGlvbnMua2V5Ym9hcmQgJiYgdGhpcy4kZWxlbWVudC5vbigna2V5ZG93bi5icy5jYXJvdXNlbCcsICQucHJveHkodGhpcy5rZXlkb3duLCB0aGlzKSlcblxuICAgIHRoaXMub3B0aW9ucy5wYXVzZSA9PSAnaG92ZXInICYmICEoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSAmJiB0aGlzLiRlbGVtZW50XG4gICAgICAub24oJ21vdXNlZW50ZXIuYnMuY2Fyb3VzZWwnLCAkLnByb3h5KHRoaXMucGF1c2UsIHRoaXMpKVxuICAgICAgLm9uKCdtb3VzZWxlYXZlLmJzLmNhcm91c2VsJywgJC5wcm94eSh0aGlzLmN5Y2xlLCB0aGlzKSlcbiAgfVxuXG4gIENhcm91c2VsLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIENhcm91c2VsLlRSQU5TSVRJT05fRFVSQVRJT04gPSA2MDBcblxuICBDYXJvdXNlbC5ERUZBVUxUUyA9IHtcbiAgICBpbnRlcnZhbDogNTAwMCxcbiAgICBwYXVzZTogJ2hvdmVyJyxcbiAgICB3cmFwOiB0cnVlLFxuICAgIGtleWJvYXJkOiB0cnVlXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUua2V5ZG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZS50YXJnZXQudGFnTmFtZSkpIHJldHVyblxuICAgIHN3aXRjaCAoZS53aGljaCkge1xuICAgICAgY2FzZSAzNzogdGhpcy5wcmV2KCk7IGJyZWFrXG4gICAgICBjYXNlIDM5OiB0aGlzLm5leHQoKTsgYnJlYWtcbiAgICAgIGRlZmF1bHQ6IHJldHVyblxuICAgIH1cblxuICAgIGUucHJldmVudERlZmF1bHQoKVxuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmN5Y2xlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBlIHx8ICh0aGlzLnBhdXNlZCA9IGZhbHNlKVxuXG4gICAgdGhpcy5pbnRlcnZhbCAmJiBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWwpXG5cbiAgICB0aGlzLm9wdGlvbnMuaW50ZXJ2YWxcbiAgICAgICYmICF0aGlzLnBhdXNlZFxuICAgICAgJiYgKHRoaXMuaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgkLnByb3h5KHRoaXMubmV4dCwgdGhpcyksIHRoaXMub3B0aW9ucy5pbnRlcnZhbCkpXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmdldEl0ZW1JbmRleCA9IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgdGhpcy4kaXRlbXMgPSBpdGVtLnBhcmVudCgpLmNoaWxkcmVuKCcuaXRlbScpXG4gICAgcmV0dXJuIHRoaXMuJGl0ZW1zLmluZGV4KGl0ZW0gfHwgdGhpcy4kYWN0aXZlKVxuICB9XG5cbiAgQ2Fyb3VzZWwucHJvdG90eXBlLmdldEl0ZW1Gb3JEaXJlY3Rpb24gPSBmdW5jdGlvbiAoZGlyZWN0aW9uLCBhY3RpdmUpIHtcbiAgICB2YXIgYWN0aXZlSW5kZXggPSB0aGlzLmdldEl0ZW1JbmRleChhY3RpdmUpXG4gICAgdmFyIHdpbGxXcmFwID0gKGRpcmVjdGlvbiA9PSAncHJldicgJiYgYWN0aXZlSW5kZXggPT09IDApXG4gICAgICAgICAgICAgICAgfHwgKGRpcmVjdGlvbiA9PSAnbmV4dCcgJiYgYWN0aXZlSW5kZXggPT0gKHRoaXMuJGl0ZW1zLmxlbmd0aCAtIDEpKVxuICAgIGlmICh3aWxsV3JhcCAmJiAhdGhpcy5vcHRpb25zLndyYXApIHJldHVybiBhY3RpdmVcbiAgICB2YXIgZGVsdGEgPSBkaXJlY3Rpb24gPT0gJ3ByZXYnID8gLTEgOiAxXG4gICAgdmFyIGl0ZW1JbmRleCA9IChhY3RpdmVJbmRleCArIGRlbHRhKSAlIHRoaXMuJGl0ZW1zLmxlbmd0aFxuICAgIHJldHVybiB0aGlzLiRpdGVtcy5lcShpdGVtSW5kZXgpXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUudG8gPSBmdW5jdGlvbiAocG9zKSB7XG4gICAgdmFyIHRoYXQgICAgICAgID0gdGhpc1xuICAgIHZhciBhY3RpdmVJbmRleCA9IHRoaXMuZ2V0SXRlbUluZGV4KHRoaXMuJGFjdGl2ZSA9IHRoaXMuJGVsZW1lbnQuZmluZCgnLml0ZW0uYWN0aXZlJykpXG5cbiAgICBpZiAocG9zID4gKHRoaXMuJGl0ZW1zLmxlbmd0aCAtIDEpIHx8IHBvcyA8IDApIHJldHVyblxuXG4gICAgaWYgKHRoaXMuc2xpZGluZykgICAgICAgcmV0dXJuIHRoaXMuJGVsZW1lbnQub25lKCdzbGlkLmJzLmNhcm91c2VsJywgZnVuY3Rpb24gKCkgeyB0aGF0LnRvKHBvcykgfSkgLy8geWVzLCBcInNsaWRcIlxuICAgIGlmIChhY3RpdmVJbmRleCA9PSBwb3MpIHJldHVybiB0aGlzLnBhdXNlKCkuY3ljbGUoKVxuXG4gICAgcmV0dXJuIHRoaXMuc2xpZGUocG9zID4gYWN0aXZlSW5kZXggPyAnbmV4dCcgOiAncHJldicsIHRoaXMuJGl0ZW1zLmVxKHBvcykpXG4gIH1cblxuICBDYXJvdXNlbC5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoZSkge1xuICAgIGUgfHwgKHRoaXMucGF1c2VkID0gdHJ1ZSlcblxuICAgIGlmICh0aGlzLiRlbGVtZW50LmZpbmQoJy5uZXh0LCAucHJldicpLmxlbmd0aCAmJiAkLnN1cHBvcnQudHJhbnNpdGlvbikge1xuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCQuc3VwcG9ydC50cmFuc2l0aW9uLmVuZClcbiAgICAgIHRoaXMuY3ljbGUodHJ1ZSlcbiAgICB9XG5cbiAgICB0aGlzLmludGVydmFsID0gY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5uZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnNsaWRpbmcpIHJldHVyblxuICAgIHJldHVybiB0aGlzLnNsaWRlKCduZXh0JylcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnNsaWRpbmcpIHJldHVyblxuICAgIHJldHVybiB0aGlzLnNsaWRlKCdwcmV2JylcbiAgfVxuXG4gIENhcm91c2VsLnByb3RvdHlwZS5zbGlkZSA9IGZ1bmN0aW9uICh0eXBlLCBuZXh0KSB7XG4gICAgdmFyICRhY3RpdmUgICA9IHRoaXMuJGVsZW1lbnQuZmluZCgnLml0ZW0uYWN0aXZlJylcbiAgICB2YXIgJG5leHQgICAgID0gbmV4dCB8fCB0aGlzLmdldEl0ZW1Gb3JEaXJlY3Rpb24odHlwZSwgJGFjdGl2ZSlcbiAgICB2YXIgaXNDeWNsaW5nID0gdGhpcy5pbnRlcnZhbFxuICAgIHZhciBkaXJlY3Rpb24gPSB0eXBlID09ICduZXh0JyA/ICdsZWZ0JyA6ICdyaWdodCdcbiAgICB2YXIgdGhhdCAgICAgID0gdGhpc1xuXG4gICAgaWYgKCRuZXh0Lmhhc0NsYXNzKCdhY3RpdmUnKSkgcmV0dXJuICh0aGlzLnNsaWRpbmcgPSBmYWxzZSlcblxuICAgIHZhciByZWxhdGVkVGFyZ2V0ID0gJG5leHRbMF1cbiAgICB2YXIgc2xpZGVFdmVudCA9ICQuRXZlbnQoJ3NsaWRlLmJzLmNhcm91c2VsJywge1xuICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldCxcbiAgICAgIGRpcmVjdGlvbjogZGlyZWN0aW9uXG4gICAgfSlcbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc2xpZGVFdmVudClcbiAgICBpZiAoc2xpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLnNsaWRpbmcgPSB0cnVlXG5cbiAgICBpc0N5Y2xpbmcgJiYgdGhpcy5wYXVzZSgpXG5cbiAgICBpZiAodGhpcy4kaW5kaWNhdG9ycy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuJGluZGljYXRvcnMuZmluZCgnLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuICAgICAgdmFyICRuZXh0SW5kaWNhdG9yID0gJCh0aGlzLiRpbmRpY2F0b3JzLmNoaWxkcmVuKClbdGhpcy5nZXRJdGVtSW5kZXgoJG5leHQpXSlcbiAgICAgICRuZXh0SW5kaWNhdG9yICYmICRuZXh0SW5kaWNhdG9yLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgIH1cblxuICAgIHZhciBzbGlkRXZlbnQgPSAkLkV2ZW50KCdzbGlkLmJzLmNhcm91c2VsJywgeyByZWxhdGVkVGFyZ2V0OiByZWxhdGVkVGFyZ2V0LCBkaXJlY3Rpb246IGRpcmVjdGlvbiB9KSAvLyB5ZXMsIFwic2xpZFwiXG4gICAgaWYgKCQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ3NsaWRlJykpIHtcbiAgICAgICRuZXh0LmFkZENsYXNzKHR5cGUpXG4gICAgICAkbmV4dFswXS5vZmZzZXRXaWR0aCAvLyBmb3JjZSByZWZsb3dcbiAgICAgICRhY3RpdmUuYWRkQ2xhc3MoZGlyZWN0aW9uKVxuICAgICAgJG5leHQuYWRkQ2xhc3MoZGlyZWN0aW9uKVxuICAgICAgJGFjdGl2ZVxuICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgJG5leHQucmVtb3ZlQ2xhc3MoW3R5cGUsIGRpcmVjdGlvbl0uam9pbignICcpKS5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgICAgICAkYWN0aXZlLnJlbW92ZUNsYXNzKFsnYWN0aXZlJywgZGlyZWN0aW9uXS5qb2luKCcgJykpXG4gICAgICAgICAgdGhhdC5zbGlkaW5nID0gZmFsc2VcbiAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcihzbGlkRXZlbnQpXG4gICAgICAgICAgfSwgMClcbiAgICAgICAgfSlcbiAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKENhcm91c2VsLlRSQU5TSVRJT05fRFVSQVRJT04pXG4gICAgfSBlbHNlIHtcbiAgICAgICRhY3RpdmUucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpXG4gICAgICAkbmV4dC5hZGRDbGFzcygnYWN0aXZlJylcbiAgICAgIHRoaXMuc2xpZGluZyA9IGZhbHNlXG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc2xpZEV2ZW50KVxuICAgIH1cblxuICAgIGlzQ3ljbGluZyAmJiB0aGlzLmN5Y2xlKClcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuXG4gIC8vIENBUk9VU0VMIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmNhcm91c2VsJylcbiAgICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sIENhcm91c2VsLkRFRkFVTFRTLCAkdGhpcy5kYXRhKCksIHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uKVxuICAgICAgdmFyIGFjdGlvbiAgPSB0eXBlb2Ygb3B0aW9uID09ICdzdHJpbmcnID8gb3B0aW9uIDogb3B0aW9ucy5zbGlkZVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmNhcm91c2VsJywgKGRhdGEgPSBuZXcgQ2Fyb3VzZWwodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ251bWJlcicpIGRhdGEudG8ob3B0aW9uKVxuICAgICAgZWxzZSBpZiAoYWN0aW9uKSBkYXRhW2FjdGlvbl0oKVxuICAgICAgZWxzZSBpZiAob3B0aW9ucy5pbnRlcnZhbCkgZGF0YS5wYXVzZSgpLmN5Y2xlKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uY2Fyb3VzZWxcblxuICAkLmZuLmNhcm91c2VsICAgICAgICAgICAgID0gUGx1Z2luXG4gICQuZm4uY2Fyb3VzZWwuQ29uc3RydWN0b3IgPSBDYXJvdXNlbFxuXG5cbiAgLy8gQ0FST1VTRUwgTk8gQ09ORkxJQ1RcbiAgLy8gPT09PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLmNhcm91c2VsLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5jYXJvdXNlbCA9IG9sZFxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuXG4gIC8vIENBUk9VU0VMIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgdmFyIGNsaWNrSGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIGhyZWZcbiAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICB2YXIgJHRhcmdldCA9ICQoJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKSB8fCAoaHJlZiA9ICR0aGlzLmF0dHIoJ2hyZWYnKSkgJiYgaHJlZi5yZXBsYWNlKC8uKig/PSNbXlxcc10rJCkvLCAnJykpIC8vIHN0cmlwIGZvciBpZTdcbiAgICBpZiAoISR0YXJnZXQuaGFzQ2xhc3MoJ2Nhcm91c2VsJykpIHJldHVyblxuICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sICR0YXJnZXQuZGF0YSgpLCAkdGhpcy5kYXRhKCkpXG4gICAgdmFyIHNsaWRlSW5kZXggPSAkdGhpcy5hdHRyKCdkYXRhLXNsaWRlLXRvJylcbiAgICBpZiAoc2xpZGVJbmRleCkgb3B0aW9ucy5pbnRlcnZhbCA9IGZhbHNlXG5cbiAgICBQbHVnaW4uY2FsbCgkdGFyZ2V0LCBvcHRpb25zKVxuXG4gICAgaWYgKHNsaWRlSW5kZXgpIHtcbiAgICAgICR0YXJnZXQuZGF0YSgnYnMuY2Fyb3VzZWwnKS50byhzbGlkZUluZGV4KVxuICAgIH1cblxuICAgIGUucHJldmVudERlZmF1bHQoKVxuICB9XG5cbiAgJChkb2N1bWVudClcbiAgICAub24oJ2NsaWNrLmJzLmNhcm91c2VsLmRhdGEtYXBpJywgJ1tkYXRhLXNsaWRlXScsIGNsaWNrSGFuZGxlcilcbiAgICAub24oJ2NsaWNrLmJzLmNhcm91c2VsLmRhdGEtYXBpJywgJ1tkYXRhLXNsaWRlLXRvXScsIGNsaWNrSGFuZGxlcilcblxuICAkKHdpbmRvdykub24oJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgJCgnW2RhdGEtcmlkZT1cImNhcm91c2VsXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJGNhcm91c2VsID0gJCh0aGlzKVxuICAgICAgUGx1Z2luLmNhbGwoJGNhcm91c2VsLCAkY2Fyb3VzZWwuZGF0YSgpKVxuICAgIH0pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9jYXJvdXNlbC5qc1xuLy8gbW9kdWxlIGlkID0gNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogY29sbGFwc2UuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNjb2xsYXBzZVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuLyoganNoaW50IGxhdGVkZWY6IGZhbHNlICovXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQ09MTEFQU0UgUFVCTElDIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgQ29sbGFwc2UgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGVsZW1lbnQgICAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLm9wdGlvbnMgICAgICAgPSAkLmV4dGVuZCh7fSwgQ29sbGFwc2UuREVGQVVMVFMsIG9wdGlvbnMpXG4gICAgdGhpcy4kdHJpZ2dlciAgICAgID0gJCgnW2RhdGEtdG9nZ2xlPVwiY29sbGFwc2VcIl1baHJlZj1cIiMnICsgZWxlbWVudC5pZCArICdcIl0sJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAnW2RhdGEtdG9nZ2xlPVwiY29sbGFwc2VcIl1bZGF0YS10YXJnZXQ9XCIjJyArIGVsZW1lbnQuaWQgKyAnXCJdJylcbiAgICB0aGlzLnRyYW5zaXRpb25pbmcgPSBudWxsXG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnBhcmVudCkge1xuICAgICAgdGhpcy4kcGFyZW50ID0gdGhpcy5nZXRQYXJlbnQoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyh0aGlzLiRlbGVtZW50LCB0aGlzLiR0cmlnZ2VyKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMudG9nZ2xlKSB0aGlzLnRvZ2dsZSgpXG4gIH1cblxuICBDb2xsYXBzZS5WRVJTSU9OICA9ICczLjMuNydcblxuICBDb2xsYXBzZS5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMzUwXG5cbiAgQ29sbGFwc2UuREVGQVVMVFMgPSB7XG4gICAgdG9nZ2xlOiB0cnVlXG4gIH1cblxuICBDb2xsYXBzZS5wcm90b3R5cGUuZGltZW5zaW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBoYXNXaWR0aCA9IHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ3dpZHRoJylcbiAgICByZXR1cm4gaGFzV2lkdGggPyAnd2lkdGgnIDogJ2hlaWdodCdcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnRyYW5zaXRpb25pbmcgfHwgdGhpcy4kZWxlbWVudC5oYXNDbGFzcygnaW4nKSkgcmV0dXJuXG5cbiAgICB2YXIgYWN0aXZlc0RhdGFcbiAgICB2YXIgYWN0aXZlcyA9IHRoaXMuJHBhcmVudCAmJiB0aGlzLiRwYXJlbnQuY2hpbGRyZW4oJy5wYW5lbCcpLmNoaWxkcmVuKCcuaW4sIC5jb2xsYXBzaW5nJylcblxuICAgIGlmIChhY3RpdmVzICYmIGFjdGl2ZXMubGVuZ3RoKSB7XG4gICAgICBhY3RpdmVzRGF0YSA9IGFjdGl2ZXMuZGF0YSgnYnMuY29sbGFwc2UnKVxuICAgICAgaWYgKGFjdGl2ZXNEYXRhICYmIGFjdGl2ZXNEYXRhLnRyYW5zaXRpb25pbmcpIHJldHVyblxuICAgIH1cblxuICAgIHZhciBzdGFydEV2ZW50ID0gJC5FdmVudCgnc2hvdy5icy5jb2xsYXBzZScpXG4gICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKHN0YXJ0RXZlbnQpXG4gICAgaWYgKHN0YXJ0RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgaWYgKGFjdGl2ZXMgJiYgYWN0aXZlcy5sZW5ndGgpIHtcbiAgICAgIFBsdWdpbi5jYWxsKGFjdGl2ZXMsICdoaWRlJylcbiAgICAgIGFjdGl2ZXNEYXRhIHx8IGFjdGl2ZXMuZGF0YSgnYnMuY29sbGFwc2UnLCBudWxsKVxuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb24gPSB0aGlzLmRpbWVuc2lvbigpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlJylcbiAgICAgIC5hZGRDbGFzcygnY29sbGFwc2luZycpW2RpbWVuc2lvbl0oMClcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSlcblxuICAgIHRoaXMuJHRyaWdnZXJcbiAgICAgIC5yZW1vdmVDbGFzcygnY29sbGFwc2VkJylcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgdHJ1ZSlcblxuICAgIHRoaXMudHJhbnNpdGlvbmluZyA9IDFcblxuICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLnJlbW92ZUNsYXNzKCdjb2xsYXBzaW5nJylcbiAgICAgICAgLmFkZENsYXNzKCdjb2xsYXBzZSBpbicpW2RpbWVuc2lvbl0oJycpXG4gICAgICB0aGlzLnRyYW5zaXRpb25pbmcgPSAwXG4gICAgICB0aGlzLiRlbGVtZW50XG4gICAgICAgIC50cmlnZ2VyKCdzaG93bi5icy5jb2xsYXBzZScpXG4gICAgfVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuIGNvbXBsZXRlLmNhbGwodGhpcylcblxuICAgIHZhciBzY3JvbGxTaXplID0gJC5jYW1lbENhc2UoWydzY3JvbGwnLCBkaW1lbnNpb25dLmpvaW4oJy0nKSlcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsICQucHJveHkoY29tcGxldGUsIHRoaXMpKVxuICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKENvbGxhcHNlLlRSQU5TSVRJT05fRFVSQVRJT04pW2RpbWVuc2lvbl0odGhpcy4kZWxlbWVudFswXVtzY3JvbGxTaXplXSlcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnRyYW5zaXRpb25pbmcgfHwgIXRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2luJykpIHJldHVyblxuXG4gICAgdmFyIHN0YXJ0RXZlbnQgPSAkLkV2ZW50KCdoaWRlLmJzLmNvbGxhcHNlJylcbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoc3RhcnRFdmVudClcbiAgICBpZiAoc3RhcnRFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB2YXIgZGltZW5zaW9uID0gdGhpcy5kaW1lbnNpb24oKVxuXG4gICAgdGhpcy4kZWxlbWVudFtkaW1lbnNpb25dKHRoaXMuJGVsZW1lbnRbZGltZW5zaW9uXSgpKVswXS5vZmZzZXRIZWlnaHRcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIC5hZGRDbGFzcygnY29sbGFwc2luZycpXG4gICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNlIGluJylcbiAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgZmFsc2UpXG5cbiAgICB0aGlzLiR0cmlnZ2VyXG4gICAgICAuYWRkQ2xhc3MoJ2NvbGxhcHNlZCcpXG4gICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsIGZhbHNlKVxuXG4gICAgdGhpcy50cmFuc2l0aW9uaW5nID0gMVxuXG4gICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgdGhpcy50cmFuc2l0aW9uaW5nID0gMFxuICAgICAgdGhpcy4kZWxlbWVudFxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ2NvbGxhcHNpbmcnKVxuICAgICAgICAuYWRkQ2xhc3MoJ2NvbGxhcHNlJylcbiAgICAgICAgLnRyaWdnZXIoJ2hpZGRlbi5icy5jb2xsYXBzZScpXG4gICAgfVxuXG4gICAgaWYgKCEkLnN1cHBvcnQudHJhbnNpdGlvbikgcmV0dXJuIGNvbXBsZXRlLmNhbGwodGhpcylcblxuICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgIFtkaW1lbnNpb25dKDApXG4gICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCAkLnByb3h5KGNvbXBsZXRlLCB0aGlzKSlcbiAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChDb2xsYXBzZS5UUkFOU0lUSU9OX0RVUkFUSU9OKVxuICB9XG5cbiAgQ29sbGFwc2UucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzW3RoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2luJykgPyAnaGlkZScgOiAnc2hvdyddKClcbiAgfVxuXG4gIENvbGxhcHNlLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICQodGhpcy5vcHRpb25zLnBhcmVudClcbiAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXVtkYXRhLXBhcmVudD1cIicgKyB0aGlzLm9wdGlvbnMucGFyZW50ICsgJ1wiXScpXG4gICAgICAuZWFjaCgkLnByb3h5KGZ1bmN0aW9uIChpLCBlbGVtZW50KSB7XG4gICAgICAgIHZhciAkZWxlbWVudCA9ICQoZWxlbWVudClcbiAgICAgICAgdGhpcy5hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoZ2V0VGFyZ2V0RnJvbVRyaWdnZXIoJGVsZW1lbnQpLCAkZWxlbWVudClcbiAgICAgIH0sIHRoaXMpKVxuICAgICAgLmVuZCgpXG4gIH1cblxuICBDb2xsYXBzZS5wcm90b3R5cGUuYWRkQXJpYUFuZENvbGxhcHNlZENsYXNzID0gZnVuY3Rpb24gKCRlbGVtZW50LCAkdHJpZ2dlcikge1xuICAgIHZhciBpc09wZW4gPSAkZWxlbWVudC5oYXNDbGFzcygnaW4nKVxuXG4gICAgJGVsZW1lbnQuYXR0cignYXJpYS1leHBhbmRlZCcsIGlzT3BlbilcbiAgICAkdHJpZ2dlclxuICAgICAgLnRvZ2dsZUNsYXNzKCdjb2xsYXBzZWQnLCAhaXNPcGVuKVxuICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBpc09wZW4pXG4gIH1cblxuICBmdW5jdGlvbiBnZXRUYXJnZXRGcm9tVHJpZ2dlcigkdHJpZ2dlcikge1xuICAgIHZhciBocmVmXG4gICAgdmFyIHRhcmdldCA9ICR0cmlnZ2VyLmF0dHIoJ2RhdGEtdGFyZ2V0JylcbiAgICAgIHx8IChocmVmID0gJHRyaWdnZXIuYXR0cignaHJlZicpKSAmJiBocmVmLnJlcGxhY2UoLy4qKD89I1teXFxzXSskKS8sICcnKSAvLyBzdHJpcCBmb3IgaWU3XG5cbiAgICByZXR1cm4gJCh0YXJnZXQpXG4gIH1cblxuXG4gIC8vIENPTExBUFNFIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLmNvbGxhcHNlJylcbiAgICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe30sIENvbGxhcHNlLkRFRkFVTFRTLCAkdGhpcy5kYXRhKCksIHR5cGVvZiBvcHRpb24gPT0gJ29iamVjdCcgJiYgb3B0aW9uKVxuXG4gICAgICBpZiAoIWRhdGEgJiYgb3B0aW9ucy50b2dnbGUgJiYgL3Nob3d8aGlkZS8udGVzdChvcHRpb24pKSBvcHRpb25zLnRvZ2dsZSA9IGZhbHNlXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmNvbGxhcHNlJywgKGRhdGEgPSBuZXcgQ29sbGFwc2UodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmNvbGxhcHNlXG5cbiAgJC5mbi5jb2xsYXBzZSAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmNvbGxhcHNlLkNvbnN0cnVjdG9yID0gQ29sbGFwc2VcblxuXG4gIC8vIENPTExBUFNFIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5jb2xsYXBzZS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uY29sbGFwc2UgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBDT0xMQVBTRSBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5jb2xsYXBzZS5kYXRhLWFwaScsICdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG5cbiAgICBpZiAoISR0aGlzLmF0dHIoJ2RhdGEtdGFyZ2V0JykpIGUucHJldmVudERlZmF1bHQoKVxuXG4gICAgdmFyICR0YXJnZXQgPSBnZXRUYXJnZXRGcm9tVHJpZ2dlcigkdGhpcylcbiAgICB2YXIgZGF0YSAgICA9ICR0YXJnZXQuZGF0YSgnYnMuY29sbGFwc2UnKVxuICAgIHZhciBvcHRpb24gID0gZGF0YSA/ICd0b2dnbGUnIDogJHRoaXMuZGF0YSgpXG5cbiAgICBQbHVnaW4uY2FsbCgkdGFyZ2V0LCBvcHRpb24pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9jb2xsYXBzZS5qc1xuLy8gbW9kdWxlIGlkID0gN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEJvb3RzdHJhcDogZHJvcGRvd24uanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNkcm9wZG93bnNcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weXJpZ2h0IDIwMTEtMjAxNiBUd2l0dGVyLCBJbmMuXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cblxuK2Z1bmN0aW9uICgkKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvLyBEUk9QRE9XTiBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgYmFja2Ryb3AgPSAnLmRyb3Bkb3duLWJhY2tkcm9wJ1xuICB2YXIgdG9nZ2xlICAgPSAnW2RhdGEtdG9nZ2xlPVwiZHJvcGRvd25cIl0nXG4gIHZhciBEcm9wZG93biA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgJChlbGVtZW50KS5vbignY2xpY2suYnMuZHJvcGRvd24nLCB0aGlzLnRvZ2dsZSlcbiAgfVxuXG4gIERyb3Bkb3duLlZFUlNJT04gPSAnMy4zLjcnXG5cbiAgZnVuY3Rpb24gZ2V0UGFyZW50KCR0aGlzKSB7XG4gICAgdmFyIHNlbGVjdG9yID0gJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKVxuXG4gICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgc2VsZWN0b3IgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICAgIHNlbGVjdG9yID0gc2VsZWN0b3IgJiYgLyNbQS1aYS16XS8udGVzdChzZWxlY3RvcikgJiYgc2VsZWN0b3IucmVwbGFjZSgvLiooPz0jW15cXHNdKiQpLywgJycpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB9XG5cbiAgICB2YXIgJHBhcmVudCA9IHNlbGVjdG9yICYmICQoc2VsZWN0b3IpXG5cbiAgICByZXR1cm4gJHBhcmVudCAmJiAkcGFyZW50Lmxlbmd0aCA/ICRwYXJlbnQgOiAkdGhpcy5wYXJlbnQoKVxuICB9XG5cbiAgZnVuY3Rpb24gY2xlYXJNZW51cyhlKSB7XG4gICAgaWYgKGUgJiYgZS53aGljaCA9PT0gMykgcmV0dXJuXG4gICAgJChiYWNrZHJvcCkucmVtb3ZlKClcbiAgICAkKHRvZ2dsZSkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICAgICAgICA9ICQodGhpcylcbiAgICAgIHZhciAkcGFyZW50ICAgICAgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgICAgdmFyIHJlbGF0ZWRUYXJnZXQgPSB7IHJlbGF0ZWRUYXJnZXQ6IHRoaXMgfVxuXG4gICAgICBpZiAoISRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKSkgcmV0dXJuXG5cbiAgICAgIGlmIChlICYmIGUudHlwZSA9PSAnY2xpY2snICYmIC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZS50YXJnZXQudGFnTmFtZSkgJiYgJC5jb250YWlucygkcGFyZW50WzBdLCBlLnRhcmdldCkpIHJldHVyblxuXG4gICAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ2hpZGUuYnMuZHJvcGRvd24nLCByZWxhdGVkVGFyZ2V0KSlcblxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgICAkdGhpcy5hdHRyKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJylcbiAgICAgICRwYXJlbnQucmVtb3ZlQ2xhc3MoJ29wZW4nKS50cmlnZ2VyKCQuRXZlbnQoJ2hpZGRlbi5icy5kcm9wZG93bicsIHJlbGF0ZWRUYXJnZXQpKVxuICAgIH0pXG4gIH1cblxuICBEcm9wZG93bi5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG5cbiAgICBpZiAoJHRoaXMuaXMoJy5kaXNhYmxlZCwgOmRpc2FibGVkJykpIHJldHVyblxuXG4gICAgdmFyICRwYXJlbnQgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgIHZhciBpc0FjdGl2ZSA9ICRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKVxuXG4gICAgY2xlYXJNZW51cygpXG5cbiAgICBpZiAoIWlzQWN0aXZlKSB7XG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmICEkcGFyZW50LmNsb3Nlc3QoJy5uYXZiYXItbmF2JykubGVuZ3RoKSB7XG4gICAgICAgIC8vIGlmIG1vYmlsZSB3ZSB1c2UgYSBiYWNrZHJvcCBiZWNhdXNlIGNsaWNrIGV2ZW50cyBkb24ndCBkZWxlZ2F0ZVxuICAgICAgICAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKVxuICAgICAgICAgIC5hZGRDbGFzcygnZHJvcGRvd24tYmFja2Ryb3AnKVxuICAgICAgICAgIC5pbnNlcnRBZnRlcigkKHRoaXMpKVxuICAgICAgICAgIC5vbignY2xpY2snLCBjbGVhck1lbnVzKVxuICAgICAgfVxuXG4gICAgICB2YXIgcmVsYXRlZFRhcmdldCA9IHsgcmVsYXRlZFRhcmdldDogdGhpcyB9XG4gICAgICAkcGFyZW50LnRyaWdnZXIoZSA9ICQuRXZlbnQoJ3Nob3cuYnMuZHJvcGRvd24nLCByZWxhdGVkVGFyZ2V0KSlcblxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgICAkdGhpc1xuICAgICAgICAudHJpZ2dlcignZm9jdXMnKVxuICAgICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsICd0cnVlJylcblxuICAgICAgJHBhcmVudFxuICAgICAgICAudG9nZ2xlQ2xhc3MoJ29wZW4nKVxuICAgICAgICAudHJpZ2dlcigkLkV2ZW50KCdzaG93bi5icy5kcm9wZG93bicsIHJlbGF0ZWRUYXJnZXQpKVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgRHJvcGRvd24ucHJvdG90eXBlLmtleWRvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmICghLygzOHw0MHwyN3wzMikvLnRlc3QoZS53aGljaCkgfHwgL2lucHV0fHRleHRhcmVhL2kudGVzdChlLnRhcmdldC50YWdOYW1lKSkgcmV0dXJuXG5cbiAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG5cbiAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpXG5cbiAgICBpZiAoJHRoaXMuaXMoJy5kaXNhYmxlZCwgOmRpc2FibGVkJykpIHJldHVyblxuXG4gICAgdmFyICRwYXJlbnQgID0gZ2V0UGFyZW50KCR0aGlzKVxuICAgIHZhciBpc0FjdGl2ZSA9ICRwYXJlbnQuaGFzQ2xhc3MoJ29wZW4nKVxuXG4gICAgaWYgKCFpc0FjdGl2ZSAmJiBlLndoaWNoICE9IDI3IHx8IGlzQWN0aXZlICYmIGUud2hpY2ggPT0gMjcpIHtcbiAgICAgIGlmIChlLndoaWNoID09IDI3KSAkcGFyZW50LmZpbmQodG9nZ2xlKS50cmlnZ2VyKCdmb2N1cycpXG4gICAgICByZXR1cm4gJHRoaXMudHJpZ2dlcignY2xpY2snKVxuICAgIH1cblxuICAgIHZhciBkZXNjID0gJyBsaTpub3QoLmRpc2FibGVkKTp2aXNpYmxlIGEnXG4gICAgdmFyICRpdGVtcyA9ICRwYXJlbnQuZmluZCgnLmRyb3Bkb3duLW1lbnUnICsgZGVzYylcblxuICAgIGlmICghJGl0ZW1zLmxlbmd0aCkgcmV0dXJuXG5cbiAgICB2YXIgaW5kZXggPSAkaXRlbXMuaW5kZXgoZS50YXJnZXQpXG5cbiAgICBpZiAoZS53aGljaCA9PSAzOCAmJiBpbmRleCA+IDApICAgICAgICAgICAgICAgICBpbmRleC0tICAgICAgICAgLy8gdXBcbiAgICBpZiAoZS53aGljaCA9PSA0MCAmJiBpbmRleCA8ICRpdGVtcy5sZW5ndGggLSAxKSBpbmRleCsrICAgICAgICAgLy8gZG93blxuICAgIGlmICghfmluZGV4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gMFxuXG4gICAgJGl0ZW1zLmVxKGluZGV4KS50cmlnZ2VyKCdmb2N1cycpXG4gIH1cblxuXG4gIC8vIERST1BET1dOIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgdmFyIGRhdGEgID0gJHRoaXMuZGF0YSgnYnMuZHJvcGRvd24nKVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmRyb3Bkb3duJywgKGRhdGEgPSBuZXcgRHJvcGRvd24odGhpcykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXS5jYWxsKCR0aGlzKVxuICAgIH0pXG4gIH1cblxuICB2YXIgb2xkID0gJC5mbi5kcm9wZG93blxuXG4gICQuZm4uZHJvcGRvd24gICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5kcm9wZG93bi5Db25zdHJ1Y3RvciA9IERyb3Bkb3duXG5cblxuICAvLyBEUk9QRE9XTiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PVxuXG4gICQuZm4uZHJvcGRvd24ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkLmZuLmRyb3Bkb3duID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gQVBQTFkgVE8gU1RBTkRBUkQgRFJPUERPV04gRUxFTUVOVFNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAkKGRvY3VtZW50KVxuICAgIC5vbignY2xpY2suYnMuZHJvcGRvd24uZGF0YS1hcGknLCBjbGVhck1lbnVzKVxuICAgIC5vbignY2xpY2suYnMuZHJvcGRvd24uZGF0YS1hcGknLCAnLmRyb3Bkb3duIGZvcm0nLCBmdW5jdGlvbiAoZSkgeyBlLnN0b3BQcm9wYWdhdGlvbigpIH0pXG4gICAgLm9uKCdjbGljay5icy5kcm9wZG93bi5kYXRhLWFwaScsIHRvZ2dsZSwgRHJvcGRvd24ucHJvdG90eXBlLnRvZ2dsZSlcbiAgICAub24oJ2tleWRvd24uYnMuZHJvcGRvd24uZGF0YS1hcGknLCB0b2dnbGUsIERyb3Bkb3duLnByb3RvdHlwZS5rZXlkb3duKVxuICAgIC5vbigna2V5ZG93bi5icy5kcm9wZG93bi5kYXRhLWFwaScsICcuZHJvcGRvd24tbWVudScsIERyb3Bkb3duLnByb3RvdHlwZS5rZXlkb3duKVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvZHJvcGRvd24uanNcbi8vIG1vZHVsZSBpZCA9IDhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IG1vZGFsLmpzIHYzLjMuN1xuICogaHR0cDovL2dldGJvb3RzdHJhcC5jb20vamF2YXNjcmlwdC8jbW9kYWxzXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gTU9EQUwgQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIE1vZGFsID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgICAgICAgICAgICAgPSBvcHRpb25zXG4gICAgdGhpcy4kYm9keSAgICAgICAgICAgICAgID0gJChkb2N1bWVudC5ib2R5KVxuICAgIHRoaXMuJGVsZW1lbnQgICAgICAgICAgICA9ICQoZWxlbWVudClcbiAgICB0aGlzLiRkaWFsb2cgICAgICAgICAgICAgPSB0aGlzLiRlbGVtZW50LmZpbmQoJy5tb2RhbC1kaWFsb2cnKVxuICAgIHRoaXMuJGJhY2tkcm9wICAgICAgICAgICA9IG51bGxcbiAgICB0aGlzLmlzU2hvd24gICAgICAgICAgICAgPSBudWxsXG4gICAgdGhpcy5vcmlnaW5hbEJvZHlQYWQgICAgID0gbnVsbFxuICAgIHRoaXMuc2Nyb2xsYmFyV2lkdGggICAgICA9IDBcbiAgICB0aGlzLmlnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5yZW1vdGUpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLmZpbmQoJy5tb2RhbC1jb250ZW50JylcbiAgICAgICAgLmxvYWQodGhpcy5vcHRpb25zLnJlbW90ZSwgJC5wcm94eShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdsb2FkZWQuYnMubW9kYWwnKVxuICAgICAgICB9LCB0aGlzKSlcbiAgICB9XG4gIH1cblxuICBNb2RhbC5WRVJTSU9OICA9ICczLjMuNydcblxuICBNb2RhbC5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMzAwXG4gIE1vZGFsLkJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04gPSAxNTBcblxuICBNb2RhbC5ERUZBVUxUUyA9IHtcbiAgICBiYWNrZHJvcDogdHJ1ZSxcbiAgICBrZXlib2FyZDogdHJ1ZSxcbiAgICBzaG93OiB0cnVlXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gKF9yZWxhdGVkVGFyZ2V0KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNTaG93biA/IHRoaXMuaGlkZSgpIDogdGhpcy5zaG93KF9yZWxhdGVkVGFyZ2V0KVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoX3JlbGF0ZWRUYXJnZXQpIHtcbiAgICB2YXIgdGhhdCA9IHRoaXNcbiAgICB2YXIgZSAgICA9ICQuRXZlbnQoJ3Nob3cuYnMubW9kYWwnLCB7IHJlbGF0ZWRUYXJnZXQ6IF9yZWxhdGVkVGFyZ2V0IH0pXG5cbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgIGlmICh0aGlzLmlzU2hvd24gfHwgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLmlzU2hvd24gPSB0cnVlXG5cbiAgICB0aGlzLmNoZWNrU2Nyb2xsYmFyKClcbiAgICB0aGlzLnNldFNjcm9sbGJhcigpXG4gICAgdGhpcy4kYm9keS5hZGRDbGFzcygnbW9kYWwtb3BlbicpXG5cbiAgICB0aGlzLmVzY2FwZSgpXG4gICAgdGhpcy5yZXNpemUoKVxuXG4gICAgdGhpcy4kZWxlbWVudC5vbignY2xpY2suZGlzbWlzcy5icy5tb2RhbCcsICdbZGF0YS1kaXNtaXNzPVwibW9kYWxcIl0nLCAkLnByb3h5KHRoaXMuaGlkZSwgdGhpcykpXG5cbiAgICB0aGlzLiRkaWFsb2cub24oJ21vdXNlZG93bi5kaXNtaXNzLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgdGhhdC4kZWxlbWVudC5vbmUoJ21vdXNldXAuZGlzbWlzcy5icy5tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICgkKGUudGFyZ2V0KS5pcyh0aGF0LiRlbGVtZW50KSkgdGhhdC5pZ25vcmVCYWNrZHJvcENsaWNrID0gdHJ1ZVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgdGhpcy5iYWNrZHJvcChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvbiA9ICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoYXQuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKVxuXG4gICAgICBpZiAoIXRoYXQuJGVsZW1lbnQucGFyZW50KCkubGVuZ3RoKSB7XG4gICAgICAgIHRoYXQuJGVsZW1lbnQuYXBwZW5kVG8odGhhdC4kYm9keSkgLy8gZG9uJ3QgbW92ZSBtb2RhbHMgZG9tIHBvc2l0aW9uXG4gICAgICB9XG5cbiAgICAgIHRoYXQuJGVsZW1lbnRcbiAgICAgICAgLnNob3coKVxuICAgICAgICAuc2Nyb2xsVG9wKDApXG5cbiAgICAgIHRoYXQuYWRqdXN0RGlhbG9nKClcblxuICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgdGhhdC4kZWxlbWVudFswXS5vZmZzZXRXaWR0aCAvLyBmb3JjZSByZWZsb3dcbiAgICAgIH1cblxuICAgICAgdGhhdC4kZWxlbWVudC5hZGRDbGFzcygnaW4nKVxuXG4gICAgICB0aGF0LmVuZm9yY2VGb2N1cygpXG5cbiAgICAgIHZhciBlID0gJC5FdmVudCgnc2hvd24uYnMubW9kYWwnLCB7IHJlbGF0ZWRUYXJnZXQ6IF9yZWxhdGVkVGFyZ2V0IH0pXG5cbiAgICAgIHRyYW5zaXRpb24gP1xuICAgICAgICB0aGF0LiRkaWFsb2cgLy8gd2FpdCBmb3IgbW9kYWwgdG8gc2xpZGUgaW5cbiAgICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2ZvY3VzJykudHJpZ2dlcihlKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKE1vZGFsLlRSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdmb2N1cycpLnRyaWdnZXIoZSlcbiAgICB9KVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmIChlKSBlLnByZXZlbnREZWZhdWx0KClcblxuICAgIGUgPSAkLkV2ZW50KCdoaWRlLmJzLm1vZGFsJylcblxuICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcihlKVxuXG4gICAgaWYgKCF0aGlzLmlzU2hvd24gfHwgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkgcmV0dXJuXG5cbiAgICB0aGlzLmlzU2hvd24gPSBmYWxzZVxuXG4gICAgdGhpcy5lc2NhcGUoKVxuICAgIHRoaXMucmVzaXplKClcblxuICAgICQoZG9jdW1lbnQpLm9mZignZm9jdXNpbi5icy5tb2RhbCcpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQ2xhc3MoJ2luJylcbiAgICAgIC5vZmYoJ2NsaWNrLmRpc21pc3MuYnMubW9kYWwnKVxuICAgICAgLm9mZignbW91c2V1cC5kaXNtaXNzLmJzLm1vZGFsJylcblxuICAgIHRoaXMuJGRpYWxvZy5vZmYoJ21vdXNlZG93bi5kaXNtaXNzLmJzLm1vZGFsJylcblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICB0aGlzLiRlbGVtZW50XG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsICQucHJveHkodGhpcy5oaWRlTW9kYWwsIHRoaXMpKVxuICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoTW9kYWwuVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgdGhpcy5oaWRlTW9kYWwoKVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLmVuZm9yY2VGb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKGRvY3VtZW50KVxuICAgICAgLm9mZignZm9jdXNpbi5icy5tb2RhbCcpIC8vIGd1YXJkIGFnYWluc3QgaW5maW5pdGUgZm9jdXMgbG9vcFxuICAgICAgLm9uKCdmb2N1c2luLmJzLm1vZGFsJywgJC5wcm94eShmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZG9jdW1lbnQgIT09IGUudGFyZ2V0ICYmXG4gICAgICAgICAgICB0aGlzLiRlbGVtZW50WzBdICE9PSBlLnRhcmdldCAmJlxuICAgICAgICAgICAgIXRoaXMuJGVsZW1lbnQuaGFzKGUudGFyZ2V0KS5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2ZvY3VzJylcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcykpXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUuZXNjYXBlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmlzU2hvd24gJiYgdGhpcy5vcHRpb25zLmtleWJvYXJkKSB7XG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdrZXlkb3duLmRpc21pc3MuYnMubW9kYWwnLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUud2hpY2ggPT0gMjcgJiYgdGhpcy5oaWRlKClcbiAgICAgIH0sIHRoaXMpKVxuICAgIH0gZWxzZSBpZiAoIXRoaXMuaXNTaG93bikge1xuICAgICAgdGhpcy4kZWxlbWVudC5vZmYoJ2tleWRvd24uZGlzbWlzcy5icy5tb2RhbCcpXG4gICAgfVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pc1Nob3duKSB7XG4gICAgICAkKHdpbmRvdykub24oJ3Jlc2l6ZS5icy5tb2RhbCcsICQucHJveHkodGhpcy5oYW5kbGVVcGRhdGUsIHRoaXMpKVxuICAgIH0gZWxzZSB7XG4gICAgICAkKHdpbmRvdykub2ZmKCdyZXNpemUuYnMubW9kYWwnKVxuICAgIH1cbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5oaWRlTW9kYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRoYXQgPSB0aGlzXG4gICAgdGhpcy4kZWxlbWVudC5oaWRlKClcbiAgICB0aGlzLmJhY2tkcm9wKGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoYXQuJGJvZHkucmVtb3ZlQ2xhc3MoJ21vZGFsLW9wZW4nKVxuICAgICAgdGhhdC5yZXNldEFkanVzdG1lbnRzKClcbiAgICAgIHRoYXQucmVzZXRTY3JvbGxiYXIoKVxuICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdoaWRkZW4uYnMubW9kYWwnKVxuICAgIH0pXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUucmVtb3ZlQmFja2Ryb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy4kYmFja2Ryb3AgJiYgdGhpcy4kYmFja2Ryb3AucmVtb3ZlKClcbiAgICB0aGlzLiRiYWNrZHJvcCA9IG51bGxcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5iYWNrZHJvcCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHZhciB0aGF0ID0gdGhpc1xuICAgIHZhciBhbmltYXRlID0gdGhpcy4kZWxlbWVudC5oYXNDbGFzcygnZmFkZScpID8gJ2ZhZGUnIDogJydcblxuICAgIGlmICh0aGlzLmlzU2hvd24gJiYgdGhpcy5vcHRpb25zLmJhY2tkcm9wKSB7XG4gICAgICB2YXIgZG9BbmltYXRlID0gJC5zdXBwb3J0LnRyYW5zaXRpb24gJiYgYW5pbWF0ZVxuXG4gICAgICB0aGlzLiRiYWNrZHJvcCA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpXG4gICAgICAgIC5hZGRDbGFzcygnbW9kYWwtYmFja2Ryb3AgJyArIGFuaW1hdGUpXG4gICAgICAgIC5hcHBlbmRUbyh0aGlzLiRib2R5KVxuXG4gICAgICB0aGlzLiRlbGVtZW50Lm9uKCdjbGljay5kaXNtaXNzLmJzLm1vZGFsJywgJC5wcm94eShmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5pZ25vcmVCYWNrZHJvcENsaWNrKSB7XG4gICAgICAgICAgdGhpcy5pZ25vcmVCYWNrZHJvcENsaWNrID0gZmFsc2VcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBpZiAoZS50YXJnZXQgIT09IGUuY3VycmVudFRhcmdldCkgcmV0dXJuXG4gICAgICAgIHRoaXMub3B0aW9ucy5iYWNrZHJvcCA9PSAnc3RhdGljJ1xuICAgICAgICAgID8gdGhpcy4kZWxlbWVudFswXS5mb2N1cygpXG4gICAgICAgICAgOiB0aGlzLmhpZGUoKVxuICAgICAgfSwgdGhpcykpXG5cbiAgICAgIGlmIChkb0FuaW1hdGUpIHRoaXMuJGJhY2tkcm9wWzBdLm9mZnNldFdpZHRoIC8vIGZvcmNlIHJlZmxvd1xuXG4gICAgICB0aGlzLiRiYWNrZHJvcC5hZGRDbGFzcygnaW4nKVxuXG4gICAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm5cblxuICAgICAgZG9BbmltYXRlID9cbiAgICAgICAgdGhpcy4kYmFja2Ryb3BcbiAgICAgICAgICAub25lKCdic1RyYW5zaXRpb25FbmQnLCBjYWxsYmFjaylcbiAgICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoTW9kYWwuQkFDS0RST1BfVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgICBjYWxsYmFjaygpXG5cbiAgICB9IGVsc2UgaWYgKCF0aGlzLmlzU2hvd24gJiYgdGhpcy4kYmFja2Ryb3ApIHtcbiAgICAgIHRoaXMuJGJhY2tkcm9wLnJlbW92ZUNsYXNzKCdpbicpXG5cbiAgICAgIHZhciBjYWxsYmFja1JlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5yZW1vdmVCYWNrZHJvcCgpXG4gICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKClcbiAgICAgIH1cbiAgICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJGVsZW1lbnQuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAgIHRoaXMuJGJhY2tkcm9wXG4gICAgICAgICAgLm9uZSgnYnNUcmFuc2l0aW9uRW5kJywgY2FsbGJhY2tSZW1vdmUpXG4gICAgICAgICAgLmVtdWxhdGVUcmFuc2l0aW9uRW5kKE1vZGFsLkJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgY2FsbGJhY2tSZW1vdmUoKVxuXG4gICAgfSBlbHNlIGlmIChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2soKVxuICAgIH1cbiAgfVxuXG4gIC8vIHRoZXNlIGZvbGxvd2luZyBtZXRob2RzIGFyZSB1c2VkIHRvIGhhbmRsZSBvdmVyZmxvd2luZyBtb2RhbHNcblxuICBNb2RhbC5wcm90b3R5cGUuaGFuZGxlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYWRqdXN0RGlhbG9nKClcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5hZGp1c3REaWFsb2cgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG1vZGFsSXNPdmVyZmxvd2luZyA9IHRoaXMuJGVsZW1lbnRbMF0uc2Nyb2xsSGVpZ2h0ID4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodFxuXG4gICAgdGhpcy4kZWxlbWVudC5jc3Moe1xuICAgICAgcGFkZGluZ0xlZnQ6ICAhdGhpcy5ib2R5SXNPdmVyZmxvd2luZyAmJiBtb2RhbElzT3ZlcmZsb3dpbmcgPyB0aGlzLnNjcm9sbGJhcldpZHRoIDogJycsXG4gICAgICBwYWRkaW5nUmlnaHQ6IHRoaXMuYm9keUlzT3ZlcmZsb3dpbmcgJiYgIW1vZGFsSXNPdmVyZmxvd2luZyA/IHRoaXMuc2Nyb2xsYmFyV2lkdGggOiAnJ1xuICAgIH0pXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUucmVzZXRBZGp1c3RtZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRlbGVtZW50LmNzcyh7XG4gICAgICBwYWRkaW5nTGVmdDogJycsXG4gICAgICBwYWRkaW5nUmlnaHQ6ICcnXG4gICAgfSlcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5jaGVja1Njcm9sbGJhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZnVsbFdpbmRvd1dpZHRoID0gd2luZG93LmlubmVyV2lkdGhcbiAgICBpZiAoIWZ1bGxXaW5kb3dXaWR0aCkgeyAvLyB3b3JrYXJvdW5kIGZvciBtaXNzaW5nIHdpbmRvdy5pbm5lcldpZHRoIGluIElFOFxuICAgICAgdmFyIGRvY3VtZW50RWxlbWVudFJlY3QgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICAgIGZ1bGxXaW5kb3dXaWR0aCA9IGRvY3VtZW50RWxlbWVudFJlY3QucmlnaHQgLSBNYXRoLmFicyhkb2N1bWVudEVsZW1lbnRSZWN0LmxlZnQpXG4gICAgfVxuICAgIHRoaXMuYm9keUlzT3ZlcmZsb3dpbmcgPSBkb2N1bWVudC5ib2R5LmNsaWVudFdpZHRoIDwgZnVsbFdpbmRvd1dpZHRoXG4gICAgdGhpcy5zY3JvbGxiYXJXaWR0aCA9IHRoaXMubWVhc3VyZVNjcm9sbGJhcigpXG4gIH1cblxuICBNb2RhbC5wcm90b3R5cGUuc2V0U2Nyb2xsYmFyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBib2R5UGFkID0gcGFyc2VJbnQoKHRoaXMuJGJvZHkuY3NzKCdwYWRkaW5nLXJpZ2h0JykgfHwgMCksIDEwKVxuICAgIHRoaXMub3JpZ2luYWxCb2R5UGFkID0gZG9jdW1lbnQuYm9keS5zdHlsZS5wYWRkaW5nUmlnaHQgfHwgJydcbiAgICBpZiAodGhpcy5ib2R5SXNPdmVyZmxvd2luZykgdGhpcy4kYm9keS5jc3MoJ3BhZGRpbmctcmlnaHQnLCBib2R5UGFkICsgdGhpcy5zY3JvbGxiYXJXaWR0aClcbiAgfVxuXG4gIE1vZGFsLnByb3RvdHlwZS5yZXNldFNjcm9sbGJhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRib2R5LmNzcygncGFkZGluZy1yaWdodCcsIHRoaXMub3JpZ2luYWxCb2R5UGFkKVxuICB9XG5cbiAgTW9kYWwucHJvdG90eXBlLm1lYXN1cmVTY3JvbGxiYXIgPSBmdW5jdGlvbiAoKSB7IC8vIHRoeCB3YWxzaFxuICAgIHZhciBzY3JvbGxEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHNjcm9sbERpdi5jbGFzc05hbWUgPSAnbW9kYWwtc2Nyb2xsYmFyLW1lYXN1cmUnXG4gICAgdGhpcy4kYm9keS5hcHBlbmQoc2Nyb2xsRGl2KVxuICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHNjcm9sbERpdi5vZmZzZXRXaWR0aCAtIHNjcm9sbERpdi5jbGllbnRXaWR0aFxuICAgIHRoaXMuJGJvZHlbMF0ucmVtb3ZlQ2hpbGQoc2Nyb2xsRGl2KVxuICAgIHJldHVybiBzY3JvbGxiYXJXaWR0aFxuICB9XG5cblxuICAvLyBNT0RBTCBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIFBsdWdpbihvcHRpb24sIF9yZWxhdGVkVGFyZ2V0KSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICAgIHZhciBkYXRhICAgID0gJHRoaXMuZGF0YSgnYnMubW9kYWwnKVxuICAgICAgdmFyIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgTW9kYWwuREVGQVVMVFMsICR0aGlzLmRhdGEoKSwgdHlwZW9mIG9wdGlvbiA9PSAnb2JqZWN0JyAmJiBvcHRpb24pXG5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMubW9kYWwnLCAoZGF0YSA9IG5ldyBNb2RhbCh0aGlzLCBvcHRpb25zKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKF9yZWxhdGVkVGFyZ2V0KVxuICAgICAgZWxzZSBpZiAob3B0aW9ucy5zaG93KSBkYXRhLnNob3coX3JlbGF0ZWRUYXJnZXQpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLm1vZGFsXG5cbiAgJC5mbi5tb2RhbCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLm1vZGFsLkNvbnN0cnVjdG9yID0gTW9kYWxcblxuXG4gIC8vIE1PREFMIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5tb2RhbC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4ubW9kYWwgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBNT0RBTCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQoZG9jdW1lbnQpLm9uKCdjbGljay5icy5tb2RhbC5kYXRhLWFwaScsICdbZGF0YS10b2dnbGU9XCJtb2RhbFwiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgdmFyIGhyZWYgICAgPSAkdGhpcy5hdHRyKCdocmVmJylcbiAgICB2YXIgJHRhcmdldCA9ICQoJHRoaXMuYXR0cignZGF0YS10YXJnZXQnKSB8fCAoaHJlZiAmJiBocmVmLnJlcGxhY2UoLy4qKD89I1teXFxzXSskKS8sICcnKSkpIC8vIHN0cmlwIGZvciBpZTdcbiAgICB2YXIgb3B0aW9uICA9ICR0YXJnZXQuZGF0YSgnYnMubW9kYWwnKSA/ICd0b2dnbGUnIDogJC5leHRlbmQoeyByZW1vdGU6ICEvIy8udGVzdChocmVmKSAmJiBocmVmIH0sICR0YXJnZXQuZGF0YSgpLCAkdGhpcy5kYXRhKCkpXG5cbiAgICBpZiAoJHRoaXMuaXMoJ2EnKSkgZS5wcmV2ZW50RGVmYXVsdCgpXG5cbiAgICAkdGFyZ2V0Lm9uZSgnc2hvdy5icy5tb2RhbCcsIGZ1bmN0aW9uIChzaG93RXZlbnQpIHtcbiAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVybiAvLyBvbmx5IHJlZ2lzdGVyIGZvY3VzIHJlc3RvcmVyIGlmIG1vZGFsIHdpbGwgYWN0dWFsbHkgZ2V0IHNob3duXG4gICAgICAkdGFyZ2V0Lm9uZSgnaGlkZGVuLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAkdGhpcy5pcygnOnZpc2libGUnKSAmJiAkdGhpcy50cmlnZ2VyKCdmb2N1cycpXG4gICAgICB9KVxuICAgIH0pXG4gICAgUGx1Z2luLmNhbGwoJHRhcmdldCwgb3B0aW9uLCB0aGlzKVxuICB9KVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvbW9kYWwuanNcbi8vIG1vZHVsZSBpZCA9IDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHRvb2x0aXAuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyN0b29sdGlwXG4gKiBJbnNwaXJlZCBieSB0aGUgb3JpZ2luYWwgalF1ZXJ5LnRpcHN5IGJ5IEphc29uIEZyYW1lXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVE9PTFRJUCBQVUJMSUMgQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIFRvb2x0aXAgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMudHlwZSAgICAgICA9IG51bGxcbiAgICB0aGlzLm9wdGlvbnMgICAgPSBudWxsXG4gICAgdGhpcy5lbmFibGVkICAgID0gbnVsbFxuICAgIHRoaXMudGltZW91dCAgICA9IG51bGxcbiAgICB0aGlzLmhvdmVyU3RhdGUgPSBudWxsXG4gICAgdGhpcy4kZWxlbWVudCAgID0gbnVsbFxuICAgIHRoaXMuaW5TdGF0ZSAgICA9IG51bGxcblxuICAgIHRoaXMuaW5pdCgndG9vbHRpcCcsIGVsZW1lbnQsIG9wdGlvbnMpXG4gIH1cblxuICBUb29sdGlwLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFRvb2x0aXAuVFJBTlNJVElPTl9EVVJBVElPTiA9IDE1MFxuXG4gIFRvb2x0aXAuREVGQVVMVFMgPSB7XG4gICAgYW5pbWF0aW9uOiB0cnVlLFxuICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgc2VsZWN0b3I6IGZhbHNlLFxuICAgIHRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRvb2x0aXBcIiByb2xlPVwidG9vbHRpcFwiPjxkaXYgY2xhc3M9XCJ0b29sdGlwLWFycm93XCI+PC9kaXY+PGRpdiBjbGFzcz1cInRvb2x0aXAtaW5uZXJcIj48L2Rpdj48L2Rpdj4nLFxuICAgIHRyaWdnZXI6ICdob3ZlciBmb2N1cycsXG4gICAgdGl0bGU6ICcnLFxuICAgIGRlbGF5OiAwLFxuICAgIGh0bWw6IGZhbHNlLFxuICAgIGNvbnRhaW5lcjogZmFsc2UsXG4gICAgdmlld3BvcnQ6IHtcbiAgICAgIHNlbGVjdG9yOiAnYm9keScsXG4gICAgICBwYWRkaW5nOiAwXG4gICAgfVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICh0eXBlLCBlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy5lbmFibGVkICAgPSB0cnVlXG4gICAgdGhpcy50eXBlICAgICAgPSB0eXBlXG4gICAgdGhpcy4kZWxlbWVudCAgPSAkKGVsZW1lbnQpXG4gICAgdGhpcy5vcHRpb25zICAgPSB0aGlzLmdldE9wdGlvbnMob3B0aW9ucylcbiAgICB0aGlzLiR2aWV3cG9ydCA9IHRoaXMub3B0aW9ucy52aWV3cG9ydCAmJiAkKCQuaXNGdW5jdGlvbih0aGlzLm9wdGlvbnMudmlld3BvcnQpID8gdGhpcy5vcHRpb25zLnZpZXdwb3J0LmNhbGwodGhpcywgdGhpcy4kZWxlbWVudCkgOiAodGhpcy5vcHRpb25zLnZpZXdwb3J0LnNlbGVjdG9yIHx8IHRoaXMub3B0aW9ucy52aWV3cG9ydCkpXG4gICAgdGhpcy5pblN0YXRlICAgPSB7IGNsaWNrOiBmYWxzZSwgaG92ZXI6IGZhbHNlLCBmb2N1czogZmFsc2UgfVxuXG4gICAgaWYgKHRoaXMuJGVsZW1lbnRbMF0gaW5zdGFuY2VvZiBkb2N1bWVudC5jb25zdHJ1Y3RvciAmJiAhdGhpcy5vcHRpb25zLnNlbGVjdG9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BzZWxlY3RvcmAgb3B0aW9uIG11c3QgYmUgc3BlY2lmaWVkIHdoZW4gaW5pdGlhbGl6aW5nICcgKyB0aGlzLnR5cGUgKyAnIG9uIHRoZSB3aW5kb3cuZG9jdW1lbnQgb2JqZWN0IScpXG4gICAgfVxuXG4gICAgdmFyIHRyaWdnZXJzID0gdGhpcy5vcHRpb25zLnRyaWdnZXIuc3BsaXQoJyAnKVxuXG4gICAgZm9yICh2YXIgaSA9IHRyaWdnZXJzLmxlbmd0aDsgaS0tOykge1xuICAgICAgdmFyIHRyaWdnZXIgPSB0cmlnZ2Vyc1tpXVxuXG4gICAgICBpZiAodHJpZ2dlciA9PSAnY2xpY2snKSB7XG4gICAgICAgIHRoaXMuJGVsZW1lbnQub24oJ2NsaWNrLicgKyB0aGlzLnR5cGUsIHRoaXMub3B0aW9ucy5zZWxlY3RvciwgJC5wcm94eSh0aGlzLnRvZ2dsZSwgdGhpcykpXG4gICAgICB9IGVsc2UgaWYgKHRyaWdnZXIgIT0gJ21hbnVhbCcpIHtcbiAgICAgICAgdmFyIGV2ZW50SW4gID0gdHJpZ2dlciA9PSAnaG92ZXInID8gJ21vdXNlZW50ZXInIDogJ2ZvY3VzaW4nXG4gICAgICAgIHZhciBldmVudE91dCA9IHRyaWdnZXIgPT0gJ2hvdmVyJyA/ICdtb3VzZWxlYXZlJyA6ICdmb2N1c291dCdcblxuICAgICAgICB0aGlzLiRlbGVtZW50Lm9uKGV2ZW50SW4gICsgJy4nICsgdGhpcy50eXBlLCB0aGlzLm9wdGlvbnMuc2VsZWN0b3IsICQucHJveHkodGhpcy5lbnRlciwgdGhpcykpXG4gICAgICAgIHRoaXMuJGVsZW1lbnQub24oZXZlbnRPdXQgKyAnLicgKyB0aGlzLnR5cGUsIHRoaXMub3B0aW9ucy5zZWxlY3RvciwgJC5wcm94eSh0aGlzLmxlYXZlLCB0aGlzKSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm9wdGlvbnMuc2VsZWN0b3IgP1xuICAgICAgKHRoaXMuX29wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zLCB7IHRyaWdnZXI6ICdtYW51YWwnLCBzZWxlY3RvcjogJycgfSkpIDpcbiAgICAgIHRoaXMuZml4VGl0bGUoKVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0RGVmYXVsdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFRvb2x0aXAuREVGQVVMVFNcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmdldE9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5nZXREZWZhdWx0cygpLCB0aGlzLiRlbGVtZW50LmRhdGEoKSwgb3B0aW9ucylcblxuICAgIGlmIChvcHRpb25zLmRlbGF5ICYmIHR5cGVvZiBvcHRpb25zLmRlbGF5ID09ICdudW1iZXInKSB7XG4gICAgICBvcHRpb25zLmRlbGF5ID0ge1xuICAgICAgICBzaG93OiBvcHRpb25zLmRlbGF5LFxuICAgICAgICBoaWRlOiBvcHRpb25zLmRlbGF5XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdGlvbnNcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmdldERlbGVnYXRlT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb3B0aW9ucyAgPSB7fVxuICAgIHZhciBkZWZhdWx0cyA9IHRoaXMuZ2V0RGVmYXVsdHMoKVxuXG4gICAgdGhpcy5fb3B0aW9ucyAmJiAkLmVhY2godGhpcy5fb3B0aW9ucywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgIGlmIChkZWZhdWx0c1trZXldICE9IHZhbHVlKSBvcHRpb25zW2tleV0gPSB2YWx1ZVxuICAgIH0pXG5cbiAgICByZXR1cm4gb3B0aW9uc1xuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZW50ZXIgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIHNlbGYgPSBvYmogaW5zdGFuY2VvZiB0aGlzLmNvbnN0cnVjdG9yID9cbiAgICAgIG9iaiA6ICQob2JqLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2JzLicgKyB0aGlzLnR5cGUpXG5cbiAgICBpZiAoIXNlbGYpIHtcbiAgICAgIHNlbGYgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihvYmouY3VycmVudFRhcmdldCwgdGhpcy5nZXREZWxlZ2F0ZU9wdGlvbnMoKSlcbiAgICAgICQob2JqLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2JzLicgKyB0aGlzLnR5cGUsIHNlbGYpXG4gICAgfVxuXG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mICQuRXZlbnQpIHtcbiAgICAgIHNlbGYuaW5TdGF0ZVtvYmoudHlwZSA9PSAnZm9jdXNpbicgPyAnZm9jdXMnIDogJ2hvdmVyJ10gPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHNlbGYudGlwKCkuaGFzQ2xhc3MoJ2luJykgfHwgc2VsZi5ob3ZlclN0YXRlID09ICdpbicpIHtcbiAgICAgIHNlbGYuaG92ZXJTdGF0ZSA9ICdpbidcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNsZWFyVGltZW91dChzZWxmLnRpbWVvdXQpXG5cbiAgICBzZWxmLmhvdmVyU3RhdGUgPSAnaW4nXG5cbiAgICBpZiAoIXNlbGYub3B0aW9ucy5kZWxheSB8fCAhc2VsZi5vcHRpb25zLmRlbGF5LnNob3cpIHJldHVybiBzZWxmLnNob3coKVxuXG4gICAgc2VsZi50aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoc2VsZi5ob3ZlclN0YXRlID09ICdpbicpIHNlbGYuc2hvdygpXG4gICAgfSwgc2VsZi5vcHRpb25zLmRlbGF5LnNob3cpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5pc0luU3RhdGVUcnVlID0gZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmluU3RhdGUpIHtcbiAgICAgIGlmICh0aGlzLmluU3RhdGVba2V5XSkgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmxlYXZlID0gZnVuY3Rpb24gKG9iaikge1xuICAgIHZhciBzZWxmID0gb2JqIGluc3RhbmNlb2YgdGhpcy5jb25zdHJ1Y3RvciA/XG4gICAgICBvYmogOiAkKG9iai5jdXJyZW50VGFyZ2V0KS5kYXRhKCdicy4nICsgdGhpcy50eXBlKVxuXG4gICAgaWYgKCFzZWxmKSB7XG4gICAgICBzZWxmID0gbmV3IHRoaXMuY29uc3RydWN0b3Iob2JqLmN1cnJlbnRUYXJnZXQsIHRoaXMuZ2V0RGVsZWdhdGVPcHRpb25zKCkpXG4gICAgICAkKG9iai5jdXJyZW50VGFyZ2V0KS5kYXRhKCdicy4nICsgdGhpcy50eXBlLCBzZWxmKVxuICAgIH1cblxuICAgIGlmIChvYmogaW5zdGFuY2VvZiAkLkV2ZW50KSB7XG4gICAgICBzZWxmLmluU3RhdGVbb2JqLnR5cGUgPT0gJ2ZvY3Vzb3V0JyA/ICdmb2N1cycgOiAnaG92ZXInXSA9IGZhbHNlXG4gICAgfVxuXG4gICAgaWYgKHNlbGYuaXNJblN0YXRlVHJ1ZSgpKSByZXR1cm5cblxuICAgIGNsZWFyVGltZW91dChzZWxmLnRpbWVvdXQpXG5cbiAgICBzZWxmLmhvdmVyU3RhdGUgPSAnb3V0J1xuXG4gICAgaWYgKCFzZWxmLm9wdGlvbnMuZGVsYXkgfHwgIXNlbGYub3B0aW9ucy5kZWxheS5oaWRlKSByZXR1cm4gc2VsZi5oaWRlKClcblxuICAgIHNlbGYudGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKHNlbGYuaG92ZXJTdGF0ZSA9PSAnb3V0Jykgc2VsZi5oaWRlKClcbiAgICB9LCBzZWxmLm9wdGlvbnMuZGVsYXkuaGlkZSlcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGUgPSAkLkV2ZW50KCdzaG93LmJzLicgKyB0aGlzLnR5cGUpXG5cbiAgICBpZiAodGhpcy5oYXNDb250ZW50KCkgJiYgdGhpcy5lbmFibGVkKSB7XG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgICAgdmFyIGluRG9tID0gJC5jb250YWlucyh0aGlzLiRlbGVtZW50WzBdLm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLiRlbGVtZW50WzBdKVxuICAgICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgIWluRG9tKSByZXR1cm5cbiAgICAgIHZhciB0aGF0ID0gdGhpc1xuXG4gICAgICB2YXIgJHRpcCA9IHRoaXMudGlwKClcblxuICAgICAgdmFyIHRpcElkID0gdGhpcy5nZXRVSUQodGhpcy50eXBlKVxuXG4gICAgICB0aGlzLnNldENvbnRlbnQoKVxuICAgICAgJHRpcC5hdHRyKCdpZCcsIHRpcElkKVxuICAgICAgdGhpcy4kZWxlbWVudC5hdHRyKCdhcmlhLWRlc2NyaWJlZGJ5JywgdGlwSWQpXG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuYW5pbWF0aW9uKSAkdGlwLmFkZENsYXNzKCdmYWRlJylcblxuICAgICAgdmFyIHBsYWNlbWVudCA9IHR5cGVvZiB0aGlzLm9wdGlvbnMucGxhY2VtZW50ID09ICdmdW5jdGlvbicgP1xuICAgICAgICB0aGlzLm9wdGlvbnMucGxhY2VtZW50LmNhbGwodGhpcywgJHRpcFswXSwgdGhpcy4kZWxlbWVudFswXSkgOlxuICAgICAgICB0aGlzLm9wdGlvbnMucGxhY2VtZW50XG5cbiAgICAgIHZhciBhdXRvVG9rZW4gPSAvXFxzP2F1dG8/XFxzPy9pXG4gICAgICB2YXIgYXV0b1BsYWNlID0gYXV0b1Rva2VuLnRlc3QocGxhY2VtZW50KVxuICAgICAgaWYgKGF1dG9QbGFjZSkgcGxhY2VtZW50ID0gcGxhY2VtZW50LnJlcGxhY2UoYXV0b1Rva2VuLCAnJykgfHwgJ3RvcCdcblxuICAgICAgJHRpcFxuICAgICAgICAuZGV0YWNoKClcbiAgICAgICAgLmNzcyh7IHRvcDogMCwgbGVmdDogMCwgZGlzcGxheTogJ2Jsb2NrJyB9KVxuICAgICAgICAuYWRkQ2xhc3MocGxhY2VtZW50KVxuICAgICAgICAuZGF0YSgnYnMuJyArIHRoaXMudHlwZSwgdGhpcylcblxuICAgICAgdGhpcy5vcHRpb25zLmNvbnRhaW5lciA/ICR0aXAuYXBwZW5kVG8odGhpcy5vcHRpb25zLmNvbnRhaW5lcikgOiAkdGlwLmluc2VydEFmdGVyKHRoaXMuJGVsZW1lbnQpXG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2luc2VydGVkLmJzLicgKyB0aGlzLnR5cGUpXG5cbiAgICAgIHZhciBwb3MgICAgICAgICAgPSB0aGlzLmdldFBvc2l0aW9uKClcbiAgICAgIHZhciBhY3R1YWxXaWR0aCAgPSAkdGlwWzBdLm9mZnNldFdpZHRoXG4gICAgICB2YXIgYWN0dWFsSGVpZ2h0ID0gJHRpcFswXS5vZmZzZXRIZWlnaHRcblxuICAgICAgaWYgKGF1dG9QbGFjZSkge1xuICAgICAgICB2YXIgb3JnUGxhY2VtZW50ID0gcGxhY2VtZW50XG4gICAgICAgIHZhciB2aWV3cG9ydERpbSA9IHRoaXMuZ2V0UG9zaXRpb24odGhpcy4kdmlld3BvcnQpXG5cbiAgICAgICAgcGxhY2VtZW50ID0gcGxhY2VtZW50ID09ICdib3R0b20nICYmIHBvcy5ib3R0b20gKyBhY3R1YWxIZWlnaHQgPiB2aWV3cG9ydERpbS5ib3R0b20gPyAndG9wJyAgICA6XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlbWVudCA9PSAndG9wJyAgICAmJiBwb3MudG9wICAgIC0gYWN0dWFsSGVpZ2h0IDwgdmlld3BvcnREaW0udG9wICAgID8gJ2JvdHRvbScgOlxuICAgICAgICAgICAgICAgICAgICBwbGFjZW1lbnQgPT0gJ3JpZ2h0JyAgJiYgcG9zLnJpZ2h0ICArIGFjdHVhbFdpZHRoICA+IHZpZXdwb3J0RGltLndpZHRoICA/ICdsZWZ0JyAgIDpcbiAgICAgICAgICAgICAgICAgICAgcGxhY2VtZW50ID09ICdsZWZ0JyAgICYmIHBvcy5sZWZ0ICAgLSBhY3R1YWxXaWR0aCAgPCB2aWV3cG9ydERpbS5sZWZ0ICAgPyAncmlnaHQnICA6XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlbWVudFxuXG4gICAgICAgICR0aXBcbiAgICAgICAgICAucmVtb3ZlQ2xhc3Mob3JnUGxhY2VtZW50KVxuICAgICAgICAgIC5hZGRDbGFzcyhwbGFjZW1lbnQpXG4gICAgICB9XG5cbiAgICAgIHZhciBjYWxjdWxhdGVkT2Zmc2V0ID0gdGhpcy5nZXRDYWxjdWxhdGVkT2Zmc2V0KHBsYWNlbWVudCwgcG9zLCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KVxuXG4gICAgICB0aGlzLmFwcGx5UGxhY2VtZW50KGNhbGN1bGF0ZWRPZmZzZXQsIHBsYWNlbWVudClcblxuICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJldkhvdmVyU3RhdGUgPSB0aGF0LmhvdmVyU3RhdGVcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdzaG93bi5icy4nICsgdGhhdC50eXBlKVxuICAgICAgICB0aGF0LmhvdmVyU3RhdGUgPSBudWxsXG5cbiAgICAgICAgaWYgKHByZXZIb3ZlclN0YXRlID09ICdvdXQnKSB0aGF0LmxlYXZlKHRoYXQpXG4gICAgICB9XG5cbiAgICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmIHRoaXMuJHRpcC5oYXNDbGFzcygnZmFkZScpID9cbiAgICAgICAgJHRpcFxuICAgICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGNvbXBsZXRlKVxuICAgICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChUb29sdGlwLlRSQU5TSVRJT05fRFVSQVRJT04pIDpcbiAgICAgICAgY29tcGxldGUoKVxuICAgIH1cbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmFwcGx5UGxhY2VtZW50ID0gZnVuY3Rpb24gKG9mZnNldCwgcGxhY2VtZW50KSB7XG4gICAgdmFyICR0aXAgICA9IHRoaXMudGlwKClcbiAgICB2YXIgd2lkdGggID0gJHRpcFswXS5vZmZzZXRXaWR0aFxuICAgIHZhciBoZWlnaHQgPSAkdGlwWzBdLm9mZnNldEhlaWdodFxuXG4gICAgLy8gbWFudWFsbHkgcmVhZCBtYXJnaW5zIGJlY2F1c2UgZ2V0Qm91bmRpbmdDbGllbnRSZWN0IGluY2x1ZGVzIGRpZmZlcmVuY2VcbiAgICB2YXIgbWFyZ2luVG9wID0gcGFyc2VJbnQoJHRpcC5jc3MoJ21hcmdpbi10b3AnKSwgMTApXG4gICAgdmFyIG1hcmdpbkxlZnQgPSBwYXJzZUludCgkdGlwLmNzcygnbWFyZ2luLWxlZnQnKSwgMTApXG5cbiAgICAvLyB3ZSBtdXN0IGNoZWNrIGZvciBOYU4gZm9yIGllIDgvOVxuICAgIGlmIChpc05hTihtYXJnaW5Ub3ApKSAgbWFyZ2luVG9wICA9IDBcbiAgICBpZiAoaXNOYU4obWFyZ2luTGVmdCkpIG1hcmdpbkxlZnQgPSAwXG5cbiAgICBvZmZzZXQudG9wICArPSBtYXJnaW5Ub3BcbiAgICBvZmZzZXQubGVmdCArPSBtYXJnaW5MZWZ0XG5cbiAgICAvLyAkLmZuLm9mZnNldCBkb2Vzbid0IHJvdW5kIHBpeGVsIHZhbHVlc1xuICAgIC8vIHNvIHdlIHVzZSBzZXRPZmZzZXQgZGlyZWN0bHkgd2l0aCBvdXIgb3duIGZ1bmN0aW9uIEItMFxuICAgICQub2Zmc2V0LnNldE9mZnNldCgkdGlwWzBdLCAkLmV4dGVuZCh7XG4gICAgICB1c2luZzogZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgICR0aXAuY3NzKHtcbiAgICAgICAgICB0b3A6IE1hdGgucm91bmQocHJvcHMudG9wKSxcbiAgICAgICAgICBsZWZ0OiBNYXRoLnJvdW5kKHByb3BzLmxlZnQpXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSwgb2Zmc2V0KSwgMClcblxuICAgICR0aXAuYWRkQ2xhc3MoJ2luJylcblxuICAgIC8vIGNoZWNrIHRvIHNlZSBpZiBwbGFjaW5nIHRpcCBpbiBuZXcgb2Zmc2V0IGNhdXNlZCB0aGUgdGlwIHRvIHJlc2l6ZSBpdHNlbGZcbiAgICB2YXIgYWN0dWFsV2lkdGggID0gJHRpcFswXS5vZmZzZXRXaWR0aFxuICAgIHZhciBhY3R1YWxIZWlnaHQgPSAkdGlwWzBdLm9mZnNldEhlaWdodFxuXG4gICAgaWYgKHBsYWNlbWVudCA9PSAndG9wJyAmJiBhY3R1YWxIZWlnaHQgIT0gaGVpZ2h0KSB7XG4gICAgICBvZmZzZXQudG9wID0gb2Zmc2V0LnRvcCArIGhlaWdodCAtIGFjdHVhbEhlaWdodFxuICAgIH1cblxuICAgIHZhciBkZWx0YSA9IHRoaXMuZ2V0Vmlld3BvcnRBZGp1c3RlZERlbHRhKHBsYWNlbWVudCwgb2Zmc2V0LCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KVxuXG4gICAgaWYgKGRlbHRhLmxlZnQpIG9mZnNldC5sZWZ0ICs9IGRlbHRhLmxlZnRcbiAgICBlbHNlIG9mZnNldC50b3AgKz0gZGVsdGEudG9wXG5cbiAgICB2YXIgaXNWZXJ0aWNhbCAgICAgICAgICA9IC90b3B8Ym90dG9tLy50ZXN0KHBsYWNlbWVudClcbiAgICB2YXIgYXJyb3dEZWx0YSAgICAgICAgICA9IGlzVmVydGljYWwgPyBkZWx0YS5sZWZ0ICogMiAtIHdpZHRoICsgYWN0dWFsV2lkdGggOiBkZWx0YS50b3AgKiAyIC0gaGVpZ2h0ICsgYWN0dWFsSGVpZ2h0XG4gICAgdmFyIGFycm93T2Zmc2V0UG9zaXRpb24gPSBpc1ZlcnRpY2FsID8gJ29mZnNldFdpZHRoJyA6ICdvZmZzZXRIZWlnaHQnXG5cbiAgICAkdGlwLm9mZnNldChvZmZzZXQpXG4gICAgdGhpcy5yZXBsYWNlQXJyb3coYXJyb3dEZWx0YSwgJHRpcFswXVthcnJvd09mZnNldFBvc2l0aW9uXSwgaXNWZXJ0aWNhbClcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnJlcGxhY2VBcnJvdyA9IGZ1bmN0aW9uIChkZWx0YSwgZGltZW5zaW9uLCBpc1ZlcnRpY2FsKSB7XG4gICAgdGhpcy5hcnJvdygpXG4gICAgICAuY3NzKGlzVmVydGljYWwgPyAnbGVmdCcgOiAndG9wJywgNTAgKiAoMSAtIGRlbHRhIC8gZGltZW5zaW9uKSArICclJylcbiAgICAgIC5jc3MoaXNWZXJ0aWNhbCA/ICd0b3AnIDogJ2xlZnQnLCAnJylcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnNldENvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICR0aXAgID0gdGhpcy50aXAoKVxuICAgIHZhciB0aXRsZSA9IHRoaXMuZ2V0VGl0bGUoKVxuXG4gICAgJHRpcC5maW5kKCcudG9vbHRpcC1pbm5lcicpW3RoaXMub3B0aW9ucy5odG1sID8gJ2h0bWwnIDogJ3RleHQnXSh0aXRsZSlcbiAgICAkdGlwLnJlbW92ZUNsYXNzKCdmYWRlIGluIHRvcCBib3R0b20gbGVmdCByaWdodCcpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgdmFyIHRoYXQgPSB0aGlzXG4gICAgdmFyICR0aXAgPSAkKHRoaXMuJHRpcClcbiAgICB2YXIgZSAgICA9ICQuRXZlbnQoJ2hpZGUuYnMuJyArIHRoaXMudHlwZSlcblxuICAgIGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgaWYgKHRoYXQuaG92ZXJTdGF0ZSAhPSAnaW4nKSAkdGlwLmRldGFjaCgpXG4gICAgICBpZiAodGhhdC4kZWxlbWVudCkgeyAvLyBUT0RPOiBDaGVjayB3aGV0aGVyIGd1YXJkaW5nIHRoaXMgY29kZSB3aXRoIHRoaXMgYGlmYCBpcyByZWFsbHkgbmVjZXNzYXJ5LlxuICAgICAgICB0aGF0LiRlbGVtZW50XG4gICAgICAgICAgLnJlbW92ZUF0dHIoJ2FyaWEtZGVzY3JpYmVkYnknKVxuICAgICAgICAgIC50cmlnZ2VyKCdoaWRkZW4uYnMuJyArIHRoYXQudHlwZSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKClcbiAgICB9XG5cbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoZSlcblxuICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSByZXR1cm5cblxuICAgICR0aXAucmVtb3ZlQ2xhc3MoJ2luJylcblxuICAgICQuc3VwcG9ydC50cmFuc2l0aW9uICYmICR0aXAuaGFzQ2xhc3MoJ2ZhZGUnKSA/XG4gICAgICAkdGlwXG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIGNvbXBsZXRlKVxuICAgICAgICAuZW11bGF0ZVRyYW5zaXRpb25FbmQoVG9vbHRpcC5UUkFOU0lUSU9OX0RVUkFUSU9OKSA6XG4gICAgICBjb21wbGV0ZSgpXG5cbiAgICB0aGlzLmhvdmVyU3RhdGUgPSBudWxsXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZml4VGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIGlmICgkZS5hdHRyKCd0aXRsZScpIHx8IHR5cGVvZiAkZS5hdHRyKCdkYXRhLW9yaWdpbmFsLXRpdGxlJykgIT0gJ3N0cmluZycpIHtcbiAgICAgICRlLmF0dHIoJ2RhdGEtb3JpZ2luYWwtdGl0bGUnLCAkZS5hdHRyKCd0aXRsZScpIHx8ICcnKS5hdHRyKCd0aXRsZScsICcnKVxuICAgIH1cbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmhhc0NvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VGl0bGUoKVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0UG9zaXRpb24gPSBmdW5jdGlvbiAoJGVsZW1lbnQpIHtcbiAgICAkZWxlbWVudCAgID0gJGVsZW1lbnQgfHwgdGhpcy4kZWxlbWVudFxuXG4gICAgdmFyIGVsICAgICA9ICRlbGVtZW50WzBdXG4gICAgdmFyIGlzQm9keSA9IGVsLnRhZ05hbWUgPT0gJ0JPRFknXG5cbiAgICB2YXIgZWxSZWN0ICAgID0gZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICBpZiAoZWxSZWN0LndpZHRoID09IG51bGwpIHtcbiAgICAgIC8vIHdpZHRoIGFuZCBoZWlnaHQgYXJlIG1pc3NpbmcgaW4gSUU4LCBzbyBjb21wdXRlIHRoZW0gbWFudWFsbHk7IHNlZSBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzE0MDkzXG4gICAgICBlbFJlY3QgPSAkLmV4dGVuZCh7fSwgZWxSZWN0LCB7IHdpZHRoOiBlbFJlY3QucmlnaHQgLSBlbFJlY3QubGVmdCwgaGVpZ2h0OiBlbFJlY3QuYm90dG9tIC0gZWxSZWN0LnRvcCB9KVxuICAgIH1cbiAgICB2YXIgaXNTdmcgPSB3aW5kb3cuU1ZHRWxlbWVudCAmJiBlbCBpbnN0YW5jZW9mIHdpbmRvdy5TVkdFbGVtZW50XG4gICAgLy8gQXZvaWQgdXNpbmcgJC5vZmZzZXQoKSBvbiBTVkdzIHNpbmNlIGl0IGdpdmVzIGluY29ycmVjdCByZXN1bHRzIGluIGpRdWVyeSAzLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzIwMjgwXG4gICAgdmFyIGVsT2Zmc2V0ICA9IGlzQm9keSA/IHsgdG9wOiAwLCBsZWZ0OiAwIH0gOiAoaXNTdmcgPyBudWxsIDogJGVsZW1lbnQub2Zmc2V0KCkpXG4gICAgdmFyIHNjcm9sbCAgICA9IHsgc2Nyb2xsOiBpc0JvZHkgPyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIDogJGVsZW1lbnQuc2Nyb2xsVG9wKCkgfVxuICAgIHZhciBvdXRlckRpbXMgPSBpc0JvZHkgPyB7IHdpZHRoOiAkKHdpbmRvdykud2lkdGgoKSwgaGVpZ2h0OiAkKHdpbmRvdykuaGVpZ2h0KCkgfSA6IG51bGxcblxuICAgIHJldHVybiAkLmV4dGVuZCh7fSwgZWxSZWN0LCBzY3JvbGwsIG91dGVyRGltcywgZWxPZmZzZXQpXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRDYWxjdWxhdGVkT2Zmc2V0ID0gZnVuY3Rpb24gKHBsYWNlbWVudCwgcG9zLCBhY3R1YWxXaWR0aCwgYWN0dWFsSGVpZ2h0KSB7XG4gICAgcmV0dXJuIHBsYWNlbWVudCA9PSAnYm90dG9tJyA/IHsgdG9wOiBwb3MudG9wICsgcG9zLmhlaWdodCwgICBsZWZ0OiBwb3MubGVmdCArIHBvcy53aWR0aCAvIDIgLSBhY3R1YWxXaWR0aCAvIDIgfSA6XG4gICAgICAgICAgIHBsYWNlbWVudCA9PSAndG9wJyAgICA/IHsgdG9wOiBwb3MudG9wIC0gYWN0dWFsSGVpZ2h0LCBsZWZ0OiBwb3MubGVmdCArIHBvcy53aWR0aCAvIDIgLSBhY3R1YWxXaWR0aCAvIDIgfSA6XG4gICAgICAgICAgIHBsYWNlbWVudCA9PSAnbGVmdCcgICA/IHsgdG9wOiBwb3MudG9wICsgcG9zLmhlaWdodCAvIDIgLSBhY3R1YWxIZWlnaHQgLyAyLCBsZWZ0OiBwb3MubGVmdCAtIGFjdHVhbFdpZHRoIH0gOlxuICAgICAgICAvKiBwbGFjZW1lbnQgPT0gJ3JpZ2h0JyAqLyB7IHRvcDogcG9zLnRvcCArIHBvcy5oZWlnaHQgLyAyIC0gYWN0dWFsSGVpZ2h0IC8gMiwgbGVmdDogcG9zLmxlZnQgKyBwb3Mud2lkdGggfVxuXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRWaWV3cG9ydEFkanVzdGVkRGVsdGEgPSBmdW5jdGlvbiAocGxhY2VtZW50LCBwb3MsIGFjdHVhbFdpZHRoLCBhY3R1YWxIZWlnaHQpIHtcbiAgICB2YXIgZGVsdGEgPSB7IHRvcDogMCwgbGVmdDogMCB9XG4gICAgaWYgKCF0aGlzLiR2aWV3cG9ydCkgcmV0dXJuIGRlbHRhXG5cbiAgICB2YXIgdmlld3BvcnRQYWRkaW5nID0gdGhpcy5vcHRpb25zLnZpZXdwb3J0ICYmIHRoaXMub3B0aW9ucy52aWV3cG9ydC5wYWRkaW5nIHx8IDBcbiAgICB2YXIgdmlld3BvcnREaW1lbnNpb25zID0gdGhpcy5nZXRQb3NpdGlvbih0aGlzLiR2aWV3cG9ydClcblxuICAgIGlmICgvcmlnaHR8bGVmdC8udGVzdChwbGFjZW1lbnQpKSB7XG4gICAgICB2YXIgdG9wRWRnZU9mZnNldCAgICA9IHBvcy50b3AgLSB2aWV3cG9ydFBhZGRpbmcgLSB2aWV3cG9ydERpbWVuc2lvbnMuc2Nyb2xsXG4gICAgICB2YXIgYm90dG9tRWRnZU9mZnNldCA9IHBvcy50b3AgKyB2aWV3cG9ydFBhZGRpbmcgLSB2aWV3cG9ydERpbWVuc2lvbnMuc2Nyb2xsICsgYWN0dWFsSGVpZ2h0XG4gICAgICBpZiAodG9wRWRnZU9mZnNldCA8IHZpZXdwb3J0RGltZW5zaW9ucy50b3ApIHsgLy8gdG9wIG92ZXJmbG93XG4gICAgICAgIGRlbHRhLnRvcCA9IHZpZXdwb3J0RGltZW5zaW9ucy50b3AgLSB0b3BFZGdlT2Zmc2V0XG4gICAgICB9IGVsc2UgaWYgKGJvdHRvbUVkZ2VPZmZzZXQgPiB2aWV3cG9ydERpbWVuc2lvbnMudG9wICsgdmlld3BvcnREaW1lbnNpb25zLmhlaWdodCkgeyAvLyBib3R0b20gb3ZlcmZsb3dcbiAgICAgICAgZGVsdGEudG9wID0gdmlld3BvcnREaW1lbnNpb25zLnRvcCArIHZpZXdwb3J0RGltZW5zaW9ucy5oZWlnaHQgLSBib3R0b21FZGdlT2Zmc2V0XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBsZWZ0RWRnZU9mZnNldCAgPSBwb3MubGVmdCAtIHZpZXdwb3J0UGFkZGluZ1xuICAgICAgdmFyIHJpZ2h0RWRnZU9mZnNldCA9IHBvcy5sZWZ0ICsgdmlld3BvcnRQYWRkaW5nICsgYWN0dWFsV2lkdGhcbiAgICAgIGlmIChsZWZ0RWRnZU9mZnNldCA8IHZpZXdwb3J0RGltZW5zaW9ucy5sZWZ0KSB7IC8vIGxlZnQgb3ZlcmZsb3dcbiAgICAgICAgZGVsdGEubGVmdCA9IHZpZXdwb3J0RGltZW5zaW9ucy5sZWZ0IC0gbGVmdEVkZ2VPZmZzZXRcbiAgICAgIH0gZWxzZSBpZiAocmlnaHRFZGdlT2Zmc2V0ID4gdmlld3BvcnREaW1lbnNpb25zLnJpZ2h0KSB7IC8vIHJpZ2h0IG92ZXJmbG93XG4gICAgICAgIGRlbHRhLmxlZnQgPSB2aWV3cG9ydERpbWVuc2lvbnMubGVmdCArIHZpZXdwb3J0RGltZW5zaW9ucy53aWR0aCAtIHJpZ2h0RWRnZU9mZnNldFxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkZWx0YVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZ2V0VGl0bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRpdGxlXG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIHZhciBvICA9IHRoaXMub3B0aW9uc1xuXG4gICAgdGl0bGUgPSAkZS5hdHRyKCdkYXRhLW9yaWdpbmFsLXRpdGxlJylcbiAgICAgIHx8ICh0eXBlb2Ygby50aXRsZSA9PSAnZnVuY3Rpb24nID8gby50aXRsZS5jYWxsKCRlWzBdKSA6ICBvLnRpdGxlKVxuXG4gICAgcmV0dXJuIHRpdGxlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5nZXRVSUQgPSBmdW5jdGlvbiAocHJlZml4KSB7XG4gICAgZG8gcHJlZml4ICs9IH5+KE1hdGgucmFuZG9tKCkgKiAxMDAwMDAwKVxuICAgIHdoaWxlIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwcmVmaXgpKVxuICAgIHJldHVybiBwcmVmaXhcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuJHRpcCkge1xuICAgICAgdGhpcy4kdGlwID0gJCh0aGlzLm9wdGlvbnMudGVtcGxhdGUpXG4gICAgICBpZiAodGhpcy4kdGlwLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnR5cGUgKyAnIGB0ZW1wbGF0ZWAgb3B0aW9uIG11c3QgY29uc2lzdCBvZiBleGFjdGx5IDEgdG9wLWxldmVsIGVsZW1lbnQhJylcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuJHRpcFxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuYXJyb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICh0aGlzLiRhcnJvdyA9IHRoaXMuJGFycm93IHx8IHRoaXMudGlwKCkuZmluZCgnLnRvb2x0aXAtYXJyb3cnKSlcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSB0cnVlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlXG4gIH1cblxuICBUb29sdGlwLnByb3RvdHlwZS50b2dnbGVFbmFibGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZW5hYmxlZCA9ICF0aGlzLmVuYWJsZWRcbiAgfVxuXG4gIFRvb2x0aXAucHJvdG90eXBlLnRvZ2dsZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzXG4gICAgaWYgKGUpIHtcbiAgICAgIHNlbGYgPSAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYnMuJyArIHRoaXMudHlwZSlcbiAgICAgIGlmICghc2VsZikge1xuICAgICAgICBzZWxmID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZS5jdXJyZW50VGFyZ2V0LCB0aGlzLmdldERlbGVnYXRlT3B0aW9ucygpKVxuICAgICAgICAkKGUuY3VycmVudFRhcmdldCkuZGF0YSgnYnMuJyArIHRoaXMudHlwZSwgc2VsZilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZSkge1xuICAgICAgc2VsZi5pblN0YXRlLmNsaWNrID0gIXNlbGYuaW5TdGF0ZS5jbGlja1xuICAgICAgaWYgKHNlbGYuaXNJblN0YXRlVHJ1ZSgpKSBzZWxmLmVudGVyKHNlbGYpXG4gICAgICBlbHNlIHNlbGYubGVhdmUoc2VsZilcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi50aXAoKS5oYXNDbGFzcygnaW4nKSA/IHNlbGYubGVhdmUoc2VsZikgOiBzZWxmLmVudGVyKHNlbGYpXG4gICAgfVxuICB9XG5cbiAgVG9vbHRpcC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdGhhdCA9IHRoaXNcbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0KVxuICAgIHRoaXMuaGlkZShmdW5jdGlvbiAoKSB7XG4gICAgICB0aGF0LiRlbGVtZW50Lm9mZignLicgKyB0aGF0LnR5cGUpLnJlbW92ZURhdGEoJ2JzLicgKyB0aGF0LnR5cGUpXG4gICAgICBpZiAodGhhdC4kdGlwKSB7XG4gICAgICAgIHRoYXQuJHRpcC5kZXRhY2goKVxuICAgICAgfVxuICAgICAgdGhhdC4kdGlwID0gbnVsbFxuICAgICAgdGhhdC4kYXJyb3cgPSBudWxsXG4gICAgICB0aGF0LiR2aWV3cG9ydCA9IG51bGxcbiAgICAgIHRoYXQuJGVsZW1lbnQgPSBudWxsXG4gICAgfSlcbiAgfVxuXG5cbiAgLy8gVE9PTFRJUCBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnRvb2x0aXAnKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEgJiYgL2Rlc3Ryb3l8aGlkZS8udGVzdChvcHRpb24pKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMudG9vbHRpcCcsIChkYXRhID0gbmV3IFRvb2x0aXAodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLnRvb2x0aXBcblxuICAkLmZuLnRvb2x0aXAgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yID0gVG9vbHRpcFxuXG5cbiAgLy8gVE9PTFRJUCBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi50b29sdGlwLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi50b29sdGlwID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvdG9vbHRpcC5qc1xuLy8gbW9kdWxlIGlkID0gMTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHBvcG92ZXIuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyNwb3BvdmVyc1xuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFBPUE9WRVIgUFVCTElDIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHZhciBQb3BvdmVyID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmluaXQoJ3BvcG92ZXInLCBlbGVtZW50LCBvcHRpb25zKVxuICB9XG5cbiAgaWYgKCEkLmZuLnRvb2x0aXApIHRocm93IG5ldyBFcnJvcignUG9wb3ZlciByZXF1aXJlcyB0b29sdGlwLmpzJylcblxuICBQb3BvdmVyLlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFBvcG92ZXIuREVGQVVMVFMgPSAkLmV4dGVuZCh7fSwgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yLkRFRkFVTFRTLCB7XG4gICAgcGxhY2VtZW50OiAncmlnaHQnLFxuICAgIHRyaWdnZXI6ICdjbGljaycsXG4gICAgY29udGVudDogJycsXG4gICAgdGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwicG9wb3ZlclwiIHJvbGU9XCJ0b29sdGlwXCI+PGRpdiBjbGFzcz1cImFycm93XCI+PC9kaXY+PGgzIGNsYXNzPVwicG9wb3Zlci10aXRsZVwiPjwvaDM+PGRpdiBjbGFzcz1cInBvcG92ZXItY29udGVudFwiPjwvZGl2PjwvZGl2PidcbiAgfSlcblxuXG4gIC8vIE5PVEU6IFBPUE9WRVIgRVhURU5EUyB0b29sdGlwLmpzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgUG9wb3Zlci5wcm90b3R5cGUgPSAkLmV4dGVuZCh7fSwgJC5mbi50b29sdGlwLkNvbnN0cnVjdG9yLnByb3RvdHlwZSlcblxuICBQb3BvdmVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFBvcG92ZXJcblxuICBQb3BvdmVyLnByb3RvdHlwZS5nZXREZWZhdWx0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gUG9wb3Zlci5ERUZBVUxUU1xuICB9XG5cbiAgUG9wb3Zlci5wcm90b3R5cGUuc2V0Q29udGVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHRpcCAgICA9IHRoaXMudGlwKClcbiAgICB2YXIgdGl0bGUgICA9IHRoaXMuZ2V0VGl0bGUoKVxuICAgIHZhciBjb250ZW50ID0gdGhpcy5nZXRDb250ZW50KClcblxuICAgICR0aXAuZmluZCgnLnBvcG92ZXItdGl0bGUnKVt0aGlzLm9wdGlvbnMuaHRtbCA/ICdodG1sJyA6ICd0ZXh0J10odGl0bGUpXG4gICAgJHRpcC5maW5kKCcucG9wb3Zlci1jb250ZW50JykuY2hpbGRyZW4oKS5kZXRhY2goKS5lbmQoKVsgLy8gd2UgdXNlIGFwcGVuZCBmb3IgaHRtbCBvYmplY3RzIHRvIG1haW50YWluIGpzIGV2ZW50c1xuICAgICAgdGhpcy5vcHRpb25zLmh0bWwgPyAodHlwZW9mIGNvbnRlbnQgPT0gJ3N0cmluZycgPyAnaHRtbCcgOiAnYXBwZW5kJykgOiAndGV4dCdcbiAgICBdKGNvbnRlbnQpXG5cbiAgICAkdGlwLnJlbW92ZUNsYXNzKCdmYWRlIHRvcCBib3R0b20gbGVmdCByaWdodCBpbicpXG5cbiAgICAvLyBJRTggZG9lc24ndCBhY2NlcHQgaGlkaW5nIHZpYSB0aGUgYDplbXB0eWAgcHNldWRvIHNlbGVjdG9yLCB3ZSBoYXZlIHRvIGRvXG4gICAgLy8gdGhpcyBtYW51YWxseSBieSBjaGVja2luZyB0aGUgY29udGVudHMuXG4gICAgaWYgKCEkdGlwLmZpbmQoJy5wb3BvdmVyLXRpdGxlJykuaHRtbCgpKSAkdGlwLmZpbmQoJy5wb3BvdmVyLXRpdGxlJykuaGlkZSgpXG4gIH1cblxuICBQb3BvdmVyLnByb3RvdHlwZS5oYXNDb250ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmdldFRpdGxlKCkgfHwgdGhpcy5nZXRDb250ZW50KClcbiAgfVxuXG4gIFBvcG92ZXIucHJvdG90eXBlLmdldENvbnRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRlID0gdGhpcy4kZWxlbWVudFxuICAgIHZhciBvICA9IHRoaXMub3B0aW9uc1xuXG4gICAgcmV0dXJuICRlLmF0dHIoJ2RhdGEtY29udGVudCcpXG4gICAgICB8fCAodHlwZW9mIG8uY29udGVudCA9PSAnZnVuY3Rpb24nID9cbiAgICAgICAgICAgIG8uY29udGVudC5jYWxsKCRlWzBdKSA6XG4gICAgICAgICAgICBvLmNvbnRlbnQpXG4gIH1cblxuICBQb3BvdmVyLnByb3RvdHlwZS5hcnJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKHRoaXMuJGFycm93ID0gdGhpcy4kYXJyb3cgfHwgdGhpcy50aXAoKS5maW5kKCcuYXJyb3cnKSlcbiAgfVxuXG5cbiAgLy8gUE9QT1ZFUiBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnBvcG92ZXInKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEgJiYgL2Rlc3Ryb3l8aGlkZS8udGVzdChvcHRpb24pKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMucG9wb3ZlcicsIChkYXRhID0gbmV3IFBvcG92ZXIodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLnBvcG92ZXJcblxuICAkLmZuLnBvcG92ZXIgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5wb3BvdmVyLkNvbnN0cnVjdG9yID0gUG9wb3ZlclxuXG5cbiAgLy8gUE9QT1ZFUiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5wb3BvdmVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi5wb3BvdmVyID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvcG9wb3Zlci5qc1xuLy8gbW9kdWxlIGlkID0gMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBCb290c3RyYXA6IHNjcm9sbHNweS5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI3Njcm9sbHNweVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5cmlnaHQgMjAxMS0yMDE2IFR3aXR0ZXIsIEluYy5cbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFNDUk9MTFNQWSBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gU2Nyb2xsU3B5KGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLiRib2R5ICAgICAgICAgID0gJChkb2N1bWVudC5ib2R5KVxuICAgIHRoaXMuJHNjcm9sbEVsZW1lbnQgPSAkKGVsZW1lbnQpLmlzKGRvY3VtZW50LmJvZHkpID8gJCh3aW5kb3cpIDogJChlbGVtZW50KVxuICAgIHRoaXMub3B0aW9ucyAgICAgICAgPSAkLmV4dGVuZCh7fSwgU2Nyb2xsU3B5LkRFRkFVTFRTLCBvcHRpb25zKVxuICAgIHRoaXMuc2VsZWN0b3IgICAgICAgPSAodGhpcy5vcHRpb25zLnRhcmdldCB8fCAnJykgKyAnIC5uYXYgbGkgPiBhJ1xuICAgIHRoaXMub2Zmc2V0cyAgICAgICAgPSBbXVxuICAgIHRoaXMudGFyZ2V0cyAgICAgICAgPSBbXVxuICAgIHRoaXMuYWN0aXZlVGFyZ2V0ICAgPSBudWxsXG4gICAgdGhpcy5zY3JvbGxIZWlnaHQgICA9IDBcblxuICAgIHRoaXMuJHNjcm9sbEVsZW1lbnQub24oJ3Njcm9sbC5icy5zY3JvbGxzcHknLCAkLnByb3h5KHRoaXMucHJvY2VzcywgdGhpcykpXG4gICAgdGhpcy5yZWZyZXNoKClcbiAgICB0aGlzLnByb2Nlc3MoKVxuICB9XG5cbiAgU2Nyb2xsU3B5LlZFUlNJT04gID0gJzMuMy43J1xuXG4gIFNjcm9sbFNweS5ERUZBVUxUUyA9IHtcbiAgICBvZmZzZXQ6IDEwXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLmdldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy4kc2Nyb2xsRWxlbWVudFswXS5zY3JvbGxIZWlnaHQgfHwgTWF0aC5tYXgodGhpcy4kYm9keVswXS5zY3JvbGxIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQpXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRoYXQgICAgICAgICAgPSB0aGlzXG4gICAgdmFyIG9mZnNldE1ldGhvZCAgPSAnb2Zmc2V0J1xuICAgIHZhciBvZmZzZXRCYXNlICAgID0gMFxuXG4gICAgdGhpcy5vZmZzZXRzICAgICAgPSBbXVxuICAgIHRoaXMudGFyZ2V0cyAgICAgID0gW11cbiAgICB0aGlzLnNjcm9sbEhlaWdodCA9IHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KClcblxuICAgIGlmICghJC5pc1dpbmRvdyh0aGlzLiRzY3JvbGxFbGVtZW50WzBdKSkge1xuICAgICAgb2Zmc2V0TWV0aG9kID0gJ3Bvc2l0aW9uJ1xuICAgICAgb2Zmc2V0QmFzZSAgID0gdGhpcy4kc2Nyb2xsRWxlbWVudC5zY3JvbGxUb3AoKVxuICAgIH1cblxuICAgIHRoaXMuJGJvZHlcbiAgICAgIC5maW5kKHRoaXMuc2VsZWN0b3IpXG4gICAgICAubWFwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRlbCAgID0gJCh0aGlzKVxuICAgICAgICB2YXIgaHJlZiAgPSAkZWwuZGF0YSgndGFyZ2V0JykgfHwgJGVsLmF0dHIoJ2hyZWYnKVxuICAgICAgICB2YXIgJGhyZWYgPSAvXiMuLy50ZXN0KGhyZWYpICYmICQoaHJlZilcblxuICAgICAgICByZXR1cm4gKCRocmVmXG4gICAgICAgICAgJiYgJGhyZWYubGVuZ3RoXG4gICAgICAgICAgJiYgJGhyZWYuaXMoJzp2aXNpYmxlJylcbiAgICAgICAgICAmJiBbWyRocmVmW29mZnNldE1ldGhvZF0oKS50b3AgKyBvZmZzZXRCYXNlLCBocmVmXV0pIHx8IG51bGxcbiAgICAgIH0pXG4gICAgICAuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYVswXSAtIGJbMF0gfSlcbiAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5vZmZzZXRzLnB1c2godGhpc1swXSlcbiAgICAgICAgdGhhdC50YXJnZXRzLnB1c2godGhpc1sxXSlcbiAgICAgIH0pXG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLnByb2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNjcm9sbFRvcCAgICA9IHRoaXMuJHNjcm9sbEVsZW1lbnQuc2Nyb2xsVG9wKCkgKyB0aGlzLm9wdGlvbnMub2Zmc2V0XG4gICAgdmFyIHNjcm9sbEhlaWdodCA9IHRoaXMuZ2V0U2Nyb2xsSGVpZ2h0KClcbiAgICB2YXIgbWF4U2Nyb2xsICAgID0gdGhpcy5vcHRpb25zLm9mZnNldCArIHNjcm9sbEhlaWdodCAtIHRoaXMuJHNjcm9sbEVsZW1lbnQuaGVpZ2h0KClcbiAgICB2YXIgb2Zmc2V0cyAgICAgID0gdGhpcy5vZmZzZXRzXG4gICAgdmFyIHRhcmdldHMgICAgICA9IHRoaXMudGFyZ2V0c1xuICAgIHZhciBhY3RpdmVUYXJnZXQgPSB0aGlzLmFjdGl2ZVRhcmdldFxuICAgIHZhciBpXG5cbiAgICBpZiAodGhpcy5zY3JvbGxIZWlnaHQgIT0gc2Nyb2xsSGVpZ2h0KSB7XG4gICAgICB0aGlzLnJlZnJlc2goKVxuICAgIH1cblxuICAgIGlmIChzY3JvbGxUb3AgPj0gbWF4U2Nyb2xsKSB7XG4gICAgICByZXR1cm4gYWN0aXZlVGFyZ2V0ICE9IChpID0gdGFyZ2V0c1t0YXJnZXRzLmxlbmd0aCAtIDFdKSAmJiB0aGlzLmFjdGl2YXRlKGkpXG4gICAgfVxuXG4gICAgaWYgKGFjdGl2ZVRhcmdldCAmJiBzY3JvbGxUb3AgPCBvZmZzZXRzWzBdKSB7XG4gICAgICB0aGlzLmFjdGl2ZVRhcmdldCA9IG51bGxcbiAgICAgIHJldHVybiB0aGlzLmNsZWFyKClcbiAgICB9XG5cbiAgICBmb3IgKGkgPSBvZmZzZXRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgYWN0aXZlVGFyZ2V0ICE9IHRhcmdldHNbaV1cbiAgICAgICAgJiYgc2Nyb2xsVG9wID49IG9mZnNldHNbaV1cbiAgICAgICAgJiYgKG9mZnNldHNbaSArIDFdID09PSB1bmRlZmluZWQgfHwgc2Nyb2xsVG9wIDwgb2Zmc2V0c1tpICsgMV0pXG4gICAgICAgICYmIHRoaXMuYWN0aXZhdGUodGFyZ2V0c1tpXSlcbiAgICB9XG4gIH1cblxuICBTY3JvbGxTcHkucHJvdG90eXBlLmFjdGl2YXRlID0gZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIHRoaXMuYWN0aXZlVGFyZ2V0ID0gdGFyZ2V0XG5cbiAgICB0aGlzLmNsZWFyKClcblxuICAgIHZhciBzZWxlY3RvciA9IHRoaXMuc2VsZWN0b3IgK1xuICAgICAgJ1tkYXRhLXRhcmdldD1cIicgKyB0YXJnZXQgKyAnXCJdLCcgK1xuICAgICAgdGhpcy5zZWxlY3RvciArICdbaHJlZj1cIicgKyB0YXJnZXQgKyAnXCJdJ1xuXG4gICAgdmFyIGFjdGl2ZSA9ICQoc2VsZWN0b3IpXG4gICAgICAucGFyZW50cygnbGknKVxuICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuXG4gICAgaWYgKGFjdGl2ZS5wYXJlbnQoJy5kcm9wZG93bi1tZW51JykubGVuZ3RoKSB7XG4gICAgICBhY3RpdmUgPSBhY3RpdmVcbiAgICAgICAgLmNsb3Nlc3QoJ2xpLmRyb3Bkb3duJylcbiAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgIH1cblxuICAgIGFjdGl2ZS50cmlnZ2VyKCdhY3RpdmF0ZS5icy5zY3JvbGxzcHknKVxuICB9XG5cbiAgU2Nyb2xsU3B5LnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAkKHRoaXMuc2VsZWN0b3IpXG4gICAgICAucGFyZW50c1VudGlsKHRoaXMub3B0aW9ucy50YXJnZXQsICcuYWN0aXZlJylcbiAgICAgIC5yZW1vdmVDbGFzcygnYWN0aXZlJylcbiAgfVxuXG5cbiAgLy8gU0NST0xMU1BZIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGZ1bmN0aW9uIFBsdWdpbihvcHRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkdGhpcyAgID0gJCh0aGlzKVxuICAgICAgdmFyIGRhdGEgICAgPSAkdGhpcy5kYXRhKCdicy5zY3JvbGxzcHknKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLnNjcm9sbHNweScsIChkYXRhID0gbmV3IFNjcm9sbFNweSh0aGlzLCBvcHRpb25zKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4uc2Nyb2xsc3B5XG5cbiAgJC5mbi5zY3JvbGxzcHkgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi5zY3JvbGxzcHkuQ29uc3RydWN0b3IgPSBTY3JvbGxTcHlcblxuXG4gIC8vIFNDUk9MTFNQWSBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cblxuICAkLmZuLnNjcm9sbHNweS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uc2Nyb2xsc3B5ID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gU0NST0xMU1BZIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PT09PT09PVxuXG4gICQod2luZG93KS5vbignbG9hZC5icy5zY3JvbGxzcHkuZGF0YS1hcGknLCBmdW5jdGlvbiAoKSB7XG4gICAgJCgnW2RhdGEtc3B5PVwic2Nyb2xsXCJdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHNweSA9ICQodGhpcylcbiAgICAgIFBsdWdpbi5jYWxsKCRzcHksICRzcHkuZGF0YSgpKVxuICAgIH0pXG4gIH0pXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy9zY3JvbGxzcHkuanNcbi8vIG1vZHVsZSBpZCA9IDEyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiB0YWIuanMgdjMuMy43XG4gKiBodHRwOi8vZ2V0Ym9vdHN0cmFwLmNvbS9qYXZhc2NyaXB0LyN0YWJzXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVEFCIENMQVNTIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT1cblxuICB2YXIgVGFiID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAvLyBqc2NzOmRpc2FibGUgcmVxdWlyZURvbGxhckJlZm9yZWpRdWVyeUFzc2lnbm1lbnRcbiAgICB0aGlzLmVsZW1lbnQgPSAkKGVsZW1lbnQpXG4gICAgLy8ganNjczplbmFibGUgcmVxdWlyZURvbGxhckJlZm9yZWpRdWVyeUFzc2lnbm1lbnRcbiAgfVxuXG4gIFRhYi5WRVJTSU9OID0gJzMuMy43J1xuXG4gIFRhYi5UUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwXG5cbiAgVGFiLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkdGhpcyAgICA9IHRoaXMuZWxlbWVudFxuICAgIHZhciAkdWwgICAgICA9ICR0aGlzLmNsb3Nlc3QoJ3VsOm5vdCguZHJvcGRvd24tbWVudSknKVxuICAgIHZhciBzZWxlY3RvciA9ICR0aGlzLmRhdGEoJ3RhcmdldCcpXG5cbiAgICBpZiAoIXNlbGVjdG9yKSB7XG4gICAgICBzZWxlY3RvciA9ICR0aGlzLmF0dHIoJ2hyZWYnKVxuICAgICAgc2VsZWN0b3IgPSBzZWxlY3RvciAmJiBzZWxlY3Rvci5yZXBsYWNlKC8uKig/PSNbXlxcc10qJCkvLCAnJykgLy8gc3RyaXAgZm9yIGllN1xuICAgIH1cblxuICAgIGlmICgkdGhpcy5wYXJlbnQoJ2xpJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKSByZXR1cm5cblxuICAgIHZhciAkcHJldmlvdXMgPSAkdWwuZmluZCgnLmFjdGl2ZTpsYXN0IGEnKVxuICAgIHZhciBoaWRlRXZlbnQgPSAkLkV2ZW50KCdoaWRlLmJzLnRhYicsIHtcbiAgICAgIHJlbGF0ZWRUYXJnZXQ6ICR0aGlzWzBdXG4gICAgfSlcbiAgICB2YXIgc2hvd0V2ZW50ID0gJC5FdmVudCgnc2hvdy5icy50YWInLCB7XG4gICAgICByZWxhdGVkVGFyZ2V0OiAkcHJldmlvdXNbMF1cbiAgICB9KVxuXG4gICAgJHByZXZpb3VzLnRyaWdnZXIoaGlkZUV2ZW50KVxuICAgICR0aGlzLnRyaWdnZXIoc2hvd0V2ZW50KVxuXG4gICAgaWYgKHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSB8fCBoaWRlRXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgdmFyICR0YXJnZXQgPSAkKHNlbGVjdG9yKVxuXG4gICAgdGhpcy5hY3RpdmF0ZSgkdGhpcy5jbG9zZXN0KCdsaScpLCAkdWwpXG4gICAgdGhpcy5hY3RpdmF0ZSgkdGFyZ2V0LCAkdGFyZ2V0LnBhcmVudCgpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAkcHJldmlvdXMudHJpZ2dlcih7XG4gICAgICAgIHR5cGU6ICdoaWRkZW4uYnMudGFiJyxcbiAgICAgICAgcmVsYXRlZFRhcmdldDogJHRoaXNbMF1cbiAgICAgIH0pXG4gICAgICAkdGhpcy50cmlnZ2VyKHtcbiAgICAgICAgdHlwZTogJ3Nob3duLmJzLnRhYicsXG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6ICRwcmV2aW91c1swXVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgVGFiLnByb3RvdHlwZS5hY3RpdmF0ZSA9IGZ1bmN0aW9uIChlbGVtZW50LCBjb250YWluZXIsIGNhbGxiYWNrKSB7XG4gICAgdmFyICRhY3RpdmUgICAgPSBjb250YWluZXIuZmluZCgnPiAuYWN0aXZlJylcbiAgICB2YXIgdHJhbnNpdGlvbiA9IGNhbGxiYWNrXG4gICAgICAmJiAkLnN1cHBvcnQudHJhbnNpdGlvblxuICAgICAgJiYgKCRhY3RpdmUubGVuZ3RoICYmICRhY3RpdmUuaGFzQ2xhc3MoJ2ZhZGUnKSB8fCAhIWNvbnRhaW5lci5maW5kKCc+IC5mYWRlJykubGVuZ3RoKVxuXG4gICAgZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgICRhY3RpdmVcbiAgICAgICAgLnJlbW92ZUNsYXNzKCdhY3RpdmUnKVxuICAgICAgICAuZmluZCgnPiAuZHJvcGRvd24tbWVudSA+IC5hY3RpdmUnKVxuICAgICAgICAgIC5yZW1vdmVDbGFzcygnYWN0aXZlJylcbiAgICAgICAgLmVuZCgpXG4gICAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKVxuICAgICAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgZmFsc2UpXG5cbiAgICAgIGVsZW1lbnRcbiAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAuZmluZCgnW2RhdGEtdG9nZ2xlPVwidGFiXCJdJylcbiAgICAgICAgICAuYXR0cignYXJpYS1leHBhbmRlZCcsIHRydWUpXG5cbiAgICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICAgIGVsZW1lbnRbMF0ub2Zmc2V0V2lkdGggLy8gcmVmbG93IGZvciB0cmFuc2l0aW9uXG4gICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoJ2luJylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ2ZhZGUnKVxuICAgICAgfVxuXG4gICAgICBpZiAoZWxlbWVudC5wYXJlbnQoJy5kcm9wZG93bi1tZW51JykubGVuZ3RoKSB7XG4gICAgICAgIGVsZW1lbnRcbiAgICAgICAgICAuY2xvc2VzdCgnbGkuZHJvcGRvd24nKVxuICAgICAgICAgICAgLmFkZENsYXNzKCdhY3RpdmUnKVxuICAgICAgICAgIC5lbmQoKVxuICAgICAgICAgIC5maW5kKCdbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKVxuICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKVxuICAgICAgfVxuXG4gICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpXG4gICAgfVxuXG4gICAgJGFjdGl2ZS5sZW5ndGggJiYgdHJhbnNpdGlvbiA/XG4gICAgICAkYWN0aXZlXG4gICAgICAgIC5vbmUoJ2JzVHJhbnNpdGlvbkVuZCcsIG5leHQpXG4gICAgICAgIC5lbXVsYXRlVHJhbnNpdGlvbkVuZChUYWIuVFJBTlNJVElPTl9EVVJBVElPTikgOlxuICAgICAgbmV4dCgpXG5cbiAgICAkYWN0aXZlLnJlbW92ZUNsYXNzKCdpbicpXG4gIH1cblxuXG4gIC8vIFRBQiBQTFVHSU4gREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSAgPSAkdGhpcy5kYXRhKCdicy50YWInKVxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLnRhYicsIChkYXRhID0gbmV3IFRhYih0aGlzKSkpXG4gICAgICBpZiAodHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJykgZGF0YVtvcHRpb25dKClcbiAgICB9KVxuICB9XG5cbiAgdmFyIG9sZCA9ICQuZm4udGFiXG5cbiAgJC5mbi50YWIgICAgICAgICAgICAgPSBQbHVnaW5cbiAgJC5mbi50YWIuQ29uc3RydWN0b3IgPSBUYWJcblxuXG4gIC8vIFRBQiBOTyBDT05GTElDVFxuICAvLyA9PT09PT09PT09PT09PT1cblxuICAkLmZuLnRhYi5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4udGFiID0gb2xkXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG5cbiAgLy8gVEFCIERBVEEtQVBJXG4gIC8vID09PT09PT09PT09PVxuXG4gIHZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKVxuICAgIFBsdWdpbi5jYWxsKCQodGhpcyksICdzaG93JylcbiAgfVxuXG4gICQoZG9jdW1lbnQpXG4gICAgLm9uKCdjbGljay5icy50YWIuZGF0YS1hcGknLCAnW2RhdGEtdG9nZ2xlPVwidGFiXCJdJywgY2xpY2tIYW5kbGVyKVxuICAgIC5vbignY2xpY2suYnMudGFiLmRhdGEtYXBpJywgJ1tkYXRhLXRvZ2dsZT1cInBpbGxcIl0nLCBjbGlja0hhbmRsZXIpXG5cbn0oalF1ZXJ5KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC9qcy90YWIuanNcbi8vIG1vZHVsZSBpZCA9IDEzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwOiBhZmZpeC5qcyB2My4zLjdcbiAqIGh0dHA6Ly9nZXRib290c3RyYXAuY29tL2phdmFzY3JpcHQvI2FmZml4XG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHlyaWdodCAyMDExLTIwMTYgVHdpdHRlciwgSW5jLlxuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG5cbitmdW5jdGlvbiAoJCkge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gQUZGSVggQ0xBU1MgREVGSU5JVElPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09XG5cbiAgdmFyIEFmZml4ID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgQWZmaXguREVGQVVMVFMsIG9wdGlvbnMpXG5cbiAgICB0aGlzLiR0YXJnZXQgPSAkKHRoaXMub3B0aW9ucy50YXJnZXQpXG4gICAgICAub24oJ3Njcm9sbC5icy5hZmZpeC5kYXRhLWFwaScsICQucHJveHkodGhpcy5jaGVja1Bvc2l0aW9uLCB0aGlzKSlcbiAgICAgIC5vbignY2xpY2suYnMuYWZmaXguZGF0YS1hcGknLCAgJC5wcm94eSh0aGlzLmNoZWNrUG9zaXRpb25XaXRoRXZlbnRMb29wLCB0aGlzKSlcblxuICAgIHRoaXMuJGVsZW1lbnQgICAgID0gJChlbGVtZW50KVxuICAgIHRoaXMuYWZmaXhlZCAgICAgID0gbnVsbFxuICAgIHRoaXMudW5waW4gICAgICAgID0gbnVsbFxuICAgIHRoaXMucGlubmVkT2Zmc2V0ID0gbnVsbFxuXG4gICAgdGhpcy5jaGVja1Bvc2l0aW9uKClcbiAgfVxuXG4gIEFmZml4LlZFUlNJT04gID0gJzMuMy43J1xuXG4gIEFmZml4LlJFU0VUICAgID0gJ2FmZml4IGFmZml4LXRvcCBhZmZpeC1ib3R0b20nXG5cbiAgQWZmaXguREVGQVVMVFMgPSB7XG4gICAgb2Zmc2V0OiAwLFxuICAgIHRhcmdldDogd2luZG93XG4gIH1cblxuICBBZmZpeC5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoc2Nyb2xsSGVpZ2h0LCBoZWlnaHQsIG9mZnNldFRvcCwgb2Zmc2V0Qm90dG9tKSB7XG4gICAgdmFyIHNjcm9sbFRvcCAgICA9IHRoaXMuJHRhcmdldC5zY3JvbGxUb3AoKVxuICAgIHZhciBwb3NpdGlvbiAgICAgPSB0aGlzLiRlbGVtZW50Lm9mZnNldCgpXG4gICAgdmFyIHRhcmdldEhlaWdodCA9IHRoaXMuJHRhcmdldC5oZWlnaHQoKVxuXG4gICAgaWYgKG9mZnNldFRvcCAhPSBudWxsICYmIHRoaXMuYWZmaXhlZCA9PSAndG9wJykgcmV0dXJuIHNjcm9sbFRvcCA8IG9mZnNldFRvcCA/ICd0b3AnIDogZmFsc2VcblxuICAgIGlmICh0aGlzLmFmZml4ZWQgPT0gJ2JvdHRvbScpIHtcbiAgICAgIGlmIChvZmZzZXRUb3AgIT0gbnVsbCkgcmV0dXJuIChzY3JvbGxUb3AgKyB0aGlzLnVucGluIDw9IHBvc2l0aW9uLnRvcCkgPyBmYWxzZSA6ICdib3R0b20nXG4gICAgICByZXR1cm4gKHNjcm9sbFRvcCArIHRhcmdldEhlaWdodCA8PSBzY3JvbGxIZWlnaHQgLSBvZmZzZXRCb3R0b20pID8gZmFsc2UgOiAnYm90dG9tJ1xuICAgIH1cblxuICAgIHZhciBpbml0aWFsaXppbmcgICA9IHRoaXMuYWZmaXhlZCA9PSBudWxsXG4gICAgdmFyIGNvbGxpZGVyVG9wICAgID0gaW5pdGlhbGl6aW5nID8gc2Nyb2xsVG9wIDogcG9zaXRpb24udG9wXG4gICAgdmFyIGNvbGxpZGVySGVpZ2h0ID0gaW5pdGlhbGl6aW5nID8gdGFyZ2V0SGVpZ2h0IDogaGVpZ2h0XG5cbiAgICBpZiAob2Zmc2V0VG9wICE9IG51bGwgJiYgc2Nyb2xsVG9wIDw9IG9mZnNldFRvcCkgcmV0dXJuICd0b3AnXG4gICAgaWYgKG9mZnNldEJvdHRvbSAhPSBudWxsICYmIChjb2xsaWRlclRvcCArIGNvbGxpZGVySGVpZ2h0ID49IHNjcm9sbEhlaWdodCAtIG9mZnNldEJvdHRvbSkpIHJldHVybiAnYm90dG9tJ1xuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBBZmZpeC5wcm90b3R5cGUuZ2V0UGlubmVkT2Zmc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnBpbm5lZE9mZnNldCkgcmV0dXJuIHRoaXMucGlubmVkT2Zmc2V0XG4gICAgdGhpcy4kZWxlbWVudC5yZW1vdmVDbGFzcyhBZmZpeC5SRVNFVCkuYWRkQ2xhc3MoJ2FmZml4JylcbiAgICB2YXIgc2Nyb2xsVG9wID0gdGhpcy4kdGFyZ2V0LnNjcm9sbFRvcCgpXG4gICAgdmFyIHBvc2l0aW9uICA9IHRoaXMuJGVsZW1lbnQub2Zmc2V0KClcbiAgICByZXR1cm4gKHRoaXMucGlubmVkT2Zmc2V0ID0gcG9zaXRpb24udG9wIC0gc2Nyb2xsVG9wKVxuICB9XG5cbiAgQWZmaXgucHJvdG90eXBlLmNoZWNrUG9zaXRpb25XaXRoRXZlbnRMb29wID0gZnVuY3Rpb24gKCkge1xuICAgIHNldFRpbWVvdXQoJC5wcm94eSh0aGlzLmNoZWNrUG9zaXRpb24sIHRoaXMpLCAxKVxuICB9XG5cbiAgQWZmaXgucHJvdG90eXBlLmNoZWNrUG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLiRlbGVtZW50LmlzKCc6dmlzaWJsZScpKSByZXR1cm5cblxuICAgIHZhciBoZWlnaHQgICAgICAgPSB0aGlzLiRlbGVtZW50LmhlaWdodCgpXG4gICAgdmFyIG9mZnNldCAgICAgICA9IHRoaXMub3B0aW9ucy5vZmZzZXRcbiAgICB2YXIgb2Zmc2V0VG9wICAgID0gb2Zmc2V0LnRvcFxuICAgIHZhciBvZmZzZXRCb3R0b20gPSBvZmZzZXQuYm90dG9tXG4gICAgdmFyIHNjcm9sbEhlaWdodCA9IE1hdGgubWF4KCQoZG9jdW1lbnQpLmhlaWdodCgpLCAkKGRvY3VtZW50LmJvZHkpLmhlaWdodCgpKVxuXG4gICAgaWYgKHR5cGVvZiBvZmZzZXQgIT0gJ29iamVjdCcpICAgICAgICAgb2Zmc2V0Qm90dG9tID0gb2Zmc2V0VG9wID0gb2Zmc2V0XG4gICAgaWYgKHR5cGVvZiBvZmZzZXRUb3AgPT0gJ2Z1bmN0aW9uJykgICAgb2Zmc2V0VG9wICAgID0gb2Zmc2V0LnRvcCh0aGlzLiRlbGVtZW50KVxuICAgIGlmICh0eXBlb2Ygb2Zmc2V0Qm90dG9tID09ICdmdW5jdGlvbicpIG9mZnNldEJvdHRvbSA9IG9mZnNldC5ib3R0b20odGhpcy4kZWxlbWVudClcblxuICAgIHZhciBhZmZpeCA9IHRoaXMuZ2V0U3RhdGUoc2Nyb2xsSGVpZ2h0LCBoZWlnaHQsIG9mZnNldFRvcCwgb2Zmc2V0Qm90dG9tKVxuXG4gICAgaWYgKHRoaXMuYWZmaXhlZCAhPSBhZmZpeCkge1xuICAgICAgaWYgKHRoaXMudW5waW4gIT0gbnVsbCkgdGhpcy4kZWxlbWVudC5jc3MoJ3RvcCcsICcnKVxuXG4gICAgICB2YXIgYWZmaXhUeXBlID0gJ2FmZml4JyArIChhZmZpeCA/ICctJyArIGFmZml4IDogJycpXG4gICAgICB2YXIgZSAgICAgICAgID0gJC5FdmVudChhZmZpeFR5cGUgKyAnLmJzLmFmZml4JylcblxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKGUpXG5cbiAgICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSByZXR1cm5cblxuICAgICAgdGhpcy5hZmZpeGVkID0gYWZmaXhcbiAgICAgIHRoaXMudW5waW4gPSBhZmZpeCA9PSAnYm90dG9tJyA/IHRoaXMuZ2V0UGlubmVkT2Zmc2V0KCkgOiBudWxsXG5cbiAgICAgIHRoaXMuJGVsZW1lbnRcbiAgICAgICAgLnJlbW92ZUNsYXNzKEFmZml4LlJFU0VUKVxuICAgICAgICAuYWRkQ2xhc3MoYWZmaXhUeXBlKVxuICAgICAgICAudHJpZ2dlcihhZmZpeFR5cGUucmVwbGFjZSgnYWZmaXgnLCAnYWZmaXhlZCcpICsgJy5icy5hZmZpeCcpXG4gICAgfVxuXG4gICAgaWYgKGFmZml4ID09ICdib3R0b20nKSB7XG4gICAgICB0aGlzLiRlbGVtZW50Lm9mZnNldCh7XG4gICAgICAgIHRvcDogc2Nyb2xsSGVpZ2h0IC0gaGVpZ2h0IC0gb2Zmc2V0Qm90dG9tXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG5cbiAgLy8gQUZGSVggUExVR0lOIERFRklOSVRJT05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuICBmdW5jdGlvbiBQbHVnaW4ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgICA9ICQodGhpcylcbiAgICAgIHZhciBkYXRhICAgID0gJHRoaXMuZGF0YSgnYnMuYWZmaXgnKVxuICAgICAgdmFyIG9wdGlvbnMgPSB0eXBlb2Ygb3B0aW9uID09ICdvYmplY3QnICYmIG9wdGlvblxuXG4gICAgICBpZiAoIWRhdGEpICR0aGlzLmRhdGEoJ2JzLmFmZml4JywgKGRhdGEgPSBuZXcgQWZmaXgodGhpcywgb3B0aW9ucykpKVxuICAgICAgaWYgKHR5cGVvZiBvcHRpb24gPT0gJ3N0cmluZycpIGRhdGFbb3B0aW9uXSgpXG4gICAgfSlcbiAgfVxuXG4gIHZhciBvbGQgPSAkLmZuLmFmZml4XG5cbiAgJC5mbi5hZmZpeCAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLmFmZml4LkNvbnN0cnVjdG9yID0gQWZmaXhcblxuXG4gIC8vIEFGRklYIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09XG5cbiAgJC5mbi5hZmZpeC5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQuZm4uYWZmaXggPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBBRkZJWCBEQVRBLUFQSVxuICAvLyA9PT09PT09PT09PT09PVxuXG4gICQod2luZG93KS5vbignbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAkKCdbZGF0YS1zcHk9XCJhZmZpeFwiXScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICRzcHkgPSAkKHRoaXMpXG4gICAgICB2YXIgZGF0YSA9ICRzcHkuZGF0YSgpXG5cbiAgICAgIGRhdGEub2Zmc2V0ID0gZGF0YS5vZmZzZXQgfHwge31cblxuICAgICAgaWYgKGRhdGEub2Zmc2V0Qm90dG9tICE9IG51bGwpIGRhdGEub2Zmc2V0LmJvdHRvbSA9IGRhdGEub2Zmc2V0Qm90dG9tXG4gICAgICBpZiAoZGF0YS5vZmZzZXRUb3AgICAgIT0gbnVsbCkgZGF0YS5vZmZzZXQudG9wICAgID0gZGF0YS5vZmZzZXRUb3BcblxuICAgICAgUGx1Z2luLmNhbGwoJHNweSwgZGF0YSlcbiAgICB9KVxuICB9KVxuXG59KGpRdWVyeSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvanMvYWZmaXguanNcbi8vIG1vZHVsZSBpZCA9IDE0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxyXG4gKiBCb290c3RyYXAtc2VsZWN0IHYxLjEyLjQgKGh0dHA6Ly9zaWx2aW9tb3JldG8uZ2l0aHViLmlvL2Jvb3RzdHJhcC1zZWxlY3QpXHJcbiAqXHJcbiAqIENvcHlyaWdodCAyMDEzLTIwMTcgYm9vdHN0cmFwLXNlbGVjdFxyXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS9zaWx2aW9tb3JldG8vYm9vdHN0cmFwLXNlbGVjdC9ibG9iL21hc3Rlci9MSUNFTlNFKVxyXG4gKi9cclxuXHJcbihmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHVubGVzcyBhbWRNb2R1bGVJZCBpcyBzZXRcbiAgICBkZWZpbmUoW1wianF1ZXJ5XCJdLCBmdW5jdGlvbiAoYTApIHtcbiAgICAgIHJldHVybiAoZmFjdG9yeShhMCkpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgLy8gTm9kZS4gRG9lcyBub3Qgd29yayB3aXRoIHN0cmljdCBDb21tb25KUywgYnV0XG4gICAgLy8gb25seSBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB0aGF0IHN1cHBvcnQgbW9kdWxlLmV4cG9ydHMsXG4gICAgLy8gbGlrZSBOb2RlLlxuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwianF1ZXJ5XCIpKTtcbiAgfSBlbHNlIHtcbiAgICBmYWN0b3J5KHJvb3RbXCJqUXVlcnlcIl0pO1xuICB9XG59KHRoaXMsIGZ1bmN0aW9uIChqUXVlcnkpIHtcblxuKGZ1bmN0aW9uICgkKSB7XHJcbiAgJ3VzZSBzdHJpY3QnO1xyXG5cclxuICAvLzxlZGl0b3ItZm9sZCBkZXNjPVwiU2hpbXNcIj5cclxuICBpZiAoIVN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMpIHtcclxuICAgIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICd1c2Ugc3RyaWN0JzsgLy8gbmVlZGVkIHRvIHN1cHBvcnQgYGFwcGx5YC9gY2FsbGAgd2l0aCBgdW5kZWZpbmVkYC9gbnVsbGBcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIGluZGV4T2YgPSAnJy5pbmRleE9mO1xyXG4gICAgICB2YXIgaW5jbHVkZXMgPSBmdW5jdGlvbiAoc2VhcmNoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHRoaXMpO1xyXG4gICAgICAgIGlmIChzZWFyY2ggJiYgdG9TdHJpbmcuY2FsbChzZWFyY2gpID09ICdbb2JqZWN0IFJlZ0V4cF0nKSB7XHJcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xyXG4gICAgICAgIHZhciBzZWFyY2hTdHJpbmcgPSBTdHJpbmcoc2VhcmNoKTtcclxuICAgICAgICB2YXIgc2VhcmNoTGVuZ3RoID0gc2VhcmNoU3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgcG9zaXRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAvLyBgVG9JbnRlZ2VyYFxyXG4gICAgICAgIHZhciBwb3MgPSBwb3NpdGlvbiA/IE51bWJlcihwb3NpdGlvbikgOiAwO1xyXG4gICAgICAgIGlmIChwb3MgIT0gcG9zKSB7IC8vIGJldHRlciBgaXNOYU5gXHJcbiAgICAgICAgICBwb3MgPSAwO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBNYXRoLm1pbihNYXRoLm1heChwb3MsIDApLCBzdHJpbmdMZW5ndGgpO1xyXG4gICAgICAgIC8vIEF2b2lkIHRoZSBgaW5kZXhPZmAgY2FsbCBpZiBubyBtYXRjaCBpcyBwb3NzaWJsZVxyXG4gICAgICAgIGlmIChzZWFyY2hMZW5ndGggKyBzdGFydCA+IHN0cmluZ0xlbmd0aCkge1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaW5kZXhPZi5jYWxsKHN0cmluZywgc2VhcmNoU3RyaW5nLCBwb3MpICE9IC0xO1xyXG4gICAgICB9O1xyXG4gICAgICBpZiAoZGVmaW5lUHJvcGVydHkpIHtcclxuICAgICAgICBkZWZpbmVQcm9wZXJ0eShTdHJpbmcucHJvdG90eXBlLCAnaW5jbHVkZXMnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBpbmNsdWRlcyxcclxuICAgICAgICAgICdjb25maWd1cmFibGUnOiB0cnVlLFxyXG4gICAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIFN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMgPSBpbmNsdWRlcztcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoKSB7XHJcbiAgICAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAndXNlIHN0cmljdCc7IC8vIG5lZWRlZCB0byBzdXBwb3J0IGBhcHBseWAvYGNhbGxgIHdpdGggYHVuZGVmaW5lZGAvYG51bGxgXHJcbiAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gSUUgOCBvbmx5IHN1cHBvcnRzIGBPYmplY3QuZGVmaW5lUHJvcGVydHlgIG9uIERPTSBlbGVtZW50c1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XHJcbiAgICAgICAgICB2YXIgJGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5O1xyXG4gICAgICAgICAgdmFyIHJlc3VsdCA9ICRkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG9iamVjdCwgb2JqZWN0KSAmJiAkZGVmaW5lUHJvcGVydHk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfSgpKTtcclxuICAgICAgdmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XHJcbiAgICAgIHZhciBzdGFydHNXaXRoID0gZnVuY3Rpb24gKHNlYXJjaCkge1xyXG4gICAgICAgIGlmICh0aGlzID09IG51bGwpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0cmluZyA9IFN0cmluZyh0aGlzKTtcclxuICAgICAgICBpZiAoc2VhcmNoICYmIHRvU3RyaW5nLmNhbGwoc2VhcmNoKSA9PSAnW29iamVjdCBSZWdFeHBdJykge1xyXG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RyaW5nTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcclxuICAgICAgICB2YXIgc2VhcmNoU3RyaW5nID0gU3RyaW5nKHNlYXJjaCk7XHJcbiAgICAgICAgdmFyIHNlYXJjaExlbmd0aCA9IHNlYXJjaFN0cmluZy5sZW5ndGg7XHJcbiAgICAgICAgdmFyIHBvc2l0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgLy8gYFRvSW50ZWdlcmBcclxuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPyBOdW1iZXIocG9zaXRpb24pIDogMDtcclxuICAgICAgICBpZiAocG9zICE9IHBvcykgeyAvLyBiZXR0ZXIgYGlzTmFOYFxyXG4gICAgICAgICAgcG9zID0gMDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5taW4oTWF0aC5tYXgocG9zLCAwKSwgc3RyaW5nTGVuZ3RoKTtcclxuICAgICAgICAvLyBBdm9pZCB0aGUgYGluZGV4T2ZgIGNhbGwgaWYgbm8gbWF0Y2ggaXMgcG9zc2libGVcclxuICAgICAgICBpZiAoc2VhcmNoTGVuZ3RoICsgc3RhcnQgPiBzdHJpbmdMZW5ndGgpIHtcclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGluZGV4ID0gLTE7XHJcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzZWFyY2hMZW5ndGgpIHtcclxuICAgICAgICAgIGlmIChzdHJpbmcuY2hhckNvZGVBdChzdGFydCArIGluZGV4KSAhPSBzZWFyY2hTdHJpbmcuY2hhckNvZGVBdChpbmRleCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfTtcclxuICAgICAgaWYgKGRlZmluZVByb3BlcnR5KSB7XHJcbiAgICAgICAgZGVmaW5lUHJvcGVydHkoU3RyaW5nLnByb3RvdHlwZSwgJ3N0YXJ0c1dpdGgnLCB7XHJcbiAgICAgICAgICAndmFsdWUnOiBzdGFydHNXaXRoLFxyXG4gICAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXHJcbiAgICAgICAgICAnd3JpdGFibGUnOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgU3RyaW5nLnByb3RvdHlwZS5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcclxuICAgICAgfVxyXG4gICAgfSgpKTtcclxuICB9XHJcblxyXG4gIGlmICghT2JqZWN0LmtleXMpIHtcclxuICAgIE9iamVjdC5rZXlzID0gZnVuY3Rpb24gKFxyXG4gICAgICBvLCAvLyBvYmplY3RcclxuICAgICAgaywgLy8ga2V5XHJcbiAgICAgIHIgIC8vIHJlc3VsdCBhcnJheVxyXG4gICAgICApe1xyXG4gICAgICAvLyBpbml0aWFsaXplIG9iamVjdCBhbmQgcmVzdWx0XHJcbiAgICAgIHI9W107XHJcbiAgICAgIC8vIGl0ZXJhdGUgb3ZlciBvYmplY3Qga2V5c1xyXG4gICAgICBmb3IgKGsgaW4gbylcclxuICAgICAgICAgIC8vIGZpbGwgcmVzdWx0IGFycmF5IHdpdGggbm9uLXByb3RvdHlwaWNhbCBrZXlzXHJcbiAgICAgICAgci5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspICYmIHIucHVzaChrKTtcclxuICAgICAgLy8gcmV0dXJuIHJlc3VsdFxyXG4gICAgICByZXR1cm4gcjtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBzZXQgZGF0YS1zZWxlY3RlZCBvbiBzZWxlY3QgZWxlbWVudCBpZiB0aGUgdmFsdWUgaGFzIGJlZW4gcHJvZ3JhbW1hdGljYWxseSBzZWxlY3RlZFxyXG4gIC8vIHByaW9yIHRvIGluaXRpYWxpemF0aW9uIG9mIGJvb3RzdHJhcC1zZWxlY3RcclxuICAvLyAqIGNvbnNpZGVyIHJlbW92aW5nIG9yIHJlcGxhY2luZyBhbiBhbHRlcm5hdGl2ZSBtZXRob2QgKlxyXG4gIHZhciB2YWxIb29rcyA9IHtcclxuICAgIHVzZURlZmF1bHQ6IGZhbHNlLFxyXG4gICAgX3NldDogJC52YWxIb29rcy5zZWxlY3Quc2V0XHJcbiAgfTtcclxuXHJcbiAgJC52YWxIb29rcy5zZWxlY3Quc2V0ID0gZnVuY3Rpb24oZWxlbSwgdmFsdWUpIHtcclxuICAgIGlmICh2YWx1ZSAmJiAhdmFsSG9va3MudXNlRGVmYXVsdCkgJChlbGVtKS5kYXRhKCdzZWxlY3RlZCcsIHRydWUpO1xyXG5cclxuICAgIHJldHVybiB2YWxIb29rcy5fc2V0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgfTtcclxuXHJcbiAgdmFyIGNoYW5nZWRfYXJndW1lbnRzID0gbnVsbDtcclxuXHJcbiAgdmFyIEV2ZW50SXNTdXBwb3J0ZWQgPSAoZnVuY3Rpb24oKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBuZXcgRXZlbnQoJ2NoYW5nZScpO1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH0pKCk7XHJcblxyXG4gICQuZm4udHJpZ2dlck5hdGl2ZSA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgIHZhciBlbCA9IHRoaXNbMF0sXHJcbiAgICAgICAgZXZlbnQ7XHJcblxyXG4gICAgaWYgKGVsLmRpc3BhdGNoRXZlbnQpIHsgLy8gZm9yIG1vZGVybiBicm93c2VycyAmIElFOStcclxuICAgICAgaWYgKEV2ZW50SXNTdXBwb3J0ZWQpIHtcclxuICAgICAgICAvLyBGb3IgbW9kZXJuIGJyb3dzZXJzXHJcbiAgICAgICAgZXZlbnQgPSBuZXcgRXZlbnQoZXZlbnROYW1lLCB7XHJcbiAgICAgICAgICBidWJibGVzOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gRm9yIElFIHNpbmNlIGl0IGRvZXNuJ3Qgc3VwcG9ydCBFdmVudCBjb25zdHJ1Y3RvclxyXG4gICAgICAgIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XHJcbiAgICAgICAgZXZlbnQuaW5pdEV2ZW50KGV2ZW50TmFtZSwgdHJ1ZSwgZmFsc2UpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBlbC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcclxuICAgIH0gZWxzZSBpZiAoZWwuZmlyZUV2ZW50KSB7IC8vIGZvciBJRThcclxuICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudE9iamVjdCgpO1xyXG4gICAgICBldmVudC5ldmVudFR5cGUgPSBldmVudE5hbWU7XHJcbiAgICAgIGVsLmZpcmVFdmVudCgnb24nICsgZXZlbnROYW1lLCBldmVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBmYWxsIGJhY2sgdG8galF1ZXJ5LnRyaWdnZXJcclxuICAgICAgdGhpcy50cmlnZ2VyKGV2ZW50TmFtZSk7XHJcbiAgICB9XHJcbiAgfTtcclxuICAvLzwvZWRpdG9yLWZvbGQ+XHJcblxyXG4gIC8vIENhc2UgaW5zZW5zaXRpdmUgY29udGFpbnMgc2VhcmNoXHJcbiAgJC5leHByLnBzZXVkb3MuaWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suaW5jbHVkZXMobWV0YVszXS50b1VwcGVyQ2FzZSgpKTtcclxuICB9O1xyXG5cclxuICAvLyBDYXNlIGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5pYmVnaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmoudGV4dCgpKS50b1N0cmluZygpLnRvVXBwZXJDYXNlKCk7XHJcbiAgICByZXR1cm4gaGF5c3RhY2suc3RhcnRzV2l0aChtZXRhWzNdLnRvVXBwZXJDYXNlKCkpO1xyXG4gIH07XHJcblxyXG4gIC8vIENhc2UgYW5kIGFjY2VudCBpbnNlbnNpdGl2ZSBjb250YWlucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWNvbnRhaW5zID0gZnVuY3Rpb24gKG9iaiwgaW5kZXgsIG1ldGEpIHtcclxuICAgIHZhciAkb2JqID0gJChvYmopLmZpbmQoJ2EnKTtcclxuICAgIHZhciBoYXlzdGFjayA9ICgkb2JqLmRhdGEoJ3Rva2VucycpIHx8ICRvYmouZGF0YSgnbm9ybWFsaXplZFRleHQnKSB8fCAkb2JqLnRleHQoKSkudG9TdHJpbmcoKS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgcmV0dXJuIGhheXN0YWNrLmluY2x1ZGVzKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ2FzZSBhbmQgYWNjZW50IGluc2Vuc2l0aXZlIGJlZ2lucyBzZWFyY2hcclxuICAkLmV4cHIucHNldWRvcy5haWJlZ2lucyA9IGZ1bmN0aW9uIChvYmosIGluZGV4LCBtZXRhKSB7XHJcbiAgICB2YXIgJG9iaiA9ICQob2JqKS5maW5kKCdhJyk7XHJcbiAgICB2YXIgaGF5c3RhY2sgPSAoJG9iai5kYXRhKCd0b2tlbnMnKSB8fCAkb2JqLmRhdGEoJ25vcm1hbGl6ZWRUZXh0JykgfHwgJG9iai50ZXh0KCkpLnRvU3RyaW5nKCkudG9VcHBlckNhc2UoKTtcclxuICAgIHJldHVybiBoYXlzdGFjay5zdGFydHNXaXRoKG1ldGFbM10udG9VcHBlckNhc2UoKSk7XHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFsbCBkaWF0cmljcyBmcm9tIHRoZSBnaXZlbiB0ZXh0LlxyXG4gICAqIEBhY2Nlc3MgcHJpdmF0ZVxyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0XHJcbiAgICogQHJldHVybnMge1N0cmluZ31cclxuICAgKi9cclxuICBmdW5jdGlvbiBub3JtYWxpemVUb0Jhc2UodGV4dCkge1xyXG4gICAgdmFyIHJFeHBzID0gW1xyXG4gICAgICB7cmU6IC9bXFx4QzAtXFx4QzZdL2csIGNoOiBcIkFcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhFMC1cXHhFNl0vZywgY2g6IFwiYVwifSxcclxuICAgICAge3JlOiAvW1xceEM4LVxceENCXS9nLCBjaDogXCJFXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RTgtXFx4RUJdL2csIGNoOiBcImVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDQy1cXHhDRl0vZywgY2g6IFwiSVwifSxcclxuICAgICAge3JlOiAvW1xceEVDLVxceEVGXS9nLCBjaDogXCJpXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RDItXFx4RDZdL2csIGNoOiBcIk9cIn0sXHJcbiAgICAgIHtyZTogL1tcXHhGMi1cXHhGNl0vZywgY2g6IFwib1wifSxcclxuICAgICAge3JlOiAvW1xceEQ5LVxceERDXS9nLCBjaDogXCJVXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjktXFx4RkNdL2csIGNoOiBcInVcIn0sXHJcbiAgICAgIHtyZTogL1tcXHhDNy1cXHhFN10vZywgY2g6IFwiY1wifSxcclxuICAgICAge3JlOiAvW1xceEQxXS9nLCBjaDogXCJOXCJ9LFxyXG4gICAgICB7cmU6IC9bXFx4RjFdL2csIGNoOiBcIm5cIn1cclxuICAgIF07XHJcbiAgICAkLmVhY2gockV4cHMsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGV4dCA9IHRleHQgPyB0ZXh0LnJlcGxhY2UodGhpcy5yZSwgdGhpcy5jaCkgOiAnJztcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHRleHQ7XHJcbiAgfVxyXG5cclxuXHJcbiAgLy8gTGlzdCBvZiBIVE1MIGVudGl0aWVzIGZvciBlc2NhcGluZy5cclxuICB2YXIgZXNjYXBlTWFwID0ge1xyXG4gICAgJyYnOiAnJmFtcDsnLFxyXG4gICAgJzwnOiAnJmx0OycsXHJcbiAgICAnPic6ICcmZ3Q7JyxcclxuICAgICdcIic6ICcmcXVvdDsnLFxyXG4gICAgXCInXCI6ICcmI3gyNzsnLFxyXG4gICAgJ2AnOiAnJiN4NjA7J1xyXG4gIH07XHJcbiAgXHJcbiAgdmFyIHVuZXNjYXBlTWFwID0ge1xyXG4gICAgJyZhbXA7JzogJyYnLFxyXG4gICAgJyZsdDsnOiAnPCcsXHJcbiAgICAnJmd0Oyc6ICc+JyxcclxuICAgICcmcXVvdDsnOiAnXCInLFxyXG4gICAgJyYjeDI3Oyc6IFwiJ1wiLFxyXG4gICAgJyYjeDYwOyc6ICdgJ1xyXG4gIH07XHJcblxyXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cclxuICB2YXIgY3JlYXRlRXNjYXBlciA9IGZ1bmN0aW9uKG1hcCkge1xyXG4gICAgdmFyIGVzY2FwZXIgPSBmdW5jdGlvbihtYXRjaCkge1xyXG4gICAgICByZXR1cm4gbWFwW21hdGNoXTtcclxuICAgIH07XHJcbiAgICAvLyBSZWdleGVzIGZvciBpZGVudGlmeWluZyBhIGtleSB0aGF0IG5lZWRzIHRvIGJlIGVzY2FwZWQuXHJcbiAgICB2YXIgc291cmNlID0gJyg/OicgKyBPYmplY3Qua2V5cyhtYXApLmpvaW4oJ3wnKSArICcpJztcclxuICAgIHZhciB0ZXN0UmVnZXhwID0gUmVnRXhwKHNvdXJjZSk7XHJcbiAgICB2YXIgcmVwbGFjZVJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UsICdnJyk7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XHJcbiAgICAgIHN0cmluZyA9IHN0cmluZyA9PSBudWxsID8gJycgOiAnJyArIHN0cmluZztcclxuICAgICAgcmV0dXJuIHRlc3RSZWdleHAudGVzdChzdHJpbmcpID8gc3RyaW5nLnJlcGxhY2UocmVwbGFjZVJlZ2V4cCwgZXNjYXBlcikgOiBzdHJpbmc7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIHZhciBodG1sRXNjYXBlID0gY3JlYXRlRXNjYXBlcihlc2NhcGVNYXApO1xyXG4gIHZhciBodG1sVW5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKHVuZXNjYXBlTWFwKTtcclxuXHJcbiAgdmFyIFNlbGVjdHBpY2tlciA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XHJcbiAgICAvLyBib290c3RyYXAtc2VsZWN0IGhhcyBiZWVuIGluaXRpYWxpemVkIC0gcmV2ZXJ0IHZhbEhvb2tzLnNlbGVjdC5zZXQgYmFjayB0byBpdHMgb3JpZ2luYWwgZnVuY3Rpb25cclxuICAgIGlmICghdmFsSG9va3MudXNlRGVmYXVsdCkge1xyXG4gICAgICAkLnZhbEhvb2tzLnNlbGVjdC5zZXQgPSB2YWxIb29rcy5fc2V0O1xyXG4gICAgICB2YWxIb29rcy51c2VEZWZhdWx0ID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLiRlbGVtZW50ID0gJChlbGVtZW50KTtcclxuICAgIHRoaXMuJG5ld0VsZW1lbnQgPSBudWxsO1xyXG4gICAgdGhpcy4kYnV0dG9uID0gbnVsbDtcclxuICAgIHRoaXMuJG1lbnUgPSBudWxsO1xyXG4gICAgdGhpcy4kbGlzID0gbnVsbDtcclxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XHJcblxyXG4gICAgLy8gSWYgd2UgaGF2ZSBubyB0aXRsZSB5ZXQsIHRyeSB0byBwdWxsIGl0IGZyb20gdGhlIGh0bWwgdGl0bGUgYXR0cmlidXRlIChqUXVlcnkgZG9lc250JyBwaWNrIGl0IHVwIGFzIGl0J3Mgbm90IGFcclxuICAgIC8vIGRhdGEtYXR0cmlidXRlKVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PT0gbnVsbCkge1xyXG4gICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9ybWF0IHdpbmRvdyBwYWRkaW5nXHJcbiAgICB2YXIgd2luUGFkID0gdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmc7XHJcbiAgICBpZiAodHlwZW9mIHdpblBhZCA9PT0gJ251bWJlcicpIHtcclxuICAgICAgdGhpcy5vcHRpb25zLndpbmRvd1BhZGRpbmcgPSBbd2luUGFkLCB3aW5QYWQsIHdpblBhZCwgd2luUGFkXTtcclxuICAgIH1cclxuXHJcbiAgICAvL0V4cG9zZSBwdWJsaWMgbWV0aG9kc1xyXG4gICAgdGhpcy52YWwgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnZhbDtcclxuICAgIHRoaXMucmVuZGVyID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW5kZXI7XHJcbiAgICB0aGlzLnJlZnJlc2ggPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnJlZnJlc2g7XHJcbiAgICB0aGlzLnNldFN0eWxlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZXRTdHlsZTtcclxuICAgIHRoaXMuc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5zZWxlY3RBbGw7XHJcbiAgICB0aGlzLmRlc2VsZWN0QWxsID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5kZXNlbGVjdEFsbDtcclxuICAgIHRoaXMuZGVzdHJveSA9IFNlbGVjdHBpY2tlci5wcm90b3R5cGUuZGVzdHJveTtcclxuICAgIHRoaXMucmVtb3ZlID0gU2VsZWN0cGlja2VyLnByb3RvdHlwZS5yZW1vdmU7XHJcbiAgICB0aGlzLnNob3cgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLnNob3c7XHJcbiAgICB0aGlzLmhpZGUgPSBTZWxlY3RwaWNrZXIucHJvdG90eXBlLmhpZGU7XHJcblxyXG4gICAgdGhpcy5pbml0KCk7XHJcbiAgfTtcclxuXHJcbiAgU2VsZWN0cGlja2VyLlZFUlNJT04gPSAnMS4xMi40JztcclxuXHJcbiAgLy8gcGFydCBvZiB0aGlzIGlzIGR1cGxpY2F0ZWQgaW4gaTE4bi9kZWZhdWx0cy1lbl9VUy5qcy4gTWFrZSBzdXJlIHRvIHVwZGF0ZSBib3RoLlxyXG4gIFNlbGVjdHBpY2tlci5ERUZBVUxUUyA9IHtcclxuICAgIG5vbmVTZWxlY3RlZFRleHQ6ICdOb3RoaW5nIHNlbGVjdGVkJyxcclxuICAgIG5vbmVSZXN1bHRzVGV4dDogJ05vIHJlc3VsdHMgbWF0Y2hlZCB7MH0nLFxyXG4gICAgY291bnRTZWxlY3RlZFRleHQ6IGZ1bmN0aW9uIChudW1TZWxlY3RlZCwgbnVtVG90YWwpIHtcclxuICAgICAgcmV0dXJuIChudW1TZWxlY3RlZCA9PSAxKSA/IFwiezB9IGl0ZW0gc2VsZWN0ZWRcIiA6IFwiezB9IGl0ZW1zIHNlbGVjdGVkXCI7XHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uc1RleHQ6IGZ1bmN0aW9uIChudW1BbGwsIG51bUdyb3VwKSB7XHJcbiAgICAgIHJldHVybiBbXHJcbiAgICAgICAgKG51bUFsbCA9PSAxKSA/ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbSBtYXgpJyA6ICdMaW1pdCByZWFjaGVkICh7bn0gaXRlbXMgbWF4KScsXHJcbiAgICAgICAgKG51bUdyb3VwID09IDEpID8gJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtIG1heCknIDogJ0dyb3VwIGxpbWl0IHJlYWNoZWQgKHtufSBpdGVtcyBtYXgpJ1xyXG4gICAgICBdO1xyXG4gICAgfSxcclxuICAgIHNlbGVjdEFsbFRleHQ6ICdTZWxlY3QgQWxsJyxcclxuICAgIGRlc2VsZWN0QWxsVGV4dDogJ0Rlc2VsZWN0IEFsbCcsXHJcbiAgICBkb25lQnV0dG9uOiBmYWxzZSxcclxuICAgIGRvbmVCdXR0b25UZXh0OiAnQ2xvc2UnLFxyXG4gICAgbXVsdGlwbGVTZXBhcmF0b3I6ICcsICcsXHJcbiAgICBzdHlsZUJhc2U6ICdidG4nLFxyXG4gICAgc3R5bGU6ICdidG4tZGVmYXVsdCcsXHJcbiAgICBzaXplOiAnYXV0bycsXHJcbiAgICB0aXRsZTogbnVsbCxcclxuICAgIHNlbGVjdGVkVGV4dEZvcm1hdDogJ3ZhbHVlcycsXHJcbiAgICB3aWR0aDogZmFsc2UsXHJcbiAgICBjb250YWluZXI6IGZhbHNlLFxyXG4gICAgaGlkZURpc2FibGVkOiBmYWxzZSxcclxuICAgIHNob3dTdWJ0ZXh0OiBmYWxzZSxcclxuICAgIHNob3dJY29uOiB0cnVlLFxyXG4gICAgc2hvd0NvbnRlbnQ6IHRydWUsXHJcbiAgICBkcm9wdXBBdXRvOiB0cnVlLFxyXG4gICAgaGVhZGVyOiBmYWxzZSxcclxuICAgIGxpdmVTZWFyY2g6IGZhbHNlLFxyXG4gICAgbGl2ZVNlYXJjaFBsYWNlaG9sZGVyOiBudWxsLFxyXG4gICAgbGl2ZVNlYXJjaE5vcm1hbGl6ZTogZmFsc2UsXHJcbiAgICBsaXZlU2VhcmNoU3R5bGU6ICdjb250YWlucycsXHJcbiAgICBhY3Rpb25zQm94OiBmYWxzZSxcclxuICAgIGljb25CYXNlOiAnZ2x5cGhpY29uJyxcclxuICAgIHRpY2tJY29uOiAnZ2x5cGhpY29uLW9rJyxcclxuICAgIHNob3dUaWNrOiBmYWxzZSxcclxuICAgIHRlbXBsYXRlOiB7XHJcbiAgICAgIGNhcmV0OiAnPHNwYW4gY2xhc3M9XCJjYXJldFwiPjwvc3Bhbj4nXHJcbiAgICB9LFxyXG4gICAgbWF4T3B0aW9uczogZmFsc2UsXHJcbiAgICBtb2JpbGU6IGZhbHNlLFxyXG4gICAgc2VsZWN0T25UYWI6IGZhbHNlLFxyXG4gICAgZHJvcGRvd25BbGlnblJpZ2h0OiBmYWxzZSxcclxuICAgIHdpbmRvd1BhZGRpbmc6IDBcclxuICB9O1xyXG5cclxuICBTZWxlY3RwaWNrZXIucHJvdG90eXBlID0ge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yOiBTZWxlY3RwaWNrZXIsXHJcblxyXG4gICAgaW5pdDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICBpZCA9IHRoaXMuJGVsZW1lbnQuYXR0cignaWQnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4nKTtcclxuXHJcbiAgICAgIC8vIHN0b3JlIG9yaWdpbmFsSW5kZXggKGtleSkgYW5kIG5ld0luZGV4ICh2YWx1ZSkgaW4gdGhpcy5saU9iaiBmb3IgZmFzdCBhY2Nlc3NpYmlsaXR5XHJcbiAgICAgIC8vIGFsbG93cyB1cyB0byBkbyB0aGlzLiRsaXMuZXEodGhhdC5saU9ialtpbmRleF0pIGluc3RlYWQgb2YgdGhpcy4kbGlzLmZpbHRlcignW2RhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCJdJylcclxuICAgICAgdGhpcy5saU9iaiA9IHt9O1xyXG4gICAgICB0aGlzLm11bHRpcGxlID0gdGhpcy4kZWxlbWVudC5wcm9wKCdtdWx0aXBsZScpO1xyXG4gICAgICB0aGlzLmF1dG9mb2N1cyA9IHRoaXMuJGVsZW1lbnQucHJvcCgnYXV0b2ZvY3VzJyk7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpZXcoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudFxyXG4gICAgICAgIC5hZnRlcih0aGlzLiRuZXdFbGVtZW50KVxyXG4gICAgICAgIC5hcHBlbmRUbyh0aGlzLiRuZXdFbGVtZW50KTtcclxuICAgICAgdGhpcy4kYnV0dG9uID0gdGhpcy4kbmV3RWxlbWVudC5jaGlsZHJlbignYnV0dG9uJyk7XHJcbiAgICAgIHRoaXMuJG1lbnUgPSB0aGlzLiRuZXdFbGVtZW50LmNoaWxkcmVuKCcuZHJvcGRvd24tbWVudScpO1xyXG4gICAgICB0aGlzLiRtZW51SW5uZXIgPSB0aGlzLiRtZW51LmNoaWxkcmVuKCcuaW5uZXInKTtcclxuICAgICAgdGhpcy4kc2VhcmNoYm94ID0gdGhpcy4kbWVudS5maW5kKCdpbnB1dCcpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmVDbGFzcygnYnMtc2VsZWN0LWhpZGRlbicpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09IHRydWUpIHRoaXMuJG1lbnUuYWRkQ2xhc3MoJ2Ryb3Bkb3duLW1lbnUtcmlnaHQnKTtcclxuXHJcbiAgICAgIGlmICh0eXBlb2YgaWQgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ2RhdGEtaWQnLCBpZCk7XHJcbiAgICAgICAgJCgnbGFiZWxbZm9yPVwiJyArIGlkICsgJ1wiXScpLmNsaWNrKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMuY2xpY2tMaXN0ZW5lcigpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmxpdmVTZWFyY2gpIHRoaXMubGl2ZVNlYXJjaExpc3RlbmVyKCk7XHJcbiAgICAgIHRoaXMucmVuZGVyKCk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmNvbnRhaW5lcikgdGhpcy5zZWxlY3RQb3NpdGlvbigpO1xyXG4gICAgICB0aGlzLiRtZW51LmRhdGEoJ3RoaXMnLCB0aGlzKTtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5kYXRhKCd0aGlzJywgdGhpcyk7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMubW9iaWxlKSB0aGlzLm1vYmlsZSgpO1xyXG5cclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5vbih7XHJcbiAgICAgICAgJ2hpZGUuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ2hpZGUuYnMuc2VsZWN0JywgZSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAnaGlkZGVuLmJzLmRyb3Bkb3duJzogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignaGlkZGVuLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgJ3Nob3cuYnMuZHJvcGRvd24nOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCB0cnVlKTtcclxuICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignc2hvdy5icy5zZWxlY3QnLCBlKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgICdzaG93bi5icy5kcm9wZG93bic6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICB0aGF0LiRlbGVtZW50LnRyaWdnZXIoJ3Nob3duLmJzLnNlbGVjdCcsIGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICBpZiAodGhhdC4kZWxlbWVudFswXS5oYXNBdHRyaWJ1dGUoJ3JlcXVpcmVkJykpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50Lm9uKCdpbnZhbGlkJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLmFkZENsYXNzKCdicy1pbnZhbGlkJyk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kZWxlbWVudC5vbih7XHJcbiAgICAgICAgICAgICdmb2N1cy5icy5zZWxlY3QnOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgdGhhdC4kZWxlbWVudC5vZmYoJ2ZvY3VzLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAnc2hvd24uYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnRcclxuICAgICAgICAgICAgICAgIC52YWwodGhhdC4kZWxlbWVudC52YWwoKSkgLy8gc2V0IHRoZSB2YWx1ZSB0byBoaWRlIHRoZSB2YWxpZGF0aW9uIG1lc3NhZ2UgaW4gQ2hyb21lIHdoZW4gbWVudSBpcyBvcGVuZWRcclxuICAgICAgICAgICAgICAgIC5vZmYoJ3Nob3duLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAncmVuZGVyZWQuYnMuc2VsZWN0JzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgIC8vIGlmIHNlbGVjdCBpcyBubyBsb25nZXIgaW52YWxpZCwgcmVtb3ZlIHRoZSBicy1pbnZhbGlkIGNsYXNzXHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMudmFsaWRpdHkudmFsaWQpIHRoYXQuJGJ1dHRvbi5yZW1vdmVDbGFzcygnYnMtaW52YWxpZCcpO1xyXG4gICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQub2ZmKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgdGhhdC4kYnV0dG9uLm9uKCdibHVyLmJzLnNlbGVjdCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB0aGF0LiRlbGVtZW50LmZvY3VzKCkuYmx1cigpO1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24ub2ZmKCdibHVyLmJzLnNlbGVjdCcpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbG9hZGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlRHJvcGRvd246IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gT3B0aW9uc1xyXG4gICAgICAvLyBJZiB3ZSBhcmUgbXVsdGlwbGUgb3Igc2hvd1RpY2sgb3B0aW9uIGlzIHNldCwgdGhlbiBhZGQgdGhlIHNob3ctdGljayBjbGFzc1xyXG4gICAgICB2YXIgc2hvd1RpY2sgPSAodGhpcy5tdWx0aXBsZSB8fCB0aGlzLm9wdGlvbnMuc2hvd1RpY2spID8gJyBzaG93LXRpY2snIDogJycsXHJcbiAgICAgICAgICBpbnB1dEdyb3VwID0gdGhpcy4kZWxlbWVudC5wYXJlbnQoKS5oYXNDbGFzcygnaW5wdXQtZ3JvdXAnKSA/ICcgaW5wdXQtZ3JvdXAtYnRuJyA6ICcnLFxyXG4gICAgICAgICAgYXV0b2ZvY3VzID0gdGhpcy5hdXRvZm9jdXMgPyAnIGF1dG9mb2N1cycgOiAnJztcclxuICAgICAgLy8gRWxlbWVudHNcclxuICAgICAgdmFyIGhlYWRlciA9IHRoaXMub3B0aW9ucy5oZWFkZXIgPyAnPGRpdiBjbGFzcz1cInBvcG92ZXItdGl0bGVcIj48YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImNsb3NlXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvYnV0dG9uPicgKyB0aGlzLm9wdGlvbnMuaGVhZGVyICsgJzwvZGl2PicgOiAnJztcclxuICAgICAgdmFyIHNlYXJjaGJveCA9IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoID9cclxuICAgICAgJzxkaXYgY2xhc3M9XCJicy1zZWFyY2hib3hcIj4nICtcclxuICAgICAgJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCInICtcclxuICAgICAgKG51bGwgPT09IHRoaXMub3B0aW9ucy5saXZlU2VhcmNoUGxhY2Vob2xkZXIgPyAnJyA6ICcgcGxhY2Vob2xkZXI9XCInICsgaHRtbEVzY2FwZSh0aGlzLm9wdGlvbnMubGl2ZVNlYXJjaFBsYWNlaG9sZGVyKSArICdcIicpICsgJyByb2xlPVwidGV4dGJveFwiIGFyaWEtbGFiZWw9XCJTZWFyY2hcIj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBhY3Rpb25zYm94ID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuYWN0aW9uc0JveCA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtYWN0aW9uc2JveFwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tZ3JvdXAtc20gYnRuLWJsb2NrXCI+JyArXHJcbiAgICAgICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImFjdGlvbnMtYnRuIGJzLXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5zZWxlY3RBbGxUZXh0ICtcclxuICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJhY3Rpb25zLWJ0biBicy1kZXNlbGVjdC1hbGwgYnRuIGJ0bi1kZWZhdWx0XCI+JyArXHJcbiAgICAgIHRoaXMub3B0aW9ucy5kZXNlbGVjdEFsbFRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkb25lYnV0dG9uID0gdGhpcy5tdWx0aXBsZSAmJiB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvbiA/XHJcbiAgICAgICc8ZGl2IGNsYXNzPVwiYnMtZG9uZWJ1dHRvblwiPicgK1xyXG4gICAgICAnPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBidG4tYmxvY2tcIj4nICtcclxuICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tZGVmYXVsdFwiPicgK1xyXG4gICAgICB0aGlzLm9wdGlvbnMuZG9uZUJ1dHRvblRleHQgK1xyXG4gICAgICAnPC9idXR0b24+JyArXHJcbiAgICAgICc8L2Rpdj4nICtcclxuICAgICAgJzwvZGl2PidcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHZhciBkcm9wID1cclxuICAgICAgICAgICc8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIGJvb3RzdHJhcC1zZWxlY3QnICsgc2hvd1RpY2sgKyBpbnB1dEdyb3VwICsgJ1wiPicgK1xyXG4gICAgICAgICAgJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiJyArIHRoaXMub3B0aW9ucy5zdHlsZUJhc2UgKyAnIGRyb3Bkb3duLXRvZ2dsZVwiIGRhdGEtdG9nZ2xlPVwiZHJvcGRvd25cIicgKyBhdXRvZm9jdXMgKyAnIHJvbGU9XCJidXR0b25cIj4nICtcclxuICAgICAgICAgICc8c3BhbiBjbGFzcz1cImZpbHRlci1vcHRpb24gcHVsbC1sZWZ0XCI+PC9zcGFuPiZuYnNwOycgK1xyXG4gICAgICAgICAgJzxzcGFuIGNsYXNzPVwiYnMtY2FyZXRcIj4nICtcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy50ZW1wbGF0ZS5jYXJldCArXHJcbiAgICAgICAgICAnPC9zcGFuPicgK1xyXG4gICAgICAgICAgJzwvYnV0dG9uPicgK1xyXG4gICAgICAgICAgJzxkaXYgY2xhc3M9XCJkcm9wZG93bi1tZW51IG9wZW5cIiByb2xlPVwiY29tYm9ib3hcIj4nICtcclxuICAgICAgICAgIGhlYWRlciArXHJcbiAgICAgICAgICBzZWFyY2hib3ggK1xyXG4gICAgICAgICAgYWN0aW9uc2JveCArXHJcbiAgICAgICAgICAnPHVsIGNsYXNzPVwiZHJvcGRvd24tbWVudSBpbm5lclwiIHJvbGU9XCJsaXN0Ym94XCIgYXJpYS1leHBhbmRlZD1cImZhbHNlXCI+JyArXHJcbiAgICAgICAgICAnPC91bD4nICtcclxuICAgICAgICAgIGRvbmVidXR0b24gK1xyXG4gICAgICAgICAgJzwvZGl2PicgK1xyXG4gICAgICAgICAgJzwvZGl2Pic7XHJcblxyXG4gICAgICByZXR1cm4gJChkcm9wKTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlVmlldzogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgJGRyb3AgPSB0aGlzLmNyZWF0ZURyb3Bkb3duKCksXHJcbiAgICAgICAgICBsaSA9IHRoaXMuY3JlYXRlTGkoKTtcclxuXHJcbiAgICAgICRkcm9wLmZpbmQoJ3VsJylbMF0uaW5uZXJIVE1MID0gbGk7XHJcbiAgICAgIHJldHVybiAkZHJvcDtcclxuICAgIH0sXHJcblxyXG4gICAgcmVsb2FkTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgLy8gcmVidWlsZFxyXG4gICAgICB2YXIgbGkgPSB0aGlzLmNyZWF0ZUxpKCk7XHJcbiAgICAgIHRoaXMuJG1lbnVJbm5lclswXS5pbm5lckhUTUwgPSBsaTtcclxuICAgIH0sXHJcblxyXG4gICAgY3JlYXRlTGk6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgX2xpID0gW10sXHJcbiAgICAgICAgICBvcHRJRCA9IDAsXHJcbiAgICAgICAgICB0aXRsZU9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgbGlJbmRleCA9IC0xOyAvLyBpbmNyZW1lbnQgbGlJbmRleCB3aGVuZXZlciBhIG5ldyA8bGk+IGVsZW1lbnQgaXMgY3JlYXRlZCB0byBlbnN1cmUgbGlPYmogaXMgY29ycmVjdFxyXG5cclxuICAgICAgLy8gSGVscGVyIGZ1bmN0aW9uc1xyXG4gICAgICAvKipcclxuICAgICAgICogQHBhcmFtIGNvbnRlbnRcclxuICAgICAgICogQHBhcmFtIFtpbmRleF1cclxuICAgICAgICogQHBhcmFtIFtjbGFzc2VzXVxyXG4gICAgICAgKiBAcGFyYW0gW29wdGdyb3VwXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlTEkgPSBmdW5jdGlvbiAoY29udGVudCwgaW5kZXgsIGNsYXNzZXMsIG9wdGdyb3VwKSB7XHJcbiAgICAgICAgcmV0dXJuICc8bGknICtcclxuICAgICAgICAgICAgKCh0eXBlb2YgY2xhc3NlcyAhPT0gJ3VuZGVmaW5lZCcgJiYgJycgIT09IGNsYXNzZXMpID8gJyBjbGFzcz1cIicgKyBjbGFzc2VzICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICgodHlwZW9mIGluZGV4ICE9PSAndW5kZWZpbmVkJyAmJiBudWxsICE9PSBpbmRleCkgPyAnIGRhdGEtb3JpZ2luYWwtaW5kZXg9XCInICsgaW5kZXggKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKCh0eXBlb2Ygb3B0Z3JvdXAgIT09ICd1bmRlZmluZWQnICYmIG51bGwgIT09IG9wdGdyb3VwKSA/ICdkYXRhLW9wdGdyb3VwPVwiJyArIG9wdGdyb3VwICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICc+JyArIGNvbnRlbnQgKyAnPC9saT4nO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgLyoqXHJcbiAgICAgICAqIEBwYXJhbSB0ZXh0XHJcbiAgICAgICAqIEBwYXJhbSBbY2xhc3Nlc11cclxuICAgICAgICogQHBhcmFtIFtpbmxpbmVdXHJcbiAgICAgICAqIEBwYXJhbSBbdG9rZW5zXVxyXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gICAgICAgKi9cclxuICAgICAgdmFyIGdlbmVyYXRlQSA9IGZ1bmN0aW9uICh0ZXh0LCBjbGFzc2VzLCBpbmxpbmUsIHRva2Vucykge1xyXG4gICAgICAgIHJldHVybiAnPGEgdGFiaW5kZXg9XCIwXCInICtcclxuICAgICAgICAgICAgKHR5cGVvZiBjbGFzc2VzICE9PSAndW5kZWZpbmVkJyA/ICcgY2xhc3M9XCInICsgY2xhc3NlcyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAoaW5saW5lID8gJyBzdHlsZT1cIicgKyBpbmxpbmUgKyAnXCInIDogJycpICtcclxuICAgICAgICAgICAgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplID8gJyBkYXRhLW5vcm1hbGl6ZWQtdGV4dD1cIicgKyBub3JtYWxpemVUb0Jhc2UoaHRtbEVzY2FwZSgkKHRleHQpLmh0bWwoKSkpICsgJ1wiJyA6ICcnKSArXHJcbiAgICAgICAgICAgICh0eXBlb2YgdG9rZW5zICE9PSAndW5kZWZpbmVkJyB8fCB0b2tlbnMgIT09IG51bGwgPyAnIGRhdGEtdG9rZW5zPVwiJyArIHRva2VucyArICdcIicgOiAnJykgK1xyXG4gICAgICAgICAgICAnIHJvbGU9XCJvcHRpb25cIj4nICsgdGV4dCArXHJcbiAgICAgICAgICAgICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyB0aGF0Lm9wdGlvbnMudGlja0ljb24gKyAnIGNoZWNrLW1hcmtcIj48L3NwYW4+JyArXHJcbiAgICAgICAgICAgICc8L2E+JztcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMudGl0bGUgJiYgIXRoaXMubXVsdGlwbGUpIHtcclxuICAgICAgICAvLyB0aGlzIG9wdGlvbiBkb2Vzbid0IGNyZWF0ZSBhIG5ldyA8bGk+IGVsZW1lbnQsIGJ1dCBkb2VzIGFkZCBhIG5ldyBvcHRpb24sIHNvIGxpSW5kZXggaXMgZGVjcmVhc2VkXHJcbiAgICAgICAgLy8gc2luY2UgbGlPYmogaXMgcmVjYWxjdWxhdGVkIG9uIGV2ZXJ5IHJlZnJlc2gsIGxpSW5kZXggbmVlZHMgdG8gYmUgZGVjcmVhc2VkIGV2ZW4gaWYgdGhlIHRpdGxlT3B0aW9uIGlzIGFscmVhZHkgYXBwZW5kZWRcclxuICAgICAgICBsaUluZGV4LS07XHJcblxyXG4gICAgICAgIGlmICghdGhpcy4kZWxlbWVudC5maW5kKCcuYnMtdGl0bGUtb3B0aW9uJykubGVuZ3RoKSB7XHJcbiAgICAgICAgICAvLyBVc2UgbmF0aXZlIEpTIHRvIHByZXBlbmQgb3B0aW9uIChmYXN0ZXIpXHJcbiAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuJGVsZW1lbnRbMF07XHJcbiAgICAgICAgICB0aXRsZU9wdGlvbi5jbGFzc05hbWUgPSAnYnMtdGl0bGUtb3B0aW9uJztcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLmlubmVySFRNTCA9IHRoaXMub3B0aW9ucy50aXRsZTtcclxuICAgICAgICAgIHRpdGxlT3B0aW9uLnZhbHVlID0gJyc7XHJcbiAgICAgICAgICBlbGVtZW50Lmluc2VydEJlZm9yZSh0aXRsZU9wdGlvbiwgZWxlbWVudC5maXJzdENoaWxkKTtcclxuICAgICAgICAgIC8vIENoZWNrIGlmIHNlbGVjdGVkIG9yIGRhdGEtc2VsZWN0ZWQgYXR0cmlidXRlIGlzIGFscmVhZHkgc2V0IG9uIGFuIG9wdGlvbi4gSWYgbm90LCBzZWxlY3QgdGhlIHRpdGxlT3B0aW9uIG9wdGlvbi5cclxuICAgICAgICAgIC8vIHRoZSBzZWxlY3RlZCBpdGVtIG1heSBoYXZlIGJlZW4gY2hhbmdlZCBieSB1c2VyIG9yIHByb2dyYW1tYXRpY2FsbHkgYmVmb3JlIHRoZSBib290c3RyYXAgc2VsZWN0IHBsdWdpbiBydW5zLFxyXG4gICAgICAgICAgLy8gaWYgc28sIHRoZSBzZWxlY3Qgd2lsbCBoYXZlIHRoZSBkYXRhLXNlbGVjdGVkIGF0dHJpYnV0ZVxyXG4gICAgICAgICAgdmFyICRvcHQgPSAkKGVsZW1lbnQub3B0aW9uc1tlbGVtZW50LnNlbGVjdGVkSW5kZXhdKTtcclxuICAgICAgICAgIGlmICgkb3B0LmF0dHIoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCAmJiB0aGlzLiRlbGVtZW50LmRhdGEoJ3NlbGVjdGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICB0aXRsZU9wdGlvbi5zZWxlY3RlZCA9IHRydWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgJHNlbGVjdE9wdGlvbnMuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBsaUluZGV4Kys7XHJcblxyXG4gICAgICAgIGlmICgkdGhpcy5oYXNDbGFzcygnYnMtdGl0bGUtb3B0aW9uJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgLy8gR2V0IHRoZSBjbGFzcyBhbmQgdGV4dCBmb3IgdGhlIG9wdGlvblxyXG4gICAgICAgIHZhciBvcHRpb25DbGFzcyA9IHRoaXMuY2xhc3NOYW1lIHx8ICcnLFxyXG4gICAgICAgICAgICBpbmxpbmUgPSBodG1sRXNjYXBlKHRoaXMuc3R5bGUuY3NzVGV4dCksXHJcbiAgICAgICAgICAgIHRleHQgPSAkdGhpcy5kYXRhKCdjb250ZW50JykgPyAkdGhpcy5kYXRhKCdjb250ZW50JykgOiAkdGhpcy5odG1sKCksXHJcbiAgICAgICAgICAgIHRva2VucyA9ICR0aGlzLmRhdGEoJ3Rva2VucycpID8gJHRoaXMuZGF0YSgndG9rZW5zJykgOiBudWxsLFxyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gdHlwZW9mICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkdGhpcy5kYXRhKCdzdWJ0ZXh0JykgKyAnPC9zbWFsbD4nIDogJycsXHJcbiAgICAgICAgICAgIGljb24gPSB0eXBlb2YgJHRoaXMuZGF0YSgnaWNvbicpICE9PSAndW5kZWZpbmVkJyA/ICc8c3BhbiBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9zcGFuPiAnIDogJycsXHJcbiAgICAgICAgICAgICRwYXJlbnQgPSAkdGhpcy5wYXJlbnQoKSxcclxuICAgICAgICAgICAgaXNPcHRncm91cCA9ICRwYXJlbnRbMF0udGFnTmFtZSA9PT0gJ09QVEdST1VQJyxcclxuICAgICAgICAgICAgaXNPcHRncm91cERpc2FibGVkID0gaXNPcHRncm91cCAmJiAkcGFyZW50WzBdLmRpc2FibGVkLFxyXG4gICAgICAgICAgICBpc0Rpc2FibGVkID0gdGhpcy5kaXNhYmxlZCB8fCBpc09wdGdyb3VwRGlzYWJsZWQsXHJcbiAgICAgICAgICAgIHByZXZIaWRkZW5JbmRleDtcclxuXHJcbiAgICAgICAgaWYgKGljb24gIT09ICcnICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgIGljb24gPSAnPHNwYW4+JyArIGljb24gKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAoaXNEaXNhYmxlZCAmJiAhaXNPcHRncm91cCB8fCBpc09wdGdyb3VwRGlzYWJsZWQpKSB7XHJcbiAgICAgICAgICAvLyBzZXQgcHJldkhpZGRlbkluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBoaWRkZW4gb3B0aW9uIGluIGEgZ3JvdXAgb2YgaGlkZGVuIG9wdGlvbnNcclxuICAgICAgICAgIC8vIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IGEgZGl2aWRlciBzaG91bGQgYmUgcGxhY2VkIGFmdGVyIGFuIG9wdGdyb3VwIGlmIHRoZXJlIGFyZVxyXG4gICAgICAgICAgLy8gaGlkZGVuIG9wdGlvbnMgYmV0d2VlbiB0aGUgb3B0Z3JvdXAgYW5kIHRoZSBmaXJzdCB2aXNpYmxlIG9wdGlvblxyXG4gICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcbiAgICAgICAgICAkdGhpcy5uZXh0KCkuZGF0YSgncHJldkhpZGRlbkluZGV4JywgKHByZXZIaWRkZW5JbmRleCAhPT0gdW5kZWZpbmVkID8gcHJldkhpZGRlbkluZGV4IDogaW5kZXgpKTtcclxuXHJcbiAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoISR0aGlzLmRhdGEoJ2NvbnRlbnQnKSkge1xyXG4gICAgICAgICAgLy8gUHJlcGVuZCBhbnkgaWNvbiBhbmQgYXBwZW5kIGFueSBzdWJ0ZXh0IHRvIHRoZSBtYWluIHRleHQuXHJcbiAgICAgICAgICB0ZXh0ID0gaWNvbiArICc8c3BhbiBjbGFzcz1cInRleHRcIj4nICsgdGV4dCArIHN1YnRleHQgKyAnPC9zcGFuPic7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaXNPcHRncm91cCAmJiAkdGhpcy5kYXRhKCdkaXZpZGVyJykgIT09IHRydWUpIHtcclxuICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuaGlkZURpc2FibGVkICYmIGlzRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgaWYgKCRwYXJlbnQuZGF0YSgnYWxsT3B0aW9uc0Rpc2FibGVkJykgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIHZhciAkb3B0aW9ucyA9ICRwYXJlbnQuY2hpbGRyZW4oKTtcclxuICAgICAgICAgICAgICAkcGFyZW50LmRhdGEoJ2FsbE9wdGlvbnNEaXNhYmxlZCcsICRvcHRpb25zLmZpbHRlcignOmRpc2FibGVkJykubGVuZ3RoID09PSAkb3B0aW9ucy5sZW5ndGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5kYXRhKCdhbGxPcHRpb25zRGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgICAgIGxpSW5kZXgtLTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB2YXIgb3B0R3JvdXBDbGFzcyA9ICcgJyArICRwYXJlbnRbMF0uY2xhc3NOYW1lIHx8ICcnO1xyXG5cclxuICAgICAgICAgIGlmICgkdGhpcy5pbmRleCgpID09PSAwKSB7IC8vIElzIGl0IHRoZSBmaXJzdCBvcHRpb24gb2YgdGhlIG9wdGdyb3VwP1xyXG4gICAgICAgICAgICBvcHRJRCArPSAxO1xyXG5cclxuICAgICAgICAgICAgLy8gR2V0IHRoZSBvcHQgZ3JvdXAgbGFiZWxcclxuICAgICAgICAgICAgdmFyIGxhYmVsID0gJHBhcmVudFswXS5sYWJlbCxcclxuICAgICAgICAgICAgICAgIGxhYmVsU3VidGV4dCA9IHR5cGVvZiAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSAhPT0gJ3VuZGVmaW5lZCcgPyAnPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyAkcGFyZW50LmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPicgOiAnJyxcclxuICAgICAgICAgICAgICAgIGxhYmVsSWNvbiA9ICRwYXJlbnQuZGF0YSgnaWNvbicpID8gJzxzcGFuIGNsYXNzPVwiJyArIHRoYXQub3B0aW9ucy5pY29uQmFzZSArICcgJyArICRwYXJlbnQuZGF0YSgnaWNvbicpICsgJ1wiPjwvc3Bhbj4gJyA6ICcnO1xyXG5cclxuICAgICAgICAgICAgbGFiZWwgPSBsYWJlbEljb24gKyAnPHNwYW4gY2xhc3M9XCJ0ZXh0XCI+JyArIGh0bWxFc2NhcGUobGFiZWwpICsgbGFiZWxTdWJ0ZXh0ICsgJzwvc3Bhbj4nO1xyXG5cclxuICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAwICYmIF9saS5sZW5ndGggPiAwKSB7IC8vIElzIGl0IE5PVCB0aGUgZmlyc3Qgb3B0aW9uIG9mIHRoZSBzZWxlY3QgJiYgYXJlIHRoZXJlIGVsZW1lbnRzIGluIHRoZSBkcm9wZG93bj9cclxuICAgICAgICAgICAgICBsaUluZGV4Kys7XHJcbiAgICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGlJbmRleCsrO1xyXG4gICAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGxhYmVsLCBudWxsLCAnZHJvcGRvd24taGVhZGVyJyArIG9wdEdyb3VwQ2xhc3MsIG9wdElEKSk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBsaUluZGV4LS07XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCAnb3B0ICcgKyBvcHRpb25DbGFzcyArIG9wdEdyb3VwQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICcnLCBvcHRJRCkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuZGF0YSgnZGl2aWRlcicpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKCcnLCBpbmRleCwgJ2RpdmlkZXInKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdoaWRkZW4nKSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgLy8gc2V0IHByZXZIaWRkZW5JbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgaGlkZGVuIG9wdGlvbiBpbiBhIGdyb3VwIG9mIGhpZGRlbiBvcHRpb25zXHJcbiAgICAgICAgICAvLyB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCBhIGRpdmlkZXIgc2hvdWxkIGJlIHBsYWNlZCBhZnRlciBhbiBvcHRncm91cCBpZiB0aGVyZSBhcmVcclxuICAgICAgICAgIC8vIGhpZGRlbiBvcHRpb25zIGJldHdlZW4gdGhlIG9wdGdyb3VwIGFuZCB0aGUgZmlyc3QgdmlzaWJsZSBvcHRpb25cclxuICAgICAgICAgIHByZXZIaWRkZW5JbmRleCA9ICR0aGlzLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcpO1xyXG4gICAgICAgICAgJHRoaXMubmV4dCgpLmRhdGEoJ3ByZXZIaWRkZW5JbmRleCcsIChwcmV2SGlkZGVuSW5kZXggIT09IHVuZGVmaW5lZCA/IHByZXZIaWRkZW5JbmRleCA6IGluZGV4KSk7XHJcblxyXG4gICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSShnZW5lcmF0ZUEodGV4dCwgb3B0aW9uQ2xhc3MsIGlubGluZSwgdG9rZW5zKSwgaW5kZXgsICdoaWRkZW4gaXMtaGlkZGVuJykpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB2YXIgc2hvd0RpdmlkZXIgPSB0aGlzLnByZXZpb3VzRWxlbWVudFNpYmxpbmcgJiYgdGhpcy5wcmV2aW91c0VsZW1lbnRTaWJsaW5nLnRhZ05hbWUgPT09ICdPUFRHUk9VUCc7XHJcblxyXG4gICAgICAgICAgLy8gaWYgcHJldmlvdXMgZWxlbWVudCBpcyBub3QgYW4gb3B0Z3JvdXAgYW5kIGhpZGVEaXNhYmxlZCBpcyB0cnVlXHJcbiAgICAgICAgICBpZiAoIXNob3dEaXZpZGVyICYmIHRoYXQub3B0aW9ucy5oaWRlRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgcHJldkhpZGRlbkluZGV4ID0gJHRoaXMuZGF0YSgncHJldkhpZGRlbkluZGV4Jyk7XHJcblxyXG4gICAgICAgICAgICBpZiAocHJldkhpZGRlbkluZGV4ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAvLyBzZWxlY3QgdGhlIGVsZW1lbnQgKipiZWZvcmUqKiB0aGUgZmlyc3QgaGlkZGVuIGVsZW1lbnQgaW4gdGhlIGdyb3VwXHJcbiAgICAgICAgICAgICAgdmFyIHByZXZIaWRkZW4gPSAkc2VsZWN0T3B0aW9ucy5lcShwcmV2SGlkZGVuSW5kZXgpWzBdLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XHJcbiAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgaWYgKHByZXZIaWRkZW4gJiYgcHJldkhpZGRlbi50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmICFwcmV2SGlkZGVuLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICBzaG93RGl2aWRlciA9IHRydWU7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHNob3dEaXZpZGVyKSB7XHJcbiAgICAgICAgICAgIGxpSW5kZXgrKztcclxuICAgICAgICAgICAgX2xpLnB1c2goZ2VuZXJhdGVMSSgnJywgbnVsbCwgJ2RpdmlkZXInLCBvcHRJRCArICdkaXYnKSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBfbGkucHVzaChnZW5lcmF0ZUxJKGdlbmVyYXRlQSh0ZXh0LCBvcHRpb25DbGFzcywgaW5saW5lLCB0b2tlbnMpLCBpbmRleCkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC5saU9ialtpbmRleF0gPSBsaUluZGV4O1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vSWYgd2UgYXJlIG5vdCBtdWx0aXBsZSwgd2UgZG9uJ3QgaGF2ZSBhIHNlbGVjdGVkIGl0ZW0sIGFuZCB3ZSBkb24ndCBoYXZlIGEgdGl0bGUsIHNlbGVjdCB0aGUgZmlyc3QgZWxlbWVudCBzbyBzb21ldGhpbmcgaXMgc2V0IGluIHRoZSBidXR0b25cclxuICAgICAgaWYgKCF0aGlzLm11bHRpcGxlICYmIHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykubGVuZ3RoID09PSAwICYmICF0aGlzLm9wdGlvbnMudGl0bGUpIHtcclxuICAgICAgICB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLmVxKDApLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSkuYXR0cignc2VsZWN0ZWQnLCAnc2VsZWN0ZWQnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIF9saS5qb2luKCcnKTtcclxuICAgIH0sXHJcblxyXG4gICAgZmluZExpczogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kbGlzID09IG51bGwpIHRoaXMuJGxpcyA9IHRoaXMuJG1lbnUuZmluZCgnbGknKTtcclxuICAgICAgcmV0dXJuIHRoaXMuJGxpcztcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3VwZGF0ZUxpXSBkZWZhdWx0cyB0byB0cnVlXHJcbiAgICAgKi9cclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKHVwZGF0ZUxpKSB7XHJcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgIG5vdERpc2FibGVkLFxyXG4gICAgICAgICAgJHNlbGVjdE9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpO1xyXG5cclxuICAgICAgLy9VcGRhdGUgdGhlIExJIHRvIG1hdGNoIHRoZSBTRUxFQ1RcclxuICAgICAgaWYgKHVwZGF0ZUxpICE9PSBmYWxzZSkge1xyXG4gICAgICAgICRzZWxlY3RPcHRpb25zLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XHJcbiAgICAgICAgICB2YXIgJGxpcyA9IHRoYXQuZmluZExpcygpLmVxKHRoYXQubGlPYmpbaW5kZXhdKTtcclxuXHJcbiAgICAgICAgICB0aGF0LnNldERpc2FibGVkKGluZGV4LCB0aGlzLmRpc2FibGVkIHx8IHRoaXMucGFyZW50Tm9kZS50YWdOYW1lID09PSAnT1BUR1JPVVAnICYmIHRoaXMucGFyZW50Tm9kZS5kaXNhYmxlZCwgJGxpcyk7XHJcbiAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGluZGV4LCB0aGlzLnNlbGVjdGVkLCAkbGlzKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy50b2dnbGVQbGFjZWhvbGRlcigpO1xyXG5cclxuICAgICAgdGhpcy50YWJJbmRleCgpO1xyXG5cclxuICAgICAgdmFyIHNlbGVjdGVkSXRlbXMgPSAkc2VsZWN0T3B0aW9ucy5tYXAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkKSB7XHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmhpZGVEaXNhYmxlZCAmJiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLnBhcmVudE5vZGUudGFnTmFtZSA9PT0gJ09QVEdST1VQJyAmJiB0aGlzLnBhcmVudE5vZGUuZGlzYWJsZWQpKSByZXR1cm47XHJcblxyXG4gICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICAgICBpY29uID0gJHRoaXMuZGF0YSgnaWNvbicpICYmIHRoYXQub3B0aW9ucy5zaG93SWNvbiA/ICc8aSBjbGFzcz1cIicgKyB0aGF0Lm9wdGlvbnMuaWNvbkJhc2UgKyAnICcgKyAkdGhpcy5kYXRhKCdpY29uJykgKyAnXCI+PC9pPiAnIDogJycsXHJcbiAgICAgICAgICAgICAgc3VidGV4dDtcclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLnNob3dTdWJ0ZXh0ICYmICR0aGlzLmRhdGEoJ3N1YnRleHQnKSAmJiAhdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JyArICR0aGlzLmRhdGEoJ3N1YnRleHQnKSArICc8L3NtYWxsPic7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdWJ0ZXh0ID0gJyc7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAodHlwZW9mICR0aGlzLmF0dHIoJ3RpdGxlJykgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5hdHRyKCd0aXRsZScpO1xyXG4gICAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5kYXRhKCdjb250ZW50JykgJiYgdGhhdC5vcHRpb25zLnNob3dDb250ZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybiAkdGhpcy5kYXRhKCdjb250ZW50JykudG9TdHJpbmcoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpY29uICsgJHRoaXMuaHRtbCgpICsgc3VidGV4dDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pLnRvQXJyYXkoKTtcclxuXHJcbiAgICAgIC8vRml4ZXMgaXNzdWUgaW4gSUUxMCBvY2N1cnJpbmcgd2hlbiBubyBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZCBhbmQgYXQgbGVhc3Qgb25lIG9wdGlvbiBpcyBkaXNhYmxlZFxyXG4gICAgICAvL0NvbnZlcnQgYWxsIHRoZSB2YWx1ZXMgaW50byBhIGNvbW1hIGRlbGltaXRlZCBzdHJpbmdcclxuICAgICAgdmFyIHRpdGxlID0gIXRoaXMubXVsdGlwbGUgPyBzZWxlY3RlZEl0ZW1zWzBdIDogc2VsZWN0ZWRJdGVtcy5qb2luKHRoaXMub3B0aW9ucy5tdWx0aXBsZVNlcGFyYXRvcik7XHJcblxyXG4gICAgICAvL0lmIHRoaXMgaXMgbXVsdGkgc2VsZWN0LCBhbmQgdGhlIHNlbGVjdFRleHQgdHlwZSBpcyBjb3VudCwgdGhlIHNob3cgMSBvZiAyIHNlbGVjdGVkIGV0Yy4uXHJcbiAgICAgIGlmICh0aGlzLm11bHRpcGxlICYmIHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuaW5kZXhPZignY291bnQnKSA+IC0xKSB7XHJcbiAgICAgICAgdmFyIG1heCA9IHRoaXMub3B0aW9ucy5zZWxlY3RlZFRleHRGb3JtYXQuc3BsaXQoJz4nKTtcclxuICAgICAgICBpZiAoKG1heC5sZW5ndGggPiAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID4gbWF4WzFdKSB8fCAobWF4Lmxlbmd0aCA9PSAxICYmIHNlbGVjdGVkSXRlbXMubGVuZ3RoID49IDIpKSB7XHJcbiAgICAgICAgICBub3REaXNhYmxlZCA9IHRoaXMub3B0aW9ucy5oaWRlRGlzYWJsZWQgPyAnLCBbZGlzYWJsZWRdJyA6ICcnO1xyXG4gICAgICAgICAgdmFyIHRvdGFsQ291bnQgPSAkc2VsZWN0T3B0aW9ucy5ub3QoJ1tkYXRhLWRpdmlkZXI9XCJ0cnVlXCJdLCBbZGF0YS1oaWRkZW49XCJ0cnVlXCJdJyArIG5vdERpc2FibGVkKS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgdHI4blRleHQgPSAodHlwZW9mIHRoaXMub3B0aW9ucy5jb3VudFNlbGVjdGVkVGV4dCA9PT0gJ2Z1bmN0aW9uJykgPyB0aGlzLm9wdGlvbnMuY291bnRTZWxlY3RlZFRleHQoc2VsZWN0ZWRJdGVtcy5sZW5ndGgsIHRvdGFsQ291bnQpIDogdGhpcy5vcHRpb25zLmNvdW50U2VsZWN0ZWRUZXh0O1xyXG4gICAgICAgICAgdGl0bGUgPSB0cjhuVGV4dC5yZXBsYWNlKCd7MH0nLCBzZWxlY3RlZEl0ZW1zLmxlbmd0aC50b1N0cmluZygpKS5yZXBsYWNlKCd7MX0nLCB0b3RhbENvdW50LnRvU3RyaW5nKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy50aXRsZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICB0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2VsZWN0ZWRUZXh0Rm9ybWF0ID09ICdzdGF0aWMnKSB7XHJcbiAgICAgICAgdGl0bGUgPSB0aGlzLm9wdGlvbnMudGl0bGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vSWYgd2UgZG9udCBoYXZlIGEgdGl0bGUsIHRoZW4gdXNlIHRoZSBkZWZhdWx0LCBvciBpZiBub3RoaW5nIGlzIHNldCBhdCBhbGwsIHVzZSB0aGUgbm90IHNlbGVjdGVkIHRleHRcclxuICAgICAgaWYgKCF0aXRsZSkge1xyXG4gICAgICAgIHRpdGxlID0gdHlwZW9mIHRoaXMub3B0aW9ucy50aXRsZSAhPT0gJ3VuZGVmaW5lZCcgPyB0aGlzLm9wdGlvbnMudGl0bGUgOiB0aGlzLm9wdGlvbnMubm9uZVNlbGVjdGVkVGV4dDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy9zdHJpcCBhbGwgSFRNTCB0YWdzIGFuZCB0cmltIHRoZSByZXN1bHQsIHRoZW4gdW5lc2NhcGUgYW55IGVzY2FwZWQgdGFnc1xyXG4gICAgICB0aGlzLiRidXR0b24uYXR0cigndGl0bGUnLCBodG1sVW5lc2NhcGUoJC50cmltKHRpdGxlLnJlcGxhY2UoLzxbXj5dKj4/L2csICcnKSkpKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLmNoaWxkcmVuKCcuZmlsdGVyLW9wdGlvbicpLmh0bWwodGl0bGUpO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCdyZW5kZXJlZC5icy5zZWxlY3QnKTtcclxuICAgIH0sXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0gW3N0eWxlXVxyXG4gICAgICogQHBhcmFtIFtzdGF0dXNdXHJcbiAgICAgKi9cclxuICAgIHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUsIHN0YXR1cykge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5hdHRyKCdjbGFzcycpKSB7XHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5hZGRDbGFzcyh0aGlzLiRlbGVtZW50LmF0dHIoJ2NsYXNzJykucmVwbGFjZSgvc2VsZWN0cGlja2VyfG1vYmlsZS1kZXZpY2V8YnMtc2VsZWN0LWhpZGRlbnx2YWxpZGF0ZVxcWy4qXFxdL2dpLCAnJykpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICB2YXIgYnV0dG9uQ2xhc3MgPSBzdHlsZSA/IHN0eWxlIDogdGhpcy5vcHRpb25zLnN0eWxlO1xyXG5cclxuICAgICAgaWYgKHN0YXR1cyA9PSAnYWRkJykge1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcyhidXR0b25DbGFzcyk7XHJcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID09ICdyZW1vdmUnKSB7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLnJlbW92ZUNsYXNzKGJ1dHRvbkNsYXNzKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLiRidXR0b24ucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLnN0eWxlKTtcclxuICAgICAgICB0aGlzLiRidXR0b24uYWRkQ2xhc3MoYnV0dG9uQ2xhc3MpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGxpSGVpZ2h0OiBmdW5jdGlvbiAocmVmcmVzaCkge1xyXG4gICAgICBpZiAoIXJlZnJlc2ggJiYgKHRoaXMub3B0aW9ucy5zaXplID09PSBmYWxzZSB8fCB0aGlzLnNpemVJbmZvKSkgcmV0dXJuO1xyXG5cclxuICAgICAgdmFyIG5ld0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcclxuICAgICAgICAgIG1lbnVJbm5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3VsJyksXHJcbiAgICAgICAgICBkaXZpZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGxpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSxcclxuICAgICAgICAgIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyksXHJcbiAgICAgICAgICB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLFxyXG4gICAgICAgICAgaGVhZGVyID0gdGhpcy5vcHRpb25zLmhlYWRlciAmJiB0aGlzLiRtZW51LmZpbmQoJy5wb3BvdmVyLXRpdGxlJykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLnBvcG92ZXItdGl0bGUnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgc2VhcmNoID0gdGhpcy5vcHRpb25zLmxpdmVTZWFyY2ggPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSA6IG51bGwsXHJcbiAgICAgICAgICBhY3Rpb25zID0gdGhpcy5vcHRpb25zLmFjdGlvbnNCb3ggJiYgdGhpcy5tdWx0aXBsZSAmJiB0aGlzLiRtZW51LmZpbmQoJy5icy1hY3Rpb25zYm94JykubGVuZ3RoID4gMCA/IHRoaXMuJG1lbnUuZmluZCgnLmJzLWFjdGlvbnNib3gnKVswXS5jbG9uZU5vZGUodHJ1ZSkgOiBudWxsLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbiA9IHRoaXMub3B0aW9ucy5kb25lQnV0dG9uICYmIHRoaXMubXVsdGlwbGUgJiYgdGhpcy4kbWVudS5maW5kKCcuYnMtZG9uZWJ1dHRvbicpLmxlbmd0aCA+IDAgPyB0aGlzLiRtZW51LmZpbmQoJy5icy1kb25lYnV0dG9uJylbMF0uY2xvbmVOb2RlKHRydWUpIDogbnVsbDtcclxuXHJcbiAgICAgIHRleHQuY2xhc3NOYW1lID0gJ3RleHQnO1xyXG4gICAgICBuZXdFbGVtZW50LmNsYXNzTmFtZSA9IHRoaXMuJG1lbnVbMF0ucGFyZW50Tm9kZS5jbGFzc05hbWUgKyAnIG9wZW4nO1xyXG4gICAgICBtZW51LmNsYXNzTmFtZSA9ICdkcm9wZG93bi1tZW51IG9wZW4nO1xyXG4gICAgICBtZW51SW5uZXIuY2xhc3NOYW1lID0gJ2Ryb3Bkb3duLW1lbnUgaW5uZXInO1xyXG4gICAgICBkaXZpZGVyLmNsYXNzTmFtZSA9ICdkaXZpZGVyJztcclxuXHJcbiAgICAgIHRleHQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJ0lubmVyIHRleHQnKSk7XHJcbiAgICAgIGEuYXBwZW5kQ2hpbGQodGV4dCk7XHJcbiAgICAgIGxpLmFwcGVuZENoaWxkKGEpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQobGkpO1xyXG4gICAgICBtZW51SW5uZXIuYXBwZW5kQ2hpbGQoZGl2aWRlcik7XHJcbiAgICAgIGlmIChoZWFkZXIpIG1lbnUuYXBwZW5kQ2hpbGQoaGVhZGVyKTtcclxuICAgICAgaWYgKHNlYXJjaCkge1xyXG4gICAgICAgIHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcbiAgICAgICAgc2VhcmNoLmNsYXNzTmFtZSA9ICdicy1zZWFyY2hib3gnO1xyXG4gICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICdmb3JtLWNvbnRyb2wnO1xyXG4gICAgICAgIHNlYXJjaC5hcHBlbmRDaGlsZChpbnB1dCk7XHJcbiAgICAgICAgbWVudS5hcHBlbmRDaGlsZChzZWFyY2gpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChhY3Rpb25zKSBtZW51LmFwcGVuZENoaWxkKGFjdGlvbnMpO1xyXG4gICAgICBtZW51LmFwcGVuZENoaWxkKG1lbnVJbm5lcik7XHJcbiAgICAgIGlmIChkb25lQnV0dG9uKSBtZW51LmFwcGVuZENoaWxkKGRvbmVCdXR0b24pO1xyXG4gICAgICBuZXdFbGVtZW50LmFwcGVuZENoaWxkKG1lbnUpO1xyXG5cclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgIHZhciBsaUhlaWdodCA9IGEub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gaGVhZGVyID8gaGVhZGVyLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSBzZWFyY2ggPyBzZWFyY2gub2Zmc2V0SGVpZ2h0IDogMCxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSBhY3Rpb25zID8gYWN0aW9ucy5vZmZzZXRIZWlnaHQgOiAwLFxyXG4gICAgICAgICAgZG9uZUJ1dHRvbkhlaWdodCA9IGRvbmVCdXR0b24gPyBkb25lQnV0dG9uLm9mZnNldEhlaWdodCA6IDAsXHJcbiAgICAgICAgICBkaXZpZGVySGVpZ2h0ID0gJChkaXZpZGVyKS5vdXRlckhlaWdodCh0cnVlKSxcclxuICAgICAgICAgIC8vIGZhbGwgYmFjayB0byBqUXVlcnkgaWYgZ2V0Q29tcHV0ZWRTdHlsZSBpcyBub3Qgc3VwcG9ydGVkXHJcbiAgICAgICAgICBtZW51U3R5bGUgPSB0eXBlb2YgZ2V0Q29tcHV0ZWRTdHlsZSA9PT0gJ2Z1bmN0aW9uJyA/IGdldENvbXB1dGVkU3R5bGUobWVudSkgOiBmYWxzZSxcclxuICAgICAgICAgICRtZW51ID0gbWVudVN0eWxlID8gbnVsbCA6ICQobWVudSksXHJcbiAgICAgICAgICBtZW51UGFkZGluZyA9IHtcclxuICAgICAgICAgICAgdmVydDogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdUb3AgOiAkbWVudS5jc3MoJ3BhZGRpbmdUb3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUucGFkZGluZ0JvdHRvbSA6ICRtZW51LmNzcygncGFkZGluZ0JvdHRvbScpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJUb3BXaWR0aCA6ICRtZW51LmNzcygnYm9yZGVyVG9wV2lkdGgnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUuYm9yZGVyQm90dG9tV2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckJvdHRvbVdpZHRoJykpLFxyXG4gICAgICAgICAgICBob3JpejogcGFyc2VJbnQobWVudVN0eWxlID8gbWVudVN0eWxlLnBhZGRpbmdMZWZ0IDogJG1lbnUuY3NzKCdwYWRkaW5nTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5wYWRkaW5nUmlnaHQgOiAkbWVudS5jc3MoJ3BhZGRpbmdSaWdodCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJMZWZ0V2lkdGggOiAkbWVudS5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5ib3JkZXJSaWdodFdpZHRoIDogJG1lbnUuY3NzKCdib3JkZXJSaWdodFdpZHRoJykpXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9ICB7XHJcbiAgICAgICAgICAgIHZlcnQ6IG1lbnVQYWRkaW5nLnZlcnQgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luVG9wIDogJG1lbnUuY3NzKCdtYXJnaW5Ub3AnKSkgK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luQm90dG9tIDogJG1lbnUuY3NzKCdtYXJnaW5Cb3R0b20nKSkgKyAyLFxyXG4gICAgICAgICAgICBob3JpejogbWVudVBhZGRpbmcuaG9yaXogK1xyXG4gICAgICAgICAgICAgICAgICBwYXJzZUludChtZW51U3R5bGUgPyBtZW51U3R5bGUubWFyZ2luTGVmdCA6ICRtZW51LmNzcygnbWFyZ2luTGVmdCcpKSArXHJcbiAgICAgICAgICAgICAgICAgIHBhcnNlSW50KG1lbnVTdHlsZSA/IG1lbnVTdHlsZS5tYXJnaW5SaWdodCA6ICRtZW51LmNzcygnbWFyZ2luUmlnaHQnKSkgKyAyXHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKG5ld0VsZW1lbnQpO1xyXG5cclxuICAgICAgdGhpcy5zaXplSW5mbyA9IHtcclxuICAgICAgICBsaUhlaWdodDogbGlIZWlnaHQsXHJcbiAgICAgICAgaGVhZGVySGVpZ2h0OiBoZWFkZXJIZWlnaHQsXHJcbiAgICAgICAgc2VhcmNoSGVpZ2h0OiBzZWFyY2hIZWlnaHQsXHJcbiAgICAgICAgYWN0aW9uc0hlaWdodDogYWN0aW9uc0hlaWdodCxcclxuICAgICAgICBkb25lQnV0dG9uSGVpZ2h0OiBkb25lQnV0dG9uSGVpZ2h0LFxyXG4gICAgICAgIGRpdmlkZXJIZWlnaHQ6IGRpdmlkZXJIZWlnaHQsXHJcbiAgICAgICAgbWVudVBhZGRpbmc6IG1lbnVQYWRkaW5nLFxyXG4gICAgICAgIG1lbnVFeHRyYXM6IG1lbnVFeHRyYXNcclxuICAgICAgfTtcclxuICAgIH0sXHJcblxyXG4gICAgc2V0U2l6ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLmZpbmRMaXMoKTtcclxuICAgICAgdGhpcy5saUhlaWdodCgpO1xyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5oZWFkZXIpIHRoaXMuJG1lbnUuY3NzKCdwYWRkaW5nLXRvcCcsIDApO1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnNpemUgPT09IGZhbHNlKSByZXR1cm47XHJcblxyXG4gICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAkbWVudSA9IHRoaXMuJG1lbnUsXHJcbiAgICAgICAgICAkbWVudUlubmVyID0gdGhpcy4kbWVudUlubmVyLFxyXG4gICAgICAgICAgJHdpbmRvdyA9ICQod2luZG93KSxcclxuICAgICAgICAgIHNlbGVjdEhlaWdodCA9IHRoaXMuJG5ld0VsZW1lbnRbMF0ub2Zmc2V0SGVpZ2h0LFxyXG4gICAgICAgICAgc2VsZWN0V2lkdGggPSB0aGlzLiRuZXdFbGVtZW50WzBdLm9mZnNldFdpZHRoLFxyXG4gICAgICAgICAgbGlIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydsaUhlaWdodCddLFxyXG4gICAgICAgICAgaGVhZGVySGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snaGVhZGVySGVpZ2h0J10sXHJcbiAgICAgICAgICBzZWFyY2hIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydzZWFyY2hIZWlnaHQnXSxcclxuICAgICAgICAgIGFjdGlvbnNIZWlnaHQgPSB0aGlzLnNpemVJbmZvWydhY3Rpb25zSGVpZ2h0J10sXHJcbiAgICAgICAgICBkb25lQnV0dG9uSGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZG9uZUJ1dHRvbkhlaWdodCddLFxyXG4gICAgICAgICAgZGl2SGVpZ2h0ID0gdGhpcy5zaXplSW5mb1snZGl2aWRlckhlaWdodCddLFxyXG4gICAgICAgICAgbWVudVBhZGRpbmcgPSB0aGlzLnNpemVJbmZvWydtZW51UGFkZGluZyddLFxyXG4gICAgICAgICAgbWVudUV4dHJhcyA9IHRoaXMuc2l6ZUluZm9bJ21lbnVFeHRyYXMnXSxcclxuICAgICAgICAgIG5vdERpc2FibGVkID0gdGhpcy5vcHRpb25zLmhpZGVEaXNhYmxlZCA/ICcuZGlzYWJsZWQnIDogJycsXHJcbiAgICAgICAgICBtZW51SGVpZ2h0LFxyXG4gICAgICAgICAgbWVudVdpZHRoLFxyXG4gICAgICAgICAgZ2V0SGVpZ2h0LFxyXG4gICAgICAgICAgZ2V0V2lkdGgsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRCb3QsXHJcbiAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0LFxyXG4gICAgICAgICAgc2VsZWN0T2Zmc2V0UmlnaHQsXHJcbiAgICAgICAgICBnZXRQb3MgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgdmFyIHBvcyA9IHRoYXQuJG5ld0VsZW1lbnQub2Zmc2V0KCksXHJcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyID0gJCh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSxcclxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclBvcztcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyICYmICEkY29udGFpbmVyLmlzKCdib2R5JykpIHtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MgPSAkY29udGFpbmVyLm9mZnNldCgpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy50b3AgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlclRvcFdpZHRoJykpO1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcy5sZWZ0ICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJMZWZ0V2lkdGgnKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdmFyIHdpblBhZCA9IHRoYXQub3B0aW9ucy53aW5kb3dQYWRkaW5nO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgPSBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCAtICR3aW5kb3cuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgIHNlbGVjdE9mZnNldEJvdCA9ICR3aW5kb3cuaGVpZ2h0KCkgLSBzZWxlY3RPZmZzZXRUb3AgLSBzZWxlY3RIZWlnaHQgLSBjb250YWluZXJQb3MudG9wIC0gd2luUGFkWzJdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0ID0gcG9zLmxlZnQgLSBjb250YWluZXJQb3MubGVmdCAtICR3aW5kb3cuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRSaWdodCA9ICR3aW5kb3cud2lkdGgoKSAtIHNlbGVjdE9mZnNldExlZnQgLSBzZWxlY3RXaWR0aCAtIGNvbnRhaW5lclBvcy5sZWZ0IC0gd2luUGFkWzFdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRUb3AgLT0gd2luUGFkWzBdO1xyXG4gICAgICAgICAgICBzZWxlY3RPZmZzZXRMZWZ0IC09IHdpblBhZFszXTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICBnZXRQb3MoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSA9PT0gJ2F1dG8nKSB7XHJcbiAgICAgICAgdmFyIGdldFNpemUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB2YXIgbWluSGVpZ2h0LFxyXG4gICAgICAgICAgICAgIGhhc0NsYXNzID0gZnVuY3Rpb24gKGNsYXNzTmFtZSwgaW5jbHVkZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluY2x1ZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChlbGVtZW50LmNsYXNzTGlzdCA/IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSkgOiAkKGVsZW1lbnQpLmhhc0NsYXNzKGNsYXNzTmFtZSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhKGVsZW1lbnQuY2xhc3NMaXN0ID8gZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSA6ICQoZWxlbWVudCkuaGFzQ2xhc3MoY2xhc3NOYW1lKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgIGxpcyA9IHRoYXQuJG1lbnVJbm5lclswXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbGknKSxcclxuICAgICAgICAgICAgICBsaXNWaXNpYmxlID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXMsIGhhc0NsYXNzKCdoaWRkZW4nLCBmYWxzZSkpIDogdGhhdC4kbGlzLm5vdCgnLmhpZGRlbicpLFxyXG4gICAgICAgICAgICAgIG9wdEdyb3VwID0gQXJyYXkucHJvdG90eXBlLmZpbHRlciA/IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChsaXNWaXNpYmxlLCBoYXNDbGFzcygnZHJvcGRvd24taGVhZGVyJywgdHJ1ZSkpIDogbGlzVmlzaWJsZS5maWx0ZXIoJy5kcm9wZG93bi1oZWFkZXInKTtcclxuXHJcbiAgICAgICAgICBnZXRQb3MoKTtcclxuICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRCb3QgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICBtZW51V2lkdGggPSBzZWxlY3RPZmZzZXRSaWdodCAtIG1lbnVFeHRyYXMuaG9yaXo7XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgICBnZXRIZWlnaHQgPSAkbWVudS5kYXRhKCdoZWlnaHQnKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJG1lbnUuZGF0YSgnd2lkdGgnKSkgJG1lbnUuZGF0YSgnd2lkdGgnLCAkbWVudS53aWR0aCgpKTtcclxuICAgICAgICAgICAgZ2V0V2lkdGggPSAkbWVudS5kYXRhKCd3aWR0aCcpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuaGVpZ2h0KCk7XHJcbiAgICAgICAgICAgIGdldFdpZHRoID0gJG1lbnUud2lkdGgoKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLmRyb3B1cEF1dG8pIHtcclxuICAgICAgICAgICAgdGhhdC4kbmV3RWxlbWVudC50b2dnbGVDbGFzcygnZHJvcHVwJywgc2VsZWN0T2Zmc2V0VG9wID4gc2VsZWN0T2Zmc2V0Qm90ICYmIChtZW51SGVpZ2h0IC0gbWVudUV4dHJhcy52ZXJ0KSA8IGdldEhlaWdodCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2Ryb3B1cCcpKSB7XHJcbiAgICAgICAgICAgIG1lbnVIZWlnaHQgPSBzZWxlY3RPZmZzZXRUb3AgLSBtZW51RXh0cmFzLnZlcnQ7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wZG93bkFsaWduUmlnaHQgPT09ICdhdXRvJykge1xyXG4gICAgICAgICAgICAkbWVudS50b2dnbGVDbGFzcygnZHJvcGRvd24tbWVudS1yaWdodCcsIHNlbGVjdE9mZnNldExlZnQgPiBzZWxlY3RPZmZzZXRSaWdodCAmJiAobWVudVdpZHRoIC0gbWVudUV4dHJhcy5ob3JpeikgPCAoZ2V0V2lkdGggLSBzZWxlY3RXaWR0aCkpO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICgobGlzVmlzaWJsZS5sZW5ndGggKyBvcHRHcm91cC5sZW5ndGgpID4gMykge1xyXG4gICAgICAgICAgICBtaW5IZWlnaHQgPSBsaUhlaWdodCAqIDMgKyBtZW51RXh0cmFzLnZlcnQgLSAyO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbWluSGVpZ2h0ID0gMDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cnOiAnaGlkZGVuJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBtaW5IZWlnaHQgKyBoZWFkZXJIZWlnaHQgKyBzZWFyY2hIZWlnaHQgKyBhY3Rpb25zSGVpZ2h0ICsgZG9uZUJ1dHRvbkhlaWdodCArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgICAnbWF4LWhlaWdodCc6IG1lbnVIZWlnaHQgLSBoZWFkZXJIZWlnaHQgLSBzZWFyY2hIZWlnaHQgLSBhY3Rpb25zSGVpZ2h0IC0gZG9uZUJ1dHRvbkhlaWdodCAtIG1lbnVQYWRkaW5nLnZlcnQgKyAncHgnLFxyXG4gICAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICAgJ21pbi1oZWlnaHQnOiBNYXRoLm1heChtaW5IZWlnaHQgLSBtZW51UGFkZGluZy52ZXJ0LCAwKSArICdweCdcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgZ2V0U2l6ZSgpO1xyXG4gICAgICAgIHRoaXMuJHNlYXJjaGJveC5vZmYoJ2lucHV0LmdldFNpemUgcHJvcGVydHljaGFuZ2UuZ2V0U2l6ZScpLm9uKCdpbnB1dC5nZXRTaXplIHByb3BlcnR5Y2hhbmdlLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgICAkd2luZG93Lm9mZigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnKS5vbigncmVzaXplLmdldFNpemUgc2Nyb2xsLmdldFNpemUnLCBnZXRTaXplKTtcclxuICAgICAgfSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuc2l6ZSAmJiB0aGlzLm9wdGlvbnMuc2l6ZSAhPSAnYXV0bycgJiYgdGhpcy4kbGlzLm5vdChub3REaXNhYmxlZCkubGVuZ3RoID4gdGhpcy5vcHRpb25zLnNpemUpIHtcclxuICAgICAgICB2YXIgb3B0SW5kZXggPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlcicpLm5vdChub3REaXNhYmxlZCkuY2hpbGRyZW4oKS5zbGljZSgwLCB0aGlzLm9wdGlvbnMuc2l6ZSkubGFzdCgpLnBhcmVudCgpLmluZGV4KCksXHJcbiAgICAgICAgICAgIGRpdkxlbmd0aCA9IHRoaXMuJGxpcy5zbGljZSgwLCBvcHRJbmRleCArIDEpLmZpbHRlcignLmRpdmlkZXInKS5sZW5ndGg7XHJcbiAgICAgICAgbWVudUhlaWdodCA9IGxpSGVpZ2h0ICogdGhpcy5vcHRpb25zLnNpemUgKyBkaXZMZW5ndGggKiBkaXZIZWlnaHQgKyBtZW51UGFkZGluZy52ZXJ0O1xyXG5cclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmNvbnRhaW5lcikge1xyXG4gICAgICAgICAgaWYgKCEkbWVudS5kYXRhKCdoZWlnaHQnKSkgJG1lbnUuZGF0YSgnaGVpZ2h0JywgJG1lbnUuaGVpZ2h0KCkpO1xyXG4gICAgICAgICAgZ2V0SGVpZ2h0ID0gJG1lbnUuZGF0YSgnaGVpZ2h0Jyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGdldEhlaWdodCA9ICRtZW51LmhlaWdodCgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5kcm9wdXBBdXRvKSB7XHJcbiAgICAgICAgICAvL25vaW5zcGVjdGlvbiBKU1VudXNlZEFzc2lnbm1lbnRcclxuICAgICAgICAgIHRoaXMuJG5ld0VsZW1lbnQudG9nZ2xlQ2xhc3MoJ2Ryb3B1cCcsIHNlbGVjdE9mZnNldFRvcCA+IHNlbGVjdE9mZnNldEJvdCAmJiAobWVudUhlaWdodCAtIG1lbnVFeHRyYXMudmVydCkgPCBnZXRIZWlnaHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkbWVudS5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0ICsgaGVhZGVySGVpZ2h0ICsgc2VhcmNoSGVpZ2h0ICsgYWN0aW9uc0hlaWdodCArIGRvbmVCdXR0b25IZWlnaHQgKyAncHgnLFxyXG4gICAgICAgICAgJ292ZXJmbG93JzogJ2hpZGRlbicsXHJcbiAgICAgICAgICAnbWluLWhlaWdodCc6ICcnXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgJG1lbnVJbm5lci5jc3Moe1xyXG4gICAgICAgICAgJ21heC1oZWlnaHQnOiBtZW51SGVpZ2h0IC0gbWVudVBhZGRpbmcudmVydCArICdweCcsXHJcbiAgICAgICAgICAnb3ZlcmZsb3cteSc6ICdhdXRvJyxcclxuICAgICAgICAgICdtaW4taGVpZ2h0JzogJydcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZXRXaWR0aDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnYXV0bycpIHtcclxuICAgICAgICB0aGlzLiRtZW51LmNzcygnbWluLXdpZHRoJywgJzAnKTtcclxuXHJcbiAgICAgICAgLy8gR2V0IGNvcnJlY3Qgd2lkdGggaWYgZWxlbWVudCBpcyBoaWRkZW5cclxuICAgICAgICB2YXIgJHNlbGVjdENsb25lID0gdGhpcy4kbWVudS5wYXJlbnQoKS5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JyksXHJcbiAgICAgICAgICAgICRzZWxlY3RDbG9uZTIgPSB0aGlzLm9wdGlvbnMuY29udGFpbmVyID8gdGhpcy4kbmV3RWxlbWVudC5jbG9uZSgpLmFwcGVuZFRvKCdib2R5JykgOiAkc2VsZWN0Q2xvbmUsXHJcbiAgICAgICAgICAgIHVsV2lkdGggPSAkc2VsZWN0Q2xvbmUuY2hpbGRyZW4oJy5kcm9wZG93bi1tZW51Jykub3V0ZXJXaWR0aCgpLFxyXG4gICAgICAgICAgICBidG5XaWR0aCA9ICRzZWxlY3RDbG9uZTIuY3NzKCd3aWR0aCcsICdhdXRvJykuY2hpbGRyZW4oJ2J1dHRvbicpLm91dGVyV2lkdGgoKTtcclxuXHJcbiAgICAgICAgJHNlbGVjdENsb25lLnJlbW92ZSgpO1xyXG4gICAgICAgICRzZWxlY3RDbG9uZTIucmVtb3ZlKCk7XHJcblxyXG4gICAgICAgIC8vIFNldCB3aWR0aCB0byB3aGF0ZXZlcidzIGxhcmdlciwgYnV0dG9uIHRpdGxlIG9yIGxvbmdlc3Qgb3B0aW9uXHJcbiAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5jc3MoJ3dpZHRoJywgTWF0aC5tYXgodWxXaWR0aCwgYnRuV2lkdGgpICsgJ3B4Jyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLndpZHRoID09PSAnZml0Jykge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJykuYWRkQ2xhc3MoJ2ZpdC13aWR0aCcpO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy53aWR0aCkge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkIGZyb20gJ2F1dG8nXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCB0aGlzLm9wdGlvbnMud2lkdGgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFJlbW92ZSBpbmxpbmUgbWluLXdpZHRoL3dpZHRoIHNvIHdpZHRoIGNhbiBiZSBjaGFuZ2VkXHJcbiAgICAgICAgdGhpcy4kbWVudS5jc3MoJ21pbi13aWR0aCcsICcnKTtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmNzcygnd2lkdGgnLCAnJyk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gUmVtb3ZlIGZpdC13aWR0aCBjbGFzcyBpZiB3aWR0aCBpcyBjaGFuZ2VkIHByb2dyYW1tYXRpY2FsbHlcclxuICAgICAgaWYgKHRoaXMuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ2ZpdC13aWR0aCcpICYmIHRoaXMub3B0aW9ucy53aWR0aCAhPT0gJ2ZpdCcpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdmaXQtd2lkdGgnKTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRic0NvbnRhaW5lciA9ICQoJzxkaXYgY2xhc3M9XCJicy1jb250YWluZXJcIiAvPicpO1xyXG5cclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGNvbnRhaW5lciA9ICQodGhpcy5vcHRpb25zLmNvbnRhaW5lciksXHJcbiAgICAgICAgICBwb3MsXHJcbiAgICAgICAgICBjb250YWluZXJQb3MsXHJcbiAgICAgICAgICBhY3R1YWxIZWlnaHQsXHJcbiAgICAgICAgICBnZXRQbGFjZW1lbnQgPSBmdW5jdGlvbiAoJGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgdGhhdC4kYnNDb250YWluZXIuYWRkQ2xhc3MoJGVsZW1lbnQuYXR0cignY2xhc3MnKS5yZXBsYWNlKC9mb3JtLWNvbnRyb2x8Zml0LXdpZHRoL2dpLCAnJykpLnRvZ2dsZUNsYXNzKCdkcm9wdXAnLCAkZWxlbWVudC5oYXNDbGFzcygnZHJvcHVwJykpO1xyXG4gICAgICAgICAgICBwb3MgPSAkZWxlbWVudC5vZmZzZXQoKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghJGNvbnRhaW5lci5pcygnYm9keScpKSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zID0gJGNvbnRhaW5lci5vZmZzZXQoKTtcclxuICAgICAgICAgICAgICBjb250YWluZXJQb3MudG9wICs9IHBhcnNlSW50KCRjb250YWluZXIuY3NzKCdib3JkZXJUb3BXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsVG9wKCk7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyUG9zLmxlZnQgKz0gcGFyc2VJbnQoJGNvbnRhaW5lci5jc3MoJ2JvcmRlckxlZnRXaWR0aCcpKSAtICRjb250YWluZXIuc2Nyb2xsTGVmdCgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIGNvbnRhaW5lclBvcyA9IHsgdG9wOiAwLCBsZWZ0OiAwIH07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGFjdHVhbEhlaWdodCA9ICRlbGVtZW50Lmhhc0NsYXNzKCdkcm9wdXAnKSA/IDAgOiAkZWxlbWVudFswXS5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5jc3Moe1xyXG4gICAgICAgICAgICAgICd0b3AnOiBwb3MudG9wIC0gY29udGFpbmVyUG9zLnRvcCArIGFjdHVhbEhlaWdodCxcclxuICAgICAgICAgICAgICAnbGVmdCc6IHBvcy5sZWZ0IC0gY29udGFpbmVyUG9zLmxlZnQsXHJcbiAgICAgICAgICAgICAgJ3dpZHRoJzogJGVsZW1lbnRbMF0ub2Zmc2V0V2lkdGhcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9O1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLm9uKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICBpZiAodGhhdC5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGdldFBsYWNlbWVudCh0aGF0LiRuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgICAgdGhhdC4kYnNDb250YWluZXJcclxuICAgICAgICAgIC5hcHBlbmRUbyh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKVxyXG4gICAgICAgICAgLnRvZ2dsZUNsYXNzKCdvcGVuJywgISR0aGlzLmhhc0NsYXNzKCdvcGVuJykpXHJcbiAgICAgICAgICAuYXBwZW5kKHRoYXQuJG1lbnUpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgICQod2luZG93KS5vbigncmVzaXplIHNjcm9sbCcsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBnZXRQbGFjZW1lbnQodGhhdC4kbmV3RWxlbWVudCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignaGlkZS5icy5zZWxlY3QnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5kYXRhKCdoZWlnaHQnLCB0aGF0LiRtZW51LmhlaWdodCgpKTtcclxuICAgICAgICB0aGF0LiRic0NvbnRhaW5lci5kZXRhY2goKTtcclxuICAgICAgfSk7XHJcbiAgICB9LFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IC0gdGhlIGluZGV4IG9mIHRoZSBvcHRpb24gdGhhdCBpcyBiZWluZyBjaGFuZ2VkXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNlbGVjdGVkIC0gdHJ1ZSBpZiB0aGUgb3B0aW9uIGlzIGJlaW5nIHNlbGVjdGVkLCBmYWxzZSBpZiBiZWluZyBkZXNlbGVjdGVkXHJcbiAgICAgKiBAcGFyYW0ge0pRdWVyeX0gJGxpcyAtIHRoZSAnbGknIGVsZW1lbnQgdGhhdCBpcyBiZWluZyBtb2RpZmllZFxyXG4gICAgICovXHJcbiAgICBzZXRTZWxlY3RlZDogZnVuY3Rpb24gKGluZGV4LCBzZWxlY3RlZCwgJGxpcykge1xyXG4gICAgICBpZiAoISRsaXMpIHtcclxuICAgICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7IC8vIGNoZWNrIGlmIHNldFNlbGVjdGVkIGlzIGJlaW5nIGNhbGxlZCBieSBjaGFuZ2luZyB0aGUgdmFsdWUgb2YgdGhlIHNlbGVjdFxyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICRsaXMudG9nZ2xlQ2xhc3MoJ3NlbGVjdGVkJywgc2VsZWN0ZWQpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgc2VsZWN0ZWQpO1xyXG4gICAgfSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCAtIHRoZSBpbmRleCBvZiB0aGUgb3B0aW9uIHRoYXQgaXMgYmVpbmcgZGlzYWJsZWRcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlzYWJsZWQgLSB0cnVlIGlmIHRoZSBvcHRpb24gaXMgYmVpbmcgZGlzYWJsZWQsIGZhbHNlIGlmIGJlaW5nIGVuYWJsZWRcclxuICAgICAqIEBwYXJhbSB7SlF1ZXJ5fSAkbGlzIC0gdGhlICdsaScgZWxlbWVudCB0aGF0IGlzIGJlaW5nIG1vZGlmaWVkXHJcbiAgICAgKi9cclxuICAgIHNldERpc2FibGVkOiBmdW5jdGlvbiAoaW5kZXgsIGRpc2FibGVkLCAkbGlzKSB7XHJcbiAgICAgIGlmICghJGxpcykge1xyXG4gICAgICAgICRsaXMgPSB0aGlzLmZpbmRMaXMoKS5lcSh0aGlzLmxpT2JqW2luZGV4XSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChkaXNhYmxlZCkge1xyXG4gICAgICAgICRsaXMuYWRkQ2xhc3MoJ2Rpc2FibGVkJykuY2hpbGRyZW4oJ2EnKS5hdHRyKCdocmVmJywgJyMnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgJGxpcy5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5jaGlsZHJlbignYScpLnJlbW92ZUF0dHIoJ2hyZWYnKS5hdHRyKCd0YWJpbmRleCcsIDApLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCBmYWxzZSk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgaXNEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy4kZWxlbWVudFswXS5kaXNhYmxlZDtcclxuICAgIH0sXHJcblxyXG4gICAgY2hlY2tEaXNhYmxlZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcblxyXG4gICAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpIHtcclxuICAgICAgICB0aGlzLiRuZXdFbGVtZW50LmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgIHRoaXMuJGJ1dHRvbi5hZGRDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCd0YWJpbmRleCcsIC0xKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgdHJ1ZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5hdHRyKCdhcmlhLWRpc2FibGVkJywgZmFsc2UpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuJGJ1dHRvbi5hdHRyKCd0YWJpbmRleCcpID09IC0xICYmICF0aGlzLiRlbGVtZW50LmRhdGEoJ3RhYmluZGV4JykpIHtcclxuICAgICAgICAgIHRoaXMuJGJ1dHRvbi5yZW1vdmVBdHRyKCd0YWJpbmRleCcpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLmNsaWNrKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gIXRoYXQuaXNEaXNhYmxlZCgpO1xyXG4gICAgICB9KTtcclxuICAgIH0sXHJcblxyXG4gICAgdG9nZ2xlUGxhY2Vob2xkZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHZhbHVlID0gdGhpcy4kZWxlbWVudC52YWwoKTtcclxuICAgICAgdGhpcy4kYnV0dG9uLnRvZ2dsZUNsYXNzKCdicy1wbGFjZWhvbGRlcicsIHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnJyB8fCAodmFsdWUuY29uc3RydWN0b3IgPT09IEFycmF5ICYmIHZhbHVlLmxlbmd0aCA9PT0gMCkpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0YWJJbmRleDogZnVuY3Rpb24gKCkge1xyXG4gICAgICBpZiAodGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpICE9PSB0aGlzLiRlbGVtZW50LmF0dHIoJ3RhYmluZGV4JykgJiYgXHJcbiAgICAgICAgKHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gLTk4ICYmIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSAhPT0gJy05OCcpKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcsIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnKSk7XHJcbiAgICAgICAgdGhpcy4kYnV0dG9uLmF0dHIoJ3RhYmluZGV4JywgdGhpcy4kZWxlbWVudC5kYXRhKCd0YWJpbmRleCcpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcsIC05OCk7XHJcbiAgICB9LFxyXG5cclxuICAgIGNsaWNrTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJGRvY3VtZW50ID0gJChkb2N1bWVudCk7XHJcblxyXG4gICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLiRidXR0b24ub24oJ2tleXVwJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAoLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgJiYgJGRvY3VtZW50LmRhdGEoJ3NwYWNlU2VsZWN0JykpIHtcclxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICAkZG9jdW1lbnQuZGF0YSgnc3BhY2VTZWxlY3QnLCBmYWxzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC5zZXRTaXplKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kZWxlbWVudC5vbignc2hvd24uYnMuc2VsZWN0JywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICghdGhhdC5vcHRpb25zLmxpdmVTZWFyY2ggJiYgIXRoYXQubXVsdGlwbGUpIHtcclxuICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQgYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmICghdGhhdC5tdWx0aXBsZSkge1xyXG4gICAgICAgICAgdmFyIHNlbGVjdGVkSW5kZXggPSB0aGF0LmxpT2JqW3RoYXQuJGVsZW1lbnRbMF0uc2VsZWN0ZWRJbmRleF07XHJcblxyXG4gICAgICAgICAgaWYgKHR5cGVvZiBzZWxlY3RlZEluZGV4ICE9PSAnbnVtYmVyJyB8fCB0aGF0Lm9wdGlvbnMuc2l6ZSA9PT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAvLyBzY3JvbGwgdG8gc2VsZWN0ZWQgb3B0aW9uXHJcbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gdGhhdC4kbGlzLmVxKHNlbGVjdGVkSW5kZXgpWzBdLm9mZnNldFRvcCAtIHRoYXQuJG1lbnVJbm5lclswXS5vZmZzZXRUb3A7XHJcbiAgICAgICAgICBvZmZzZXQgPSBvZmZzZXQgLSB0aGF0LiRtZW51SW5uZXJbMF0ub2Zmc2V0SGVpZ2h0LzIgKyB0aGF0LnNpemVJbmZvLmxpSGVpZ2h0LzI7XHJcbiAgICAgICAgICB0aGF0LiRtZW51SW5uZXJbMF0uc2Nyb2xsVG9wID0gb2Zmc2V0O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJ2xpIGEnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAgIGNsaWNrZWRJbmRleCA9ICR0aGlzLnBhcmVudCgpLmRhdGEoJ29yaWdpbmFsSW5kZXgnKSxcclxuICAgICAgICAgICAgcHJldlZhbHVlID0gdGhhdC4kZWxlbWVudC52YWwoKSxcclxuICAgICAgICAgICAgcHJldkluZGV4ID0gdGhhdC4kZWxlbWVudC5wcm9wKCdzZWxlY3RlZEluZGV4JyksXHJcbiAgICAgICAgICAgIHRyaWdnZXJDaGFuZ2UgPSB0cnVlO1xyXG5cclxuICAgICAgICAvLyBEb24ndCBjbG9zZSBvbiBtdWx0aSBjaG9pY2UgbWVudVxyXG4gICAgICAgIGlmICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zICE9PSAxKSB7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgICAgICAvL0Rvbid0IHJ1biBpZiB3ZSBoYXZlIGJlZW4gZGlzYWJsZWRcclxuICAgICAgICBpZiAoIXRoYXQuaXNEaXNhYmxlZCgpICYmICEkdGhpcy5wYXJlbnQoKS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgdmFyICRvcHRpb25zID0gdGhhdC4kZWxlbWVudC5maW5kKCdvcHRpb24nKSxcclxuICAgICAgICAgICAgICAkb3B0aW9uID0gJG9wdGlvbnMuZXEoY2xpY2tlZEluZGV4KSxcclxuICAgICAgICAgICAgICBzdGF0ZSA9ICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSxcclxuICAgICAgICAgICAgICAkb3B0Z3JvdXAgPSAkb3B0aW9uLnBhcmVudCgnb3B0Z3JvdXAnKSxcclxuICAgICAgICAgICAgICBtYXhPcHRpb25zID0gdGhhdC5vcHRpb25zLm1heE9wdGlvbnMsXHJcbiAgICAgICAgICAgICAgbWF4T3B0aW9uc0dycCA9ICRvcHRncm91cC5kYXRhKCdtYXhPcHRpb25zJykgfHwgZmFsc2U7XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlKSB7IC8vIERlc2VsZWN0IGFsbCBvdGhlcnMgaWYgbm90IG11bHRpIHNlbGVjdCBib3hcclxuICAgICAgICAgICAgJG9wdGlvbnMucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5zZWxlY3RlZCcpLnJlbW92ZUNsYXNzKCdzZWxlY3RlZCcpLmZpbmQoJ2EnKS5hdHRyKCdhcmlhLXNlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICB0aGF0LnNldFNlbGVjdGVkKGNsaWNrZWRJbmRleCwgdHJ1ZSk7XHJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBUb2dnbGUgdGhlIG9uZSB3ZSBoYXZlIGNob3NlbiBpZiB3ZSBhcmUgbXVsdGkgc2VsZWN0LlxyXG4gICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgIXN0YXRlKTtcclxuICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsICFzdGF0ZSk7XHJcbiAgICAgICAgICAgICR0aGlzLmJsdXIoKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChtYXhPcHRpb25zICE9PSBmYWxzZSB8fCBtYXhPcHRpb25zR3JwICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgIHZhciBtYXhSZWFjaGVkID0gbWF4T3B0aW9ucyA8ICRvcHRpb25zLmZpbHRlcignOnNlbGVjdGVkJykubGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgICBtYXhSZWFjaGVkR3JwID0gbWF4T3B0aW9uc0dycCA8ICRvcHRncm91cC5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5sZW5ndGg7XHJcblxyXG4gICAgICAgICAgICAgIGlmICgobWF4T3B0aW9ucyAmJiBtYXhSZWFjaGVkKSB8fCAobWF4T3B0aW9uc0dycCAmJiBtYXhSZWFjaGVkR3JwKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4T3B0aW9ucyA9PSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb25zLnByb3AoJ3NlbGVjdGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJywgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXhPcHRpb25zR3JwICYmIG1heE9wdGlvbnNHcnAgPT0gMSkge1xyXG4gICAgICAgICAgICAgICAgICAkb3B0Z3JvdXAuZmluZCgnb3B0aW9uOnNlbGVjdGVkJykucHJvcCgnc2VsZWN0ZWQnLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgdmFyIG9wdGdyb3VwSUQgPSAkdGhpcy5wYXJlbnQoKS5kYXRhKCdvcHRncm91cCcpO1xyXG4gICAgICAgICAgICAgICAgICB0aGF0LiRtZW51SW5uZXIuZmluZCgnW2RhdGEtb3B0Z3JvdXA9XCInICsgb3B0Z3JvdXBJRCArICdcIl0nKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcclxuICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgdmFyIG1heE9wdGlvbnNUZXh0ID0gdHlwZW9mIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zVGV4dCA9PT0gJ3N0cmluZycgPyBbdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LCB0aGF0Lm9wdGlvbnMubWF4T3B0aW9uc1RleHRdIDogdGhhdC5vcHRpb25zLm1heE9wdGlvbnNUZXh0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4T3B0aW9uc0FyciA9IHR5cGVvZiBtYXhPcHRpb25zVGV4dCA9PT0gJ2Z1bmN0aW9uJyA/IG1heE9wdGlvbnNUZXh0KG1heE9wdGlvbnMsIG1heE9wdGlvbnNHcnApIDogbWF4T3B0aW9uc1RleHQsXHJcbiAgICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhPcHRpb25zQXJyWzBdLnJlcGxhY2UoJ3tufScsIG1heE9wdGlvbnMpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgbWF4VHh0R3JwID0gbWF4T3B0aW9uc0FyclsxXS5yZXBsYWNlKCd7bn0nLCBtYXhPcHRpb25zR3JwKSxcclxuICAgICAgICAgICAgICAgICAgICAgICRub3RpZnkgPSAkKCc8ZGl2IGNsYXNzPVwibm90aWZ5XCI+PC9kaXY+Jyk7XHJcbiAgICAgICAgICAgICAgICAgIC8vIElmIHt2YXJ9IGlzIHNldCBpbiBhcnJheSwgcmVwbGFjZSBpdFxyXG4gICAgICAgICAgICAgICAgICAvKiogQGRlcHJlY2F0ZWQgKi9cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNBcnJbMl0pIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHQgPSBtYXhUeHQucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnMgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgICBtYXhUeHRHcnAgPSBtYXhUeHRHcnAucmVwbGFjZSgne3Zhcn0nLCBtYXhPcHRpb25zQXJyWzJdW21heE9wdGlvbnNHcnAgPiAxID8gMCA6IDFdKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgJG9wdGlvbi5wcm9wKCdzZWxlY3RlZCcsIGZhbHNlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgIHRoYXQuJG1lbnUuYXBwZW5kKCRub3RpZnkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnMgJiYgbWF4UmVhY2hlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgaWYgKG1heE9wdGlvbnNHcnAgJiYgbWF4UmVhY2hlZEdycCkge1xyXG4gICAgICAgICAgICAgICAgICAgICRub3RpZnkuYXBwZW5kKCQoJzxkaXY+JyArIG1heFR4dEdycCArICc8L2Rpdj4nKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckNoYW5nZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuJGVsZW1lbnQudHJpZ2dlcignbWF4UmVhY2hlZEdycC5icy5zZWxlY3QnKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5zZXRTZWxlY3RlZChjbGlja2VkSW5kZXgsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgfSwgMTApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgJG5vdGlmeS5kZWxheSg3NTApLmZhZGVPdXQoMzAwLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5yZW1vdmUoKTtcclxuICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCF0aGF0Lm11bHRpcGxlIHx8ICh0aGF0Lm11bHRpcGxlICYmIHRoYXQub3B0aW9ucy5tYXhPcHRpb25zID09PSAxKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gVHJpZ2dlciBzZWxlY3QgJ2NoYW5nZSdcclxuICAgICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlKSB7XHJcbiAgICAgICAgICAgIGlmICgocHJldlZhbHVlICE9IHRoYXQuJGVsZW1lbnQudmFsKCkgJiYgdGhhdC5tdWx0aXBsZSkgfHwgKHByZXZJbmRleCAhPSB0aGF0LiRlbGVtZW50LnByb3AoJ3NlbGVjdGVkSW5kZXgnKSAmJiAhdGhhdC5tdWx0aXBsZSkpIHtcclxuICAgICAgICAgICAgICAvLyAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJykgaXMgY3VycmVudCBvcHRpb24gc3RhdGUgKHNlbGVjdGVkL3Vuc2VsZWN0ZWQpLiBzdGF0ZSBpcyBwcmV2aW91cyBvcHRpb24gc3RhdGUuXHJcbiAgICAgICAgICAgICAgY2hhbmdlZF9hcmd1bWVudHMgPSBbY2xpY2tlZEluZGV4LCAkb3B0aW9uLnByb3AoJ3NlbGVjdGVkJyksIHN0YXRlXTtcclxuICAgICAgICAgICAgICB0aGF0LiRlbGVtZW50XHJcbiAgICAgICAgICAgICAgICAudHJpZ2dlck5hdGl2ZSgnY2hhbmdlJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnbGkuZGlzYWJsZWQgYSwgLnBvcG92ZXItdGl0bGUsIC5wb3BvdmVyLXRpdGxlIDpub3QoLmNsb3NlKScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgaWYgKGUuY3VycmVudFRhcmdldCA9PSB0aGlzKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoICYmICEkKGUudGFyZ2V0KS5oYXNDbGFzcygnY2xvc2UnKSkge1xyXG4gICAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoYXQuJGJ1dHRvbi5mb2N1cygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRtZW51SW5uZXIub24oJ2NsaWNrJywgJy5kaXZpZGVyLCAuZHJvcGRvd24taGVhZGVyJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLnBvcG92ZXItdGl0bGUgLmNsb3NlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGJ1dHRvbi5jbGljaygpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJHNlYXJjaGJveC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kbWVudS5vbignY2xpY2snLCAnLmFjdGlvbnMtYnRuJywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICAgIHRoYXQuJHNlYXJjaGJveC5mb2N1cygpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcygnYnMtc2VsZWN0LWFsbCcpKSB7XHJcbiAgICAgICAgICB0aGF0LnNlbGVjdEFsbCgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LmRlc2VsZWN0QWxsKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuY2hhbmdlKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGF0LnJlbmRlcihmYWxzZSk7XHJcbiAgICAgICAgdGhhdC4kZWxlbWVudC50cmlnZ2VyKCdjaGFuZ2VkLmJzLnNlbGVjdCcsIGNoYW5nZWRfYXJndW1lbnRzKTtcclxuICAgICAgICBjaGFuZ2VkX2FyZ3VtZW50cyA9IG51bGw7XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBsaXZlU2VhcmNoTGlzdGVuZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgJG5vX3Jlc3VsdHMgPSAkKCc8bGkgY2xhc3M9XCJuby1yZXN1bHRzXCI+PC9saT4nKTtcclxuXHJcbiAgICAgIHRoaXMuJGJ1dHRvbi5vbignY2xpY2suZHJvcGRvd24uZGF0YS1hcGknLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUnKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgaWYgKCEhdGhhdC4kc2VhcmNoYm94LnZhbCgpKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3gudmFsKCcnKTtcclxuICAgICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICBpZiAoISEkbm9fcmVzdWx0cy5wYXJlbnQoKS5sZW5ndGgpICRub19yZXN1bHRzLnJlbW92ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIXRoYXQubXVsdGlwbGUpIHRoYXQuJG1lbnVJbm5lci5maW5kKCcuc2VsZWN0ZWQnKS5hZGRDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB0aGF0LiRzZWFyY2hib3guZm9jdXMoKTtcclxuICAgICAgICB9LCAxMCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy4kc2VhcmNoYm94Lm9uKCdjbGljay5kcm9wZG93bi5kYXRhLWFwaSBmb2N1cy5kcm9wZG93bi5kYXRhLWFwaSB0b3VjaGVuZC5kcm9wZG93bi5kYXRhLWFwaScsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICB0aGlzLiRzZWFyY2hib3gub24oJ2lucHV0IHByb3BlcnR5Y2hhbmdlJywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoYXQuJGxpcy5ub3QoJy5pcy1oaWRkZW4nKS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgdGhhdC4kbGlzLmZpbHRlcignLmFjdGl2ZScpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAkbm9fcmVzdWx0cy5yZW1vdmUoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoYXQuJHNlYXJjaGJveC52YWwoKSkge1xyXG4gICAgICAgICAgdmFyICRzZWFyY2hCYXNlID0gdGhhdC4kbGlzLm5vdCgnLmlzLWhpZGRlbiwgLmRpdmlkZXIsIC5kcm9wZG93bi1oZWFkZXInKSxcclxuICAgICAgICAgICAgICAkaGlkZUl0ZW1zO1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoTm9ybWFsaXplKSB7XHJcbiAgICAgICAgICAgICRoaWRlSXRlbXMgPSAkc2VhcmNoQmFzZS5ub3QoJzphJyArIHRoYXQuX3NlYXJjaFN0eWxlKCkgKyAnKFwiJyArIG5vcm1hbGl6ZVRvQmFzZSh0aGF0LiRzZWFyY2hib3gudmFsKCkpICsgJ1wiKScpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcyA9ICRzZWFyY2hCYXNlLm5vdCgnOicgKyB0aGF0Ll9zZWFyY2hTdHlsZSgpICsgJyhcIicgKyB0aGF0LiRzZWFyY2hib3gudmFsKCkgKyAnXCIpJyk7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgaWYgKCRoaWRlSXRlbXMubGVuZ3RoID09PSAkc2VhcmNoQmFzZS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgJG5vX3Jlc3VsdHMuaHRtbCh0aGF0Lm9wdGlvbnMubm9uZVJlc3VsdHNUZXh0LnJlcGxhY2UoJ3swfScsICdcIicgKyBodG1sRXNjYXBlKHRoYXQuJHNlYXJjaGJveC52YWwoKSkgKyAnXCInKSk7XHJcbiAgICAgICAgICAgIHRoYXQuJG1lbnVJbm5lci5hcHBlbmQoJG5vX3Jlc3VsdHMpO1xyXG4gICAgICAgICAgICB0aGF0LiRsaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgJGhpZGVJdGVtcy5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICB2YXIgJGxpc1Zpc2libGUgPSB0aGF0LiRsaXMubm90KCcuaGlkZGVuJyksXHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXY7XHJcblxyXG4gICAgICAgICAgICAvLyBoaWRlIGRpdmlkZXIgaWYgZmlyc3Qgb3IgbGFzdCB2aXNpYmxlLCBvciBpZiBmb2xsb3dlZCBieSBhbm90aGVyIGRpdmlkZXJcclxuICAgICAgICAgICAgJGxpc1Zpc2libGUuZWFjaChmdW5jdGlvbiAoaW5kZXgpIHtcclxuICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG5cclxuICAgICAgICAgICAgICBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2RpdmlkZXInKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZERpdiA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICR0aGlzLmFkZENsYXNzKCdoaWRkZW4nKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcbiAgICAgICAgICAgICAgICAgICRmb3VuZERpdiA9ICR0aGlzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLWhlYWRlcicpICYmICRsaXNWaXNpYmxlLmVxKGluZGV4ICsgMSkuZGF0YSgnb3B0Z3JvdXAnKSAhPT0gJHRoaXMuZGF0YSgnb3B0Z3JvdXAnKSkge1xyXG4gICAgICAgICAgICAgICAgJHRoaXMuYWRkQ2xhc3MoJ2hpZGRlbicpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAkZm91bmREaXYgPSBudWxsO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmICgkZm91bmREaXYpICRmb3VuZERpdi5hZGRDbGFzcygnaGlkZGVuJyk7XHJcblxyXG4gICAgICAgICAgICAkc2VhcmNoQmFzZS5ub3QoJy5oaWRkZW4nKS5maXJzdCgpLmFkZENsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgdGhhdC4kbWVudUlubmVyLnNjcm9sbFRvcCgwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSxcclxuXHJcbiAgICBfc2VhcmNoU3R5bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyIHN0eWxlcyA9IHtcclxuICAgICAgICBiZWdpbnM6ICdpYmVnaW5zJyxcclxuICAgICAgICBzdGFydHNXaXRoOiAnaWJlZ2lucydcclxuICAgICAgfTtcclxuXHJcbiAgICAgIHJldHVybiBzdHlsZXNbdGhpcy5vcHRpb25zLmxpdmVTZWFyY2hTdHlsZV0gfHwgJ2ljb250YWlucyc7XHJcbiAgICB9LFxyXG5cclxuICAgIHZhbDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgdGhpcy4kZWxlbWVudC52YWwodmFsdWUpO1xyXG4gICAgICAgIHRoaXMucmVuZGVyKCk7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiRlbGVtZW50LnZhbCgpO1xyXG4gICAgICB9XHJcbiAgICB9LFxyXG5cclxuICAgIGNoYW5nZUFsbDogZnVuY3Rpb24gKHN0YXR1cykge1xyXG4gICAgICBpZiAoIXRoaXMubXVsdGlwbGUpIHJldHVybjtcclxuICAgICAgaWYgKHR5cGVvZiBzdGF0dXMgPT09ICd1bmRlZmluZWQnKSBzdGF0dXMgPSB0cnVlO1xyXG5cclxuICAgICAgdGhpcy5maW5kTGlzKCk7XHJcblxyXG4gICAgICB2YXIgJG9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbicpLFxyXG4gICAgICAgICAgJGxpc1Zpc2libGUgPSB0aGlzLiRsaXMubm90KCcuZGl2aWRlciwgLmRyb3Bkb3duLWhlYWRlciwgLmRpc2FibGVkLCAuaGlkZGVuJyksXHJcbiAgICAgICAgICBsaXNWaXNMZW4gPSAkbGlzVmlzaWJsZS5sZW5ndGgsXHJcbiAgICAgICAgICBzZWxlY3RlZE9wdGlvbnMgPSBbXTtcclxuICAgICAgICAgIFxyXG4gICAgICBpZiAoc3RhdHVzKSB7XHJcbiAgICAgICAgaWYgKCRsaXNWaXNpYmxlLmZpbHRlcignLnNlbGVjdGVkJykubGVuZ3RoID09PSAkbGlzVmlzaWJsZS5sZW5ndGgpIHJldHVybjtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpZiAoJGxpc1Zpc2libGUuZmlsdGVyKCcuc2VsZWN0ZWQnKS5sZW5ndGggPT09IDApIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICAgICAgXHJcbiAgICAgICRsaXNWaXNpYmxlLnRvZ2dsZUNsYXNzKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc1Zpc0xlbjsgaSsrKSB7XHJcbiAgICAgICAgdmFyIG9yaWdJbmRleCA9ICRsaXNWaXNpYmxlW2ldLmdldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC1pbmRleCcpO1xyXG4gICAgICAgIHNlbGVjdGVkT3B0aW9uc1tzZWxlY3RlZE9wdGlvbnMubGVuZ3RoXSA9ICRvcHRpb25zLmVxKG9yaWdJbmRleClbMF07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICQoc2VsZWN0ZWRPcHRpb25zKS5wcm9wKCdzZWxlY3RlZCcsIHN0YXR1cyk7XHJcblxyXG4gICAgICB0aGlzLnJlbmRlcihmYWxzZSk7XHJcblxyXG4gICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKCk7XHJcblxyXG4gICAgICB0aGlzLiRlbGVtZW50XHJcbiAgICAgICAgLnRyaWdnZXJOYXRpdmUoJ2NoYW5nZScpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzZWxlY3RBbGw6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY2hhbmdlQWxsKHRydWUpO1xyXG4gICAgfSxcclxuXHJcbiAgICBkZXNlbGVjdEFsbDogZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdGhpcy5jaGFuZ2VBbGwoZmFsc2UpO1xyXG4gICAgfSxcclxuXHJcbiAgICB0b2dnbGU6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcclxuXHJcbiAgICAgIGlmIChlKSBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuICAgICAgdGhpcy4kYnV0dG9uLnRyaWdnZXIoJ2NsaWNrJyk7XHJcbiAgICB9LFxyXG5cclxuICAgIGtleWRvd246IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAkcGFyZW50ID0gJHRoaXMuaXMoJ2lucHV0JykgPyAkdGhpcy5wYXJlbnQoKS5wYXJlbnQoKSA6ICR0aGlzLnBhcmVudCgpLFxyXG4gICAgICAgICAgJGl0ZW1zLFxyXG4gICAgICAgICAgdGhhdCA9ICRwYXJlbnQuZGF0YSgndGhpcycpLFxyXG4gICAgICAgICAgaW5kZXgsXHJcbiAgICAgICAgICBwcmV2SW5kZXgsXHJcbiAgICAgICAgICBpc0FjdGl2ZSxcclxuICAgICAgICAgIHNlbGVjdG9yID0gJzpub3QoLmRpc2FibGVkLCAuaGlkZGVuLCAuZHJvcGRvd24taGVhZGVyLCAuZGl2aWRlciknLFxyXG4gICAgICAgICAga2V5Q29kZU1hcCA9IHtcclxuICAgICAgICAgICAgMzI6ICcgJyxcclxuICAgICAgICAgICAgNDg6ICcwJyxcclxuICAgICAgICAgICAgNDk6ICcxJyxcclxuICAgICAgICAgICAgNTA6ICcyJyxcclxuICAgICAgICAgICAgNTE6ICczJyxcclxuICAgICAgICAgICAgNTI6ICc0JyxcclxuICAgICAgICAgICAgNTM6ICc1JyxcclxuICAgICAgICAgICAgNTQ6ICc2JyxcclxuICAgICAgICAgICAgNTU6ICc3JyxcclxuICAgICAgICAgICAgNTY6ICc4JyxcclxuICAgICAgICAgICAgNTc6ICc5JyxcclxuICAgICAgICAgICAgNTk6ICc7JyxcclxuICAgICAgICAgICAgNjU6ICdhJyxcclxuICAgICAgICAgICAgNjY6ICdiJyxcclxuICAgICAgICAgICAgNjc6ICdjJyxcclxuICAgICAgICAgICAgNjg6ICdkJyxcclxuICAgICAgICAgICAgNjk6ICdlJyxcclxuICAgICAgICAgICAgNzA6ICdmJyxcclxuICAgICAgICAgICAgNzE6ICdnJyxcclxuICAgICAgICAgICAgNzI6ICdoJyxcclxuICAgICAgICAgICAgNzM6ICdpJyxcclxuICAgICAgICAgICAgNzQ6ICdqJyxcclxuICAgICAgICAgICAgNzU6ICdrJyxcclxuICAgICAgICAgICAgNzY6ICdsJyxcclxuICAgICAgICAgICAgNzc6ICdtJyxcclxuICAgICAgICAgICAgNzg6ICduJyxcclxuICAgICAgICAgICAgNzk6ICdvJyxcclxuICAgICAgICAgICAgODA6ICdwJyxcclxuICAgICAgICAgICAgODE6ICdxJyxcclxuICAgICAgICAgICAgODI6ICdyJyxcclxuICAgICAgICAgICAgODM6ICdzJyxcclxuICAgICAgICAgICAgODQ6ICd0JyxcclxuICAgICAgICAgICAgODU6ICd1JyxcclxuICAgICAgICAgICAgODY6ICd2JyxcclxuICAgICAgICAgICAgODc6ICd3JyxcclxuICAgICAgICAgICAgODg6ICd4JyxcclxuICAgICAgICAgICAgODk6ICd5JyxcclxuICAgICAgICAgICAgOTA6ICd6JyxcclxuICAgICAgICAgICAgOTY6ICcwJyxcclxuICAgICAgICAgICAgOTc6ICcxJyxcclxuICAgICAgICAgICAgOTg6ICcyJyxcclxuICAgICAgICAgICAgOTk6ICczJyxcclxuICAgICAgICAgICAgMTAwOiAnNCcsXHJcbiAgICAgICAgICAgIDEwMTogJzUnLFxyXG4gICAgICAgICAgICAxMDI6ICc2JyxcclxuICAgICAgICAgICAgMTAzOiAnNycsXHJcbiAgICAgICAgICAgIDEwNDogJzgnLFxyXG4gICAgICAgICAgICAxMDU6ICc5J1xyXG4gICAgICAgICAgfTtcclxuXHJcblxyXG4gICAgICBpc0FjdGl2ZSA9IHRoYXQuJG5ld0VsZW1lbnQuaGFzQ2xhc3MoJ29wZW4nKTtcclxuXHJcbiAgICAgIGlmICghaXNBY3RpdmUgJiYgKGUua2V5Q29kZSA+PSA0OCAmJiBlLmtleUNvZGUgPD0gNTcgfHwgZS5rZXlDb2RlID49IDk2ICYmIGUua2V5Q29kZSA8PSAxMDUgfHwgZS5rZXlDb2RlID49IDY1ICYmIGUua2V5Q29kZSA8PSA5MCkpIHtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5jb250YWluZXIpIHtcclxuICAgICAgICAgIHRoYXQuc2V0U2l6ZSgpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5hZGRDbGFzcygnb3BlbicpO1xyXG4gICAgICAgICAgaXNBY3RpdmUgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24udHJpZ2dlcignY2xpY2snKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhhdC4kc2VhcmNoYm94LmZvY3VzKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAodGhhdC5vcHRpb25zLmxpdmVTZWFyY2gpIHtcclxuICAgICAgICBpZiAoLyheOSR8MjcpLy50ZXN0KGUua2V5Q29kZS50b1N0cmluZygxMCkpICYmIGlzQWN0aXZlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmNsaWNrKCk7XHJcbiAgICAgICAgICB0aGF0LiRidXR0b24uZm9jdXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICgvKDM4fDQwKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgIGlmICghJGl0ZW1zLmxlbmd0aCkgcmV0dXJuO1xyXG5cclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICBpbmRleCA9ICRpdGVtcy5pbmRleCgkaXRlbXMuZmluZCgnYScpLmZpbHRlcignOmZvY3VzJykucGFyZW50KCkpO1xyXG5cdCAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgaW5kZXggPSAkaXRlbXMuaW5kZXgoJGl0ZW1zLmZpbHRlcignLmFjdGl2ZScpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHByZXZJbmRleCA9IHRoYXQuJG1lbnVJbm5lci5kYXRhKCdwcmV2SW5kZXgnKTtcclxuXHJcbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PSAzOCkge1xyXG4gICAgICAgICAgaWYgKCh0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCB8fCBpbmRleCA9PSBwcmV2SW5kZXgpICYmIGluZGV4ICE9IC0xKSBpbmRleC0tO1xyXG4gICAgICAgICAgaWYgKGluZGV4IDwgMCkgaW5kZXggKz0gJGl0ZW1zLmxlbmd0aDtcclxuICAgICAgICB9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSA0MCkge1xyXG4gICAgICAgICAgaWYgKHRoYXQub3B0aW9ucy5saXZlU2VhcmNoIHx8IGluZGV4ID09IHByZXZJbmRleCkgaW5kZXgrKztcclxuICAgICAgICAgIGluZGV4ID0gaW5kZXggJSAkaXRlbXMubGVuZ3RoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhhdC4kbWVudUlubmVyLmRhdGEoJ3ByZXZJbmRleCcsIGluZGV4KTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkge1xyXG4gICAgICAgICAgJGl0ZW1zLmVxKGluZGV4KS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIGlmICghJHRoaXMuaGFzQ2xhc3MoJ2Ryb3Bkb3duLXRvZ2dsZScpKSB7XHJcbiAgICAgICAgICAgICRpdGVtcy5yZW1vdmVDbGFzcygnYWN0aXZlJykuZXEoaW5kZXgpLmFkZENsYXNzKCdhY3RpdmUnKS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcbiAgICAgICAgICAgICR0aGlzLmZvY3VzKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgfSBlbHNlIGlmICghJHRoaXMuaXMoJ2lucHV0JykpIHtcclxuICAgICAgICB2YXIga2V5SW5kZXggPSBbXSxcclxuICAgICAgICAgICAgY291bnQsXHJcbiAgICAgICAgICAgIHByZXZLZXk7XHJcblxyXG4gICAgICAgICRpdGVtcyA9IHRoYXQuJGxpcy5maWx0ZXIoc2VsZWN0b3IpO1xyXG4gICAgICAgICRpdGVtcy5lYWNoKGZ1bmN0aW9uIChpKSB7XHJcbiAgICAgICAgICBpZiAoJC50cmltKCQodGhpcykuY2hpbGRyZW4oJ2EnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpID09IGtleUNvZGVNYXBbZS5rZXlDb2RlXSkge1xyXG4gICAgICAgICAgICBrZXlJbmRleC5wdXNoKGkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBjb3VudCA9ICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50Jyk7XHJcbiAgICAgICAgY291bnQrKztcclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIGNvdW50KTtcclxuXHJcbiAgICAgICAgcHJldktleSA9ICQudHJpbSgkKCc6Zm9jdXMnKS50ZXh0KCkudG9Mb3dlckNhc2UoKSkuc3Vic3RyaW5nKDAsIDEpO1xyXG5cclxuICAgICAgICBpZiAocHJldktleSAhPSBrZXlDb2RlTWFwW2Uua2V5Q29kZV0pIHtcclxuICAgICAgICAgIGNvdW50ID0gMTtcclxuICAgICAgICAgICQoZG9jdW1lbnQpLmRhdGEoJ2tleWNvdW50JywgY291bnQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoY291bnQgPj0ga2V5SW5kZXgubGVuZ3RoKSB7XHJcbiAgICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICAgICAgaWYgKGNvdW50ID4ga2V5SW5kZXgubGVuZ3RoKSBjb3VudCA9IDE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAkaXRlbXMuZXEoa2V5SW5kZXhbY291bnQgLSAxXSkuY2hpbGRyZW4oJ2EnKS5mb2N1cygpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZWxlY3QgZm9jdXNlZCBvcHRpb24gaWYgXCJFbnRlclwiLCBcIlNwYWNlYmFyXCIgb3IgXCJUYWJcIiAod2hlbiBzZWxlY3RPblRhYiBpcyB0cnVlKSBhcmUgcHJlc3NlZCBpbnNpZGUgdGhlIG1lbnUuXHJcbiAgICAgIGlmICgoLygxM3wzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkgfHwgKC8oXjkkKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiB0aGF0Lm9wdGlvbnMuc2VsZWN0T25UYWIpKSAmJiBpc0FjdGl2ZSkge1xyXG4gICAgICAgIGlmICghLygzMikvLnRlc3QoZS5rZXlDb2RlLnRvU3RyaW5nKDEwKSkpIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBpZiAoIXRoYXQub3B0aW9ucy5saXZlU2VhcmNoKSB7XHJcbiAgICAgICAgICB2YXIgZWxlbSA9ICQoJzpmb2N1cycpO1xyXG4gICAgICAgICAgZWxlbS5jbGljaygpO1xyXG4gICAgICAgICAgLy8gQnJpbmcgYmFjayBmb2N1cyBmb3IgbXVsdGlzZWxlY3RzXHJcbiAgICAgICAgICBlbGVtLmZvY3VzKCk7XHJcbiAgICAgICAgICAvLyBQcmV2ZW50IHNjcmVlbiBmcm9tIHNjcm9sbGluZyBpZiB0aGUgdXNlciBoaXQgdGhlIHNwYWNlYmFyXHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAvLyBGaXhlcyBzcGFjZWJhciBzZWxlY3Rpb24gb2YgZHJvcGRvd24gaXRlbXMgaW4gRkYgJiBJRVxyXG4gICAgICAgICAgJChkb2N1bWVudCkuZGF0YSgnc3BhY2VTZWxlY3QnLCB0cnVlKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCEvKDMyKS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSkge1xyXG4gICAgICAgICAgdGhhdC4kbWVudUlubmVyLmZpbmQoJy5hY3RpdmUgYScpLmNsaWNrKCk7XHJcbiAgICAgICAgICAkdGhpcy5mb2N1cygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAkKGRvY3VtZW50KS5kYXRhKCdrZXljb3VudCcsIDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoKC8oXjkkfDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiBpc0FjdGl2ZSAmJiAodGhhdC5tdWx0aXBsZSB8fCB0aGF0Lm9wdGlvbnMubGl2ZVNlYXJjaCkpIHx8ICgvKDI3KS8udGVzdChlLmtleUNvZGUudG9TdHJpbmcoMTApKSAmJiAhaXNBY3RpdmUpKSB7XHJcbiAgICAgICAgdGhhdC4kbWVudS5wYXJlbnQoKS5yZW1vdmVDbGFzcygnb3BlbicpO1xyXG4gICAgICAgIGlmICh0aGF0Lm9wdGlvbnMuY29udGFpbmVyKSB0aGF0LiRuZXdFbGVtZW50LnJlbW92ZUNsYXNzKCdvcGVuJyk7XHJcbiAgICAgICAgdGhhdC4kYnV0dG9uLmZvY3VzKCk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcblxyXG4gICAgbW9iaWxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJGVsZW1lbnQuYWRkQ2xhc3MoJ21vYmlsZS1kZXZpY2UnKTtcclxuICAgIH0sXHJcblxyXG4gICAgcmVmcmVzaDogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRsaXMgPSBudWxsO1xyXG4gICAgICB0aGlzLmxpT2JqID0ge307XHJcbiAgICAgIHRoaXMucmVsb2FkTGkoKTtcclxuICAgICAgdGhpcy5yZW5kZXIoKTtcclxuICAgICAgdGhpcy5jaGVja0Rpc2FibGVkKCk7XHJcbiAgICAgIHRoaXMubGlIZWlnaHQodHJ1ZSk7XHJcbiAgICAgIHRoaXMuc2V0U3R5bGUoKTtcclxuICAgICAgdGhpcy5zZXRXaWR0aCgpO1xyXG4gICAgICBpZiAodGhpcy4kbGlzKSB0aGlzLiRzZWFyY2hib3gudHJpZ2dlcigncHJvcGVydHljaGFuZ2UnKTtcclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcigncmVmcmVzaGVkLmJzLnNlbGVjdCcpO1xyXG4gICAgfSxcclxuXHJcbiAgICBoaWRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuaGlkZSgpO1xyXG4gICAgfSxcclxuXHJcbiAgICBzaG93OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgIHRoaXMuJG5ld0VsZW1lbnQuc2hvdygpO1xyXG4gICAgfSxcclxuXHJcbiAgICByZW1vdmU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgdGhpcy4kbmV3RWxlbWVudC5yZW1vdmUoKTtcclxuICAgICAgdGhpcy4kZWxlbWVudC5yZW1vdmUoKTtcclxuICAgIH0sXHJcblxyXG4gICAgZGVzdHJveTogZnVuY3Rpb24gKCkge1xyXG4gICAgICB0aGlzLiRuZXdFbGVtZW50LmJlZm9yZSh0aGlzLiRlbGVtZW50KS5yZW1vdmUoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLiRic0NvbnRhaW5lcikge1xyXG4gICAgICAgIHRoaXMuJGJzQ29udGFpbmVyLnJlbW92ZSgpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuJG1lbnUucmVtb3ZlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuJGVsZW1lbnRcclxuICAgICAgICAub2ZmKCcuYnMuc2VsZWN0JylcclxuICAgICAgICAucmVtb3ZlRGF0YSgnc2VsZWN0cGlja2VyJylcclxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ2JzLXNlbGVjdC1oaWRkZW4gc2VsZWN0cGlja2VyJyk7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIFBMVUdJTiBERUZJTklUSU9OXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xyXG4gICAgLy8gZ2V0IHRoZSBhcmdzIG9mIHRoZSBvdXRlciBmdW5jdGlvbi4uXHJcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcclxuICAgIC8vIFRoZSBhcmd1bWVudHMgb2YgdGhlIGZ1bmN0aW9uIGFyZSBleHBsaWNpdGx5IHJlLWRlZmluZWQgZnJvbSB0aGUgYXJndW1lbnQgbGlzdCwgYmVjYXVzZSB0aGUgc2hpZnQgY2F1c2VzIHRoZW1cclxuICAgIC8vIHRvIGdldCBsb3N0L2NvcnJ1cHRlZCBpbiBhbmRyb2lkIDIuMyBhbmQgSUU5ICM3MTUgIzc3NVxyXG4gICAgdmFyIF9vcHRpb24gPSBvcHRpb247XHJcblxyXG4gICAgW10uc2hpZnQuYXBwbHkoYXJncyk7XHJcblxyXG4gICAgdmFyIHZhbHVlO1xyXG4gICAgdmFyIGNoYWluID0gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcclxuICAgICAgaWYgKCR0aGlzLmlzKCdzZWxlY3QnKSkge1xyXG4gICAgICAgIHZhciBkYXRhID0gJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJyksXHJcbiAgICAgICAgICAgIG9wdGlvbnMgPSB0eXBlb2YgX29wdGlvbiA9PSAnb2JqZWN0JyAmJiBfb3B0aW9uO1xyXG5cclxuICAgICAgICBpZiAoIWRhdGEpIHtcclxuICAgICAgICAgIHZhciBjb25maWcgPSAkLmV4dGVuZCh7fSwgU2VsZWN0cGlja2VyLkRFRkFVTFRTLCAkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyB8fCB7fSwgJHRoaXMuZGF0YSgpLCBvcHRpb25zKTtcclxuICAgICAgICAgIGNvbmZpZy50ZW1wbGF0ZSA9ICQuZXh0ZW5kKHt9LCBTZWxlY3RwaWNrZXIuREVGQVVMVFMudGVtcGxhdGUsICgkLmZuLnNlbGVjdHBpY2tlci5kZWZhdWx0cyA/ICQuZm4uc2VsZWN0cGlja2VyLmRlZmF1bHRzLnRlbXBsYXRlIDoge30pLCAkdGhpcy5kYXRhKCkudGVtcGxhdGUsIG9wdGlvbnMudGVtcGxhdGUpO1xyXG4gICAgICAgICAgJHRoaXMuZGF0YSgnc2VsZWN0cGlja2VyJywgKGRhdGEgPSBuZXcgU2VsZWN0cGlja2VyKHRoaXMsIGNvbmZpZykpKTtcclxuICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMpIHtcclxuICAgICAgICAgIGZvciAodmFyIGkgaW4gb3B0aW9ucykge1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG4gICAgICAgICAgICAgIGRhdGEub3B0aW9uc1tpXSA9IG9wdGlvbnNbaV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YgX29wdGlvbiA9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgaWYgKGRhdGFbX29wdGlvbl0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGFbX29wdGlvbl0uYXBwbHkoZGF0YSwgYXJncyk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB2YWx1ZSA9IGRhdGEub3B0aW9uc1tfb3B0aW9uXTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkQXNzaWdubWVudFxyXG4gICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gY2hhaW47XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgb2xkID0gJC5mbi5zZWxlY3RwaWNrZXI7XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIgPSBQbHVnaW47XHJcbiAgJC5mbi5zZWxlY3RwaWNrZXIuQ29uc3RydWN0b3IgPSBTZWxlY3RwaWNrZXI7XHJcblxyXG4gIC8vIFNFTEVDVFBJQ0tFUiBOTyBDT05GTElDVFxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gICQuZm4uc2VsZWN0cGlja2VyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAkLmZuLnNlbGVjdHBpY2tlciA9IG9sZDtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH07XHJcblxyXG4gICQoZG9jdW1lbnQpXHJcbiAgICAgIC5kYXRhKCdrZXljb3VudCcsIDApXHJcbiAgICAgIC5vbigna2V5ZG93bi5icy5zZWxlY3QnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgU2VsZWN0cGlja2VyLnByb3RvdHlwZS5rZXlkb3duKVxyXG4gICAgICAub24oJ2ZvY3VzaW4ubW9kYWwnLCAnLmJvb3RzdHJhcC1zZWxlY3QgW2RhdGEtdG9nZ2xlPWRyb3Bkb3duXSwgLmJvb3RzdHJhcC1zZWxlY3QgW3JvbGU9XCJsaXN0Ym94XCJdLCAuYnMtc2VhcmNoYm94IGlucHV0JywgZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgLy8gU0VMRUNUUElDS0VSIERBVEEtQVBJXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09XHJcbiAgJCh3aW5kb3cpLm9uKCdsb2FkLmJzLnNlbGVjdC5kYXRhLWFwaScsIGZ1bmN0aW9uICgpIHtcclxuICAgICQoJy5zZWxlY3RwaWNrZXInKS5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgdmFyICRzZWxlY3RwaWNrZXIgPSAkKHRoaXMpO1xyXG4gICAgICBQbHVnaW4uY2FsbCgkc2VsZWN0cGlja2VyLCAkc2VsZWN0cGlja2VyLmRhdGEoKSk7XHJcbiAgICB9KVxyXG4gIH0pO1xyXG59KShqUXVlcnkpO1xyXG5cblxufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXNlbGVjdC9kaXN0L2pzL2Jvb3RzdHJhcC1zZWxlY3QuanNcbi8vIG1vZHVsZSBpZCA9IDE1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQm9vdHN0cmFwIChwbHVnaW4pOiB2YWxpZGF0b3IuanMgdjAuMTEuOVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYgQ2luYSBTYWZmYXJ5LlxuICogTWFkZSBieSBAMTAwMGh6IGluIHRoZSBzdHlsZSBvZiBCb290c3RyYXAgMyBlcmEgQGZhdFxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAqIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAqIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuICogYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4gKiBUSEUgU09GVFdBUkUuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuXG4rZnVuY3Rpb24gKCQpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8vIFZBTElEQVRPUiBDTEFTUyBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgZnVuY3Rpb24gZ2V0VmFsdWUoJGVsKSB7XG4gICAgcmV0dXJuICRlbC5pcygnW3R5cGU9XCJjaGVja2JveFwiXScpID8gJGVsLnByb3AoJ2NoZWNrZWQnKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6XG4gICAgICAgICAgICRlbC5pcygnW3R5cGU9XCJyYWRpb1wiXScpICAgID8gISEkKCdbbmFtZT1cIicgKyAkZWwuYXR0cignbmFtZScpICsgJ1wiXTpjaGVja2VkJykubGVuZ3RoIDpcbiAgICAgICAgICAgJGVsLmlzKCdzZWxlY3RbbXVsdGlwbGVdJykgID8gKCRlbC52YWwoKSB8fCBbXSkubGVuZ3RoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbC52YWwoKVxuICB9XG5cbiAgdmFyIFZhbGlkYXRvciA9IGZ1bmN0aW9uIChlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zICAgID0gb3B0aW9uc1xuICAgIHRoaXMudmFsaWRhdG9ycyA9ICQuZXh0ZW5kKHt9LCBWYWxpZGF0b3IuVkFMSURBVE9SUywgb3B0aW9ucy5jdXN0b20pXG4gICAgdGhpcy4kZWxlbWVudCAgID0gJChlbGVtZW50KVxuICAgIHRoaXMuJGJ0biAgICAgICA9ICQoJ2J1dHRvblt0eXBlPVwic3VibWl0XCJdLCBpbnB1dFt0eXBlPVwic3VibWl0XCJdJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoJ1tmb3JtPVwiJyArIHRoaXMuJGVsZW1lbnQuYXR0cignaWQnKSArICdcIl0nKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFkZCh0aGlzLiRlbGVtZW50LmZpbmQoJ2lucHV0W3R5cGU9XCJzdWJtaXRcIl0sIGJ1dHRvblt0eXBlPVwic3VibWl0XCJdJykpXG5cbiAgICB0aGlzLnVwZGF0ZSgpXG5cbiAgICB0aGlzLiRlbGVtZW50Lm9uKCdpbnB1dC5icy52YWxpZGF0b3IgY2hhbmdlLmJzLnZhbGlkYXRvciBmb2N1c291dC5icy52YWxpZGF0b3InLCAkLnByb3h5KHRoaXMub25JbnB1dCwgdGhpcykpXG4gICAgdGhpcy4kZWxlbWVudC5vbignc3VibWl0LmJzLnZhbGlkYXRvcicsICQucHJveHkodGhpcy5vblN1Ym1pdCwgdGhpcykpXG4gICAgdGhpcy4kZWxlbWVudC5vbigncmVzZXQuYnMudmFsaWRhdG9yJywgJC5wcm94eSh0aGlzLnJlc2V0LCB0aGlzKSlcblxuICAgIHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtbWF0Y2hdJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRoaXMgID0gJCh0aGlzKVxuICAgICAgdmFyIHRhcmdldCA9ICR0aGlzLmF0dHIoJ2RhdGEtbWF0Y2gnKVxuXG4gICAgICAkKHRhcmdldCkub24oJ2lucHV0LmJzLnZhbGlkYXRvcicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGdldFZhbHVlKCR0aGlzKSAmJiAkdGhpcy50cmlnZ2VyKCdpbnB1dC5icy52YWxpZGF0b3InKVxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgLy8gcnVuIHZhbGlkYXRvcnMgZm9yIGZpZWxkcyB3aXRoIHZhbHVlcywgYnV0IGRvbid0IGNsb2JiZXIgc2VydmVyLXNpZGUgZXJyb3JzXG4gICAgdGhpcy4kaW5wdXRzLmZpbHRlcihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZ2V0VmFsdWUoJCh0aGlzKSkgJiYgISQodGhpcykuY2xvc2VzdCgnLmhhcy1lcnJvcicpLmxlbmd0aFxuICAgIH0pLnRyaWdnZXIoJ2ZvY3Vzb3V0JylcblxuICAgIHRoaXMuJGVsZW1lbnQuYXR0cignbm92YWxpZGF0ZScsIHRydWUpIC8vIGRpc2FibGUgYXV0b21hdGljIG5hdGl2ZSB2YWxpZGF0aW9uXG4gIH1cblxuICBWYWxpZGF0b3IuVkVSU0lPTiA9ICcwLjExLjknXG5cbiAgVmFsaWRhdG9yLklOUFVUX1NFTEVDVE9SID0gJzppbnB1dDpub3QoW3R5cGU9XCJoaWRkZW5cIl0sIFt0eXBlPVwic3VibWl0XCJdLCBbdHlwZT1cInJlc2V0XCJdLCBidXR0b24pJ1xuXG4gIFZhbGlkYXRvci5GT0NVU19PRkZTRVQgPSAyMFxuXG4gIFZhbGlkYXRvci5ERUZBVUxUUyA9IHtcbiAgICBkZWxheTogNTAwLFxuICAgIGh0bWw6IGZhbHNlLFxuICAgIGRpc2FibGU6IHRydWUsXG4gICAgZm9jdXM6IHRydWUsXG4gICAgY3VzdG9tOiB7fSxcbiAgICBlcnJvcnM6IHtcbiAgICAgIG1hdGNoOiAnRG9lcyBub3QgbWF0Y2gnLFxuICAgICAgbWlubGVuZ3RoOiAnTm90IGxvbmcgZW5vdWdoJ1xuICAgIH0sXG4gICAgZmVlZGJhY2s6IHtcbiAgICAgIHN1Y2Nlc3M6ICdnbHlwaGljb24tb2snLFxuICAgICAgZXJyb3I6ICdnbHlwaGljb24tcmVtb3ZlJ1xuICAgIH1cbiAgfVxuXG4gIFZhbGlkYXRvci5WQUxJREFUT1JTID0ge1xuICAgICduYXRpdmUnOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICB2YXIgZWwgPSAkZWxbMF1cbiAgICAgIGlmIChlbC5jaGVja1ZhbGlkaXR5KSB7XG4gICAgICAgIHJldHVybiAhZWwuY2hlY2tWYWxpZGl0eSgpICYmICFlbC52YWxpZGl0eS52YWxpZCAmJiAoZWwudmFsaWRhdGlvbk1lc3NhZ2UgfHwgXCJlcnJvciFcIilcbiAgICAgIH1cbiAgICB9LFxuICAgICdtYXRjaCc6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgIHZhciB0YXJnZXQgPSAkZWwuYXR0cignZGF0YS1tYXRjaCcpXG4gICAgICByZXR1cm4gJGVsLnZhbCgpICE9PSAkKHRhcmdldCkudmFsKCkgJiYgVmFsaWRhdG9yLkRFRkFVTFRTLmVycm9ycy5tYXRjaFxuICAgIH0sXG4gICAgJ21pbmxlbmd0aCc6IGZ1bmN0aW9uICgkZWwpIHtcbiAgICAgIHZhciBtaW5sZW5ndGggPSAkZWwuYXR0cignZGF0YS1taW5sZW5ndGgnKVxuICAgICAgcmV0dXJuICRlbC52YWwoKS5sZW5ndGggPCBtaW5sZW5ndGggJiYgVmFsaWRhdG9yLkRFRkFVTFRTLmVycm9ycy5taW5sZW5ndGhcbiAgICB9XG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXNcblxuICAgIHRoaXMuJGlucHV0cyA9IHRoaXMuJGVsZW1lbnQuZmluZChWYWxpZGF0b3IuSU5QVVRfU0VMRUNUT1IpXG4gICAgICAuYWRkKHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtdmFsaWRhdGU9XCJ0cnVlXCJdJykpXG4gICAgICAubm90KHRoaXMuJGVsZW1lbnQuZmluZCgnW2RhdGEtdmFsaWRhdGU9XCJmYWxzZVwiXScpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHsgc2VsZi5jbGVhckVycm9ycygkKHRoaXMpKSB9KVxuICAgICAgKVxuXG4gICAgdGhpcy50b2dnbGVTdWJtaXQoKVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUub25JbnB1dCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIHNlbGYgICAgICAgID0gdGhpc1xuICAgIHZhciAkZWwgICAgICAgICA9ICQoZS50YXJnZXQpXG4gICAgdmFyIGRlZmVyRXJyb3JzID0gZS50eXBlICE9PSAnZm9jdXNvdXQnXG5cbiAgICBpZiAoIXRoaXMuJGlucHV0cy5pcygkZWwpKSByZXR1cm5cblxuICAgIHRoaXMudmFsaWRhdGVJbnB1dCgkZWwsIGRlZmVyRXJyb3JzKS5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYudG9nZ2xlU3VibWl0KClcbiAgICB9KVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS52YWxpZGF0ZUlucHV0ID0gZnVuY3Rpb24gKCRlbCwgZGVmZXJFcnJvcnMpIHtcbiAgICB2YXIgdmFsdWUgICAgICA9IGdldFZhbHVlKCRlbClcbiAgICB2YXIgcHJldkVycm9ycyA9ICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJylcblxuICAgIGlmICgkZWwuaXMoJ1t0eXBlPVwicmFkaW9cIl0nKSkgJGVsID0gdGhpcy4kZWxlbWVudC5maW5kKCdpbnB1dFtuYW1lPVwiJyArICRlbC5hdHRyKCduYW1lJykgKyAnXCJdJylcblxuICAgIHZhciBlID0gJC5FdmVudCgndmFsaWRhdGUuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXX0pXG4gICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKGUpXG4gICAgaWYgKGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHJldHVyblxuXG4gICAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgICByZXR1cm4gdGhpcy5ydW5WYWxpZGF0b3JzKCRlbCkuZG9uZShmdW5jdGlvbiAoZXJyb3JzKSB7XG4gICAgICAkZWwuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycsIGVycm9ycylcblxuICAgICAgZXJyb3JzLmxlbmd0aFxuICAgICAgICA/IGRlZmVyRXJyb3JzID8gc2VsZi5kZWZlcigkZWwsIHNlbGYuc2hvd0Vycm9ycykgOiBzZWxmLnNob3dFcnJvcnMoJGVsKVxuICAgICAgICA6IHNlbGYuY2xlYXJFcnJvcnMoJGVsKVxuXG4gICAgICBpZiAoIXByZXZFcnJvcnMgfHwgZXJyb3JzLnRvU3RyaW5nKCkgIT09IHByZXZFcnJvcnMudG9TdHJpbmcoKSkge1xuICAgICAgICBlID0gZXJyb3JzLmxlbmd0aFxuICAgICAgICAgID8gJC5FdmVudCgnaW52YWxpZC5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdLCBkZXRhaWw6IGVycm9yc30pXG4gICAgICAgICAgOiAkLkV2ZW50KCd2YWxpZC5icy52YWxpZGF0b3InLCB7cmVsYXRlZFRhcmdldDogJGVsWzBdLCBkZXRhaWw6IHByZXZFcnJvcnN9KVxuXG4gICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcihlKVxuICAgICAgfVxuXG4gICAgICBzZWxmLnRvZ2dsZVN1Ym1pdCgpXG5cbiAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcigkLkV2ZW50KCd2YWxpZGF0ZWQuYnMudmFsaWRhdG9yJywge3JlbGF0ZWRUYXJnZXQ6ICRlbFswXX0pKVxuICAgIH0pXG4gIH1cblxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUucnVuVmFsaWRhdG9ycyA9IGZ1bmN0aW9uICgkZWwpIHtcbiAgICB2YXIgZXJyb3JzICAgPSBbXVxuICAgIHZhciBkZWZlcnJlZCA9ICQuRGVmZXJyZWQoKVxuXG4gICAgJGVsLmRhdGEoJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCcpICYmICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZGVmZXJyZWQnKS5yZWplY3QoKVxuICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZGVmZXJyZWQnLCBkZWZlcnJlZClcblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkYXRvclNwZWNpZmljRXJyb3Ioa2V5KSB7XG4gICAgICByZXR1cm4gJGVsLmF0dHIoJ2RhdGEtJyArIGtleSArICctZXJyb3InKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkaXR5U3RhdGVFcnJvcigpIHtcbiAgICAgIHZhciB2YWxpZGl0eSA9ICRlbFswXS52YWxpZGl0eVxuICAgICAgcmV0dXJuIHZhbGlkaXR5LnR5cGVNaXNtYXRjaCAgICA/ICRlbC5hdHRyKCdkYXRhLXR5cGUtZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnBhdHRlcm5NaXNtYXRjaCA/ICRlbC5hdHRyKCdkYXRhLXBhdHRlcm4tZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnN0ZXBNaXNtYXRjaCAgICA/ICRlbC5hdHRyKCdkYXRhLXN0ZXAtZXJyb3InKVxuICAgICAgICAgICA6IHZhbGlkaXR5LnJhbmdlT3ZlcmZsb3cgICA/ICRlbC5hdHRyKCdkYXRhLW1heC1lcnJvcicpXG4gICAgICAgICAgIDogdmFsaWRpdHkucmFuZ2VVbmRlcmZsb3cgID8gJGVsLmF0dHIoJ2RhdGEtbWluLWVycm9yJylcbiAgICAgICAgICAgOiB2YWxpZGl0eS52YWx1ZU1pc3NpbmcgICAgPyAkZWwuYXR0cignZGF0YS1yZXF1aXJlZC1lcnJvcicpXG4gICAgICAgICAgIDogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVsbFxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEdlbmVyaWNFcnJvcigpIHtcbiAgICAgIHJldHVybiAkZWwuYXR0cignZGF0YS1lcnJvcicpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGtleSkge1xuICAgICAgcmV0dXJuIGdldFZhbGlkYXRvclNwZWNpZmljRXJyb3Ioa2V5KVxuICAgICAgICAgIHx8IGdldFZhbGlkaXR5U3RhdGVFcnJvcigpXG4gICAgICAgICAgfHwgZ2V0R2VuZXJpY0Vycm9yKClcbiAgICB9XG5cbiAgICAkLmVhY2godGhpcy52YWxpZGF0b3JzLCAkLnByb3h5KGZ1bmN0aW9uIChrZXksIHZhbGlkYXRvcikge1xuICAgICAgdmFyIGVycm9yID0gbnVsbFxuICAgICAgaWYgKChnZXRWYWx1ZSgkZWwpIHx8ICRlbC5hdHRyKCdyZXF1aXJlZCcpKSAmJlxuICAgICAgICAgICgkZWwuYXR0cignZGF0YS0nICsga2V5KSAhPT0gdW5kZWZpbmVkIHx8IGtleSA9PSAnbmF0aXZlJykgJiZcbiAgICAgICAgICAoZXJyb3IgPSB2YWxpZGF0b3IuY2FsbCh0aGlzLCAkZWwpKSkge1xuICAgICAgICAgZXJyb3IgPSBnZXRFcnJvck1lc3NhZ2Uoa2V5KSB8fCBlcnJvclxuICAgICAgICAhfmVycm9ycy5pbmRleE9mKGVycm9yKSAmJiBlcnJvcnMucHVzaChlcnJvcilcbiAgICAgIH1cbiAgICB9LCB0aGlzKSlcblxuICAgIGlmICghZXJyb3JzLmxlbmd0aCAmJiBnZXRWYWx1ZSgkZWwpICYmICRlbC5hdHRyKCdkYXRhLXJlbW90ZScpKSB7XG4gICAgICB0aGlzLmRlZmVyKCRlbCwgZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGF0YSA9IHt9XG4gICAgICAgIGRhdGFbJGVsLmF0dHIoJ25hbWUnKV0gPSBnZXRWYWx1ZSgkZWwpXG4gICAgICAgICQuZ2V0KCRlbC5hdHRyKCdkYXRhLXJlbW90ZScpLCBkYXRhKVxuICAgICAgICAgIC5mYWlsKGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3IpIHsgZXJyb3JzLnB1c2goZ2V0RXJyb3JNZXNzYWdlKCdyZW1vdGUnKSB8fCBlcnJvcikgfSlcbiAgICAgICAgICAuYWx3YXlzKGZ1bmN0aW9uICgpIHsgZGVmZXJyZWQucmVzb2x2ZShlcnJvcnMpfSlcbiAgICAgIH0pXG4gICAgfSBlbHNlIGRlZmVycmVkLnJlc29sdmUoZXJyb3JzKVxuXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2UoKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS52YWxpZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXNcblxuICAgICQud2hlbih0aGlzLiRpbnB1dHMubWFwKGZ1bmN0aW9uIChlbCkge1xuICAgICAgcmV0dXJuIHNlbGYudmFsaWRhdGVJbnB1dCgkKHRoaXMpLCBmYWxzZSlcbiAgICB9KSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLnRvZ2dsZVN1Ym1pdCgpXG4gICAgICBzZWxmLmZvY3VzRXJyb3IoKVxuICAgIH0pXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5mb2N1c0Vycm9yID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmZvY3VzKSByZXR1cm5cblxuICAgIHZhciAkaW5wdXQgPSB0aGlzLiRlbGVtZW50LmZpbmQoXCIuaGFzLWVycm9yOmZpcnN0IDppbnB1dFwiKVxuICAgIGlmICgkaW5wdXQubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHtzY3JvbGxUb3A6ICRpbnB1dC5vZmZzZXQoKS50b3AgLSBWYWxpZGF0b3IuRk9DVVNfT0ZGU0VUfSwgMjUwKVxuICAgICRpbnB1dC5mb2N1cygpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLnNob3dFcnJvcnMgPSBmdW5jdGlvbiAoJGVsKSB7XG4gICAgdmFyIG1ldGhvZCA9IHRoaXMub3B0aW9ucy5odG1sID8gJ2h0bWwnIDogJ3RleHQnXG4gICAgdmFyIGVycm9ycyA9ICRlbC5kYXRhKCdicy52YWxpZGF0b3IuZXJyb3JzJylcbiAgICB2YXIgJGdyb3VwID0gJGVsLmNsb3Nlc3QoJy5mb3JtLWdyb3VwJylcbiAgICB2YXIgJGJsb2NrID0gJGdyb3VwLmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICB2YXIgJGZlZWRiYWNrID0gJGdyb3VwLmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuXG4gICAgaWYgKCFlcnJvcnMubGVuZ3RoKSByZXR1cm5cblxuICAgIGVycm9ycyA9ICQoJzx1bC8+JylcbiAgICAgIC5hZGRDbGFzcygnbGlzdC11bnN0eWxlZCcpXG4gICAgICAuYXBwZW5kKCQubWFwKGVycm9ycywgZnVuY3Rpb24gKGVycm9yKSB7IHJldHVybiAkKCc8bGkvPicpW21ldGhvZF0oZXJyb3IpIH0pKVxuXG4gICAgJGJsb2NrLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKSA9PT0gdW5kZWZpbmVkICYmICRibG9jay5kYXRhKCdicy52YWxpZGF0b3Iub3JpZ2luYWxDb250ZW50JywgJGJsb2NrLmh0bWwoKSlcbiAgICAkYmxvY2suZW1wdHkoKS5hcHBlbmQoZXJyb3JzKVxuICAgICRncm91cC5hZGRDbGFzcygnaGFzLWVycm9yIGhhcy1kYW5nZXInKVxuXG4gICAgJGdyb3VwLmhhc0NsYXNzKCdoYXMtZmVlZGJhY2snKVxuICAgICAgJiYgJGZlZWRiYWNrLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5zdWNjZXNzKVxuICAgICAgJiYgJGZlZWRiYWNrLmFkZENsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5lcnJvcilcbiAgICAgICYmICRncm91cC5yZW1vdmVDbGFzcygnaGFzLXN1Y2Nlc3MnKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5jbGVhckVycm9ycyA9IGZ1bmN0aW9uICgkZWwpIHtcbiAgICB2YXIgJGdyb3VwID0gJGVsLmNsb3Nlc3QoJy5mb3JtLWdyb3VwJylcbiAgICB2YXIgJGJsb2NrID0gJGdyb3VwLmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICB2YXIgJGZlZWRiYWNrID0gJGdyb3VwLmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuXG4gICAgJGJsb2NrLmh0bWwoJGJsb2NrLmRhdGEoJ2JzLnZhbGlkYXRvci5vcmlnaW5hbENvbnRlbnQnKSlcbiAgICAkZ3JvdXAucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvciBoYXMtZGFuZ2VyIGhhcy1zdWNjZXNzJylcblxuICAgICRncm91cC5oYXNDbGFzcygnaGFzLWZlZWRiYWNrJylcbiAgICAgICYmICRmZWVkYmFjay5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suZXJyb3IpXG4gICAgICAmJiAkZmVlZGJhY2sucmVtb3ZlQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG4gICAgICAmJiBnZXRWYWx1ZSgkZWwpXG4gICAgICAmJiAkZmVlZGJhY2suYWRkQ2xhc3ModGhpcy5vcHRpb25zLmZlZWRiYWNrLnN1Y2Nlc3MpXG4gICAgICAmJiAkZ3JvdXAuYWRkQ2xhc3MoJ2hhcy1zdWNjZXNzJylcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuaGFzRXJyb3JzID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIGZpZWxkRXJyb3JzKCkge1xuICAgICAgcmV0dXJuICEhKCQodGhpcykuZGF0YSgnYnMudmFsaWRhdG9yLmVycm9ycycpIHx8IFtdKS5sZW5ndGhcbiAgICB9XG5cbiAgICByZXR1cm4gISF0aGlzLiRpbnB1dHMuZmlsdGVyKGZpZWxkRXJyb3JzKS5sZW5ndGhcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUuaXNJbmNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIGZpZWxkSW5jb21wbGV0ZSgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGdldFZhbHVlKCQodGhpcykpXG4gICAgICByZXR1cm4gISh0eXBlb2YgdmFsdWUgPT0gXCJzdHJpbmdcIiA/ICQudHJpbSh2YWx1ZSkgOiB2YWx1ZSlcbiAgICB9XG5cbiAgICByZXR1cm4gISF0aGlzLiRpbnB1dHMuZmlsdGVyKCdbcmVxdWlyZWRdJykuZmlsdGVyKGZpZWxkSW5jb21wbGV0ZSkubGVuZ3RoXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLm9uU3VibWl0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICB0aGlzLnZhbGlkYXRlKClcbiAgICBpZiAodGhpcy5pc0luY29tcGxldGUoKSB8fCB0aGlzLmhhc0Vycm9ycygpKSBlLnByZXZlbnREZWZhdWx0KClcbiAgfVxuXG4gIFZhbGlkYXRvci5wcm90b3R5cGUudG9nZ2xlU3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmRpc2FibGUpIHJldHVyblxuICAgIHRoaXMuJGJ0bi50b2dnbGVDbGFzcygnZGlzYWJsZWQnLCB0aGlzLmlzSW5jb21wbGV0ZSgpIHx8IHRoaXMuaGFzRXJyb3JzKCkpXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmRlZmVyID0gZnVuY3Rpb24gKCRlbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9ICQucHJveHkoY2FsbGJhY2ssIHRoaXMsICRlbClcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5kZWxheSkgcmV0dXJuIGNhbGxiYWNrKClcbiAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KCRlbC5kYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcpKVxuICAgICRlbC5kYXRhKCdicy52YWxpZGF0b3IudGltZW91dCcsIHdpbmRvdy5zZXRUaW1lb3V0KGNhbGxiYWNrLCB0aGlzLm9wdGlvbnMuZGVsYXkpKVxuICB9XG5cbiAgVmFsaWRhdG9yLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJy5mb3JtLWNvbnRyb2wtZmVlZGJhY2snKVxuICAgICAgLnJlbW92ZUNsYXNzKHRoaXMub3B0aW9ucy5mZWVkYmFjay5lcnJvcilcbiAgICAgIC5yZW1vdmVDbGFzcyh0aGlzLm9wdGlvbnMuZmVlZGJhY2suc3VjY2VzcylcblxuICAgIHRoaXMuJGlucHV0c1xuICAgICAgLnJlbW92ZURhdGEoWydicy52YWxpZGF0b3IuZXJyb3JzJywgJ2JzLnZhbGlkYXRvci5kZWZlcnJlZCddKVxuICAgICAgLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpXG4gICAgICAgIHZhciB0aW1lb3V0ID0gJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yLnRpbWVvdXQnKVxuICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRpbWVvdXQpICYmICR0aGlzLnJlbW92ZURhdGEoJ2JzLnZhbGlkYXRvci50aW1lb3V0JylcbiAgICAgIH0pXG5cbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJy5oZWxwLWJsb2NrLndpdGgtZXJyb3JzJylcbiAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgICB2YXIgb3JpZ2luYWxDb250ZW50ID0gJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpXG5cbiAgICAgICAgJHRoaXNcbiAgICAgICAgICAucmVtb3ZlRGF0YSgnYnMudmFsaWRhdG9yLm9yaWdpbmFsQ29udGVudCcpXG4gICAgICAgICAgLmh0bWwob3JpZ2luYWxDb250ZW50KVxuICAgICAgfSlcblxuICAgIHRoaXMuJGJ0bi5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKVxuXG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCcuaGFzLWVycm9yLCAuaGFzLWRhbmdlciwgLmhhcy1zdWNjZXNzJykucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvciBoYXMtZGFuZ2VyIGhhcy1zdWNjZXNzJylcblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBWYWxpZGF0b3IucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5yZXNldCgpXG5cbiAgICB0aGlzLiRlbGVtZW50XG4gICAgICAucmVtb3ZlQXR0cignbm92YWxpZGF0ZScpXG4gICAgICAucmVtb3ZlRGF0YSgnYnMudmFsaWRhdG9yJylcbiAgICAgIC5vZmYoJy5icy52YWxpZGF0b3InKVxuXG4gICAgdGhpcy4kaW5wdXRzXG4gICAgICAub2ZmKCcuYnMudmFsaWRhdG9yJylcblxuICAgIHRoaXMub3B0aW9ucyAgICA9IG51bGxcbiAgICB0aGlzLnZhbGlkYXRvcnMgPSBudWxsXG4gICAgdGhpcy4kZWxlbWVudCAgID0gbnVsbFxuICAgIHRoaXMuJGJ0biAgICAgICA9IG51bGxcbiAgICB0aGlzLiRpbnB1dHMgICAgPSBudWxsXG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gVkFMSURBVE9SIFBMVUdJTiBERUZJTklUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5cbiAgZnVuY3Rpb24gUGx1Z2luKG9wdGlvbikge1xuICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICR0aGlzICAgPSAkKHRoaXMpXG4gICAgICB2YXIgb3B0aW9ucyA9ICQuZXh0ZW5kKHt9LCBWYWxpZGF0b3IuREVGQVVMVFMsICR0aGlzLmRhdGEoKSwgdHlwZW9mIG9wdGlvbiA9PSAnb2JqZWN0JyAmJiBvcHRpb24pXG4gICAgICB2YXIgZGF0YSAgICA9ICR0aGlzLmRhdGEoJ2JzLnZhbGlkYXRvcicpXG5cbiAgICAgIGlmICghZGF0YSAmJiBvcHRpb24gPT0gJ2Rlc3Ryb3knKSByZXR1cm5cbiAgICAgIGlmICghZGF0YSkgJHRoaXMuZGF0YSgnYnMudmFsaWRhdG9yJywgKGRhdGEgPSBuZXcgVmFsaWRhdG9yKHRoaXMsIG9wdGlvbnMpKSlcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09ICdzdHJpbmcnKSBkYXRhW29wdGlvbl0oKVxuICAgIH0pXG4gIH1cblxuICB2YXIgb2xkID0gJC5mbi52YWxpZGF0b3JcblxuICAkLmZuLnZhbGlkYXRvciAgICAgICAgICAgICA9IFBsdWdpblxuICAkLmZuLnZhbGlkYXRvci5Db25zdHJ1Y3RvciA9IFZhbGlkYXRvclxuXG5cbiAgLy8gVkFMSURBVE9SIE5PIENPTkZMSUNUXG4gIC8vID09PT09PT09PT09PT09PT09PT09PVxuXG4gICQuZm4udmFsaWRhdG9yLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJC5mbi52YWxpZGF0b3IgPSBvbGRcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cblxuICAvLyBWQUxJREFUT1IgREFUQS1BUElcbiAgLy8gPT09PT09PT09PT09PT09PT09XG5cbiAgJCh3aW5kb3cpLm9uKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICQoJ2Zvcm1bZGF0YS10b2dnbGU9XCJ2YWxpZGF0b3JcIl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkZm9ybSA9ICQodGhpcylcbiAgICAgIFBsdWdpbi5jYWxsKCRmb3JtLCAkZm9ybS5kYXRhKCkpXG4gICAgfSlcbiAgfSlcblxufShqUXVlcnkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwLXZhbGlkYXRvci9qcy92YWxpZGF0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDE2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxuICogYm9vdHN0cmFwLWZpbGVpbnB1dCB2NC40LjJcbiAqIGh0dHA6Ly9wbHVnaW5zLmtyYWplZS5jb20vZmlsZS1pbnB1dFxuICpcbiAqIEF1dGhvcjogS2FydGlrIFZpc3dlc3dhcmFuXG4gKiBDb3B5cmlnaHQ6IDIwMTQgLSAyMDE3LCBLYXJ0aWsgVmlzd2Vzd2FyYW4sIEtyYWplZS5jb21cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQlNEIDMtQ2xhdXNlXG4gKiBodHRwczovL2dpdGh1Yi5jb20va2FydGlrLXYvYm9vdHN0cmFwLWZpbGVpbnB1dC9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4gKi9cbihmdW5jdGlvbiAoZmFjdG9yeSkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkgeyAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuICAgICAgICBkZWZpbmUoWydqcXVlcnknXSwgZmFjdG9yeSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgIH0gZWxzZSB7IC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHsgLy8ganNoaW50IGlnbm9yZTpsaW5lXG4gICAgICAgICAgICAvLyBOb2RlL0NvbW1vbkpTXG4gICAgICAgICAgICAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCdqcXVlcnknKSk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgICAgICAgICBmYWN0b3J5KHdpbmRvdy5qUXVlcnkpO1xuICAgICAgICB9XG4gICAgfVxufShmdW5jdGlvbiAoJCkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgJC5mbi5maWxlaW5wdXRMb2NhbGVzID0ge307XG4gICAgJC5mbi5maWxlaW5wdXRUaGVtZXMgPSB7fTtcblxuICAgIFN0cmluZy5wcm90b3R5cGUuc2V0VG9rZW5zID0gZnVuY3Rpb24gKHJlcGxhY2VQYWlycykge1xuICAgICAgICB2YXIgc3RyID0gdGhpcy50b1N0cmluZygpLCBrZXksIHJlO1xuICAgICAgICBmb3IgKGtleSBpbiByZXBsYWNlUGFpcnMpIHtcbiAgICAgICAgICAgIGlmIChyZXBsYWNlUGFpcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIHJlID0gbmV3IFJlZ0V4cChcIlxce1wiICsga2V5ICsgXCJcXH1cIiwgXCJnXCIpO1xuICAgICAgICAgICAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKHJlLCByZXBsYWNlUGFpcnNba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgdmFyICRoLCBGaWxlSW5wdXQ7XG5cbiAgICAvLyBmaWxlaW5wdXQgaGVscGVyIG9iamVjdCBmb3IgYWxsIGdsb2JhbCB2YXJpYWJsZXMgYW5kIGludGVybmFsIGhlbHBlciBtZXRob2RzXG4gICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAkaCA9IHtcbiAgICAgICAgRlJBTUVTOiAnLmt2LXByZXZpZXctdGh1bWInLFxuICAgICAgICBTT1JUX0NTUzogJ2ZpbGUtc29ydGFibGUnLFxuICAgICAgICBTVFlMRV9TRVRUSU5HOiAnc3R5bGU9XCJ3aWR0aDp7d2lkdGh9O2hlaWdodDp7aGVpZ2h0fTtcIicsXG4gICAgICAgIE9CSkVDVF9QQVJBTVM6ICc8cGFyYW0gbmFtZT1cImNvbnRyb2xsZXJcIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd0Z1bGxTY3JlZW5cIiB2YWx1ZT1cInRydWVcIiAvPlxcbicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJhbGxvd1NjcmlwdEFjY2Vzc1wiIHZhbHVlPVwiYWx3YXlzXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1BsYXlcIiB2YWx1ZT1cImZhbHNlXCIgLz5cXG4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwiYXV0b1N0YXJ0XCIgdmFsdWU9XCJmYWxzZVwiIC8+XFxuJyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cInF1YWxpdHlcIiB2YWx1ZT1cImhpZ2hcIiAvPlxcbicsXG4gICAgICAgIERFRkFVTFRfUFJFVklFVzogJzxkaXYgY2xhc3M9XCJmaWxlLXByZXZpZXctb3RoZXJcIj5cXG4nICtcbiAgICAgICAgJzxzcGFuIGNsYXNzPVwie3ByZXZpZXdGaWxlSWNvbkNsYXNzfVwiPntwcmV2aWV3RmlsZUljb259PC9zcGFuPlxcbicgK1xuICAgICAgICAnPC9kaXY+JyxcbiAgICAgICAgTU9EQUxfSUQ6ICdrdkZpbGVpbnB1dE1vZGFsJyxcbiAgICAgICAgTU9EQUxfRVZFTlRTOiBbJ3Nob3cnLCAnc2hvd24nLCAnaGlkZScsICdoaWRkZW4nLCAnbG9hZGVkJ10sXG4gICAgICAgIG9ialVybDogd2luZG93LlVSTCB8fCB3aW5kb3cud2Via2l0VVJMLFxuICAgICAgICBjb21wYXJlOiBmdW5jdGlvbiAoaW5wdXQsIHN0ciwgZXhhY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPT0gdW5kZWZpbmVkICYmIChleGFjdCA/IGlucHV0ID09PSBzdHIgOiBpbnB1dC5tYXRjaChzdHIpKTtcbiAgICAgICAgfSxcbiAgICAgICAgaXNJRTogZnVuY3Rpb24gKHZlcikge1xuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIElFIHZlcnNpb25zIDwgMTFcbiAgICAgICAgICAgIGlmIChuYXZpZ2F0b3IuYXBwTmFtZSAhPT0gJ01pY3Jvc29mdCBJbnRlcm5ldCBFeHBsb3JlcicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmVyID09PSAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKCdtc2llXFxcXHMnICsgdmVyLCAnaScpLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKSwgc3RhdHVzO1xuICAgICAgICAgICAgZGl2LmlubmVySFRNTCA9IFwiPCEtLVtpZiBJRSBcIiArIHZlciArIFwiXT4gPGk+PC9pPiA8IVtlbmRpZl0tLT5cIjtcbiAgICAgICAgICAgIHN0YXR1cyA9IGRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZShcImlcIikubGVuZ3RoO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgICAgIHJldHVybiBzdGF0dXM7XG4gICAgICAgIH0sXG4gICAgICAgIGluaXRNb2RhbDogZnVuY3Rpb24gKCRtb2RhbCkge1xuICAgICAgICAgICAgdmFyICRib2R5ID0gJCgnYm9keScpO1xuICAgICAgICAgICAgaWYgKCRib2R5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICRtb2RhbC5hcHBlbmRUbygkYm9keSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGlzRW1wdHk6IGZ1bmN0aW9uICh2YWx1ZSwgdHJpbSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUubGVuZ3RoID09PSAwIHx8ICh0cmltICYmICQudHJpbSh2YWx1ZSkgPT09ICcnKTtcbiAgICAgICAgfSxcbiAgICAgICAgaXNBcnJheTogZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGEpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICAgICAgfSxcbiAgICAgICAgaWZTZXQ6IGZ1bmN0aW9uIChuZWVkbGUsIGhheXN0YWNrLCBkZWYpIHtcbiAgICAgICAgICAgIGRlZiA9IGRlZiB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiAoaGF5c3RhY2sgJiYgdHlwZW9mIGhheXN0YWNrID09PSAnb2JqZWN0JyAmJiBuZWVkbGUgaW4gaGF5c3RhY2spID8gaGF5c3RhY2tbbmVlZGxlXSA6IGRlZjtcbiAgICAgICAgfSxcbiAgICAgICAgY2xlYW5BcnJheTogZnVuY3Rpb24gKGFycikge1xuICAgICAgICAgICAgaWYgKCEoYXJyIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgICAgICAgYXJyID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYXJyLmZpbHRlcihmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoZSAhPT0gdW5kZWZpbmVkICYmIGUgIT09IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHNwbGljZUFycmF5OiBmdW5jdGlvbiAoYXJyLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIGksIGogPSAwLCBvdXQgPSBbXTtcbiAgICAgICAgICAgIGlmICghKGFyciBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0W2pdID0gYXJyW2ldO1xuICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0TnVtOiBmdW5jdGlvbiAobnVtLCBkZWYpIHtcbiAgICAgICAgICAgIGRlZiA9IGRlZiB8fCAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBudW0gPSBwYXJzZUZsb2F0KG51bSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaXNOYU4obnVtKSA/IGRlZiA6IG51bTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzRmlsZUFQSVN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhISh3aW5kb3cuRmlsZSAmJiB3aW5kb3cuRmlsZVJlYWRlcik7XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0RyYWdEcm9wU3VwcG9ydDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZGl2LmRyYWdnYWJsZSAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZGl2Lm9uZHJhZ3N0YXJ0ICovXG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkaXYub25kcm9wICovXG4gICAgICAgICAgICByZXR1cm4gISRoLmlzSUUoOSkgJiZcbiAgICAgICAgICAgICAgICAoZGl2LmRyYWdnYWJsZSAhPT0gdW5kZWZpbmVkIHx8IChkaXYub25kcmFnc3RhcnQgIT09IHVuZGVmaW5lZCAmJiBkaXYub25kcm9wICE9PSB1bmRlZmluZWQpKTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzRmlsZVVwbG9hZFN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAkaC5oYXNGaWxlQVBJU3VwcG9ydCgpICYmIHdpbmRvdy5Gb3JtRGF0YTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzQmxvYlN1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICEhd2luZG93LkJsb2IgJiYgQm9vbGVhbihuZXcgQmxvYigpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGhhc0FycmF5QnVmZmVyVmlld1N1cHBvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9iKFtuZXcgVWludDhBcnJheSgxMDApXSkuc2l6ZSA9PT0gMTAwO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGF0YVVSSTJCbG9iOiBmdW5jdGlvbiAoZGF0YVVSSSkge1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIHZhciBCbG9iQnVpbGRlciA9IHdpbmRvdy5CbG9iQnVpbGRlciB8fCB3aW5kb3cuV2ViS2l0QmxvYkJ1aWxkZXIgfHwgd2luZG93Lk1vekJsb2JCdWlsZGVyIHx8XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5NU0Jsb2JCdWlsZGVyLCBjYW5CbG9iID0gJGguaGFzQmxvYlN1cHBvcnQoKSwgYnl0ZVN0ciwgYXJyYXlCdWZmZXIsIGludEFycmF5LCBpLCBtaW1lU3RyLCBiYixcbiAgICAgICAgICAgICAgICBjYW5Qcm9jZWVkID0gKGNhbkJsb2IgfHwgQmxvYkJ1aWxkZXIpICYmIHdpbmRvdy5hdG9iICYmIHdpbmRvdy5BcnJheUJ1ZmZlciAmJiB3aW5kb3cuVWludDhBcnJheTtcbiAgICAgICAgICAgIGlmICghY2FuUHJvY2VlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRhdGFVUkkuc3BsaXQoJywnKVswXS5pbmRleE9mKCdiYXNlNjQnKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgYnl0ZVN0ciA9IGF0b2IoZGF0YVVSSS5zcGxpdCgnLCcpWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnl0ZVN0ciA9IGRlY29kZVVSSUNvbXBvbmVudChkYXRhVVJJLnNwbGl0KCcsJylbMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXJyYXlCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoYnl0ZVN0ci5sZW5ndGgpO1xuICAgICAgICAgICAgaW50QXJyYXkgPSBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYnl0ZVN0ci5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIGludEFycmF5W2ldID0gYnl0ZVN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWltZVN0ciA9IGRhdGFVUkkuc3BsaXQoJywnKVswXS5zcGxpdCgnOicpWzFdLnNwbGl0KCc7JylbMF07XG4gICAgICAgICAgICBpZiAoY2FuQmxvYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQmxvYihbJGguaGFzQXJyYXlCdWZmZXJWaWV3U3VwcG9ydCgpID8gaW50QXJyYXkgOiBhcnJheUJ1ZmZlcl0sIHt0eXBlOiBtaW1lU3RyfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBiYiA9IG5ldyBCbG9iQnVpbGRlcigpO1xuICAgICAgICAgICAgYmIuYXBwZW5kKGFycmF5QnVmZmVyKTtcbiAgICAgICAgICAgIHJldHVybiBiYi5nZXRCbG9iKG1pbWVTdHIpO1xuICAgICAgICB9LFxuICAgICAgICBhZGRDc3M6IGZ1bmN0aW9uICgkZWwsIGNzcykge1xuICAgICAgICAgICAgJGVsLnJlbW92ZUNsYXNzKGNzcykuYWRkQ2xhc3MoY3NzKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RWxlbWVudDogZnVuY3Rpb24gKG9wdGlvbnMsIHBhcmFtLCB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuICgkaC5pc0VtcHR5KG9wdGlvbnMpIHx8ICRoLmlzRW1wdHkob3B0aW9uc1twYXJhbV0pKSA/IHZhbHVlIDogJChvcHRpb25zW3BhcmFtXSk7XG4gICAgICAgIH0sXG4gICAgICAgIHVuaXFJZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgKyAoTWF0aC5yYW5kb20oKSAqIDEwMCkpO1xuICAgICAgICB9LFxuICAgICAgICBodG1sRW5jb2RlOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyYvZywgJyZhbXA7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7JylcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCAnJmFwb3M7Jyk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlcGxhY2VUYWdzOiBmdW5jdGlvbiAoc3RyLCB0YWdzKSB7XG4gICAgICAgICAgICB2YXIgb3V0ID0gc3RyO1xuICAgICAgICAgICAgaWYgKCF0YWdzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZWFjaCh0YWdzLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG91dCA9IG91dC5zcGxpdChrZXkpLmpvaW4odmFsdWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBjbGVhbk1lbW9yeTogZnVuY3Rpb24gKCR0aHVtYikge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSAkdGh1bWIuaXMoJ2ltZycpID8gJHRodW1iLmF0dHIoJ3NyYycpIDogJHRodW1iLmZpbmQoJ3NvdXJjZScpLmF0dHIoJ3NyYycpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgJGgub2JqVXJsLnJldm9rZU9iamVjdFVSTCAqL1xuICAgICAgICAgICAgJGgub2JqVXJsLnJldm9rZU9iamVjdFVSTChkYXRhKTtcbiAgICAgICAgfSxcbiAgICAgICAgZmluZEZpbGVOYW1lOiBmdW5jdGlvbiAoZmlsZVBhdGgpIHtcbiAgICAgICAgICAgIHZhciBzZXBJbmRleCA9IGZpbGVQYXRoLmxhc3RJbmRleE9mKCcvJyk7XG4gICAgICAgICAgICBpZiAoc2VwSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VwSW5kZXggPSBmaWxlUGF0aC5sYXN0SW5kZXhPZignXFxcXCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZpbGVQYXRoLnNwbGl0KGZpbGVQYXRoLnN1YnN0cmluZyhzZXBJbmRleCwgc2VwSW5kZXggKyAxKSkucG9wKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGNoZWNrRnVsbFNjcmVlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgICAgIHJldHVybiBkb2N1bWVudC5mdWxsc2NyZWVuRWxlbWVudCB8fCBkb2N1bWVudC5tb3pGdWxsU2NyZWVuRWxlbWVudCB8fCBkb2N1bWVudC53ZWJraXRGdWxsc2NyZWVuRWxlbWVudCB8fFxuICAgICAgICAgICAgICAgIGRvY3VtZW50Lm1zRnVsbHNjcmVlbkVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRvZ2dsZUZ1bGxTY3JlZW46IGZ1bmN0aW9uIChtYXhpbWl6ZSkge1xuICAgICAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LCBkZSA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoZGUgJiYgbWF4aW1pemUgJiYgISRoLmNoZWNrRnVsbFNjcmVlbigpKSB7XG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQucmVxdWVzdEZ1bGxzY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC5tc1JlcXVlc3RGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubW96UmVxdWVzdEZ1bGxTY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIEVsZW1lbnQuQUxMT1dfS0VZQk9BUkRfSU5QVVQgKi9cbiAgICAgICAgICAgICAgICBpZiAoZGUucmVxdWVzdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUucmVxdWVzdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlLm1zUmVxdWVzdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUubXNSZXF1ZXN0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGUubW96UmVxdWVzdEZ1bGxTY3JlZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZGUubW96UmVxdWVzdEZ1bGxTY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKEVsZW1lbnQuQUxMT1dfS0VZQk9BUkRfSU5QVVQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4gKi9cbiAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBkb2N1bWVudC5tc0V4aXRGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZG9jdW1lbnQubW96Q2FuY2VsRnVsbFNjcmVlbiAqL1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRvY3VtZW50LndlYmtpdEV4aXRGdWxsc2NyZWVuICovXG4gICAgICAgICAgICAgICAgaWYgKGRvYy5leGl0RnVsbHNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2MuZXhpdEZ1bGxzY3JlZW4oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRvYy5tc0V4aXRGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvYy5tc0V4aXRGdWxsc2NyZWVuKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkb2MubW96Q2FuY2VsRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBkb2MubW96Q2FuY2VsRnVsbFNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZG9jLndlYmtpdEV4aXRGdWxsc2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvYy53ZWJraXRFeGl0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbW92ZUFycmF5OiBmdW5jdGlvbiAoYXJyLCBvbGRJbmRleCwgbmV3SW5kZXgpIHtcbiAgICAgICAgICAgIGlmIChuZXdJbmRleCA+PSBhcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGsgPSBuZXdJbmRleCAtIGFyci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgd2hpbGUgKChrLS0pICsgMSkge1xuICAgICAgICAgICAgICAgICAgICBhcnIucHVzaCh1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFyci5zcGxpY2UobmV3SW5kZXgsIDAsIGFyci5zcGxpY2Uob2xkSW5kZXgsIDEpWzBdKTtcbiAgICAgICAgICAgIHJldHVybiBhcnI7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFuWm9vbUNhY2hlOiBmdW5jdGlvbiAoJGVsKSB7XG4gICAgICAgICAgICB2YXIgJGNhY2hlID0gJGVsLmNsb3Nlc3QoJy5rdi16b29tLWNhY2hlLXRoZW1lJyk7XG4gICAgICAgICAgICBpZiAoISRjYWNoZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkY2FjaGUgPSAkZWwuY2xvc2VzdCgnLmt2LXpvb20tY2FjaGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRjYWNoZS5yZW1vdmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0T3JpZW50YXRpb246IGZ1bmN0aW9uIChidWZmZXIsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgc2Nhbm5lciA9IG5ldyBEYXRhVmlldyhidWZmZXIpLCBpZHggPSAwLCB2YWx1ZSA9IDEsIC8vIE5vbi1yb3RhdGVkIGlzIHRoZSBkZWZhdWx0XG4gICAgICAgICAgICAgICAgbWF4Qnl0ZXMsIHVJbnQxNiwgZXhpZkxlbmd0aDtcbiAgICAgICAgICAgIGlmIChzY2FubmVyLmdldFVpbnQxNihpZHgpICE9PSAweEZGRDggfHwgYnVmZmVyLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIG5vdCBhIHByb3BlciBKUEVHXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggKz0gMjtcbiAgICAgICAgICAgIG1heEJ5dGVzID0gc2Nhbm5lci5ieXRlTGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA8IG1heEJ5dGVzIC0gMikge1xuICAgICAgICAgICAgICAgIHVJbnQxNiA9IHNjYW5uZXIuZ2V0VWludDE2KGlkeCk7XG4gICAgICAgICAgICAgICAgaWR4ICs9IDI7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh1SW50MTYpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAweEZGRTE6IC8vIFN0YXJ0IG9mIEVYSUZcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aWZMZW5ndGggPSBzY2FubmVyLmdldFVpbnQxNihpZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qnl0ZXMgPSBleGlmTGVuZ3RoIC0gaWR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWR4ICs9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAweDAxMTI6IC8vIE9yaWVudGF0aW9uIHRhZ1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBzY2FubmVyLmdldFVpbnQxNihpZHggKyA2LCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhCeXRlcyA9IDA7IC8vIFN0b3Agc2Nhbm5pbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdmFsaWRhdGVPcmllbnRhdGlvbjogZnVuY3Rpb24gKGZpbGUsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBpZiAoIXdpbmRvdy5GaWxlUmVhZGVyIHx8ICF3aW5kb3cuRGF0YVZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIHNraXAgb3JpZW50YXRpb24gaWYgcHJlLXJlcXVpc2l0ZSBsaWJyYXJpZXMgbm90IHN1cHBvcnRlZCBieSBicm93c2VyXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKSwgYnVmZmVyO1xuICAgICAgICAgICAgcmVhZGVyLm9ubG9hZGVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBidWZmZXIgPSByZWFkZXIucmVzdWx0O1xuICAgICAgICAgICAgICAgICRoLnNldE9yaWVudGF0aW9uKGJ1ZmZlciwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihmaWxlKTtcbiAgICAgICAgfSxcbiAgICAgICAgYWRqdXN0T3JpZW50ZWRJbWFnZTogZnVuY3Rpb24gKCRpbWcsIGlzWm9vbSkge1xuICAgICAgICAgICAgdmFyIG9mZnNldENvbnRUb3AsIG9mZnNldFRvcCwgbmV3VG9wO1xuICAgICAgICAgICAgaWYgKCEkaW1nLmhhc0NsYXNzKCdpcy1wb3J0cmFpdC1ndDQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc1pvb20pIHtcbiAgICAgICAgICAgICAgICAkaW1nLmNzcyh7d2lkdGg6ICRpbWcucGFyZW50KCkuaGVpZ2h0KCl9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICRpbWcuY3NzKHtoZWlnaHQ6ICdhdXRvJywgd2lkdGg6ICRpbWcuaGVpZ2h0KCl9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9mZnNldENvbnRUb3AgPSAkaW1nLnBhcmVudCgpLm9mZnNldCgpLnRvcDtcbiAgICAgICAgICAgIG9mZnNldFRvcCA9ICRpbWcub2Zmc2V0KCkudG9wO1xuICAgICAgICAgICAgbmV3VG9wID0gb2Zmc2V0Q29udFRvcCAtIG9mZnNldFRvcDtcbiAgICAgICAgICAgICRpbWcuY3NzKCdtYXJnaW4tdG9wJywgbmV3VG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsZUlucHV0ID0gZnVuY3Rpb24gKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICBzZWxmLiRlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICAgICAgaWYgKCFzZWxmLl92YWxpZGF0ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5pc1ByZXZpZXdhYmxlID0gJGguaGFzRmlsZUFQSVN1cHBvcnQoKTtcbiAgICAgICAgc2VsZi5pc0lFOSA9ICRoLmlzSUUoOSk7XG4gICAgICAgIHNlbGYuaXNJRTEwID0gJGguaXNJRSgxMCk7XG4gICAgICAgIGlmIChzZWxmLmlzUHJldmlld2FibGUgfHwgc2VsZi5pc0lFOSkge1xuICAgICAgICAgICAgc2VsZi5faW5pdChvcHRpb25zKTtcbiAgICAgICAgICAgIHNlbGYuX2xpc3RlbigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5yZW1vdmVDbGFzcygnZmlsZS1sb2FkaW5nJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkR2xvYmFsU3ltYm9sc1xuICAgIEZpbGVJbnB1dC5wcm90b3R5cGUgPSB7XG4gICAgICAgIGNvbnN0cnVjdG9yOiBGaWxlSW5wdXQsXG4gICAgICAgIF9jbGVhbnVwOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLnJlYWRlciA9IG51bGw7XG4gICAgICAgICAgICBzZWxmLmZvcm1kYXRhID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuICAgICAgICAgICAgc2VsZi5hamF4UmVxdWVzdHMgPSBbXTtcbiAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICBzZWxmLmZpbGVCYXRjaENvbXBsZXRlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNQcmV2aWV3YWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuc2hvd1ByZXZpZXcgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5hamF4QWJvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5jYW5jZWxsaW5nID0gZmFsc2U7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0OiBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRlbGVtZW50LCAkY29udCwgdCwgdG1wO1xuICAgICAgICAgICAgc2VsZi5vcHRpb25zID0gb3B0aW9ucztcbiAgICAgICAgICAgICQuZWFjaChvcHRpb25zLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkZpbGVDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21heEZpbGVDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkZpbGVTaXplJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4RmlsZVNpemUnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtYXhGaWxlUHJldmlld1NpemUnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNpemVJbWFnZVF1YWxpdHknOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNpemVJZlNpemVNb3JlVGhhbic6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3Byb2dyZXNzVXBsb2FkVGhyZXNob2xkJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnaW5pdGlhbFByZXZpZXdDb3VudCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3pvb21Nb2RhbEhlaWdodCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ21pbkltYWdlSGVpZ2h0JzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4SW1hZ2VIZWlnaHQnOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdtaW5JbWFnZVdpZHRoJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbWF4SW1hZ2VXaWR0aCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0gPSAkaC5nZXROdW0odmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHNlbGYucnRsKSB7IC8vIHN3YXAgYnV0dG9ucyBmb3IgcnRsXG4gICAgICAgICAgICAgICAgdG1wID0gc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLnByZXY7XG4gICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkljb25zLnByZXYgPSBzZWxmLnByZXZpZXdab29tQnV0dG9uSWNvbnMubmV4dDtcbiAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdab29tQnV0dG9uSWNvbnMubmV4dCA9IHRtcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2NsZWFudXAoKTtcbiAgICAgICAgICAgIHNlbGYuJGZvcm0gPSAkZWwuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFRlbXBsYXRlRGVmYXVsdHMoKTtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkRmlsZUF0dHIgPSAhJGguaXNFbXB0eSgkZWwuYXR0cignbmFtZScpKSA/ICRlbC5hdHRyKCduYW1lJykgOiAnZmlsZV9kYXRhJztcbiAgICAgICAgICAgIHQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgncHJvZ3Jlc3MnKTtcbiAgICAgICAgICAgIHNlbGYucHJvZ3Jlc3NUZW1wbGF0ZSA9IHQucmVwbGFjZSgne2NsYXNzfScsIHNlbGYucHJvZ3Jlc3NDbGFzcyk7XG4gICAgICAgICAgICBzZWxmLnByb2dyZXNzQ29tcGxldGVUZW1wbGF0ZSA9IHQucmVwbGFjZSgne2NsYXNzfScsIHNlbGYucHJvZ3Jlc3NDb21wbGV0ZUNsYXNzKTtcbiAgICAgICAgICAgIHNlbGYucHJvZ3Jlc3NFcnJvclRlbXBsYXRlID0gdC5yZXBsYWNlKCd7Y2xhc3N9Jywgc2VsZi5wcm9ncmVzc0Vycm9yQ2xhc3MpO1xuICAgICAgICAgICAgc2VsZi5kcm9wWm9uZUVuYWJsZWQgPSAkaC5oYXNEcmFnRHJvcFN1cHBvcnQoKSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZDtcbiAgICAgICAgICAgIHNlbGYuaXNEaXNhYmxlZCA9ICRlbC5hdHRyKCdkaXNhYmxlZCcpIHx8ICRlbC5hdHRyKCdyZWFkb25seScpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICRlbC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5pc1VwbG9hZGFibGUgPSAkaC5oYXNGaWxlVXBsb2FkU3VwcG9ydCgpICYmICEkaC5pc0VtcHR5KHNlbGYudXBsb2FkVXJsKTtcbiAgICAgICAgICAgIHNlbGYuaXNDbGlja2FibGUgPSBzZWxmLmJyb3dzZU9uWm9uZUNsaWNrICYmIHNlbGYuc2hvd1ByZXZpZXcgJiZcbiAgICAgICAgICAgICAgICAoc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQgfHwgISRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKTtcbiAgICAgICAgICAgIHNlbGYuc2x1ZyA9IHR5cGVvZiBvcHRpb25zLnNsdWdDYWxsYmFjayA9PT0gXCJmdW5jdGlvblwiID8gb3B0aW9ucy5zbHVnQ2FsbGJhY2sgOiBzZWxmLl9zbHVnRGVmYXVsdDtcbiAgICAgICAgICAgIHNlbGYubWFpblRlbXBsYXRlID0gc2VsZi5zaG93Q2FwdGlvbiA/IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdtYWluMScpIDogc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21haW4yJyk7XG4gICAgICAgICAgICBzZWxmLmNhcHRpb25UZW1wbGF0ZSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdjYXB0aW9uJyk7XG4gICAgICAgICAgICBzZWxmLnByZXZpZXdHZW5lcmljVGVtcGxhdGUgPSBzZWxmLl9nZXRQcmV2aWV3VGVtcGxhdGUoJ2dlbmVyaWMnKTtcbiAgICAgICAgICAgIGlmIChzZWxmLnJlc2l6ZUltYWdlICYmIChzZWxmLm1heEltYWdlV2lkdGggfHwgc2VsZi5tYXhJbWFnZUhlaWdodCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmltYWdlQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbWFnZUNhbnZhc0NvbnRleHQgPSBzZWxmLmltYWdlQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eSgkZWwuYXR0cignaWQnKSkpIHtcbiAgICAgICAgICAgICAgICAkZWwuYXR0cignaWQnLCAkaC51bmlxSWQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLm5hbWVzcGFjZSA9ICcuZmlsZWlucHV0XycgKyAkZWwuYXR0cignaWQnKS5yZXBsYWNlKC8tL2csICdfJyk7XG4gICAgICAgICAgICBpZiAoc2VsZi4kY29udGFpbmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIgPSBzZWxmLl9jcmVhdGVDb250YWluZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVmcmVzaENvbnRhaW5lcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGNvbnQgPSBzZWxmLiRjb250YWluZXI7XG4gICAgICAgICAgICBzZWxmLiRkcm9wWm9uZSA9ICRjb250LmZpbmQoJy5maWxlLWRyb3Atem9uZScpO1xuICAgICAgICAgICAgc2VsZi4kcHJvZ3Jlc3MgPSAkY29udC5maW5kKCcua3YtdXBsb2FkLXByb2dyZXNzJyk7XG4gICAgICAgICAgICBzZWxmLiRidG5VcGxvYWQgPSAkY29udC5maW5kKCcuZmlsZWlucHV0LXVwbG9hZCcpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lciA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsQ2FwdGlvbkNvbnRhaW5lcicsICRjb250LmZpbmQoJy5maWxlLWNhcHRpb24nKSk7XG4gICAgICAgICAgICBzZWxmLiRjYXB0aW9uID0gJGguZ2V0RWxlbWVudChvcHRpb25zLCAnZWxDYXB0aW9uVGV4dCcsICRjb250LmZpbmQoJy5maWxlLWNhcHRpb24tbmFtZScpKTtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXdDb250YWluZXIgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbFByZXZpZXdDb250YWluZXInLCAkY29udC5maW5kKCcuZmlsZS1wcmV2aWV3JykpO1xuICAgICAgICAgICAgc2VsZi4kcHJldmlldyA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsUHJldmlld0ltYWdlJywgJGNvbnQuZmluZCgnLmZpbGUtcHJldmlldy10aHVtYm5haWxzJykpO1xuICAgICAgICAgICAgc2VsZi4kcHJldmlld1N0YXR1cyA9ICRoLmdldEVsZW1lbnQob3B0aW9ucywgJ2VsUHJldmlld1N0YXR1cycsICRjb250LmZpbmQoJy5maWxlLXByZXZpZXctc3RhdHVzJykpO1xuICAgICAgICAgICAgc2VsZi4kZXJyb3JDb250YWluZXIgPSAkaC5nZXRFbGVtZW50KG9wdGlvbnMsICdlbEVycm9yQ29udGFpbmVyJyxcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3Q29udGFpbmVyLmZpbmQoJy5rdi1maWxlaW5wdXQtZXJyb3InKSk7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoc2VsZi5tc2dFcnJvckNsYXNzKSkge1xuICAgICAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRlcnJvckNvbnRhaW5lciwgc2VsZi5tc2dFcnJvckNsYXNzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGVycm9yQ29udGFpbmVyLmhpZGUoKTtcbiAgICAgICAgICAgIHNlbGYucHJldmlld0luaXRJZCA9IFwicHJldmlldy1cIiArICRoLnVuaXFJZCgpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdDYWNoZSgpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXcodHJ1ZSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgIHNlbGYuX3NldEZpbGVEcm9wWm9uZVRpdGxlKCk7XG4gICAgICAgICAgICAkZWwucmVtb3ZlQ2xhc3MoJ2ZpbGUtbG9hZGluZycpO1xuICAgICAgICAgICAgaWYgKCRlbC5hdHRyKCdkaXNhYmxlZCcpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5kaXNhYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9pbml0Wm9vbSgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaGlkZVRodW1ibmFpbENvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kcHJldmlldywgJ2hpZGUtY29udGVudCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfaW5pdFRlbXBsYXRlRGVmYXVsdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdE1haW4xLCB0TWFpbjIsIHRQcmV2aWV3LCB0RmlsZUljb24sIHRDbG9zZSwgdENhcHRpb24sIHRCdG5EZWZhdWx0LCB0QnRuTGluaywgdEJ0bkJyb3dzZSxcbiAgICAgICAgICAgICAgICB0TW9kYWxNYWluLCB0TW9kYWwsIHRQcm9ncmVzcywgdFNpemUsIHRGb290ZXIsIHRBY3Rpb25zLCB0QWN0aW9uRGVsZXRlLCB0QWN0aW9uVXBsb2FkLCB0QWN0aW9uWm9vbSxcbiAgICAgICAgICAgICAgICB0QWN0aW9uRHJhZywgdEluZGljYXRvciwgdFRhZ0JlZiwgdFRhZ0JlZjEsIHRUYWdCZWYyLCB0VGFnQWZ0LCB0R2VuZXJpYywgdEh0bWwsIHRJbWFnZSwgdFRleHQsIHRWaWRlbyxcbiAgICAgICAgICAgICAgICB0QXVkaW8sIHRGbGFzaCwgdE9iamVjdCwgdFBkZiwgdE90aGVyLCB0Wm9vbUNhY2hlLCB2RGVmYXVsdERpbTtcbiAgICAgICAgICAgIHRNYWluMSA9ICd7cHJldmlld31cXG4nICtcbiAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz1cImt2LXVwbG9hZC1wcm9ncmVzcyBoaWRlXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cCB7Y2xhc3N9XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgIHtjYXB0aW9ufVxcbicgK1xuICAgICAgICAgICAgICAgICcgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICB7cmVtb3ZlfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAge2NhbmNlbH1cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgIHt1cGxvYWR9XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICB7YnJvd3NlfVxcbicgK1xuICAgICAgICAgICAgICAgICcgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgICAgIHRNYWluMiA9ICd7cHJldmlld31cXG48ZGl2IGNsYXNzPVwia3YtdXBsb2FkLXByb2dyZXNzIGhpZGVcIj48L2Rpdj5cXG57cmVtb3ZlfVxcbntjYW5jZWx9XFxue3VwbG9hZH1cXG57YnJvd3NlfVxcbic7XG4gICAgICAgICAgICB0UHJldmlldyA9ICc8ZGl2IGNsYXNzPVwiZmlsZS1wcmV2aWV3IHtjbGFzc31cIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIHtjbG9zZX0nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJ7ZHJvcENsYXNzfVwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy10aHVtYm5haWxzXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPjwvZGl2PicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy1zdGF0dXMgdGV4dC1jZW50ZXIgdGV4dC1zdWNjZXNzXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwia3YtZmlsZWlucHV0LWVycm9yXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnPC9kaXY+JztcbiAgICAgICAgICAgIHRDbG9zZSA9ICc8ZGl2IGNsYXNzPVwiY2xvc2UgZmlsZWlucHV0LXJlbW92ZVwiPiZ0aW1lczs8L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEZpbGVJY29uID0gJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1maWxlIGt2LWNhcHRpb24taWNvblwiPjwvaT4nO1xuICAgICAgICAgICAgdENhcHRpb24gPSAnPGRpdiB0YWJpbmRleD1cIjUwMFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGZpbGUtY2FwdGlvbiB7Y2xhc3N9XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgIDxkaXYgY2xhc3M9XCJmaWxlLWNhcHRpb24tbmFtZVwiPjwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj5cXG4nO1xuICAgICAgICAgICAgLy9ub2luc3BlY3Rpb24gSHRtbFVua25vd25BdHRyaWJ1dGVcbiAgICAgICAgICAgIHRCdG5EZWZhdWx0ID0gJzxidXR0b24gdHlwZT1cInt0eXBlfVwiIHRhYmluZGV4PVwiNTAwXCIgdGl0bGU9XCJ7dGl0bGV9XCIgY2xhc3M9XCJ7Y3NzfVwiICcgK1xuICAgICAgICAgICAgICAgICd7c3RhdHVzfT57aWNvbn0ge2xhYmVsfTwvYnV0dG9uPic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEJ0bkxpbmsgPSAnPGEgaHJlZj1cIntocmVmfVwiIHRhYmluZGV4PVwiNTAwXCIgdGl0bGU9XCJ7dGl0bGV9XCIgY2xhc3M9XCJ7Y3NzfVwiIHtzdGF0dXN9PntpY29ufSB7bGFiZWx9PC9hPic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEJ0bkJyb3dzZSA9ICc8ZGl2IHRhYmluZGV4PVwiNTAwXCIgY2xhc3M9XCJ7Y3NzfVwiIHtzdGF0dXN9PntpY29ufSB7bGFiZWx9PC9kaXY+JztcbiAgICAgICAgICAgIHRNb2RhbE1haW4gPSAnPGRpdiBpZD1cIicgKyAkaC5NT0RBTF9JRCArICdcIiBjbGFzcz1cImZpbGUtem9vbS1kaWFsb2cgbW9kYWwgZmFkZVwiICcgK1xuICAgICAgICAgICAgICAgICd0YWJpbmRleD1cIi0xXCIgYXJpYS1sYWJlbGxlZGJ5PVwiJyArICRoLk1PREFMX0lEICsgJ0xhYmVsXCI+PC9kaXY+JztcbiAgICAgICAgICAgIHRNb2RhbCA9ICc8ZGl2IGNsYXNzPVwibW9kYWwtZGlhbG9nIG1vZGFsLWxne3J0bH1cIiByb2xlPVwiZG9jdW1lbnRcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICA8ZGl2IGNsYXNzPVwibW9kYWwtY29udGVudFwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cIm1vZGFsLWhlYWRlclwiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICA8ZGl2IGNsYXNzPVwia3Ytem9vbS1hY3Rpb25zIHB1bGwtcmlnaHRcIj57dG9nZ2xlaGVhZGVyfXtmdWxsc2NyZWVufXtib3JkZXJsZXNzfXtjbG9zZX08L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgICAgPGgzIGNsYXNzPVwibW9kYWwtdGl0bGVcIj57aGVhZGluZ30gPHNtYWxsPjxzcGFuIGNsYXNzPVwia3Ytem9vbS10aXRsZVwiPjwvc3Bhbj48L3NtYWxsPjwvaDM+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8L2Rpdj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5XCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgIDxkaXYgY2xhc3M9XCJmbG9hdGluZy1idXR0b25zXCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgIDxkaXYgY2xhc3M9XCJrdi16b29tLWJvZHkgZmlsZS16b29tLWNvbnRlbnQge3pvb21GcmFtZUNsYXNzfVwiPjwvZGl2PlxcbicgKyAne3ByZXZ9IHtuZXh0fVxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Plxcbic7XG4gICAgICAgICAgICB0UHJvZ3Jlc3MgPSAnPGRpdiBjbGFzcz1cInByb2dyZXNzXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICA8ZGl2IGNsYXNzPVwie2NsYXNzfVwiIHJvbGU9XCJwcm9ncmVzc2JhclwiJyArXG4gICAgICAgICAgICAgICAgJyBhcmlhLXZhbHVlbm93PVwie3BlcmNlbnR9XCIgYXJpYS12YWx1ZW1pbj1cIjBcIiBhcmlhLXZhbHVlbWF4PVwiMTAwXCIgc3R5bGU9XCJ3aWR0aDp7cGVyY2VudH0lO1wiPlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgICAgIHtzdGF0dXN9XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgPC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICB0U2l6ZSA9ICcgPHNhbXA+KHtzaXplVGV4dH0pPC9zYW1wPic7XG4gICAgICAgICAgICB0Rm9vdGVyID0gJzxkaXYgY2xhc3M9XCJmaWxlLXRodW1ibmFpbC1mb290ZXJcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLWZvb3Rlci1jYXB0aW9uXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIj57Y2FwdGlvbn08YnI+e3NpemV9PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICB7cHJvZ3Jlc3N9IHtpbmRpY2F0b3J9IHthY3Rpb25zfVxcbicgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICAgICAgdEFjdGlvbnMgPSAne2RyYWd9XFxuJyArXG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJmaWxlLWFjdGlvbnNcIj5cXG4nICtcbiAgICAgICAgICAgICAgICAnICAgIDxkaXYgY2xhc3M9XCJmaWxlLWZvb3Rlci1idXR0b25zXCI+XFxuJyArXG4gICAgICAgICAgICAgICAgJyAgICAgICAge3VwbG9hZH0ge2RlbGV0ZX0ge3pvb219IHtvdGhlcn0nICtcbiAgICAgICAgICAgICAgICAnICAgIDwvZGl2PlxcbicgK1xuICAgICAgICAgICAgICAgICcgICAgPGRpdiBjbGFzcz1cImNsZWFyZml4XCI+PC9kaXY+XFxuJyArXG4gICAgICAgICAgICAgICAgJzwvZGl2Pic7XG4gICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBIdG1sVW5rbm93bkF0dHJpYnV0ZVxuICAgICAgICAgICAgdEFjdGlvbkRlbGV0ZSA9ICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImt2LWZpbGUtcmVtb3ZlIHtyZW1vdmVDbGFzc31cIiAnICtcbiAgICAgICAgICAgICAgICAndGl0bGU9XCJ7cmVtb3ZlVGl0bGV9XCIge2RhdGFVcmx9e2RhdGFLZXl9PntyZW1vdmVJY29ufTwvYnV0dG9uPlxcbic7XG4gICAgICAgICAgICB0QWN0aW9uVXBsb2FkID0gJzxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwia3YtZmlsZS11cGxvYWQge3VwbG9hZENsYXNzfVwiIHRpdGxlPVwie3VwbG9hZFRpdGxlfVwiPicgK1xuICAgICAgICAgICAgICAgICd7dXBsb2FkSWNvbn08L2J1dHRvbj4nO1xuICAgICAgICAgICAgdEFjdGlvblpvb20gPSAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrdi1maWxlLXpvb20ge3pvb21DbGFzc31cIiAnICtcbiAgICAgICAgICAgICAgICAndGl0bGU9XCJ7em9vbVRpdGxlfVwiPnt6b29tSWNvbn08L2J1dHRvbj4nO1xuICAgICAgICAgICAgdEFjdGlvbkRyYWcgPSAnPHNwYW4gY2xhc3M9XCJmaWxlLWRyYWctaGFuZGxlIHtkcmFnQ2xhc3N9XCIgdGl0bGU9XCJ7ZHJhZ1RpdGxlfVwiPntkcmFnSWNvbn08L3NwYW4+JztcbiAgICAgICAgICAgIHRJbmRpY2F0b3IgPSAnPGRpdiBjbGFzcz1cImZpbGUtdXBsb2FkLWluZGljYXRvclwiIHRpdGxlPVwie2luZGljYXRvclRpdGxlfVwiPntpbmRpY2F0b3J9PC9kaXY+JztcbiAgICAgICAgICAgIHRUYWdCZWYgPSAnPGRpdiBjbGFzcz1cImZpbGUtcHJldmlldy1mcmFtZSB7ZnJhbWVDbGFzc31cIiBpZD1cIntwcmV2aWV3SWR9XCIgZGF0YS1maWxlaW5kZXg9XCJ7ZmlsZWluZGV4fVwiJyArXG4gICAgICAgICAgICAgICAgJyBkYXRhLXRlbXBsYXRlPVwie3RlbXBsYXRlfVwiJztcbiAgICAgICAgICAgIHRUYWdCZWYxID0gdFRhZ0JlZiArICc+PGRpdiBjbGFzcz1cImt2LWZpbGUtY29udGVudFwiPlxcbic7XG4gICAgICAgICAgICB0VGFnQmVmMiA9IHRUYWdCZWYgKyAnIHRpdGxlPVwie2NhcHRpb259XCI+PGRpdiBjbGFzcz1cImt2LWZpbGUtY29udGVudFwiPlxcbic7XG4gICAgICAgICAgICB0VGFnQWZ0ID0gJzwvZGl2Pntmb290ZXJ9XFxuPC9kaXY+XFxuJztcbiAgICAgICAgICAgIHRHZW5lcmljID0gJ3tjb250ZW50fVxcbic7XG4gICAgICAgICAgICB0SHRtbCA9ICc8ZGl2IGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy1odG1sXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiAnICsgJGguU1RZTEVfU0VUVElORyArXG4gICAgICAgICAgICAgICAgJz57ZGF0YX08L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEltYWdlID0gJzxpbWcgc3JjPVwie2RhdGF9XCIgY2xhc3M9XCJmaWxlLXByZXZpZXctaW1hZ2Uga3YtcHJldmlldy1kYXRhXCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiBhbHQ9XCJ7Y2FwdGlvbn1cIiAnICtcbiAgICAgICAgICAgICAgICAkaC5TVFlMRV9TRVRUSU5HICsgJz5cXG4nO1xuICAgICAgICAgICAgdFRleHQgPSAnPHRleHRhcmVhIGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy10ZXh0XCIgdGl0bGU9XCJ7Y2FwdGlvbn1cIiByZWFkb25seSAnICtcbiAgICAgICAgICAgICAgICAkaC5TVFlMRV9TRVRUSU5HICsgJz57ZGF0YX08L3RleHRhcmVhPlxcbic7XG4gICAgICAgICAgICB0VmlkZW8gPSAnPHZpZGVvIGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtcHJldmlldy12aWRlb1wiIHdpZHRoPVwie3dpZHRofVwiICcgK1xuICAgICAgICAgICAgICAgICdoZWlnaHQ9XCJ7aGVpZ2h0fVwiIGNvbnRyb2xzPlxcbicgKyAnPHNvdXJjZSBzcmM9XCJ7ZGF0YX1cIiB0eXBlPVwie3R5cGV9XCI+XFxuJyArICRoLkRFRkFVTFRfUFJFVklFVyArXG4gICAgICAgICAgICAgICAgJ1xcbjwvdmlkZW8+XFxuJztcbiAgICAgICAgICAgIHRBdWRpbyA9ICc8ZGl2IGNsYXNzPVwiZmlsZS1wcmV2aWV3LWF1ZGlvXCI+PGF1ZGlvIGNsYXNzPVwia3YtcHJldmlldy1kYXRhXCIgY29udHJvbHM+XFxuPHNvdXJjZSBzcmM9XCJ7ZGF0YX1cIiAnICtcbiAgICAgICAgICAgICAgICAndHlwZT1cInt0eXBlfVwiPlxcbicgKyAkaC5ERUZBVUxUX1BSRVZJRVcgKyAnXFxuPC9hdWRpbz48L2Rpdj5cXG4nO1xuICAgICAgICAgICAgdEZsYXNoID0gJzxvYmplY3QgY2xhc3M9XCJrdi1wcmV2aWV3LWRhdGEgZmlsZS1vYmplY3RcIiB0eXBlPVwiYXBwbGljYXRpb24veC1zaG9ja3dhdmUtZmxhc2hcIiAnICtcbiAgICAgICAgICAgICAgICAnd2lkdGg9XCJ7d2lkdGh9XCIgaGVpZ2h0PVwie2hlaWdodH1cIiBkYXRhPVwie2RhdGF9XCI+XFxuJyArICRoLk9CSkVDVF9QQVJBTVMgKyAnICcgKyAkaC5ERUZBVUxUX1BSRVZJRVcgK1xuICAgICAgICAgICAgICAgICdcXG48L29iamVjdD5cXG4nO1xuICAgICAgICAgICAgdE9iamVjdCA9ICc8b2JqZWN0IGNsYXNzPVwia3YtcHJldmlldy1kYXRhIGZpbGUtb2JqZWN0IHt0eXBlQ3NzfVwiIGRhdGE9XCJ7ZGF0YX1cIiB0eXBlPVwie3R5cGV9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3dpZHRoPVwie3dpZHRofVwiIGhlaWdodD1cIntoZWlnaHR9XCI+XFxuJyArICc8cGFyYW0gbmFtZT1cIm1vdmllXCIgdmFsdWU9XCJ7Y2FwdGlvbn1cIiAvPlxcbicgK1xuICAgICAgICAgICAgICAgICRoLk9CSkVDVF9QQVJBTVMgKyAnICcgKyAkaC5ERUZBVUxUX1BSRVZJRVcgKyAnXFxuPC9vYmplY3Q+XFxuJztcbiAgICAgICAgICAgIHRQZGYgPSAnPGVtYmVkIGNsYXNzPVwia3YtcHJldmlldy1kYXRhXCIgc3JjPVwie2RhdGF9XCIgJyArXG4gICAgICAgICAgICAgICAgJ3dpZHRoPVwie3dpZHRofVwiIGhlaWdodD1cIntoZWlnaHR9XCIgdHlwZT1cImFwcGxpY2F0aW9uL3BkZlwiPlxcbic7XG4gICAgICAgICAgICB0T3RoZXIgPSAnPGRpdiBjbGFzcz1cImt2LXByZXZpZXctZGF0YSBmaWxlLXByZXZpZXctb3RoZXItZnJhbWVcIj5cXG4nICsgJGguREVGQVVMVF9QUkVWSUVXICsgJ1xcbjwvZGl2Plxcbic7XG4gICAgICAgICAgICB0Wm9vbUNhY2hlID0gJzxkaXYgY2xhc3M9XCJrdi16b29tLWNhY2hlXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmVcIj57em9vbUNvbnRlbnR9PC9kaXY+JztcbiAgICAgICAgICAgIHZEZWZhdWx0RGltID0ge3dpZHRoOiBcIjEwMCVcIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9O1xuICAgICAgICAgICAgc2VsZi5kZWZhdWx0cyA9IHtcbiAgICAgICAgICAgICAgICBsYXlvdXRUZW1wbGF0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgbWFpbjE6IHRNYWluMSxcbiAgICAgICAgICAgICAgICAgICAgbWFpbjI6IHRNYWluMixcbiAgICAgICAgICAgICAgICAgICAgcHJldmlldzogdFByZXZpZXcsXG4gICAgICAgICAgICAgICAgICAgIGNsb3NlOiB0Q2xvc2UsXG4gICAgICAgICAgICAgICAgICAgIGZpbGVJY29uOiB0RmlsZUljb24sXG4gICAgICAgICAgICAgICAgICAgIGNhcHRpb246IHRDYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICBtb2RhbE1haW46IHRNb2RhbE1haW4sXG4gICAgICAgICAgICAgICAgICAgIG1vZGFsOiB0TW9kYWwsXG4gICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiB0UHJvZ3Jlc3MsXG4gICAgICAgICAgICAgICAgICAgIHNpemU6IHRTaXplLFxuICAgICAgICAgICAgICAgICAgICBmb290ZXI6IHRGb290ZXIsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvcjogdEluZGljYXRvcixcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uczogdEFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbkRlbGV0ZTogdEFjdGlvbkRlbGV0ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uVXBsb2FkOiB0QWN0aW9uVXBsb2FkLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25ab29tOiB0QWN0aW9uWm9vbSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uRHJhZzogdEFjdGlvbkRyYWcsXG4gICAgICAgICAgICAgICAgICAgIGJ0bkRlZmF1bHQ6IHRCdG5EZWZhdWx0LFxuICAgICAgICAgICAgICAgICAgICBidG5MaW5rOiB0QnRuTGluayxcbiAgICAgICAgICAgICAgICAgICAgYnRuQnJvd3NlOiB0QnRuQnJvd3NlLFxuICAgICAgICAgICAgICAgICAgICB6b29tQ2FjaGU6IHRab29tQ2FjaGVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdNYXJrdXBUYWdzOiB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ0JlZm9yZTE6IHRUYWdCZWYxLFxuICAgICAgICAgICAgICAgICAgICB0YWdCZWZvcmUyOiB0VGFnQmVmMixcbiAgICAgICAgICAgICAgICAgICAgdGFnQWZ0ZXI6IHRUYWdBZnRcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByZXZpZXdDb250ZW50VGVtcGxhdGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIGdlbmVyaWM6IHRHZW5lcmljLFxuICAgICAgICAgICAgICAgICAgICBodG1sOiB0SHRtbCxcbiAgICAgICAgICAgICAgICAgICAgaW1hZ2U6IHRJbWFnZSxcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogdFRleHQsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0VmlkZW8sXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0QXVkaW8sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiB0Rmxhc2gsXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdDogdE9iamVjdCxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiB0UGRmLFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjogdE90aGVyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbGxvd2VkUHJldmlld1R5cGVzOiBbJ2ltYWdlJywgJ2h0bWwnLCAndGV4dCcsICd2aWRlbycsICdhdWRpbycsICdmbGFzaCcsICdwZGYnLCAnb2JqZWN0J10sXG4gICAgICAgICAgICAgICAgcHJldmlld1RlbXBsYXRlczoge30sXG4gICAgICAgICAgICAgICAgcHJldmlld1NldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIGh0bWw6IHt3aWR0aDogXCIyMTNweFwiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHt3aWR0aDogXCIyMTNweFwiLCBoZWlnaHQ6IFwiMTYwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTAwJVwiLCAnbWF4LXdpZHRoJzogXCIxMDAlXCJ9LFxuICAgICAgICAgICAgICAgICAgICBhdWRpbzoge3dpZHRoOiBcIjEwMCVcIiwgaGVpZ2h0OiBcIjMwcHhcIn0sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiB7d2lkdGg6IFwiYXV0b1wiLCBoZWlnaHQ6IFwiMTAwJVwiLCAnbWF4LXdpZHRoJzogXCIxMDAlXCJ9LFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IHtoZWlnaHQ6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiB7d2lkdGg6IFwiMTYwcHhcIiwgaGVpZ2h0OiBcIjE2MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjoge3dpZHRoOiBcIjE2MHB4XCIsIGhlaWdodDogXCIxNjBweFwifVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcHJldmlld1pvb21TZXR0aW5nczoge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZToge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcImF1dG9cIiwgJ21heC13aWR0aCc6IFwiMTAwJVwiLCAnbWF4LWhlaWdodCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgaHRtbDogdkRlZmF1bHREaW0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IHZEZWZhdWx0RGltLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21heC13aWR0aCc6IFwiMTAwJVwifSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW86IHt3aWR0aDogXCIxMDAlXCIsIGhlaWdodDogXCIzMHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBmbGFzaDoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjQ4MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IHt3aWR0aDogXCJhdXRvXCIsIGhlaWdodDogXCIxMDAlXCIsICdtYXgtd2lkdGgnOiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9LFxuICAgICAgICAgICAgICAgICAgICBwZGY6IHZEZWZhdWx0RGltLFxuICAgICAgICAgICAgICAgICAgICBvdGhlcjoge3dpZHRoOiBcImF1dG9cIiwgaGVpZ2h0OiBcIjEwMCVcIiwgJ21pbi1oZWlnaHQnOiBcIjQ4MHB4XCJ9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmaWxlVHlwZVNldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2ltYWdlLionKSB8fCAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKGdpZnxwbmd8anBlP2cpJC9pKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgaHRtbDogZnVuY3Rpb24gKHZUeXBlLCB2TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRoLmNvbXBhcmUodlR5cGUsICd0ZXh0L2h0bWwnKSB8fCAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKGh0bXxodG1sKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IGZ1bmN0aW9uICh2VHlwZSwgdk5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkaC5jb21wYXJlKHZUeXBlLCAndGV4dC4qJykgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLih4bWx8amF2YXNjcmlwdCkkL2kpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguY29tcGFyZSh2TmFtZSwgL1xcLih0eHR8bWR8Y3N2fG5mb3xpbml8anNvbnxwaHB8anN8Y3NzKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ3ZpZGVvLionKSAmJiAoJGguY29tcGFyZSh2VHlwZSwgLyhvZ2d8bXA0fG1wP2d8bW92fHdlYm18M2dwKSQvaSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKG9nP3xtcDR8d2VibXxtcD9nfG1vdnwzZ3ApJC9pKSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2F1ZGlvLionKSAmJiAoJGguY29tcGFyZSh2TmFtZSwgLyhvZ2d8bXAzfG1wP2d8d2F2KSQvaSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jb21wYXJlKHZOYW1lLCAvXFwuKG9nP3xtcDN8bXA/Z3x3YXYpJC9pKSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZsYXNoOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2FwcGxpY2F0aW9uL3gtc2hvY2t3YXZlLWZsYXNoJywgdHJ1ZSkgfHwgJGguY29tcGFyZSh2TmFtZSwgL1xcLihzd2YpJC9pKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgcGRmOiBmdW5jdGlvbiAodlR5cGUsIHZOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGguY29tcGFyZSh2VHlwZSwgJ2FwcGxpY2F0aW9uL3BkZicsIHRydWUpIHx8ICRoLmNvbXBhcmUodk5hbWUsIC9cXC4ocGRmKSQvaSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG90aGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmlsZUFjdGlvblNldHRpbmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIHNob3dSZW1vdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNob3dVcGxvYWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHNob3dab29tOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBzaG93RHJhZzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmFzaCB0ZXh0LWRhbmdlclwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICByZW1vdmVDbGFzczogJ2J0biBidG4teHMgYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICByZW1vdmVUaXRsZTogJ1JlbW92ZSBmaWxlJyxcbiAgICAgICAgICAgICAgICAgICAgdXBsb2FkSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi11cGxvYWQgdGV4dC1pbmZvXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZENsYXNzOiAnYnRuIGJ0bi14cyBidG4tZGVmYXVsdCcsXG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZFRpdGxlOiAnVXBsb2FkIGZpbGUnLFxuICAgICAgICAgICAgICAgICAgICB6b29tSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi16b29tLWluXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIHpvb21DbGFzczogJ2J0biBidG4teHMgYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgICAgICB6b29tVGl0bGU6ICdWaWV3IERldGFpbHMnLFxuICAgICAgICAgICAgICAgICAgICBkcmFnSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1tZW51LWhhbWJ1cmdlclwiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBkcmFnQ2xhc3M6ICd0ZXh0LWluZm8nLFxuICAgICAgICAgICAgICAgICAgICBkcmFnVGl0bGU6ICdNb3ZlIC8gUmVhcnJhbmdlJyxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1NldHRpbmdzOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yTmV3OiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWhhbmQtZG93biB0ZXh0LXdhcm5pbmdcIj48L2k+JyxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yU3VjY2VzczogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1vay1zaWduIHRleHQtc3VjY2Vzc1wiPjwvaT4nLFxuICAgICAgICAgICAgICAgICAgICBpbmRpY2F0b3JFcnJvcjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1leGNsYW1hdGlvbi1zaWduIHRleHQtZGFuZ2VyXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvckxvYWRpbmc6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24taGFuZC11cCB0ZXh0LW11dGVkXCI+PC9pPicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvck5ld1RpdGxlOiAnTm90IHVwbG9hZGVkIHlldCcsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvclN1Y2Nlc3NUaXRsZTogJ1VwbG9hZGVkJyxcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNhdG9yRXJyb3JUaXRsZTogJ1VwbG9hZCBFcnJvcicsXG4gICAgICAgICAgICAgICAgICAgIGluZGljYXRvckxvYWRpbmdUaXRsZTogJ1VwbG9hZGluZyAuLi4nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICQuZWFjaChzZWxmLmRlZmF1bHRzLCBmdW5jdGlvbiAoa2V5LCBzZXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2FsbG93ZWRQcmV2aWV3VHlwZXMnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmFsbG93ZWRQcmV2aWV3VHlwZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzID0gc2V0dGluZztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGZba2V5XSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBzZXR0aW5nLCBzZWxmW2tleV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld1RlbXBsYXRlcygpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXdUZW1wbGF0ZXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2ZnID0gc2VsZi5kZWZhdWx0cywgdGFncyA9IHNlbGYucHJldmlld01hcmt1cFRhZ3MsIHRhZ0JlZiwgdGFnQWZ0ID0gdGFncy50YWdBZnRlcjtcbiAgICAgICAgICAgICQuZWFjaChjZmcucHJldmlld0NvbnRlbnRUZW1wbGF0ZXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoc2VsZi5wcmV2aWV3VGVtcGxhdGVzW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ0JlZiA9IHRhZ3MudGFnQmVmb3JlMjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2dlbmVyaWMnIHx8IGtleSA9PT0gJ2ltYWdlJyB8fCBrZXkgPT09ICdodG1sJyB8fCBrZXkgPT09ICd0ZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnQmVmID0gdGFncy50YWdCZWZvcmUxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld1RlbXBsYXRlc1trZXldID0gdGFnQmVmICsgdmFsdWUgKyB0YWdBZnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0UHJldmlld0NhY2hlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZSA9IHtcbiAgICAgICAgICAgICAgICBkYXRhOiB7fSxcbiAgICAgICAgICAgICAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZW50ID0gc2VsZi5pbml0aWFsUHJldmlldztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMCAmJiAhJGguaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3BsaXQoc2VsZi5pbml0aWFsUHJldmlld0RlbGltaXRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdzOiBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmZXRjaDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50LmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4gIT09IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY291bnQ6IGZ1bmN0aW9uIChhbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSAmJiAhIXNlbGYucHJldmlld0NhY2hlLmRhdGEuY29udGVudCA/XG4gICAgICAgICAgICAgICAgICAgICAgICAoYWxsID8gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb250ZW50Lmxlbmd0aCA6IHNlbGYucHJldmlld0NhY2hlLmZldGNoKCkubGVuZ3RoKSA6IDA7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIChpLCBpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmQgPSAnaW5pdF8nICsgaSwgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGRhdGEuY29udGVudFtpXSwgcHJldmlld0lkID0gc2VsZi5wcmV2aWV3SW5pdElkICsgJy0nICsgaW5kLCBvdXQsICR0bXAsIGNhdCwgZnRyLFxuICAgICAgICAgICAgICAgICAgICAgICAgZm5hbWUsIGZ0eXBlLCBmcmFtZUNsYXNzLCBhc0RhdGEgPSAkaC5pZlNldCgncHJldmlld0FzRGF0YScsIGNvbmZpZywgc2VsZi5pbml0aWFsUHJldmlld0FzRGF0YSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJzZVRlbXBsYXRlID0gZnVuY3Rpb24gKGNhdCwgZGF0LCBmbiwgZnQsIGlkLCBmdHIsIGluZCwgZmMsIHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYyA9ICcgZmlsZS1wcmV2aWV3LWluaXRpYWwgJyArICRoLlNPUlRfQ1NTICsgKGZjID8gJyAnICsgZmMgOiAnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dlbmVyYXRlUHJldmlld1RlbXBsYXRlKGNhdCwgZGF0LCBmbiwgZnQsIGlkLCBmYWxzZSwgbnVsbCwgZmMsIGZ0ciwgaW5kLCB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29udGVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQgPSBpc0Rpc2FibGVkID09PSB1bmRlZmluZWQgPyB0cnVlIDogaXNEaXNhYmxlZDtcbiAgICAgICAgICAgICAgICAgICAgY2F0ID0gJGguaWZTZXQoJ3R5cGUnLCBjb25maWcsIHNlbGYuaW5pdGlhbFByZXZpZXdGaWxlVHlwZSB8fCAnZ2VuZXJpYycpO1xuICAgICAgICAgICAgICAgICAgICBmbmFtZSA9ICRoLmlmU2V0KCdmaWxlbmFtZScsIGNvbmZpZywgJGguaWZTZXQoJ2NhcHRpb24nLCBjb25maWcpKTtcbiAgICAgICAgICAgICAgICAgICAgZnR5cGUgPSAkaC5pZlNldCgnZmlsZXR5cGUnLCBjb25maWcsIGNhdCk7XG4gICAgICAgICAgICAgICAgICAgIGZ0ciA9IHNlbGYucHJldmlld0NhY2hlLmZvb3RlcihpLCBpc0Rpc2FibGVkLCAoY29uZmlnICYmIGNvbmZpZy5zaXplIHx8IG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVDbGFzcyA9ICRoLmlmU2V0KCdmcmFtZUNsYXNzJywgY29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFzRGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gcGFyc2VUZW1wbGF0ZShjYXQsIGNvbnRlbnQsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBmdHIsIGluZCwgZnJhbWVDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSBwYXJzZVRlbXBsYXRlKCdnZW5lcmljJywgY29udGVudCwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGZ0ciwgaW5kLCBmcmFtZUNsYXNzLCBjYXQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNldFRva2Vucyh7J2NvbnRlbnQnOiBkYXRhLmNvbnRlbnRbaV19KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS50YWdzLmxlbmd0aCAmJiBkYXRhLnRhZ3NbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9ICRoLnJlcGxhY2VUYWdzKG91dCwgZGF0YS50YWdzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBjb25maWcuZnJhbWVBdHRyICovXG4gICAgICAgICAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShjb25maWcpICYmICEkaC5pc0VtcHR5KGNvbmZpZy5mcmFtZUF0dHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdG1wID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaHRtbChvdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRtcC5maW5kKCcuZmlsZS1wcmV2aWV3LWluaXRpYWwnKS5hdHRyKGNvbmZpZy5mcmFtZUF0dHIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gJHRtcC5odG1sKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdG1wLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhZGQ6IGZ1bmN0aW9uIChjb250ZW50LCBjb25maWcsIHRhZ3MsIGFwcGVuZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmRhdGEsIGluZGV4O1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRoLmlzQXJyYXkoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNwbGl0KHNlbGYuaW5pdGlhbFByZXZpZXdEZWxpbWl0ZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gZGF0YS5jb250ZW50LnB1c2goY29udGVudCkgLSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWdbaW5kZXhdID0gY29uZmlnO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzW2luZGV4XSA9IHRhZ3M7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGNvbnRlbnQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29udGVudCA9IGNvbnRlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFncyA9IHRhZ3M7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKGNvbnRlbnQsIGNvbmZpZywgdGFncywgYXBwZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSwgaSwgY2hrO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbnRlbnQgfHwgIWNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkaC5pc0FycmF5KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gY29udGVudC5zcGxpdChzZWxmLmluaXRpYWxQcmV2aWV3RGVsaW1pdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjaGsgPSBjb250ZW50LmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG4gIT09IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNoay5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5jb250ZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29udGVudCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNvbmZpZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnRhZ3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS50YWdzID0gW107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFwcGVuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbnRlbnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udGVudFtpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQucHVzaChjb250ZW50W2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29uZmlnLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbmZpZ1tpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbmZpZy5wdXNoKGNvbmZpZ1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3MucHVzaCh0YWdzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnQgPSBjb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb25maWcgPSBjb25maWc7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnRhZ3MgPSB0YWdzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdW5zZXQ6IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hrID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjaGspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hrID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbnRlbnQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEuY29uZmlnID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLnRhZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLmNvbnRlbnRbaW5kZXhdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS5jb25maWdbaW5kZXhdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YS50YWdzW2luZGV4XSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvdXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGh0bWwgPSAnJywgY2FwdGlvbiwgbGVuID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQodHJ1ZSksIGk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZW4gPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7Y29udGVudDogJycsIGNhcHRpb246ICcnfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0bWwgKz0gc2VsZi5wcmV2aWV3Q2FjaGUuZ2V0KGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzZWxmLl9nZXRNc2dTZWxlY3RlZChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtjb250ZW50OiBodG1sLCBjYXB0aW9uOiBjYXB0aW9ufTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZvb3RlcjogZnVuY3Rpb24gKGksIGlzRGlzYWJsZWQsIHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEgfHwgIWRhdGEuY29uZmlnIHx8IGRhdGEuY29uZmlnLmxlbmd0aCA9PT0gMCB8fCAkaC5pc0VtcHR5KGRhdGEuY29uZmlnW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzRGlzYWJsZWQgPSBpc0Rpc2FibGVkID09PSB1bmRlZmluZWQgPyB0cnVlIDogaXNEaXNhYmxlZDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldLCBjYXB0aW9uID0gJGguaWZTZXQoJ2NhcHRpb24nLCBjb25maWcpLCBhY3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAkaC5pZlNldCgnd2lkdGgnLCBjb25maWcsICdhdXRvJyksIHVybCA9ICRoLmlmU2V0KCd1cmwnLCBjb25maWcsIGZhbHNlKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9ICRoLmlmU2V0KCdrZXknLCBjb25maWcsIG51bGwpLCBmcyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdFByZXZpZXdTaG93RGVsID0gc2VsZi5pbml0aWFsUHJldmlld1Nob3dEZWxldGUgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93RGVsID0gJGguaWZTZXQoJ3Nob3dEZWxldGUnLCBjb25maWcsICRoLmlmU2V0KCdzaG93RGVsZXRlJywgZnMsIGluaXRQcmV2aWV3U2hvd0RlbCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd1pvb20gPSAkaC5pZlNldCgnc2hvd1pvb20nLCBjb25maWcsICRoLmlmU2V0KCdzaG93Wm9vbScsIGZzLCB0cnVlKSksXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93RHJhZyA9ICRoLmlmU2V0KCdzaG93RHJhZycsIGNvbmZpZywgJGguaWZTZXQoJ3Nob3dEcmFnJywgZnMsIHRydWUpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkID0gKHVybCA9PT0gZmFsc2UpICYmIGlzRGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnMgPSBzZWxmLl9yZW5kZXJGaWxlQWN0aW9ucyhmYWxzZSwgc2hvd0RlbCwgc2hvd1pvb20sIHNob3dEcmFnLCBkaXNhYmxlZCwgdXJsLCBrZXksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Zvb3RlcicpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAncHJvZ3Jlc3MnOiBzZWxmLl9yZW5kZXJUaHVtYlByb2dyZXNzKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAnYWN0aW9ucyc6IGFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZSc6IHNlbGYuX2dldFNpemUoc2l6ZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdpbmRpY2F0b3InOiAnJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuaW5pdCgpO1xuICAgICAgICB9LFxuICAgICAgICBfaGFuZGxlcjogZnVuY3Rpb24gKCRlbCwgZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIG5zID0gc2VsZi5uYW1lc3BhY2UsIGV2ID0gZXZlbnQuc3BsaXQoJyAnKS5qb2luKG5zICsgJyAnKSArIG5zO1xuICAgICAgICAgICAgaWYgKCEkZWwgfHwgISRlbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkZWwub2ZmKGV2KS5vbihldiwgY2FsbGJhY2spO1xuICAgICAgICB9LFxuICAgICAgICBfbG9nOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGlkID0gc2VsZi4kZWxlbWVudC5hdHRyKCdpZCcpO1xuICAgICAgICAgICAgaWYgKGlkKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gJ1wiJyArIGlkICsgJ1wiOiAnICsgbXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuY29uc29sZS5sb2cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmFsZXJ0KG1zZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF92YWxpZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBzdGF0dXMgPSBzZWxmLiRlbGVtZW50LmF0dHIoJ3R5cGUnKSA9PT0gJ2ZpbGUnO1xuICAgICAgICAgICAgaWYgKCFzdGF0dXMpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9sb2coJ1RoZSBpbnB1dCBcInR5cGVcIiBtdXN0IGJlIHNldCB0byBcImZpbGVcIiBmb3IgaW5pdGlhbGl6aW5nIHRoZSBcImJvb3RzdHJhcC1maWxlaW5wdXRcIiBwbHVnaW4uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3RhdHVzO1xuICAgICAgICB9LFxuICAgICAgICBfZXJyb3JzRXhpc3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVycjtcbiAgICAgICAgICAgIGlmIChzZWxmLiRlcnJvckNvbnRhaW5lci5maW5kKCdsaScpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVyciA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwoc2VsZi4kZXJyb3JDb250YWluZXIuaHRtbCgpKTtcbiAgICAgICAgICAgICRlcnIuZmluZCgnc3Bhbi5rdi1lcnJvci1jbG9zZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgJGVyci5maW5kKCd1bCcpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuICQudHJpbSgkZXJyLnRleHQoKSkubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBfZXJyb3JIYW5kbGVyOiBmdW5jdGlvbiAoZXZ0LCBjYXB0aW9uKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGVyciA9IGV2dC50YXJnZXQuZXJyb3IsIHNob3dFcnJvciA9IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93RXJyb3IobXNnLnJlcGxhY2UoJ3tuYW1lfScsIGNhcHRpb24pKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBlcnIuTk9UX0ZPVU5EX0VSUiAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZXJyLlNFQ1VSSVRZX0VSUiAqL1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZXJyLk5PVF9SRUFEQUJMRV9FUlIgKi9cbiAgICAgICAgICAgIGlmIChlcnIuY29kZSA9PT0gZXJyLk5PVF9GT1VORF9FUlIpIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlTm90Rm91bmQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChlcnIuY29kZSA9PT0gZXJyLlNFQ1VSSVRZX0VSUikge1xuICAgICAgICAgICAgICAgIHNob3dFcnJvcihzZWxmLm1zZ0ZpbGVTZWN1cmVkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyLmNvZGUgPT09IGVyci5OT1RfUkVBREFCTEVfRVJSKSB7XG4gICAgICAgICAgICAgICAgc2hvd0Vycm9yKHNlbGYubXNnRmlsZU5vdFJlYWRhYmxlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyLmNvZGUgPT09IGVyci5BQk9SVF9FUlIpIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlUHJldmlld0Fib3J0ZWQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaG93RXJyb3Ioc2VsZi5tc2dGaWxlUHJldmlld0Vycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2FkZEVycm9yOiBmdW5jdGlvbiAobXNnKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKG1zZyAmJiAkZXJyb3IubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmh0bWwoc2VsZi5lcnJvckNsb3NlQnV0dG9uICsgbXNnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlcnJvci5maW5kKCcua3YtZXJyb3ItY2xvc2UnKSwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkZXJyb3IuZmFkZU91dCgnc2xvdycpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfcmVzZXRFcnJvcnM6IGZ1bmN0aW9uIChmYWRlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gZmFsc2U7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgJGVycm9yLmh0bWwoJycpO1xuICAgICAgICAgICAgaWYgKGZhZGUpIHtcbiAgICAgICAgICAgICAgICAkZXJyb3IuZmFkZU91dCgnc2xvdycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkZXJyb3IuaGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2hvd0ZvbGRlckVycm9yOiBmdW5jdGlvbiAoZm9sZGVycykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZXJyb3IgPSBzZWxmLiRlcnJvckNvbnRhaW5lciwgbXNnO1xuICAgICAgICAgICAgaWYgKCFmb2xkZXJzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dGb2xkZXJzTm90QWxsb3dlZC5yZXBsYWNlKCd7bn0nLCBmb2xkZXJzKTtcbiAgICAgICAgICAgIHNlbGYuX2FkZEVycm9yKG1zZyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgICAgICAkZXJyb3IuZmFkZUluKDgwMCk7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWZvbGRlcmVycm9yJywgW2ZvbGRlcnMsIG1zZ10pO1xuICAgICAgICB9LFxuICAgICAgICBfc2hvd1VwbG9hZEVycm9yOiBmdW5jdGlvbiAobXNnLCBwYXJhbXMsIGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyLCBldiA9IGV2ZW50IHx8ICdmaWxldXBsb2FkZXJyb3InLCBlID0gcGFyYW1zICYmIHBhcmFtcy5pZCA/XG4gICAgICAgICAgICAnPGxpIGRhdGEtZmlsZS1pZD1cIicgKyBwYXJhbXMuaWQgKyAnXCI+JyArIG1zZyArICc8L2xpPicgOiAnPGxpPicgKyBtc2cgKyAnPC9saT4nO1xuICAgICAgICAgICAgaWYgKCRlcnJvci5maW5kKCd1bCcpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2FkZEVycm9yKCc8dWw+JyArIGUgKyAnPC91bD4nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJGVycm9yLmZpbmQoJ3VsJykuYXBwZW5kKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGVycm9yLmZhZGVJbig4MDApO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoZXYsIFtwYXJhbXMsIG1zZ10pO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLWlucHV0LW5ldycpO1xuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2hhcy1lcnJvcicpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9zaG93RXJyb3I6IGZ1bmN0aW9uIChtc2csIHBhcmFtcywgZXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVycm9yID0gc2VsZi4kZXJyb3JDb250YWluZXIsIGV2ID0gZXZlbnQgfHwgJ2ZpbGVlcnJvcic7XG4gICAgICAgICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgICAgICAgICBwYXJhbXMucmVhZGVyID0gc2VsZi5yZWFkZXI7XG4gICAgICAgICAgICBzZWxmLl9hZGRFcnJvcihtc2cpO1xuICAgICAgICAgICAgJGVycm9yLmZhZGVJbig4MDApO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoZXYsIFtwYXJhbXMsIG1zZ10pO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgICAgICBzZWxmLiRidG5VcGxvYWQuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfbm9GaWxlc0Vycm9yOiBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGxhYmVsID0gc2VsZi5taW5GaWxlQ291bnQgPiAxID8gc2VsZi5maWxlUGx1cmFsIDogc2VsZi5maWxlU2luZ2xlLFxuICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnRmlsZXNUb29MZXNzLnJlcGxhY2UoJ3tufScsIHNlbGYubWluRmlsZUNvdW50KS5yZXBsYWNlKCd7ZmlsZXN9JywgbGFiZWwpLFxuICAgICAgICAgICAgICAgICRlcnJvciA9IHNlbGYuJGVycm9yQ29udGFpbmVyO1xuICAgICAgICAgICAgc2VsZi5fYWRkRXJyb3IobXNnKTtcbiAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IHRydWU7XG4gICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscygwKTtcbiAgICAgICAgICAgICRlcnJvci5mYWRlSW4oODAwKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlZXJyb3InLCBbcGFyYW1zLCBtc2ddKTtcbiAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnaGFzLWVycm9yJyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9wYXJzZUVycm9yOiBmdW5jdGlvbiAob3BlcmF0aW9uLCBqcVhIUiwgZXJyb3JUaHJvd24sIGZpbGVOYW1lKSB7XG4gICAgICAgICAgICAvKiogQG5hbWVzcGFjZSBqcVhIUi5yZXNwb25zZUpTT04gKi9cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZXJyTXNnID0gJC50cmltKGVycm9yVGhyb3duICsgJycpLCBkb3QgPSBlcnJNc2cuc2xpY2UoLTEpID09PSAnLicgPyAnJyA6ICcuJyxcbiAgICAgICAgICAgICAgICB0ZXh0ID0ganFYSFIucmVzcG9uc2VKU09OICE9PSB1bmRlZmluZWQgJiYganFYSFIucmVzcG9uc2VKU09OLmVycm9yICE9PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgICAgICAgICBqcVhIUi5yZXNwb25zZUpTT04uZXJyb3IgOiBqcVhIUi5yZXNwb25zZVRleHQ7XG4gICAgICAgICAgICBpZiAoc2VsZi5jYW5jZWxsaW5nICYmIHNlbGYubXNnVXBsb2FkQWJvcnRlZCkge1xuICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYubXNnVXBsb2FkQWJvcnRlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dBamF4RXJyb3JEZXRhaWxzICYmIHRleHQpIHtcbiAgICAgICAgICAgICAgICB0ZXh0ID0gJC50cmltKHRleHQucmVwbGFjZSgvXFxuXFxzKlxcbi9nLCAnXFxuJykpO1xuICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0Lmxlbmd0aCA+IDAgPyAnPHByZT4nICsgdGV4dCArICc8L3ByZT4nIDogJyc7XG4gICAgICAgICAgICAgICAgZXJyTXNnICs9IGRvdCArIHRleHQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVyck1zZyArPSBkb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXJyTXNnID09PSBkb3QpIHtcbiAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLm1zZ0FqYXhFcnJvci5yZXBsYWNlKCd7b3BlcmF0aW9ufScsIG9wZXJhdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLmNhbmNlbGxpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBmaWxlTmFtZSA/ICc8Yj4nICsgZmlsZU5hbWUgKyAnOiA8L2I+JyArIGVyck1zZyA6IGVyck1zZztcbiAgICAgICAgfSxcbiAgICAgICAgX3BhcnNlRmlsZVR5cGU6IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGlzVmFsaWQsIHZUeXBlLCBjYXQsIGksIHR5cGVzID0gc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzIHx8IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2F0ID0gdHlwZXNbaV07XG4gICAgICAgICAgICAgICAgaXNWYWxpZCA9IHNlbGYuZmlsZVR5cGVTZXR0aW5nc1tjYXRdO1xuICAgICAgICAgICAgICAgIHZUeXBlID0gaXNWYWxpZChmaWxlLnR5cGUsIGZpbGUubmFtZSkgPyBjYXQgOiAnJztcbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkodlR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2VHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ290aGVyJztcbiAgICAgICAgfSxcbiAgICAgICAgX2dldFByZXZpZXdJY29uOiBmdW5jdGlvbiAoZm5hbWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZXh0LCBvdXQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKGZuYW1lICYmIGZuYW1lLmluZGV4T2YoJy4nKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgZXh0ID0gZm5hbWUuc3BsaXQoJy4nKS5wb3AoKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLnByZXZpZXdGaWxlSWNvblNldHRpbmdzW2V4dF0gfHwgc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5nc1tleHQudG9Mb3dlckNhc2UoKV0gfHwgbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYucHJldmlld0ZpbGVFeHRTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgICAgICAkLmVhY2goc2VsZi5wcmV2aWV3RmlsZUV4dFNldHRpbmdzLCBmdW5jdGlvbiAoa2V5LCBmdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5wcmV2aWV3RmlsZUljb25TZXR0aW5nc1trZXldICYmIGZ1bmMoZXh0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IHNlbGYucHJldmlld0ZpbGVJY29uU2V0dGluZ3Nba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL25vaW5zcGVjdGlvbiBVbm5lY2Vzc2FyeVJldHVyblN0YXRlbWVudEpTXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBfcGFyc2VGaWxlUHJldmlld0ljb246IGZ1bmN0aW9uIChjb250ZW50LCBmbmFtZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpY24gPSBzZWxmLl9nZXRQcmV2aWV3SWNvbihmbmFtZSkgfHwgc2VsZi5wcmV2aWV3RmlsZUljb24sIG91dCA9IGNvbnRlbnQ7XG4gICAgICAgICAgICBpZiAob3V0LmluZGV4T2YoJ3twcmV2aWV3RmlsZUljb259JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIG91dCA9IG91dC5zZXRUb2tlbnMoeydwcmV2aWV3RmlsZUljb25DbGFzcyc6IHNlbGYucHJldmlld0ZpbGVJY29uQ2xhc3MsICdwcmV2aWV3RmlsZUljb24nOiBpY259KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9yYWlzZTogZnVuY3Rpb24gKGV2ZW50LCBwYXJhbXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZSA9ICQuRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmFtcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKGUsIHBhcmFtcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpIHx8IGUucmVzdWx0ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBpZ25vcmUgdGhlc2UgZXZlbnRzXG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGViYXRjaHVwbG9hZHN1Y2Nlc3MnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGV1cGxvYWRlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWNsZWFyJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlY2xlYXJlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZXJlc2V0JzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVmb2xkZXJlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZXVwbG9hZGVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlYmF0Y2h1cGxvYWRlcnJvcic6XG4gICAgICAgICAgICAgICAgY2FzZSAnZmlsZWRlbGV0ZWVycm9yJzpcbiAgICAgICAgICAgICAgICBjYXNlICdmaWxlY3VzdG9tZXJyb3InOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbGVzdWNjZXNzcmVtb3ZlJzpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgLy8gcmVjZWl2ZSBkYXRhIHJlc3BvbnNlIHZpYSBgZmlsZWN1c3RvbWVycm9yYCBldmVudGBcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuYWpheEFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBlLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuRnVsbFNjcmVlbjogZnVuY3Rpb24gKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJGJ0bkZ1bGwsICRidG5Cb3JkO1xuICAgICAgICAgICAgaWYgKCEkbW9kYWwgfHwgISRtb2RhbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkYnRuRnVsbCA9ICRtb2RhbCAmJiAkbW9kYWwuZmluZCgnLmJ0bi1mdWxsc2NyZWVuJyk7XG4gICAgICAgICAgICAkYnRuQm9yZCA9ICRtb2RhbCAmJiAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyk7XG4gICAgICAgICAgICBpZiAoISRidG5GdWxsLmxlbmd0aCB8fCAhJGJ0bkJvcmQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGJ0bkZ1bGwucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgJGJ0bkJvcmQucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgaWYgKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICRidG5GdWxsLmFkZENsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAndHJ1ZScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkYnRuQm9yZC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkbW9kYWwuaGFzQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJykpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRmb3JtID0gc2VsZi4kZm9ybSwgJGNvbnQgPSBzZWxmLiRjb250YWluZXIsIGZ1bGxTY3JlZW5FdmVudHM7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRlbCwgJ2NoYW5nZScsICQucHJveHkoc2VsZi5fY2hhbmdlLCBzZWxmKSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93QnJvd3NlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcihzZWxmLiRidG5GaWxlLCAnY2xpY2snLCAkLnByb3h5KHNlbGYuX2Jyb3dzZSwgc2VsZikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkY29udC5maW5kKCcuZmlsZWlucHV0LXJlbW92ZTpub3QoW2Rpc2FibGVkXSknKSwgJ2NsaWNrJywgJC5wcm94eShzZWxmLmNsZWFyLCBzZWxmKSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRjb250LmZpbmQoJy5maWxlaW5wdXQtY2FuY2VsJyksICdjbGljaycsICQucHJveHkoc2VsZi5jYW5jZWwsIHNlbGYpKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXREcmFnRHJvcCgpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZm9ybSwgJ3Jlc2V0JywgJC5wcm94eShzZWxmLnJlc2V0LCBzZWxmKSk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZm9ybSwgJ3N1Ym1pdCcsICQucHJveHkoc2VsZi5fc3VibWl0Rm9ybSwgc2VsZikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faGFuZGxlcihzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGVpbnB1dC11cGxvYWQnKSwgJ2NsaWNrJywgJC5wcm94eShzZWxmLl91cGxvYWRDbGljaywgc2VsZikpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkKHdpbmRvdyksICdyZXNpemUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbGlzdGVuRnVsbFNjcmVlbihzY3JlZW4ud2lkdGggPT09IHdpbmRvdy5pbm5lcldpZHRoICYmIHNjcmVlbi5oZWlnaHQgPT09IHdpbmRvdy5pbm5lckhlaWdodCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZ1bGxTY3JlZW5FdmVudHMgPSAnd2Via2l0ZnVsbHNjcmVlbmNoYW5nZSBtb3pmdWxsc2NyZWVuY2hhbmdlIGZ1bGxzY3JlZW5jaGFuZ2UgTVNGdWxsc2NyZWVuQ2hhbmdlJztcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJChkb2N1bWVudCksIGZ1bGxTY3JlZW5FdmVudHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9saXN0ZW5GdWxsU2NyZWVuKCRoLmNoZWNrRnVsbFNjcmVlbigpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faW5pdENsaWNrYWJsZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdENsaWNrYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkem9uZTtcbiAgICAgICAgICAgIGlmICghc2VsZi5pc0NsaWNrYWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR6b25lID0gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLiRkcm9wWm9uZSA6IHNlbGYuJHByZXZpZXcuZmluZCgnLmZpbGUtZGVmYXVsdC1wcmV2aWV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3MoJHpvbmUsICdjbGlja2FibGUnKTtcbiAgICAgICAgICAgICR6b25lLmF0dHIoJ3RhYmluZGV4JywgLTEpO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkem9uZSwgJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRhciA9ICQoZS50YXJnZXQpO1xuICAgICAgICAgICAgICAgIGlmICghJHRhci5wYXJlbnRzKCcuZmlsZS1wcmV2aWV3LXRodW1ibmFpbHMnKS5sZW5ndGggfHwgJHRhci5wYXJlbnRzKCcuZmlsZS1kZWZhdWx0LXByZXZpZXcnKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKCdjbGljaycpO1xuICAgICAgICAgICAgICAgICAgICAkem9uZS5ibHVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0RHJhZ0Ryb3A6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHpvbmUgPSBzZWxmLiRkcm9wWm9uZTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZCAmJiBzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkem9uZSwgJ2RyYWdlbnRlciBkcmFnb3ZlcicsICQucHJveHkoc2VsZi5fem9uZURyYWdFbnRlciwgc2VsZikpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHpvbmUsICdkcmFnbGVhdmUnLCAkLnByb3h5KHNlbGYuX3pvbmVEcmFnTGVhdmUsIHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCR6b25lLCAnZHJvcCcsICQucHJveHkoc2VsZi5fem9uZURyb3AsIHNlbGYpKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCQoZG9jdW1lbnQpLCAnZHJhZ2VudGVyIGRyYWdvdmVyIGRyb3AnLCBzZWxmLl96b25lRHJhZ0Ryb3BJbml0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcmFnRHJvcEluaXQ6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9LFxuICAgICAgICBfem9uZURyYWdFbnRlcjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaGFzRmlsZXMgPSAkLmluQXJyYXkoJ0ZpbGVzJywgZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2Zlci50eXBlcykgPiAtMTtcbiAgICAgICAgICAgIHNlbGYuX3pvbmVEcmFnRHJvcEluaXQoZSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Rpc2FibGVkIHx8ICFoYXNGaWxlcykge1xuICAgICAgICAgICAgICAgIGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICdub25lJztcbiAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGRyb3Bab25lLCAnZmlsZS1oaWdobGlnaHRlZCcpO1xuICAgICAgICB9LFxuICAgICAgICBfem9uZURyYWdMZWF2ZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuX3pvbmVEcmFnRHJvcEluaXQoZSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5pc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kZHJvcFpvbmUucmVtb3ZlQ2xhc3MoJ2ZpbGUtaGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvbmVEcm9wOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgLyoqIEBuYW1lc3BhY2UgZS5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2ZlciAqL1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNEaXNhYmxlZCB8fCAkaC5pc0VtcHR5KGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIuZmlsZXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fY2hhbmdlKGUsICdkcmFnZHJvcCcpO1xuICAgICAgICAgICAgc2VsZi4kZHJvcFpvbmUucmVtb3ZlQ2xhc3MoJ2ZpbGUtaGlnaGxpZ2h0ZWQnKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwbG9hZENsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkYnRuID0gc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtdXBsb2FkJyksICRmb3JtLFxuICAgICAgICAgICAgICAgIGlzRW5hYmxlZCA9ICEkYnRuLmhhc0NsYXNzKCdkaXNhYmxlZCcpICYmICRoLmlzRW1wdHkoJGJ0bi5hdHRyKCdkaXNhYmxlZCcpKTtcbiAgICAgICAgICAgIGlmIChlICYmIGUuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCAmJiAkYnRuLmF0dHIoJ3R5cGUnKSAhPT0gJ3N1Ym1pdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgJGZvcm0gPSAkYnRuLmNsb3Nlc3QoJ2Zvcm0nKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gZG93bmdyYWRlIHRvIG5vcm1hbCBmb3JtIHN1Ym1pdCBpZiBwb3NzaWJsZVxuICAgICAgICAgICAgICAgICAgICBpZiAoJGZvcm0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZm9ybS50cmlnZ2VyKCdzdWJtaXQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc3VibWl0Rm9ybTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2lzRmlsZVNlbGVjdGlvblZhbGlkKCkgJiYgIXNlbGYuX2Fib3J0KHt9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyUHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkcCA9IHNlbGYuJHByZXZpZXcsXG4gICAgICAgICAgICAgICAgJHRodW1icyA9IHNlbGYuc2hvd1VwbG9hZGVkVGh1bWJzID8gc2VsZi5nZXRGcmFtZXMoJzpub3QoLmZpbGUtcHJldmlldy1zdWNjZXNzKScpIDogc2VsZi5nZXRGcmFtZXMoKTtcbiAgICAgICAgICAgICR0aHVtYnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwLmZpbmQoJyN6b29tLScgKyAkdGh1bWIuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuZ2V0RnJhbWVzKCkubGVuZ3RoIHx8ICFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3ZhbGlkYXRlRGVmYXVsdFByZXZpZXcoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRTb3J0YWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZWwgPSBzZWxmLiRwcmV2aWV3LCBzZXR0aW5ncywgc2VsZWN0b3IgPSAnLicgKyAkaC5TT1JUX0NTUztcbiAgICAgICAgICAgIGlmICghd2luZG93Lkt2U29ydGFibGUgfHwgJGVsLmZpbmQoc2VsZWN0b3IpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW51c2VkR2xvYmFsU3ltYm9sc1xuICAgICAgICAgICAgc2V0dGluZ3MgPSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlOiAnLmRyYWctaGFuZGxlLWluaXQnLFxuICAgICAgICAgICAgICAgIGRhdGFJZEF0dHI6ICdkYXRhLXByZXZpZXctaWQnLFxuICAgICAgICAgICAgICAgIHNjcm9sbDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZHJhZ2dhYmxlOiBzZWxlY3RvcixcbiAgICAgICAgICAgICAgICBvblNvcnQ6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvbGRJbmRleCA9IGUub2xkSW5kZXgsIG5ld0luZGV4ID0gZS5uZXdJbmRleCwga2V5LCAkZnJhbWU7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXcgPSAkaC5tb3ZlQXJyYXkoc2VsZi5pbml0aWFsUHJldmlldywgb2xkSW5kZXgsIG5ld0luZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyA9ICRoLm1vdmVBcnJheShzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnLCBvbGRJbmRleCwgbmV3SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWdbaV0gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXkgPSBzZWxmLmluaXRpYWxQcmV2aWV3Q29uZmlnW2ldLmtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZnJhbWUgPSAkKFwiLmt2LWZpbGUtcmVtb3ZlW2RhdGEta2V5PSdcIiArIGtleSArIFwiJ11cIikuY2xvc2VzdCgkaC5GUkFNRVMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcsICdpbml0XycgKyBpKS5hdHRyKCdkYXRhLWZpbGVpbmRleCcsICdpbml0XycgKyBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXNvcnRlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpZXdJZDogJChlLml0ZW0pLmF0dHIoJ2lkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAnb2xkSW5kZXgnOiBvbGRJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgICduZXdJbmRleCc6IG5ld0luZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhY2s6IHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICgkZWwuZGF0YSgna3Zzb3J0YWJsZScpKSB7XG4gICAgICAgICAgICAgICAgJGVsLmt2c29ydGFibGUoJ2Rlc3Ryb3knKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHNldHRpbmdzLCBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncy5kcmFnU2V0dGluZ3MpO1xuICAgICAgICAgICAgJGVsLmt2c29ydGFibGUoc2V0dGluZ3MpO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXc6IGZ1bmN0aW9uIChpc0luaXQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2FwID0gc2VsZi5pbml0aWFsQ2FwdGlvbiB8fCAnJywgb3V0O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzSW5pdCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdENhcHRpb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICBjYXAgPSBpc0luaXQgJiYgc2VsZi5pbml0aWFsQ2FwdGlvbiA/IHNlbGYuaW5pdGlhbENhcHRpb24gOiBvdXQuY2FwdGlvbjtcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuaHRtbChvdXQuY29udGVudCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShvdXQuY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRab29tQnV0dG9uOiBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsYWJlbCA9IHNlbGYucHJldmlld1pvb21CdXR0b25JY29uc1t0eXBlXSwgY3NzID0gc2VsZi5wcmV2aWV3Wm9vbUJ1dHRvbkNsYXNzZXNbdHlwZV0sXG4gICAgICAgICAgICAgICAgdGl0bGUgPSAnIHRpdGxlPVwiJyArIChzZWxmLnByZXZpZXdab29tQnV0dG9uVGl0bGVzW3R5cGVdIHx8ICcnKSArICdcIiAnLFxuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHRpdGxlICsgKHR5cGUgPT09ICdjbG9zZScgPyAnIGRhdGEtZGlzbWlzcz1cIm1vZGFsXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCInIDogJycpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdmdWxsc2NyZWVuJyB8fCB0eXBlID09PSAnYm9yZGVybGVzcycgfHwgdHlwZSA9PT0gJ3RvZ2dsZWhlYWRlcicpIHtcbiAgICAgICAgICAgICAgICBwYXJhbXMgKz0gJyBkYXRhLXRvZ2dsZT1cImJ1dHRvblwiIGFyaWEtcHJlc3NlZD1cImZhbHNlXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIicgKyBjc3MgKyAnIGJ0bi0nICsgdHlwZSArICdcIicgKyBwYXJhbXMgKyAnPicgKyBsYWJlbCArICc8L2J1dHRvbj4nO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0TW9kYWxDb250ZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21vZGFsJykuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAncnRsJzogc2VsZi5ydGwgPyAnIGt2LXJ0bCcgOiAnJyxcbiAgICAgICAgICAgICAgICAnem9vbUZyYW1lQ2xhc3MnOiBzZWxmLmZyYW1lQ2xhc3MsXG4gICAgICAgICAgICAgICAgJ2hlYWRpbmcnOiBzZWxmLm1zZ1pvb21Nb2RhbEhlYWRpbmcsXG4gICAgICAgICAgICAgICAgJ3ByZXYnOiBzZWxmLl9nZXRab29tQnV0dG9uKCdwcmV2JyksXG4gICAgICAgICAgICAgICAgJ25leHQnOiBzZWxmLl9nZXRab29tQnV0dG9uKCduZXh0JyksXG4gICAgICAgICAgICAgICAgJ3RvZ2dsZWhlYWRlcic6IHNlbGYuX2dldFpvb21CdXR0b24oJ3RvZ2dsZWhlYWRlcicpLFxuICAgICAgICAgICAgICAgICdmdWxsc2NyZWVuJzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbignZnVsbHNjcmVlbicpLFxuICAgICAgICAgICAgICAgICdib3JkZXJsZXNzJzogc2VsZi5fZ2V0Wm9vbUJ1dHRvbignYm9yZGVybGVzcycpLFxuICAgICAgICAgICAgICAgICdjbG9zZSc6IHNlbGYuX2dldFpvb21CdXR0b24oJ2Nsb3NlJylcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfbGlzdGVuTW9kYWxFdmVudDogZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRtb2RhbCA9IHNlbGYuJG1vZGFsLCBnZXRQYXJhbXMgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZUV2ZW50OiBlLFxuICAgICAgICAgICAgICAgICAgICBwcmV2aWV3SWQ6ICRtb2RhbC5kYXRhKCdwcmV2aWV3SWQnKSxcbiAgICAgICAgICAgICAgICAgICAgbW9kYWw6ICRtb2RhbFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgJG1vZGFsLm9uKGV2ZW50ICsgJy5icy5tb2RhbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyICRidG5GdWxsID0gJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpLCAkYnRuQm9yZCA9ICRtb2RhbC5maW5kKCcuYnRuLWJvcmRlcmxlc3MnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXpvb20nICsgZXZlbnQsIGdldFBhcmFtcyhlKSk7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50ID09PSAnc2hvd24nKSB7XG4gICAgICAgICAgICAgICAgICAgICRidG5Cb3JkLnJlbW92ZUNsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgJGJ0bkZ1bGwucmVtb3ZlQ2xhc3MoJ2FjdGl2ZScpLmF0dHIoJ2FyaWEtcHJlc3NlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoJG1vZGFsLmhhc0NsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkaC5jaGVja0Z1bGxTY3JlZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5GdWxsLmFkZENsYXNzKCdhY3RpdmUnKS5hdHRyKCdhcmlhLXByZXNzZWQnLCAndHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5hZGRDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb206IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGRpYWxvZywgbW9kYWxNYWluID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ21vZGFsTWFpbicpLCBtb2RhbElkID0gJyMnICsgJGguTU9EQUxfSUQ7XG4gICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRtb2RhbCA9ICQobW9kYWxJZCk7XG4gICAgICAgICAgICBpZiAoIXNlbGYuJG1vZGFsIHx8ICFzZWxmLiRtb2RhbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkZGlhbG9nID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaHRtbChtb2RhbE1haW4pLmluc2VydEFmdGVyKHNlbGYuJGNvbnRhaW5lcik7XG4gICAgICAgICAgICAgICAgc2VsZi4kbW9kYWwgPSAkKG1vZGFsSWQpLmluc2VydEJlZm9yZSgkZGlhbG9nKTtcbiAgICAgICAgICAgICAgICAkZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGguaW5pdE1vZGFsKHNlbGYuJG1vZGFsKTtcbiAgICAgICAgICAgIHNlbGYuJG1vZGFsLmh0bWwoc2VsZi5fZ2V0TW9kYWxDb250ZW50KCkpO1xuICAgICAgICAgICAgJC5lYWNoKCRoLk1PREFMX0VWRU5UUywgZnVuY3Rpb24gKGtleSwgZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9saXN0ZW5Nb2RhbEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb21CdXR0b25zOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHByZXZpZXdJZCA9IHNlbGYuJG1vZGFsLmRhdGEoJ3ByZXZpZXdJZCcpIHx8ICcnLCAkZmlyc3QsICRsYXN0LFxuICAgICAgICAgICAgICAgIHRodW1icyA9IHNlbGYuZ2V0RnJhbWVzKCkudG9BcnJheSgpLCBsZW4gPSB0aHVtYnMubGVuZ3RoLCAkcHJldiA9IHNlbGYuJG1vZGFsLmZpbmQoJy5idG4tcHJldicpLFxuICAgICAgICAgICAgICAgICRuZXh0ID0gc2VsZi4kbW9kYWwuZmluZCgnLmJ0bi1uZXh0Jyk7XG4gICAgICAgICAgICBpZiAodGh1bWJzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICAkcHJldi5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJG5leHQuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJHByZXYuc2hvdygpO1xuICAgICAgICAgICAgICAgICRuZXh0LnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbGVuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGZpcnN0ID0gJCh0aHVtYnNbMF0pO1xuICAgICAgICAgICAgJGxhc3QgPSAkKHRodW1ic1tsZW4gLSAxXSk7XG4gICAgICAgICAgICAkcHJldi5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgJG5leHQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIGlmICgkZmlyc3QubGVuZ3RoICYmICRmaXJzdC5hdHRyKCdpZCcpID09PSBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICAkcHJldi5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRsYXN0Lmxlbmd0aCAmJiAkbGFzdC5hdHRyKCdpZCcpID09PSBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgICAgICAkbmV4dC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfbWF4aW1pemVab29tRGlhbG9nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRtb2RhbCA9IHNlbGYuJG1vZGFsLCAkaGVhZCA9ICRtb2RhbC5maW5kKCcubW9kYWwtaGVhZGVyOnZpc2libGUnKSxcbiAgICAgICAgICAgICAgICAkZm9vdCA9ICRtb2RhbC5maW5kKCcubW9kYWwtZm9vdGVyOnZpc2libGUnKSwgJGJvZHkgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWJvZHknKSxcbiAgICAgICAgICAgICAgICBoID0gJCh3aW5kb3cpLmhlaWdodCgpLCBkaWZmID0gMDtcbiAgICAgICAgICAgICRtb2RhbC5hZGRDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKTtcbiAgICAgICAgICAgIGlmICgkaGVhZCAmJiAkaGVhZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBoIC09ICRoZWFkLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRmb290ICYmICRmb290Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGggLT0gJGZvb3Qub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJGJvZHkgJiYgJGJvZHkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGlmZiA9ICRib2R5Lm91dGVySGVpZ2h0KHRydWUpIC0gJGJvZHkuaGVpZ2h0KCk7XG4gICAgICAgICAgICAgICAgaCAtPSBkaWZmO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmZpbmQoJy5rdi16b29tLWJvZHknKS5oZWlnaHQoaCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNpemVab29tRGlhbG9nOiBmdW5jdGlvbiAoZnVsbFNjcmVlbikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJGJ0bkZ1bGwgPSAkbW9kYWwuZmluZCgnLmJ0bi1mdWxsc2NyZWVuJyksXG4gICAgICAgICAgICAgICAgJGJ0bkJvcmQgPSAkbW9kYWwuZmluZCgnLmJ0bi1ib3JkZXJsZXNzJyk7XG4gICAgICAgICAgICBpZiAoJG1vZGFsLmhhc0NsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgJGgudG9nZ2xlRnVsbFNjcmVlbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgaWYgKCFmdWxsU2NyZWVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghJGJ0bkZ1bGwuaGFzQ2xhc3MoJ2FjdGl2ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkbW9kYWwucmVtb3ZlQ2xhc3MoJ2ZpbGUtem9vbS1mdWxsc2NyZWVuJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLiRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5JykuY3NzKCdoZWlnaHQnLCBzZWxmLnpvb21Nb2RhbEhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYnRuRnVsbC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRidG5GdWxsLmhhc0NsYXNzKCdhY3RpdmUnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJG1vZGFsLnJlbW92ZUNsYXNzKCdmaWxlLXpvb20tZnVsbHNjcmVlbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVzaXplWm9vbURpYWxvZyh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkYnRuQm9yZC5oYXNDbGFzcygnYWN0aXZlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuQm9yZC5yZW1vdmVDbGFzcygnYWN0aXZlJykuYXR0cignYXJpYS1wcmVzc2VkJywgJ2ZhbHNlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghZnVsbFNjcmVlbikge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9tYXhpbWl6ZVpvb21EaWFsb2coKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkaC50b2dnbGVGdWxsU2NyZWVuKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmZvY3VzKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRab29tQ29udGVudDogZnVuY3Rpb24gKCRmcmFtZSwgYW5pbWF0ZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkY29udGVudCwgdG1wbHQsIGJvZHksIHRpdGxlLCAkYm9keSwgJGRhdGFFbCwgY29uZmlnLCBwaWQgPSAkZnJhbWUuYXR0cignaWQnKSxcbiAgICAgICAgICAgICAgICAkbW9kYWwgPSBzZWxmLiRtb2RhbCwgJHByZXYgPSAkbW9kYWwuZmluZCgnLmJ0bi1wcmV2JyksICRuZXh0ID0gJG1vZGFsLmZpbmQoJy5idG4tbmV4dCcpLCAkdG1wLFxuICAgICAgICAgICAgICAgICRidG5GdWxsID0gJG1vZGFsLmZpbmQoJy5idG4tZnVsbHNjcmVlbicpLCAkYnRuQm9yZCA9ICRtb2RhbC5maW5kKCcuYnRuLWJvcmRlcmxlc3MnKSwgY2FwLCBzaXplLFxuICAgICAgICAgICAgICAgICRidG5Ub2doID0gJG1vZGFsLmZpbmQoJy5idG4tdG9nZ2xlaGVhZGVyJyksICR6b29tUHJldmlldyA9IHNlbGYuJHByZXZpZXcuZmluZCgnI3pvb20tJyArIHBpZCk7XG4gICAgICAgICAgICB0bXBsdCA9ICR6b29tUHJldmlldy5hdHRyKCdkYXRhLXRlbXBsYXRlJykgfHwgJ2dlbmVyaWMnO1xuICAgICAgICAgICAgJGNvbnRlbnQgPSAkem9vbVByZXZpZXcuZmluZCgnLmt2LWZpbGUtY29udGVudCcpO1xuICAgICAgICAgICAgYm9keSA9ICRjb250ZW50Lmxlbmd0aCA/ICRjb250ZW50Lmh0bWwoKSA6ICcnO1xuICAgICAgICAgICAgY2FwID0gJGZyYW1lLmRhdGEoJ2NhcHRpb24nKSB8fCAnJztcbiAgICAgICAgICAgIHNpemUgPSAkZnJhbWUuZGF0YSgnc2l6ZScpIHx8ICcnO1xuICAgICAgICAgICAgdGl0bGUgPSBjYXAgKyAnICcgKyBzaXplO1xuICAgICAgICAgICAgJG1vZGFsLmZpbmQoJy5rdi16b29tLXRpdGxlJykuaHRtbCh0aXRsZSk7XG4gICAgICAgICAgICAkYm9keSA9ICRtb2RhbC5maW5kKCcua3Ytem9vbS1ib2R5Jyk7XG4gICAgICAgICAgICAkbW9kYWwucmVtb3ZlQ2xhc3MoJ2t2LXNpbmdsZS1jb250ZW50Jyk7XG4gICAgICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgICAgICR0bXAgPSAkYm9keS5hZGRDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJykuY2xvbmUoKS5pbnNlcnRBZnRlcigkYm9keSk7XG4gICAgICAgICAgICAgICAgJGJvZHkuaHRtbChib2R5KS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJHRtcC5mYWRlT3V0KCdmYXN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAkYm9keS5mYWRlSW4oJ2Zhc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYm9keS5yZW1vdmVDbGFzcygnZmlsZS10aHVtYi1sb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAkdG1wLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkYm9keS5odG1sKGJvZHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlnID0gc2VsZi5wcmV2aWV3Wm9vbVNldHRpbmdzW3RtcGx0XTtcbiAgICAgICAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgICAgICAgICAkZGF0YUVsID0gJGJvZHkuZmluZCgnLmt2LXByZXZpZXctZGF0YScpO1xuICAgICAgICAgICAgICAgICRoLmFkZENzcygkZGF0YUVsLCAnZmlsZS16b29tLWRldGFpbCcpO1xuICAgICAgICAgICAgICAgICQuZWFjaChjb25maWcsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICRkYXRhRWwuY3NzKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKCRkYXRhRWwuYXR0cignd2lkdGgnKSAmJiBrZXkgPT09ICd3aWR0aCcpIHx8ICgkZGF0YUVsLmF0dHIoJ2hlaWdodCcpICYmIGtleSA9PT0gJ2hlaWdodCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZGF0YUVsLnJlbW92ZUF0dHIoa2V5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJG1vZGFsLmRhdGEoJ3ByZXZpZXdJZCcsIHBpZCk7XG4gICAgICAgICAgICB2YXIgJGltZyA9ICRib2R5LmZpbmQoJ2ltZycpO1xuICAgICAgICAgICAgaWYgKCRpbWcubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGguYWRqdXN0T3JpZW50ZWRJbWFnZSgkaW1nLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJHByZXYsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCdwcmV2JywgcGlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkbmV4dCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3pvb21TbGlkZVNob3coJ25leHQnLCBwaWQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRidG5GdWxsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmVzaXplWm9vbURpYWxvZyh0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkYnRuQm9yZCwgJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2l6ZVpvb21EaWFsb2coZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRidG5Ub2doLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRoZWFkZXIgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWhlYWRlcicpLCAkZmxvYXRCYXIgPSAkbW9kYWwuZmluZCgnLm1vZGFsLWJvZHkgLmZsb2F0aW5nLWJ1dHRvbnMnKSxcbiAgICAgICAgICAgICAgICAgICAgaHQsICRhY3Rpb25zID0gJGhlYWRlci5maW5kKCcua3Ytem9vbS1hY3Rpb25zJyksIHJlc2l6ZSA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkYm9keSA9IHNlbGYuJG1vZGFsLmZpbmQoJy5rdi16b29tLWJvZHknKSwgaCA9IHNlbGYuem9vbU1vZGFsSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRtb2RhbC5oYXNDbGFzcygnZmlsZS16b29tLWZ1bGxzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGggPSAkYm9keS5vdXRlckhlaWdodCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoID0gaCAtICRoZWFkZXIub3V0ZXJIZWlnaHQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGJvZHkuY3NzKCdoZWlnaHQnLCBoZWlnaHQgPyBoICsgaGVpZ2h0IDogaCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKCRoZWFkZXIuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgaHQgPSAkaGVhZGVyLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAkaGVhZGVyLnNsaWRlVXAoJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkYWN0aW9ucy5maW5kKCcuYnRuJykuYXBwZW5kVG8oJGZsb2F0QmFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZShodCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICRmbG9hdEJhci5maW5kKCcuYnRuJykuYXBwZW5kVG8oJGFjdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAkaGVhZGVyLnNsaWRlRG93bignc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJG1vZGFsLmZvY3VzKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJG1vZGFsLCAna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGUud2hpY2ggfHwgZS5rZXlDb2RlO1xuICAgICAgICAgICAgICAgIGlmIChrZXkgPT09IDM3ICYmICEkcHJldi5hdHRyKCdkaXNhYmxlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3pvb21TbGlkZVNob3coJ3ByZXYnLCBwaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoa2V5ID09PSAzOSAmJiAhJG5leHQuYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl96b29tU2xpZGVTaG93KCduZXh0JywgcGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3pvb21QcmV2aWV3OiBmdW5jdGlvbiAoJGJ0bikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUsICRtb2RhbCA9IHNlbGYuJG1vZGFsO1xuICAgICAgICAgICAgaWYgKCEkYnRuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93ICdDYW5ub3Qgem9vbSB0byBkZXRhaWxlZCBwcmV2aWV3ISc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaC5pbml0TW9kYWwoJG1vZGFsKTtcbiAgICAgICAgICAgICRtb2RhbC5odG1sKHNlbGYuX2dldE1vZGFsQ29udGVudCgpKTtcbiAgICAgICAgICAgICRmcmFtZSA9ICRidG4uY2xvc2VzdCgkaC5GUkFNRVMpO1xuICAgICAgICAgICAgc2VsZi5fc2V0Wm9vbUNvbnRlbnQoJGZyYW1lKTtcbiAgICAgICAgICAgICRtb2RhbC5tb2RhbCgnc2hvdycpO1xuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b25zKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF96b29tU2xpZGVTaG93OiBmdW5jdGlvbiAoZGlyLCBwcmV2aWV3SWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGJ0biA9IHNlbGYuJG1vZGFsLmZpbmQoJy5rdi16b29tLWFjdGlvbnMgLmJ0bi0nICsgZGlyKSwgJHRhcmdGcmFtZSwgaSxcbiAgICAgICAgICAgICAgICB0aHVtYnMgPSBzZWxmLmdldEZyYW1lcygpLnRvQXJyYXkoKSwgbGVuID0gdGh1bWJzLmxlbmd0aCwgb3V0O1xuICAgICAgICAgICAgaWYgKCRidG4uYXR0cignZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICgkKHRodW1ic1tpXSkuYXR0cignaWQnKSA9PT0gcHJldmlld0lkKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9IGRpciA9PT0gJ3ByZXYnID8gaSAtIDEgOiBpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG91dCA8IDAgfHwgb3V0ID49IGxlbiB8fCAhdGh1bWJzW291dF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGFyZ0ZyYW1lID0gJCh0aHVtYnNbb3V0XSk7XG4gICAgICAgICAgICBpZiAoJHRhcmdGcmFtZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRab29tQ29udGVudCgkdGFyZ0ZyYW1lLCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9ucygpO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGV6b29tJyArIGRpciwgeydwcmV2aWV3SWQnOiBwcmV2aWV3SWQsIG1vZGFsOiBzZWxmLiRtb2RhbH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFpvb21CdXR0b246IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuZmluZCgnLmt2LWZpbGUtem9vbScpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkZWwgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3pvb21QcmV2aWV3KCRlbCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyT2JqZWN0czogZnVuY3Rpb24gKCRlbCkge1xuICAgICAgICAgICAgJGVsLmZpbmQoJ3ZpZGVvIGF1ZGlvJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXVzZSgpO1xuICAgICAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICRlbC5maW5kKCdpbWcgb2JqZWN0IGRpdicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX2NsZWFyRmlsZUlucHV0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRzcmNGcm0sICR0bXBGcm0sICR0bXBFbDtcbiAgICAgICAgICAgIHNlbGYuZmlsZUlucHV0Q2xlYXJlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eSgkZWwudmFsKCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRml4IGZvciBJRSB2ZXIgPCAxMSwgdGhhdCBkb2VzIG5vdCBjbGVhciBmaWxlIGlucHV0cy4gUmVxdWlyZXMgYSBzZXF1ZW5jZSBvZiBzdGVwcyB0byBwcmV2ZW50IElFXG4gICAgICAgICAgICAvLyBjcmFzaGluZyBidXQgc3RpbGwgYWxsb3cgY2xlYXJpbmcgb2YgdGhlIGZpbGUgaW5wdXQuXG4gICAgICAgICAgICBpZiAoc2VsZi5pc0lFOSB8fCBzZWxmLmlzSUUxMCkge1xuICAgICAgICAgICAgICAgICRzcmNGcm0gPSAkZWwuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgICAgICR0bXBGcm0gPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2Zvcm0nKSk7XG4gICAgICAgICAgICAgICAgJHRtcEVsID0gJChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgICAgICAgICAgICAgJGVsLmJlZm9yZSgkdG1wRWwpO1xuICAgICAgICAgICAgICAgIGlmICgkc3JjRnJtLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAkc3JjRnJtLmFmdGVyKCR0bXBGcm0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICR0bXBFbC5hZnRlcigkdG1wRnJtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJHRtcEZybS5hcHBlbmQoJGVsKS50cmlnZ2VyKCdyZXNldCcpO1xuICAgICAgICAgICAgICAgICR0bXBFbC5iZWZvcmUoJGVsKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAkdG1wRnJtLnJlbW92ZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHsgLy8gbm9ybWFsIGlucHV0IGNsZWFyIGJlaGF2aW9yIGZvciBvdGhlciBzYW5lIGJyb3dzZXJzXG4gICAgICAgICAgICAgICAgJGVsLnZhbCgnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldFVwbG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZSA9IHtjb250ZW50OiBbXSwgY29uZmlnOiBbXSwgdGFnczogW10sIGFwcGVuZDogdHJ1ZX07XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygwKTtcbiAgICAgICAgICAgICRoLmFkZENzcyhzZWxmLiRwcm9ncmVzcywgJ2hpZGUnKTtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKGZhbHNlKTtcbiAgICAgICAgICAgIHNlbGYuYWpheEFib3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuYWpheFJlcXVlc3RzID0gW107XG4gICAgICAgICAgICBzZWxmLl9yZXNldENhbnZhcygpO1xuICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0ge307XG4gICAgICAgICAgICBpZiAoc2VsZi5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9IFtdO1xuICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSBbXTtcbiAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gW107XG4gICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgY29udGVudDogW10sXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZzogW10sXG4gICAgICAgICAgICAgICAgICAgIHRhZ3M6IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3Jlc2V0Q2FudmFzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoc2VsZi5jYW52YXMgJiYgc2VsZi5pbWFnZUNhbnZhc0NvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmltYWdlQ2FudmFzQ29udGV4dC5jbGVhclJlY3QoMCwgMCwgc2VsZi5jYW52YXMud2lkdGgsIHNlbGYuY2FudmFzLmhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9oYXNJbml0aWFsUHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuICFzZWxmLm92ZXJ3cml0ZUluaXRpYWwgJiYgc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3Jlc2V0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBvdXQsIGNhcDtcbiAgICAgICAgICAgIGlmIChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKG91dC5jb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICAgICAgY2FwID0gc2VsZi5pbml0aWFsQ2FwdGlvbiA/IHNlbGYuaW5pdGlhbENhcHRpb24gOiBvdXQuY2FwdGlvbjtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRDYXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRab29tKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9jbGVhckRlZmF1bHRQcmV2aWV3OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLiRwcmV2aWV3LmZpbmQoJy5maWxlLWRlZmF1bHQtcHJldmlldycpLnJlbW92ZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGVEZWZhdWx0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3IHx8ICRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKCc8ZGl2IGNsYXNzPVwiZmlsZS1kZWZhdWx0LXByZXZpZXdcIj4nICsgc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQgKyAnPC9kaXY+Jyk7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICBzZWxmLl9pbml0Q2xpY2thYmxlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldFByZXZpZXdUaHVtYnM6IGZ1bmN0aW9uIChpc0FqYXgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgb3V0O1xuICAgICAgICAgICAgaWYgKGlzQWpheCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLl9oYXNJbml0aWFsUHJldmlldygpKSB7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5wcmV2aWV3Q2FjaGUub3V0KCk7XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKG91dC5jb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRJbml0VGh1bWJBdHRyKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihvdXQuY2FwdGlvbik7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyUHJldmlldygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfZ2V0TGF5b3V0VGVtcGxhdGU6IGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHRlbXBsYXRlID0gc2VsZi5sYXlvdXRUZW1wbGF0ZXNbdF07XG4gICAgICAgICAgICBpZiAoJGguaXNFbXB0eShzZWxmLmN1c3RvbUxheW91dFRhZ3MpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRoLnJlcGxhY2VUYWdzKHRlbXBsYXRlLCBzZWxmLmN1c3RvbUxheW91dFRhZ3MpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0UHJldmlld1RlbXBsYXRlOiBmdW5jdGlvbiAodCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0ZW1wbGF0ZSA9IHNlbGYucHJldmlld1RlbXBsYXRlc1t0XTtcbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KHNlbGYuY3VzdG9tUHJldmlld1RhZ3MpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRoLnJlcGxhY2VUYWdzKHRlbXBsYXRlLCBzZWxmLmN1c3RvbVByZXZpZXdUYWdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldE91dERhdGE6IGZ1bmN0aW9uIChqcVhIUiwgcmVzcG9uc2VEYXRhLCBmaWxlc0RhdGEpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGpxWEhSID0ganFYSFIgfHwge307XG4gICAgICAgICAgICByZXNwb25zZURhdGEgPSByZXNwb25zZURhdGEgfHwge307XG4gICAgICAgICAgICBmaWxlc0RhdGEgPSBmaWxlc0RhdGEgfHwgc2VsZi5maWxlc3RhY2suc2xpY2UoMCkgfHwge307XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGZvcm06IHNlbGYuZm9ybWRhdGEsXG4gICAgICAgICAgICAgICAgZmlsZXM6IGZpbGVzRGF0YSxcbiAgICAgICAgICAgICAgICBmaWxlbmFtZXM6IHNlbGYuZmlsZW5hbWVzLFxuICAgICAgICAgICAgICAgIGZpbGVzY291bnQ6IHNlbGYuZ2V0RmlsZXNDb3VudCgpLFxuICAgICAgICAgICAgICAgIGV4dHJhOiBzZWxmLl9nZXRFeHRyYURhdGEoKSxcbiAgICAgICAgICAgICAgICByZXNwb25zZTogcmVzcG9uc2VEYXRhLFxuICAgICAgICAgICAgICAgIHJlYWRlcjogc2VsZi5yZWFkZXIsXG4gICAgICAgICAgICAgICAganFYSFI6IGpxWEhSXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0TXNnU2VsZWN0ZWQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHN0ckZpbGVzID0gbiA9PT0gMSA/IHNlbGYuZmlsZVNpbmdsZSA6IHNlbGYuZmlsZVBsdXJhbDtcbiAgICAgICAgICAgIHJldHVybiBuID4gMCA/IHNlbGYubXNnU2VsZWN0ZWQucmVwbGFjZSgne259JywgbikucmVwbGFjZSgne2ZpbGVzfScsIHN0ckZpbGVzKSA6IHNlbGYubXNnTm9GaWxlc1NlbGVjdGVkO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RnJhbWU6IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUgPSAkKCcjJyArIGlkKTtcbiAgICAgICAgICAgIGlmICghJGZyYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2xvZygnSW52YWxpZCB0aHVtYiBmcmFtZSB3aXRoIGlkOiBcIicgKyBpZCArICdcIi4nKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkZnJhbWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRUaHVtYnM6IGZ1bmN0aW9uIChjc3MpIHtcbiAgICAgICAgICAgIGNzcyA9IGNzcyB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEZyYW1lcygnOm5vdCguZmlsZS1wcmV2aWV3LWluaXRpYWwpJyArIGNzcyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRFeHRyYURhdGE6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGRhdGEgPSBzZWxmLnVwbG9hZEV4dHJhRGF0YTtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi51cGxvYWRFeHRyYURhdGEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBzZWxmLnVwbG9hZEV4dHJhRGF0YShwcmV2aWV3SWQsIGluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFhocjogZnVuY3Rpb24gKHhocm9iaiwgcHJldmlld0lkLCBmaWxlQ291bnQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICh4aHJvYmoudXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgeGhyb2JqLnVwbG9hZC5hZGRFdmVudExpc3RlbmVyKCdwcm9ncmVzcycsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGN0ID0gMCwgdG90YWwgPSBldmVudC50b3RhbCwgcG9zaXRpb24gPSBldmVudC5sb2FkZWQgfHwgZXZlbnQucG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGV2ZW50Lmxlbmd0aENvbXB1dGFibGUgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50Lmxlbmd0aENvbXB1dGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBjdCA9IE1hdGguZmxvb3IocG9zaXRpb24gLyB0b3RhbCAqIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpZXdJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0QXN5bmNVcGxvYWRTdGF0dXMocHJldmlld0lkLCBwY3QsIGZpbGVDb3VudCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcyhwY3QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHhocm9iajtcbiAgICAgICAgfSxcbiAgICAgICAgX2FqYXhTdWJtaXQ6IGZ1bmN0aW9uIChmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yLCBwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHNldHRpbmdzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLl9yYWlzZSgnZmlsZXByZWFqYXgnLCBbcHJldmlld0lkLCBpbmRleF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fdXBsb2FkRXh0cmEocHJldmlld0lkLCBpbmRleCk7XG4gICAgICAgICAgICBzZXR0aW5ncyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB7XG4gICAgICAgICAgICAgICAgeGhyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4aHJvYmogPSAkLmFqYXhTZXR0aW5ncy54aHIoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2luaXRYaHIoeGhyb2JqLCBwcmV2aWV3SWQsIHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHVybDogc2VsZi51cGxvYWRVcmwsXG4gICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgZGF0YTogc2VsZi5mb3JtZGF0YSxcbiAgICAgICAgICAgICAgICBjYWNoZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgcHJvY2Vzc0RhdGE6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBiZWZvcmVTZW5kOiBmbkJlZm9yZSxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiBmblN1Y2Nlc3MsXG4gICAgICAgICAgICAgICAgY29tcGxldGU6IGZuQ29tcGxldGUsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZuRXJyb3JcbiAgICAgICAgICAgIH0sIHNlbGYuYWpheFNldHRpbmdzKTtcbiAgICAgICAgICAgIHNlbGYuYWpheFJlcXVlc3RzLnB1c2goJC5hamF4KHNldHRpbmdzKSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9tZXJnZUFycmF5OiBmdW5jdGlvbiAocHJvcCwgY29udGVudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhcnIxID0gJGguY2xlYW5BcnJheShzZWxmW3Byb3BdKSwgYXJyMiA9ICRoLmNsZWFuQXJyYXkoY29udGVudCk7XG4gICAgICAgICAgICBzZWxmW3Byb3BdID0gYXJyMS5jb25jYXQoYXJyMik7XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0VXBsb2FkU3VjY2VzczogZnVuY3Rpb24gKG91dCwgJHRodW1iLCBhbGxGaWxlcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhcHBlbmQsIGRhdGEsIGluZGV4LCAkZGl2LCAkbmV3Q2FjaGUsIGNvbnRlbnQsIGNvbmZpZywgdGFncywgaTtcbiAgICAgICAgICAgIGlmICghc2VsZi5zaG93UHJldmlldyB8fCB0eXBlb2Ygb3V0ICE9PSAnb2JqZWN0JyB8fCAkLmlzRW1wdHlPYmplY3Qob3V0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvdXQuaW5pdGlhbFByZXZpZXcgIT09IHVuZGVmaW5lZCAmJiBvdXQuaW5pdGlhbFByZXZpZXcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNlbGYuaGFzSW5pdERhdGEgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBvdXQuaW5pdGlhbFByZXZpZXcgfHwgW107XG4gICAgICAgICAgICAgICAgY29uZmlnID0gb3V0LmluaXRpYWxQcmV2aWV3Q29uZmlnIHx8IFtdO1xuICAgICAgICAgICAgICAgIHRhZ3MgPSBvdXQuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MgfHwgW107XG4gICAgICAgICAgICAgICAgYXBwZW5kID0gb3V0LmFwcGVuZCA9PT0gdW5kZWZpbmVkIHx8IG91dC5hcHBlbmQgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMCAmJiAhJGguaXNBcnJheShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gY29udGVudC5zcGxpdChzZWxmLmluaXRpYWxQcmV2aWV3RGVsaW1pdGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fbWVyZ2VBcnJheSgnaW5pdGlhbFByZXZpZXcnLCBjb250ZW50KTtcbiAgICAgICAgICAgICAgICBzZWxmLl9tZXJnZUFycmF5KCdpbml0aWFsUHJldmlld0NvbmZpZycsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fbWVyZ2VBcnJheSgnaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MnLCB0YWdzKTtcbiAgICAgICAgICAgICAgICBpZiAoJHRodW1iICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBzZWxmLnByZXZpZXdDYWNoZS5hZGQoY29udGVudCwgY29uZmlnWzBdLCB0YWdzWzBdLCBhcHBlbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHNlbGYucHJldmlld0NhY2hlLmdldChpbmRleCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGRpdiA9ICQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLmh0bWwoZGF0YSkuaGlkZSgpLmluc2VydEFmdGVyKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgICAgICAkbmV3Q2FjaGUgPSAkZGl2LmZpbmQoJy5rdi16b29tLWNhY2hlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJG5ld0NhY2hlICYmICRuZXdDYWNoZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbmV3Q2FjaGUuaW5zZXJ0QWZ0ZXIoJHRodW1iKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5mYWRlT3V0KCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkbmV3VGh1bWIgPSAkZGl2LmZpbmQoJy5maWxlLXByZXZpZXctZnJhbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoJG5ld1RodW1iICYmICRuZXdUaHVtYi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJG5ld1RodW1iLmluc2VydEJlZm9yZSgkdGh1bWIpLmZhZGVJbignc2xvdycpLmNzcygnZGlzcGxheTppbmxpbmUtYmxvY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZShzZWxmLiRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyAkdGh1bWIuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkZGl2LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLmNvbnRlbnRbaV0gPSBjb250ZW50WzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS5jb25maWdbaV0gPSBjb25maWdbMF0gfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZENhY2hlLnRhZ3NbaV0gPSB0YWdzWzBdIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS5hcHBlbmQgPSBhcHBlbmQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByZXZpZXdDYWNoZS5zZXQoY29udGVudCwgY29uZmlnLCB0YWdzLCBhcHBlbmQpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlldygpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0U3VjY2Vzc1RodW1iczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCRoLkZSQU1FUyArICcuZmlsZS1wcmV2aWV3LXN1Y2Nlc3MnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3LCAkcmVtb3ZlID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXJlbW92ZScpO1xuICAgICAgICAgICAgICAgICRyZW1vdmUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVyKCRyZW1vdmUsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkID0gJHRodW1iLmF0dHIoJ2lkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLl9yYWlzZSgnZmlsZXN1Y2Nlc3NyZW1vdmUnLCBbaWQsICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICRoLmNsZWFuTWVtb3J5KCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvdXQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmZhZGVPdXQoJ3Nsb3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkaC5jbGVhblpvb21DYWNoZSgkcHJldmlldy5maW5kKCcjem9vbS0nICsgaWQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5nZXRGcmFtZXMoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jaGVja0FzeW5jQ29tcGxldGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgcHJldmlld0lkLCBpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGYuZmlsZXN0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArIFwiLVwiICsgaTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQuaW5BcnJheShwcmV2aWV3SWQsIHNlbGYudXBsb2FkTG9nKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoc2VsZi51cGxvYWRBc3luY0NvdW50ID09PSBzZWxmLnVwbG9hZExvZy5sZW5ndGgpO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkRXh0cmE6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGRhdGEgPSBzZWxmLl9nZXRFeHRyYURhdGEocHJldmlld0lkLCBpbmRleCk7XG4gICAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkLmVhY2goZGF0YSwgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmZvcm1kYXRhLmFwcGVuZChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkU2luZ2xlOiBmdW5jdGlvbiAoaSwgZmlsZXMsIGFsbEZpbGVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHRvdGFsID0gc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGgsIGZvcm1kYXRhID0gbmV3IEZvcm1EYXRhKCksIG91dERhdGEsXG4gICAgICAgICAgICAgICAgcHJldmlld0lkID0gc2VsZi5wcmV2aWV3SW5pdElkICsgXCItXCIgKyBpLCAkdGh1bWIsIGNoa0NvbXBsZXRlLCAkYnRuVXBsb2FkLCAkYnRuRGVsZXRlLFxuICAgICAgICAgICAgICAgIGhhc1Bvc3REYXRhID0gc2VsZi5maWxlc3RhY2subGVuZ3RoID4gMCB8fCAhJC5pc0VtcHR5T2JqZWN0KHNlbGYudXBsb2FkRXh0cmFEYXRhKSxcbiAgICAgICAgICAgICAgICAkcHJvZyA9ICQoJyMnICsgcHJldmlld0lkKS5maW5kKCcuZmlsZS10aHVtYi1wcm9ncmVzcycpLFxuICAgICAgICAgICAgICAgIGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IsIHVwZGF0ZVVwbG9hZExvZywgcGFyYW1zID0ge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpfSxcbiAgICAgICAgICAgICAgICB1cGxvYWRGYWlsZWQsIG11bHRpVXBsb2FkTW9kZSA9ICEkaC5pc0VtcHR5KHNlbGYuJGVsZW1lbnQuYXR0cignbXVsdGlwbGUnKSk7XG4gICAgICAgICAgICBzZWxmLmZvcm1kYXRhID0gZm9ybWRhdGE7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICR0aHVtYiA9ICQoJyMnICsgcHJldmlld0lkICsgJzpub3QoLmZpbGUtcHJldmlldy1pbml0aWFsKScpO1xuICAgICAgICAgICAgICAgICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyk7XG4gICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZSA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS1yZW1vdmUnKTtcbiAgICAgICAgICAgICAgICAkcHJvZy5yZW1vdmVDbGFzcygnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRvdGFsID09PSAwIHx8ICFoYXNQb3N0RGF0YSB8fCAoJGJ0blVwbG9hZCAmJiAkYnRuVXBsb2FkLmhhc0NsYXNzKCdkaXNhYmxlZCcpKSB8fCBzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nID0gZnVuY3Rpb24gKGksIHByZXZpZXdJZCkge1xuICAgICAgICAgICAgICAgIGlmIChtdWx0aVVwbG9hZE1vZGUgfHwgIXVwbG9hZEZhaWxlZCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGksIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkTG9nLnB1c2gocHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5fY2hlY2tBc3luY0NvbXBsZXRlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjaGtDb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdSA9IHNlbGYudXBsb2FkQ2FjaGUsICRpbml0VGh1bWJzLCBpLCBqLCBsZW4gPSAwLCBkYXRhID0gc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3O1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiBkYXRhLmNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVuID0gZGF0YS5jb250ZW50Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmlnZ2VyUmVzZXQgPSBtdWx0aVVwbG9hZE1vZGUgfHwgIXVwbG9hZEZhaWxlZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLnNldCh1LmNvbnRlbnQsIHUuY29uZmlnLCB1LnRhZ3MsIHUuYXBwZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdS5jb250ZW50Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGogPSBpICsgbGVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvbnRlbnRbal0gPSB1LmNvbnRlbnRbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vbm9pbnNwZWN0aW9uIEpTVW5yZXNvbHZlZFZhcmlhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNvbmZpZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuY29uZmlnW2pdID0gdS5jb25maWdbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEudGFncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudGFnc1tqXSA9IHUudGFnc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gJGguY2xlYW5BcnJheShkYXRhLmNvbnRlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSAkaC5jbGVhbkFycmF5KGRhdGEuY29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gJGguY2xlYW5BcnJheShkYXRhLnRhZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3ID0gdS5jb250ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcgPSB1LmNvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzID0gdS50YWdzO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5oYXNJbml0RGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRQcmV2aWV3KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VsZi51bmxvY2sodHJpZ2dlclJlc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWdnZXJSZXNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkaW5pdFRodW1icyA9IHNlbGYuJHByZXZpZXcuZmluZCgnLmZpbGUtcHJldmlldy1pbml0aWFsJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnVwbG9hZEFzeW5jICYmICRpbml0VGh1bWJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRpbml0VGh1bWJzLCAkaC5TT1JUX0NTUyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0U29ydGFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEpO1xuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5CZWZvcmUgPSBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUik7XG4gICAgICAgICAgICAgICAgc2VsZi5maWxlQmF0Y2hDb21wbGV0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISR0aHVtYi5oYXNDbGFzcygnZmlsZS1wcmV2aWV3LXN1Y2Nlc3MnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnTG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCR0aHVtYiwgJ2ZpbGUtdXBsb2FkaW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAkYnRuRGVsZXRlLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2NrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlcHJldXBsb2FkJywgW291dERhdGEsIHByZXZpZXdJZCwgaV0pO1xuICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHBhcmFtcywgb3V0RGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAganFYSFIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3NDYW5jZWxsZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5TdWNjZXNzID0gZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBpZCA9IHNlbGYuc2hvd1ByZXZpZXcgJiYgJHRodW1iLmF0dHIoJ2lkJykgPyAkdGh1bWIuYXR0cignaWQnKSA6IHByZXZpZXdJZDtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUiwgZGF0YSk7XG4gICAgICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgcGFyYW1zLCBvdXREYXRhKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYlN0YXR1cygkdGh1bWIsICdTdWNjZXNzJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFVwbG9hZFN1Y2Nlc3MoZGF0YSwgJHRodW1iLCBhbGxGaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoMTAxLCAkcHJvZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXVwbG9hZGVkJywgW291dERhdGEsIHBpZCwgaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhbGxGaWxlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soaSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlVXBsb2FkTG9nKGksIHBpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGxvYWRGYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGRhdGEuZXJyb3IsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iLCBpLCAobXVsdGlVcGxvYWRNb2RlID8gbnVsbCA6IHNlbGYuZmlsZXN0YWNrW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVVcGxvYWRMb2coaSwgcGlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRidG5EZWxldGUucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVubG9jayhmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhckZpbGVJbnB1dCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hrQ29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0U3VjY2Vzc1RodW1icygpO1xuICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLnVwbG9hZFRodW1iLFxuICAgICAgICAgICAgICAgICAgICBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24sIChhbGxGaWxlcyA/IGZpbGVzW2ldLm5hbWUgOiBudWxsKSk7XG4gICAgICAgICAgICAgICAgdXBsb2FkRmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFsbEZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVVcGxvYWRMb2coaSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnVwbG9hZFN0YXR1c1twcmV2aWV3SWRdID0gMTAwO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iLCBpLCAobXVsdGlVcGxvYWRNb2RlID8gbnVsbCA6IHNlbGYuZmlsZXN0YWNrW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgICQuZXh0ZW5kKHRydWUsIHBhcmFtcywgc2VsZi5fZ2V0T3V0RGF0YShqcVhIUikpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsICRwcm9nLCBzZWxmLm1zZ0FqYXhQcm9ncmVzc0Vycm9yLnJlcGxhY2UoJ3tvcGVyYXRpb259Jywgb3ApKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGVyck1zZywgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvcm1kYXRhLmFwcGVuZChzZWxmLnVwbG9hZEZpbGVBdHRyLCBmaWxlc1tpXSwgc2VsZi5maWxlbmFtZXNbaV0pO1xuICAgICAgICAgICAgZm9ybWRhdGEuYXBwZW5kKCdmaWxlX2lkJywgaSk7XG4gICAgICAgICAgICBzZWxmLl9hamF4U3VibWl0KGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IsIHByZXZpZXdJZCwgaSk7XG4gICAgICAgIH0sXG4gICAgICAgIF91cGxvYWRCYXRjaDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBmaWxlcyA9IHNlbGYuZmlsZXN0YWNrLCB0b3RhbCA9IGZpbGVzLmxlbmd0aCwgcGFyYW1zID0ge30sIGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuRXJyb3IsXG4gICAgICAgICAgICAgICAgZm5Db21wbGV0ZSwgaGFzUG9zdERhdGEgPSBzZWxmLmZpbGVzdGFjay5sZW5ndGggPiAwIHx8ICEkLmlzRW1wdHlPYmplY3Qoc2VsZi51cGxvYWRFeHRyYURhdGEpLFxuICAgICAgICAgICAgICAgIHNldEFsbFVwbG9hZGVkO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgaWYgKHRvdGFsID09PSAwIHx8ICFoYXNQb3N0RGF0YSB8fCBzZWxmLl9hYm9ydChwYXJhbXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0QWxsVXBsb2FkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soa2V5LCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5CZWZvcmUgPSBmdW5jdGlvbiAoanFYSFIpIHtcbiAgICAgICAgICAgICAgICBzZWxmLmxvY2soKTtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpO1xuICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZSA9ICR0aHVtYi5maW5kKCcua3YtZmlsZS1yZW1vdmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghJHRodW1iLmhhc0NsYXNzKCdmaWxlLXByZXZpZXctc3VjY2VzcycpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnTG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmFkZENzcygkdGh1bWIsICdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGJ0blVwbG9hZC5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGJ0bkRlbGV0ZS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHByZXVwbG9hZCcsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KG91dERhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGpxWEhSLmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzQ2FuY2VsbGVkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuU3VjY2VzcyA9IGZ1bmN0aW9uIChkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuICAgICAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGRhdGEuZXJyb3JrZXlzICovXG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSLCBkYXRhKSwgJHRodW1icyA9IHNlbGYuX2dldFRodW1icygnOm5vdCguZmlsZS1wcmV2aWV3LWVycm9yKScpLFxuICAgICAgICAgICAgICAgICAgICBrZXkgPSAwLFxuICAgICAgICAgICAgICAgICAgICBrZXlzID0gJGguaXNFbXB0eShkYXRhKSB8fCAkaC5pc0VtcHR5KGRhdGEuZXJyb3JrZXlzKSA/IFtdIDogZGF0YS5lcnJvcmtleXM7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2Fkc3VjY2VzcycsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgICAgIHNldEFsbFVwbG9hZGVkKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGh1bWJzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCAkYnRuVXBsb2FkID0gJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnU3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aHVtYnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksICRidG5EZWxldGUgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQgPSAkdGh1bWIuZmluZCgnLmt2LWZpbGUtdXBsb2FkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRidG5VcGxvYWQucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYnRuRGVsZXRlLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkLmluQXJyYXkoa2V5LCBrZXlzKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnU3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnVwZGF0ZVN0YWNrKGtleSwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2luaXRVcGxvYWRTdWNjZXNzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihkYXRhLmVycm9yLCBvdXREYXRhLCAnZmlsZWJhdGNodXBsb2FkZXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnVubG9jaygpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2luaXRTdWNjZXNzVGh1bWJzKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpLCBvcCA9IHNlbGYuYWpheE9wZXJhdGlvbnMudXBsb2FkQmF0Y2gsXG4gICAgICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYuX3BhcnNlRXJyb3Iob3AsIGpxWEhSLCBlcnJvclRocm93bik7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGVyck1zZywgb3V0RGF0YSwgJ2ZpbGViYXRjaHVwbG9hZGVycm9yJyk7XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRGaWxlQ291bnQgPSB0b3RhbCAtIDE7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkdGh1bWIgPSAkKHRoaXMpLCBrZXkgPSAkdGh1bWIuYXR0cignZGF0YS1maWxlaW5kZXgnKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5maWxlc3RhY2tba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcmV2aWV3RXJyb3IoJHRodW1iKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygnIC5rdi1maWxlLXVwbG9hZCcpLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCcgLmt2LWZpbGUtZGVsZXRlJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0FqYXhQcm9ncmVzc0Vycm9yLnJlcGxhY2UoJ3tvcGVyYXRpb259Jywgb3ApKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAkLmVhY2goZmlsZXMsIGZ1bmN0aW9uIChrZXksIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZXNba2V5XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5mb3JtZGF0YS5hcHBlbmQoc2VsZi51cGxvYWRGaWxlQXR0ciwgZGF0YSwgc2VsZi5maWxlbmFtZXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzZWxmLl9hamF4U3VibWl0KGZuQmVmb3JlLCBmblN1Y2Nlc3MsIGZuQ29tcGxldGUsIGZuRXJyb3IpO1xuICAgICAgICB9LFxuICAgICAgICBfdXBsb2FkRXh0cmFPbmx5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIHBhcmFtcyA9IHt9LCBmbkJlZm9yZSwgZm5TdWNjZXNzLCBmbkNvbXBsZXRlLCBmbkVycm9yO1xuICAgICAgICAgICAgc2VsZi5mb3JtZGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbkJlZm9yZSA9IGZ1bmN0aW9uIChqcVhIUikge1xuICAgICAgICAgICAgICAgIHNlbGYubG9jaygpO1xuICAgICAgICAgICAgICAgIHZhciBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YShqcVhIUik7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGViYXRjaHByZXVwbG9hZCcsIFtvdXREYXRhXSk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3MoNTApO1xuICAgICAgICAgICAgICAgIHBhcmFtcy5kYXRhID0gb3V0RGF0YTtcbiAgICAgICAgICAgICAgICBwYXJhbXMueGhyID0ganFYSFI7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2Fib3J0KHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICAgICAganFYSFIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0UHJvZ3Jlc3NDYW5jZWxsZWQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5TdWNjZXNzID0gZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dERhdGEgPSBzZWxmLl9nZXRPdXREYXRhKGpxWEhSLCBkYXRhKTtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eShkYXRhKSB8fCAkaC5pc0VtcHR5KGRhdGEuZXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2h1cGxvYWRzdWNjZXNzJywgW291dERhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdFVwbG9hZFN1Y2Nlc3MoZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKGRhdGEuZXJyb3IsIG91dERhdGEsICdmaWxlYmF0Y2h1cGxvYWRlcnJvcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmbkNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYudW5sb2NrKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNodXBsb2FkY29tcGxldGUnLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZm5FcnJvciA9IGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0RGF0YSA9IHNlbGYuX2dldE91dERhdGEoanFYSFIpLCBvcCA9IHNlbGYuYWpheE9wZXJhdGlvbnMudXBsb2FkRXh0cmEsXG4gICAgICAgICAgICAgICAgICAgIGVyck1zZyA9IHNlbGYuX3BhcnNlRXJyb3Iob3AsIGpxWEhSLCBlcnJvclRocm93bik7XG4gICAgICAgICAgICAgICAgcGFyYW1zLmRhdGEgPSBvdXREYXRhO1xuICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dVcGxvYWRFcnJvcihlcnJNc2csIG91dERhdGEsICdmaWxlYmF0Y2h1cGxvYWRlcnJvcicpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSwgc2VsZi4kcHJvZ3Jlc3MsIHNlbGYubXNnQWpheFByb2dyZXNzRXJyb3IucmVwbGFjZSgne29wZXJhdGlvbn0nLCBvcCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGYuX2FqYXhTdWJtaXQoZm5CZWZvcmUsIGZuU3VjY2VzcywgZm5Db21wbGV0ZSwgZm5FcnJvcik7XG4gICAgICAgIH0sXG4gICAgICAgIF9kZWxldGVGaWxlSW5kZXg6IGZ1bmN0aW9uICgkZnJhbWUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgaW5kID0gJGZyYW1lLmF0dHIoJ2RhdGEtZmlsZWluZGV4Jyk7XG4gICAgICAgICAgICBpZiAoaW5kLnN1YnN0cmluZygwLCA1KSA9PT0gJ2luaXRfJykge1xuICAgICAgICAgICAgICAgIGluZCA9IHBhcnNlSW50KGluZC5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlldyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXcsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXdDb25maWcsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5pbml0aWFsUHJldmlld1RodW1iVGFncyA9ICRoLnNwbGljZUFycmF5KHNlbGYuaW5pdGlhbFByZXZpZXdUaHVtYlRhZ3MsIGluZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5nZXRGcmFtZXMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRuRnJhbWUgPSAkKHRoaXMpLCBuSW5kID0gJG5GcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobkluZC5zdWJzdHJpbmcoMCwgNSkgPT09ICdpbml0XycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5JbmQgPSBwYXJzZUludChuSW5kLnJlcGxhY2UoJ2luaXRfJywgJycpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuSW5kID4gaW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbkluZC0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRuRnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnLCAnaW5pdF8nICsgbkluZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi51cGxvYWRBc3luYykge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlSW5pdGlhbFByZXZpZXcgPSBzZWxmLmdldFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0RmlsZUFjdGlvbnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b24oKTtcbiAgICAgICAgICAgIHNlbGYuZ2V0RnJhbWVzKCcgLmt2LWZpbGUtcmVtb3ZlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlbCA9ICQodGhpcyksICRmcmFtZSA9ICRlbC5jbG9zZXN0KCRoLkZSQU1FUyksIGhhc0Vycm9yLCBpZCA9ICRmcmFtZS5hdHRyKCdpZCcpLFxuICAgICAgICAgICAgICAgICAgICBpbmQgPSAkZnJhbWUuYXR0cignZGF0YS1maWxlaW5kZXgnKSwgbiwgY2FwLCBzdGF0dXM7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZWwsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gc2VsZi5fcmFpc2UoJ2ZpbGVwcmVyZW1vdmUnLCBbaWQsIGluZF0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSBmYWxzZSB8fCAhc2VsZi5fdmFsaWRhdGVNaW5Db3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaGFzRXJyb3IgPSAkZnJhbWUuaGFzQ2xhc3MoJ2ZpbGUtcHJldmlldy1lcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICAkaC5jbGVhbk1lbW9yeSgkZnJhbWUpO1xuICAgICAgICAgICAgICAgICAgICAkZnJhbWUuZmFkZU91dCgnc2xvdycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyBpZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi51cGRhdGVTdGFjayhpbmQsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhck9iamVjdHMoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpZCAmJiBoYXNFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuJGVycm9yQ29udGFpbmVyLmZpbmQoJ2xpW2RhdGEtZmlsZS1pZD1cIicgKyBpZCArICdcIl0nKS5mYWRlT3V0KCdmYXN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuX2Vycm9yc0V4aXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmlsZXN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2sodHJ1ZSksIGNoayA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuID0gZmlsZXN0YWNrLmxlbmd0aCwgaGFzVGh1bWIgPSBzZWxmLnNob3dQcmV2aWV3ICYmIHNlbGYuZ2V0RnJhbWVzKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbiA9PT0gMCAmJiBjaGsgPT09IDAgJiYgIWhhc1RodW1iKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gY2hrICsgbGVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcCA9IG4gPiAxID8gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobikgOiAoZmlsZXN0YWNrWzBdID8gc2VsZi5fZ2V0RmlsZU5hbWVzKClbMF0gOiAnJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVyZW1vdmVkJywgW2lkLCBpbmRdKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuZ2V0RnJhbWVzKCcgLmt2LWZpbGUtdXBsb2FkJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlbCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faGFuZGxlcigkZWwsICdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRmcmFtZSA9ICRlbC5jbG9zZXN0KCRoLkZSQU1FUyksIGluZCA9ICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISRmcmFtZS5oYXNDbGFzcygnZmlsZS1wcmV2aWV3LWVycm9yJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwbG9hZFNpbmdsZShpbmQsIHNlbGYuZmlsZXN0YWNrLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaW5pdFByZXZpZXdBY3Rpb25zOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldywgZGVsZXRlRXh0cmFEYXRhID0gc2VsZi5kZWxldGVFeHRyYURhdGEgfHwge30sXG4gICAgICAgICAgICAgICAgYnRuUmVtb3ZlID0gJGguRlJBTUVTICsgJyAua3YtZmlsZS1yZW1vdmUnLFxuICAgICAgICAgICAgICAgIHJlc2V0UHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoYXNGaWxlcyA9IHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQoKSA6IHNlbGYuJGVsZW1lbnQuZ2V0KDApLmZpbGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRwcmV2aWV3LmZpbmQoYnRuUmVtb3ZlKS5sZW5ndGggPT09IDAgJiYgIWhhc0ZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmluaXRpYWxDYXB0aW9uID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5faW5pdFpvb21CdXR0b24oKTtcbiAgICAgICAgICAgICRwcmV2aWV3LmZpbmQoYnRuUmVtb3ZlKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGVsID0gJCh0aGlzKSwgdlVybCA9ICRlbC5kYXRhKCd1cmwnKSB8fCBzZWxmLmRlbGV0ZVVybCwgdktleSA9ICRlbC5kYXRhKCdrZXknKTtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eSh2VXJsKSB8fCB2S2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgJGZyYW1lID0gJGVsLmNsb3Nlc3QoJGguRlJBTUVTKSwgY2FjaGUgPSBzZWxmLnByZXZpZXdDYWNoZS5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBzZXR0aW5ncywgcGFyYW1zLCBpbmRleCA9ICRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpLCBjb25maWcsIGV4dHJhRGF0YTtcbiAgICAgICAgICAgICAgICBpbmRleCA9IHBhcnNlSW50KGluZGV4LnJlcGxhY2UoJ2luaXRfJywgJycpKTtcbiAgICAgICAgICAgICAgICBjb25maWcgPSAkaC5pc0VtcHR5KGNhY2hlLmNvbmZpZykgJiYgJGguaXNFbXB0eShjYWNoZS5jb25maWdbaW5kZXhdKSA/IG51bGwgOiBjYWNoZS5jb25maWdbaW5kZXhdO1xuICAgICAgICAgICAgICAgIGV4dHJhRGF0YSA9ICRoLmlzRW1wdHkoY29uZmlnKSB8fCAkaC5pc0VtcHR5KGNvbmZpZy5leHRyYSkgPyBkZWxldGVFeHRyYURhdGEgOiBjb25maWcuZXh0cmE7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBleHRyYURhdGEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBleHRyYURhdGEgPSBleHRyYURhdGEoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge2lkOiAkZWwuYXR0cignaWQnKSwga2V5OiB2S2V5LCBleHRyYTogZXh0cmFEYXRhfTtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncyA9ICQuZXh0ZW5kKHRydWUsIHt9LCB7XG4gICAgICAgICAgICAgICAgICAgIHVybDogdlVybCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiAkLmV4dGVuZCh0cnVlLCB7fSwge2tleTogdktleX0sIGV4dHJhRGF0YSksXG4gICAgICAgICAgICAgICAgICAgIGJlZm9yZVNlbmQ6IGZ1bmN0aW9uIChqcVhIUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hamF4QWJvcnRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVwcmVkZWxldGUnLCBbdktleSwganFYSFIsIGV4dHJhRGF0YV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuYWpheEFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqcVhIUi5hYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJGZyYW1lLCAnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaC5hZGRDc3MoJGVsLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbiwgY2FwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoZGF0YSkgfHwgJGguaXNFbXB0eShkYXRhLmVycm9yKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ID0gcGFyc2VJbnQoKCRmcmFtZS5hdHRyKCdkYXRhLWZpbGVpbmRleCcpKS5yZXBsYWNlKCdpbml0XycsICcnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wcmV2aWV3Q2FjaGUudW5zZXQoaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcCA9IG4gPiAwID8gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobikgOiAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9kZWxldGVGaWxlSW5kZXgoJGZyYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGNhcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVkZWxldGVkJywgW3ZLZXksIGpxWEhSLCBleHRyYURhdGFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmpxWEhSID0ganFYSFI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnJlc3BvbnNlID0gZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9zaG93RXJyb3IoZGF0YS5lcnJvciwgcGFyYW1zLCAnZmlsZWRlbGV0ZWVycm9yJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRlbC5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldFByb2dyZXNzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpLmFkZENsYXNzKCdmaWxlLWRlbGV0ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5mYWRlT3V0KCdzbG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRoLmNsZWFuWm9vbUNhY2hlKCRwcmV2aWV3LmZpbmQoJyN6b29tLScgKyAkZnJhbWUuYXR0cignaWQnKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyT2JqZWN0cygkZnJhbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRmcmFtZS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldFByb2dyZXNzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFuICYmIHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3AgPSBzZWxmLmFqYXhPcGVyYXRpb25zLmRlbGV0ZVRodW1iLCBlcnJNc2cgPSBzZWxmLl9wYXJzZUVycm9yKG9wLCBqcVhIUiwgZXJyb3JUaHJvd24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmpxWEhSID0ganFYSFI7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Nob3dFcnJvcihlcnJNc2csIHBhcmFtcywgJ2ZpbGVkZWxldGVlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGZyYW1lLnJlbW92ZUNsYXNzKCdmaWxlLXVwbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRQcm9ncmVzcygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgc2VsZi5hamF4RGVsZXRlU2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2hhbmRsZXIoJGVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5fdmFsaWRhdGVNaW5Db3VudCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgJC5hamF4KHNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfaGlkZUZpbGVJY29uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kY2FwdGlvbkNvbnRhaW5lci5maW5kKCcua3YtY2FwdGlvbi1pY29uJykuaGlkZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2hvd0ZpbGVJY29uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5zaG93KCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRTaXplOiBmdW5jdGlvbiAoYnl0ZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgc2l6ZSA9IHBhcnNlRmxvYXQoYnl0ZXMpLCBpLCBmdW5jID0gc2VsZi5maWxlU2l6ZUdldHRlciwgc2l6ZXMsIG91dDtcbiAgICAgICAgICAgIGlmICghJC5pc051bWVyaWMoYnl0ZXMpIHx8ICEkLmlzTnVtZXJpYyhzaXplKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIG91dCA9IGZ1bmMoc2l6ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzaXplID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9ICcwLjAwIEInO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGkgPSBNYXRoLmZsb29yKE1hdGgubG9nKHNpemUpIC8gTWF0aC5sb2coMTAyNCkpO1xuICAgICAgICAgICAgICAgICAgICBzaXplcyA9IFsnQicsICdLQicsICdNQicsICdHQicsICdUQicsICdQQicsICdFQicsICdaQicsICdZQiddO1xuICAgICAgICAgICAgICAgICAgICBvdXQgPSAoc2l6ZSAvIE1hdGgucG93KDEwMjQsIGkpKS50b0ZpeGVkKDIpICogMSArICcgJyArIHNpemVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnc2l6ZScpLnJlcGxhY2UoJ3tzaXplVGV4dH0nLCBvdXQpO1xuICAgICAgICB9LFxuICAgICAgICBfZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGU6IGZ1bmN0aW9uIChjYXQsIGRhdGEsIGZuYW1lLCBmdHlwZSwgcHJldmlld0lkLCBpc0Vycm9yLCBzaXplLCBmcmFtZUNsYXNzLCBmb290LCBpbmQsIHRlbXBsKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLCBwcmV2Q29udGVudCwgem9vbUNvbnRlbnQgPSAnJyxcbiAgICAgICAgICAgICAgICBjb25maWcgPSBzZWxmLnByZXZpZXdTZXR0aW5nc1tjYXRdIHx8IHNlbGYuZGVmYXVsdHMucHJldmlld1NldHRpbmdzW2NhdF0sXG4gICAgICAgICAgICAgICAgdyA9IGNvbmZpZyAmJiBjb25maWcud2lkdGggPyBjb25maWcud2lkdGggOiAnJywgaCA9IGNvbmZpZyAmJiBjb25maWcuaGVpZ2h0ID8gY29uZmlnLmhlaWdodCA6ICcnLFxuICAgICAgICAgICAgICAgIGZvb3RlciA9IGZvb3QgfHwgc2VsZi5fcmVuZGVyRmlsZUZvb3RlcihjYXB0aW9uLCBzaXplLCAoJGguaXNFbXB0eSh3KSA/ICdhdXRvJyA6IHcpLCBpc0Vycm9yKSxcbiAgICAgICAgICAgICAgICBoYXNJY29uU2V0dGluZyA9IHNlbGYuX2dldFByZXZpZXdJY29uKGZuYW1lKSwgdHlwZUNzcyA9ICd0eXBlLWRlZmF1bHQnLFxuICAgICAgICAgICAgICAgIGZvcmNlUHJldkljb24gPSBoYXNJY29uU2V0dGluZyAmJiBzZWxmLnByZWZlckljb25pY1ByZXZpZXcsXG4gICAgICAgICAgICAgICAgZm9yY2Vab29tSWNvbiA9IGhhc0ljb25TZXR0aW5nICYmIHNlbGYucHJlZmVySWNvbmljWm9vbVByZXZpZXcsXG4gICAgICAgICAgICAgICAgZ2V0Q29udGVudCA9IGZ1bmN0aW9uIChjLCBkLCB6b29tLCBmcmFtZUNzcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaWQgPSB6b29tID8gJ3pvb20tJyArIHByZXZpZXdJZCA6IHByZXZpZXdJZCwgdG1wbHQgPSBzZWxmLl9nZXRQcmV2aWV3VGVtcGxhdGUoYyksXG4gICAgICAgICAgICAgICAgICAgICAgICBjc3MgPSAoZnJhbWVDbGFzcyB8fCAnJykgKyAnICcgKyBmcmFtZUNzcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuZnJhbWVDbGFzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3NzID0gc2VsZi5mcmFtZUNsYXNzICsgJyAnICsgY3NzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh6b29tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjc3MgPSBjc3MucmVwbGFjZSgnICcgKyAkaC5TT1JUX0NTUywgJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRtcGx0ID0gc2VsZi5fcGFyc2VGaWxlUHJldmlld0ljb24odG1wbHQsIGZuYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMgPT09ICd0ZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZCA9ICRoLmh0bWxFbmNvZGUoZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhdCA9PT0gJ29iamVjdCcgJiYgIWZ0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2goc2VsZi5kZWZhdWx0cy5maWxlVHlwZVNldHRpbmdzLCBmdW5jdGlvbiAoa2V5LCBmdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ29iamVjdCcgfHwga2V5ID09PSAnb3RoZXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZ1bmMoZm5hbWUsIGZ0eXBlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlQ3NzID0gJ3R5cGUtJyArIGtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdG1wbHQuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICdwcmV2aWV3SWQnOiBpZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdjYXB0aW9uJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICdmcmFtZUNsYXNzJzogY3NzLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBmdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICdmaWxlaW5kZXgnOiBpbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3LFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2hlaWdodCc6IGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAndHlwZUNzcyc6IHR5cGVDc3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZm9vdGVyJzogZm9vdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2RhdGEnOiBkLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RlbXBsYXRlJzogdGVtcGwgfHwgY2F0XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpbmQgPSBpbmQgfHwgcHJldmlld0lkLnNsaWNlKHByZXZpZXdJZC5sYXN0SW5kZXhPZignLScpICsgMSk7XG4gICAgICAgICAgICBpZiAoc2VsZi5maWxlQWN0aW9uU2V0dGluZ3Muc2hvd1pvb20pIHtcbiAgICAgICAgICAgICAgICB6b29tQ29udGVudCA9IGdldENvbnRlbnQoKGZvcmNlWm9vbUljb24gPyAnb3RoZXInIDogY2F0KSwgZGF0YSwgdHJ1ZSwgJ2t2LXpvb20tdGh1bWInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHpvb21Db250ZW50ID0gJ1xcbicgKyBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnem9vbUNhY2hlJykucmVwbGFjZSgne3pvb21Db250ZW50fScsIHpvb21Db250ZW50KTtcbiAgICAgICAgICAgIHByZXZDb250ZW50ID0gZ2V0Q29udGVudCgoZm9yY2VQcmV2SWNvbiA/ICdvdGhlcicgOiBjYXQpLCBkYXRhLCBmYWxzZSwgJ2t2LXByZXZpZXctdGh1bWInKTtcbiAgICAgICAgICAgIHJldHVybiBwcmV2Q29udGVudCArIHpvb21Db250ZW50O1xuICAgICAgICB9LFxuICAgICAgICBfcHJldmlld0RlZmF1bHQ6IGZ1bmN0aW9uIChmaWxlLCBwcmV2aWV3SWQsIGlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHByZXZpZXcgPSBzZWxmLiRwcmV2aWV3O1xuICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGZuYW1lID0gZmlsZSA/IGZpbGUubmFtZSA6ICcnLCBmdHlwZSA9IGZpbGUgPyBmaWxlLnR5cGUgOiAnJywgY29udGVudCwgc2l6ZSA9IGZpbGUuc2l6ZSB8fCAwLFxuICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLCBpc0Vycm9yID0gaXNEaXNhYmxlZCA9PT0gdHJ1ZSAmJiAhc2VsZi5pc1VwbG9hZGFibGUsXG4gICAgICAgICAgICAgICAgZGF0YSA9ICRoLm9ialVybC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG4gICAgICAgICAgICBzZWxmLl9jbGVhckRlZmF1bHRQcmV2aWV3KCk7XG4gICAgICAgICAgICBjb250ZW50ID0gc2VsZi5fZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGUoJ290aGVyJywgZGF0YSwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGlzRXJyb3IsIHNpemUpO1xuICAgICAgICAgICAgJHByZXZpZXcuYXBwZW5kKFwiXFxuXCIgKyBjb250ZW50KTtcbiAgICAgICAgICAgIHNlbGYuX3NldFRodW1iQXR0cihwcmV2aWV3SWQsIGNhcHRpb24sIHNpemUpO1xuICAgICAgICAgICAgaWYgKGlzRGlzYWJsZWQgPT09IHRydWUgJiYgc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYlN0YXR1cygkKCcjJyArIHByZXZpZXdJZCksICdFcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfcHJldmlld0ZpbGU6IGZ1bmN0aW9uIChpLCBmaWxlLCB0aGVGaWxlLCBwcmV2aWV3SWQsIGRhdGEpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zaG93UHJldmlldykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgY2F0ID0gc2VsZi5fcGFyc2VGaWxlVHlwZShmaWxlKSwgZm5hbWUgPSBmaWxlID8gZmlsZS5uYW1lIDogJycsIGNhcHRpb24gPSBzZWxmLnNsdWcoZm5hbWUpLFxuICAgICAgICAgICAgICAgIHR5cGVzID0gc2VsZi5hbGxvd2VkUHJldmlld1R5cGVzLCBtaW1lcyA9IHNlbGYuYWxsb3dlZFByZXZpZXdNaW1lVHlwZXMsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldyxcbiAgICAgICAgICAgICAgICBjaGtUeXBlcyA9IHR5cGVzICYmIHR5cGVzLmluZGV4T2YoY2F0KSA+PSAwLCBmc2l6ZSA9IGZpbGUuc2l6ZSB8fCAwLCBmdHlwZSA9IGZpbGUudHlwZSxcbiAgICAgICAgICAgICAgICBpRGF0YSA9IChjYXQgPT09ICd0ZXh0JyB8fCBjYXQgPT09ICdodG1sJyB8fCBjYXQgPT09ICdpbWFnZScpID8gdGhlRmlsZS50YXJnZXQucmVzdWx0IDogZGF0YSwgY29udGVudCxcbiAgICAgICAgICAgICAgICBjaGtNaW1lcyA9IG1pbWVzICYmIG1pbWVzLmluZGV4T2YoZnR5cGUpICE9PSAtMTtcbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIHdpbmRvdy5ET01QdXJpZnkgKi9cbiAgICAgICAgICAgIGlmIChjYXQgPT09ICdodG1sJyAmJiBzZWxmLnB1cmlmeUh0bWwgJiYgd2luZG93LkRPTVB1cmlmeSkge1xuICAgICAgICAgICAgICAgIGlEYXRhID0gd2luZG93LkRPTVB1cmlmeS5zYW5pdGl6ZShpRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2hrVHlwZXMgfHwgY2hrTWltZXMpIHtcbiAgICAgICAgICAgICAgICBjb250ZW50ID0gc2VsZi5fZ2VuZXJhdGVQcmV2aWV3VGVtcGxhdGUoY2F0LCBpRGF0YSwgZm5hbWUsIGZ0eXBlLCBwcmV2aWV3SWQsIGZhbHNlLCBmc2l6ZSk7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJEZWZhdWx0UHJldmlldygpO1xuICAgICAgICAgICAgICAgICRwcmV2aWV3LmFwcGVuZChcIlxcblwiICsgY29udGVudCk7XG4gICAgICAgICAgICAgICAgdmFyICRpbWcgPSAkcHJldmlldy5maW5kKCcjJyArIHByZXZpZXdJZCArICcgaW1nJyk7XG4gICAgICAgICAgICAgICAgaWYgKCRpbWcubGVuZ3RoICYmIHNlbGYuYXV0b09yaWVudEltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICRoLnZhbGlkYXRlT3JpZW50YXRpb24oZmlsZSwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHpvb21JbWcgPSAkcHJldmlldy5maW5kKCcjem9vbS0nICsgcHJldmlld0lkICsgJyBpbWcnKSwgY3NzID0gJ3JvdGF0ZS0nICsgdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID4gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjc3MgKz0gKCRpbWcud2lkdGgoKSA+ICRpbWcuaGVpZ2h0KCkgPyAnIGlzLXBvcnRyYWl0LWd0NCcgOiAnIGlzLWxhbmRzY2FwZS1ndDQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCRpbWcsIGNzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRkQ3NzKCR6b29tSW1nLCBjc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VvcmllbnRlZCcsIHsnJGltZyc6ICRpbWcsICdmaWxlJzogZmlsZX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVJbWFnZShwcmV2aWV3SWQsIGNhcHRpb24sIGZ0eXBlLCBmc2l6ZSwgaURhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGguYWRqdXN0T3JpZW50ZWRJbWFnZSgkaW1nKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVJbWFnZShwcmV2aWV3SWQsIGNhcHRpb24sIGZ0eXBlLCBmc2l6ZSwgaURhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3NldFRodW1iQXR0cihwcmV2aWV3SWQsIGNhcHRpb24sIGZzaXplKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRTb3J0YWJsZSgpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0VGh1bWJBdHRyOiBmdW5jdGlvbiAoaWQsIGNhcHRpb24sIHNpemUpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gJCgnIycgKyBpZCk7XG4gICAgICAgICAgICBpZiAoJGZyYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNpemUgPSBzaXplICYmIHNpemUgPiAwID8gc2VsZi5fZ2V0U2l6ZShzaXplKSA6ICcnO1xuICAgICAgICAgICAgICAgICRmcmFtZS5kYXRhKHsnY2FwdGlvbic6IGNhcHRpb24sICdzaXplJzogc2l6ZX0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2V0SW5pdFRodW1iQXR0cjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhID0gc2VsZi5wcmV2aWV3Q2FjaGUuZGF0YSwgbGVuID0gc2VsZi5wcmV2aWV3Q2FjaGUuY291bnQodHJ1ZSksIGNvbmZpZyxcbiAgICAgICAgICAgICAgICBjYXB0aW9uLCBzaXplLCBwcmV2aWV3SWQ7XG4gICAgICAgICAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbmZpZyA9IGRhdGEuY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgIHByZXZpZXdJZCA9IHNlbGYucHJldmlld0luaXRJZCArICctJyArICdpbml0XycgKyBpO1xuICAgICAgICAgICAgICAgIGNhcHRpb24gPSAkaC5pZlNldCgnY2FwdGlvbicsIGNvbmZpZywgJGguaWZTZXQoJ2ZpbGVuYW1lJywgY29uZmlnKSk7XG4gICAgICAgICAgICAgICAgc2l6ZSA9ICRoLmlmU2V0KCdzaXplJywgY29uZmlnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRUaHVtYkF0dHIocHJldmlld0lkLCBjYXB0aW9uLCBzaXplKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX3NsdWdEZWZhdWx0OiBmdW5jdGlvbiAodGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuICRoLmlzRW1wdHkodGV4dCkgPyAnJyA6IFN0cmluZyh0ZXh0KS5yZXBsYWNlKC9bXFwtXFxbXFxdXFwvXFx7fTo7IyU9XFwoXFwpXFwqXFwrXFw/XFxcXFxcXlxcJFxcfDw+JlwiJ10vZywgJ18nKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlYWRGaWxlczogZnVuY3Rpb24gKGZpbGVzKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQsICRwcmV2aWV3ID0gc2VsZi4kcHJldmlldywgcmVhZGVyID0gc2VsZi5yZWFkZXIsXG4gICAgICAgICAgICAgICAgJGNvbnRhaW5lciA9IHNlbGYuJHByZXZpZXdDb250YWluZXIsICRzdGF0dXMgPSBzZWxmLiRwcmV2aWV3U3RhdHVzLCBtc2dMb2FkaW5nID0gc2VsZi5tc2dMb2FkaW5nLFxuICAgICAgICAgICAgICAgIG1zZ1Byb2dyZXNzID0gc2VsZi5tc2dQcm9ncmVzcywgcHJldmlld0luaXRJZCA9IHNlbGYucHJldmlld0luaXRJZCwgbnVtRmlsZXMgPSBmaWxlcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSBzZWxmLmZpbGVUeXBlU2V0dGluZ3MsIGN0ciA9IHNlbGYuZmlsZXN0YWNrLmxlbmd0aCwgcmVhZEZpbGUsXG4gICAgICAgICAgICAgICAgZmlsZVR5cGVzID0gc2VsZi5hbGxvd2VkRmlsZVR5cGVzLCB0eXBMZW4gPSBmaWxlVHlwZXMgPyBmaWxlVHlwZXMubGVuZ3RoIDogMCxcbiAgICAgICAgICAgICAgICBmaWxlRXh0ID0gc2VsZi5hbGxvd2VkRmlsZUV4dGVuc2lvbnMsIHN0ckV4dCA9ICRoLmlzRW1wdHkoZmlsZUV4dCkgPyAnJyA6IGZpbGVFeHQuam9pbignLCAnKSxcbiAgICAgICAgICAgICAgICBtYXhQcmV2aWV3U2l6ZSA9IHNlbGYubWF4RmlsZVByZXZpZXdTaXplICYmIHBhcnNlRmxvYXQoc2VsZi5tYXhGaWxlUHJldmlld1NpemUpLFxuICAgICAgICAgICAgICAgIGNhblByZXZpZXcgPSAkcHJldmlldy5sZW5ndGggJiYgKCFtYXhQcmV2aWV3U2l6ZSB8fCBpc05hTihtYXhQcmV2aWV3U2l6ZSkpLFxuICAgICAgICAgICAgICAgIHRocm93RXJyb3IgPSBmdW5jdGlvbiAobXNnLCBmaWxlLCBwcmV2aWV3SWQsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwMSA9ICQuZXh0ZW5kKHRydWUsIHt9LCBzZWxmLl9nZXRPdXREYXRhKHt9LCB7fSwgZmlsZXMpLCB7aWQ6IHByZXZpZXdJZCwgaW5kZXg6IGluZGV4fSksXG4gICAgICAgICAgICAgICAgICAgICAgICBwMiA9IHtpZDogcHJldmlld0lkLCBpbmRleDogaW5kZXgsIGZpbGU6IGZpbGUsIGZpbGVzOiBmaWxlc307XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdEZWZhdWx0KGZpbGUsIHByZXZpZXdJZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRUb1N0YWNrKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpbmRleCArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9pbml0RmlsZUFjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYucmVtb3ZlRnJvbVByZXZpZXdPbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKCcjJyArIHByZXZpZXdJZCkucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGYuaXNVcGxvYWRhYmxlID8gc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1zZywgcDEpIDogc2VsZi5fc2hvd0Vycm9yKG1zZywgcDIpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHNlbGYubG9hZGVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBzZWxmLnRvdGFsSW1hZ2VzQ291bnQgPSAwO1xuXG4gICAgICAgICAgICAkLmVhY2goZmlsZXMsIGZ1bmN0aW9uIChrZXksIGZpbGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IHNlbGYuZmlsZVR5cGVTZXR0aW5ncy5pbWFnZTtcbiAgICAgICAgICAgICAgICBpZiAoZnVuYyAmJiBmdW5jKGZpbGUudHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi50b3RhbEltYWdlc0NvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZWFkRmlsZSA9IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCRoLmlzRW1wdHkoJGVsLmF0dHIoJ211bHRpcGxlJykpKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bUZpbGVzID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGkgPj0gbnVtRmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlICYmIHNlbGYuZmlsZXN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hzZWxlY3RlZCcsIFtzZWxmLmdldEZpbGVTdGFjaygpXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJhdGNoc2VsZWN0ZWQnLCBbZmlsZXNdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgJHN0YXR1cy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IGN0ciArIGksIHByZXZpZXdJZCA9IHByZXZpZXdJbml0SWQgKyBcIi1cIiArIG5vZGUsIGlzVGV4dCwgaXNJbWFnZSwgZmlsZSA9IGZpbGVzW2ldLCBmU2l6ZUtCLFxuICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gZmlsZS5uYW1lID8gc2VsZi5zbHVnKGZpbGUubmFtZSkgOiAnJywgZmlsZVNpemUgPSAoZmlsZS5zaXplIHx8IDApIC8gMTAwMCwgaiwgbXNnLFxuICAgICAgICAgICAgICAgICAgICBmaWxlRXh0RXhwciA9ICcnLCBwcmV2aWV3RGF0YSA9ICRoLm9ialVybC5jcmVhdGVPYmplY3RVUkwoZmlsZSksIHR5cCwgY2hrLCB0eXAxLCB0eXAyLFxuICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgPSAwLCBzdHJUeXBlcyA9ICcnLCBmdW5jO1xuICAgICAgICAgICAgICAgIGlmICh0eXBMZW4gPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB0eXBMZW47IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwMSA9IGZpbGVUeXBlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cDIgPSBzZWxmLm1zZ0ZpbGVUeXBlc1t0eXAxXSB8fCB0eXAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyVHlwZXMgKz0gaiA9PT0gMCA/IHR5cDIgOiAnLCAnICsgdHlwMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2FwdGlvbiA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjYXB0aW9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ0ludmFsaWRGaWxlTmFtZS5yZXBsYWNlKCd7bmFtZX0nLCAkaC5odG1sRW5jb2RlKGZpbGUubmFtZSkpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZUV4dCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsZUV4dEV4cHIgPSBuZXcgUmVnRXhwKCdcXFxcLignICsgZmlsZUV4dC5qb2luKCd8JykgKyAnKSQnLCAnaScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmU2l6ZUtCID0gZmlsZVNpemUudG9GaXhlZCgyKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5tYXhGaWxlU2l6ZSA+IDAgJiYgZmlsZVNpemUgPiBzZWxmLm1heEZpbGVTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnU2l6ZVRvb0xhcmdlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAnbmFtZSc6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZSc6IGZTaXplS0IsXG4gICAgICAgICAgICAgICAgICAgICAgICAnbWF4U2l6ZSc6IHNlbGYubWF4RmlsZVNpemVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaXNFcnJvciA9IHRocm93RXJyb3IobXNnLCBmaWxlLCBwcmV2aWV3SWQsIGkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzZWxmLm1pbkZpbGVTaXplICE9PSBudWxsICYmIGZpbGVTaXplIDw9ICRoLmdldE51bShzZWxmLm1pbkZpbGVTaXplKSkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzZWxmLm1zZ1NpemVUb29TbWFsbC5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBmU2l6ZUtCLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ21pblNpemUnOiBzZWxmLm1pbkZpbGVTaXplXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkoZmlsZVR5cGVzKSAmJiAkaC5pc0FycmF5KGZpbGVUeXBlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGZpbGVUeXBlcy5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwID0gZmlsZVR5cGVzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnVuYyA9IHNldHRpbmdzW3R5cF07XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgKz0gIWZ1bmMgfHwgKHR5cGVvZiBmdW5jICE9PSAnZnVuY3Rpb24nKSA/IDAgOiAoZnVuYyhmaWxlLnR5cGUsIGZpbGUubmFtZSkgPyAxIDogMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGVDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXNnID0gc2VsZi5tc2dJbnZhbGlkRmlsZVR5cGUuc2V0VG9rZW5zKHsnbmFtZSc6IGNhcHRpb24sICd0eXBlcyc6IHN0clR5cGVzfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmlsZUNvdW50ID09PSAwICYmICEkaC5pc0VtcHR5KGZpbGVFeHQpICYmICRoLmlzQXJyYXkoZmlsZUV4dCkgJiYgISRoLmlzRW1wdHkoZmlsZUV4dEV4cHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoayA9ICRoLmNvbXBhcmUoY2FwdGlvbiwgZmlsZUV4dEV4cHIpO1xuICAgICAgICAgICAgICAgICAgICBmaWxlQ291bnQgKz0gJGguaXNFbXB0eShjaGspID8gMCA6IGNoay5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnSW52YWxpZEZpbGVFeHRlbnNpb24uc2V0VG9rZW5zKHsnbmFtZSc6IGNhcHRpb24sICdleHRlbnNpb25zJzogc3RyRXh0fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmlzRXJyb3IgPSB0aHJvd0Vycm9yKG1zZywgZmlsZSwgcHJldmlld0lkLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmFkZFRvU3RhY2soZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlbG9hZGVkJywgW2ZpbGUsIHByZXZpZXdJZCwgaSwgcmVhZGVyXSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFjYW5QcmV2aWV3ICYmIGZpbGVTaXplID4gbWF4UHJldmlld1NpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRUb1N0YWNrKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAkY29udGFpbmVyLmFkZENsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdEZpbGVBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKG51bUZpbGVzKTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZEZpbGUoaSArIDEpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgkcHJldmlldy5sZW5ndGggJiYgRmlsZVJlYWRlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2dMb2FkaW5nLnJlcGxhY2UoJ3tpbmRleH0nLCBpICsgMSkucmVwbGFjZSgne2ZpbGVzfScsIG51bUZpbGVzKSk7XG4gICAgICAgICAgICAgICAgICAgICRjb250YWluZXIuYWRkQ2xhc3MoJ2ZpbGUtdGh1bWItbG9hZGluZycpO1xuICAgICAgICAgICAgICAgICAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2Vycm9ySGFuZGxlcihldnQsIGNhcHRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKHRoZUZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3ByZXZpZXdGaWxlKGksIGZpbGUsIHRoZUZpbGUsIHByZXZpZXdJZCwgcHJldmlld0RhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5faW5pdEZpbGVBY3Rpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5vbmxvYWRlbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBtc2dQcm9ncmVzcy5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpbmRleCc6IGkgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdmaWxlcyc6IG51bUZpbGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdwZXJjZW50JzogNTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUZpbGVEZXRhaWxzKG51bUZpbGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVsb2FkZWQnLCBbZmlsZSwgcHJldmlld0lkLCBpLCByZWFkZXJdKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEubGVuZ3RoQ29tcHV0YWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmYWN0ID0gKGRhdGEubG9hZGVkIC8gZGF0YS50b3RhbCkgKiAxMDAsIHByb2dyZXNzID0gTWF0aC5jZWlsKGZhY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZyA9IG1zZ1Byb2dyZXNzLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpbmRleCc6IGkgKyAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZmlsZXMnOiBudW1GaWxlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3BlcmNlbnQnOiBwcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ25hbWUnOiBjYXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0dXMuaHRtbChtc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlzVGV4dCA9IHNldHRpbmdzLnRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGlzSW1hZ2UgPSBzZXR0aW5ncy5pbWFnZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNUZXh0KGZpbGUudHlwZSwgY2FwdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUsIHNlbGYudGV4dEVuY29kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0ltYWdlKGZpbGUudHlwZSwgY2FwdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcHJldmlld0RlZmF1bHQoZmlsZSwgcHJldmlld0lkKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkRmlsZShpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVGaWxlRGV0YWlscyhudW1GaWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlbG9hZGVkJywgW2ZpbGUsIHByZXZpZXdJZCwgaSwgcmVhZGVyXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuYWRkVG9TdGFjayhmaWxlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJlYWRGaWxlKDApO1xuICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMobnVtRmlsZXMsIGZhbHNlKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3VwZGF0ZUZpbGVEZXRhaWxzOiBmdW5jdGlvbiAobnVtRmlsZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kZWxlbWVudCwgZmlsZVN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2soKSxcbiAgICAgICAgICAgICAgICBuYW1lID0gKCRoLmlzSUUoOSkgJiYgJGguZmluZEZpbGVOYW1lKCRlbC52YWwoKSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICgkZWxbMF0uZmlsZXNbMF0gJiYgJGVsWzBdLmZpbGVzWzBdLm5hbWUpIHx8IChmaWxlU3RhY2subGVuZ3RoICYmIGZpbGVTdGFja1swXS5uYW1lKSB8fCAnJyxcbiAgICAgICAgICAgICAgICBsYWJlbCA9IHNlbGYuc2x1ZyhuYW1lKSwgbiA9IHNlbGYuaXNVcGxvYWRhYmxlID8gZmlsZVN0YWNrLmxlbmd0aCA6IG51bUZpbGVzLFxuICAgICAgICAgICAgICAgIG5GaWxlcyA9IHNlbGYucHJldmlld0NhY2hlLmNvdW50KCkgKyBuLCBsb2cgPSBuID4gMSA/IHNlbGYuX2dldE1zZ1NlbGVjdGVkKG5GaWxlcykgOiBsYWJlbDtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3Q29udGFpbmVyLnJlbW92ZUNsYXNzKCdmaWxlLXRodW1iLWxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRwcmV2aWV3U3RhdHVzLmh0bWwoJycpO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmt2LWNhcHRpb24taWNvbicpLmhpZGUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0ZpbGVJY29uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRDYXB0aW9uKGxvZywgc2VsZi5pc0Vycm9yKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS1pbnB1dC1uZXcgZmlsZS1pbnB1dC1hamF4LW5ldycpO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXNlbGVjdCcsIFtudW1GaWxlcywgbGFiZWxdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFByZXZpZXdBY3Rpb25zKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRUaHVtYlN0YXR1czogZnVuY3Rpb24gKCR0aHVtYiwgc3RhdHVzKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBpZiAoIXNlbGYuc2hvd1ByZXZpZXcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaWNvbiA9ICdpbmRpY2F0b3InICsgc3RhdHVzLCBtc2cgPSBpY29uICsgJ1RpdGxlJyxcbiAgICAgICAgICAgICAgICBjc3MgPSAnZmlsZS1wcmV2aWV3LScgKyBzdGF0dXMudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgICAgICAgICAkaW5kaWNhdG9yID0gJHRodW1iLmZpbmQoJy5maWxlLXVwbG9hZC1pbmRpY2F0b3InKSxcbiAgICAgICAgICAgICAgICBjb25maWcgPSBzZWxmLmZpbGVBY3Rpb25TZXR0aW5ncztcbiAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS1wcmV2aWV3LXN1Y2Nlc3MgZmlsZS1wcmV2aWV3LWVycm9yIGZpbGUtcHJldmlldy1sb2FkaW5nJyk7XG4gICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgJHRodW1iLmZpbmQoJy5rdi1maWxlLXVwbG9hZCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnU3VjY2VzcycpIHtcbiAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmZpbGUtZHJhZy1oYW5kbGUnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAkaW5kaWNhdG9yLmNzcygnbWFyZ2luLWxlZnQnLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRpbmRpY2F0b3IuaHRtbChjb25maWdbaWNvbl0pO1xuICAgICAgICAgICAgJGluZGljYXRvci5hdHRyKCd0aXRsZScsIGNvbmZpZ1ttc2ddKTtcbiAgICAgICAgICAgICR0aHVtYi5hZGRDbGFzcyhjc3MpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0UHJvZ3Jlc3NDYW5jZWxsZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKDEwMSwgc2VsZi4kcHJvZ3Jlc3MsIHNlbGYubXNnQ2FuY2VsbGVkKTtcbiAgICAgICAgfSxcbiAgICAgICAgX3NldFByb2dyZXNzOiBmdW5jdGlvbiAocCwgJGVsLCBlcnJvcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBwY3QgPSBNYXRoLm1pbihwLCAxMDApLCBvdXQsIHBjdExpbWl0ID0gc2VsZi5wcm9ncmVzc1VwbG9hZFRocmVzaG9sZCxcbiAgICAgICAgICAgICAgICB0ID0gcCA8PSAxMDAgPyBzZWxmLnByb2dyZXNzVGVtcGxhdGUgOiBzZWxmLnByb2dyZXNzQ29tcGxldGVUZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZSA9IHBjdCA8IDEwMCA/IHNlbGYucHJvZ3Jlc3NUZW1wbGF0ZSA6IChlcnJvciA/IHNlbGYucHJvZ3Jlc3NFcnJvclRlbXBsYXRlIDogdCk7XG4gICAgICAgICAgICAkZWwgPSAkZWwgfHwgc2VsZi4kcHJvZ3Jlc3M7XG4gICAgICAgICAgICBpZiAoISRoLmlzRW1wdHkodGVtcGxhdGUpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBjdExpbWl0ICYmIHBjdCA+IHBjdExpbWl0ICYmIHAgPD0gMTAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7J3BlcmNlbnQnOiBwY3RMaW1pdCwgJ3N0YXR1cyc6IHNlbGYubXNnVXBsb2FkVGhyZXNob2xkfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0ID0gdGVtcGxhdGUuc2V0VG9rZW5zKHsncGVyY2VudCc6IHBjdCwgJ3N0YXR1cyc6IChwID4gMTAwID8gc2VsZi5tc2dVcGxvYWRFbmQgOiBwY3QgKyAnJScpfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICRlbC5odG1sKG91dCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICRlbC5maW5kKCdbcm9sZT1cInByb2dyZXNzYmFyXCJdJykuaHRtbChlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBfc2V0RmlsZURyb3Bab25lVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJHpvbmUgPSBzZWxmLiRjb250YWluZXIuZmluZCgnLmZpbGUtZHJvcC16b25lJyksIHRpdGxlID0gc2VsZi5kcm9wWm9uZVRpdGxlLCBzdHJGaWxlcztcbiAgICAgICAgICAgIGlmIChzZWxmLmlzQ2xpY2thYmxlKSB7XG4gICAgICAgICAgICAgICAgc3RyRmlsZXMgPSAkaC5pc0VtcHR5KHNlbGYuJGVsZW1lbnQuYXR0cignbXVsdGlwbGUnKSkgPyBzZWxmLmZpbGVTaW5nbGUgOiBzZWxmLmZpbGVQbHVyYWw7XG4gICAgICAgICAgICAgICAgdGl0bGUgKz0gc2VsZi5kcm9wWm9uZUNsaWNrVGl0bGUucmVwbGFjZSgne2ZpbGVzfScsIHN0ckZpbGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR6b25lLmZpbmQoJy4nICsgc2VsZi5kcm9wWm9uZVRpdGxlQ2xhc3MpLnJlbW92ZSgpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSB8fCAhc2VsZi5zaG93UHJldmlldyB8fCAkem9uZS5sZW5ndGggPT09IDAgfHwgc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGggPiAwIHx8ICFzZWxmLmRyb3Bab25lRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkem9uZS5maW5kKCRoLkZSQU1FUykubGVuZ3RoID09PSAwICYmICRoLmlzRW1wdHkoc2VsZi5kZWZhdWx0UHJldmlld0NvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgJHpvbmUucHJlcGVuZCgnPGRpdiBjbGFzcz1cIicgKyBzZWxmLmRyb3Bab25lVGl0bGVDbGFzcyArICdcIj4nICsgdGl0bGUgKyAnPC9kaXY+Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnZmlsZS1pbnB1dC1hamF4LW5ldycpO1xuICAgICAgICB9LFxuICAgICAgICBfc2V0QXN5bmNVcGxvYWRTdGF0dXM6IGZ1bmN0aW9uIChwcmV2aWV3SWQsIHBjdCwgdG90YWwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgc3VtID0gMDtcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKHBjdCwgJCgnIycgKyBwcmV2aWV3SWQpLmZpbmQoJy5maWxlLXRodW1iLXByb2dyZXNzJykpO1xuICAgICAgICAgICAgc2VsZi51cGxvYWRTdGF0dXNbcHJldmlld0lkXSA9IHBjdDtcbiAgICAgICAgICAgICQuZWFjaChzZWxmLnVwbG9hZFN0YXR1cywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzdW0gKz0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNlbGYuX3NldFByb2dyZXNzKE1hdGguZmxvb3Ioc3VtIC8gdG90YWwpKTtcblxuICAgICAgICB9LFxuICAgICAgICBfdmFsaWRhdGVNaW5Db3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsZW4gPSBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoIDogc2VsZi4kZWxlbWVudC5nZXQoMCkuZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHNlbGYudmFsaWRhdGVJbml0aWFsQ291bnQgJiYgc2VsZi5taW5GaWxlQ291bnQgPiAwICYmIHNlbGYuX2dldEZpbGVDb3VudChsZW4gLSAxKSA8IHNlbGYubWluRmlsZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fbm9GaWxlc0Vycm9yKHt9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZpbGVDb3VudDogZnVuY3Rpb24gKGZpbGVDb3VudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBhZGRDb3VudCA9IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi52YWxpZGF0ZUluaXRpYWxDb3VudCAmJiAhc2VsZi5vdmVyd3JpdGVJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgYWRkQ291bnQgPSBzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpO1xuICAgICAgICAgICAgICAgIGZpbGVDb3VudCArPSBhZGRDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmaWxlQ291bnQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlSWQ6IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGN1c3RvbSA9IHNlbGYuZ2VuZXJhdGVGaWxlSWQsIHJlbGF0aXZlUGF0aDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VzdG9tID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN1c3RvbShmaWxlLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qKiBAbmFtZXNwYWNlIGZpbGUud2Via2l0UmVsYXRpdmVQYXRoICovXG4gICAgICAgICAgICByZWxhdGl2ZVBhdGggPSBmaWxlLndlYmtpdFJlbGF0aXZlUGF0aCB8fCBmaWxlLmZpbGVOYW1lIHx8IGZpbGUubmFtZSB8fCBudWxsO1xuICAgICAgICAgICAgaWYgKCFyZWxhdGl2ZVBhdGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoZmlsZS5zaXplICsgJy0nICsgcmVsYXRpdmVQYXRoLnJlcGxhY2UoL1teMC05YS16QS1aXy1dL2ltZywgJycpKTtcbiAgICAgICAgfSxcbiAgICAgICAgX2dldEZpbGVOYW1lOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZpbGUgJiYgZmlsZS5uYW1lID8gdGhpcy5zbHVnKGZpbGUubmFtZSkgOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIF9nZXRGaWxlSWRzOiBmdW5jdGlvbiAoc2tpcE51bGwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmZpbGVpZHMuZmlsdGVyKGZ1bmN0aW9uIChuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChza2lwTnVsbCA/IG4gIT09IHVuZGVmaW5lZCA6IG4gIT09IHVuZGVmaW5lZCAmJiBuICE9PSBudWxsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfZ2V0RmlsZU5hbWVzOiBmdW5jdGlvbiAoc2tpcE51bGwpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLmZpbGVuYW1lcy5maWx0ZXIoZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHNraXBOdWxsID8gbiAhPT0gdW5kZWZpbmVkIDogbiAhPT0gdW5kZWZpbmVkICYmIG4gIT09IG51bGwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRQcmV2aWV3RXJyb3I6IGZ1bmN0aW9uICgkdGh1bWIsIGksIHZhbCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKGkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHNlbGYudXBkYXRlU3RhY2soaSwgdmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLnJlbW92ZUZyb21QcmV2aWV3T25FcnJvcikge1xuICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2V0VGh1bWJTdGF0dXMoJHRodW1iLCAnRXJyb3InKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2NoZWNrRGltZW5zaW9uczogZnVuY3Rpb24gKGksIGNoaywgJGltZywgJHRodW1iLCBmbmFtZSwgdHlwZSwgcGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIG1zZywgZGltLCB0YWcgPSBjaGsgPT09ICdTbWFsbCcgPyAnbWluJyA6ICdtYXgnLCBsaW1pdCA9IHNlbGZbdGFnICsgJ0ltYWdlJyArIHR5cGVdLFxuICAgICAgICAgICAgICAgICRpbWdFbCwgaXNWYWxpZDtcbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KGxpbWl0KSB8fCAhJGltZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaW1nRWwgPSAkaW1nWzBdO1xuICAgICAgICAgICAgZGltID0gKHR5cGUgPT09ICdXaWR0aCcpID8gJGltZ0VsLm5hdHVyYWxXaWR0aCB8fCAkaW1nRWwud2lkdGggOiAkaW1nRWwubmF0dXJhbEhlaWdodCB8fCAkaW1nRWwuaGVpZ2h0O1xuICAgICAgICAgICAgaXNWYWxpZCA9IGNoayA9PT0gJ1NtYWxsJyA/IGRpbSA+PSBsaW1pdCA6IGRpbSA8PSBsaW1pdDtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbXNnID0gc2VsZlsnbXNnSW1hZ2UnICsgdHlwZSArIGNoa10uc2V0VG9rZW5zKHsnbmFtZSc6IGZuYW1lLCAnc2l6ZSc6IGxpbWl0fSk7XG4gICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3IobXNnLCBwYXJhbXMpO1xuICAgICAgICAgICAgc2VsZi5fc2V0UHJldmlld0Vycm9yKCR0aHVtYiwgaSwgbnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIF92YWxpZGF0ZUltYWdlOiBmdW5jdGlvbiAocHJldmlld0lkLCBmbmFtZSwgZnR5cGUsIGZzaXplLCBpRGF0YSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkcHJldmlldyA9IHNlbGYuJHByZXZpZXcsIHBhcmFtcywgdzEsIHcyLCAkdGh1bWIgPSAkcHJldmlldy5maW5kKFwiI1wiICsgcHJldmlld0lkKSxcbiAgICAgICAgICAgICAgICBpID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4JyksICRpbWcgPSAkdGh1bWIuZmluZCgnaW1nJyksIGV4aWZPYmplY3Q7XG4gICAgICAgICAgICBmbmFtZSA9IGZuYW1lIHx8ICdVbnRpdGxlZCc7XG4gICAgICAgICAgICAkaW1nLm9uZSgnbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB3MSA9ICR0aHVtYi53aWR0aCgpO1xuICAgICAgICAgICAgICAgIHcyID0gJHByZXZpZXcud2lkdGgoKTtcbiAgICAgICAgICAgICAgICBpZiAodzEgPiB3Mikge1xuICAgICAgICAgICAgICAgICAgICAkaW1nLmNzcygnd2lkdGgnLCAnMTAwJScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJhbXMgPSB7aW5kOiBpLCBpZDogcHJldmlld0lkfTtcbiAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ1NtYWxsJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ1dpZHRoJywgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ1NtYWxsJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ0hlaWdodCcsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLnJlc2l6ZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX2NoZWNrRGltZW5zaW9ucyhpLCAnTGFyZ2UnLCAkaW1nLCAkdGh1bWIsIGZuYW1lLCAnV2lkdGgnLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9jaGVja0RpbWVuc2lvbnMoaSwgJ0xhcmdlJywgJGltZywgJHRodW1iLCBmbmFtZSwgJ0hlaWdodCcsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2Vsb2FkZWQnLCBbcHJldmlld0lkXSk7XG4gICAgICAgICAgICAgICAgZXhpZk9iamVjdCA9IHdpbmRvdy5waWV4aWYgPyB3aW5kb3cucGlleGlmLmxvYWQoaURhdGEpIDogbnVsbDtcbiAgICAgICAgICAgICAgICBzZWxmLmxvYWRlZEltYWdlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgaW5kOiBpLFxuICAgICAgICAgICAgICAgICAgICBpbWc6ICRpbWcsXG4gICAgICAgICAgICAgICAgICAgIHRodW1iOiAkdGh1bWIsXG4gICAgICAgICAgICAgICAgICAgIHBpZDogcHJldmlld0lkLFxuICAgICAgICAgICAgICAgICAgICB0eXA6IGZ0eXBlLFxuICAgICAgICAgICAgICAgICAgICBzaXo6IGZzaXplLFxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBpbWdEYXRhOiBpRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgZXhpZk9iajogZXhpZk9iamVjdFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICR0aHVtYi5kYXRhKCdleGlmJywgZXhpZk9iamVjdCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVBbGxJbWFnZXMoKTtcbiAgICAgICAgICAgIH0pLm9uZSgnZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZWxvYWRlcnJvcicsIFtwcmV2aWV3SWRdKTtcbiAgICAgICAgICAgIH0pLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcykudHJpZ2dlcignbG9hZCcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKHRoaXMpLnRyaWdnZXIoJ2Vycm9yJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgX3ZhbGlkYXRlQWxsSW1hZ2VzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGksIGNvdW50ZXIgPSB7dmFsOiAwfSwgbnVtSW1ncyA9IHNlbGYubG9hZGVkSW1hZ2VzLmxlbmd0aCwgY29uZmlnLFxuICAgICAgICAgICAgICAgIGZzaXplLCBtaW5TaXplID0gc2VsZi5yZXNpemVJZlNpemVNb3JlVGhhbjtcbiAgICAgICAgICAgIGlmIChudW1JbWdzICE9PSBzZWxmLnRvdGFsSW1hZ2VzQ291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlc2xvYWRlZCcpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnJlc2l6ZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGYubG9hZGVkSW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnID0gc2VsZi5sb2FkZWRJbWFnZXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy52YWxpZGF0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZzaXplID0gY29uZmlnLnNpejtcbiAgICAgICAgICAgICAgICBpZiAoZnNpemUgJiYgZnNpemUgPiBtaW5TaXplICogMTAwMCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9nZXRSZXNpemVkSW1hZ2UoY29uZmlnLCBjb3VudGVyLCBudW1JbWdzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5sb2FkZWRJbWFnZXNbaV0udmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2dldFJlc2l6ZWRJbWFnZTogZnVuY3Rpb24gKGNvbmZpZywgY291bnRlciwgbnVtSW1ncykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpbWcgPSAkKGNvbmZpZy5pbWcpWzBdLCB3aWR0aCA9IGltZy5uYXR1cmFsV2lkdGgsIGhlaWdodCA9IGltZy5uYXR1cmFsSGVpZ2h0LCBibG9iLFxuICAgICAgICAgICAgICAgIHJhdGlvID0gMSwgbWF4V2lkdGggPSBzZWxmLm1heEltYWdlV2lkdGggfHwgd2lkdGgsIG1heEhlaWdodCA9IHNlbGYubWF4SW1hZ2VIZWlnaHQgfHwgaGVpZ2h0LFxuICAgICAgICAgICAgICAgIGlzVmFsaWRJbWFnZSA9ICEhKHdpZHRoICYmIGhlaWdodCksIGNoa1dpZHRoLCBjaGtIZWlnaHQsIGNhbnZhcyA9IHNlbGYuaW1hZ2VDYW52YXMsIGRhdGFVUkksXG4gICAgICAgICAgICAgICAgY29udGV4dCA9IHNlbGYuaW1hZ2VDYW52YXNDb250ZXh0LCB0eXBlID0gY29uZmlnLnR5cCwgcGlkID0gY29uZmlnLnBpZCwgaW5kID0gY29uZmlnLmluZCxcbiAgICAgICAgICAgICAgICAkdGh1bWIgPSBjb25maWcudGh1bWIsIHRocm93RXJyb3IsIG1zZywgZXhpZk9iaiA9IGNvbmZpZy5leGlmT2JqLCBleGlmU3RyO1xuICAgICAgICAgICAgdGhyb3dFcnJvciA9IGZ1bmN0aW9uIChtc2csIHBhcmFtcywgZXYpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKG1zZywgcGFyYW1zLCBldik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2hvd0Vycm9yKG1zZywgcGFyYW1zLCBldik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuX3NldFByZXZpZXdFcnJvcigkdGh1bWIsIGluZCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCFzZWxmLmZpbGVzdGFja1tpbmRdIHx8ICFpc1ZhbGlkSW1hZ2UgfHwgKHdpZHRoIDw9IG1heFdpZHRoICYmIGhlaWdodCA8PSBtYXhIZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRJbWFnZSAmJiBzZWxmLmZpbGVzdGFja1tpbmRdKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VyZXNpemVkJywgW3BpZCwgaW5kXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvdW50ZXIudmFsKys7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIudmFsID09PSBudW1JbWdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VzcmVzaXplZCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRJbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvd0Vycm9yKHNlbGYubXNnSW1hZ2VSZXNpemVFcnJvciwge2lkOiBwaWQsICdpbmRleCc6IGluZH0sICdmaWxlaW1hZ2VyZXNpemVlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHlwZSA9IHR5cGUgfHwgc2VsZi5yZXNpemVEZWZhdWx0SW1hZ2VUeXBlO1xuICAgICAgICAgICAgY2hrV2lkdGggPSB3aWR0aCA+IG1heFdpZHRoO1xuICAgICAgICAgICAgY2hrSGVpZ2h0ID0gaGVpZ2h0ID4gbWF4SGVpZ2h0O1xuICAgICAgICAgICAgaWYgKHNlbGYucmVzaXplUHJlZmVyZW5jZSA9PT0gJ3dpZHRoJykge1xuICAgICAgICAgICAgICAgIHJhdGlvID0gY2hrV2lkdGggPyBtYXhXaWR0aCAvIHdpZHRoIDogKGNoa0hlaWdodCA/IG1heEhlaWdodCAvIGhlaWdodCA6IDEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByYXRpbyA9IGNoa0hlaWdodCA/IG1heEhlaWdodCAvIGhlaWdodCA6IChjaGtXaWR0aCA/IG1heFdpZHRoIC8gd2lkdGggOiAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0Q2FudmFzKCk7XG4gICAgICAgICAgICB3aWR0aCAqPSByYXRpbztcbiAgICAgICAgICAgIGhlaWdodCAqPSByYXRpbztcbiAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5kcmF3SW1hZ2UoaW1nLCAwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBkYXRhVVJJID0gY2FudmFzLnRvRGF0YVVSTCh0eXBlLCBzZWxmLnJlc2l6ZVF1YWxpdHkpO1xuICAgICAgICAgICAgICAgIGlmIChleGlmT2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aWZTdHIgPSB3aW5kb3cucGlleGlmLmR1bXAoZXhpZk9iaik7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFVUkkgPSB3aW5kb3cucGlleGlmLmluc2VydChleGlmU3RyLCBkYXRhVVJJKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYmxvYiA9ICRoLmRhdGFVUkkyQmxvYihkYXRhVVJJKTtcbiAgICAgICAgICAgICAgICBzZWxmLmZpbGVzdGFja1tpbmRdID0gYmxvYjtcbiAgICAgICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWltYWdlcmVzaXplZCcsIFtwaWQsIGluZF0pO1xuICAgICAgICAgICAgICAgIGNvdW50ZXIudmFsKys7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ZXIudmFsID09PSBudW1JbWdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlaW1hZ2VzcmVzaXplZCcsIFt1bmRlZmluZWQsIHVuZGVmaW5lZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIShibG9iIGluc3RhbmNlb2YgQmxvYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3dFcnJvcihzZWxmLm1zZ0ltYWdlUmVzaXplRXJyb3IsIHtpZDogcGlkLCAnaW5kZXgnOiBpbmR9LCAnZmlsZWltYWdlcmVzaXplZXJyb3InKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY291bnRlci52YWwrKztcbiAgICAgICAgICAgICAgICBpZiAoY291bnRlci52YWwgPT09IG51bUltZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVpbWFnZXNyZXNpemVkJywgW3VuZGVmaW5lZCwgdW5kZWZpbmVkXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnSW1hZ2VSZXNpemVFeGNlcHRpb24ucmVwbGFjZSgne2Vycm9yc30nLCBlcnIubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgdGhyb3dFcnJvcihtc2csIHtpZDogcGlkLCAnaW5kZXgnOiBpbmR9LCAnZmlsZWltYWdlcmVzaXplZXhjZXB0aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIF9pbml0QnJvd3NlOiBmdW5jdGlvbiAoJGNvbnRhaW5lcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd0Jyb3dzZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGJ0bkZpbGUgPSAkY29udGFpbmVyLmZpbmQoJy5idG4tZmlsZScpO1xuICAgICAgICAgICAgICAgIHNlbGYuJGJ0bkZpbGUuYXBwZW5kKHNlbGYuJGVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRlbGVtZW50LmhpZGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgX2luaXRDYXB0aW9uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcCA9IHNlbGYuaW5pdGlhbENhcHRpb24gfHwgJyc7XG4gICAgICAgICAgICBpZiAoc2VsZi5vdmVyd3JpdGVJbml0aWFsIHx8ICRoLmlzRW1wdHkoY2FwKSkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbCgnJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fc2V0Q2FwdGlvbihjYXApO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIF9zZXRDYXB0aW9uOiBmdW5jdGlvbiAoY29udGVudCwgaXNFcnJvcikge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0aXRsZSwgb3V0LCBuLCBjYXAsIHN0YWNrID0gc2VsZi5nZXRGaWxlU3RhY2soKTtcbiAgICAgICAgICAgIGlmICghc2VsZi4kY2FwdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNFcnJvcikge1xuICAgICAgICAgICAgICAgIHRpdGxlID0gJCgnPGRpdj4nICsgc2VsZi5tc2dWYWxpZGF0aW9uRXJyb3IgKyAnPC9kaXY+JykudGV4dCgpO1xuICAgICAgICAgICAgICAgIG4gPSBzdGFjay5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FwID0gbiA9PT0gMSAmJiBzdGFja1swXSA/IHNlbGYuX2dldEZpbGVOYW1lcygpWzBdIDogc2VsZi5fZ2V0TXNnU2VsZWN0ZWQobik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2FwID0gc2VsZi5fZ2V0TXNnU2VsZWN0ZWQoc2VsZi5tc2dObyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG91dCA9ICc8c3BhbiBjbGFzcz1cIicgKyBzZWxmLm1zZ1ZhbGlkYXRpb25FcnJvckNsYXNzICsgJ1wiPicgKyBzZWxmLm1zZ1ZhbGlkYXRpb25FcnJvckljb24gK1xuICAgICAgICAgICAgICAgICAgICAoJGguaXNFbXB0eShjb250ZW50KSA/IGNhcCA6IGNvbnRlbnQpICsgJzwvc3Bhbj4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoJGguaXNFbXB0eShjb250ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRpdGxlID0gJCgnPGRpdj4nICsgY29udGVudCArICc8L2Rpdj4nKS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2ZpbGVJY29uJykgKyB0aXRsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbChvdXQpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbi5hdHRyKCd0aXRsZScsIHRpdGxlKTtcbiAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmZpbGUtY2FwdGlvbi1lbGxpcHNpcycpLmF0dHIoJ3RpdGxlJywgdGl0bGUpO1xuICAgICAgICB9LFxuICAgICAgICBfY3JlYXRlQ29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGF0dHJpYnMgPSB7XCJjbGFzc1wiOiAnZmlsZS1pbnB1dCBmaWxlLWlucHV0LW5ldycgKyAoc2VsZi5ydGwgPyAnIGt2LXJ0bCcgOiAnJyl9LFxuICAgICAgICAgICAgICAgICRjb250YWluZXIgPSAkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIikpLmF0dHIoYXR0cmlicykuaHRtbChzZWxmLl9yZW5kZXJNYWluKCkpO1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5iZWZvcmUoJGNvbnRhaW5lcik7XG4gICAgICAgICAgICBzZWxmLl9pbml0QnJvd3NlKCRjb250YWluZXIpO1xuICAgICAgICAgICAgaWYgKHNlbGYudGhlbWUpIHtcbiAgICAgICAgICAgICAgICAkY29udGFpbmVyLmFkZENsYXNzKCd0aGVtZS0nICsgc2VsZi50aGVtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJGNvbnRhaW5lcjtcbiAgICAgICAgfSxcbiAgICAgICAgX3JlZnJlc2hDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGNvbnRhaW5lciA9IHNlbGYuJGNvbnRhaW5lcjtcbiAgICAgICAgICAgICRjb250YWluZXIuYmVmb3JlKHNlbGYuJGVsZW1lbnQpO1xuICAgICAgICAgICAgJGNvbnRhaW5lci5odG1sKHNlbGYuX3JlbmRlck1haW4oKSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0QnJvd3NlKCRjb250YWluZXIpO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyTWFpbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgICAgICAgIGRyb3BDc3MgPSAoc2VsZi5pc1VwbG9hZGFibGUgJiYgc2VsZi5kcm9wWm9uZUVuYWJsZWQpID8gJyBmaWxlLWRyb3Atem9uZScgOiAnZmlsZS1kcm9wLWRpc2FibGVkJyxcbiAgICAgICAgICAgICAgICBjbG9zZSA9ICFzZWxmLnNob3dDbG9zZSA/ICcnIDogc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Nsb3NlJyksXG4gICAgICAgICAgICAgICAgcHJldmlldyA9ICFzZWxmLnNob3dQcmV2aWV3ID8gJycgOiBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgncHJldmlldycpXG4gICAgICAgICAgICAgICAgICAgIC5zZXRUb2tlbnMoeydjbGFzcyc6IHNlbGYucHJldmlld0NsYXNzLCAnZHJvcENsYXNzJzogZHJvcENzc30pLFxuICAgICAgICAgICAgICAgIGNzcyA9IHNlbGYuaXNEaXNhYmxlZCA/IHNlbGYuY2FwdGlvbkNsYXNzICsgJyBmaWxlLWNhcHRpb24tZGlzYWJsZWQnIDogc2VsZi5jYXB0aW9uQ2xhc3MsXG4gICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNlbGYuY2FwdGlvblRlbXBsYXRlLnNldFRva2Vucyh7J2NsYXNzJzogY3NzICsgJyBrdi1maWxlaW5wdXQtY2FwdGlvbid9KTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLm1haW5UZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6IHNlbGYubWFpbkNsYXNzICsgKCFzZWxmLnNob3dCcm93c2UgJiYgc2VsZi5zaG93Q2FwdGlvbiA/ICcgbm8tYnJvd3NlJyA6ICcnKSxcbiAgICAgICAgICAgICAgICAncHJldmlldyc6IHByZXZpZXcsXG4gICAgICAgICAgICAgICAgJ2Nsb3NlJzogY2xvc2UsXG4gICAgICAgICAgICAgICAgJ2NhcHRpb24nOiBjYXB0aW9uLFxuICAgICAgICAgICAgICAgICd1cGxvYWQnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ3VwbG9hZCcpLFxuICAgICAgICAgICAgICAgICdyZW1vdmUnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ3JlbW92ZScpLFxuICAgICAgICAgICAgICAgICdjYW5jZWwnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ2NhbmNlbCcpLFxuICAgICAgICAgICAgICAgICdicm93c2UnOiBzZWxmLl9yZW5kZXJCdXR0b24oJ2Jyb3dzZScpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyQnV0dG9uOiBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0bXBsdCA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdidG5EZWZhdWx0JyksIGNzcyA9IHNlbGZbdHlwZSArICdDbGFzcyddLFxuICAgICAgICAgICAgICAgIHRpdGxlID0gc2VsZlt0eXBlICsgJ1RpdGxlJ10sIGljb24gPSBzZWxmW3R5cGUgKyAnSWNvbiddLCBsYWJlbCA9IHNlbGZbdHlwZSArICdMYWJlbCddLFxuICAgICAgICAgICAgICAgIHN0YXR1cyA9IHNlbGYuaXNEaXNhYmxlZCA/ICcgZGlzYWJsZWQnIDogJycsIGJ0blR5cGUgPSAnYnV0dG9uJztcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JlbW92ZSc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2FuY2VsJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjc3MgKz0gJyBoaWRlJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndXBsb2FkJzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLnNob3dVcGxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5pc1VwbG9hZGFibGUgJiYgIXNlbGYuaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG1wbHQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYnRuTGluaycpLnJlcGxhY2UoJ3tocmVmfScsIHNlbGYudXBsb2FkVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ0blR5cGUgPSAnc3VibWl0JztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdicm93c2UnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbGYuc2hvd0Jyb3dzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRtcGx0ID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2J0bkJyb3dzZScpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNzcyArPSB0eXBlID09PSAnYnJvd3NlJyA/ICcgYnRuLWZpbGUnIDogJyBmaWxlaW5wdXQtJyArIHR5cGUgKyAnIGZpbGVpbnB1dC0nICsgdHlwZSArICctYnV0dG9uJztcbiAgICAgICAgICAgIGlmICghJGguaXNFbXB0eShsYWJlbCkpIHtcbiAgICAgICAgICAgICAgICBsYWJlbCA9ICcgPHNwYW4gY2xhc3M9XCInICsgc2VsZi5idXR0b25MYWJlbENsYXNzICsgJ1wiPicgKyBsYWJlbCArICc8L3NwYW4+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0bXBsdC5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICd0eXBlJzogYnRuVHlwZSwgJ2Nzcyc6IGNzcywgJ3RpdGxlJzogdGl0bGUsICdzdGF0dXMnOiBzdGF0dXMsICdpY29uJzogaWNvbiwgJ2xhYmVsJzogbGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyVGh1bWJQcm9ncmVzczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuICc8ZGl2IGNsYXNzPVwiZmlsZS10aHVtYi1wcm9ncmVzcyBoaWRlXCI+JyArXG4gICAgICAgICAgICAgICAgc2VsZi5wcm9ncmVzc1RlbXBsYXRlLnNldFRva2Vucyh7J3BlcmNlbnQnOiAnMCcsICdzdGF0dXMnOiBzZWxmLm1zZ1VwbG9hZEJlZ2lufSkgK1xuICAgICAgICAgICAgICAgICc8L2Rpdj4nO1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyRmlsZUZvb3RlcjogZnVuY3Rpb24gKGNhcHRpb24sIHNpemUsIHdpZHRoLCBpc0Vycm9yKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNvbmZpZyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLCByZW0gPSBjb25maWcuc2hvd1JlbW92ZSwgZHJnID0gY29uZmlnLnNob3dEcmFnLFxuICAgICAgICAgICAgICAgIHVwbCA9IGNvbmZpZy5zaG93VXBsb2FkLCB6b29tID0gY29uZmlnLnNob3dab29tLCBvdXQsIHRlbXBsYXRlID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2Zvb3RlcicpLFxuICAgICAgICAgICAgICAgIGluZCA9IGlzRXJyb3IgPyBjb25maWcuaW5kaWNhdG9yRXJyb3IgOiBjb25maWcuaW5kaWNhdG9yTmV3LFxuICAgICAgICAgICAgICAgIHRJbmQgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnaW5kaWNhdG9yJyksXG4gICAgICAgICAgICAgICAgdGl0bGUgPSBpc0Vycm9yID8gY29uZmlnLmluZGljYXRvckVycm9yVGl0bGUgOiBjb25maWcuaW5kaWNhdG9yTmV3VGl0bGUsXG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gdEluZC5zZXRUb2tlbnMoeydpbmRpY2F0b3InOiBpbmQsICdpbmRpY2F0b3JUaXRsZSc6IHRpdGxlfSk7XG4gICAgICAgICAgICBzaXplID0gc2VsZi5fZ2V0U2l6ZShzaXplKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdhY3Rpb25zJzogc2VsZi5fcmVuZGVyRmlsZUFjdGlvbnModXBsLCByZW0sIHpvb20sIGRyZywgZmFsc2UsIGZhbHNlLCBmYWxzZSksXG4gICAgICAgICAgICAgICAgICAgICdjYXB0aW9uJzogY2FwdGlvbixcbiAgICAgICAgICAgICAgICAgICAgJ3NpemUnOiBzaXplLFxuICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiB3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgJ3Byb2dyZXNzJzogc2VsZi5fcmVuZGVyVGh1bWJQcm9ncmVzcygpLFxuICAgICAgICAgICAgICAgICAgICAnaW5kaWNhdG9yJzogaW5kaWNhdG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dCA9IHRlbXBsYXRlLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdhY3Rpb25zJzogc2VsZi5fcmVuZGVyRmlsZUFjdGlvbnMoZmFsc2UsIGZhbHNlLCB6b29tLCBkcmcsIGZhbHNlLCBmYWxzZSwgZmFsc2UpLFxuICAgICAgICAgICAgICAgICAgICAnY2FwdGlvbic6IGNhcHRpb24sXG4gICAgICAgICAgICAgICAgICAgICdzaXplJzogc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICdwcm9ncmVzcyc6ICcnLFxuICAgICAgICAgICAgICAgICAgICAnaW5kaWNhdG9yJzogaW5kaWNhdG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvdXQgPSAkaC5yZXBsYWNlVGFncyhvdXQsIHNlbGYucHJldmlld1RodW1iVGFncyk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9LFxuICAgICAgICBfcmVuZGVyRmlsZUFjdGlvbnM6IGZ1bmN0aW9uIChzaG93VXBsb2FkLCBzaG93RGVsZXRlLCBzaG93Wm9vbSwgc2hvd0RyYWcsIGRpc2FibGVkLCB1cmwsIGtleSwgaXNJbml0KSB7XG4gICAgICAgICAgICBpZiAoIXNob3dVcGxvYWQgJiYgIXNob3dEZWxldGUgJiYgIXNob3dab29tICYmICFzaG93RHJhZykge1xuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgdlVybCA9IHVybCA9PT0gZmFsc2UgPyAnJyA6ICcgZGF0YS11cmw9XCInICsgdXJsICsgJ1wiJyxcbiAgICAgICAgICAgICAgICB2S2V5ID0ga2V5ID09PSBmYWxzZSA/ICcnIDogJyBkYXRhLWtleT1cIicgKyBrZXkgKyAnXCInLFxuICAgICAgICAgICAgICAgIGJ0bkRlbGV0ZSA9ICcnLCBidG5VcGxvYWQgPSAnJywgYnRuWm9vbSA9ICcnLCBidG5EcmFnID0gJycsIGNzcyxcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZSA9IHNlbGYuX2dldExheW91dFRlbXBsYXRlKCdhY3Rpb25zJyksIGNvbmZpZyA9IHNlbGYuZmlsZUFjdGlvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgIG90aGVyQnV0dG9ucyA9IHNlbGYub3RoZXJBY3Rpb25CdXR0b25zLnNldFRva2Vucyh7J2RhdGFLZXknOiB2S2V5fSksXG4gICAgICAgICAgICAgICAgcmVtb3ZlQ2xhc3MgPSBkaXNhYmxlZCA/IGNvbmZpZy5yZW1vdmVDbGFzcyArICcgZGlzYWJsZWQnIDogY29uZmlnLnJlbW92ZUNsYXNzO1xuICAgICAgICAgICAgaWYgKHNob3dEZWxldGUpIHtcbiAgICAgICAgICAgICAgICBidG5EZWxldGUgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYWN0aW9uRGVsZXRlJykuc2V0VG9rZW5zKHtcbiAgICAgICAgICAgICAgICAgICAgJ3JlbW92ZUNsYXNzJzogcmVtb3ZlQ2xhc3MsXG4gICAgICAgICAgICAgICAgICAgICdyZW1vdmVJY29uJzogY29uZmlnLnJlbW92ZUljb24sXG4gICAgICAgICAgICAgICAgICAgICdyZW1vdmVUaXRsZSc6IGNvbmZpZy5yZW1vdmVUaXRsZSxcbiAgICAgICAgICAgICAgICAgICAgJ2RhdGFVcmwnOiB2VXJsLFxuICAgICAgICAgICAgICAgICAgICAnZGF0YUtleSc6IHZLZXlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzaG93VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgYnRuVXBsb2FkID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvblVwbG9hZCcpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICd1cGxvYWRDbGFzcyc6IGNvbmZpZy51cGxvYWRDbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgJ3VwbG9hZEljb24nOiBjb25maWcudXBsb2FkSWNvbixcbiAgICAgICAgICAgICAgICAgICAgJ3VwbG9hZFRpdGxlJzogY29uZmlnLnVwbG9hZFRpdGxlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hvd1pvb20pIHtcbiAgICAgICAgICAgICAgICBidG5ab29tID0gc2VsZi5fZ2V0TGF5b3V0VGVtcGxhdGUoJ2FjdGlvblpvb20nKS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICAgICAnem9vbUNsYXNzJzogY29uZmlnLnpvb21DbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgJ3pvb21JY29uJzogY29uZmlnLnpvb21JY29uLFxuICAgICAgICAgICAgICAgICAgICAnem9vbVRpdGxlJzogY29uZmlnLnpvb21UaXRsZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNob3dEcmFnICYmIGlzSW5pdCkge1xuICAgICAgICAgICAgICAgIGNzcyA9ICdkcmFnLWhhbmRsZS1pbml0ICcgKyBjb25maWcuZHJhZ0NsYXNzO1xuICAgICAgICAgICAgICAgIGJ0bkRyYWcgPSBzZWxmLl9nZXRMYXlvdXRUZW1wbGF0ZSgnYWN0aW9uRHJhZycpLnNldFRva2Vucyh7XG4gICAgICAgICAgICAgICAgICAgICdkcmFnQ2xhc3MnOiBjc3MsXG4gICAgICAgICAgICAgICAgICAgICdkcmFnVGl0bGUnOiBjb25maWcuZHJhZ1RpdGxlLFxuICAgICAgICAgICAgICAgICAgICAnZHJhZ0ljb24nOiBjb25maWcuZHJhZ0ljb25cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZS5zZXRUb2tlbnMoe1xuICAgICAgICAgICAgICAgICdkZWxldGUnOiBidG5EZWxldGUsXG4gICAgICAgICAgICAgICAgJ3VwbG9hZCc6IGJ0blVwbG9hZCxcbiAgICAgICAgICAgICAgICAnem9vbSc6IGJ0blpvb20sXG4gICAgICAgICAgICAgICAgJ2RyYWcnOiBidG5EcmFnLFxuICAgICAgICAgICAgICAgICdvdGhlcic6IG90aGVyQnV0dG9uc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIF9icm93c2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWJyb3dzZScpO1xuICAgICAgICAgICAgaWYgKGUgJiYgZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzRXJyb3IgJiYgIXNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5jbGVhcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lci5mb2N1cygpO1xuICAgICAgICB9LFxuICAgICAgICBfZmlsdGVyRHVwbGljYXRlOiBmdW5jdGlvbiAoZmlsZSwgZmlsZXMsIGZpbGVJZHMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgZmlsZUlkID0gc2VsZi5fZ2V0RmlsZUlkKGZpbGUpO1xuICAgICAgICAgICAgaWYgKGZpbGVJZCAmJiBmaWxlSWRzICYmIGZpbGVJZHMuaW5kZXhPZihmaWxlSWQpID4gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWZpbGVJZHMpIHtcbiAgICAgICAgICAgICAgICBmaWxlSWRzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgICAgICAgZmlsZUlkcy5wdXNoKGZpbGVJZCk7XG4gICAgICAgIH0sXG4gICAgICAgIF9jaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRlbCA9IHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgICAgICBpZiAoIXNlbGYuaXNVcGxvYWRhYmxlICYmICRoLmlzRW1wdHkoJGVsLnZhbCgpKSAmJiBzZWxmLmZpbGVJbnB1dENsZWFyZWQpIHsgLy8gSUUgMTEgZml4XG4gICAgICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5maWxlSW5wdXRDbGVhcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgdGZpbGVzID0gW10sIG1zZywgdG90YWwsIGlzRHJhZ0Ryb3AgPSBhcmd1bWVudHMubGVuZ3RoID4gMSwgaXNBamF4VXBsb2FkID0gc2VsZi5pc1VwbG9hZGFibGUsIG4sIGxlbixcbiAgICAgICAgICAgICAgICBmaWxlcyA9IGlzRHJhZ0Ryb3AgPyBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzIDogJGVsLmdldCgwKS5maWxlcywgY3RyID0gc2VsZi5maWxlc3RhY2subGVuZ3RoLFxuICAgICAgICAgICAgICAgIGlzU2luZ2xlVXBsb2FkID0gJGguaXNFbXB0eSgkZWwuYXR0cignbXVsdGlwbGUnKSksIGZsYWdTaW5nbGUgPSAoaXNTaW5nbGVVcGxvYWQgJiYgY3RyID4gMCksXG4gICAgICAgICAgICAgICAgZm9sZGVycyA9IDAsIGZpbGVJZHMgPSBzZWxmLl9nZXRGaWxlSWRzKCksIHRocm93RXJyb3IgPSBmdW5jdGlvbiAobWVzZywgZmlsZSwgcHJldmlld0lkLCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcDEgPSAkLmV4dGVuZCh0cnVlLCB7fSwgc2VsZi5fZ2V0T3V0RGF0YSh7fSwge30sIGZpbGVzKSwge2lkOiBwcmV2aWV3SWQsIGluZGV4OiBpbmRleH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgcDIgPSB7aWQ6IHByZXZpZXdJZCwgaW5kZXg6IGluZGV4LCBmaWxlOiBmaWxlLCBmaWxlczogZmlsZXN9O1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5pc1VwbG9hZGFibGUgPyBzZWxmLl9zaG93VXBsb2FkRXJyb3IobWVzZywgcDEpIDogc2VsZi5fc2hvd0Vycm9yKG1lc2csIHAyKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZi5yZWFkZXIgPSBudWxsO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIHNlbGYuX2hpZGVGaWxlSWNvbigpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlLWRyb3Atem9uZSAuJyArIHNlbGYuZHJvcFpvbmVUaXRsZUNsYXNzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0RyYWdEcm9wKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoaSwgZikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZiAmJiAhZi50eXBlICYmIGYuc2l6ZSAhPT0gdW5kZWZpbmVkICYmIGYuc2l6ZSAlIDQwOTYgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvbGRlcnMrKztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2ZpbHRlckR1cGxpY2F0ZShmLCB0ZmlsZXMsIGZpbGVJZHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChlLnRhcmdldCAmJiBlLnRhcmdldC5maWxlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzID0gZS50YXJnZXQudmFsdWUgPyBbe25hbWU6IGUudGFyZ2V0LnZhbHVlLnJlcGxhY2UoL14uK1xcXFwvLCAnJyl9XSA6IFtdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzID0gZS50YXJnZXQuZmlsZXMgfHwge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpc0FqYXhVcGxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoaSwgZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fZmlsdGVyRHVwbGljYXRlKGYsIHRmaWxlcywgZmlsZUlkcyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRmaWxlcyA9IGZpbGVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkaC5pc0VtcHR5KHRmaWxlcykgfHwgdGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNBamF4VXBsb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd0ZvbGRlckVycm9yKGZvbGRlcnMpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlc2VsZWN0bm9uZScpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKCk7XG4gICAgICAgICAgICBsZW4gPSB0ZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgdG90YWwgPSBzZWxmLl9nZXRGaWxlQ291bnQoc2VsZi5pc1VwbG9hZGFibGUgPyAoc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGggKyBsZW4pIDogbGVuKTtcbiAgICAgICAgICAgIGlmIChzZWxmLm1heEZpbGVDb3VudCA+IDAgJiYgdG90YWwgPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgIGlmICghc2VsZi5hdXRvUmVwbGFjZSB8fCBsZW4gPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICBuID0gKHNlbGYuYXV0b1JlcGxhY2UgJiYgbGVuID4gc2VsZi5tYXhGaWxlQ291bnQpID8gbGVuIDogdG90YWw7XG4gICAgICAgICAgICAgICAgICAgIG1zZyA9IHNlbGYubXNnRmlsZXNUb29NYW55LnJlcGxhY2UoJ3ttfScsIHNlbGYubWF4RmlsZUNvdW50KS5yZXBsYWNlKCd7bn0nLCBuKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pc0Vycm9yID0gdGhyb3dFcnJvcihtc2csIG51bGwsIG51bGwsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRjYXB0aW9uQ29udGFpbmVyLmZpbmQoJy5rdi1jYXB0aW9uLWljb24nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3NldENhcHRpb24oJycsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3IGZpbGUtaW5wdXQtYWpheC1uZXcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodG90YWwgPiBzZWxmLm1heEZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXdUaHVtYnMoaXNBamF4VXBsb2FkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghaXNBamF4VXBsb2FkIHx8IGZsYWdTaW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVzZXRQcmV2aWV3VGh1bWJzKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZsYWdTaW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQWpheFVwbG9hZCAmJiBjdHIgPT09IDAgJiYgKCFzZWxmLnByZXZpZXdDYWNoZS5jb3VudCgpIHx8IHNlbGYub3ZlcndyaXRlSW5pdGlhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0UHJldmlld1RodW1icyh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzUHJldmlld2FibGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZWFkRmlsZXModGZpbGVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fdXBkYXRlRmlsZURldGFpbHMoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zaG93Rm9sZGVyRXJyb3IoZm9sZGVycyk7XG4gICAgICAgIH0sXG4gICAgICAgIF9hYm9ydDogZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBkYXRhO1xuICAgICAgICAgICAgaWYgKHNlbGYuYWpheEFib3J0ZWQgJiYgdHlwZW9mIHNlbGYuYWpheEFib3J0ZWQgPT09IFwib2JqZWN0XCIgJiYgc2VsZi5hamF4QWJvcnRlZC5tZXNzYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gJC5leHRlbmQodHJ1ZSwge30sIHNlbGYuX2dldE91dERhdGEoKSwgcGFyYW1zKTtcbiAgICAgICAgICAgICAgICBkYXRhLmFib3J0RGF0YSA9IHNlbGYuYWpheEFib3J0ZWQuZGF0YSB8fCB7fTtcbiAgICAgICAgICAgICAgICBkYXRhLmFib3J0TWVzc2FnZSA9IHNlbGYuYWpheEFib3J0ZWQubWVzc2FnZTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygxMDEsIHNlbGYuJHByb2dyZXNzLCBzZWxmLm1zZ0NhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKHNlbGYuYWpheEFib3J0ZWQubWVzc2FnZSwgZGF0YSwgJ2ZpbGVjdXN0b21lcnJvcicpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0sXG4gICAgICAgIF9yZXNldEZpbGVTdGFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBpID0gMCwgbmV3c3RhY2sgPSBbXSwgbmV3bmFtZXMgPSBbXSwgbmV3aWRzID0gW107XG4gICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHRodW1iID0gJCh0aGlzKSwgaW5kID0gJHRodW1iLmF0dHIoJ2RhdGEtZmlsZWluZGV4JyksIGZpbGUgPSBzZWxmLmZpbGVzdGFja1tpbmRdLFxuICAgICAgICAgICAgICAgICAgICBwaWQgPSAkdGh1bWIuYXR0cignaWQnKSwgbmV3SWQ7XG4gICAgICAgICAgICAgICAgaWYgKGluZCA9PT0gJy0xJyB8fCBpbmQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZpbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdzdGFja1tpXSA9IGZpbGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld25hbWVzW2ldID0gc2VsZi5fZ2V0RmlsZU5hbWUoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld2lkc1tpXSA9IHNlbGYuX2dldEZpbGVJZChmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmF0dHIoeydpZCc6IHNlbGYucHJldmlld0luaXRJZCArICctJyArIGksICdkYXRhLWZpbGVpbmRleCc6IGl9KTtcbiAgICAgICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0lkID0gJ3VwbG9hZGVkLScgKyAkaC51bmlxSWQoKTtcbiAgICAgICAgICAgICAgICAgICAgJHRodW1iLmF0dHIoeydpZCc6IG5ld0lkLCAnZGF0YS1maWxlaW5kZXgnOiAnLTEnfSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuJHByZXZpZXcuZmluZCgnI3pvb20tJyArIHBpZCkuYXR0cignaWQnLCAnem9vbS0nICsgbmV3SWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5maWxlc3RhY2sgPSBuZXdzdGFjaztcbiAgICAgICAgICAgIHNlbGYuZmlsZW5hbWVzID0gbmV3bmFtZXM7XG4gICAgICAgICAgICBzZWxmLmZpbGVpZHMgPSBuZXdpZHM7XG4gICAgICAgIH0sXG4gICAgICAgIF9pc0ZpbGVTZWxlY3Rpb25WYWxpZDogZnVuY3Rpb24gKGNudCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgY250ID0gY250IHx8IDA7XG4gICAgICAgICAgICBpZiAoc2VsZi5yZXF1aXJlZCAmJiAhc2VsZi5nZXRGaWxlc0NvdW50KCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLiRlcnJvckNvbnRhaW5lci5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93VXBsb2FkRXJyb3Ioc2VsZi5tc2dGaWxlUmVxdWlyZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLm1pbkZpbGVDb3VudCA+IDAgJiYgc2VsZi5fZ2V0RmlsZUNvdW50KGNudCkgPCBzZWxmLm1pbkZpbGVDb3VudCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX25vRmlsZXNFcnJvcih7fSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFyU3RhY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuZmlsZXN0YWNrID0gW107XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lcyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzID0gW107XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgdXBkYXRlU3RhY2s6IGZ1bmN0aW9uIChpLCBmaWxlKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmZpbGVzdGFja1tpXSA9IGZpbGU7XG4gICAgICAgICAgICBzZWxmLmZpbGVuYW1lc1tpXSA9IHNlbGYuX2dldEZpbGVOYW1lKGZpbGUpO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzW2ldID0gZmlsZSAmJiBzZWxmLl9nZXRGaWxlSWQoZmlsZSkgfHwgbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBhZGRUb1N0YWNrOiBmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgc2VsZi5maWxlc3RhY2sucHVzaChmaWxlKTtcbiAgICAgICAgICAgIHNlbGYuZmlsZW5hbWVzLnB1c2goc2VsZi5fZ2V0RmlsZU5hbWUoZmlsZSkpO1xuICAgICAgICAgICAgc2VsZi5maWxlaWRzLnB1c2goc2VsZi5fZ2V0RmlsZUlkKGZpbGUpKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBnZXRGaWxlU3RhY2s6IGZ1bmN0aW9uIChza2lwTnVsbCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuZmlsZXN0YWNrLmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgICAgIHJldHVybiAoc2tpcE51bGwgPyBuICE9PSB1bmRlZmluZWQgOiBuICE9PSB1bmRlZmluZWQgJiYgbiAhPT0gbnVsbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0RmlsZXNDb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCBsZW4gPSBzZWxmLmlzVXBsb2FkYWJsZSA/IHNlbGYuZ2V0RmlsZVN0YWNrKCkubGVuZ3RoIDogc2VsZi4kZWxlbWVudC5nZXQoMCkuZmlsZXMubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuX2dldEZpbGVDb3VudChsZW4pO1xuICAgICAgICB9LFxuICAgICAgICBsb2NrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLl9yZXNldEVycm9ycygpO1xuICAgICAgICAgICAgc2VsZi5kaXNhYmxlKCk7XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LXJlbW92ZScpLCAnaGlkZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuc2hvd0NhbmNlbCkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LWNhbmNlbCcpLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZWxvY2snLCBbc2VsZi5maWxlc3RhY2ssIHNlbGYuX2dldEV4dHJhRGF0YSgpXSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgfSxcbiAgICAgICAgdW5sb2NrOiBmdW5jdGlvbiAocmVzZXQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmIChyZXNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmVzZXQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5lbmFibGUoKTtcbiAgICAgICAgICAgIGlmIChzZWxmLnNob3dDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtY2FuY2VsJyksICdoaWRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi5zaG93UmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoJy5maWxlaW5wdXQtcmVtb3ZlJykucmVtb3ZlQ2xhc3MoJ2hpZGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZXNldCkge1xuICAgICAgICAgICAgICAgIHNlbGYuX3Jlc2V0RmlsZVN0YWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yYWlzZSgnZmlsZXVubG9jaycsIFtzZWxmLmZpbGVzdGFjaywgc2VsZi5fZ2V0RXh0cmFEYXRhKCldKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgeGhyID0gc2VsZi5hamF4UmVxdWVzdHMsIGxlbiA9IHhoci5sZW5ndGgsIGk7XG4gICAgICAgICAgICBpZiAobGVuID4gMCkge1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmNhbmNlbGxpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB4aHJbaV0uYWJvcnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzc0NhbmNlbGxlZCgpO1xuICAgICAgICAgICAgc2VsZi5fZ2V0VGh1bWJzKCkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aHVtYiA9ICQodGhpcyksIGluZCA9ICR0aHVtYi5hdHRyKCdkYXRhLWZpbGVpbmRleCcpO1xuICAgICAgICAgICAgICAgICR0aHVtYi5yZW1vdmVDbGFzcygnZmlsZS11cGxvYWRpbmcnKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5maWxlc3RhY2tbaW5kXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aHVtYi5maW5kKCcua3YtZmlsZS11cGxvYWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKS5yZW1vdmVBdHRyKCdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAkdGh1bWIuZmluZCgnLmt2LWZpbGUtcmVtb3ZlJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJykucmVtb3ZlQXR0cignZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi51bmxvY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsIGNhcDtcbiAgICAgICAgICAgIGlmICghc2VsZi5fcmFpc2UoJ2ZpbGVjbGVhcicpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi4kYnRuVXBsb2FkLnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLl9nZXRUaHVtYnMoKS5maW5kKCd2aWRlbyxhdWRpbyxpbWcnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAkaC5jbGVhbk1lbW9yeSgkKHRoaXMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc2VsZi5fcmVzZXRVcGxvYWQoKTtcbiAgICAgICAgICAgIHNlbGYuY2xlYXJTdGFjaygpO1xuICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgIHNlbGYuX3Jlc2V0RXJyb3JzKHRydWUpO1xuICAgICAgICAgICAgaWYgKHNlbGYuX2hhc0luaXRpYWxQcmV2aWV3KCkpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl9zaG93RmlsZUljb24oKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXcoKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0FjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICBzZWxmLiRjb250YWluZXIucmVtb3ZlQ2xhc3MoJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuX2dldFRodW1icygpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9jbGVhck9iamVjdHMoJCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucHJldmlld0NhY2hlLmRhdGEgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5odG1sKCcnKTtcbiAgICAgICAgICAgICAgICBjYXAgPSAoIXNlbGYub3ZlcndyaXRlSW5pdGlhbCAmJiBzZWxmLmluaXRpYWxDYXB0aW9uLmxlbmd0aCA+IDApID8gc2VsZi5pbml0aWFsQ2FwdGlvbiA6ICcnO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uaHRtbChjYXApO1xuICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb24uYXR0cigndGl0bGUnLCAnJyk7XG4gICAgICAgICAgICAgICAgJGguYWRkQ3NzKHNlbGYuJGNvbnRhaW5lciwgJ2ZpbGUtaW5wdXQtbmV3Jyk7XG4gICAgICAgICAgICAgICAgc2VsZi5fdmFsaWRhdGVEZWZhdWx0UHJldmlldygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNlbGYuJGNvbnRhaW5lci5maW5kKCRoLkZSQU1FUykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWxmLl9pbml0Q2FwdGlvbigpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuJGNhcHRpb25Db250YWluZXIuZmluZCgnLmt2LWNhcHRpb24taWNvbicpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9oaWRlRmlsZUljb24oKTtcbiAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlY2xlYXJlZCcpO1xuICAgICAgICAgICAgc2VsZi4kY2FwdGlvbkNvbnRhaW5lci5mb2N1cygpO1xuICAgICAgICAgICAgc2VsZi5fc2V0RmlsZURyb3Bab25lVGl0bGUoKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLl9yYWlzZSgnZmlsZXJlc2V0JykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldFByZXZpZXcoKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKCcuZmlsZWlucHV0LWZpbGVuYW1lJykudGV4dCgnJyk7XG4gICAgICAgICAgICAkaC5hZGRDc3Moc2VsZi4kY29udGFpbmVyLCAnZmlsZS1pbnB1dC1uZXcnKTtcbiAgICAgICAgICAgIGlmIChzZWxmLmdldEZyYW1lcygpLmxlbmd0aCB8fCBzZWxmLmlzVXBsb2FkYWJsZSAmJiBzZWxmLmRyb3Bab25lRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnZmlsZS1pbnB1dC1uZXcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuX3NldEZpbGVEcm9wWm9uZVRpdGxlKCk7XG4gICAgICAgICAgICBzZWxmLmNsZWFyU3RhY2soKTtcbiAgICAgICAgICAgIHNlbGYuZm9ybWRhdGEgPSB7fTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICBzZWxmLmlzRGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kZWxlbWVudC5hdHRyKCdkaXNhYmxlZCcsICdkaXNhYmxlZCcpO1xuICAgICAgICAgICAgc2VsZi4kY29udGFpbmVyLmZpbmQoXCIua3YtZmlsZWlucHV0LWNhcHRpb25cIikuYWRkQ2xhc3MoXCJmaWxlLWNhcHRpb24tZGlzYWJsZWRcIik7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZChcIi5idG4tZmlsZSwgLmZpbGVpbnB1dC1yZW1vdmUsIC5maWxlaW5wdXQtdXBsb2FkLCAuZmlsZS1wcmV2aWV3LWZyYW1lIGJ1dHRvblwiKVxuICAgICAgICAgICAgICAgIC5hdHRyKFwiZGlzYWJsZWRcIiwgdHJ1ZSk7XG4gICAgICAgICAgICBzZWxmLl9pbml0RHJhZ0Ryb3AoKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBlbmFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIHNlbGYuaXNEaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5fcmFpc2UoJ2ZpbGVlbmFibGVkJyk7XG4gICAgICAgICAgICBzZWxmLiRlbGVtZW50LnJlbW92ZUF0dHIoJ2Rpc2FibGVkJyk7XG4gICAgICAgICAgICBzZWxmLiRjb250YWluZXIuZmluZChcIi5rdi1maWxlaW5wdXQtY2FwdGlvblwiKS5yZW1vdmVDbGFzcyhcImZpbGUtY2FwdGlvbi1kaXNhYmxlZFwiKTtcbiAgICAgICAgICAgIHNlbGYuJGNvbnRhaW5lci5maW5kKFwiLmJ0bi1maWxlLCAuZmlsZWlucHV0LXJlbW92ZSwgLmZpbGVpbnB1dC11cGxvYWQsIC5maWxlLXByZXZpZXctZnJhbWUgYnV0dG9uXCIpXG4gICAgICAgICAgICAgICAgLnJlbW92ZUF0dHIoXCJkaXNhYmxlZFwiKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXREcmFnRHJvcCgpO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGYuJGVsZW1lbnQ7XG4gICAgICAgIH0sXG4gICAgICAgIHVwbG9hZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCB0b3RMZW4gPSBzZWxmLmdldEZpbGVTdGFjaygpLmxlbmd0aCwgaSwgb3V0RGF0YSwgbGVuLFxuICAgICAgICAgICAgICAgIGhhc0V4dHJhRGF0YSA9ICEkLmlzRW1wdHlPYmplY3Qoc2VsZi5fZ2V0RXh0cmFEYXRhKCkpO1xuICAgICAgICAgICAgaWYgKCFzZWxmLmlzVXBsb2FkYWJsZSB8fCBzZWxmLmlzRGlzYWJsZWQgfHwgIXNlbGYuX2lzRmlsZVNlbGVjdGlvblZhbGlkKHRvdExlbikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9yZXNldFVwbG9hZCgpO1xuICAgICAgICAgICAgaWYgKHRvdExlbiA9PT0gMCAmJiAhaGFzRXh0cmFEYXRhKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fc2hvd1VwbG9hZEVycm9yKHNlbGYubXNnVXBsb2FkRW1wdHkpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbGYuJHByb2dyZXNzLnJlbW92ZUNsYXNzKCdoaWRlJyk7XG4gICAgICAgICAgICBzZWxmLnVwbG9hZENvdW50ID0gMDtcbiAgICAgICAgICAgIHNlbGYudXBsb2FkU3RhdHVzID0ge307XG4gICAgICAgICAgICBzZWxmLnVwbG9hZExvZyA9IFtdO1xuICAgICAgICAgICAgc2VsZi5sb2NrKCk7XG4gICAgICAgICAgICBzZWxmLl9zZXRQcm9ncmVzcygyKTtcbiAgICAgICAgICAgIGlmICh0b3RMZW4gPT09IDAgJiYgaGFzRXh0cmFEYXRhKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fdXBsb2FkRXh0cmFPbmx5KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGVuID0gc2VsZi5maWxlc3RhY2subGVuZ3RoO1xuICAgICAgICAgICAgc2VsZi5oYXNJbml0RGF0YSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHNlbGYudXBsb2FkQXN5bmMpIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhID0gc2VsZi5fZ2V0T3V0RGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3JhaXNlKCdmaWxlYmF0Y2hwcmV1cGxvYWQnLCBbb3V0RGF0YV0pO1xuICAgICAgICAgICAgICAgIHNlbGYuZmlsZUJhdGNoQ29tcGxldGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZSA9IHtjb250ZW50OiBbXSwgY29uZmlnOiBbXSwgdGFnczogW10sIGFwcGVuZDogdHJ1ZX07XG4gICAgICAgICAgICAgICAgc2VsZi51cGxvYWRBc3luY0NvdW50ID0gc2VsZi5nZXRGaWxlU3RhY2soKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuY29udGVudFtpXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYudXBsb2FkQ2FjaGUuY29uZmlnW2ldID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cGxvYWRDYWNoZS50YWdzW2ldID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VsZi4kcHJldmlldy5maW5kKCcuZmlsZS1wcmV2aWV3LWluaXRpYWwnKS5yZW1vdmVDbGFzcygkaC5TT1JUX0NTUyk7XG4gICAgICAgICAgICAgICAgc2VsZi5faW5pdFNvcnRhYmxlKCk7XG4gICAgICAgICAgICAgICAgc2VsZi5jYWNoZUluaXRpYWxQcmV2aWV3ID0gc2VsZi5nZXRQcmV2aWV3KCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuZmlsZXN0YWNrW2ldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3VwbG9hZFNpbmdsZShpLCBzZWxmLmZpbGVzdGFjaywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5fdXBsb2FkQmF0Y2goKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRlbGVtZW50O1xuICAgICAgICB9LFxuICAgICAgICBkZXN0cm95OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXMsICRmb3JtID0gc2VsZi4kZm9ybSwgJGNvbnQgPSBzZWxmLiRjb250YWluZXIsICRlbCA9IHNlbGYuJGVsZW1lbnQsIG5zID0gc2VsZi5uYW1lc3BhY2U7XG4gICAgICAgICAgICAkKGRvY3VtZW50KS5vZmYobnMpO1xuICAgICAgICAgICAgJCh3aW5kb3cpLm9mZihucyk7XG4gICAgICAgICAgICBpZiAoJGZvcm0gJiYgJGZvcm0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgJGZvcm0ub2ZmKG5zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZWxmLmlzVXBsb2FkYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlbGYuX2NsZWFyRmlsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLl9jbGVhbnVwKCk7XG4gICAgICAgICAgICBzZWxmLl9pbml0UHJldmlld0NhY2hlKCk7XG4gICAgICAgICAgICAkZWwuaW5zZXJ0QmVmb3JlKCRjb250KS5vZmYobnMpLnJlbW92ZURhdGEoKTtcbiAgICAgICAgICAgICRjb250Lm9mZigpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuICRlbDtcbiAgICAgICAgfSxcbiAgICAgICAgcmVmcmVzaDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGVsID0gc2VsZi4kZWxlbWVudDtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8gJC5leHRlbmQodHJ1ZSwge30sIHNlbGYub3B0aW9ucywgb3B0aW9ucykgOiBzZWxmLm9wdGlvbnM7XG4gICAgICAgICAgICBzZWxmLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICRlbC5maWxlaW5wdXQob3B0aW9ucyk7XG4gICAgICAgICAgICBzZWxmID0gJGVsLmRhdGEoJ2ZpbGVpbnB1dCcpO1xuICAgICAgICAgICAgaWYgKHNlbGYuaXNVcGxvYWRhYmxlKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2xlYXJGaWxlSW5wdXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkZWwudmFsKCkpIHtcbiAgICAgICAgICAgICAgICAkZWwudHJpZ2dlcignY2hhbmdlLmZpbGVpbnB1dCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRlbDtcbiAgICAgICAgfSxcbiAgICAgICAgem9vbTogZnVuY3Rpb24gKGZyYW1lSWQpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcywgJGZyYW1lID0gc2VsZi5fZ2V0RnJhbWUoZnJhbWVJZCksICRtb2RhbCA9IHNlbGYuJG1vZGFsO1xuICAgICAgICAgICAgaWYgKCEkZnJhbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkaC5pbml0TW9kYWwoJG1vZGFsKTtcbiAgICAgICAgICAgICRtb2RhbC5odG1sKHNlbGYuX2dldE1vZGFsQ29udGVudCgpKTtcbiAgICAgICAgICAgIHNlbGYuX3NldFpvb21Db250ZW50KCRmcmFtZSk7XG4gICAgICAgICAgICAkbW9kYWwubW9kYWwoJ3Nob3cnKTtcbiAgICAgICAgICAgIHNlbGYuX2luaXRab29tQnV0dG9ucygpO1xuICAgICAgICB9LFxuICAgICAgICBnZXRFeGlmOiBmdW5jdGlvbiAoZnJhbWVJZCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzLCAkZnJhbWUgPSBzZWxmLl9nZXRGcmFtZShmcmFtZUlkKTtcbiAgICAgICAgICAgIHJldHVybiAkZnJhbWUgJiYgJGZyYW1lLmRhdGEoJ2V4aWYnKSB8fCBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBnZXRGcmFtZXM6IGZ1bmN0aW9uIChjc3NGaWx0ZXIpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGNzc0ZpbHRlciA9IGNzc0ZpbHRlciB8fCAnJztcbiAgICAgICAgICAgIHJldHVybiBzZWxmLiRwcmV2aWV3LmZpbmQoJGguRlJBTUVTICsgY3NzRmlsdGVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0UHJldmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjb250ZW50OiBzZWxmLmluaXRpYWxQcmV2aWV3LFxuICAgICAgICAgICAgICAgIGNvbmZpZzogc2VsZi5pbml0aWFsUHJldmlld0NvbmZpZyxcbiAgICAgICAgICAgICAgICB0YWdzOiBzZWxmLmluaXRpYWxQcmV2aWV3VGh1bWJUYWdzXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgICQuZm4uZmlsZWlucHV0ID0gZnVuY3Rpb24gKG9wdGlvbikge1xuICAgICAgICBpZiAoISRoLmhhc0ZpbGVBUElTdXBwb3J0KCkgJiYgISRoLmlzSUUoOSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYXJncyA9IEFycmF5LmFwcGx5KG51bGwsIGFyZ3VtZW50cyksIHJldHZhbHMgPSBbXTtcbiAgICAgICAgYXJncy5zaGlmdCgpO1xuICAgICAgICB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSAkKHRoaXMpLCBkYXRhID0gc2VsZi5kYXRhKCdmaWxlaW5wdXQnKSwgb3B0aW9ucyA9IHR5cGVvZiBvcHRpb24gPT09ICdvYmplY3QnICYmIG9wdGlvbixcbiAgICAgICAgICAgICAgICB0aGVtZSA9IG9wdGlvbnMudGhlbWUgfHwgc2VsZi5kYXRhKCd0aGVtZScpLCBsID0ge30sIHQgPSB7fSxcbiAgICAgICAgICAgICAgICBsYW5nID0gb3B0aW9ucy5sYW5ndWFnZSB8fCBzZWxmLmRhdGEoJ2xhbmd1YWdlJykgfHwgJC5mbi5maWxlaW5wdXQuZGVmYXVsdHMubGFuZ3VhZ2UgfHwgJ2VuJywgb3B0O1xuICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoZW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHQgPSAkLmZuLmZpbGVpbnB1dFRoZW1lc1t0aGVtZV0gfHwge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChsYW5nICE9PSAnZW4nICYmICEkaC5pc0VtcHR5KCQuZm4uZmlsZWlucHV0TG9jYWxlc1tsYW5nXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbCA9ICQuZm4uZmlsZWlucHV0TG9jYWxlc1tsYW5nXSB8fCB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb3B0ID0gJC5leHRlbmQodHJ1ZSwge30sICQuZm4uZmlsZWlucHV0LmRlZmF1bHRzLCB0LCAkLmZuLmZpbGVpbnB1dExvY2FsZXMuZW4sIGwsIG9wdGlvbnMsIHNlbGYuZGF0YSgpKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IEZpbGVJbnB1dCh0aGlzLCBvcHQpO1xuICAgICAgICAgICAgICAgIHNlbGYuZGF0YSgnZmlsZWlucHV0JywgZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHJldHZhbHMucHVzaChkYXRhW29wdGlvbl0uYXBwbHkoZGF0YSwgYXJncykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgc3dpdGNoIChyZXR2YWxzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIHJldHVybiByZXR2YWxzWzBdO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dmFscztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dC5kZWZhdWx0cyA9IHtcbiAgICAgICAgbGFuZ3VhZ2U6ICdlbicsXG4gICAgICAgIHNob3dDYXB0aW9uOiB0cnVlLFxuICAgICAgICBzaG93QnJvd3NlOiB0cnVlLFxuICAgICAgICBzaG93UHJldmlldzogdHJ1ZSxcbiAgICAgICAgc2hvd1JlbW92ZTogdHJ1ZSxcbiAgICAgICAgc2hvd1VwbG9hZDogdHJ1ZSxcbiAgICAgICAgc2hvd0NhbmNlbDogdHJ1ZSxcbiAgICAgICAgc2hvd0Nsb3NlOiB0cnVlLFxuICAgICAgICBzaG93VXBsb2FkZWRUaHVtYnM6IHRydWUsXG4gICAgICAgIGJyb3dzZU9uWm9uZUNsaWNrOiBmYWxzZSxcbiAgICAgICAgYXV0b1JlcGxhY2U6IGZhbHNlLFxuICAgICAgICBhdXRvT3JpZW50SW1hZ2U6IHRydWUsIC8vIGZvciBKUEVHIGltYWdlcyBiYXNlZCBvbiBFWElGIG9yaWVudGF0aW9uIHRhZ1xuICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgIHJ0bDogZmFsc2UsXG4gICAgICAgIGhpZGVUaHVtYm5haWxDb250ZW50OiBmYWxzZSxcbiAgICAgICAgZ2VuZXJhdGVGaWxlSWQ6IG51bGwsXG4gICAgICAgIHByZXZpZXdDbGFzczogJycsXG4gICAgICAgIGNhcHRpb25DbGFzczogJycsXG4gICAgICAgIGZyYW1lQ2xhc3M6ICdrcmFqZWUtZGVmYXVsdCcsXG4gICAgICAgIG1haW5DbGFzczogJ2ZpbGUtY2FwdGlvbi1tYWluJyxcbiAgICAgICAgbWFpblRlbXBsYXRlOiBudWxsLFxuICAgICAgICBwdXJpZnlIdG1sOiB0cnVlLFxuICAgICAgICBmaWxlU2l6ZUdldHRlcjogbnVsbCxcbiAgICAgICAgaW5pdGlhbENhcHRpb246ICcnLFxuICAgICAgICBpbml0aWFsUHJldmlldzogW10sXG4gICAgICAgIGluaXRpYWxQcmV2aWV3RGVsaW1pdGVyOiAnKiQkKicsXG4gICAgICAgIGluaXRpYWxQcmV2aWV3QXNEYXRhOiBmYWxzZSxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdGaWxlVHlwZTogJ2ltYWdlJyxcbiAgICAgICAgaW5pdGlhbFByZXZpZXdDb25maWc6IFtdLFxuICAgICAgICBpbml0aWFsUHJldmlld1RodW1iVGFnczogW10sXG4gICAgICAgIHByZXZpZXdUaHVtYlRhZ3M6IHt9LFxuICAgICAgICBpbml0aWFsUHJldmlld1Nob3dEZWxldGU6IHRydWUsXG4gICAgICAgIHJlbW92ZUZyb21QcmV2aWV3T25FcnJvcjogZmFsc2UsXG4gICAgICAgIGRlbGV0ZVVybDogJycsXG4gICAgICAgIGRlbGV0ZUV4dHJhRGF0YToge30sXG4gICAgICAgIG92ZXJ3cml0ZUluaXRpYWw6IHRydWUsXG4gICAgICAgIHByZXZpZXdab29tQnV0dG9uSWNvbnM6IHtcbiAgICAgICAgICAgIHByZXY6ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdHJpYW5nbGUtbGVmdFwiPjwvaT4nLFxuICAgICAgICAgICAgbmV4dDogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmlhbmdsZS1yaWdodFwiPjwvaT4nLFxuICAgICAgICAgICAgdG9nZ2xlaGVhZGVyOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXJlc2l6ZS12ZXJ0aWNhbFwiPjwvaT4nLFxuICAgICAgICAgICAgZnVsbHNjcmVlbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1mdWxsc2NyZWVuXCI+PC9pPicsXG4gICAgICAgICAgICBib3JkZXJsZXNzOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLXJlc2l6ZS1mdWxsXCI+PC9pPicsXG4gICAgICAgICAgICBjbG9zZTogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi1yZW1vdmVcIj48L2k+J1xuICAgICAgICB9LFxuICAgICAgICBwcmV2aWV3Wm9vbUJ1dHRvbkNsYXNzZXM6IHtcbiAgICAgICAgICAgIHByZXY6ICdidG4gYnRuLW5hdmlnYXRlJyxcbiAgICAgICAgICAgIG5leHQ6ICdidG4gYnRuLW5hdmlnYXRlJyxcbiAgICAgICAgICAgIHRvZ2dsZWhlYWRlcjogJ2J0biBidG4tZGVmYXVsdCBidG4taGVhZGVyLXRvZ2dsZScsXG4gICAgICAgICAgICBmdWxsc2NyZWVuOiAnYnRuIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgICAgIGJvcmRlcmxlc3M6ICdidG4gYnRuLWRlZmF1bHQnLFxuICAgICAgICAgICAgY2xvc2U6ICdidG4gYnRuLWRlZmF1bHQnXG4gICAgICAgIH0sXG4gICAgICAgIHByZWZlckljb25pY1ByZXZpZXc6IGZhbHNlLFxuICAgICAgICBwcmVmZXJJY29uaWNab29tUHJldmlldzogZmFsc2UsXG4gICAgICAgIGFsbG93ZWRQcmV2aWV3VHlwZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgYWxsb3dlZFByZXZpZXdNaW1lVHlwZXM6IG51bGwsXG4gICAgICAgIGFsbG93ZWRGaWxlVHlwZXM6IG51bGwsXG4gICAgICAgIGFsbG93ZWRGaWxlRXh0ZW5zaW9uczogbnVsbCxcbiAgICAgICAgZGVmYXVsdFByZXZpZXdDb250ZW50OiBudWxsLFxuICAgICAgICBjdXN0b21MYXlvdXRUYWdzOiB7fSxcbiAgICAgICAgY3VzdG9tUHJldmlld1RhZ3M6IHt9LFxuICAgICAgICBwcmV2aWV3RmlsZUljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tZmlsZVwiPjwvaT4nLFxuICAgICAgICBwcmV2aWV3RmlsZUljb25DbGFzczogJ2ZpbGUtb3RoZXItaWNvbicsXG4gICAgICAgIHByZXZpZXdGaWxlSWNvblNldHRpbmdzOiB7fSxcbiAgICAgICAgcHJldmlld0ZpbGVFeHRTZXR0aW5nczoge30sXG4gICAgICAgIGJ1dHRvbkxhYmVsQ2xhc3M6ICdoaWRkZW4teHMnLFxuICAgICAgICBicm93c2VJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWZvbGRlci1vcGVuXCI+PC9pPiZuYnNwOycsXG4gICAgICAgIGJyb3dzZUNsYXNzOiAnYnRuIGJ0bi1wcmltYXJ5JyxcbiAgICAgICAgcmVtb3ZlSWNvbjogJzxpIGNsYXNzPVwiZ2x5cGhpY29uIGdseXBoaWNvbi10cmFzaFwiPjwvaT4nLFxuICAgICAgICByZW1vdmVDbGFzczogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgIGNhbmNlbEljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tYmFuLWNpcmNsZVwiPjwvaT4nLFxuICAgICAgICBjYW5jZWxDbGFzczogJ2J0biBidG4tZGVmYXVsdCcsXG4gICAgICAgIHVwbG9hZEljb246ICc8aSBjbGFzcz1cImdseXBoaWNvbiBnbHlwaGljb24tdXBsb2FkXCI+PC9pPicsXG4gICAgICAgIHVwbG9hZENsYXNzOiAnYnRuIGJ0bi1kZWZhdWx0JyxcbiAgICAgICAgdXBsb2FkVXJsOiBudWxsLFxuICAgICAgICB1cGxvYWRBc3luYzogdHJ1ZSxcbiAgICAgICAgdXBsb2FkRXh0cmFEYXRhOiB7fSxcbiAgICAgICAgem9vbU1vZGFsSGVpZ2h0OiA0ODAsXG4gICAgICAgIG1pbkltYWdlV2lkdGg6IG51bGwsXG4gICAgICAgIG1pbkltYWdlSGVpZ2h0OiBudWxsLFxuICAgICAgICBtYXhJbWFnZVdpZHRoOiBudWxsLFxuICAgICAgICBtYXhJbWFnZUhlaWdodDogbnVsbCxcbiAgICAgICAgcmVzaXplSW1hZ2U6IGZhbHNlLFxuICAgICAgICByZXNpemVQcmVmZXJlbmNlOiAnd2lkdGgnLFxuICAgICAgICByZXNpemVRdWFsaXR5OiAwLjkyLFxuICAgICAgICByZXNpemVEZWZhdWx0SW1hZ2VUeXBlOiAnaW1hZ2UvanBlZycsXG4gICAgICAgIHJlc2l6ZUlmU2l6ZU1vcmVUaGFuOiAwLCAvLyBpbiBLQlxuICAgICAgICBtaW5GaWxlU2l6ZTogMCxcbiAgICAgICAgbWF4RmlsZVNpemU6IDAsXG4gICAgICAgIG1heEZpbGVQcmV2aWV3U2l6ZTogMjU2MDAsIC8vIDI1IE1CXG4gICAgICAgIG1pbkZpbGVDb3VudDogMCxcbiAgICAgICAgbWF4RmlsZUNvdW50OiAwLFxuICAgICAgICB2YWxpZGF0ZUluaXRpYWxDb3VudDogZmFsc2UsXG4gICAgICAgIG1zZ1ZhbGlkYXRpb25FcnJvckNsYXNzOiAndGV4dC1kYW5nZXInLFxuICAgICAgICBtc2dWYWxpZGF0aW9uRXJyb3JJY29uOiAnPGkgY2xhc3M9XCJnbHlwaGljb24gZ2x5cGhpY29uLWV4Y2xhbWF0aW9uLXNpZ25cIj48L2k+ICcsXG4gICAgICAgIG1zZ0Vycm9yQ2xhc3M6ICdmaWxlLWVycm9yLW1lc3NhZ2UnLFxuICAgICAgICBwcm9ncmVzc1RodW1iQ2xhc3M6IFwicHJvZ3Jlc3MtYmFyIHByb2dyZXNzLWJhci1zdWNjZXNzIHByb2dyZXNzLWJhci1zdHJpcGVkIGFjdGl2ZVwiLFxuICAgICAgICBwcm9ncmVzc0NsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItc3VjY2VzcyBwcm9ncmVzcy1iYXItc3RyaXBlZCBhY3RpdmVcIixcbiAgICAgICAgcHJvZ3Jlc3NDb21wbGV0ZUNsYXNzOiBcInByb2dyZXNzLWJhciBwcm9ncmVzcy1iYXItc3VjY2Vzc1wiLFxuICAgICAgICBwcm9ncmVzc0Vycm9yQ2xhc3M6IFwicHJvZ3Jlc3MtYmFyIHByb2dyZXNzLWJhci1kYW5nZXJcIixcbiAgICAgICAgcHJvZ3Jlc3NVcGxvYWRUaHJlc2hvbGQ6IDk5LFxuICAgICAgICBwcmV2aWV3RmlsZVR5cGU6ICdpbWFnZScsXG4gICAgICAgIGVsQ2FwdGlvbkNvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgZWxDYXB0aW9uVGV4dDogbnVsbCxcbiAgICAgICAgZWxQcmV2aWV3Q29udGFpbmVyOiBudWxsLFxuICAgICAgICBlbFByZXZpZXdJbWFnZTogbnVsbCxcbiAgICAgICAgZWxQcmV2aWV3U3RhdHVzOiBudWxsLFxuICAgICAgICBlbEVycm9yQ29udGFpbmVyOiBudWxsLFxuICAgICAgICBlcnJvckNsb3NlQnV0dG9uOiAnPHNwYW4gY2xhc3M9XCJjbG9zZSBrdi1lcnJvci1jbG9zZVwiPiZ0aW1lczs8L3NwYW4+JyxcbiAgICAgICAgc2x1Z0NhbGxiYWNrOiBudWxsLFxuICAgICAgICBkcm9wWm9uZUVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGRyb3Bab25lVGl0bGVDbGFzczogJ2ZpbGUtZHJvcC16b25lLXRpdGxlJyxcbiAgICAgICAgZmlsZUFjdGlvblNldHRpbmdzOiB7fSxcbiAgICAgICAgb3RoZXJBY3Rpb25CdXR0b25zOiAnJyxcbiAgICAgICAgdGV4dEVuY29kaW5nOiAnVVRGLTgnLFxuICAgICAgICBhamF4U2V0dGluZ3M6IHt9LFxuICAgICAgICBhamF4RGVsZXRlU2V0dGluZ3M6IHt9LFxuICAgICAgICBzaG93QWpheEVycm9yRGV0YWlsczogdHJ1ZVxuICAgIH07XG5cbiAgICAkLmZuLmZpbGVpbnB1dExvY2FsZXMuZW4gPSB7XG4gICAgICAgIGZpbGVTaW5nbGU6ICdmaWxlJyxcbiAgICAgICAgZmlsZVBsdXJhbDogJ2ZpbGVzJyxcbiAgICAgICAgYnJvd3NlTGFiZWw6ICdCcm93c2UgJmhlbGxpcDsnLFxuICAgICAgICByZW1vdmVMYWJlbDogJ1JlbW92ZScsXG4gICAgICAgIHJlbW92ZVRpdGxlOiAnQ2xlYXIgc2VsZWN0ZWQgZmlsZXMnLFxuICAgICAgICBjYW5jZWxMYWJlbDogJ0NhbmNlbCcsXG4gICAgICAgIGNhbmNlbFRpdGxlOiAnQWJvcnQgb25nb2luZyB1cGxvYWQnLFxuICAgICAgICB1cGxvYWRMYWJlbDogJ1VwbG9hZCcsXG4gICAgICAgIHVwbG9hZFRpdGxlOiAnVXBsb2FkIHNlbGVjdGVkIGZpbGVzJyxcbiAgICAgICAgbXNnTm86ICdObycsXG4gICAgICAgIG1zZ05vRmlsZXNTZWxlY3RlZDogJ05vIGZpbGVzIHNlbGVjdGVkJyxcbiAgICAgICAgbXNnQ2FuY2VsbGVkOiAnQ2FuY2VsbGVkJyxcbiAgICAgICAgbXNnWm9vbU1vZGFsSGVhZGluZzogJ0RldGFpbGVkIFByZXZpZXcnLFxuICAgICAgICBtc2dGaWxlUmVxdWlyZWQ6ICdZb3UgbXVzdCBzZWxlY3QgYSBmaWxlIHRvIHVwbG9hZC4nLFxuICAgICAgICBtc2dTaXplVG9vU21hbGw6ICdGaWxlIFwie25hbWV9XCIgKDxiPntzaXplfSBLQjwvYj4pIGlzIHRvbyBzbWFsbCBhbmQgbXVzdCBiZSBsYXJnZXIgdGhhbiA8Yj57bWluU2l6ZX0gS0I8L2I+LicsXG4gICAgICAgIG1zZ1NpemVUb29MYXJnZTogJ0ZpbGUgXCJ7bmFtZX1cIiAoPGI+e3NpemV9IEtCPC9iPikgZXhjZWVkcyBtYXhpbXVtIGFsbG93ZWQgdXBsb2FkIHNpemUgb2YgPGI+e21heFNpemV9IEtCPC9iPi4nLFxuICAgICAgICBtc2dGaWxlc1Rvb0xlc3M6ICdZb3UgbXVzdCBzZWxlY3QgYXQgbGVhc3QgPGI+e259PC9iPiB7ZmlsZXN9IHRvIHVwbG9hZC4nLFxuICAgICAgICBtc2dGaWxlc1Rvb01hbnk6ICdOdW1iZXIgb2YgZmlsZXMgc2VsZWN0ZWQgZm9yIHVwbG9hZCA8Yj4oe259KTwvYj4gZXhjZWVkcyBtYXhpbXVtIGFsbG93ZWQgbGltaXQgb2YgPGI+e219PC9iPi4nLFxuICAgICAgICBtc2dGaWxlTm90Rm91bmQ6ICdGaWxlIFwie25hbWV9XCIgbm90IGZvdW5kIScsXG4gICAgICAgIG1zZ0ZpbGVTZWN1cmVkOiAnU2VjdXJpdHkgcmVzdHJpY3Rpb25zIHByZXZlbnQgcmVhZGluZyB0aGUgZmlsZSBcIntuYW1lfVwiLicsXG4gICAgICAgIG1zZ0ZpbGVOb3RSZWFkYWJsZTogJ0ZpbGUgXCJ7bmFtZX1cIiBpcyBub3QgcmVhZGFibGUuJyxcbiAgICAgICAgbXNnRmlsZVByZXZpZXdBYm9ydGVkOiAnRmlsZSBwcmV2aWV3IGFib3J0ZWQgZm9yIFwie25hbWV9XCIuJyxcbiAgICAgICAgbXNnRmlsZVByZXZpZXdFcnJvcjogJ0FuIGVycm9yIG9jY3VycmVkIHdoaWxlIHJlYWRpbmcgdGhlIGZpbGUgXCJ7bmFtZX1cIi4nLFxuICAgICAgICBtc2dJbnZhbGlkRmlsZU5hbWU6ICdJbnZhbGlkIG9yIHVuc3VwcG9ydGVkIGNoYXJhY3RlcnMgaW4gZmlsZSBuYW1lIFwie25hbWV9XCIuJyxcbiAgICAgICAgbXNnSW52YWxpZEZpbGVUeXBlOiAnSW52YWxpZCB0eXBlIGZvciBmaWxlIFwie25hbWV9XCIuIE9ubHkgXCJ7dHlwZXN9XCIgZmlsZXMgYXJlIHN1cHBvcnRlZC4nLFxuICAgICAgICBtc2dJbnZhbGlkRmlsZUV4dGVuc2lvbjogJ0ludmFsaWQgZXh0ZW5zaW9uIGZvciBmaWxlIFwie25hbWV9XCIuIE9ubHkgXCJ7ZXh0ZW5zaW9uc31cIiBmaWxlcyBhcmUgc3VwcG9ydGVkLicsXG4gICAgICAgIG1zZ0ZpbGVUeXBlczoge1xuICAgICAgICAgICAgJ2ltYWdlJzogJ2ltYWdlJyxcbiAgICAgICAgICAgICdodG1sJzogJ0hUTUwnLFxuICAgICAgICAgICAgJ3RleHQnOiAndGV4dCcsXG4gICAgICAgICAgICAndmlkZW8nOiAndmlkZW8nLFxuICAgICAgICAgICAgJ2F1ZGlvJzogJ2F1ZGlvJyxcbiAgICAgICAgICAgICdmbGFzaCc6ICdmbGFzaCcsXG4gICAgICAgICAgICAncGRmJzogJ1BERicsXG4gICAgICAgICAgICAnb2JqZWN0JzogJ29iamVjdCdcbiAgICAgICAgfSxcbiAgICAgICAgbXNnVXBsb2FkQWJvcnRlZDogJ1RoZSBmaWxlIHVwbG9hZCB3YXMgYWJvcnRlZCcsXG4gICAgICAgIG1zZ1VwbG9hZFRocmVzaG9sZDogJ1Byb2Nlc3NpbmcuLi4nLFxuICAgICAgICBtc2dVcGxvYWRCZWdpbjogJ0luaXRpYWxpemluZy4uLicsXG4gICAgICAgIG1zZ1VwbG9hZEVuZDogJ0RvbmUnLFxuICAgICAgICBtc2dVcGxvYWRFbXB0eTogJ05vIHZhbGlkIGRhdGEgYXZhaWxhYmxlIGZvciB1cGxvYWQuJyxcbiAgICAgICAgbXNnVmFsaWRhdGlvbkVycm9yOiAnVmFsaWRhdGlvbiBFcnJvcicsXG4gICAgICAgIG1zZ0xvYWRpbmc6ICdMb2FkaW5nIGZpbGUge2luZGV4fSBvZiB7ZmlsZXN9ICZoZWxsaXA7JyxcbiAgICAgICAgbXNnUHJvZ3Jlc3M6ICdMb2FkaW5nIGZpbGUge2luZGV4fSBvZiB7ZmlsZXN9IC0ge25hbWV9IC0ge3BlcmNlbnR9JSBjb21wbGV0ZWQuJyxcbiAgICAgICAgbXNnU2VsZWN0ZWQ6ICd7bn0ge2ZpbGVzfSBzZWxlY3RlZCcsXG4gICAgICAgIG1zZ0ZvbGRlcnNOb3RBbGxvd2VkOiAnRHJhZyAmIGRyb3AgZmlsZXMgb25seSEge259IGZvbGRlcihzKSBkcm9wcGVkIHdlcmUgc2tpcHBlZC4nLFxuICAgICAgICBtc2dJbWFnZVdpZHRoU21hbGw6ICdXaWR0aCBvZiBpbWFnZSBmaWxlIFwie25hbWV9XCIgbXVzdCBiZSBhdCBsZWFzdCB7c2l6ZX0gcHguJyxcbiAgICAgICAgbXNnSW1hZ2VIZWlnaHRTbWFsbDogJ0hlaWdodCBvZiBpbWFnZSBmaWxlIFwie25hbWV9XCIgbXVzdCBiZSBhdCBsZWFzdCB7c2l6ZX0gcHguJyxcbiAgICAgICAgbXNnSW1hZ2VXaWR0aExhcmdlOiAnV2lkdGggb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIGNhbm5vdCBleGNlZWQge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlSGVpZ2h0TGFyZ2U6ICdIZWlnaHQgb2YgaW1hZ2UgZmlsZSBcIntuYW1lfVwiIGNhbm5vdCBleGNlZWQge3NpemV9IHB4LicsXG4gICAgICAgIG1zZ0ltYWdlUmVzaXplRXJyb3I6ICdDb3VsZCBub3QgZ2V0IHRoZSBpbWFnZSBkaW1lbnNpb25zIHRvIHJlc2l6ZS4nLFxuICAgICAgICBtc2dJbWFnZVJlc2l6ZUV4Y2VwdGlvbjogJ0Vycm9yIHdoaWxlIHJlc2l6aW5nIHRoZSBpbWFnZS48cHJlPntlcnJvcnN9PC9wcmU+JyxcbiAgICAgICAgbXNnQWpheEVycm9yOiAnU29tZXRoaW5nIHdlbnQgd3Jvbmcgd2l0aCB0aGUge29wZXJhdGlvbn0gb3BlcmF0aW9uLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyIScsXG4gICAgICAgIG1zZ0FqYXhQcm9ncmVzc0Vycm9yOiAne29wZXJhdGlvbn0gZmFpbGVkJyxcbiAgICAgICAgYWpheE9wZXJhdGlvbnM6IHtcbiAgICAgICAgICAgIGRlbGV0ZVRodW1iOiAnZmlsZSBkZWxldGUnLFxuICAgICAgICAgICAgdXBsb2FkVGh1bWI6ICdmaWxlIHVwbG9hZCcsXG4gICAgICAgICAgICB1cGxvYWRCYXRjaDogJ2JhdGNoIGZpbGUgdXBsb2FkJyxcbiAgICAgICAgICAgIHVwbG9hZEV4dHJhOiAnZm9ybSBkYXRhIHVwbG9hZCdcbiAgICAgICAgfSxcbiAgICAgICAgZHJvcFpvbmVUaXRsZTogJ0RyYWcgJiBkcm9wIGZpbGVzIGhlcmUgJmhlbGxpcDsnLFxuICAgICAgICBkcm9wWm9uZUNsaWNrVGl0bGU6ICc8YnI+KG9yIGNsaWNrIHRvIHNlbGVjdCB7ZmlsZXN9KScsXG4gICAgICAgIHByZXZpZXdab29tQnV0dG9uVGl0bGVzOiB7XG4gICAgICAgICAgICBwcmV2OiAnVmlldyBwcmV2aW91cyBmaWxlJyxcbiAgICAgICAgICAgIG5leHQ6ICdWaWV3IG5leHQgZmlsZScsXG4gICAgICAgICAgICB0b2dnbGVoZWFkZXI6ICdUb2dnbGUgaGVhZGVyJyxcbiAgICAgICAgICAgIGZ1bGxzY3JlZW46ICdUb2dnbGUgZnVsbCBzY3JlZW4nLFxuICAgICAgICAgICAgYm9yZGVybGVzczogJ1RvZ2dsZSBib3JkZXJsZXNzIG1vZGUnLFxuICAgICAgICAgICAgY2xvc2U6ICdDbG9zZSBkZXRhaWxlZCBwcmV2aWV3J1xuICAgICAgICB9XG4gICAgfTtcblxuICAgICQuZm4uZmlsZWlucHV0LkNvbnN0cnVjdG9yID0gRmlsZUlucHV0O1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydCBhdXRvbWF0aWNhbGx5IGZpbGUgaW5wdXRzIHdpdGggY2xhc3MgJ2ZpbGUnIGludG8gYSBib290c3RyYXAgZmlsZWlucHV0IGNvbnRyb2wuXG4gICAgICovXG4gICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGlucHV0ID0gJCgnaW5wdXQuZmlsZVt0eXBlPWZpbGVdJyk7XG4gICAgICAgIGlmICgkaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAkaW5wdXQuZmlsZWlucHV0KCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn0pKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtZmlsZWlucHV0L2pzL2ZpbGVpbnB1dC5qc1xuLy8gbW9kdWxlIGlkID0gMTdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9jc3MvYm9vdHN0cmFwLmNzc1xuLy8gbW9kdWxlIGlkID0gMThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ib290c3RyYXAtc2VsZWN0L2Rpc3QvY3NzL2Jvb3RzdHJhcC1zZWxlY3QuY3NzXG4vLyBtb2R1bGUgaWQgPSAxOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2Jvb3RzdHJhcC1maWxlaW5wdXQvY3NzL2ZpbGVpbnB1dC5jc3Ncbi8vIG1vZHVsZSBpZCA9IDIwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvc3R5bGUuY3NzXG4vLyBtb2R1bGUgaWQgPSAyMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwic291cmNlUm9vdCI6IiJ9
|